php.ini路径为:
/etc/php/7.4/apache2/php.ini /etc/php/7.4/cli/php.ini
接下来需要安装解密和调试PHP文件所需的扩展vld。
vld是PECL(PHP 扩展和应用仓库)的一个PHP扩展,现在最新版本是 0.17.2 (2021-11-30),它的作用是:显示转储PHP脚本(opcode)的内部表示。
简单来说就是,可以查看PHP程序的opcode。
访问网站http://pecl.php.net/get/vld-0.17.0.tgz进行下载,解压。
在之前的测试中发现,官方版本的vld扩展在对sg11加密文件进行调试时,并不会显示完整的opcode。
于是我们需要下载补丁,对vld进行魔改。
补丁地址:https://github.com/clouds-flight/php7-vld-sg11-patch
将vld_patch.c 和srm_oparray_patch.c拷贝到vld扩展源码目录下。
在命令行中执行:
patch -p0 < vld_patch.c patch -p0 < srm_oparray_patch.c phpize ./configure make && make install
安装完成后,会显示扩展安装后的路径,正常应该是PHP的扩展目录。
同样,需要在php.ini中,加入extension=vld.so。
以上,前期环境准备全部完成。
Ubuntu 20.04.1PHP 7.4.3 apt install libjpeg62-devapt install php7.4-dev SourceGuardian 13 Evaluation for Linux GUI ixed.7.4.lin vld 0.17.0
0x02 加密解密
2.1 加密
加密的流程还是比较简单的。
双击打开加密程序,输入注册时的账号密码进行授权。
点击 File -> New -> add,添加一个需要加密的PHP文件,之后选择一个加密后文件的保存目录即可。
加密后的文件有明显的特征,例如:sg_load。
并且,文件可以正常运行。
2.2 解密
之前说过,目前互联网上没有自动化的解密工具,大部分解密都是人工解密,导致价格很高。
并且也没有一篇完整的解密相关的文档,大部分都是引流。
具体原因,应该是解密流程过于复杂。
解密,就用到了上面提到的vld扩展,我们需要根据opcode,人工还原代码。
命令如下:
php -dvld.active=1 -dvld.execute=0 test.php
其中:
dvld.active=1表示启用vld扩展,dvld.execute=0表示不执行PHP文件。
这两个参数加在一起,就表示只显示opcode。
运行结果很长,我们把它分成三部分来看。
✍️首先是第一部分:
line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 2 0 E > INIT_FCALL 'error_reporting' 1 SEND_VAL 0 2 DO_FCALL 28 3 INIT_FCALL 'unserialize' 4 FETCH_R global ~1 '_POST' 5 FETCH_DIM_R ~2 ~1,url 6 SEND_VAL ~2 7 DO_FCALL 31 8 > RETURN 1
先看列名,我们主要关注的是line、op和operands。
line表示当前对应的是哪一行php语句。
op则是opcode。
而operands是具体描述。
举个栗子🌰,例如前三行。
INIT_FCALL 准备了执行函数时所需要的上下文数据。
DO_FCALL 负责执行函数。
SEND_VAL表示函数调用时传递值作为参数。
综合以上信息,可知:
error_reporting(0);
并且在文件的第二行。
而分析第一部分内容,不难得出以下代码👇
<?phperror_reporting(0); class Welcome { function gogogo() {}}...unserialize($_POST['url']); ?>
之后,继续分析下一部分内容:
这部分内容为gogogo函数。
具体opcode的功能解释,可参考OPCODE的功能列表http://dezend.qiling.org/985.html
文中不再赘述了哦~
需要注意的是compiled vars,里面表明了所用到的变量名。
标号0是函数传入的参数,$url。
而标号12的指令含义是条件跳转,也可以理解为if,而它一直持续到了最后。
也就是说明,这其中的代码都在if的花括号里面。
而1-11则是if的条件。
分析结果如下:
<?php error_reporting(0); class Welcome { function gogogo($url) { if(!pg_match("/file|ftp/i", $url) && pg_match("/^\w+:\/\/127\.0\.0\.1/i", $url)) { $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); } }}unserialize($_POST['url']);?>
现在,继续分析最后一部分内容。
这一部分的主要内容是Class中的__wakeup和__destruct两个函数。
内容很少,其中__wakeup是直接进行了赋值操作。
__destruct则是进行了一个简单的判断,判断url是否存在。
至此,分析结束。
但是,一直到最后,我们并没有发现类中定义变量的操作。
所以,还需要以下操作:
<?php include('./test.php'); $a = new Welcome(); $arr = get_defined_vars();#$func=get_defined_functions(); var_dump($arr['a']);#var_dump($func); ?>
结果如下:
object(Welcome)#1 (1) { ["url":protected]=> NULL}
所以,class中定义了protected类型的url变量。
复原代码如下:
<?phperror_reporting(0); class Welcome { protected $url; function gogogo($url) { if(!pg_match("/file|ftp/i", $url) && pg_match("/^\w+:\/\/127\.0\.0\.1/i", $url)) { $ch=curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result=curl_exec($ch); curl_close($ch); echo ($result); } } function __wakeup() { $this->url='http://127.0.0.1/index.php'; } function __destruct() { if(!empty($this->url)) { $this->gogogo($this->url); } } } unserialize($_POST['url']); ?>
0x03 写在最后
文章中提到的样例,是最理想的状态。
如果在opcode不能明显看出具体调用的话,则可能需要:
include('./test.php'); $func=get_defined_functions();$arr = get_defined_vars();
这就需要更加细心,也更耗费时间和精力。
总的来说,vld魔改之后,对于解密sg11的帮助是很大的。
只要稍微看懂一点opcode,就可以大概复原出代码逻辑。
本文只是起到一个入门级的指引作用,作者本身对于opcode和sg11的原理并不是很了解。
之所以写这篇文章,也只是记录一下自己的学习流程。
文章所述,仅供参考,如有错误,欢迎指正。
本文地址:百科问答频道 https://www.neebe.cn/wenda/906551_2.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!