w00tzenheimer/d810-ng

GitHub: w00tzenheimer/d810-ng

D810-ng 是一个 IDA Pro 反混淆插件,通过在反编译时修改微码来简化被混淆的表达式并还原控制流,支持 O-LLVM、Tigress 等多种混淆器。

Stars: 215 | Forks: 35

[![d810-ng 测试](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/8413127706052612.svg)](https://github.com/w00tzenheimer/d810-ng/actions/workflows/python.yml) # 简介 ## 什么是 D-810 ng D-810 ng (Next Generation) 是一个 IDA Pro 插件,它可以通过在反编译时修改 IDA Pro 的微码来对代码进行反混淆。 它的设计初衷包含以下目标: * 尽可能减少对我们标准逆向工程工作流的影响 * 完全集成到 IDA Pro 中 * 易于扩展和配置 * 快速创建新的反混淆规则 * 高度可配置,从而无需为了在特定项目中使用规则而去修改源代码 * 性能影响应该在合理范围内 * 我们的目标是对逆向工程师保持透明 * 但如果最终生成的代码能简单得多,我们并不介意函数的反编译过程多花 1 秒钟。 ## D-810?这是什么意思? **D-810** 这个名字是对 "deobfuscation"(反混淆)的一个双关语,如下面的映射所示: ``` D E O B F U S C A T I O N ▲ ▲ ▲ ▲ ▲ │ │ │ │ │ D └───── 8 ─────┘ └─10──┘ ``` ## 使用 D-810 ng 使用 `Ctrl-Shift-D` 快捷键加载插件,你将看到以下配置 GUI !["Configuration Gui"](./resources/assets/gui_plugin_configuration.png "Configuration GUI") 点击某条规则以查看其更多详细信息: !["Rule View Gui"](./resources/assets/gui_plugin_configuration_v2.png "Rule View") ## 功能概述 ### 指令级优化 D-810 在 IDA Hex-Rays 微码的多个成熟度级别上运行。指令规则在反编译过程之前和期间简化被混淆的表达式。 | 类别 | 规则 | 描述 | |----------|-------|-------------| | **MBA (混合布尔算术)** | `Add`, `Sub`, `Mul`, `And`, `Or`, `Xor`, `Bnot`, `Neg`, `Mov` | 简化 MBA 混淆表达式(例如 `(a+b)-2*(a&b) => a^b`)。位于 `d810/mba/rules/` 中经 Z3 验证的 DSL 规则。 | | **Hacker's Delight** | `Add_HackersDelight*`, `And_HackersDelight*`, 等 | 来自《Hacker's Delight》的位操作等价替换。 | | **O-LLVM 模式** | `Add_OllvmRule_*`, `And_OllvmRule_*`, `Or_OllvmRule_1` | 特定于 Obfuscator-LLVM 的 MBA 模式。 | | **常量折叠** | `CstSimplificationRule1–22` | 算术和逻辑常量简化。 | | **谓词简化** | `Pred0Rule*`, `PredFFRule*`, `PredSetzRule*`, `PredSetnzRule*` | 不透明谓词移除,setz/setnz/lnot/smod 简化。 | | **因式分解规则** | `AndBnot_FactorRule_*`, `Xor_FactorRule_*`, 等 | 代数因式分解和重写。 | | **链式规则** | `AndChain`, `OrChain`, `XorChain`, `ArithmeticChain` | 简化相同操作的链式序列。 | | **Z3 规则** | `Z3ConstantOptimization`, `Z3setzRuleGeneric`, `Z3SmodRuleGeneric`, 等 | 当模板匹配失败时基于 SMT 的简化。 | | **窥孔优化** | `FoldReadonlyDataRule`, `LocalizedConstantPropagationRule` | 折叠从只读数据区的读取,常量传播。 | | **特定于 Hodur** | `Xor_Hodur_1`, `Bnot_Hodur_1`, `Or_Hodur_1`, `Or_Hodur_2` | 在 Hodur (PlugX) 恶意软件中出现的 MBA 模式。 | ### 控制流反平坦化 流优化器从平坦化的分发器中恢复自然的控制流。规则的顺序很重要;反平坦化器按顺序执行。 | 反平坦化器 | 目标 | 描述 | |-------------|--------|-------------| | **Unflattener** | O-LLVM | 移除 O-LLVM 风格的控制流平坦化:带有状态变量的 switch/if-chain 分发器。 | | **UnflattenerSwitchCase** | Tigress | 带有 switch-case 分发器 (`m_jtbl`) 的 Tigress。 | | **UnflattenerTigressIndirect** | Tigress | 带有间接跳转 (`m_ijmp`) 的 Tigress,需要 `goto_table_info` 配置。 | | **HodurUnflattener** | Hodur (PlugX) | 嵌套的 `while(1)` 状态机,带有 `jnz state, #CONST`;无 switch 分发器。 | | **BadWhileLoop** | Approov | Approov 风格的 `while(v8 != C)`,其状态常量在 0xF6000–0xF6FFF 范围内。 | | **UnflattenerFakeJump** | 通用 | 移除根据前驱块判断始终会/不会执行的条件跳转。 | | **SingleIterationLoopUnflattener** | 残留 | 清理单次迭代循环:`INIT == CHECK` 且 `UPDATE != CHECK`。 | | **UnflattenControlFlowRule** (实验性) | 通用 | 基于路径模拟的替代性 CFG 反平坦化器。 | ### 流优化 (非反平坦化) | 规则 | 描述 | |------|-------------| | **BlockMerger** | 在安全时合并顺序执行的代码块。 | | **JumpFixer** | 解析不透明/常量条件的跳转 (``JnzRule*``, ``JbRule1``, ``JaeRule1``, ``CompareConstantRule*``, ``JmpRuleZ3Const``)。 | | **GlobalConstantInliner** | 内联作为立即数使用的全局常量。 | | **IndirectCallResolver** | 通过函数指针表分析解析 `m_icall`。 | | **IndirectBranchResolver** | 通过跳转表分析解析间接分支。 | | **FixPredecessorOfConditionalJumpBlock** | 当跳转方向已知时修复前驱边。 | ### 支持的混淆器 / 模式 | 混淆器 | 配置 | 反平坦化器 | 备注 | |------------|--------|----------------|-------| | O-LLVM (obfuscator-llvm) | `default_unflattening_ollvm.json` | `Unflattener` | FLA + BCF + MBA。 | | Tigress | `default_unflattening_approov.json` | `UnflattenerSwitchCase`, `BadWhileLoop` | switch-case 和 Approov 样本模式。 | | Approov | `default_unflattening_approov.json` | `UnflattenerSwitchCase`, `BadWhileLoop` | While 循环状态常量位于魔术数字范围内。 | | Hodur (PlugX) | `hodur_deobfuscation.json`, `example_hodur.json` | `HodurUnflattener`, `Unflattener` | Hodur MBA + Hodur while 循环反平坦化。 | | Tigress indirect | `example_libobfuscated.json` | `UnflattenerTigressIndirect` | 需要 `goto_table_info` 映射。 | ### DSL 与规则验证 添加新的 MBA 规则非常简单:只需以纯符号形式定义模式和替换规则。无需手动证明,在定义时也不与 IDA 耦合。规则是与后端无关的;相同的 DSL 树会被转换为用于证明的 Z3 和用于匹配的 IDA AstNode。抽象保持得很干净:`d810.mba.dsl` 和 `d810.mba.verifier` 在规则定义层级没有任何 IDA 或 Z3 的导入。 **添加规则:** 继承 `VerifiableRule` 子类,设置 `PATTERN` 和 `REPLACEMENT`。注册和验证是自动进行的。 ``` from d810.mba.dsl import Var from d810.mba.rules import VerifiableRule x, y = Var("x_0"), Var("x_1") class Xor_HackersDelightRule_1(VerifiableRule): PATTERN = (x | y) - (x & y) REPLACEMENT = x ^ y DESCRIPTION = "Simplify (x | y) - (x & y) to x ^ y" ``` **构造保证正确性:** `verify_rule()` 通过 Z3 后端证明 `PATTERN` 和 `REPLACEMENT` 是等价的。如果验证失败,Z3 会返回一个反例。测试会对所有已注册的规则进行参数化,因此新规则会被自动验证。 **可扩展的约束:** 约束是声明式的且与后端无关。`VerificationEngine` 协议支持可插拔的后端(目前支持 Z3 和 egglog)。约束形式包括: * 声明式 `ConstraintExpr`(例如 `bnot_x == ~x`,`c_minus_2 == Const("-2", -2)`) * 运行时谓词(`when.equal_mops`,`when.is_bnot`)用于 IDA 特定的检查;可选择附加额外的后端进行验证。 * 当规则需要特定于求解器的逻辑时,通过 `get_constraints()` 进行每个后端的重写。 标记为 `SKIP_VERIFICATION = True` 的规则(例如微码类型检查或非常慢的 Z3 情况)会被豁免,但必须有文档说明。 ### 规则成熟度系统 D-810 的规则会在特定的 IDA 微码成熟度级别触发。每条规则都会声明其目标的成熟度;优化器只会在声明的级别调用规则。 #### 成熟度级别 | 常量 | 值 | 描述 | |----------|-------|-------------| | `MMAT_PREOPTIMIZED` | 2 | IDA 优化器之前的原始微码 | | `MMAT_LOCOPT` | 3 | 局部优化之后 | | `MMAT_CALLS` | 4 | 调用分析之后 | | `MMAT_GLBOPT1` | 5 | 全局优化第一阶段之后 | #### 默认行为 未声明成熟度的规则将继承优化器的默认设置:`MMAT_LOCOPT`、`MMAT_CALLS` 和 `MMAT_GLBOPT1`。默认情况下 **不** 包含 `MMAT_PREOPTIMIZED` —— 在成熟度 2 时对复杂函数触发规则可能会导致表达式急剧膨胀并导致 IDA 卡死。 #### 按类别例外 - **MBA 规则**(XOR, OR, AND, HackersDelight, O-LLVM 等)显式声明了 `MMAT_PREOPTIMIZED`,因为它们需要在 IDA 优化器将这些算术模式转换掉之前进行匹配。 - **CstSimplification 规则** 则有意忽略了 `MMAT_PREOPTIMIZED`,以防止表达式膨胀 —— 例如,在成熟度 2 时应用德摩根定律展开可能会产生级联重写,从而使得反编译停滞。 #### 通过项目配置进行按规则覆盖 任何规则的成熟度都可以在你的项目 JSON 配置中被覆盖: ``` { "name": "CstSimplificationRule17", "is_activated": true, "config": { "maturities": ["MMAT_PREOPTIMIZED", "MMAT_LOCOPT", "MMAT_CALLS", "MMAT_GLBOPT1"] } } ``` 优先级顺序为:**项目配置 JSON** > **类级别的 `maturities`** > **优化器默认继承**。 #### 为新规则添加成熟度 当继承 `VerifiableRule` 子类时,如果规则需要在 `MMAT_PREOPTIMIZED` 阶段触发,请添加一个类级别的 `maturities` 属性: ``` class MyNewRule(VerifiableRule): maturities = [2, 3, 4, 5] # Include MMAT_PREOPTIMIZED (2) PATTERN = ... REPLACEMENT = ... ``` 完全省略 `maturities` 以继承默认值(`MMAT_LOCOPT`、`MMAT_CALLS`、`MMAT_GLBOPT1`),这对大多数规则来说是安全的。 ## 安装 **仅支持附带 Python 3.10 及更高版本的 IDA v9 或更高版本**(因为我们需要微码的 Python API) 将此仓库的内容复制到 `.idapro/plugins` 或 `%appdata%\Hex-Rays\IDA pro\plugins`。 要激活 [Cython](https://cython.org) 加速,请为你的平台安装预编译的 wheels,然后运行将 Z3 与 IDA 隔离的辅助脚本: ``` pip3 install d810-ng[speedups] python -m d810.speedups.install ``` 加速功能由 [Mahmoud Abdelkader](https://mahmoudimus.com) 慷慨提供,他撰写了关于 Cython 如何["为逆向工程的重载工具超频"](https://mahmoudimus.com/blog/2025/08/ida-pro-and-cython-super-charging-the-work-horse-of-reverse-engineering/) 的文章,指出它在保持 Python 生产力的同时提供了 C++ 级别的性能。 ### 可选加速依赖 `d810-ng[speedups]` 会安装 Cython 加速,但不会安装 Z3。IDA 附带的 DLL 版本较旧,因此请将匹配的 `libz3.dll` 安装到一个隔离的用户目录中,而不是 `site-packages` 中: ``` python -m d810.speedups.install ``` 此命令会将 `z3-solver>=4.13,<4.15.5` 安装到 `~/.d810-speedups/`(可通过 `D810_SPEEDUPS_DIR` 覆盖),并且 d810 会在导入 Z3 之前将该目录前置到 `sys.path` 中,从而防止 IDA DLL 冲突。 ### 从源码安装 要将 D-810 ng 作为可编辑的包安装(适用于开发或与仓库保持同步): ``` pip install -e . ``` #### 使用 Cython 加速构建 d810 包含用于性能关键路径的可选 Cython 扩展。每个 Cython 模块都有纯 Python备方案,因此加速完全是可选的。 #### 前置条件 ``` pip install "Cython>=3.0.0" ``` #### 本地构建 **不带加速(纯 Python,所有平台):** ``` pip install -e . ``` 这将以开发模式安装该包,以便对源代码的更改能立即反映出来,并且它可以在所有平台上运行,不需要编译器或 IDA SDK。所有 Cython 模块都有纯 Python 后备方案。 **macOS / Linux:** ``` # 如果不存在,SDK 从 GitHub 自动下载 D810_BUILD_SPEEDUPS=1 pip install -e ".[speedups]" --no-build-isolation ``` 要指定本地的 IDA SDK 路径: ``` IDA_SDK=/path/to/ida-sdk D810_BUILD_SPEEDUPS=1 pip install -e ".[speedups]" --no-build-isolation ``` **Windows (PowerShell):** ``` $env:D810_BUILD_SPEEDUPS=1; $env:IDA_SDK="C:\IDA\9\sdk"; python -m pip install -e ".[speedups]" --no-build-isolation ``` **仅原地构建扩展(不安装):** ``` D810_BUILD_SPEEDUPS=1 python setup.py build_ext --inplace ``` ### 在 Docker 中(推荐) 在 IDA 容器内构建可确保 SDK 头文件和符号可用: ``` apt-get update && apt-get install -y g++ pip install setuptools wheel "Cython>=3.0.0" D810_BUILD_SPEEDUPS=1 pip install --no-build-isolation -e ".[dev]" ``` ### 环境变量 | 变量 | 用途 | 默认值 | |---|---|---| | `D810_BUILD_SPEEDUPS` | 设置为 `1` 以编译 `.pyx` 文件 | `0` (禁用) | | `IDA_SDK` | IDA SDK 目录的路径 | 自动下载到 `.ida-sdk/` | | `DEBUG` | 设置为 `1` 以进行带有性能分析/跟踪的调试构建 | `0` | | `D810_NO_CYTHON` | 设置为 `1` 以在运行时禁用 Cython | 未设置 (启用) | ## 如何使用 D810 1. 选择或创建你的项目配置。如果你不确定这里该怎么做,保持使用 *default_instruction_only.json* 即可。 2. 点击 `Start` 按钮以启用反混淆。 3. 反编译一个被混淆的函数,代码应该会被简化(希望如此)。 当你想禁用反混淆时,只需点击 `Stop` 按钮或使用上下文菜单: !["Disassembly context menu"](./resources/assets/disasmview_context_menu.png "Disassembly context menu") !["Pseudocode context menu"](./resources/assets/pseudocode_context_menu.png "Pseudocode context menu") ## 添加新的混淆示例 在 `samples/src` 目录下,有各种使用 `samples/Makefile` 编译为共享库的 `C` 程序,编译时未进行优化 (`-O0`)。在 Windows 上,该共享库是 `.dll`;在 macOS 上是 `.dylib`;在 Linux 上是 `.so`。其中包含一个编译好的 DLL 示例 `libobfuscated.dll`,可用作观察插件实际运行效果的测试基础。请提交包含更多混淆 `C` 示例的 pull request,以建立一个用于进一步研究的混淆样本代码仓库。 ### 测试运行器 D-810 ng 附带了一个内置的测试运行器,可以从 tests 文件夹(主要在 `tests/system` 下)加载 IDA 运行时测试。这个 GUI 是一个简单的测试运行器,允许开发者 *在* IDA Pro *内部* 运行测试,访问 hexrays 反编译器 API 并利用 `samples/bins` 下的特定样本来测试转换。 该测试运行器非常直观: !["Test Runner Example"](./resources/assets/test_runner_example-01.png "Test Runner Example") 测试重新加载功能无需重启 `IDA Pro` 即可生效,你可以通过测试上下文菜单执行测试的不同部分: !["Test Runner Context Menu"](./resources/assets/test_runner_example-ctx-menu.png "Test Runner Context Menu") ### 如何构建 样本二进制文件通过 `samples/Makefile` 构建。你可以交叉编译针对不同的操作系统和架构。 * 输出名称: * 默认 (`BINARY_NAME` 未更改): `bins/__.` * 显式 `BINARY_NAME` (CLI/环境变量): `bins/.` * `` 默认为 `libobfuscated` * `` 是运行 `make` 的机器 (`darwin`,`linux`,`windows`) * `` 为规范化后的架构 (`x86_64` 或 `arm64`) * `` 来源于目标操作系统:`dll` (windows),`dylib` (darwin),`so` (linux) 你可以传递给 `make` 的标志: * `TARGET_OS` (默认: `windows`) * 取值为以下之一:`windows`,`darwin`,`linux`,`native` * `native` 会被规范化为检测到的主机 OS (`darwin`,`linux`,或 `windows`) * `BUILD_ARCH` (默认: `x86_64`) * 示例:`x86_64`,`x86`,`arm64` * `x86` 会被规范化为 `x86_64` (不支持 32 位构建) * 也接受显式的编译器标志 (例如,`-m64`,`-arch arm64`) * `BINARY_NAME` (默认: `libobfuscated`) 注意事项: * 构建默认未优化:`-O0 -g`,并且禁用了内联/向量化。 * 在非 Linux 主机上,`TARGET_OS=linux` 会自动使用 Docker 来生成真正的 ELF 输出。 * Linux Docker 构建会根据 `BUILD_ARCH` 选择平台: * `x86_64` -> `linux/amd64` * `arm64` -> `linux/arm64` * 在非 Windows 主机上,当未提供显式的 Windows sysroot/工具链时,`TARGET_OS=windows` 将使用 Docker。 示例(从仓库根目录运行): ``` # 构建默认值:Windows DLL (名称默认包含 host+arch) cd samples && make # → bins/libobfuscated__x86_64.dll # 构建用于 x86_64 ELF 的 Linux .so make TARGET_OS=linux BUILD_ARCH=x86_64 # → bins/libobfuscated__x86_64.so # 构建用于 arm64 ELF 的 Linux .so make TARGET_OS=linux BUILD_ARCH=arm64 # → bins/libobfuscated__arm64.so # 构建用于 x86_64 的 macOS .dylib make TARGET_OS=darwin BUILD_ARCH=x86_64 # → bins/libobfuscated__x86_64.dylib # 为原生 host OS 构建 (x86 映射至 x86_64) make TARGET_OS=native BUILD_ARCH=x86 # → bins/libobfuscated__x86_64. # 自定义二进制文件名称 make BINARY_NAME=libobfuscatedv2 # → bins/libobfuscatedv2.dll (或基于 TARGET_OS 的 .so/.dylib) # 清理构建产物 make clean ``` ### 测试常量简化 **之前**: !["Before"](./resources/assets/test_cst_simplification_before.png "Before Plugin") **之后**: !["After"](./resources/assets/test_cst_simplification_after.png "After Plugin") ### 测试 XOR 简化 **之前**: !["Before"](./resources/assets/test_xor_before.png "Before Plugin") **之后**: !["After"](./resources/assets/test_xor_after.png "After Plugin") ## 运行测试 D-810 ng 拥有在 IDA Pro 无头模式 (`idalib`) 下运行的全面测试套件。测试在捆绑了 IDA Pro 及所需 Python 环境的 Docker 容器中执行。 **前置条件:** * Docker 和 Docker Compose * 对 `ghcr.io/w00tzenheimer/idapro-linux` 容器镜像的访问权限 ### 快速开始 ``` # 运行所有 IDA 系统测试 (默认排除 profiling 测试) docker compose run --rm --entrypoint bash idapro-tests-9.2 -c \ "pip install -e .[dev] -q && pytest tests/system/ -v --tb=short" ``` ### 测试分类 | 标记 | 描述 | 默认 | |--------|-------------|---------| | `pure_python` | 无需 IDA Pro 即可运行的测试(快速,无外部依赖) | 包含 | | `requires_ida` | 需要运行 IDA Pro 的测试 | 包含 | | `slow` | 慢速测试 (>10s) —— 通常是 Z3 验证或复杂的反混淆 | 包含 | | `profile` | 性能分析测试(重复反编译函数) | **排除** | ### 运行特定的测试套件 ``` # 仅运行单元测试 (无需 IDA) pytest tests/unit/ -v # 运行 IDA 系统测试 docker compose run --rm --entrypoint bash idapro-tests-9.2 -c \ "pip install -e .[dev] -q && pytest tests/system/ -v --tb=short" # 运行特定测试类 docker compose run --rm --entrypoint bash idapro-tests-9.2 -c \ "pip install -e .[dev] -q && pytest tests/system/e2e/test_libdeobfuscated_dsl.py::TestOLLVMPatterns -v --tb=short" # 运行 profiling 测试 (默认排除,仅限选择加入) docker compose run --rm --entrypoint bash idapro-tests-9.2 -c \ "pip install -e .[dev] -q && pytest tests/system/e2e/test_profile_libobfuscated.py -m profile -v -s" # 覆盖默认 marker 过滤器以运行所有内容 docker compose run --rm --entrypoint bash idapro-tests-9.2 -c \ "pip install -e .[dev] -q && pytest tests/system/ -o 'addopts=' -v" ``` 请参阅 `tests/TEST_CLASSIFICATION.md` 了解严格的测试放置规则和通道定义。 ### Docker 服务 | 服务 | 镜像 | Python | 描述 | |---------|-------|--------|-------------| | `idapro-tests` | `idapro-linux:idapro-tests` | 3.10 | 旧版测试容器 | | `idapro-tests-9.2` | `idapro-linux:idapro-tests-9.2-py312` | 3.12 | 主要测试容器 (推荐) | ## 警告 此插件仍处于早期开发阶段,因此 ~~可能~~ 肯定会出现问题。 * 不正确地修改 IDA 微码可能会导致 IDA 崩溃。我们正尽可能多地检测以避免崩溃,但由于它仍有可能发生,**请经常保存你的 IDA 数据库** * 插件已在 Windows、Mac 和 Linux 上进行了测试。 ## 文档 正在编写中 目前,你可以阅读我们的[博客文章](https://eshard.com/posts/)以获取一些信息。 ## 许可证 本库基于 LGPL V3 许可证授权。详情请参见 [LICENSE](LICENSE) 文件。 ## 作者 请参见 [AUTHORS](AUTHORS.md) 获取项目贡献者列表。 ## 致谢 感谢 Rolf Rolles 通过他的 [HexRaysDeob 插件](https://github.com/RolfRolles/HexRaysDeob) 所做的巨大工作,以及他在[博客文章](https://www.hex-rays.com/blog/hex-rays-microcode-api-vs-obfuscating-compiler/)中描述的关于 Hex-Rays 微码内部原理的所有信息。我们在 D-810 中仍在使用他插件的部分代码。 感谢 Dennis Elser 的 [genmc 插件](https://github.com/patois/genmc),该插件对调试 D-810 的错误非常有帮助。 特别感谢 [Boris Batteux](https://gitlab.com/borisbatteux) 提供了这个出色的插件!
标签:C++, DAST, Deobfuscation, Hex-Rays, IDA Pro, MBA化简, Python, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 代码优化, 代码分析, 凭证管理, 反混淆, 安全规则引擎, 微码分析, 恶意软件分析, 插件, 数据擦除, 无后门, 混淆对抗, 请求拦截, 逆向工具, 逆向工程, 静态分析