想象一下,你在服务器上发现了一个旧的可执行文件。它是你公司遗留软件的关键部分,但有一个问题: 源代码丢失了。没有 GitHub 仓库,没有备份的压缩包。只有原始的二进制文件。
要更新或修复这个软件,你需要执行反编译——这是一个将编译步骤逆转,把机器代码转换回人类可读的编程语言 (如 C 语言) 的过程。几十年来,这一直是 Ghidra 或 IDA Pro 等专业工具的领域。虽然这些工具很强大,但它们的输出往往看起来更像是一个数学谜题,而不是清晰的代码。
LLM4Decompile 应运而生。在最近的一篇论文中,来自南方科技大学和香港理工大学的研究人员推出了首个专门用于反编译二进制代码的开源大型语言模型 (LLM) 系列。这些模型的参数范围从 13 亿到 330 亿不等,它们不仅仅是猜测代码,而是经过训练以生成可重新执行的源代码。
在这篇文章中,我们将剖析 LLM4Decompile 的工作原理,传统方法为何举步维艰,以及这种新方法如何在这个特定领域超越 GPT-4o 等巨头。
反编译的难题
要理解为什么需要 LLM4Decompile,我们首先需要看看为什么反编译如此困难。
当你编译 C 代码时,编译器 (如 GCC) 会经历几个激进的步骤:
- 预处理: 展开宏并删除注释。
- 编译: 将 C 语言转换为汇编语言 (ASM) 。
- 汇编: 将汇编语言转换为二进制 (0 和 1) 。
- 链接: 连接函数以创建最终的可执行文件。
在这个过程中,大量信息丢失了。变量名被丢弃,高级结构 (如 for 循环) 被扁平化为 jmp (跳转) 指令,数据类型被转换为原始的内存偏移量。
从二进制恢复原始 C 代码就像试图从汉堡还原出一整头牛。你可能会猜到大概的成分,但要恢复原始结构极其困难。
传统方法与现实
像 Ghidra 这样的工具试图通过分析二进制文件的控制流图来逆转这一过程。它们寻找类似于循环或 if 语句的模式。

如图 1 所示,结果往往喜忧参半。
- 左上: 原始源代码是一个带有嵌套循环的清晰 C 函数。
- 右下: Ghidra 的输出捕捉到了逻辑,但用
while(true)和do-while结构替换了标准循环。它丢失了变量名 (称之为param_1、local_28) ,并使用了人类难以解析的指针运算。
关键是,Ghidra 的输出通常是伪代码 。 由于语法错误、未定义类型 (如 undefined4) 和缺少头文件,它通常无法重新编译。这使得它对分析很有用,但在重建软件时却很糟糕。
解决方案: LLM4Decompile
研究人员提出,擅长翻译任务 (例如法语到英语) 的 LLM 可以被视为二进制到代码的翻译器 。 他们介绍了两种解决此问题的独特方法:
- 端到端反编译: 直接将汇编语言翻译成 C 语言。
- 精细化反编译: 使用 LLM 来“修复” Ghidra 混乱的输出。
让我们探索这两种方法的架构。
1. 端到端方法 (LLM4Decompile-End)
“端到端” (End2End) 方法将汇编语言 (ASM) 视为源语言,将 C 代码视为目标语言。

如图 2 所示,这个过程概念简单但执行复杂:
- 系统获取二进制文件 (Binary) 。
- 它使用像
objdump这样的工具将二进制文件反汇编 (Disassemble) 为汇编指令 (ASM) 。 - LLM4Decompile 模型将此 ASM 文本作为输入,并预测原始源代码 (SRC’) 。
- 在训练期间,模型将其预测与原始源代码进行比较,以计算损失并进行学习。
秘诀: 数据增强与两阶段训练 你不能简单地在随机的 GitHub 代码上训练模型。为了使模型具有鲁棒性,研究人员使用编译优化作为一种数据增强形式。
开发人员在不同的优化级别编译代码 (O0 为无优化,最高到 O3 为激进优化) 。研究人员在 O0、O1、O2 和 O3 级别编译了数百万个 C 函数。这教会了模型: 看起来截然不同的汇编代码可以映射回同一个 C 源代码。
他们还采用了两阶段训练策略:
- 第一阶段: 可编译数据: 他们在 70 亿 token 的“可编译”代码 (未完全链接的目标文件) 上进行训练。这给了模型大量的通用 C 语言知识。
- 第二阶段: 可执行数据: 他们在“可执行”二进制文件 (完全链接) 上进行了微调。
为什么要区分这两者?

图 6 强调了细微但关键的差异。在“可编译”目标文件 (左) 中,跳转地址是相对偏移量。在“可执行”文件 (右) 中,链接器已将这些偏移量替换为特定的内存地址 (例如 jmp 11f1) 。通过在这两种数据上进行训练,模型学会了无论内存寻址如何都能理解代码逻辑。
2. 精细化方法 (LLM4Decompile-Ref)
第二种方法承认,像 Ghidra 这样的工具实际上非常擅长恢复通用逻辑,即使语法很难看。

