前面一篇文章 实战还原PHP加密文件 说到我发现了PHP加密文件方式的不足,所以才有了这篇文章。
背景分析
众所周知 PHP 是一种脚本语言,脚本语言主要是使用解释运行而非编译运行。所以相对于编译型语言(C、C#、C++),它没有直接生成exedll的能力。所以传统型的加密方式加壳它使用不上。
所以PHP的加密方式一般有两种:混淆和加密。
混淆这种严格意义上不算加密,这种代码就像用拼音缩写命名变量的代码,只是你看起来费劲了点。这种不在我们讨论范围。
加密分为两种方式执行:一种是有扩展(Loader)。 另外一种是无扩展。
首先讲讲无扩展的加密方式。这种加密方式非常的无脑,因为他的解密过程是公开的,而且得利用已知的PHP函数。加密之后的代码一般类似下面:
<?phpeval(base64_decode("cGhwaW5mbygpOw=="));
即使看起来非常复杂的:
也不过是上面的变式而已。像这种解密形式公开的非常好破解,只要找到 eval 改成 echo 就行。
另外一种有扩展方式就比较复杂了。扩展在这里的作用主要是解密跟执行代码,相比无扩展的形式他将解密跟执行的代码隐藏在扩展里,所以破解较为复杂。
这里的扩展一般分为两种类型的:1、提供解密执行函数的。2、直接覆盖 zend_compile_file 实现解析自定义的php文件功能。
第一种最典型的例子就是我上篇文章提到的 zoeeyguard,主要使用了 zend_eval_string 这个函数来执行php代码。
第二种代表的有:Zend Guard 和 松哥的 php-beast 。
可以说两种破解思路都差不多。可以优先尝试我上一篇文章里面的思路。
当然如果我上一篇没有解决的情况下怎么办呢?
这个时候就需要奉上大杀器了。
你会发现我在前文一直说到两个的函数 zend_compile_file 和 zend_eval_string,有些聪明的phper已经想到了,对!思路还是 只要找到 eval 改成 echo 就行。
实战例子
咱们不能光打嘴炮,光说不做。来个例子:
这次咱们拿松哥的 php-beast 来下手。松哥的代码写得非常漂亮,知道 AES DES 解密耗费时间还写了个 Cache 。
1.下载 linux 的 php 源码包(版本最好在5.6跟5.5之间选择一个,7不支持,BTW:7的改动还是挺大的,很多东西都没兼容,Zend Guard 也不支持7。这里我走了弯路。)
2.找到文件 Zendzend_language_scanner.c 中的函数:zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) 大概在500多行的样子,将如下的代码加在前面(代码写得烂,切勿吐槽):
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) { zend_lex_state original_lex_state; zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); zend_op_array *original_active_op_array = CG(active_op_array); zend_op_array *retval=NULL; int compiler_result; zend_bool compilation_successful=0; znode retval_znode; zend_bool original_in_compilation = CG(in_compilation); /** BEGIN **/ //加在这里的含义就是每次php编译php源码的时候都把这份源码打印一份 char *buf; size_t size; zend_stream_fixup(file_handle, &buf, &size); printf("\n#######\nFILE TYPE: %d FILE NAME: %s CONTENT: %s\n#######\n", (*file_handle).type, (*file_handle).filename, buf); /** END **/
在php文件夹下执行:
//节省点时间 ./configure --disable-ipv6 --disable-all make make install
4.如果顺利的话PHP已经安装成功了。
5.我们写两个测试文件:作用是: test.php 执行它去加密 before.php 生成 after.php。
//test.php <?php $path = __DIR__ . '/before.php'; $newPath = __DIR__ . '/after.php'; $result = beast_encode_file($path, $newPath, 0, BEAST_ENCRYPT_TYPE_DES); var_dump($result);
//before.php <?php print 'http://wx-app.com.cn/' . PHP_EOL;
7.执行以下 php test.php 接着在执行 php after.php。
下面就看截图吧:
总结
1、没有破不了的密码。我们能做的只是增加破解时间。如果这个破解时间大于一个人的寿命,那么这个加密方式肯定是成功的。
2、对于加密的程序,就像破解者需要了解、猜测编写者的思路一样,编写者也需要去了解破解者的方法、手段。这样才能写出破解难度更高的程序。
3、相比加密我觉得混淆更适合php源代码的“加密”。
4、如果你的php代码想要加密发布出去,最好的方式还是提高收费然后直接源码提供。