phpjiami 数种解密方法

phpjiami 数种解密方法

phithon
2017 九月 23 22:13
阅读:25622
网络安全
解密, phpjiami

Pwnhub公开赛出了个简单的PHP代码审计题目,考点有两个:

  1. http://www.phpjiami.com/ 加密过的源码还原
  2. 上传取后缀方式不同导致的文件上传漏洞

如果说仅为了做出题目拿到flag,这个题目太简单,后台也有数十名选手提交了答案和writeup。但深入研究一下这两个知识点,还是很有意思的。

首先通过简单的目录扫描,找到备份文件index.php.bak。下载后发现文件是经过了混淆加密处理的,大部分同学是直接网上找了付费解密的网站给解的,也有少数几个人说明了解密方法,我挑几种方法说一下。

0x01 phpjiami 代码分析破解法

这种方法我最佩服了,作者甚至给出了解密脚本,文章如下: http://sec2hack.com/web/phpjiami-decode.html

我自己在出题目之前也进行过分析,但后面并没有耐心写一个完整的脚本出来,所以我十分佩服这个作者。

我们分析phpjiami后的文件,可以看到他有如下特点:

  1. 函数名、变量名全部变成“乱码”
  2. 改动任意一个地方,将导致文件不能运行

之所以函数名、变量名可以变成“乱码”,是因为PHP的函数名、变量名是支持除了特殊符号以外大部分字符的,比如汉字等。利用这一特点,phpjiami就将所有正常的英文变量给转换了一下形式,其实没有什么特别的奥秘。

那么,为了方便分析,我们可以想办法再将其转换回英文和数字。比如,作者使用的是 http://zhaoyuanma.com/phpcodefix.html 对混淆过的代码进行美化;而我是使用 https://github.com/nikic/PHP-Parser 对整个代码进行了结构化的分析,并将所有变量和函数名进行了美化。

方法一的好处是我不需要写任何代码,就可以大致进行美化,但显然,美化后的代码是有错误的,原文中也提到了这一点;方法二,虽然需要自己写代码,但美化后的代码没有语法错误,看起来更加直观,并且我还能进一步的进行美化,比如将字符串中的乱码转换成\x的形式。

我美化后的代码如下:

后续的操作和上文也差不多,通过源码的分析,正如上文中所说,phpjiami加密源码的整个流程是:

加密流程:源码 -> 加密处理(压缩,替换,BASE64,转义)-> 安全处理(验证文件 MD5 值,限制 IP、限域名、限时间、防破解、防命令行调试)-> 加密程序成品,再简单的说:源码 + 加密外壳 == 加密程序 (该段出处)

所以,其实这种方法并没有对源码进行混淆,只是对“解密源码的壳”进行了混淆。所以你看到的中文变量、中文函数,其实是一个壳,去掉这层壳,我可以拿到完整的PHP源码。

所以呀,后台提交的writeup里,有的同学想当然地认为修改eval为echo就能输出源码了……实际上根本没实际试过,改动文件是会导致不能运行的;还有同学认为这里仅是将源码混淆为用户体验极差的代码,导致人眼无法阅读,并没有理解这里其实混淆的不是源码。

0x02 HOOK EVAL法

0x01中说到的方法固然是很美好的,但是假如加密者随意改动一点加密的逻辑,可能导致我们需要重新分析加密方法,写解密脚本。我们有没有更通用的方法?

HOOK EVAL应该是被提到过最多的方法,我也看到了Medici.Yan发布的一篇文章: http://blog.evalbug.com/2017/09/21/phpdecode_01/

我前文说过,phpjiami其实是只是混淆了壳,这个壳的作用是执行真正的源码。那么,执行源码必然是会经过eval之类的“函数”(当然也不尽然),那么,如果我们能够有办法将eval给替换掉,不就可以获得源码了么?

遗憾的是,如果我们仅仅简单地将eval替换成echo,将导致整个脚本不能运行——因为phpjiami检测了文件是否被修改。

那么,我们可以寻求更底层的方法。就是很多人以前提到过的,将PHP底层的函数 zend_compile_string给拦截下来,并输出值。Medici.Yan的文章中说的很清楚,也给出了参考文档和源码,我就不再赘述了。

我自己简单写了一个扩展,并用php5.6编译: https://drive.google.com/open?id=0B4uxE69uafD5anVTZ1VwNXN0WEU

