ShaneBreazeale/rsleigh

GitHub: ShaneBreazeale/rsleigh

这是一个纯Rust编写的二进制反汇编与反编译工具,它利用Ghidra的SLEIGH规范将机器码提升至P-code IR,进而还原出带类型和语义信息的C语言伪代码。

Stars: 1 | Forks: 0

# rSleigh 将 Ghidra 的 SLEIGH 架构规范编译为原生 Rust 解码器,用于反汇编和反编译二进制文件为类 C 伪代码。无需 JVM,无需 C++,只需 `cargo build`。 ## 功能简介 rsleigh 解析 `.slaspec` 文件(即 Ghidra 附带的同一架构定义),生成将机器指令解码为 [P-code IR](https://ghidra.re/courses/languages/html/pcoderef.html) 的 Rust 代码,然后将该 IR 反编译为可读的伪代码,其中包含函数签名、带类型的局部变量、字符串字面量、导入名称、DWARF 变量恢复以及控制流重构。 它是 [Spectra](https://github.com/ShaneBreazeale/spectra) 的反汇编和反编译后端,完全取代了 Ghidra 的 JVM 守护进程。 ## CLI ``` cargo install --path rsleigh-cli ``` ``` rsleigh ./binary # list functions rsleigh ./binary main # decompile a function rsleigh ./binary main vuln init # decompile multiple functions rsleigh ./binary --all # decompile everything (two-pass type propagation) rsleigh ./binary main --json # JSON output for tool integration rsleigh ./binary --disasm main # disassembly with P-code rsleigh ./binary --sigs extra.json # load additional signatures from JSON ``` ``` $ rsleigh ./ctf_challenge main // main init(); puts("Welcome to my intricate trap, where all who are not me shall fail."); if (stage1() == 0) { fail(); if (stage2() == 0) { fail(); if (stage3() == 0) { fail(); puts("Amazing"); give_flag(); } } } ``` ## 反编译器输出 来自包含 DWARF 调试信息的编译 C 代码: ``` int factorial(int n) { if (n > 1) { return n * factorial(n - 1); } else { return 1; } } int main(void) { printf("add(3,4) = %d\n", add(3, 4)); printf("factorial(6) = %d\n", factorial(6)); printf("sum = %d\n", sum_array(nums, 5)); printf("strlen = %d\n", string_length("hello world")); return 0; } ``` 来自真实 CTF 二进制文件(剥离符号的 ELF,无源码): ``` // hkcert UAF — win function immediately visible void get_shell(void) { system("/bin/sh"); } // Crypto-Cat login — buffer overflow with all strings resolved puts("Enter admin password: "); gets(var_12); // overflow here strcmp(var_12); puts("Correct Password!"); // Heap menu — full string + import resolution void menu(long param_0) { print("Welcome to ABC Zoo!!!"); print("1) Add animal"); printf("> "); scanf("%d", buf); } ``` 来自 -O2 优化代码: ``` // Division by constant recognized return RAX % 3; // was: x * 0x55555556 >> 32 // Switch/case from jump table switch (d) { case 0: return "Sunday"; case 1: return "Monday"; ... } // For-loop recovery for (; len > i; i++) { total = arr[i] + total; } ``` 来自 PE64 二进制文件(PsExec,附带恶意软件分析注解): ``` // Dynamic API resolution — arguments fully visible GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlInitUnicodeString"); // dynamic API resolution GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtOpenFile"); // dynamic API resolution // RTTI vtable resolution *param_0 = std::bad_array_new_length::vftable; // Registry operations with annotations RegCreateKeyExW(..., HKEY_LOCAL_MACHINE); // ⚠ registry modification IsDebuggerPresent(); // ⚠ anti-debug check ``` 来自 C++ 二进制文件(Mach-O,已修饰名称还原): ``` phttp::Initialize(); phttp::Server::Server(); pthread_create(); phttp::Server::ListenAndRun(); phttp::Shutdown(); ``` 已针对来自 CSAW、HSCTF、DiceCTF、Google CTF、hkcert、Crypto-Cat、fbctf 和 Phoenix 的 30 多个 CTF 二进制文件进行测试。已在 Sysinternals PE64 工具(PsExec、strings64、whois64)、tinyssh、phttp 以及来自 theZoo 的真实恶意软件样本(WannaCry、Stuxnet/Duqu、Dyre、Emotet、Wildfire)上进行了测试。 ## 支持架构 | 架构 | 构造器数 | 备注 | |---|---|---| | x86-64 | 5700+ | 完整指令集,Windows x64 + SysV 调用约定 | | x86-32 | 4200+ | SSE/AVX,PE32 IAT,cdecl/thiscall,ELF32 PIE 字符串解析 | | AArch64 | 3500+ | NEON + SVE | | ARM32 | 1200+ | ARMv7 + Thumb | | MIPS32 | 900+ | FPU,DSP,MIPS16,microMIPS | | RISC-V 64 | 500+ | RV64GC + F/D/B/K/P/Q/V/C | **二进制格式:** ELF (32/64)、Mach-O (x86-64, AArch64)、PE (32/64,包括 ARM64 Windows) —— 根据头信息自动检测。在涵盖 PE32、PE64、Mach-O 和 ARM64 的 13 个测试二进制文件中,有 11 个的函数发现能力**优于 Ghidra**。10 阶段发现流程:符号表 → 递归 CALL 下行 → 穷尽 CALL/BL 目标扫描 → `.pdata` 异常目录(x86-64 12 字节 + ARM64 8 字节)→ `LC_FUNCTION_STARTS` (Mach-O) → `__objc_stubs`/`__stubs` (Mach-O) → 序言模式匹配(x86-32/x86-64/AArch64)→ JMP thunk 检测 → vtable 指针扫描 → `.rdata` 交叉引用。PE 机器类型自动检测(x86-64、ARM64、i386、ARM32)。回退手动 PE 解析器可处理畸形二进制文件(Stuxnet、加壳恶意软件)。 **38K+ 函数签名**自动加载 —— C stdlib、POSIX、Linux(syscall、ptrace、epoll、io_uring)、macOS(GCD、ObjC runtime、CoreFoundation、IOKit、Mach、Security、CommonCrypto)、Android、Win32/64(带细粒度 typedef:HKEY、HWND、REGSAM、LSTATUS)、OpenSSL、zlib。签名通过过程间两遍分析传播参数名称(调用处的 `/* param_name */`)和 Win32 typedef 类型。 ## 工作原理 ``` .slaspec → parser → codegen → generated Rust crates → compile ↓ bytes + addr → Decoder::decode() → Instruction { disassembly, ops: Vec } ↓ decompile_with_binary() → CFG → SSA → fold → structure → C pseudocode ``` **反编译器流水线(5 遍):** 1. **CFG** — P-code 到基本块,分支解析,IAT 调用目标解析,x86-32 CALL/RET 样板代码剥离 2. **SSA** — 带 phi 插入的迭代数据流(针对循环携带变量的多遍收敛) 3. **Fold** — 表达式折叠,死代码消除,条件恢复,类型推断(有符号/浮点/指针/布尔),调用约定检测(SysV/Win64/cdecl),常数除法,取模,基于签名的类型传播(38K+ 签名),过程间 typedef 传播(两遍),反向 Load 传播,MBA 混淆去混淆(SiMBA + 通过 egg 实现的等式饱和) 4. **Structure** — If/else、while/for/do-while 循环恢复,跳转表生成 switch/case,深度限制递归(最大 256) 5. **Printer** — 带类型参数和 Win32 typedef(HKEY、HWND、DWORD)的函数签名,调用处的 `/* param_name */` 注解,Ghidra 风格带数组大小的局部声明(`WCHAR local_8[262]`),ObjC 括号语法(`[self method:]`),MSVC C++ 名称修饰还原(`cout <<`、`cin >>`、`cin.ignore`),C++ 流包装器内联(`cout << "text" << "more"`),自动命名(针对 x86-32/x86-64/ARM64/XMM 的 iVar/lVar/dVar),指针解引用简化(`*param_N`),导入解析(PLT/GOT/IAT + thunk + CRT 包装器),全局命名(DAT_xxx),RBP/RSP 栈变量命名,字符串字面量检测,ELF32 PIE,栈/序言噪声消除 ## Rust API ``` use rsleigh_api::{Decoder, Architecture}; let mut dec = Decoder::new(Architecture::X86_64); let inst = dec.decode(&[0x48, 0x89, 0xd8], 0x1000).unwrap(); // MOV RAX,RBX (3 bytes) let binary = std::fs::read("my_binary").unwrap(); let pseudocode = rsleigh_decompile::decompile_with_binary( Architecture::X86_64, &instructions, Some(&binary), Some(path)); ``` ## 快速开始 ``` make test # generate all archs + build + run tests ``` 或者分步进行: ``` cargo run -p rsleigh-generate # parse slaspecs, emit generated Rust (~30s) cargo test -p test-harness # compile generated crates + run tests ``` ## 仓库结构 ``` rsleigh/ src/ SLEIGH parser + Rust codegen library pcode-ir/ PcodeOp/Varnode types + peephole optimizer (no_std) rsleigh-api/ Decoder API — bytes to instructions + P-code rsleigh-decompile/ Decompiler — P-code to C pseudocode + 38K signature DB rsleigh-cli/ CLI binary (two-pass interprocedural decompilation) scripts/ Ghidra signature extraction script rsleigh-generate/ Slaspec parser, generates Rust crate source generated/ Output crates (regenerated from slaspecs) test-harness/ Golden tests, corpus, fuzz, decompiler validation slaspec/ Ghidra .slaspec files (Apache 2.0) ``` ## 测试 跨 10 个类别的约 6000 条断言: - **Golden P-code** — 覆盖所有架构的 145 条精确解码断言 - **压力/边界** — 符号扩展、溢出、REX 前缀、SIB 寻址边缘情况 - **功能** — 14 条多指令序列测试(序言、调用约定、循环) - **Bug 探测** — 55 条语义检查(所有 16 种 x86 Jcc 变体、IDIV、MOVZX/MOVSX、ARM LDR 大小) - **编译代码模式** — canaries、跳转表、SETcc、LOCK、SSE2、PLT/GOT、TBZ/TBNZ - **Ghidra 差异对比** — 约 300 条指令与 Ghidra 的 P-code 输出进行了对比 - **反编译器对比** — 11 个函数与 Ghidra 12 进行了并排反编译对比 - **CTF 验证** — 30 多个真实二进制文件反编译成功 - **解码器模糊测试** — 1000 个随机字节序列,零 panic - **反编译器模糊测试** — 200 个随机指令序列通过完整流水线,零 panic ## 安全性 反编译器已针对不受信任的输入进行加固: - 带边界检查的 VarId 访问(越界时返回哨兵值,无 panic) - 结构恢复中的递归深度限制(256) - PLT/GOT/IAT 偏移计算中的已检查算术运算 - 反编译器模糊测试可捕获来自病态 P-code 的 panic - 反编译器和 API crate 中零 `unsafe` 代码块 ## 已知限制 - 表达式完整性 —— 某些寄存器值无法追溯至其定义表达式 - 循环条件并不总能恢复到源代码级别的比较 - x86-32 连续的 TEST/JNZ 模式有时嵌套不正确 - 寄存器间接调用(从 IAT 加载的 `CALL EDI`)未解析为导入名称 - 加壳恶意软件 —— 仅可见存根函数(Emotet);需先进行脱壳 - 结构字段类型 —— 显示字段偏移但未作为结构成员进行类型化 - MBA 混淆去混淆 —— 处理 1-4 变量线性 MBA;非线性表达式需要综合处理 ## 许可证 Apache 2.0。随附的 `.slaspec` 文件来自 Ghidra(同样为 Apache 2.0)。
标签:DAST, DWARF, Ghidra, Hakrawler, P-code, Rust, SLEIGH, URL提取, Wayback Machine, 中间表示, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 伪代码生成, 原生编译, 反汇编, 反编译, 可视化界面, 恶意软件分析, 控制流重建, 无JVM, 漏洞分析, 类型推断, 网络流量审计, 调试信息, 路径探测, 逆向工程, 通知系统, 静态分析