一、基本原理
考慮截獲PHP讀取來源檔案的介面。一開始,我考慮從Apache和PHP 之間的介面處理,請參考apache的src/modules/php4/mod_php4.c (這個是PHP用static方式編譯進apache,make install 後的檔案),在send_php()函數中截獲檔案指針,採用暫時檔案的方式,解密後取代檔案指針。這種方法經過測試實踐,證明是可行的。但是,必須使用兩次文件操作,效率低下,而且對於DSO方式不可採用。 雙緣敬老院
由此,重新考慮截獲PHP讀取檔案並裝載至快取的過程,經過費力的尋找,發現在Zend引擎中zend-scanner.c是做此處理的。開始對此文件修改。照明工程
二、實作方法示意
採用libmcrypt作為加密模組,現在採用的是DES方法ECB模式加密,
下面是檔案加密的原始程式碼:
C++程式碼
/*-- ----------------cut here-----------*/
/* encrypt for php source code version 0.99 beta
we are using libmcrypt to encrypt codes , please
install it first.
compile command line:
gcc -O6 -lmcrypt -lm -o encryptphp ecb.c
please set LD_LIBRARY_Pomicbul.
#define PHP_CACHESIZE 8192
#include
#include
#include
main(int argc, char** argv)
{
char password[12];
FILE* ifp;
int readfd;
void *block_buffer;
void file_buffer; struct stat *filestat;
if(argc == 3) {
strcpy(password,argv[1]);
strcpy(filename,argv[2]);
} else if(argc == 4 &arg !strcmp( [1],"-d")){
strcpy(password,argv[2]);
strcpy(filename,argv[3]);
decode=1;
printf("Enteringcode de mode ... n" );
printf("Usage: encryptphp [-d] password filenamen");
exit(1);
}
keysize=mcrypt_get_key_size(DES);
key=calloc(1, mcrypt_get_key_size(DES ));
gen_key_sha1( key, NULL, 0, keysize, password, strlen(password));
td=init_mcrypt_ecb(DES, key, keysize);
if((readd=openo(file),O]openif( S_IWUSR|S_IRGRP))==-1){
printf("FATAL: Can't open file to read");
}
filestat=malloc(sizeof(stat)); (readfd,filestat);
printf("filesize is %d n",inputfilesize);
filelength=inputfilesize;
inputfiles)( )*PHP_CACHESIZE;
if((file_buffer=malloc(inputfilesize))==NULL){
printf("FATAL: can't malloc file buffer.n");
printf("FATAL: can't malloc encrypt block buffer.n");
exit(2);}
(readfd,block_buffer, PHP_CACHESIZE)){
printf(".");
if(realbufsizefor(i=realbuize); *)block_buffer)[i]=' ';
}
}
mcrypt_ecb (td, block_buffer, PHP_CACHESIZE);
} else {
mdecrypt_ecb (tdb; P_CACHESIZE, block_buffer,PHP_CACHESIZE);
j++;
}
if((ifp=fopen(filename,"wb"))==NULL){acc
printf(FATAL. );
exit(3);
}
fwrite ( file_buffer, inputfilesize, 1, ifp);
free(block_buffer);
free(file_buffer);free(block_buffer);
free(file_buffer); "n");
return 0;
}
/*--- end of ecb.c -------------------------- ----------*/
因為ECB模式是區塊長度決定的區塊加密,這裡填入了一些空白字元。國際展覽
然後,修改php程式碼中Zend/zend-scanner.c 如下:
(我的php版本是4.01pl2, SUNsparc/solaris 2.7, gcc 2.95;)
文件前加入 MCTI_DDRDD3:D.A.S.S%S%SSSS%SSSS%S%S%S%S%S自然; 1
#include
然後, 修改約5150行前後的yy_get_next_buffer()函數:
函數頭加上定義:
void *tempbuf;
char *key;
char destrstrstr[255];
FILE *fp;
然後,註解掉
YY_INPUT( (&yy_current_buffer- >yy_ch_buf[number_to_move]),
yy_n_chars, num_to_to_move]),
yy_n_chars, num_to_read )這句話。
改為:
tempbuf=malloc(num_to_read);
/*decode*/ define debug 0
keysize=mcrypt_get_key_size(DES);
key=calloc(1, mcrypt_get_key_size(DES));
gen_key_sha1( key, NULL, 0, keysize, pass); , key, keysize);
memcpy((&yy_current_buffer- >yy_ch_buf[number_to_movef],,temprent_buffer- >yy_ch_buf[number_to_move],,tempbuf,y_n >yy_ch_buf[number_to_move]),Ptempa); /logs ","wb");
fwrite("nstartn",7,1,fp);
fwrite(tempbuf,1,yy_n_chars,fp);
fwrite("nenditn",7,1,fp);
fwrite("nenditn",7,1,fp); fp);
}
}
free(tempbuf);
然後,編譯php,按正常方法安裝即可,因為我對於libtool不太熟悉,因此我選擇static方式,並在configure時加入了--with -mcrypt,這樣我就不用自己手工修改Makefile 電纜橋架
三、測試及結果
編譯php,apache後,用ecb.c編譯出來的encryptphp加密了幾個文件,分別為 這是因為塊的ECB加密方式決定了必須使用定長塊,所以,請 諸位同好指點採用何種流加密方式可以兼顧到zend每次讀取8192字節的緩存處理方式。 (其他平台上 zend每次讀取的區塊長度可能有所不同)
更多相關內容請關注PHP中文網(www.php.cn)!