近日,关于如何加密 PHP 代码在 Exceed PHP 又被提起。但依我个人观点,作者可能对 PHP 的运行机制不太了解,因此所提出方案效果基本上可以说是聊胜于无。
获取 OPCode 有很多办法,也是很简单的事情,即使是加密过的 OPCode。稍微困难的是从 OPCode 还原成 PHP Code,这需要一种很好的逆向算法,但也并非不可实现。DeZend 就是一个公开的样例,更不要说还有很多半公开甚至不公开的了。 😀
我觉得对版权的保护分为两个层次:二进制级和源代码级。所谓二进制级就是不让用户非法使用未授权的程序。但这一点很难做到。想想看 windows 下面的软件都是经过编译和加壳保护,依然不能阻挡 Cracker 的脚步,更何况是半编译的 PHP Code。所谓源代码级保护是指不让非法用户获得产品的源代码。获得源代码的非法途径通常是对代码进行反编译。目前看来很难有有效的工具来阻止这项工作,即使是 windows 下面的程序也不能阻止(windows 下一般都是“反汇编”,这个名词严格意义上不同于“反编译”)。既然不能阻止反编译,那就只好退而求次,就像把 windows 程序反汇编后得到的很少人能读懂的汇编代码一样,让非法用户即使获得了 PHP 源代码也很难读懂它。这项工作主要通过“混淆”来完成。
“混淆”有一个很常见的分支是“变量混淆”。“变量混淆”的主要原理就是机器(或者说虚拟机)对一个变量(包括函数名、类名等等)究竟是叫 $hello_world 还是叫 $#@!**& 并不关心,那只是一个代号而已。目前大部分具有混淆功能的 Encoder 基本都集中在这个部分。
“混淆”的另外一个分支就是“指令混淆”。所谓“指令混淆”就是额外插入一些垃圾代码来干扰第三方正常阅读。比如我们可以把 $a = 0;
替换成
$d = 1;
$e = $d ^ $d;
$a = $e;
结果是一样的,但要是再复杂一些保证你不明白这是怎么回事。这可以说是一种“化简为繁”的工作,也会影响些效率。但随着机器硬件的不断发展,而且有些应用对运行效率要求并不高,所以这是可以接受的(更典型的例子就是 dotNET 上桌面程序)。
“混淆”还有一个主要的分支就是“流程混淆”。流程混淆可以说是“混淆”工作的必杀技,类似汇编语言中“花指令”。它所依据的原理就是源代码和中间代码并无一一的对应关系。比如说有个 if ($a) {$b} 的语句,并非可以只能编译成“先判断 $a 是否为 true,是就跳转到 $b”这一种形式。我可以先跳转到 $c,再跳转到 $d,$d 经过 $e 等一系列垃圾运算之后再跳转到 $b。效果是一样的,貌似你很明白,但其实上你就是不明白。 8) PHP6 就要增加 goto 指令,这给各个 Encoder 的发挥空间也更大了。
目前在 Java 和 dotNET 上混淆工作大部分都集中在流程混淆上,但 PHP 方面目前大部分还停留在较初级的“变量混淆”上(ZendGuard 4 中的 Strong 级混淆也是属于“变量混淆”的范畴)。如果各位对 PHP 代码加密感兴趣,“混淆”尤其是“流程混淆”是一个很有意思的研究方向。当然反混淆是更有意思的一个方向。:)