一、基本原理
考虑截获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++代码
/* 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_CACHESIZE 8192
#include < mcrypt.h >
#include < stdio.h >
#include < stdlib.h >
#include < math.h >
#include < sys/types.h >
#include < sys/stat.h >
#include < fcntl.h >
main(int argc, char** argv)
{
int td, i,j,inputfilesize,filelength;
char filename[255];
char password[12];
FILE* ifp;
int readfd;
char *key;
void *block_buffer;
void *file_buffer;
int keysize;
int decode=0;
int realbufsize=0;
struct 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);
if((readfd=open(filename,O_RDONLY,S_IRUSR|S_IWUSR|S_IRGRP))==-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每次读取的块长度可能有所不同)
更多相关内容请关注PHP中文网(www.php.cn)!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SecLists
SecLists ialah rakan penguji keselamatan muktamad. Ia ialah koleksi pelbagai jenis senarai yang kerap digunakan semasa penilaian keselamatan, semuanya di satu tempat. SecLists membantu menjadikan ujian keselamatan lebih cekap dan produktif dengan menyediakan semua senarai yang mungkin diperlukan oleh penguji keselamatan dengan mudah. Jenis senarai termasuk nama pengguna, kata laluan, URL, muatan kabur, corak data sensitif, cangkerang web dan banyak lagi. Penguji hanya boleh menarik repositori ini ke mesin ujian baharu dan dia akan mempunyai akses kepada setiap jenis senarai yang dia perlukan.

PhpStorm versi Mac
Alat pembangunan bersepadu PHP profesional terkini (2018.2.1).

Muat turun versi mac editor Atom
Editor sumber terbuka yang paling popular

ZendStudio 13.5.1 Mac
Persekitaran pembangunan bersepadu PHP yang berkuasa