下载之,在php.ini中添加extension=hookeval.so,然后直接访问加密过的php代码即可(当时参考tool.lu的站长xiaozi的代码 http://type.so/c/php-dump-eval.html ,所以分隔符里有关键字):

16年kuuki曾分享过一个在线解密的工具: https://xianzhi.aliyun.com/forum/read/64.html ,但测试了一下phpjiami解密不了。原因是,phpjiami在解密的时候会进行验证:

php_sapi_name() == 'cli' ? die():'';

所以如果这个源码是在命令行下运行,在执行这条语句的时候就die了。所以,即使你编译好了hookeval.so并开启了这个扩展,也需要在Web环境下运行。

提高篇:有没有什么简单的办法在命令行下也能模拟web环境呢?方法我先不说,大家可以自己思考思考。

0x03 手工dump法

那么有的同学说:php扩展太难了,我不会写C语言,怎么办?

不会写C语言也没关系,你只需要会写PHP即可。这是我凤凰师傅提到的一个方法,也是我理想中的一个解,非常简单,两行代码搞定,解密用时比你去网上花钱解密还短:

<?php
include "index.php";
var_dump(get_defined_vars());

原理其实也很简单。phpjiami的壳在解密源码并执行后,遗留下来一些变量,这些变量里就包含了解密后的源码。

虽然我们不能直接修改index.php,将这些变量打印出来,但是我们可以动态包含之,并打印下所有变量,其中必定有我们需要的源码(var_dump输出的不完整,只是用它举个例子):

当然,这个方法虽然简单,但有个很严重的问题:假如在执行源码的过程中exit()了,我们就执行不到打印变量的地方了。

所以,这个方法并不一定适用于所有情景,但对于本题来说,已经足够了。

0x04 动态调试法

那么,如果我们遇到0x03解决不了的情况怎么办?

这时候就要祭出动态调试武器了。尽管加密后的文件看起来乱七八糟,但其仍然是一个符合php语法的php文件,那么我们就可以直接利用动态调试工具进行单步调试,拿到源码。

简单拿xdebug进行调试,不停单步调试后,就可以发现我们需要的源码已经在上下文变量中的:

右键“复制值”,即可拿到源码。这也算一个比较简单的方法了。

当然,假如有一天phpjiami修改了混淆流程,源码不再储存于变量中,那么就需要分析一下代码执行的流程。所谓万变不离其中,最终断在eval的那一步,一定有你需要的源码。

0x05 代码审计Getshell

后面的部分反而比较简单。拿到index.php的源码后,发现其包含了FileUpload.class.php,所以再次下载这个文件的源码进行解密。

分析FileUpload类,发现其取后缀有两种方式:将文件名用.分割成数组$arr,一是用$arr[count($arr)-1]的方式取数组最后一个元素,二是用end($arr)的方式取数组最后一个元素。

正常来说,字符串用.分割成的数组,用这两种方法取到的末元素应该是相同的。但取文件名的时候,如果我们已经传入的是数组,则不会再次进行分割:

$filename = $_POST[...];
if(!is_array($filename)) {
    $filename = explode('.', $filename);
}

也就是说我能控制$filename这个数组。所以,我只需要找到$arr[count($arr)-1]end($arr)的区别,即可绕过后缀检查。

显然,前者是取根据数组下标来取的值,后者取的永远是数组里最后一个元素。所以,我们只需要让下标等于count($arr)-1的元素不是数组最后一个元素即可。

比如:[1=>'gif', 0=>'php']或者['0'=>'abc', '2'=>'gif', '100'=>'php']

0x06 总结

最后想说一句话:不求甚解是阻碍部分人进步的一大阻力。共勉。

 

 

转载于:https://my.oschina.net/u/190049/blog/3016989

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CTF/php后门分析中经常遇到加密压缩过的PHP文件, <? $O00OO0=urldecode("n1zb/ma5\vt0i28-pxuqy*6lrkdg9_ehcswo4+f37j");$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};eval($O00O0O("JE8wTzAwMD0iQk9DWm1LUHF5bkR4QWJmR05FdW90c2pkUlljcmlKTXdWZ0ZVenZYTGthVFNwSWxoZUhRV1dITmZhQ0d5b3RzanBRTFN3WXpyYmx4aERjQXZUT1VQUklpdW1aSmVrbktkcWdNVlhGRUJHczh3TmFWTWNCRE1BVElURTI5emhTUnpoTjEwWEpXTUhUVzBmSlYwZTJWMFFCUDdnU3dyY0pPbWZKRTloSkRhZUtJVENLbElzRXFxZlRJVmZhTWxmUjlNWFNNbWhGVXJPbzRaZlNpMGNkOXFRdHcwY0JqbGVhalpjMmx0Q2Rrd050bHdOVHBJZ05XcmZCaWtmSmdyZ2tqWmMyaTBuQjl6SFRwWm5CNW1oU2lsUU45cVFhRE1YTjVQbkZwVENLbHdOVHBJZ05XTVhTTTBIUDBDTEUwQ2ZTUmFuQjVNQ05oV3VpV0x1azlHUk5BbGdGdzBBTTlvZkpXbGNCd01DTmhBSk5BbGdOQVpPb1BJZlNNb1FhaWJmZFZMSjBmT0tZUkxKb2txQ0tsd05UOHlnSEI2TUhYdXlIQkV4WFh0bEZoM2hvNVZmUzFxUWE0emMyNHllUDBDZlNSYW5CNU1DTmhXdWlXTEtraXdEZEFsZ05oVkFGcHRDS2x3TlQ4eWdIQjZNSFh1eUhYUXZ6QjlNZHJac0Vxa2ZCZnFRYXVyTzBpRXVpOUVFUkRnT29QSU9vNFpjMjFtaFNpWmVvQXFIUDBDZW9ySTVxQlA1cjJ6NTV6ejVRMlJDVDh3TmFETWZhTXpmZEl0dVlNSEowRFdSWWlMdVlpdWROQWxnTkF6ZTJEVmhTWVpPb2s3c0VyWkNUc2FUbnRNbGZKdGE2N01aZnV5ZVAwQ2ZTUmFuQjVNQ05oaUJpRGlLa0RMdVlpdWROQWxnWWlFdWk5RUVSRGdnTjRJTzBSNGhTUnpmTjh0Q0tsd05UOHlnSGFpeFhYOXZ6bkJWK2Q3YnpYUXZ6QjlNZHJac0Vxa2ZCZnFRYXVyTzB3R0trZkx1WWl1ZE5BbGdpV09LTTlZRVJEV0oxV1dSWUlJZVRwdGMyOXpmYU10ZW9BcUhQMENlb3JJNXFCUDVyMno1NXp6NVEyUkNUOHdOYURNZmFNemZkSXR1TVJIUllNd0RSOUVFUkRnT29QSU9vNFpKM08xUXREcVFCdVpPb2s3c0VyWkNUV2dSWTFVNmYyZjVyTlc1cW5GNWV6MjU1eno1UTJSQ1Q4d05UOFpmU1JhbkI1TUNOaGdSWTFVSjFXV1JZSXRlTldFZHU1TERZaXVFUjlFRVJEZ2dONElPMlYwUUJQWk9vazdzRXJaQ1RXWUR1T1JEK0I4SUhCaWxvclpzRXFrZkJmcVFhdXJPMGlFdWk5WUR1T1JEb0FsZ1NmVlFGd01DS2x3TnRPTUFKUnFBYXVyZ1Q0WmMyOW9mZDl1blNNem4xV2d1Tjl1blNNem4xV2d1TjVQbkZwVENLbHdOSTBDc0VyL0dJPT0iO2V2YWwoJz8+Jy4kTzAwTzBPKCRPME9PMDAoJE9PME8wMCgkTzBPMDAwLCRPTzAwMDAqMiksJE9PME8wMCgkTzBPMDAwLCRPTzAwMDAsJE9PMDAwMCksJE9PME8wMCgkTzBPMDAwLDAsJE9PMDAwMCkpKSk7")); ?> 编译环境 ===================================================================== PHP : /usr/bin/php7.2 PHP_SAPI : cli PHP_VERSION : 7.2.9-1 ZEND_VERSION: 3.2.0 PHP_OS : Linux - Linux kali 4.14.0-kali3-amd64 #1 SMP Debian 4.14.17-1kali1 (2018-02-16) x86_64 INI actual : /root/temp/evalhook/tmp-php.ini More .INIs : CWD : /root/temp/evalhook Extra dirs : VALGRIND : Not used ===================================================================== TIME START 2019-01-04 07:46:12 ===================================================================== php -d extension=evalhook.so encoded_script.php 可直接dump大部分加密php文件中eval中的内容

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值