strings 什么也看不到。FLOSS 什么也看不到。rust-deobf 能看到 C2。
rust-deobf 能恢复混淆 Rust 二进制文件所隐藏的内容——C2 地址、文件路径、互斥体、注册表 键、配置——且无需运行样本。
一个按照恶意软件发布方式构建的 stripped Rust 程序(opt-level="z"、fat LTO、panic=abort),
其八个指标由 obfstr 加密——这些字符串
位于一个结构体、match 分支、比较以及一个永不执行的分支中。它们从未被打印。
由真实运行的捕获输出渲染而成(Linux x86-64,rustc 1.97):文本为 逐字内容,颜色和打字动画为添加效果,约 8 秒的模拟等待被加速,且 输出被裁剪为解码后的字符串。下方的纯文本输出为同一次运行。
文件向你展示的内容:
$ B=build/scatter_obfstr__elf__size-lto__strip
$ strings $B | grep -ciE 'northwind|10\.66|NW-5c1e9a|skip-update'
0
rust-deobf 能恢复的内容(静态分析 + Unicorn 模拟;二进制文件从不被执行):
$ python3 scripts/recover.py $B
binary: scatter_obfstr__elf__size-lto__strip format=ELF arch=x86_64
static x86-64 (recover_callsite): 0 strings decoders=9 seconds=0.2
emulation (recover_emulate): 8 strings functions=416/416 timed_out=False workers=1 seconds=6.8
== decoded strings ==
10.66.12.7:8443 [ip]
function 0xf20c (emulation)
C:\ProgramData\NorthwindSvc\state.db [path]
function 0xf20c (emulation)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) NorthwindAgent/2.1
function 0xf20c (emulation)
--skip-update-check
function 0xf443 (emulation)
Software\Northwind\Agent\Settings [registry]
function 0xf51b (emulation)
Global\NW-5c1e9a [mutex]
function 0xf5a8 (emulation)
https://telemetry.northwind.example/api/v3/beacon [url]
function 0xfd58 (emulation)
nw-agent::stage=collect
function 0xfd58 (emulation)
10 秒内完成 8/8,每个字符串都被标记并追溯到构建它的函数。
使用 ONLY=scatter_obfstr PROFILES=size-lto FORMATS=elf bash scripts/build_all.sh 复现
(输出已裁剪为解码后的字符串)。(输入是一个无害的基准测试
程序;每个植入的字符串都列在 bench_src/manifest.json 中。)
Rust 恶意软件正在增多,而其反混淆工具实际上处于缺失状态。FLOSS —— 标准的开源字符串反混淆器 —— 从常见的 Rust 混淆 crate 中什么都恢复不出来:
| 混淆器 | strings | FLOSS | rust-deobf |
|---|---|---|---|
| litcrypt / litcrypt2 | 0/5 | 0/5 | 5/5 |
| obfstr(内联 XOR+ADD) | 0/5 | 0/5 | 5/5 |
| cryptify(默认密钥) | 0/5 | 0/5 | 5/5 |
| muddy(ChaCha20-Poly1305 AEAD) | 0/5 | 0/5 | 5/5 |
| 紧凑栈字符串 | 0/5 | 0/5 | 5/5 |
| 手工编写的 XOR / ADD / SUB | 0/5 | 0/5 | 5/5 |
金丝雀基准测试,release 构建,ELF 和 PE x86-64 与 AArch64,剥离符号与未剥离符号。完整表格, 包括需要动态恢复的那一个案例(使用自定义密钥的 cryptify),见 结果。
在真实样本上:EDDIESTEALER(PE)—— 32 个混淆字符串,包括其隐藏的 C2 域名和 URL 路径,而静态工具和 FLOSS 恢复出 0 个。AmnesiaStealer(macOS Mach-O)—— C2 外传 URL、 加密剪贴板劫持配置、暂存路径。更多内容见下文。
字符串反混淆 —— 静态调用点恢复(数秒)+ 一个 Unicorn 模拟引擎,带有
真实加载器、C 运行时、路径探索和全局构造函数重放。可恢复仅在某个 match 分支中
或永不执行的分支上构建的字符串。
单屏 SOC 分诊 —— soc_triage.py:格式/架构、Rust 工具链、crate 能力
指纹(网络 / 加密 / 侦察 / 持久化 / 暂存)、按类型分组的指标,以及
一个经过校准的 LOW / MEDIUM / HIGH 信号及其证据。--json 用于 SIEM,--fail-on HIGH
用于脚本化门控。--fast(元数据 + 字面指标,不解码)随二进制
大小扩展:小样本不到一秒,20 MB 二进制约 20 秒。
多架构、多格式 —— x86-64、ARM64 和 32 位 x86,覆盖 ELF、PE 和 Mach-O。
契合你的工作流 —— FLOSS 兼容导出(--floss-json)、无头 Ghidra 注释
(plate 注释、书签、重命名)、按字节签名识别库函数
(剥离二进制中的 lib_<name>)、对目录进行批处理模式(--jsonl)。
超越字符串 —— 配置/C2 提取、哈希混淆的 API 导入解析、未打包的
第二阶段雕刻、控制流平坦化检测与重建(x86-64 和 AArch64,
已在 goldberg、OLLVM -fla 和真实的 LLVM-18 平坦化 pass 上验证)、使用 Z3 的 MBA / 不透明谓词
简化、Rust trait 对象 vtable 恢复(recover_types.py),以及
优化逆转(跳转表反切换、展开循环检测 —— premium/opt_reverse.py)。
代码虚拟化 —— detect_vm.py 标记 VMProtect/Themida/Tigress 风格的字节码 VM;
高级版反虚拟化器将它们还原。从一个具有随机化操作码和加密
操作数的 VM 中,它重建:
return (((a0 > 1000) & (((((a0 * 31) + a1) ^ (a0 >> 3)) % 97) == 0)) ? (a1 + a0) : 0xffffffff);
— 函数的精确源码。
设计上安全 — 默认采用静态分析 + 模拟执行:模拟执行在 Unicorn 下运行二进制的函数,而非二进制本身。动态(Frida)恢复为可选功能,且仅适用于隔离的虚拟机。
可经受 strip 的 Rust 元数据 — rustc 版本、带精确版本的第三方 crate,以及 panic 位置,均可从编译器在每个 Rust 二进制中留下的源码路径重建(无需 cargo-auditable)。
反编译器的字符串视图、strings、FLOSS——任何从文件中读取字符串的工具——都只能显示确实存在于文件中的字节。混淆 crate 确保明文永远不会出现在文件中,因此读取反编译器的 AI 代理看到的和你看到的一样——什么都没有。rust-deobf 则为其提供事实依据。
它是一个带 JSON 输出的 CLI,因此任何能运行 shell 命令的代理(Claude Code、Codex、Cursor 等)都可以在它已经驱动的任何反编译器工具旁边调用它:
python3 scripts/soc_triage.py sample.bin --json # one-screen facts: toolchain, crates, IOCs, signal
python3 scripts/recover.py sample.bin --json # every decoded string + the function that builds it
scripts/ghidra_run.sh sample.bin # write them into the Ghidra decompiler as plate comments
python3 scripts/mcp_server.py # or serve recover/triage/metadata/detect as MCP tools
更喜欢使用类型化工具而不是 CLI 解析?scripts/mcp_server.py 通过 stdio 将 detect / metadata / triage / recover 暴露为 MCP 工具(无需第三方包),因此 agent 可以用 JSON schema 调用它们,并得到结构化的 JSON 返回。而 scripts/export_rules.py 会把恢复出的事实转换为 capa 规则和 YARA 规则(Mandiant 检测格式),用于混淆 crate,以及从恢复出的解码器惯用法 / 哈希混淆导入中生成——--static-only 会为任意语料输出 crate 家族规则集。
一个效果很好的提示词:
“从 rust-deobf 运行
python3 scripts/soc_triage.py sample.bin --json和python3 scripts/recover.py sample.bin --json,然后反编译这些字符串来源的函数,并解释它们的作用。将 rust-deobf 解码出的字符串视为基准事实;将你推断出的任何内容标记为假设。”
想要内置 LLM 步骤?scripts/llm_triage.py 会仅将恢复出的事实(绝不包含原始二进制)交给本地模型(通过 RUST_DEOBF_LLM_BASE 使用 Ollama / vLLM——恶意软件数据保留在你的主机上)、Anthropic 或 OpenAI API,或者打印出有依据的提示词以供离线使用。
git clone https://github.com/VAHPEM/rust-deobf.git
cd rust-deobf
python3 -m pip install -r requirements.txt # lief, capstone, unicorn, z3-solver
python3 scripts/recover.py path/to/binary # static + emulation (default), never runs it
python3 scripts/soc_triage.py path/to/binary # one-screen triage card
python3 scripts/recover.py path/to/binary --json # machine-readable, for agents and pipelines
python3 scripts/recover.py path/to/binary --floss-json out.json # FLOSS results document
python3 scripts/recover.py path/to/binary --emulate never # static passes only, seconds
python3 scripts/recover.py path/to/binary --time-budget 600 # big binaries: emulate longer
python3 scripts/recover.py path/to/binary --max-ram 2G # cap memory (fewer processes)
python3 scripts/recover.py path/to/binary --libfuncs # also name Rust std/crate functions
python3 scripts/recover.py samples/ --jsonl triage.jsonl # a whole directory