一、背景:AI 反编译已经走到哪了?
2024 年以来,LLM 在二进制反编译领域取得了一系列突破。如果你还停留在”Ghidra 输出的伪代码勉强能看”的印象,那可能需要更新认知了。
1.1 LLM4Decompile:第一个开源反编译大模型
LLM4Decompile(EMNLP 2024)是第一个专门为反编译训练的开源 LLM 系列,参数规模从 1.3B 到 33B。它提供了两种模式:
- End 模式:直接从汇编代码生成 C 源码
- Ref 模式:接收 Ghidra 的伪代码输出,精炼为更高质量的 C 代码
在 HumanEval-Decompile benchmark 上,LLM4D 的 re-executability(反编译结果能否重新编译并正确执行)比 Ghidra + GPT-4o 高出 100%以上。V2 版本(6.7B-Ref)在该指标上达到约 52.7%,9B 模型更是达到了 64.9%。
1.2 SK²Decompile:骨架与皮肤的分离
SK²Decompile(2025,已提交 ICLR 2026)提出了一个优雅的解耦思路——将反编译分为两个独立阶段:
- Skeleton(骨架恢复):将二进制翻译为中间表示,保留控制流和数据结构,但把所有标识符替换为通用占位符
- Skin(表皮命名):为占位符生成有语义的标识符名称
两个阶段分别用强化学习训练,Skeleton 模型被奖励产出语法正确的结构,Skin 模型被奖励语义相似度。在 HumanEval 上 re-executability 比 GPT-4-mini 高 21.6%。
1.3 DecLLM:让反编译结果能编译
DecLLM(ISSTA 2025)关注的是另一个维度——可再编译性(recompilability)。它的核心思路是迭代修复:
Ghidra 伪代码 → LLM 修复 → 尝试编译 → 收集错误 → 再修复 → ...用 GPT-4 驱动这个循环,约 70% 的原本不可编译的 Ghidra 输出可以被修复为可编译版本。这对 CodeQL 等需要可编译代码的漏洞分析工具非常有价值。
1.4 ReCopilot:二进制分析领域特化模型
ReCopilot(2025.05,奇安信研究院)走的是领域特化路线——通过 CPT(继续预训练)→ SFT(有监督微调)→ DPO(直接偏好优化)三阶段训练一个专门的二进制分析模型。它支持反编译、函数名恢复、变量类型推断、结构体恢复等多个任务,在函数名恢复上比通用 LLM 高 13%。
值得注意的是,ReCopilot 已经引入了 data flow(数据流)和 call graph(调用图) 作为额外上下文来增强跨函数感知能力。但论文也明确指出:“建立超长思维链推理存在显著挑战”。
1.5 其他值得关注的工作
| 项目 | 来源 | 关键贡献 |
|---|---|---|
| ReF Decompile | 2025 | 跳转地址重标记 + 函数调用类型推断,HumanEval 61.43% |
| ReSym | CCS 2024 杰出论文 | LLM + Prolog 算法恢复变量和结构体符号 |
| REx86 | 2025 | 基于 Qwen2.5-Coder-7B 的本地化 x86 逆向模型 |
| TYGR | USENIX Security 2024 | GNN 做 stripped binary 的类型推断,76.6% 准确率 |
| AgentRE-Bench | 2025 | 首个逆向工程 Agent 标准化 benchmark |
看起来成果很多?但如果你仔细看,会发现一个所有这些工作共享的根本局限。
二、核心局限:函数是一座孤岛
2.1 所有现有方案都是函数级的
把上面提到的所有工作放在一起,你会发现一个惊人的事实:
它们全部都只能处理单个函数。
- LLM4Decompile:输入是一个函数的汇编,输出是一个函数的 C 代码,max 4096 tokens
- SK²Decompile:Skeleton 和 Skin 都在单函数范围内操作
- DecLLM:修复循环只关心”这一个函数能不能编译通过”
- ReF Decompile:同样的函数级端到端
- ReCopilot:虽然引入了调用图上下文,但核心推理仍是逐函数进行
这意味着什么?
2.2 一个真实的例子
假设你有一个网络服务器程序被编译为 stripped binary(所有符号信息被剥除)。程序里有这样的调用关系:
// 真实源码(你要恢复的目标)struct connection_t { int fd; char *buffer; size_t buf_size; struct sockaddr_in peer_addr;};
// 函数 A:创建连接struct connection_t* create_connection(int port, const char *host) { struct connection_t *conn = malloc(sizeof(struct connection_t)); conn->fd = socket(AF_INET, SOCK_STREAM, 0); conn->peer_addr.sin_port = htons(port); conn->peer_addr.sin_addr.s_addr = inet_addr(host); connect(conn->fd, (struct sockaddr*)&conn->peer_addr, sizeof(conn->peer_addr)); conn->buffer = malloc(4096); conn->buf_size = 4096; return conn;}
// 函数 B:发送数据(依赖函数 A 创建的 connection_t)int send_data(struct connection_t *conn, const char *data, size_t len) { if (len > conn->buf_size) { conn->buffer = realloc(conn->buffer, len); conn->buf_size = len; } memcpy(conn->buffer, data, len); return send(conn->fd, conn->buffer, len, 0);}现在用现有的函数级工具反编译。每个函数被独立处理:
函数 A 的反编译结果(不知道 B 的存在):
// LLM4D 的输出——它不知道 struct connection_t 长什么样void* sub_401234(int param_1, char *param_2) { void *v1 = malloc(32); // 不知道是 struct connection_t *(int*)v1 = socket(2, 1, 0); // ... 一堆指针偏移操作 ... return v1;}函数 B 的反编译结果(不知道 A 的存在):
// 独立反编译——同一个 struct 完全不同的理解int sub_401500(long param_1, char *param_2, int param_3) { if (param_3 > *(int*)(param_1 + 16)) { // buf_size 偏移猜测 // ... } return send(*(int*)param_1, *(char**)(param_1 + 8), param_3, 0);}看到问题了吗?
- struct connection_t 消失了:函数 A 和 B 都在操作同一个 struct,但各自用
void*和long加偏移量来理解它,没有任何人把它们统一起来 - 函数签名不一致:A 返回
void*,B 接收long——实际是同一个类型 - 语义断裂:A 创建的连接是给 B 用的,但反编译时两个函数互相不知道对方的存在
- 组合后无法编译:即使每个函数单独”看起来对”,放到一个项目里各种类型冲突
这就是函数级反编译的根本局限——每个函数都是一座信息孤岛。
2.3 量化这个问题
这不只是个理论问题。我整理了一下从函数级反编译到”完整可编译项目”之间的鸿沟:
| 需要解决的问题 | 现有方案的覆盖 | 缺口 |
|---|---|---|
| 单个函数的控制流恢复 | LLM4D, SK² 覆盖 | 无 |
| 单个函数的变量命名 | SK² Skin, ReCopilot 覆盖 | 无 |
| 跨函数的类型一致性 | 无方案覆盖 | 完全空白 |
| 全局变量的统一声明 | 无方案覆盖 | 完全空白 |
| 结构体定义的跨函数恢复 | ReSym 有初步尝试 | 大部分空白 |
| 头文件依赖恢复 | 无方案覆盖 | 完全空白 |
| 项目级编译验证 | DecLLM 仅单函数 | 项目级空白 |
| 函数间的调用签名一致性 | 无方案覆盖 | 完全空白 |
| 编译配置推断(Makefile) | 无方案覆盖 | 完全空白 |
2.4 上下文窗口不是银弹
你可能会想:“等 LLM 的上下文窗口足够大,把整个二进制的反汇编一次性塞进去不就行了?”
不行。原因有三:
1. 规模不现实。一个 1MB 的 stripped binary 反汇编后的文本量轻松超过 数百万行。即使 200K token 的模型也远远不够。
2. 注意力稀释。即使物理上塞得下,LLM 在超长上下文中的注意力分配是高度不均匀的——中间部分的信息几乎被忽略(这就是著名的 “Lost in the Middle” 问题)。
3. ReCopilot 的教训。ReCopilot 已经尝试把调用图和数据流塞进 prompt,但论文自己承认”超长思维链推理是主要瓶颈”。单模型在需要持续追踪数百个函数间依赖关系时,推理链会崩溃。
2.5 一张图总结现状
处理粒度 函数级 ◄──────────► 全程序级 │ │ LLM4Decompile ────┤ │ SK²Decompile ─────┤ │ ReF Decompile ────┤ │ DecLLM ───────────┤ │ ReCopilot ────────┼──┐ │ │ │ │ │ (有限的跨函数) │ │ │ │ ❓这里是空白 │ │ 单模型/管道 ◄──────────► 多智能体协作所有现有工作都挤在左下角(函数级 + 单模型/管道)。右上角(全程序级 + 多智能体协作)是一片空白。
三、为什么多智能体是对的架构
发现了问题,为什么我认为多智能体(Multi-Agent System)是正确的解决方向?
3.1 本质论证:任务分解
“二进制 → 可编译项目”这个任务实际上包含了性质完全不同的子任务:
| 子任务 | 性质 | 最适合的模型 |
|---|---|---|
| ASM → C 翻译 | 模式匹配 + 代码生成 | 特化小模型(LLM4D 6.7B) |
| 符号恢复(命名) | 语义推理 + 世界知识 | 通用大模型(GPT-4/Claude) |
| 类型系统统一 | 约束求解 + 冲突裁决 | 图算法 + LLM 辅助 |
| 编译修复 | 错误诊断 + 代码修改 | 代码专家模型 |
| 语义验证 | 符号执行 + 等价性检查 | 程序分析工具(angr) |
用一个模型做所有事情,就像让一个外科医生同时做手术、做化验、读 CT、开处方——理论上可能,但远不如专业团队协作高效。
3.2 解决上下文窗口问题
多智能体的杀手级优势在于将知识外化。
单模型方案:所有信息必须塞进一个上下文窗口
[一个巨大的 prompt]├── 函数 1 的反汇编 (2K tokens)├── 函数 2 的反汇编 (3K tokens)├── ...├── 函数 200 的反汇编 (1.5K tokens)├── 调用关系说明 (5K tokens)├── 全局变量列表 (2K tokens)├── 已知类型定义 (3K tokens)└── 任务指令 (1K tokens)= 远远超出上下文限制多智能体方案:知识存储在外部图数据库,每个 Agent 按需查询
Agent A 处理函数 1 时的 prompt:├── 函数 1 的 Ghidra 伪代码 (0.5K tokens)├── [从 neo4j 查询] 函数 1 调用的 3 个函数的签名 (0.3K tokens)├── [从 neo4j 查询] 函数 1 使用的 2 个全局变量的类型 (0.1K tokens)├── [从 neo4j 查询] 相关的 1 个 struct 定义 (0.2K tokens)└── 任务指令 (0.5K tokens)= 仅 1.6K tokens,精准且充分每个 Agent 只需要局部上下文,但可以通过共享知识库利用全局信息。这是单模型方案做不到的。
3.3 验证闭环天然适配
在多 Agent 架构中,“生成者”和”验证者”是天然分离的:
反编译 Agent:我觉得这个函数返回 int ↓ 写入知识库验证 Agent:编译器说调用者把返回值赋给了 char*,类型冲突 ↓ 反馈修复 Agent:根据调用上下文,应该返回 char*,修复这种对抗性设计(一个生成,另一个验证)比单模型的”自己检查自己”更可靠。DecLLM 已经证明了迭代修复循环的价值(70% 的不可编译代码被修复),但它只在单函数级别做。多 Agent 架构可以将这个闭环扩展到项目级别。
3.4 模型经济学
一个被忽视的论点:成本。
如果用 GPT-4 直接反编译一个 200 函数的程序:
- 每个函数需要大量上下文 → 每个调用 ~10K tokens
- 200 函数 × 10K = 2M tokens
- 多轮修复 × 3 = 6M tokens
- GPT-4 价格 ~180-360**
多智能体方案:
- 反编译用 LLM4D-Ref 6.7B(本地部署,成本几乎为零)
- 只有符号恢复和修复用 GPT-4(~50K tokens)
- 总计 API 成本 → $3-5
两个数量级的成本差异。
3.5 可扩展性
明天如果需要支持 ARM 架构?或者 RISC-V?
- 单模型方案:需要重新训练整个模型
- 多 Agent 方案:只需替换/增加一个”ARM 反编译 Agent”,其余架构(关系恢复、验证修复、知识库)完全不变
四、RE-MAS:我的系统设计
基于以上分析,我设计了 RE-MAS(Reverse Engineering Multi-Agent System),一个面向全程序可再编译反编译的多智能体系统。
4.1 设计哲学
三个核心原则:
- 分而治之:将超复杂任务分解为 4 个专业子任务
- 知识共享:所有 Agent 通过中心化的图数据库交换信息,而非直接通信
- 迭代收敛:验证-修复闭环驱动结果逐步逼近可编译状态
4.2 整体架构
┌─────────────────────────────────────────┐ │ Orchestrator (编排器) │ │ LangGraph StateGraph + 确定性状态机 │ └────┬────────┬──────────┬────────────┬───┘ │ │ │ │ ┌────▼───┐┌───▼────┐┌────▼─────┐┌────▼─────┐ │Phase 0 ││Phase 1 ││Phase 2 ││Phase 3 │ │预处理 ││反编译 ││关系恢复 ││验证修复 │ │Agent ││Agent ││Agent ││Agent │ │ ││ ││ ││ │ │Ghidra ││LLM4D ││GPT-4 / ││GCC + │ │headless││-Ref ││Claude ││angr + │ │+ 分析 ││6.7B ││+ neo4j ││LLM │ └───┬────┘└───┬────┘└────┬─────┘└────┬─────┘ │ │ │ │ ▼ ▼ ▼ ▼ ┌─────────────────────────────────────────┐ │ 共享知识库 │ │ neo4j (代码属性图 CPG) │ │ + SQLite (元数据与状态追踪) │ │ + 文件系统 (源码/头文件/编译产物) │ └─────────────────────────────────────────┘4.3 Phase 0:预处理 Agent
用途:把原始二进制文件”拆开”,建立初始知识库。
工具:Ghidra headless analyzer
做什么:
- 加载 ELF 二进制,自动分析
- 识别所有函数及其边界
- 提取静态调用图(谁调用了谁)
- 为每个函数生成 Ghidra 伪代码
- 识别全局变量、字符串常量、导入函数
- 将所有信息写入 neo4j(函数节点 + 调用关系边)和 SQLite(函数状态表)
关键设计——函数优先级排序:
优先级策略:修改逆拓扑排序(叶函数优先)
为什么?叶函数(不调用其他用户函数的函数)反编译时不依赖任何其他函数的信息,结果最独立可靠。先反编译它们,就可以把它们的签名信息存入知识库,供后续反编译其调用者时使用。
Batch 1: 叶函数 → 独立反编译,签名写入 CPGBatch 2: 只调用 Batch 1 的函数 → 利用 Batch 1 的签名作为上下文Batch 3: 调用 Batch 1+2 的函数 → 上下文更丰富...最后: main() → 拥有最完整的上下文这类似于编译器做的事——先处理被依赖的,再处理依赖者。
4.4 Phase 1:反编译 Agent
用途:将每个函数的 Ghidra 伪代码精炼为高质量 C 源码。
核心模型:LLM4Decompile-Ref 6.7B V2(本地 GPU 部署)
关键创新——CPG 上下文增强:
在发给 LLM4D 的 prompt 中,不只包含当前函数的 Ghidra 伪代码,还会从 neo4j 查询并注入:
- 当前函数调用的所有已知被调用函数的签名(因为叶函数已经先反编译完了)
- 当前函数使用的全局变量的类型信息
- 当前函数访问的已知结构体定义
### Context:// Known callee signatures:int parse_header(const char *buf, size_t len);void free_connection(struct conn_t *conn);
// Known global variables:extern int g_verbose_level;extern struct config_t *g_config;
// Known struct:struct conn_t { int fd; char *buffer; size_t buf_size; };
### Ghidra Pseudo-Code:undefined8 FUN_00401234(long param_1, int param_2) { ... }
### Refined C Code:这样,即使是 6.7B 的小模型,也能利用全局信息做出更好的判断——因为它不需要自己”猜”被调用函数的签名,知识库已经告诉它了。
每个反编译结果还会被评估一个置信度分数(综合语法有效性、类型一致性、调用签名匹配度、模型 log probability),低置信度的函数会被标记为后续修复的优先目标。
4.5 Phase 2:关系恢复 Agent
用途:将一堆独立的函数级反编译结果整合为一个完整的项目。
核心模型:GPT-4 / Claude(需要强语义推理能力)
这是整个系统中最核心、最有创新性的环节。它需要完成 5 个子任务:
子任务 1:类型系统统一
同一个 struct 在不同函数中可能被理解为不同的东西。例如函数 A 看到 void* 加偏移操作,函数 B 看到 struct foo*。需要:
- 收集所有函数中出现的类型信息
- 通过图上的约束传播合并等价类型
- 冲突时交给 LLM 裁决(给出两个函数的完整代码和调用上下文,让 LLM 判断哪个更正确)
子任务 2:符号恢复(函数名、变量名)
分三层逐步推理:
- 第一层(确定性):导出符号表有名字的直接用;调用
printf、malloc等标准库函数可推断参数名 - 第二层(模式匹配):函数里调
socket+bind+listen+accept→ 命名为setup_server - 第三层(LLM 深度推理):把函数代码 + 调用图上下文发给 GPT-4,推断语义化的名字
子任务 3:模块划分
用 neo4j 内置的 Louvain 社区检测算法 在调用图上做聚类。紧密调用的函数被划分到同一个 .c 文件中。main() 单独一个文件,被多个模块调用的工具函数放到 utils.c。
子任务 4:头文件生成
types.h:所有自定义结构体和类型定义(按依赖顺序排列)globals.h:全局变量的extern声明prototypes.h:非static函数的原型声明- 标准库
#include:维护一张 ~500 条的库函数 → 头文件映射表(printf → <stdio.h>,socket → <sys/socket.h>等)
子任务 5:项目组装
将以上所有结果组装为完整项目:多个 .c 文件 + 头文件 + 自动生成的 Makefile。
4.6 Phase 3:验证修复 Agent
用途:发现并修复反编译结果中的错误,形成迭代闭环。
工具:GCC(编译验证)+ angr(符号执行语义验证)+ LLM(智能修复)
四层验证体系,从快到慢、从粗到细:
Level 1: 语法验证 (tree-sitter, < 1秒) ✓ → Level 2 ✗ → 规则修复(缺分号、括号不匹配等,无需 LLM)
Level 2: 编译验证 (GCC, < 10秒) ✓ → Level 3 ✗ → 结构化错误解析 → 分类(5类错误) → 对应修复策略
Level 3: 语义验证 (angr 符号执行, 分钟级) ✓ → 完成 ✗ → LLM 深度推理修复
Level 4: 行为验证 (编译+运行对比, 可选) 对比反编译程序和原始二进制在相同输入下的输出编译错误被分为 5 类,每类有不同的修复策略:
| 类型 | 示例 | 修复方式 |
|---|---|---|
| E1 语法错误 | 缺分号、括号不匹配 | 规则修复,不用 LLM |
| E2 类型错误 | 指针/整数混用 | 查 CPG 该变量在其他函数中的类型,取更一致的 |
| E3 声明缺失 | 函数/类型/变量未声明 | 检查是否遗漏头文件或原型声明 |
| E4 链接错误 | undefined reference | 检查函数是否遗漏反编译 |
| E5 语义不一致 | 调用参数数量不匹配 | 拉取 caller+callee 完整代码,LLM 综合裁决 |
整个修复过程是迭代的,最多进行 5 轮全局迭代。如果连续 2 轮没有修复任何新错误,判定为收敛并停止。
4.7 共享知识库
这是将四个 Agent 粘合在一起的关键基础设施:
neo4j 代码属性图(CPG)——存储结构化的程序知识:
节点类型: (:Function) — 函数,含地址、名字、签名、置信度 (:Variable) — 变量,含名字、类型、作用域 (:Struct) — 结构体,含字段定义 (:Type) — 类型信息 (:SourceFile)— 源文件
关系类型: CALLS — 函数调用关系 HAS_VARIABLE — 函数拥有变量 HAS_TYPE — 变量的类型 READS_GLOBAL — 函数读取全局变量 WRITES_GLOBAL— 函数写入全局变量 INCLUDES — 文件包含关系为什么用图数据库而不是关系数据库? 因为逆向工程中最频繁的查询模式是”从这个函数出发,沿着调用链找到所有相关函数和共享的全局变量”——这正是图查询的天然优势。比如:
// 获取函数 F 的完整上下文:调用者+被调用者+共享全局变量+相关结构体MATCH (f:Function {address: 0x401234})OPTIONAL MATCH (caller)-[:CALLS]->(f)OPTIONAL MATCH (f)-[:CALLS]->(callee)OPTIONAL MATCH (f)-[:READS_GLOBAL|WRITES_GLOBAL]->(gv:Variable)OPTIONAL MATCH (f)-[:ACCESSES_STRUCT]->(s:Struct)RETURN f, collect(DISTINCT caller), collect(DISTINCT callee), collect(DISTINCT gv), collect(DISTINCT s)这个查询在关系数据库中需要多次 JOIN,在 neo4j 中是自然的一跳遍历。
SQLite 元数据库——追踪每个函数的反编译状态、修复历史、置信度分数等轻量元数据。选 SQLite 是因为零配置、单文件部署。
4.8 Orchestrator:确定性状态机
Orchestrator 不调用 LLM。它是一个用 LangGraph 实现的确定性状态图,负责:
- 控制 Phase 0 → 1 → 2 → 3 的流转
- Phase 3 发现需要重新反编译某些函数时,回退到 Phase 1
- Phase 3 发现类型系统需要调整时,回退到 Phase 2
- 追踪进度、资源消耗
- 判断何时终止(编译成功 / 迭代上限 / 收敛 / 预算用尽)
Phase 0 → Phase 1 → Phase 2 → Phase 3 ↑ ↑ │ │ │ ├── 编译通过 → 完成 │ │ ├── 类型问题 → 回退 Phase 2 │ └────────┤ │ └── 函数需重做 → 回退 Phase 1 └─────────────────┘Agent 之间不直接通信。所有信息交换通过知识库完成(黑板模型):Agent A 写入知识库 → Orchestrator 检测状态变化 → 触发 Agent B 读取知识库。这保证了解耦、可追溯、可恢复。
五、与现有工作的关键差异
| 维度 | LLM4D / SK² / ReF | DecLLM | ReCopilot | CTF Agents | RE-MAS |
|---|---|---|---|---|---|
| 处理粒度 | 函数 | 函数 | 函数(+有限跨函数) | 题目 | 全程序 |
| 跨函数信息 | 无 | 无 | 有限(受token限制) | 无 | CPG图查询 |
| 验证闭环 | 无 | 有(单函数) | 无 | 无 | 有(项目级) |
| 信息持久化 | 无 | 无 | 无 | 简单memory | 图数据库 |
| 输出产物 | 单个C函数 | 可编译单函数 | 分析建议 | CTF flag | 可编译项目 |
| 训练需求 | 大量训练 | 零(用GPT-4) | 三阶段训练 | 零 | 部分零 |
核心差异只有一句话:它们都在函数级做单模型推理,我在项目级做多 Agent 协作。
六、局限性与诚实的评估
我不想假装这个方案没有问题。以下是我目前看到的主要风险和局限:
6.1 全程序编译可能真的很难
头文件依赖恢复是个悬而未决的难题。标准库函数可以用映射表覆盖(约 500 条规则覆盖 90% 场景),但第三方库依赖几乎无法自动恢复。如果原始程序链接了 libcurl、openssl 之类的库,目前没有好的自动推断方法。
回退策略:如果全程序编译不可达,可以退而求其次——模块级可编译(每个 .c 文件单独编译通过),或者带 stub 的可编译版本(困难函数只保留签名不保留实现)。
6.2 混淆不在范围内
这个系统只针对干净逆向(无混淆的正常编译产物)。对于 OLLVM 控制流平坦化、VMP 虚拟化保护等混淆技术,目前 LLM 的处理能力非常有限——2025 年最新研究(arxiv 2505.19887)显示组合混淆下所有 SOTA LLM 普遍失败。混淆是 future work。
6.3 评估基准的缺失
现有的 benchmark(HumanEval-Decompile、ExeBench)都是函数级的。全程序级反编译目前没有标准化的评估基准,需要自建。我计划选取 8 个开源 C 项目(从 GNU coreutils 的 cat 到 Lua 解释器),编译为 stripped binary 后反编译还原,与原始源码对比。
6.4 Token 消耗
虽然反编译用本地模型几乎零成本,但关系恢复 Agent 调用 GPT-4 的开销与项目规模成正比。对于 200+ 函数的大型项目,API 成本可能达到 $30-50。不过这比让一个逆向工程师花一周时间手动还原便宜得多。
七、下一步计划
- 实现 MVP(2周):Phase 0 + Phase 1 管道跑通,在 HumanEval-Decompile 上验证不低于 LLM4D 基线
- 全管道验证(4周):四个 Phase 完整跑通,在 GNU
cat上实现端到端编译通过 - 完整评估(8周):全部 benchmark + baseline 对比 + 消融实验
- 论文撰写(12周):面向 ISSTA/ASE 等软件工程顶会投稿
项目代码将在 GitHub 上开源:chaojixinren/REAgent
参考资料与链接
核心论文
| 论文 | 会议/状态 | 链接 |
|---|---|---|
| LLM4Decompile | EMNLP 2024 | arxiv / GitHub / HuggingFace |
| SK²Decompile | submitted to ICLR 2026 | arxiv / GitHub / OpenReview |
| DecLLM | ISSTA 2025 | 会议页面 |
| ReCopilot | arxiv 2025.05 | arxiv / GitHub |
| ReSym | CCS 2024 杰出论文 | 论文 / GitHub |
| ReF Decompile | arxiv 2025 | arxiv |
| REx86 | arxiv 2025 | arxiv |
| TYGR | USENIX Security 2024 | 会议页面 |
| LLM 去混淆评估框架 | arxiv 2025.05 | arxiv |
| LLM + 符号执行语义恢复 | arxiv 2025.11 | arxiv |
| RECoRD (多Agent关系恢复) | ICML 2025 | OpenReview |
工具与框架
| 工具 | 用途 | 链接 |
|---|---|---|
| Ghidra | 传统反编译器 (NSA 开源) | 官网 / GitHub |
| IDA Pro MCP | IDA Pro 的 MCP 集成 | GitHub |
| x64dbg MCP | x64dbg 的 MCP 集成 | GitHub |
| angr | 符号执行引擎 | 官网 / 文档 |
| Joern | 代码属性图 (CPG) 框架 | 官网 / 文档 |
| neo4j | 图数据库 | 官网 |
| LangGraph | Agent 编排框架 | GitHub |
| tree-sitter | 增量解析器 | 官网 |
| CodeBLEU | 代码评估指标 | PyPI / GitHub |
Agent 参考项目
| 项目 | 方向 | 链接 |
|---|---|---|
| BUUCTF_Agent | CTF 解题 Agent | GitHub |
| AgentRE-Bench | 逆向工程 Agent Benchmark | 官网 |
| OGhidra | LLM + Ghidra 集成 | GitHub |
| BinAssistMCP | Binary Ninja MCP 集成 | GitHub |
相关视频
| 标题 | 链接 |
|---|---|
| D@wnEdg3 - Cruiser: CTF Agent实现探索 | Bilibili |
| 长亭外 - Superposition: Auto-Pentest Agent Meets CTF Challenge | Bilibili |
本文是 RE-MAS 项目的研究笔记。项目处于设计阶段,欢迎交流讨论。
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时









