修改Zend引擎实现PHP源码加密的原理及实践_php教程-查字典教程网
修改Zend引擎实现PHP源码加密的原理及实践
修改Zend引擎实现PHP源码加密的原理及实践
发布时间:2016-12-29 来源:查字典编辑
摘要:一、基本原理考虑截获PHP读取源文件的接口。一开始,我考虑从Apache和PHP之间的接口处处理,参见apache的src/modules/...

一、基本原理

考虑截获PHP读取源文件的接口。一开始,我考虑从Apache和PHP之间的接口处处理,参见apache的src/modules/php4/mod_php4.c(这个是PHP用static方式编译进apache,makeinstall后的文件),在send_php()函数中截获文件指针,采用临时文件的方式,解密后替换文件指针。这种方法经过测试实践,证明是可行的。但是,必须使用两次文件操作,效率低下,而且对于DSO方式不可采用。双缘敬老院

由此,重新考虑截获PHP读取文件并装载至缓存的过程,经过费力的寻找,发现在Zend引擎中zend-scanner.c是做此处理的。开始对此文件修改。照明工程

二、实现方法示意

采用libmcrypt作为加密模块,现在采用的是DES方法ECB模式加密,

下面是文件加密的源代码:

C++代码

/*ecb.c-------------------cuthere-----------*/

/*encryptforphpsourcecodeversion0.99beta

weareusinglibmcrypttoencryptcodes,please

installitfirst.

compilecommandline:

gcc-O6-lmcrypt-lm-oencryptphpecb.c

pleasesetLD_LIBRARY_PATHbeforeuse.

GNUcopyleft,designedbywangsu,miweicong*/

#defineMCRYPT_BACKWARDS_COMPATIBLE1

#definePHP_CACHESIZE8192

#include<mcrypt.h>

#include<stdio.h>

#include<stdlib.h>

#include<math.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

main(intargc,char**argv)

{

inttd,i,j,inputfilesize,filelength;

charfilename[255];

charpassword[12];

FILE*ifp;

intreadfd;

char*key;

void*block_buffer;

void*file_buffer;

intkeysize;

intdecode=0;

intrealbufsize=0;

structstat*filestat;

if(argc==3){

strcpy(password,argv[1]);

strcpy(filename,argv[2]);

}elseif(argc==4&&!strcmp(argv[1],"-d")){

strcpy(password,argv[2]);

strcpy(filename,argv[3]);

decode=1;

printf("Enteringdecodemode...n");

}else{

printf("Usage:encryptphp[-d]passwordfilenamen");

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((readfd=open(filename,O_RDONLY,S_IRUSR|S_IWUSR|S_IRGRP))==-1){

printf("FATAL:Can'topenfiletoread");

exit(3);

}

filestat=malloc(sizeof(stat));

fstat(readfd,filestat);

inputfilesize=filestat->st_size;

printf("filesizeis%dn",inputfilesize);

filelength=inputfilesize;

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

if((file_buffer=malloc(inputfilesize))==NULL){

printf("FATAL:can'tmallocfilebuffer.n");

exit(2);

}

if((block_buffer=malloc(PHP_CACHESIZE))==NULL){

printf("FATAL:can'tmallocencryptblockbuffer.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:fileaccesserror.n");

exit(3);

}

fwrite(file_buffer,inputfilesize,1,ifp);

free(block_buffer);

free(file_buffer);

free(filestat);

fclose(ifp);

printf("n");

return0;

}

/*---endofecb.c------------------------------------*/

因为ECB模式是块长度确定的块加密,这里填充了一些空字符。国际展览

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

(我的php版本是4.01pl2,SUNsparc/solaris2.7,gcc2.95;)

文件前加入:

#defineMCRYPT_BACKWARDS_COMPATIBLE1

#include<mcrypt.h>

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

然后,修改大约5150行前后的yy_get_next_buffer()函数:

函数头加上定义:

void*tempbuf;

char*key;

chardebugstr[255];

inttd,keysize;

intx,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*/

#definepassword"PHPphp111222"

#definedebug0

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每次读取的块长度可能有所不同)

相关阅读
推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
  • 大家都在看
  • 小编推荐
  • 猜你喜欢
  • 最新php教程学习
    热门php教程学习
    编程开发子分类