>php教程 >PHP开发 >PHP 소스 코드 암호화를 구현하기 위해 Zend 엔진을 수정하는 원리와 실습

PHP 소스 코드 암호화를 구현하기 위해 Zend 엔진을 수정하는 원리와 실습

黄舟
黄舟원래의
2016-12-14 11:46:581211검색

1. 기본 원칙
소스 파일을 읽기 위해 PHP 인터페이스를 가로채는 것을 고려해보세요. 처음에는 Apache와 PHP 사이의 인터페이스를 다루는 것을 고려했습니다. apache의 src/modules/php4/mod_php4.c(PHP가 정적으로 apache로 컴파일하여 설치하는 파일입니다.), send_php()에서 파일 포인터가 차단됩니다. 함수에서는 임시 파일 방식을 사용하며, 복호화 후 파일 포인터를 교체합니다. 이 방법은 테스트를 거쳐 실행 가능한 것으로 입증되었습니다. 그러나 두 개의 파일 작업을 사용해야 하므로 비효율적이며 DSO 방식을 사용할 수 없습니다. Shuangyuan Nursing Home
그래서 PHP가 파일을 읽는 것을 가로채서 캐시에 로드하는 과정을 다시 생각해 보았는데, 열심히 검색한 끝에 Zend 엔진의 zend-scanner.c가 이를 수행한다는 것을 발견했습니다. 이 파일 수정을 시작하세요. 조명 프로젝트

2. 구현 방법

libmcrypt를 암호화 모듈로 사용하고, 이제 DES 방식의 ECB 모드 암호화를 사용합니다.

다음은 파일 암호화 소스 코드입니다. :

C++ 코드
/* ecb.c------여기에서 잘라내기---------* /
/* PHP 소스 코드 버전 0.99 베타용 암호화
우리는 libmcrypt를 사용하여 코드를 암호화하고 있습니다.
먼저 이를 설치
컴파일 명령줄:
gcc -O6 -lmcrypt -lm -o encryptphp ecb.c
사용하기 전에 LD_LIBRARY_PATH를 설정하세요.
GNU copyleft, designs by wangsu , miweicong */

#define MCRYPT_BACKWARDS_COMPATIBLE 1
#define PHP_CACHESIZE 8192
#include
#include
#include
#include sys/types.h >
#include < sys/stat.h >
#include < fcntl.h >

main(int argc** argv)
{

int td, i,j,inputfilesize,filelength;

char 파일 이름[255]
char 비밀번호[12]; >int readfd;
void *block_buffer;
int keysize;
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("디코드 모드 시작 중...n");
} else {
printf("사용법: encryptphp [-d] 비밀번호 파일 이름"); >exit (1);
}


keysize=mcrypt_get_key_size(DES);
key=calloc(1, mcrypt_get_key_size(DES));

gen_key_sha1( 키 , NULL , 0, 키 크기, 비밀번호, strlen(비밀번호));
td=init_mcrypt_ecb(DES, 키, 키 크기);

if((readfd=open(filename,O_RDONLY,S_IRUSR|S_IWUSR| S_IRGRP) )==-1){

printf("치명적: 읽을 파일을 열 수 없습니다.")

exit(3)
}

filestat=malloc(sizeof (stat ));


fstat(readfd,filestat);

inputfilesize=filestat-

printf("filesize는 %d n입니다.",inputfilesize); ;

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

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

printf("치명적: 파일 buffer.n을 실행할 수 없습니다.");

exit(2)

}
if((block_buffer=malloc(PHP_CACHESIZE))==NULL){
printf( "치명적: 블록 버퍼를 암호화할 수 없습니다.");
exit(2)

}

j=0; while(realbufsize=read(readfd) ,block_buffer, PHP_CACHESIZE)){

printf(".");
if(!decode){
if(realbufsizefor(i=realbufsize;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("치명적: 파일 액세스 오류.n")
exit(3);
fwrite( file_buffer, inputfilesize, 1, ifp);

free(block_buffer)
free(file_buffer)
fclose(ifp); 🎜>printf ("n");

return 0;

}

/*--- ecb.c의 끝 ------------ --- ---------*/
ECB 모드는 블록 길이가 정해진 블록 암호화이기 때문에 여기에는 일부 null 문자가 채워집니다. 국제 전시회

그런 다음 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 비밀번호 "PHPphp111222"
#define 디버그 0

keysize=mcrypt_get_key_size(DES)

key=calloc(1, mcrypt_get_key_size(DES))
gen_key_sha1( key, NULL, 0, keysize, 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에 익숙하지 않기 때문에 구성 시 --를 추가했습니다. -mcrypt이므로 Makefile 케이블 트레이를 수동으로 수정할 필요가 없습니다

3. 테스트 및 결과

php와 apache를 컴파일한 후 ecb.c에서 컴파일한 encryptphp를 사용하여 여러 파일을 암호화했습니다. , 각각 블록의 ECB 암호화 방식에 따라 고정 길이 블록을 사용해야 한다고 결정하기 때문입니다. 따라서 zend의 읽기 캐시 처리 방식을 고려하여 어떤 스트림 암호화 방식을 사용할 수 있는지 조언 부탁드립니다. 매번 8192바이트입니다. (다른 플랫폼에서는 zend가 매번 읽는 블록 길이가 다를 수 있습니다)

더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.