二进制代码相似性检测:跨架构的固件与恶意代码分析
二进制代码相似性检测:跨架构的固件与恶意代码分析完全指南
在逆向工程、漏洞挖掘与恶意软件分析领域,二进制代码相似性检测是一项核心技术。它帮助研究人员在海量二进制文件中快速发现同源函数、已知漏洞代码或恶意代码家族的变种。随着物联网(IoT)和嵌入式设备的普及,固件分析所面临的跨架构挑战使得这一技术变得更加关键。本教程将系统性地讲解其原理、主流方法及实践工具,助你从零掌握二进制相似性比对。
一、什么是二进制代码相似性检测
二进制代码相似性检测(Binary Code Similarity Detection)是指在不依赖源代码的情况下,判断两个不同二进制文件中的函数或代码片段是否“相似”,即它们是否由同一段源代码编译而来,或具有功能上的等价性。相似性通常被量化为一组数值(相似度分数),用于进一步决策。
该技术直接服务于以下场景:
- 恶意代码家族聚类:识别变种恶意软件中复用的代码模块
- 固件漏洞关联:在大量固件镜像中定位已知漏洞函数
- 软件抄袭与许可证违规检测:比对第三方库的使用情况
- 补丁分析:定位补丁前后变化的二进制函数
二、跨架构分析为何成为刚需
传统检测方法大多针对同一种指令集架构(如 x86 与 x86),但现实分析中面临巨大的架构异构性:
- 物联网固件:可能包含 ARM、MIPS、PowerPC、RISC-V 等多种架构的二进制
- 恶意软件:常以 x86 Windows 样本为主,但针对 macOS (ARM64)、Android (ARM/ARM64) 的威胁也大幅增长
- 跨平台供应链:同一开源库(如 OpenSSL 或 zlib)会被编译进不同架构的产品中,出现相同漏洞
跨架构二进制相似性检测的目标就是:忽略指令集差异,捕获函数在语义和行为层面的共性。
三、检测方法的核心维度
方法可根据分析粒度、特征提取方式及比对算法分为以下层次:
3.1 基于原始字节与哈希的粗粒度检测
- 文件级哈希(MD5、SHA1):极其脆弱,任何重编译都会改变哈希值
- 模糊哈希(ssdeep、TLSH):将文件切割为块并计算滚动哈希,能够容忍少量字节差异
- 导入表哈希(ImpHash):仅对 PE 文件的导入函数表进行快速哈希,适合 Windows 恶意软件快速筛选
- 富哈希(Rich Header):解析 PE 文件的 Rich Header,获取编译环境信息
这些方法速度快,但无法进行函数级粒度的比对,且跨架构能力几近为零。
3.2 基于控制流图与图匹配的结构检测
在函数层面,控制流图(CFG)是核心数据结构。每个节点代表一个基本块,边表示跳转关系。通过图匹配算法计算两个 CFG 的相似度。
常见做法:
- CFG 抽象:对各基本块进行归一化(如仅保留出度和入度信息)
- 图编辑距离(Graph Edit Distance):计算将一个图转化为另一个图所需的最少编辑代价
- 最大公共子图(Maximum Common Subgraph, MCS):寻找两个图的最大同构部分
- 二分图匹配:将 CFG 匹配转换为节点间的加权二分匹配问题
优势:对编译器优化和寄存器重命名有一定抗性。
局限:完全依赖结构,当编译器进行积极内联、循环展开或跳转优化时,图结构可能剧变;且跨架构时基本块结构本身不同,难以直接比对。
3.3 基于特征码与统计特征的方法
提取函数的多维统计特征以构建数值向量,然后用机器学习或直接距离计算来度量相似性。
- 函数级统计特征:基本块数量、边数量、循环复杂度、节点平均出/入度、指令混合比例等
- 指令 n-gram:将反汇编指令序列切分为 n-gram,统计词频
- 字符串与常量特征:函数中出现的字符串和立即数(如 IP 地址、密码常量)是强语义信号
典型工具如 BinDiff 早期版本即融合了统计图特征。此类方法执行快速,适合大规模初筛,但语义表征能力有限,难以应对复杂混淆。
3.4 基于语义嵌入与深度学习的现代方法(跨架构关键)
为真正实现跨架构检测,近年来研究重心转向 将函数映射到与架构无关的语义向量空间。
- 图神经网络(GNN):不再使用原始 CFG,而是将 CFG 节点的基本块特征作为输入。Node 特征可包含 IR(中间表示)级别的操作码、算术逻辑操作类型及数据流关系。利用图卷积网络生成函数的嵌入向量。
- 基于自然语言处理的指令序列模型(Transformer/GRU):将指令序列视为“句子”,利用预训练模型学习指令语义。再结合 Siamese 网络比较两个函数的嵌入向量相似度。
- 中间语言(IR)转移:将不同架构的二进制先提升到同一中间语言(如 VEX IR — 被 angr 所用、LLVM IR、Ghidra 的 P-Code)。在 IR 层面进行特征提取与比对,消除底层指令集差异。这是目前工程上最稳健的跨架构方案。
代表性系统:Gemini、SAFE、Asm2Vec、INNEREYE、JTrans等。其中 Ghidra 与 BinDiff 的组合 利用 Ghidra 的反编译和 P-Code 生成能力,可实现部分跨架构比对。
四、核心工作流:从二进制到相似度报告
4.1 预处理与反汇编
- 加载文件:识别格式(ELF、PE、Mach-O、固件裸镜像)
- 反汇编:使用线性扫描或递归遍历反汇编器(如 IDA Pro、Ghidra、radare2)
- 函数识别:建立函数边界,处理交叉引用和入口点
- 库函数识别(FLIRT/Sig 匹配):预先过滤掉标准库函数,减少噪音
4.2 中间表示提升与规范化
使用中间语言(IR)转换可以屏蔽架构差异。例如:
- Ghidra/P-Code:将每个指令翻译成由若干 P-Code 操作组成的序列,这些操作遵循统一的寄存器传输语言格式
- angr/VEX:Valgrind 的 VEX IR 被用于二进制分析框架 angr
- Binary Ninja 的 MLIL/HLIL:提供多层中间表示
规范化操作还包括:常量折叠、死代码消除、缩尾跳转合并、间接调用目标解析等。此步骤的质量直接决定了跨架构检测的上限。
4.3 特征提取
根据所选方法,提取结构特征、统计特征或生成语义嵌入向量。
示例:提取图特征向量
- 将每个函数 CFG 提取后,按照节点度数、指令类别构成节点向量
- 使用 Weisfeiler-Lehman 子树核或图同构网络进行图级表示
- 或者,将无序的节点向量取平均或注意力池化,得到固定长度函数嵌入
4.4 相似性搜索与索引
当库规模庞大(数万甚至百万函数)时,暴力两两比较不可行。
- 局部敏感哈希(LSH):将高维向量映射到桶中,仅需比较同一桶中对象
- HNSW 或 FAISS 索引:对嵌入向量建立近似最近邻索引,实现毫秒级检索
- 分层匹配策略:先用轻量特征(如函数哈希、统计向量)快速过滤,再对候选集进行精确图匹配或语义匹配
五、跨架构固件分析实战思路
5.1 固件解析与库函数剥离
固件镜像通常是一个超大二进制块,需先:
- 基址定位与加载:依据压缩头或文件系统元信息确定加载偏移
- 符号恢复:利用公开符号表或字符串引用推测函数名
- 库函数标记:识别 uClibc、glibc 等常用 C 库,大幅缩小分析范围
5.2 建立已知漏洞函数指纹库
收集常见受影响架构(ARM32、ARM64、MIPS32)的漏洞库编译版本。将漏洞函数提升至 P-Code 并提取语义向量,存入检索库。
5.3 大规模扫描与关联
对每个待测固件中的每个函数,提取同类型向量并进行近似最近邻检索。设定阈值(如余弦相似度 ≥ 0.95),产出匹配对。
常见陷阱:
- 内联函数:函数边界消失,需结合函数级和基本块级比对
- 编译器优化差分:同一源码对应 ARM Thumb 和 ARM 全模式生成的代码差异巨大,需在 IR 层尽可能归一化
- 尾调用优化:导致 CFG 中缺少应有的返回边,影响图结构比对
六、恶意代码分析中的变种追踪
6.1 代码复用模式的快速识别
恶意软件作者常复制整个加密模块、通信协议处理函数或反分析代码。通过相似性检测,可以:
- 快速标注函数功能:将已知恶意功能(如键盘记录)的函数匹配到新样本中
- 追踪工具演进:观察不同版本间模块的增删改
6.2 跨 Windows↔Android↔IoT 恶意代码关联
攻击者可能将同一个 RAT(远程访问木马)的核心逻辑分别编译为 x86 Windows 后门、ARM Android APK 原生库以及 MIPS 物联网僵尸程序。借助 IR 提升和语义嵌入,可揭示跨平台的同一家族关系,这在传统字符串或字节匹配中完全不可见。
七、推荐工具栈与环境搭建
| 工具 | 核心能力 | 跨架构支持 |
|---|---|---|
| Ghidra + BinDiff | 完善的反编译器、P-Code 生成、函数匹配 | 良好(通过 P-Code) |
| IDA Pro + BinDiff | 行业标准反汇编器,插件丰富 | 需同一架构匹配,跨架构有限 |
| Binary Ninja + BinExport | 优秀的中级语言 API | 支持多种架构 |
| angr | VEX IR 仿真与分析 | 极佳,纯 IR 层研究利器 |
| JTrans / SAFE / NeuralXC | 学术界的深度学习跨架构检测 | 在特定数据集上效果突出 |
推荐初学者上手路径:Ghidra(免费且内置 P-Code 提升)→ 编写脚本导出函数 CFG 及 P-Code 序列 → 使用 Python 实现基于结构特征的比对,逐步过渡到集成 GNN(如 PyTorch Geometric)进行函数嵌入训练。
八、评估指标与数据集
进行方法验证时,常用如下公开数据集:
- Dataset-1 (binarycorp):涵盖 ARM, MIPS, x86 的多个开源项目编译版本
- IoT 漏洞库:从 CVE 对应补丁提取受影响函数
- Android Native 恶意库集合:包括 Cerberus, Anubis 等家族的 ARM 变种
推荐指标:
- Recall@K:返回的前 K 个结果中包含至少一个真正匹配的比例
- AUC 与 MRR(平均倒数排名)
- 特别关注 跨架构测试子集(训练用 x86 + ARM,测试用 MIPS)评估泛化能力
九、总结与进阶方向
二进制代码相似性检测已经走过从简单字节匹配到语义嵌入的阶段。跨架构固件与恶意代码分析的关键在于抢占中间表示层,并利用数据驱动的机器学习方法捕捉不变语义。
进阶研究与实践方向包括:
- 对抗性鲁棒性:针对插入死代码、花指令、控制流平坦化的抗混淆能力
- 增量索引更新:每日新增大量固件,如何高效添加而不重训全部嵌入
- 函数内联与多函数协同匹配:不止匹配单个函数,考虑函数间调用关系作团伙识别
掌握本指南所讲解的基础原理与工作流,你已具备构建一套面向实际分析的跨架构二进制相似性检测系统的能力。立即动手,用 Ghidra 脚本导出你的第一个 P-Code 特征库,开启相似性狩猎之旅。