Press "Enter" to skip to content

实现PHP的编译执行分离(separating compilation and execution)

刚刚在PHP群内和大家聊天,应承了大家要写一个关于如何实现PHP源码加密的文章, 借着这会QA在冒烟的机会,就这个问题,我写点思路。
我之前的文章介绍过, ZE(Zend engine) 执行一个PHP脚本会经历编译->执行, 只不过它每次执行都会去重新编译PHP文件。并没有实现编译和执行分离。
在ZE的编译和执行阶段,有俩个重要的函数:

ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);

  ZEND_API void (*zend_execute)(zend_op_array *op_array TSRMLS_DC);
  

zend_compile_file负责将要执行的脚本文件编译成由ZE的基本指令序列构成的op codes , 然后将op codes交由zend_execute执行,从而得到我们脚本的结果。
所以,我们完全可以通过修改默认的zend_complie_file和zend_execute来实现,PHP的执行和编译分离,进一步,我们还可以再这个基础上实现,对我们脚本的加密和解密。
我们通过一个PHP扩展模块来实现这个功能, 首先,我们需要在模块初始化的时候:

 PHP_MINIT_FUNCTION(sample)
{
    old_compile_file = zend_compile_file;  //保存现场
    old_execute = zend_execute;
    zend_compile_file = my_compile_file; //截获
    zend_execute = my_execute;
    return SUCCESS;
}

在我们的my_compile_file中,判断我们的文件是否是编译过的文件,假设后缀名是 *.ze

    static zend_op_array *my_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
{
    if(strstr(file_handle->filename, ".ze") != NULL){//是编译过的文件。
         直接返回文件内容.
    }
   zend_op_array *op_array;
   op_array = old_compile_file (file_handle, type TSRMLS_CC); //调用默认的compile,截获输出
   if(op_array){
       保存op_array;
   }
    return op_array;
}

这样,我们就实现了, 对已经编译文件的支持,和对文件编译的支持。
然后,需要编写我们的执行函数:

static void my_execute(zend_op_array *op_array TSRMLS_DC)
{
    old_execute(op_array TSRMLS_DC); //简单交由默认执行函数执行。
}

也许你要问为什么要包装以后的执行函数, 呵呵,我只是为了说明,一种方式,就是可以截获这个东东而已。。 有什么用,就看读者你有什么要求能通过这个方式实现了 ;)
恩,写到这里, 你也许就明白了, 如果想要对文件加密, 那么就定义个加密文件类型,比如 *.zec, 然后在my_compile_file中,判断文件类型,如果是加密文件,那么就执行解密,;),嘿嘿,简答吧?
至于怎么加密,,,那就要问你自己了,你想用什么方式,,,但是,记住,要可逆的哦~~ ^_^。

Be First to Comment

  1. bittercookie
    bittercookie March 21, 2013

    请问一下,如果这种方式,如果使用了apc的话,兼容性上是否有问题,配置上加密模块和apc模块顺序上有没有强制性的要求? 本人菜鸟,求轻拍

  2. bird
    bird April 3, 2012

    鸟哥,什么群啊,我能加吗?

  3. 雪候鸟
    雪候鸟 September 11, 2009

    @phper 惭愧, 我没有测试过,只是谈个想法, 呵呵. 这块要实现, 还是要做很大实验的.

  4. phper
    phper September 11, 2009

    不加密怎么样保存op_array?怎么直接返回文件内容?
    zend_op_array好像是链表类的结构体.
    您有没有测试过?有实例代码吗?
    if(op_array){
    保存op_array;
    }
    if(strstr(file_handle->filename, “.ze”) != NULL){//是编译过的文件。
    直接返回文件内容.
    }

  5. Anonymous
    Anonymous May 12, 2009

    最近研究這方面,在源代碼級別上開發有很多方面可以應用。

  6. 雪候鸟
    雪候鸟 August 20, 2008

    恩对,APC的实现原理和这个差不多,一般来说会存在内存,或者类dbm的数据库中。

  7. Leric
    Leric August 20, 2008

    估计APC之类的opcode缓存就是这么实现的吧,也不知道那些缓存的东西都放哪儿了

  8. 雪候鸟
    雪候鸟 August 16, 2008

    呵呵,人各有志么,我只是说个实现方式。。
    我是坚实的开源拥护者。

  9. guoxiaod
    guoxiaod August 16, 2008

    为什么要为 中国的开源事业制造绊脚石呢?

Leave a Reply to Anonymous Cancel reply

Your email address will not be published. Required fields are marked *