1. 论文背景与研究意义
二进制代码相似性分析(Binary Code Similarity Analysis, BCSA)是当前网络安全和软件工程领域的重要研究方向。这项技术通过比较不同二进制文件之间的相似度,在恶意软件检测、漏洞挖掘、软件成分分析等场景中发挥着关键作用。
传统BCSA方法主要分为两类:函数级分析和程序级分析。函数级BCSA通过逐个比较二进制文件中的函数来判断相似性,这种方法虽然精确,但时间复杂度高达O(nm³),其中n是文件比较次数,m是单个文件的函数数量。当面对海量二进制文件时,这种方法的计算开销变得难以承受。
腾讯安全实验室与上海科技大学联合提出的KEENHash方法,创新性地利用大语言模型(LLM)生成函数嵌入向量,将整个二进制文件压缩为一个固定长度的紧凑表示。这种方法不仅大幅提升了分析效率,还保持了较高的准确率,已经在腾讯BinaryAI平台实现规模化应用。
2. 关键技术解析
2.1 函数提取与预处理
KEENHash的第一步是从二进制文件中提取函数信息。与传统方法直接处理汇编代码不同,KEENHash选择使用Ghidra逆向工具将二进制代码反编译为类C伪代码。这种中间表示具有两大优势:
- 架构无关性:屏蔽了不同CPU架构(如x86、ARM)的指令集差异
- 高级抽象:更接近源代码的表示形式,便于后续的语义分析
在模型训练阶段,研究人员构建了一个包含源函数和伪函数的匹配数据集:
- 源函数:从GitHub开源C/C++项目中提取,使用Tree-Sitter解析器处理
- 伪函数:通过编译源项目生成二进制文件后反编译获得
- 关联匹配:利用调试信息建立源函数与伪函数的1-n映射关系
提示:这种"源代码-二进制"的配对数据集构建是KEENHash的创新之一,为后续的对比学习提供了高质量的监督信号。
2.2 函数嵌入模型设计
KEENHash的核心是函数嵌入模型,它需要将语义相似的函数映射到向量空间中相近的位置。论文采用了基于Pythia-410M(4.1亿参数)的Transformer模型,通过对比学习进行微调。
对比学习的核心思想是:
- 正样本:匹配的源函数-伪函数对
- 负样本:不匹配的随机组合
- 目标:最大化正样本相似度,最小化负样本相似度
具体实现采用了CLIP(Contrastive Language-Image Pretraining)的损失函数:
code复制L = -1/2N [∑log(exp(x_i·y_i/τ)/∑exp(x_i·y_j/τ)) + ∑log(exp(y_i·x_i/τ)/∑exp(y_i·x_j/τ))]
其中x_i和y_j分别是归一化的源函数和伪函数嵌入,τ是可学习的温度参数。
这种对称式损失设计确保了嵌入空间的双向一致性,即:
- 给定源函数,能找到最匹配的伪函数
- 给定伪函数,也能找回对应的源函数
2.3 程序级哈希生成
基于函数嵌入,KEENHash提出了两种程序级哈希方法:
2.3.1 结构哈希(KEENHash-stru)
这种方法将函数相似性判断转化为分类问题:
- 对海量源函数嵌入进行K-Means聚类,得到n个聚类中心
- 对目标二进制文件的每个伪函数,找到最近的聚类中心
- 使用特征哈希将高维分类结果压缩为紧凑的位向量
关键技术点:
- 聚类数量n设置为2^k形式,通过实验确定最优值
- 采用特征哈希(Feature Hashing)解决维度爆炸问题
- 最终使用Jaccard相似度比较位向量
2.3.2 语义哈希(KEENHash-sem)
这种方法更关注函数的语义重要性,通过加权聚合生成程序表示:
code复制e_prog = (∑w_i * e_i^p) / ||∑w_i * e_i^p||_2
其中权重w_i由函数的两大特征决定:
- 代码行数(LoC):反映函数复杂度
- 字符串数量(NoS):指示I/O相关操作
权重计算公式:
code复制w_i = (LoC_i)^0.4/5 + (NoS_i)^0.45/1
实验表明,这种基于代码统计量的权重设计,优于基于调用图或API使用情况的其他方案。
3. 系统实现与优化
3.1 大规模向量搜索
KEENHash在实际部署中面临的主要挑战是如何高效处理海量向量数据。论文采用了Milvus和Faiss等专用向量数据库,它们提供了以下关键能力:
- 近似最近邻搜索(ANN):牺牲少量精度换取查询速度的指数级提升
- 量化压缩:将浮点向量转换为紧凑格式,减少存储开销
- 分布式处理:支持水平扩展以应对数据量增长
在腾讯BinaryAI的实际应用中,系统需要处理超过10亿级别的函数向量,响应时间要求通常在毫秒级别。通过合理的索引设计和资源分配,KEENHash成功满足了这些严苛的生产要求。
3.2 参数调优经验
在模型训练和哈希生成过程中,几个关键参数需要特别注意:
-
聚类数量n:在KEENHash-stru中,n直接影响分类粒度。实验发现n=2^16是一个较好的平衡点,既能保持区分度,又不至于过度消耗计算资源。
-
哈希长度m:特征哈希的输出维度需要在效率和效果间权衡。论文推荐m=2^16(即8KB),这个大小既方便存储,又能有效避免哈希冲突。
-
温度参数τ:在对比学习中,τ控制着softmax的"锐度"。经过网格搜索,最终设定τ=0.05,这个值能使相似度分布保持适当的区分性。
4. 应用场景与效果评估
4.1 典型应用场景
KEENHash在以下场景中展现出显著价值:
- 恶意软件检测:快速识别变种恶意软件,即使它们经过混淆或打包处理
- 漏洞挖掘:通过比对补丁前后版本,定位关键修改点
- 软件成分分析:识别第三方库使用情况,评估许可证合规风险
- 代码溯源:追踪二进制文件的原始开发者和编译环境
4.2 性能评估
论文在三个标准数据集上进行了全面评估:
-
跨编译器检测:识别同一源码不同编译器生成的二进制文件
- 准确率:KEENHash-sem达到94.3%,优于传统方法20%以上
-
漏洞搜索:在已知漏洞数据库中检索相似二进制文件
- 查全率:Top-100命中率达到89%,远超基于签名的方案
-
规模测试:处理100万个二进制文件(约2TB数据)
- 查询延迟:平均15ms/query,满足实时性要求
- 内存占用:约500GB,可通过分布式部署进一步优化
5. 实践建议与常见问题
5.1 部署实施建议
对于希望应用KEENHash技术的团队,我们建议:
-
硬件配置:
- GPU:至少配备NVIDIA V100或同等算力
- 内存:建议64GB以上
- 存储:NVMe SSD可显著提升向量检索速度
-
软件栈选择:
- 向量数据库:Milvus或Faiss
- 深度学习框架:PyTorch
- 逆向工具:Ghidra(支持插件扩展)
-
流程优化:
- 预处理阶段批量处理二进制文件
- 建立定期更新的函数向量库
- 实现增量更新机制,避免全量重建
5.2 常见问题排查
在实际使用中,可能会遇到以下典型问题:
-
反编译失败:
- 原因:加壳或混淆处理
- 解决方案:先进行脱壳处理,或尝试其他反编译器
-
相似度波动:
- 原因:编译器优化级别差异
- 解决方案:调整权重参数,增强语义特征
-
性能下降:
- 原因:向量库规模增长
- 解决方案:重建索引或增加分片
6. 未来发展方向
尽管KEENHash已经取得了显著成果,但仍有一些值得探索的方向:
- 轻量化版本:针对边缘设备或移动端场景,开发精简模型
- 多语言支持:扩展对Rust、Go等新兴语言的支持
- 时序分析:结合版本演变历史,提升变更追踪能力
- 自动化调参:利用元学习技术优化超参数选择
从实际应用角度看,如何将这套重型系统拆解为可独立使用的组件模块,可能是加速技术落地的关键。例如,单独的函数嵌入模型就可以支持许多轻量级应用场景,而不必部署完整的程序级分析流水线。