本节摘要:本节是开工前的装备间。先给全书四篇结构(地基、工具流、纵深、方法)与三条阅读路径——工具快用型、自动化型、分析纵深型——各配时间预算与产出;再划清与《语义代码检索》的分工:有源码走那边的 LSP 与 tree-sitter,无源码走这边的反编译与交叉引用。然后是逐项环境清单:JDK 21 与 Ghidra 12.1.4、radare2、Python 3.12,配自检命令;接着约定练习对象(只用自编译程序、公开 CTF 样本与开源软件)与练习目录布局,并编译全书通用的示例程序 demo(含 stripped 版本)。最后是安全带:未知二进制一律先进隔离环境,做法见《Agent 沙箱与运行时隔离》第 2 章。
全书四篇:地基(第 0002 章)打工具底座,工具流(第 0305 章)把工具交给模型,纵深(第 0609 章)推到数据流与符号执行,方法(第 1011 章)收束成方法论与合规。
| 路径 | 章节 | 预算 | 产出 |
|---|---|---|---|
| 工具快用型 | 第 01~03 章 | 约两天 | 能和模型结对读一个陌生二进制 |
| 自动化型 | 第 02 章 + 第 04~05 章 | 约三天 | 从二进制到结构化结论的可编程数据流 |
| 分析纵深型 | 第 0611 章(先读第 0002 章打底) | 一周以上 | 漏洞研究级的方法论与评测能力 |
三条路径都从本节出发:无论走哪条,先把下面的环境清单勾完。
一个问题先问清楚:手上有源码吗?答案决定你读哪本书。
「我想理解这个程序」 │ 手上有完整源码吗? │ │ 有 没有(或只有二进制可信) ▼ ▼ 《语义代码检索》 本书(AI 逆向工程) LSP / tree-sitter 符号 反编译伪代码 / 交叉引用 AST 切分 / repo-map 动态调试 / 符号执行 「代码在哪」 「二进制在做什么」 │ │ └───── 汇合点:模型读文本提假设 ─────┘
两本书的分工可以记成一句话:那边回答「代码在哪」,这边回答「二进制在做什么」。 具体边界:
四件装备,逐项自检。所有版本号为 2026-10 社区口径,安装细节以官方文档为准。
| 项 | 版本口径 | 用途 | 自检 |
|---|---|---|---|
| JDK | 21 及以上(Ghidra 12.x 要求,以官方发行说明为准) | 运行 Ghidra | java -version |
| Ghidra | 12.1.4(Apache-2.0,NSA 开源) | 反编译与工程化分析 | 启动 ghidraRun 见到界面 |
| radare2 | 6.2.4 | 命令行逆向与脚本化 | r2 -v |
| Python | 3.12 | 全书脚本与 r2pipe / PyGhidra | python --version |
# bash —— 环境自检(任一项失败都先解决再往下走) java -version # 期望:21 及以上 r2 -v # 期望:radare2 6.x python --version # 期望:3.12.x pip install r2pipe # 第 02 章会用到
Ghidra 从官方发布页下载发行包并解压即可,无需安装器;JDK 推荐任一主流发行版(如 Temurin)。radare2 各平台安装方式不同(包管理器、官方安装脚本或 GitHub 发布页),以 radare2 官方文档为准。
全书示例对象只有三类合法来源:自己编译的程序、公开 CTF 样本、开源软件。不使用任何来路不明的商业闭源软件做演示。
re-lab/ # 全书练习根目录 ├── demo.c # 全书通用示例程序(本节创建) ├── bin/ # 编译产物:demo、demo_stripped、后续 CTF 样本 ├── out/ # 导出的函数清单 JSON、报告 └── scripts/ # 第 01 章起的 Ghidra 脚本
示例程序只有一个知识点:把许可密钥用常量异或(XOR)混淆后比较。麻雀虽小,静态阅读、交叉引用、重命名、模型提假设四件事全用得上:
// demo.c —— 全书练习用示例程序:最小许可校验(自编译,仅供教学) #include <stdio.h> #include <string.h> static int deobfuscate(const char *in, char *out) { int i = 0; while (in[i] != 0) { out[i] = (char)(in[i] ^ 0x5a); i++; } out[i] = 0; return i; } static int check_key(const char *key) { char expected[32]; deobfuscate("\x36\x33\x39\x3f\x34\x29\x3f", expected); return strcmp(key, expected) == 0; } static void grant(const char *key) { printf("[OK] license granted: %s\n", key); } static void deny(void) { puts("[FAIL] invalid license key"); } int main(int argc, char **argv) { if (argc != 2) { puts("usage: demo <key>"); return 1; } if (check_key(argv[1])) { grant(argv[1]); return 0; } deny(); return 2; }
# bash —— 编译两个版本:带符号的 demo 与去符号的 demo_stripped gcc -O0 -g -o bin/demo demo.c gcc -O0 -s -o bin/demo_stripped demo.c ./bin/demo wrong # 期望:[FAIL] invalid license key echo "正确的 key 是什么?第 1.2 节用逆向的方式揭晓"
后面各章反复使用这两个版本:demo 带符号表,用来对照「正确答案」;demo_stripped 模拟真实场景——没有函数名,只有地址。
从本节起请立一条铁律:任何来源不明的二进制,一律默认恶意,一律先进隔离环境。 这不是吓唬人:CTF 样本可能被污染,论坛上捡到的「工具」可能带后门,固件镜像里可能有测试残留。哪怕你只打算「看一眼字符串」,样本也可能在你双击或误执行的瞬间落地。
装备就位,开工。下一章把 Ghidra 装起来、把 demo 导进去、把第一个函数清单导出来——这是全书一切工具流的地基。