w00tzenheimer/d810-ng
GitHub: w00tzenheimer/d810-ng
D810-ng 是一个 IDA Pro 反混淆插件,通过在反编译时修改微码来简化被混淆的表达式并还原控制流,支持 O-LLVM、Tigress 等多种混淆器。
Stars: 215 | Forks: 35
[](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

点击某条规则以查看其更多详细信息:

## 功能概述
### 指令级优化
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` 按钮或使用上下文菜单:


## 添加新的混淆示例
在 `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` 下的特定样本来测试转换。
该测试运行器非常直观:

测试重新加载功能无需重启 `IDA Pro` 即可生效,你可以通过测试上下文菜单执行测试的不同部分:

### 如何构建
样本二进制文件通过 `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
```
### 测试常量简化
**之前**: 
**之后**: 
### 测试 XOR 简化
**之前**: 
**之后**: 
## 运行测试
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, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 代码优化, 代码分析, 凭证管理, 反混淆, 安全规则引擎, 微码分析, 恶意软件分析, 插件, 数据擦除, 无后门, 混淆对抗, 请求拦截, 逆向工具, 逆向工程, 静态分析