binsnake/omill

GitHub: binsnake/omill

基于 remill 的 Windows x64 二进制提升与反混淆框架,将提升后的 IR 转换为可重编译的原生代码并恢复 ABI 信息。

Stars: 59 | Forks: 6

# omill 一个 LLVM pass 库,用于将 [remill](https://github.com/lifting-bits/remill)-提升的 IR 降低(lowering)为可重编译的原生代码。针对使用 Win64 ABI 的 Windows x64 (PE) 二进制文件。 ## 概述 omill 将 remill 的语义保持(semantics-preserving)提升 IR —— 其作用于显式的 `State` 结构体和内存 intrinsic —— 转换为适合重编译的干净原生 LLVM IR。该流水线逐步进行: 1. **Lower remill intrinsics**(降低 remill intrinsics) —— 将(标志位、内存、原子操作、hyper call)转换为原生 LLVM 操作 2. **优化 State 访问** —— 死存储/标志位消除,将 State 字段提升为 SSA,消除内存指针 3. **恢复控制流** —— 将 `__remill_function_call`、`__remill_function_return`、`__remill_jump` 降低为原生分支/调用,然后恢复 CFG 4. **解析调度目标** —— 折叠程序计数器,解析 IAT 调用,通过常量折叠迭代解析间接分支 5. **恢复 ABI** —— 调用约定分析,栈帧恢复,函数签名恢复,State 结构体消除 6. **反混淆**(可选) —— 常量内存折叠,栈数据 outlining,导入哈希解析,延迟导入解析,死路径消除 ## 限制 - **平台支持:** 目前仅支持使用 **Win64 ABI** 的 **Windows x64 (PE)** 文件。 - **项目范围:** `omill` 专用于对控制流相对简单但逻辑复杂的函数进行反混淆。 - **不推荐用于:** - 完整的二进制提升或重编译(侧重于特定函数及其可达目标)。 - 虚拟化代码(基于 VM 的混淆,如 VMProtect 或 Themida)。 - 加壳或压缩文件(二进制文件必须已脱壳或处于代码可静态访问的状态)。 - **状态:** 反混淆能力每周都在改进,并正在扩展对更复杂混淆方法的支持。 ## 环境要求 - **LLVM 21**(已在 `C:/Program Files/LLVM21` 的预构建安装版本上测试) - **CMake** >= 3.21 - **Ninja**(推荐的生成器) - **C++17** 编译器 (Clang 21) ## 构建 ### 基础构建(不含 remill) ``` cmake -B build -G Ninja \ -DLLVM_DIR="C:/Program Files/LLVM21/lib/cmake/llvm" \ -DOMILL_ENABLE_TOOLS=ON \ -DOMILL_ENABLE_TESTING=ON cmake --build build ``` ### 包含 remill(启用端到端测试) 首先,构建 remill 的依赖项: ``` cmake -G Ninja \ -S third_party/remill/dependencies \ -B third_party/remill/dependencies/build \ -DUSE_EXTERNAL_LLVM=ON cmake --build third_party/remill/dependencies/build ``` 然后构建启用了 remill 的 omill: ``` cmake -B build-remill -G Ninja \ -DLLVM_DIR="C:/Program Files/LLVM21/lib/cmake/llvm" \ -DOMILL_ENABLE_TOOLS=ON \ -DOMILL_ENABLE_TESTING=ON \ -DOMILL_ENABLE_REMILL=ON \ -DCMAKE_PREFIX_PATH="$(pwd)/third_party/remill/dependencies/install" cmake --build build-remill ``` ### CMake 选项 | 选项 | 默认值 | 描述 | |-|-|-| | `OMILL_ENABLE_TOOLS` | `ON` | 构建 `omill-opt` 和 `ollvm-obf` CLI 工具 | | `OMILL_ENABLE_TESTING` | `ON` | 构建单元测试和端到端测试 | | `OMILL_ENABLE_REMILL` | `OFF` | 搭建 remill 以进行端到端测试 | | `OMILL_ENABLE_Z3` | auto | 基于 Z3 的调度求解器(自动下载 Z3 4.13.4) | | `OMILL_ENABLE_SIMPLIFIER` | `OFF` | 基于 EqSat 的 MBA 简化 | ## 用法 ### 作为库使用 ``` #include "omill/Omill.h" llvm::ModulePassManager MPM; omill::PipelineOptions opts; opts.lower_intrinsics = true; opts.optimize_state = true; opts.lower_control_flow = true; opts.recover_abi = true; opts.resolve_indirect_targets = true; omill::buildPipeline(MPM, opts); llvm::ModuleAnalysisManager MAM; llvm::FunctionAnalysisManager FAM; // ... register standard + omill analyses ... omill::registerAnalyses(FAM); omill::registerModuleAnalyses(MAM); MPM.run(*Module, MAM); ``` ### omill-opt CLI `omill-opt` 是一个用于在 bitcode 文件上运行流水线的独立工具: ``` omill-opt input.bc -o output.bc omill-opt input.bc -o output.bc --deobfuscate --resolve-targets --recover-abi ``` ### ollvm-obf CLI `ollvm-obf` 将 OLLVM 风格的混淆应用于 LLVM bitcode,适用于为反混淆流水线生成测试输入: ``` ollvm-obf input.bc -o output.bc --flatten --substitute --string-encrypt --const-unfold --vectorize --seed=2976579765 ``` 支持的变换:控制流平坦化、指令替换、字符串加密、常量展开和 i32 向量化 (SSE2)。 向量化支持栈数据变异(`--vectorize-data`,默认开启)和可选的按位加/减法 lowering(`--vectorize-bitwise`)。 默认情况下,所有变换均通过稳定的基础种子(`--seed`)保持确定性。 ### omill-lift CLI(需要 remill) `omill-lift` 将 Windows x64 PE 文件中特定虚拟地址 (VA) 开始的函数提升为 LLVM IR,然后运行 omill 流水线: ``` omill-lift input.exe --va 0x140001000 -o lifted.ll --deobfuscate --resolve-targets ``` 可用选项: - `--va `:提升的起始地址(必需)。 - `--deobfuscate`:启用反混淆 pass(MBA 简化、死路径消除等)。 - `--resolve-targets`:通过 Z3/SCEV 启用迭代式间接分支解析。 - `--refine-signatures`:在 ABI 恢复后启用参数类型细化。 - `--no-abi`:跳过 ABI 恢复(保留 `State` 结构体和 remill intrinsics)。 ## 架构 ### Pass 流水线 该流水线分为多个阶段,逐步降低 remill IR: | 阶段 | Passes | 目的 | |-|-|-| | 0 | StripRemillIntrinsicBodies, AlwaysInlinerPass | 准备提升的 IR 以供处理 | | 1 | LowerRemillIntrinsics (Phase1: flags, barriers, memory, atomics, hyper calls) | 用原生 LLVM 操作替换 remill intrinsics | | 2 | OptimizeState (DeadFlags, DeadStores, Promote), MemoryPointerElimination | 消除不必要的 State 访问 | | 3 | LowerRemillIntrinsics (Phase3: error/missing, return, call, jump), CFGRecovery | 恢复原生控制流 | | 3.5 | FoldProgramCounter, ResolveIATCalls, LowerRemillIntrinsics (ResolvedDispatch) | 解析静态调度目标 | | 3.6 | IterativeTargetResolution (ResolveAndLowerControlFlow + Z3DispatchSolver loop) | 通过优化不动点迭代解析间接目标 | | 3.7 | InterProceduralConstProp | 跨调用边界传播常量 | | 4 | CallingConventionAnalysis, RecoverStackFrame, RecoverStackFrameTypes, RecoverFunctionSignatures, RefineFunctionSignatures, RewriteLiftedCallsToNative, EliminateStateStruct | 恢复 ABI 并移除 State | | 5 | SimplifyVectorReassembly, ConstantMemoryFolding, RecoverGlobalTypes, OutlineConstantStackData, HashImportAnnotation, ResolveLazyImports, EliminateDeadPaths | 反混淆 | | 6 | LowerRemillIntrinsics (Undefined) | 最终清理 | ### 整合 Passes 流水线使用 4 个可通过位掩配置的 pass,每个 pass 整合了多个相关的变换,从而减少了 IR 遍历开销: - **LowerRemillIntrinsicsPass** —— 11 个 intrinsic 类别(flags、barriers、memory、atomics、hyper calls、error/missing、return、call、jump、undefined、resolved dispatch)通过 `LowerCategories` 位掩选择 - **OptimizeStatePass** —— 5 个状态优化阶段(dead flags、dead stores、redundant bytes、promote-to-SSA、roundtrip elimination)通过 `OptimizePhases` 位掩选择 - **ResolveAndLowerControlFlowPass** —— 3 个解析阶段(constant-PC dispatch、jump table recovery、symbolic/SCEV solving)通过 `ResolvePhases` 位掩选择 - **SimplifyVectorReassemblyPass** —— 4 个 XMM 模式匹配器(constant vector folding、partial write collapse、byte reassembly coalescing、flag computation simplification) ### 分析 - **RemillIntrinsicAnalysis** —— 识别并分类 remill intrinsic 调用 - **StateFieldAccessAnalysis** —— 跟踪哪些 State 结构体字段被读/写 - **CallGraphAnalysis** —— 构建带有 SCC 计算的过程间调用图 - **CallingConventionAnalysis** —— 根据寄存器使用情况确定 Win64 调用约定(XMM0-3 参数检测,被调用者保存的 GPR 过滤) - **BinaryMemoryMap** —— 提供来自原始二进制文件的常量内存内容以用于折叠 - **LiftedFunctionMap** —— 将程序计数器地址映射到提升的 `sub_` 函数 - **ExceptionInfo** —— 恢复结构化异常处理元数据 ### 项目结构 ``` omill/ ├── include/omill/ # Public headers │ ├── Analysis/ # Analysis passes │ ├── Passes/ # Transformation passes │ └── Omill.h # Pipeline builder API ├── lib/ # Implementation │ ├── Analysis/ │ ├── Passes/ │ └── Pipeline.cpp # Pipeline construction ├── tools/ │ ├── omill-opt/ # Standalone optimizer tool │ ├── omill-lift/ # Lifter tool (requires remill) │ └── ollvm-obf/ # OLLVM-style obfuscation tool ├── tests/ │ ├── unit/ # Unit tests (266 tests) │ └── e2e/ # End-to-end tests (require remill) ├── test_obf/ # Obfuscation round-trip test suite ├── third_party/ │ └── remill/ # Remill submodule (binsnake fork) └── cmake/ └── options.cmake # Build options ``` ## 测试 ``` # 运行所有测试 ctest --test-dir build # 仅运行单元测试 ctest --test-dir build -R unit # 运行 e2e 测试(需要 remill 构建) ctest --test-dir build-remill -R e2e ``` ## 致谢 - [Dna](https://github.com/Colton1skees/Dna) —— 由 Colton1skees 开发,提供了基于 remill 重编译的灵感 - [remill](https://github.com/lifting-bits/remill) —— 由 Trail of Bits 开发的二进制提升器 - [LLVM](https://llvm.org/) —— 编译器基础设施 - [Zydis](https://github.com/zyantific/zydis) —— x86/x86-64 反汇编器 - 过程间分析、类型恢复和字符串恢复 pass 与 [Claude Code](https://claude.com/claude-code) (Anthropic) 共同编写 ## 许可证 详情请参阅 [LICENSE](LICENSE)。
标签:Bash脚本, Binary Lifting, CFG 还原, Deobfuscation, DNS 反向解析, LLVM Pass, McSema2, PE 文件, Remill, Static Rewriting, Win64 ABI, Windows x64, 二进制分析, 二进制提升, 云安全监控, 云安全运维, 云资产清单, 代码优化, 代码复原, 函数签名恢复, 反混淆, 恶意代码分析, 指令集翻译, 控制流复原, 编译器基础设施, 语义保持, 逆向工程, 配置文件, 静态分析