LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

浅谈PHP源代码保护方案&受保护PHP代码の解密还原

admin
2024年7月2日 9:11 本文热度 825

前言

php是一种解释型脚本语言,与编译型语言不同,php源代码不是直接翻译成机器语言,而是翻译成中间代码(OPCODE) ,再由解释器(ZEND引擎)对中间代码进行解释运行。

在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文件前对文件进行解密操作。这种方案也可以完全还原出源代码。在无其他混淆和压缩时甚至还会保留注释。

典型开源项目:php-beast tonyenc screw-plus

手工解密

这里以beast为例:

首先在php的扩展目录下找到beast.so。

beast的加密方案会把加密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.c
ZEND_API zend_op_array *compile_file

opcode

php会将源代码翻译成类似汇编的二进制中间操作码再交给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代码

太菜了不会反编译)

附录

PHP扩展编译

docker run -it --rm -v /mnt/hgfs/tmpssd/php-eval-hook/:/ext/ php:5.6 /bin/bash
apt-get update 
apt install libtool
phpize

phpize 生成Makefile

 

./configure --enable-evalhook

配置编译选项 启用扩展

最后执行make 编译扩展

编译好的扩展会放在./modules/ 目录下

使用扩展

php -d extension=扩展位置 -f 文件

可以重复使用-d extension 加载多个扩展

总结

在选用PHP源码保护方案时,尽量选择opcode或虚拟机方案。

源代码混淆类只能对源代码获取和阅读增加一点困难,在加密扩展可被攻击者获取到时并不能起到保护作用。

PHP代码审计入门指南

参考

php内核剖析
从Zend虚拟机分析PHP加密扩展
通用加密php文件还原方法


该文章在 2024/7/2 9:25:45 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved