『代码审计』如何解密 PHP 代码

admin 2022年4月22日00:29:30评论431 views字数 5550阅读18分30秒阅读模式
『代码审计』如何解密 PHP 代码

点击蓝字,关注我们



日期:2022-04-21

作者:Obsidian

介绍:兴之所至,简单聊聊;所学不精,还请见谅。简单聊聊sg11的加密与解密~


关注微信公众号『宸极实验室』,回复关键词『0421-sg11』,即可获得文中工具及扩展大礼包😍😍


0x00 写在前面

sg11 全称为SourceGuardian ,是PHP下的加密扩展,通过将PHP源代码编译为字节码格式,然后编译为加密层,来保护PHP代码。

目前互联网上并没有详细的解密教程,经过再三搜索,找到的多为留下QQ人工解密,单文件价格高达150-200元。

至于为什么会想到尝试解密它,故事要从这里开始讲起………

『代码审计』如何解密 PHP 代码

那晚,我的一个不愿意透露姓名的朋友找到我,发来一个压缩包,是一个知名发卡平台的源码。

他问我:审一下,看看能搞吗?😟

但是我回答:

『代码审计』如何解密 PHP 代码

我能受这气????

后来,我们尝试了一晚上的解密,最终还是以失败告终。

『代码审计』如何解密 PHP 代码

再后来,就有了这篇文章。

0x01 环境准备

在之前的尝试中,我们发现,SourceGuardian对加解密环境要求十分严格,加解密环境必须一致。

并且,ubuntu18LIBC版本不适配SourceGuardian加密程序,会导致报错。

所以,本文的测试环境为:

Ubuntu 20.04.1PHP    7.4.3
apt install libjpeg62-devapt install php7.4-dev

『代码审计』如何解密 PHP 代码

SourceGuardian本身是收费软件,但是提供14天免费试用。

首先打开官网https://www.sourceguardian.com/

点击首页的 Try it Now 

『代码审计』如何解密 PHP 代码

目前它的版本已经更新到了13,我们选择 SourceGuardian 13 Evaluation for Linux

『代码审计』如何解密 PHP 代码

之后填写信息进行注册。

注册完成后,可进行下载,有命令行版本和GUI版本,我们选择 SourceGuardian 13 Evaluation for Linux GUI

『代码审计』如何解密 PHP 代码

下载完成后,将压缩包解压,之后运行install-menu-icons.sh,这一步是为了在桌面创建快捷方式。

『代码审计』如何解密 PHP 代码

运行完成后,会在桌面生成一个 SourceGuardian.desktop

『代码审计』如何解密 PHP 代码

右键,选择 Allow Launching,即可双击运行。

『代码审计』如何解密 PHP 代码

或者可通过文件夹中的RUNME.sh脚本,进行命令行启动。

在安装完加密程序(encoder)之后,还需要运行加密文件所需的加载器(loader)。

访问网站https://www.sourceguardian.com/loaders/download/loaders.linux-x86_64.tar.gz,进行下载。

解压后,找到对应版本的文件ixed.7.4.lin,将其放入PHPlib目录,例如:/usr/lib/php/20190902/

『代码审计』如何解密 PHP 代码

之后在php.ini中,加入extension=ixed.7.4.lin

『代码审计』如何解密 PHP 代码

注意,php.ini会有两个文件,分别对应Apache和命令行,建议都添加上。

php.ini路径为:

/etc/php/7.4/apache2/php.ini
/etc/php/7.4/cli/php.ini

接下来需要安装解密和调试PHP文件所需的扩展vld

vldPECLPHP 扩展和应用仓库)的一个PHP扩展,现在最新版本是 0.17.22021-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.csrm_oparray_patch.c拷贝到vld扩展源码目录下。

在命令行中执行:

patch -p0 < vld_patch.c
patch -p0 < srm_oparray_patch.c
phpize
./configure
make && make install
『代码审计』如何解密 PHP 代码

安装完成后,会显示扩展安装后的路径,正常应该是PHP的扩展目录。

『代码审计』如何解密 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 加密

加密的流程还是比较简单的。

双击打开加密程序,输入注册时的账号密码进行授权。

『代码审计』如何解密 PHP 代码

点击 File -> New -> add,添加一个需要加密的PHP文件,之后选择一个加密后文件的保存目录即可。

