22.8万函数,AI开始啃反编译

asmsense 开源 22.8 万条 stripped x86-64 函数数据,并用 Qwen3-8B LoRA 自动生成函数名和描述。它离实用工具仍有距离,但补上了二进制分析领域最稀缺的一块训练基础设施。
22.8万函数,AI开始啃反编译
近日,开源项目 asmsense 发布了一套面向二进制逆向分析的数据集与小模型:数据集包含 228,177 条 stripped x86-64 函数样本,模型则以 Qwen3-8B 为底座,通过 LoRA 微调,根据反汇编函数预测原始函数名,并生成英语和土耳其语的一句话功能描述。
这不是一个已经能替代逆向工程师的“自动反编译神器”,而是一套把问题、数据、基线和缺口同时摆到桌面上的研究基础设施。它最有价值的部分并非 8B 模型给出了多漂亮的函数名,而是开发者自行编译了 341 个宽松许可证的 C 项目,使每段机器码都能追溯到真实源码和原始符号,从而建立较可靠的监督信号。

asmsense 到底发布了什么
**asmsense 是一个用于给 stripped binary 中的函数自动命名和生成描述的开放数据集与模型项目。**所谓 stripped binary,是指经过符号剥离的二进制文件,其中原本供链接器和调试器使用的函数名、变量名等符号信息已被移除;逆向人员打开这类文件时,往往只能看到 sub_100012340 一类占位名称。
函数命名是逆向分析中耗时很高、又极度依赖上下文的工作。一个函数究竟应该叫 parse_http_header、resize_buffer 还是 verify_signature,不能只看它是否调用了 malloc 或执行了一个循环,还要综合控制流、常量、字符串、被调用函数、参数使用方式以及它在整个程序中的位置。
asmsense 当前公开的 v4 数据集包含 228,177 行数据,覆盖 341 个项目和 5 个编译优化级别。按照项目披露的划分,训练集、验证集和测试集严格按项目拆分,而不是随机拆散同一项目内的函数,这一点尤其重要:如果同一个项目的高度相似函数同时进入训练集和测试集,模型成绩很容易被重复代码和项目风格抬高。
| 数据划分 | 项目数 | 样本行数 | 唯一源码函数数 | 说明 | |---|---:|---:|---:|---| | 训练集 | 290 | 196,117 | 72,179 | 用于模型训练 | | 验证集 | 23 | 19,770 | 6,667 | 用于调参与模型选择 | | 测试集 | 28 | 12,290 | 4,685 | 选取 2024 年后、GitHub 星标不超过 200 的较冷门项目 | | 合计 | 341 | 228,177 | 83,531 | 同一源码函数可能对应多个优化版本 |
**项目级切分是这套数据集可信度较高的设计之一。**测试集专门选择较新、关注度较低的项目,是为了降低基础模型在预训练阶段见过源码的概率;这不能彻底排除数据污染,却比从热门开源项目中随机抽函数更接近真实泛化测试。
**多优化级别样本用于刻画同一份源码在不同编译策略下的机器码变化。**在低优化级别下,局部变量、分支结构和函数边界通常更接近源码;到了 -O2、-O3 或面向体积的 -Os,内联、常量折叠、循环展开、死代码消除等优化会明显改变指令形态。同一个源码函数因此可能产生多条样本,这也是 228,177 行数据明显多于 83,531 个唯一源码函数的原因。
真正稀缺的是“机器码到源码”的配对
**二进制模型训练的核心瓶颈不是底座模型,而是带真实语义标签的配对数据。**互联网公开源码很多,公开二进制也很多,但同时具备源码、编译配置、未剥离符号和剥离后函数内容的数据并不常见;如果直接抓取现实世界中的固件或程序,研究者通常无法知道 sub_401720 原来叫什么,更无法自动判断模型答案是否正确。
asmsense 采取的是“自己编译、自己剥离、自己对齐”的路线。项目从宽松许可证的 C 工程出发,在保留源码和原始函数名的条件下完成编译,再生成剥离符号后的函数表示;训练时给模型看剥离后的信息,监督标签则来自剥离前的真实名称与源码。这套流程的优势是标签可追溯,数据也能重新生成,而不是依赖另一个大模型批量猜测函数含义。
**source-aware label 是由源码和编译产物对齐得到的标签,而不是人工逐条审阅后的金标准。**这个区别不能忽略:真实函数名虽然比合成标签可靠,但源码名称本身未必清晰,do_work、handle、process_item 这类名字并不能完整表达语义;宏展开、静态函数重名、编译器生成函数和函数内联也可能给对齐过程带来噪声。
项目披露的编译漏斗同样揭示了数据偏差。候选范围涉及 473 个项目,其中 352 个成功生成过数据,另有 120 个因内核代码、嵌入式依赖或平台相关问题编译失败;公开 v4 划分最终覆盖 341 个项目。成功编译的工程天然更偏向用户态、依赖简单、能够在 macOS 环境下由 clang 构建的 C 项目,因此这 22.8 万条函数并不能代表整个原生软件世界。
Qwen3-8B LoRA 的成绩还只是起点
**LoRA 是一种只训练少量低秩适配参数、保留基础模型主体权重的参数高效微调方法。**asmsense 没有从零训练二进制专用模型,而是选择 Qwen3-8B 作为语言底座,再用领域数据训练 LoRA 适配器;这种方案降低了训练与分发门槛,也保留了 Qwen3 原有的语言生成能力。
模型的任务不只是输出一个标识符。当前方案会先生成一句功能描述,再预测函数名,同时提供英语和土耳其语描述;项目还计划加入中文描述。先描述、后命名的思路类似让模型先做语义归纳,再把归纳结果压缩成符合程序员习惯的标识符,理论上比直接猜一个名字更容易形成稳定监督。
**现有结果表明,8B 模型已经学到信号,但远未达到可以无条件采信的程度。**项目给出的最佳小模型是基于 v5 数据训练的 Qwen3-8B LoRA,它在固定 v4 测试样本上的 name F1 为 0.124,在另一组 eval_115 评测上的 name F1 为 0.155;带调用上下文的最佳大模型在同一固定测试样本上达到 0.167。
| 方案 | 输入或训练特征 | 评测集 | Name F1 | 相对 Qwen3-8B LoRA |
|---|---|---|---:|---:|
| Qwen3-8B + LoRA | v5 数据,先描述后命名 | 固定 v4 测试样本 | 0.124 | 基准 |
| Qwen3-8B + LoRA | 同一模型 | eval_115 | 0.155 | 不宜跨评测集直接比较 |
| 最佳大模型 | 加入调用上下文 | 固定 v4 测试样本 | 0.167 | 绝对增加 0.043,约高 34.7% |
**Name F1 是对预测名称与真实名称进行分词后计算的精确率和召回率调和平均值,而不是函数完全命中的准确率。**例如真实名称是 parse_http_header,模型输出 parse_header 时仍可能获得部分分数;因此 0.124 不能简单解释成“12.4% 的函数被正确命名”,更不能等同于 12.4% 的 exact match。
这个指标一方面比完全匹配更适合处理近义名称,另一方面也容易被策略性输出利用。如果模型频繁使用 get、set、parse、buffer 等高频词,即使完整语义不对,也可能积累部分 token 分数;而 copy_bytes 与 memcpy_wrapper 可能语义接近,却因词面差异拿不到理想得分。
**0.124 到 0.167 的结果说明调用上下文比单个函数体更重要,但模型规模并没有自动解决语义恢复问题。**一个只看到当前函数汇编的模型,很难判断返回整数 0 究竟表示解析成功、锁获取成功还是校验通过;如果同时看到它调用了哪些函数、被谁调用、引用了哪些字符串和全局对象,命名范围会迅速缩小。
为什么这件事比跑分更值得关注
**asmsense 的现实价值是为逆向工程提供候选名称,而不是宣称恢复原始源码。**函数名本身没有唯一答案:同一段逻辑可以被作者命名为 read_config、load_settings 或 parse_options,模型给出的名字只要能帮助分析人员定位职责,就可能节省时间。
在 Ghidra 一类逆向工具中,比较合理的产品形态是让模型批量生成低置信度建议,再由分析人员确认、修改或拒绝。项目已经准备了 Ghidra 脚本,这使研究结果有机会进入实际工作流;但在恶意软件分析、漏洞研究和固件审计中,错误命名会制造先入为主的判断,因此界面必须保留来源、置信度和原始反汇编,不能把模型输出伪装成事实。
**这套数据尤其适合研究“编译不变语义”。**如果训练和评估能保证同一源码函数的不同优化版本不会跨集合泄漏,模型就必须学习控制流与数据流中的稳定信号,而不是记住某一段固定指令序列;反过来,如果不同优化版本被错误分散到训练集和测试集,结果就会虚高。
asmsense 也提供了一个可扩展的数据生产模板。研究者可以在相同源码上切换编译器、优化级别、目标架构和链接方式,构造 clang 对 GCC、Mach-O 对 ELF、x86-64 对 ARM64 的受控实验;这种“同源多编译视图”比单纯扩大抓取规模更有研究价值,因为它能准确回答模型究竟是在识别语义,还是在识别工具链指纹。
当前短板很明确
**asmsense 当前最大的限制是数据域过窄。**现有数据全部来自 macOS 上的 clang/Mach-O 构建,目标架构是 x86-64,而现实中的服务器逆向更常见 GCC/ELF,移动端与苹果新设备大量使用 ARM64,路由器和物联网固件还会遇到 MIPS、RISC-V 等架构。
| 维度 | 当前覆盖 | 尚缺数据 | 影响 |
|---|---|---|---|
| 指令架构 | x86-64 | ARM64、RISC-V、MIPS | 无法验证跨架构泛化 |
| 编译器与格式 | clang、Mach-O | GCC、ELF 等 | 容易学习特定工具链特征 |
| 描述语言 | 英语、土耳其语 | 中文 | 中文逆向工作流尚未覆盖 |
| 标签质量 | 源码自动对齐 | 人工核验标签 | 难以量化命名噪声 |
| 上下文 | 以单函数任务为主 | 完整调用图与代理轨迹 | 难以处理跨函数语义 |
| 公共评测 | 自建固定测试集与 eval_115 | BinMetric、REBench、BinSum、DeBinVul | 暂时难与既有工作横向比较 |
**缺少公共基准结果是目前最影响外部判断的问题。**在 BinMetric、REBench、BinSum 和 DeBinVul 等公开任务上完成评测之前,0.124 或 0.167 只能说明模型在项目自己的数据和指标下达到了某个水平,不能直接证明它优于已有二进制表示模型、反编译模型或通用大模型。
**缺少人工复核则限制了描述生成质量的可信度。**函数名能够通过源码符号自动获得,但一句话描述未必存在天然标准答案;如果描述由规则、源码上下文或其他模型生成,就需要公开生成方法并抽样审计,否则模型可能学会复述名称,而不是解释行为。
此外,C 项目也只是二进制生态的一部分。C++ 的名称修饰、模板和异常处理会带来完全不同的结构,Rust 与 Go 会引入更明显的运行时模式,闭源商业软件又有自定义框架、混淆和链接时优化;这些场景才是自动命名工具真正需要面对的压力测试。
把流水线做成 RL 环境,方向对但奖励难设计
**asmsense 作者正在考虑把“编译、剥离、命名、评分”流水线改造成强化学习环境。**环境可以自动选择源码函数完成编译和符号剥离,让模型预测名称,再依据真实名称计算 token-level F1 奖励;优点是任务能够持续生成,训练闭环也不依赖昂贵的人工逐条打分。
**单独使用 token-level F1 作为奖励很容易被模型钻空子。**模型可能倾向于输出覆盖率高的通用词,或者把多个候选词拼成冗长名称,以提高与真实名称发生局部重合的概率;这种输出会得到更高奖励,却不一定更适合逆向工程师阅读。
更合理的奖励应同时衡量名称相似度、描述语义、简洁度和跨编译一致性。比如,同一源码函数经过 clang 与 GCC、-O0 与 -O3 编译后,模型应给出语义一致的名称;对于行为相近但实现不同的函数,描述也应保持可区分性。人工偏好抽样仍然必要,因为“是否有助于分析”最终是一个面向人的评价。
代理轨迹也是值得补齐的数据。真实逆向人员不会只盯着一个函数体,而会先查看字符串,再追踪调用者和被调用者,检查交叉引用,最后回到函数进行命名;记录这条工具使用轨迹,才能训练出会主动查证的二进制分析代理,而不是只会对一段汇编做单轮猜测的文本模型。
结论:数据集比模型更重要
**asmsense 目前更像一个扎实的研究起点,而不是成熟的逆向产品。**Qwen3-8B LoRA 的 name F1 仍然偏低,平台覆盖也集中在 clang、Mach-O 和 x86-64,任何实际部署都应把结果视为候选提示,而非可信标签。
**这次发布真正补上的,是二进制函数语义学习所需的可追溯开放数据。**228,177 条样本、341 个项目、5 个优化级别以及项目级测试划分,为后续研究提供了可复现底座;更重要的是,团队没有只展示最好看的分数,而是明确列出了 ARM64、RISC-V、MIPS、GCC/ELF、中文、人审标签、代理轨迹和公共基准等缺口。
对于开发者和研究者而言,短期内最值得关注的不是模型能否一次猜中原始函数名,而是它能否稳定生成有用、可验证、跨编译器一致的语义提示。只要这一点成立,即使预测名称与作者原名不同,模型依然可能明显减少人工阅读汇编的时间;如果这一点不成立,再高的 token F1 也只是指标游戏。
参考来源
- asmsense GitHub 仓库:项目代码、数据生成流程、实验结果和后续数据规划。
- Hugging Face 上的 asmsense Qwen3-8B LoRA:项目发布的 Qwen3-8B LoRA 适配器页面。
- Reddit:asmsense 228k 数据集发布讨论:作者对数据规模、语言覆盖、缺失架构和强化学习设想的说明。
- Reddit:逆向工程社区发布帖:面向逆向工程用户的任务介绍与应用讨论。