在精细化反编译框架( 图 3 )中,工作流程略有变化:
- 二进制文件首先通过 Ghidra 。
- Ghidra 生成混乱的伪代码。
- LLM4Decompile-Ref 模型将该伪代码作为输入,充当代码润色器,将其重写为有效、可读的 C 代码。
这种方法利用了两全其美的优势: Ghidra 强大的结构分析能力和 LLM 编写清晰语法的能力。
实验与结果
为了测试这些模型,研究人员不仅仅检查代码是否“看起来”正确。他们使用了一个严格的指标,称为可重新执行性 (Re-executability) 。
什么是可重新执行性?
- 获取 LLM 生成的反编译代码。
- 尝试使用 GCC 编译它。
- 针对测试用例和断言运行生成的可执行文件。
- 如果它能编译通过并能通过测试,才算成功。
这是一个非常高的标准。哪怕是一个拼写错误或逻辑错误都会导致失败。
端到端性能
研究人员在 HumanEval-Decompile (标准编码问题) 和 ExeBench (现实世界函数) 上测试了他们的模型。

表 1 揭示了一些令人印象深刻的发现:
- LLM4Decompile-End-6.7B 在 HumanEval 上达到了 45.37% 的平均成功率。
- GPT-4o , 通常被认为是通用编码领域的最新技术,仅达到 16.01% 。
- DeepSeek-Coder , 微调前的基座模型,得分为 0%——它完全不懂如何在没有经过特定训练的情况下处理二进制汇编代码。
注意随着优化级别增加 (O0 到 O3) ,性能会有所下降。高度优化 (O3) 的代码会产生与原始源代码大相径庭的汇编代码,使得反编译更加困难。
精细化的力量
加入 Ghidra 有帮助吗?绝对有。

看表 3 , 精细化方法占据主导地位:
- 仅 Ghidra 的可重新执行率约为 20% 。 它经常生成数学上正确的逻辑,但语法错误阻碍了编译。
- Ghidra + GPT-4o 将此提高到了 35% 。
- Ghidra + LLM4Decompile-Ref-6.7B 达到了 52.74% 。
这表明,当针对清理反编译器输出这一特定任务进行微调时,一个专门的小型模型 (6.7B) 可以超越庞大的通用模型 (GPT-4o) 。
代码可视化
数字虽好,但代码实际上是什么样子的呢?

图 4 提供了一个引人入胜的并排比较:
- 源代码 (左上) : 基本事实。
- Ghidra (左中) : 使用了
local_24、local_28和混乱的while(true)循环。难以阅读。 - GPT-4o (左下) : 它生成了非常干净的代码,但它产生了幻觉 。 注意它创建了一个原始代码中不存在的二维数组
arr[outer][inner]。这使得代码虽然可读,但在功能上是错误的。 - LLM4Decompile (右上) : 它几乎完美地恢复了逻辑和结构,保持了一维数组的语义,同时使用了可读的 C 语法。
为什么它仍然会失败?
虽然 50% 的可重新执行率是一个巨大的飞跃,但它并不是 100%。研究人员分析了模型在哪些方面表现挣扎。
1. 输入长度

如图 7 所示,随着汇编代码变长,性能会下降。6.7B 模型 (下图) 比 1.3B 模型 (上图) 更鲁棒,但当输入序列超过 400 个 token 时,即使是较大的模型也会表现挣扎。这是 LLM 的一个常见限制——在长序列中保持上下文是很困难的。
2. 错误类型

图 8 分解了失败原因。
- HumanEval (左) : 大多数失败是“断言 (Assert) ”错误。代码可以编译,但逻辑略有偏差,导致无法通过测试用例。
- ExeBench (右) : 主要问题是“声明 (Declare) ”和“结构体 (Struct) ”。ExeBench 使用带有自定义数据结构 (如
struct MyObject) 的现实世界代码。当代码被编译时,结构体定义被抹去了。LLM 很难“臆造”出正确的结构体定义,导致编译错误。
道德问题: 这危险吗?
一个可以完美逆向工程二进制文件的工具听起来像是开发人员恢复丢失代码的梦想,但也是安全的噩梦。恶意软件作者会用它来研究补丁吗?盗版者会用它来破解软件吗?
为了解决这个问题,研究人员针对混淆代码测试了 LLM4Decompile。开发人员经常使用“控制流扁平化”等技术故意扰乱二进制文件的逻辑,以防止逆向工程。
结果令人安心的糟糕。当在混淆的二进制文件上测试时,可重新执行率下降了 70% 以上。这些模型依赖于标准的编译器模式;当这些模式因混淆而被故意破坏时,LLM 就像人类一样会感到困惑。这表明该工具对合法的恢复任务有效,但具有天然的局限性,可以防止轻易被滥用于受保护的软件。
结论
LLM4Decompile 代表了将人工智能应用于底层系统编程的一个重要里程碑。通过将二进制代码视为另一种需要翻译的语言,研究人员创造了一种在生成可执行、可读代码方面显著优于传统反编译器的工具。
给学生和研究人员的关键要点:
- 领域专精致胜: 针对反编译进行微调的 60 亿参数模型击败了 GPT-4o。
- 混合方法行之有效: 最好的结果来自于将传统工具 (Ghidra) 与 AI 优化相结合。
- 现实世界的限制: 处理用户定义类型 (结构体) 和长上下文仍然是该技术的下一个前沿。
6.7B 和 33B 模型是开源的,这为未来铺平了道路,在那时,丢失源代码可能只不过是一个小麻烦。
](https://deep-paper.org/en/paper/2403.05286/images/cover.png)