『代码审计』如何解密 PHP 代码

加密后的文件有明显的特征,例如:sg_load

并且,文件可以正常运行。

『代码审计』如何解密 PHP 代码


2.2 解密

之前说过,目前互联网上没有自动化的解密工具,大部分解密都是人工解密,导致价格很高。

并且也没有一篇完整的解密相关的文档,大部分都是引流。

具体原因,应该是解密流程过于复杂。

『代码审计』如何解密 PHP 代码

解密,就用到了上面提到的vld扩展,我们需要根据opcode,人工还原代码。

命令如下:

php -dvld.active=1 -dvld.execute=0 test.php

其中:

dvld.active=1表示启用vld扩展,dvld.execute=0表示不执行PHP文件。

这两个参数加在一起,就表示只显示opcode

运行结果很长,我们把它分成三部分来看。

『代码审计』如何解密 PHP 代码

✍️首先是第一部分:

『代码审计』如何解密 PHP 代码


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

先看列名,我们主要关注的是lineopoperands

line表示当前对应的是哪一行php语句。

op则是opcode

operands是具体描述。

『代码审计』如何解密 PHP 代码


举个栗子🌰,例如前三行。

INIT_FCALL 准备了执行函数时所需要的上下文数据。

DO_FCALL 负责执行函数。

SEND_VAL表示函数调用时传递值作为参数。

综合以上信息,可知:

error_reporting(0);

并且在文件的第二行。

而分析第一部分内容,不难得出以下代码👇

<?phperror_reporting(0);
class Welcome {
function gogogo() {}}...unserialize($_POST['url']);
?>

此处冷场3秒
3
2
1
继续

之后,继续分析下一部分内容:

『代码审计』如何解密 PHP 代码

这部分内容为gogogo函数。

具体opcode的功能解释,可参考OPCODE的功能列表http://dezend.qiling.org/985.html

文中不再赘述了哦~

需要注意的是compiled vars,里面表明了所用到的变量名。

标号0是函数传入的参数,$url

而标号12的指令含义是条件跳转,也可以理解为if,而它一直持续到了最后。

也就是说明,这其中的代码都在if的花括号里面。

1-11则是if的条件。

『代码审计』如何解密 PHP 代码


分析结果如下:

<?php
error_reporting(0);
class Welcome { function gogogo($url) { if(!preg_match("/file|ftp/i", $url) && preg_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']);?>

现在,继续分析最后一部分内容。

『代码审计』如何解密 PHP 代码

这一部分的主要内容是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(!preg_match("/file|ftp/i", $url) && preg_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();

这就需要更加细心,也更耗费时间和精力。

『代码审计』如何解密 PHP 代码

总的来说,vld魔改之后,对于解密sg11的帮助是很大的。

只要稍微看懂一点opcode,就可以大概复原出代码逻辑。

本文只是起到一个入门级的指引作用,作者本身对于opcodesg11的原理并不是很了解。

之所以写这篇文章,也只是记录一下自己的学习流程。

文章所述,仅供参考,如有错误,欢迎指正。

『代码审计』如何解密 PHP 代码



References

   http://dezend.qiling.org/985.html


免责声明:本文仅供安全研究与讨论之用,严禁用于非法用途,违者后果自负。

『代码审计』如何解密 PHP 代码

宸极实验室

Cyber Security Lab

『代码审计』如何解密 PHP 代码

宸极实验室隶属山东九州信泰信息科技股份有限公司,致力于网络安全对抗技术研究,是山东省发改委认定的“网络安全对抗关键技术山东省工程实验室”。团队成员专注于 Web 安全、移动安全、红蓝对抗等领域,善于利用黑客视角发现和解决网络安全问题。

团队自成立以来,圆满完成了多次国家级、省部级重要网络安全保障和攻防演习活动,并积极参加各类网络安全竞赛,屡获殊荣。
对信息安全感兴趣的小伙伴欢迎加入宸极实验室,关注公众号,回复『招聘』,获取联系方式。

原文始发于微信公众号(宸极实验室):『代码审计』如何解密 PHP 代码

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月22日00:29:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   『代码审计』如何解密 PHP 代码http://cn-sec.com/archives/932258.html

发表评论

匿名网友 填写信息