Home  >  Article  >  Backend Development  >  The principle and practice of modifying the Zend engine to implement PHP source code encryption_PHP tutorial

The principle and practice of modifying the Zend engine to implement PHP source code encryption_PHP tutorial

WBOY
WBOYOriginal
2016-07-21 15:52:34865browse

1. Basic Principles
Consider intercepting the interface for PHP to read source files. At first, I considered dealing with the interface between Apache and PHP. See apache's src/modules/php4/mod_php4.c (this is the file after PHP is statically compiled into apache, make install), in send_php() The file pointer is intercepted in the function, using the method of temporary file, and the file pointer is replaced after decryption. This method has been tested and proven to be feasible. However, two file operations must be used, which is inefficient, and the DSO method cannot be used. Shuangyuan Nursing Home
Therefore, I reconsidered the process of intercepting PHP reading files and loading them into the cache. After strenuous searching, I found that zend-scanner.c does this in the Zend engine. Start modifying this file.Lighting project

2. Implementation method

Use libmcrypt as the encryption module, and now use the DES method ECB mode encryption.

The following is the source code for file encryption:

C++ code
/* 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_PATH before use.
GNU copyleft, designed by wangsu, miweicong */

#define MCRYPT_BACKWARDS_COMPATIBLE 1
#define PHP_CA CHESIZE 8192
#include < ; mcrypt.h >
#include < stdio.h >
#include < stdlib.h >
#include < math.h > /types.h >
#include < sys/stat.h >
#include < fcntl.h > )
{

int td, i,j,inputfilesize,filelength;
char filename[255];
char password[12]; int readfd;
char *key;
void *block_buffer;
void *file_buffer;
int keysize; stat *filestat;


if(argc == 3) {
strcpy(password,argv[1]);
strcpy(filename,argv[2]);
} else if(argc == 4 && !strcmp(argv[1],"-d")){
strcpy(password,argv[2]);
strcpy(filename,argv[3]);
decode=1;
printf("Entering decode 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); ))==-1){
printf("FATAL: Can't open file to read");
exit(3);
}

filestat=malloc(sizeof( stat));

fstat(readfd,filestat);
inputfilesize=filestat- >st_size;
printf("filesize is %d n",inputfilesize);
filelength=inputfilesize ; ;

inputfilesize=((int)(floor(inputfilesize/PHP_CACHESIZE)))+1)*PHP_CACHESIZE;

if((file_buffer=malloc(inputfilesize))==NULL){ >printf("FATAL: can't malloc file buffer.n"); 
exit(2); 
} 
if((block_buffer=malloc(PHP_CACHESIZE))==NULL){ 
printf("FATAL: can't malloc encrypt block buffer.n"); 
exit(2); 
}    

j=0;    
while(realbufsize=read (readfd,block_buffer, PHP_CACHESIZE)){    
printf(".");    
if(!decode){    
if(realbufsize< PHP_CACHESIZE){    
for(i=realbufsize;i< PHP_CACHESIZE;i++){    
((char *)block_buffer)[i]=' ';    
}    
}    
mcrypt_ecb (td, block_buffer, PHP_CACHESIZE);    
} else {    
mdecrypt_ecb (td, block_buffer, realbufsize);    
}    
memcpy(file_buffer+j*PHP_CACHESIZE,block_buffer,PHP_CACHESIZE);    
j++;    
}    

close(readfd);    

if((ifp=fopen(filename,"wb"))==NULL){    
printf("FATAL: file access error.n");    
exit(3);    
}    
fwrite ( file_buffer, inputfilesize, 1, ifp);    

free(block_buffer);    
free(file_buffer);    
free(filestat);    
fclose(ifp);    
printf("n");    

return 0;    

}    
/*--- end of ecb.c ------------------------------------*/   
因为ECB模式是块长度确定的块加密,这里填充了一 些空字符。国际展览

  然后,修改php代码中 Zend/zend-scanner.c 如下:

(我的php版本是4.01pl2, SUNsparc/solaris 2.7, gcc 2.95;)

文件前加入:

#define MCRYPT_BACKWARDS_COMPATIBLE 1
#include < mcrypt.h >

  然后,注释掉大约3510行前后的YY_INPUT的定义。

  然后, 修改大约5150行前后的yy_get_next_buffer()函数:
函数头加上定义:
void *tempbuf;
char *key;
char debugstr[255];
int td,keysize;
int x,y;
FILE *fp;
然后 ,注释掉
YY_INPUT( (&yy_current_buffer- >yy_ch_buf[number_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 password "PHPphp111222"
#define debug 0

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);
mdecrypt_ecb(td, tempbuf, yy_n_chars);
memcpy((&yy_current_buffer- >yy_ch_buf[number_to_move]),tempbuf,yy_n_chars);
if(debug){
fp=fopen("/tmp/logs","wb");
fwrite("nstartn",7,1,fp);
fwrite(tempbuf,1,yy_n_chars,fp);
fwrite("nenditn",7,1,fp);
fclose(fp);
}
}
free(tempbuf);

  然后,编译php,按正常方法安装即可,因为我对于libtool不太熟悉,因此我选择static方式,并在 configure时加入了--with-mcrypt,这样我就不用自己手工修改Makefile 电缆桥架

三、测试及结果

  编译php,apache后,用ecb.c编译出来的encryptphp加密了几个文件,分别为< 1K,10K+,和40K+,在处理 40K大小文件时出错,别的文件均正常。塑胶地板
  这是因为块的ECB加密方式决定了必须使用定长块,所以,请 诸位同好指点采用何种流加密方式可以兼顾到zend每次读取8192字节的缓存处理方式。(其他平台上 zend每次读取的块长度可能有所不同) 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/318873.htmlTechArticle一、基本原理 考虑截获PHP读取源文件的接口。一开始,我考虑从Apache和PHP之间的接口处处理,参见apache的src/modules/php4/mod_php4.c(这个是PHP用...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn