Principles and Practices of modifying Zend Engine to implement PHP source code encryption

Source: Internet
Author: User
Tags mcrypt
The source code of PHP files is plain text, which is not suitable for some commercial purposes. Therefore, we consider using encryption to protect the source code. It is really impatient to wait for zend to exit the compiler, and compilation and encryption are not the same thing in nature. Start modification by yourself. 1. The basic principle is to intercept interfaces for PHP to read source files. In the beginning, I considered that the source code of the PHP file between Apache and PHP is plain text, which is not suitable for some commercial purposes.
Therefore, we consider using encryption to protect the source code.

It is really impatient to wait for zend to exit the compiler, and compilation and encryption are not the same thing in nature. Start modification by yourself.

I. Basic principles

Consider intercepting interfaces for PHP to read source files. At the beginning, I considered processing from the interface between Apache and PHP. For more information, see src/modules/php4/mod_php4.c of apache. (this is PHP compiled into apache in static mode, make install file), intercept the file pointer in the send_php () function, use the temporary file method, decrypt and replace the file pointer. This method has been tested and proved to be feasible. However, two file operations are required, which is inefficient and not applicable to DSO.
As a result, re-consider the process of intercepting PHP to read files and load them to the cache, after laborious search, found that the zend-scanner.c in the Zend Engine is doing this. Start modifying this file.

II. implementation method diagram

Libmcrypt is used as the encryption module, and the DES method is used for ECB mode encryption,

The source code of file encryption is as follows:

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

Because ECB mode is block encryption with a fixed block length, some null characters are entered here.

Then, modify the Zend/zend-scanner.c in php code as follows:

(My php version is 4.01pl2, suniscsi/solaris 2.7, gcc 2.95 ;)

Before the file is added:

# Define MCRYPT_BACKWARDS_COMPATIBLE 1
# Include <mcrypt. h>

Then, comment out the definition of YY_INPUT before and after about 3510 rows.

Then, modify the yy_get_next_buffer () function before and after about 5150 rows:
Define the function header:
Void * tempbuf;
Char * key;
Char debugstr [255];
Int td, keysize;
Int x, y;
FILE * fp;
Then, comment out
YY_INPUT (& yy_current_buffer-> yy_ch_buf [number_to_move]),
Yy_n_chars, num_to_read );
This sentence.
Changed:

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

Then compile php and install it as usual. because I am not familiar with libtool, I chose static mode and added -- with-mcrypt in configure, in this way, I don't have to manually modify the Makefile.

III. test and result

Compile php, apache, and use ecb. c-compiled encryptphp encrypts several files, which are <1 K, 10 K +, and 40 K +. errors occur when processing 40 K files. other files are normal.
This is because the ECB encryption method of the block determines that the fixed length block must be used. Therefore, please give us some advice on the stream encryption method which can take into account the zend cache processing method that reads 8192 bytes each time. (The length of each zend read block on other platforms may be different)

IV. description

My machine is SUN Ultra1, solaris 2.7, gcc 2.95, apache 1.3.12,
Php 4.01pl2, libmcrypt 2.2.4
My C level is poor. please forgive me. Here is just a description of the principle.
Thank you for your assistance.
The source code complies with GNU. Note that some encryption methods provided by libmcrypt are not free.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.