首頁  >  文章  >  php教程  >  修改Zend引擎實現PHP源碼加密的原理及實踐

修改Zend引擎實現PHP源碼加密的原理及實踐

黄舟
黄舟原創
2016-12-14 11:46:581193瀏覽

一、基本原理 
  考慮截獲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 MCRYPT_BACKWARDS_COMPATIBLE 1

#define PHP_CACHESIZE 8192 
#include  
#include  
#include


main(int argc, char** argv) 
{

int td, i,j,inputfilesize,filelength;

char password[12]; 
FILE* ifp; 
int readfd; 

char *key; 

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" ); 

} else { 

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"); 

exit(3); 

}

filestat=malloc(sizeof(stat)); (readfd,filestat); 

inputfilesize=filestat- >st_size; 

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"); 

exit(2); block_buffer=malloc(PHP_CACHESIZE))==NULL){ 

printf("FATAL: can't malloc encrypt block buffer.n"); 

exit(2); 

}

(readfd,block_buffer, PHP_CACHESIZE)){ 
printf("."); 

if(!decode){ 

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++; 
}

close(readfd);


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

  然後,註解掉大約3510行前後的YY_INPUT的定義。

   然後, 修改約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); 

if((yy_n_chars=fread(tempbuf,1,num_to_read,yyin))!=0){ 

/*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); 

mdecrypt_ecb(td, tempbuf, yy_n_chars); 

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)!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn