在php源代码的保护在事理可以分为3大类.
源代码稠浊(编码)OPCODE稠浊(编码)修正阐明引擎(虚拟机)在支配上可以分为2大类.
无扩展有扩展下面剖析下各种加密方案的实现方法
PHP 加密方案剖析无扩展方案
源代码稠浊
无限扩展的加密在一些小开拓者比较常见。这种源代码保护办法侵入性小,无需对做事器做额外的配置,兼容性较强。
这种情形稠浊后的源代码还原非常大略,可完备还原出源代码。 有时连注释都会保留 (x 我以为这种稠浊都不能称之为加密基本流程 压缩代码->稠浊变量函数类名->利用大略函数和方法进行编码加密 例:base64 异或
【点击查看资料】或私信回答“资料”获取
手工解密
看到这种的php不要慌 这种处理后的文件 解密流程的变量和函数名利用了大量的非打印字符 按照正常的流程就可以ctrl+alt+l 快捷键 格式化代码 (这里利用的PhpStorm 其他IDE 格式化碰着分外符号可能出问题 这里提前调度好了文件编码)
这里有一个php的特性 php中的base64碰着非base64表中字符会直接忽略 不会影响解码注: PHP7 碰着空字符可能会抛出error 可以利用php5.6实行 (这里有一个兼容性问题 )碰着这种加密最大略的方法便是找文件中末了一步实行的函数 直接把内容打印出来
这种编码方法末了一步肯定要利用eval实行还原后的php代码 以是打印末了一个函数基本上php代码就会全部出来 (x 前面操作一大顿毫无卵用注: 有保护方案也利用了call_user_func或call_user_func_array间接调用eval
成功还原源代码 <?php phpinfo();?>
自动化通用解密
PHP供应了强大的扩展功能 可以直接通过编写php扩展hook eval干系函数 获取实行的源代码HOOK php zend引擎的 zend_compile_string zend_include_or_eval 函数达到目的这里演示的是 hook zend_compile_string 函数
/ $Id$ /#include "php.h"#include "ext/standard/info.h"static zend_op_array (old_compile_string)(zval source_string, char filename TSRMLS_DC);static zend_op_array evalhook_compile_string(zval source_string, char filename TSRMLS_DC){ if(strstr(filename, "eval()'d code")) { printf("\n------eval-------\n%s\n------eval-------\n",Z_STRVAL_P(source_string)); } return old_compile_string(source_string, filename TSRMLS_CC);}PHP_MINIT_FUNCTION(evalhook){ return SUCCESS;}PHP_MSHUTDOWN_FUNCTION(evalhook){ return SUCCESS;}PHP_RINIT_FUNCTION(evalhook){ old_compile_string = zend_compile_string; zend_compile_string = evalhook_compile_string; return SUCCESS;}PHP_RSHUTDOWN_FUNCTION(evalhook){ zend_compile_string = old_compile_string; return SUCCESS;}PHP_MINFO_FUNCTION(evalhook){ php_info_print_table_start(); php_info_print_table_row(2, "eval hooking", "enabled"); php_info_print_table_end();}zend_function_entry evalhook_functions[] = { ZEND_FE_END};zend_module_entry evalhook_module_entry = { STANDARD_MODULE_HEADER, "evalhook", evalhook_functions, PHP_MINIT(evalhook), PHP_MSHUTDOWN(evalhook), PHP_RINIT(evalhook), PHP_RSHUTDOWN(evalhook), PHP_MINFO(evalhook), "0.0.1-dev", STANDARD_MODULE_PROPERTIES};ZEND_GET_MODULE(evalhook)
成功还原源代码
PHP扩展方案源代码稠浊
利用php扩展的代码稠浊和无扩展代码稠浊比较相似,只不过是把代码还原过程从php代码转到了php扩展。同样是利用aes des 异或等加密方法直接加密php代码,HOOK翻译php的函数在翻译PHP文件前对文件进行解密操作。这种方案也可以完备还原出源代码。在无其他稠浊和压缩时乃至还会保留注释。
手工解密
这里以beast为例.首先在php的扩展目录下找到beast.sobeast的加密方案会把加密key编译进扩展中. 我们只须要探求key就可以完成解密beast由于是开源项目.有现成的符号表和源码这使得反编译探求key变得非常大略.但这样有点太大略了. 以是这里演示的是在没有源码的情形下利用IDA剖析解密流程.
首先在导入表找到zend_compile_file这个函数会将php文件翻译成opcode因此大部分php加密扩展都须要hook这个函数达到拦截php文件载入和更换php文件的功能
连续跟入创造有两个函数一样平常在这种php加密扩展设计时会对这个函数有两次操作:一个是在启动时hook 这个函数,一个是在停滞时规复这个函数。连续跟入启动hook
显然文件处理逻辑在cgi_compile_file内
跟踪文件句柄decrypt_file函数的参数存在文件句柄 以是这个函数该当便是文件解密函数
根据代码可以看出beast 加密文件的构造| encrypt_file_header_sign 文件头标记(不固定 可修正)| reallen文件长度 int 4字节 | expire 到期韶光 int 4字节| entype 加密办法 int 4字节| 加密后文件|
剖析文件头创造该文件加密办法为 02
跟入beast_get_encrypt_algo
2对应的是 aes_handler_ops
利用了AES 128 ECB加密模式直接提取key参数内容长度刚好16位
到这一步就成功拿到了加密秘钥
利用拿到的KEY就可以解密PHP文件
自动化通用解密
编写php扩展 HOOK zend_compile_file函数
beast的加密不会对php文件做额外的操作 解密文件与加密前原文件完备同等php注释和原格式都会保留把稳: 这里扩展加载顺序问题 建议直接修正php源码Zendzend_language_scanner.cZEND_API zend_op_array compile_file
opcodephp会将源代码翻译成类似汇编的二进制中间操作码再交给zend引擎实行。之前的先容的都是编译之前对php源代码的直接操作。这里是对opcode的操作,跳过翻译过程,直接把现成的opcode交给zend引擎实行(不同版本PHP引擎编译出的opcode可能会有兼容性问题)。这种php代码防护方法 只能hook zend_execute 拿到opcode。 不可能直接得到原来的源码,只能通过反编译尽可能的还原源代码。大部分商业php保护方案都利用这种可靠的方案为根本 _ZendGuard(zend) _SourceGuardian(SG) IonCube (IC) Swoole Compiler上面的方案有的还对zend引擎进行了魔改,使翻译出的opcode只能在修正后的引擎实行,进一步增强了安全性。
还原代码
hook zend_execute 拿到opcode利用对应版本的php操作码反推php代码太菜了不会反编译)
私信回答“资料”获取以下:
1、200多本网络安全系列电子书2、全套工具包3、100份src源码技能文档4、网络安全根本入门、Linux、web安全、攻防方面的视频6、 网络安全学习路线7、ctf夺旗赛解析
附录PHP扩展编译
docker run -it --rm -v /mnt/hgfs/tmpssd/php-eval-hook/:/ext/ php:5.6 /bin/bashapt-get update apt install libtool
phpize
phpize 天生Makefile
./configure --enable-evalhook
配置编译选项 启用扩展
末了实行make 编译扩展编译好的扩展会放在./modules/ 目录下利用扩展
php -d extension=扩展位置 -f 文件
可以重复利用-d extension 加载多个扩展
总结在选用PHP源码保护方案时 只管即便选择opcode或虚拟机方案源代码稠浊类只能对源代码获取和阅读增加一点困难 在加密扩展可被攻击者获取到时并不能起到保护浸染