seifreed/r2morph

GitHub: seifreed/r2morph

基于 radare2 的二进制变形引擎,支持多种变异操作并内置验证与审计报告功能。

Stars: 45 | Forks: 5

r2morph

r2morph

具备结构化验证与报告功能的变形变异引擎

PyPI Version Python Versions License CI Status Coverage

GitHub Stars GitHub Issues Buy Me a Coffee

## 概述 **r2morph** 是一个优先考虑变异的引擎,用于应用变形二进制转换,并具备显式验证、回滚和机器可读报告功能。它利用 **radare2** 和 **r2pipe** 来分析二进制文件,应用跟踪的变异,并在导出前验证结果。 ### 主要特性 | 特性 | 描述 | |---------|-------------| | **跟踪变异** | 每个应用的变异都可以记录地址、字节和反汇编代码 | | **验证管道** | 引擎内部的结构化验证,可选的运行时验证,失败时回滚 | | **机器可读报告** | 导出 JSON 报告,用于 CI、回归检查和可审计性 | | **CLI + Python API** | 作为 `mutate`、`validate`、`report` 运行,或作为库嵌入 | | **radare2 支持的分析** | 重用 radare2/r2pipe 进行反汇编和二进制元数据获取 | | **实验性模块** | 反虚拟化、增强分析、插桩和反分析辅助工具仍作为次要/实验性功能 | ## 安装说明 ### 前置条件 - Python 3.10+ - radare2 installed #### 安装 radare2 ``` git clone https://github.com/radareorg/radare2 cd radare2 sys/install.sh ``` ### 安装 r2morph ``` # Basic installation pip install r2morph # Enhanced analysis capabilities pip install "r2morph[enhanced]" # All optional features pip install "r2morph[all]" ``` ### 开发环境安装 ``` git clone https://github.com/seifreed/r2morph.git cd r2morph pip install -e . # Dev tooling pip install -e ".[dev]" ``` ## 产品重心 `r2morph` 的重心围绕单一产品: **加载二进制 -> 应用跟踪变异 -> 验证 -> 导出二进制 + 报告** 稳定的核心是变异 + 验证。高级逆向工程工作流虽可在仓库中使用,但属于次要功能,应视为实验性的。 请参阅 [docs/ROADMAP.md](docs/ROADMAP.md) 了解实施路线图和当前阶段状态。 ## 支持矩阵 ### 稳定核心 | 领域 | 支持 | 稳定性 | |------|-----------|-----------| | 格式 | ELF | 稳定 | | 架构 | x86_64 | 稳定 | | 变异 | `nop`, `substitute`, `register` | 稳定 | | 验证器 | `structural`, `runtime` | 稳定 / 支持 | | 输出 | JSON 报告 + 变异后的二进制 | 稳定 | ### 实验性 / 次要 | 领域 | 支持 | 稳定性 | |------|-----------|-----------| | 格式 | PE, Mach-O | 实验性 | | 变异 | `expand`, `block`, `opaque`, `dead-code`, `cff` | 实验性 | | 验证 | symbolic equivalence | 实验性 | | 分析 | devirtualization, Frida, anti-analysis, packer analysis | 实验性 | ## 快速开始 ``` # Stable mutate + validate flow r2morph input_binary output_binary # Explicit mutate command with report r2morph mutate input_binary -o output_binary --report mutation_report.json # Reproducible stable mutation run r2morph mutate input_binary -o output_binary --seed 1337 # Runtime validation of an original/mutated pair r2morph validate input_binary output_binary # Runtime validation with a reusable corpus r2morph validate input_binary output_binary --corpus dataset/runtime_corpus.json ``` ## 使用说明 ### 命令行界面 ``` # Stable default flow r2morph input_binary output_binary # Stable tracked mutation flow r2morph mutate input_binary -o output_binary -m nop -m substitute -m register # Reproducible mutation selection r2morph mutate input_binary -o output_binary --seed 1337 # Experimental symbolic precheck mode r2morph mutate input_binary -o output_binary --validation-mode symbolic # Allow a limited symbolic pass explicitly r2morph mutate input_binary -o output_binary --validation-mode symbolic \ --allow-limited-symbolic -m register # Degrade a limited symbolic pass to runtime validation instead of blocking r2morph mutate input_binary -o output_binary --validation-mode symbolic \ --limited-symbolic-policy degrade-runtime -m register # Export a machine-readable report r2morph mutate input_binary -o output_binary --report report.json # Fail the CLI run unless the final report reaches a minimum symbolic severity r2morph mutate input_binary -o output_binary --report report.json \ --min-severity bounded-only # Fail unless a specific pass reaches the required local severity r2morph mutate input_binary -o output_binary --report report.json \ --require-pass-severity InstructionSubstitution=bounded-only # Short mutation aliases also work in pass severity gating r2morph mutate input_binary -o output_binary --report report.json \ --require-pass-severity nop=not-requested # The generated report preserves gate requests and outcomes in `gate_evaluation` # Validate a mutated binary against the original r2morph validate input_binary output_binary # Validate with a JSON corpus of runtime cases r2morph validate input_binary output_binary --corpus dataset/runtime_corpus.json # Ignore trailing whitespace differences in stdout/stderr r2morph validate input_binary output_binary --corpus dataset/runtime_corpus.json --normalize-whitespace # Run mutate with runtime validation backed by a real corpus r2morph mutate input_binary -o output_binary \ --validation-mode runtime \ --runtime-corpus dataset/runtime_corpus.json # Display a saved report with symbolic coverage summaries and mismatch triage when available r2morph report report.json # Use the saved report as a CI gate r2morph report report.json --require-results --min-severity mismatch # Triage only runs where persisted CLI gates failed r2morph report report.json --only-failed-gates --summary-only # The summary includes compact gate failure causes for fast triage # Restrict persisted gate failures to one expected severity r2morph report report.json --only-failed-gates --only-expected-severity clean --summary-only # Restrict persisted gate failures to one pass r2morph report report.json --only-failed-gates --only-pass-failure NopInsertion --summary-only # Stable mutation aliases work for gate triage too r2morph report report.json --only-failed-gates --only-pass-failure nop --summary-only # Triage only symbolic observable mismatches r2morph report report.json --only-mismatches # Restrict the report to one pass, optionally combined with mismatch triage r2morph report report.json --only-pass InstructionSubstitution --only-mismatches # Stable mutation aliases also work in pass filtering r2morph report report.json --only-pass nop # Filter directly by symbolic status r2morph report report.json --only-status bounded-step-observable-mismatch # Show only reports where the effective validation mode was degraded r2morph report report.json --only-degraded # The report summary includes the degraded pass set and symbolic confidence for each cause # Show only the textual summary for terminal triage r2morph report report.json --summary-only # Export a filtered report JSON for CI or post-processing r2morph report report.json --only-pass InstructionSubstitution --output filtered-report.json # Fail in CI when a filtered view has no matching mutations r2morph report report.json --only-pass InstructionSubstitution --require-results # Fail in CI when a filtered gate view has no matching failures r2morph report report.json --only-failed-gates --only-expected-severity clean --require-results r2morph report report.json --only-failed-gates --only-pass-failure nop --require-results # The exported JSON includes `filtered_summary` for the active view r2morph report report.json --only-status bounded-step-passed --output filtered-report.json # `filtered_summary.symbolic_statuses` exposes the status distribution for the current view r2morph report report.json --only-pass InstructionSubstitution --output filtered-report.json # Gate-focused filtered views also preserve `gate_failures`, `gate_failure_priority`, # `gate_failure_severity_priority`, and normalized `report_filters` r2morph report report.json --only-failed-gates --only-pass-failure nop --output filtered-report.json ``` #### 报告过滤器快速参考 | 过滤器 | 用途 | 示例 | | --- | --- | --- | | `--only-pass ` | 将变异限制在当前视图中的单个 pass | `r2morph report report.json --only-pass nop` | | `--only-status ` | 将变异限制在单个符号状态 | `r2morph report report.json --only-status bounded-step-observable-mismatch` | | `--only-mismatches` | 仅显示符号可观察不匹配项 | `r2morph report report.json --only-mismatches` | | `--only-degraded` | 仅显示请求验证模式与实际验证模式不同的运行 | `r2morph report report.json --only-degraded --summary-only` | | `--only-failed-gates` | 仅显示持久化 CLI 门控失败的运行 | `r2morph report report.json --only-failed-gates --summary-only` | | `--only-expected-severity ` | 根据预期严重程度限制持久化门控失败 | `r2morph report report.json --only-failed-gates --only-expected-severity clean` | | `--only-pass-failure ` | 将持久化门控失败限制在单个 pass | `r2morph report report.json --only-failed-gates --only-pass-failure nop` | | `--summary-only` | 仅打印文本分类摘要 | `r2morph report report.json --summary-only` | | `--output ` | 导出过滤后的 JSON 视图用于 CI/后处理 | `r2morph report report.json --only-pass nop --output filtered.json` | | `--require-results` | 当过滤视图为空时以状态码 `1` 退出 | `r2morph report report.json --only-failed-gates --only-pass-failure nop --require-results` | | `--min-severity ` | 要求视图中至少有一个 pass 的严重程度达到或高于给定值 | `r2morph report report.json --require-results --min-severity mismatch` | 别名说明: - `--only-pass` 和 `--only-pass-failure` 接受稳定的别名:`nop`、`substitute`、`register`。 - 文本摘要会明确显示别名解析,例如 `nop -> NopInsertion`。 ### Python 库 ``` from r2morph import MorphEngine from r2morph.mutations import NopInsertionPass, InstructionSubstitutionPass with MorphEngine() as engine: engine.load_binary("input.exe").analyze() engine.add_mutation(NopInsertionPass()) engine.add_mutation(InstructionSubstitutionPass()) engine.add_mutation(RegisterSubstitutionPass()) result = engine.run(validation_mode="structural", report_path="mutation_report.json") engine.save("output.exe") print(f"Applied {result['total_mutations']} mutations") ``` ### 运行时语料库 `r2morph validate --corpus` 接受一个包含运行时测试用例的 JSON 数组。在 `dataset/runtime_corpus.json` 中提供了一个可复用的示例。 对于副作用,`dataset/runtime_corpus_files.json` 展示了与 `--compare-files` 配合使用的 `monitored_files` 形式。 ``` [ { "description": "default-exec", "args": [], "stdin": "", "expected_exitcode": 0 }, { "description": "help-output", "args": ["--help"], "stdin": "", "expected_exitcode": 0 } ] ``` 包含文件副作用的示例: ``` r2morph validate original mutated \ --corpus dataset/runtime_corpus_files.json \ --compare-files ``` 运行时验证还可以规范化尾随空白字符的差异: ``` r2morph validate original mutated \ --corpus dataset/runtime_corpus.json \ --normalize-whitespace ``` ### 实验性高级分析 ``` from r2morph import Binary from r2morph.detection import ObfuscationDetector from r2morph.analysis.symbolic import AngrBridge, PathExplorer from r2morph.instrumentation import FridaEngine from r2morph.devirtualization import VMHandlerAnalyzer, MBASolver with Binary("vmprotected.exe") as binary: binary.analyze() detector = ObfuscationDetector() result = detector.analyze_binary(binary) if result.vm_detected: angr_bridge = AngrBridge(binary) explorer = PathExplorer(angr_bridge) vm_result = explorer.explore_vm_handlers() frida_engine = FridaEngine() runtime_result = frida_engine.instrument_binary("vmprotected.exe") vm_analyzer = VMHandlerAnalyzer(binary) handlers = vm_analyzer.analyze_vm_architecture() mba_solver = MBASolver() simplified = mba_solver.simplify_handlers(handlers) ``` 此高级分析工作流仍处于实验阶段,且对于变异引擎而言是次要的。 详情请参阅 `docs/enhanced_analysis.md`。 CLI 访问入口位于次要命名空间下: ``` r2morph experimental analyze-enhanced sample.bin --detect-only ``` ## 实验性符号验证 `--validation-mode symbolic` 可作为实验模式用于稳定核心的有界预检。其范围被有意缩小: - 仅限 `ELF x86_64` - 仅限稳定 pass - 仅限小范围变异区域 - 结构化验证仍作为阻塞式后备方案 报告会指出是否支持符号覆盖、后端是否初始化、是否对变异区域运行了有界符号步骤,以及运行回退或未经验证的原因。 每个报告还会暴露 `pass_support..validator_capabilities`,以便消费者区分具有较强符号证据的 pass(如 `InstructionSubstitution`)与 `runtime` 仍是推荐发布门槛的 pass(如 `RegisterSubstitution`)。 对于 `InstructionSubstitution`,实验性报告还会标记变异区域是否来自已知的等价组,并在可能的情况下对比真实预 pass/后 pass 二进制文件中两段代码片段和有界状态下的一小部分可观察寄存器/标志效应。这仍是一个范围受限的提示,而非通用的语义证明。 ## 支持的转换 **稳定变异** - 指令替换 - NOP 插入 - 寄存器重分配 **实验性变异** - 基本块重排 - 指令扩展 - 不透明谓词 - 死代码注入 - 控制流平坦化 ## 示例 ### 基础二进制分析 ``` from r2morph import Binary with Binary("/path/to/binary") as binary: binary.analyze() functions = binary.get_functions() print(f"Found {len(functions)} functions") arch = binary.get_arch_info() print(f"Architecture: {arch['arch']} ({arch['bits']}-bit)") ``` ## 系统要求 - Python 3.10+ - radare2 - 完整依赖列表请参阅 `pyproject.toml` - 本地开发请参阅:`requirements-dev.txt` ## 许可证 本项目采用 MIT 许可证授权 - 详情请参阅 [LICENSE](LICENSE) 文件。 **需注明出处:** - 作者:**Marc Rivero** | [@seifreed](https://github.com/seifreed) - 仓库:[github.com/seifreed/r2morph](https://github.com/seifreed/r2morph)

为逆向工程社区倾情奉献

标签:CTF工具, DAST, DNS 反向解析, DNS 解析, Homebrew安装, Python, r2pipe, radare2, 二进制修补, 二进制变换, 二进制安全, 云资产清单, 代码变异, 代码混淆, 变形引擎, 对称加密, 恶意软件分析, 无后门, 汇编分析, 漏洞搜索, 自动化审计, 逆向工具, 逆向工程, 防病毒规避