聚合国内IT技术精华文章,分享IT技术精华,帮助IT从业人士成长

SANER'22:跨编程语言的源代码-二进制代码匹配

2022-09-08 12:10 浏览: 1305808 次 我要评论(0 条) 字号:

随着计算机软件在当今信息社会中的普及,软件的安全和版权保护问题愈来愈受到人们的重视。二进制代码是应用软件的重要发布形式之一,因而二进制代码和源代码匹配在应对这两个问题中发挥着重要作用,例如使用源代码来搜索已发布软件中的漏洞、对二进制代码进行溯源以检查其是否违背开源协议。目前,一些方法已经被提出来用于解决二进制代码和源代码匹配问题,这些方法通常是通过某些相似性约束来共同学习二者的嵌入(Embedding)向量表示实现的。

尽管现有的研究付出了很多努力,但其目标一般是匹配以单一编程语言编写的二进制代码和源代码。但在实践中,软件应用程序通常以不同的编程语言编写,以满足不同的需求和计算平台,而跨编程语言匹配二进制代码和源代码就带来了额外挑战。为此,该论文提出了问题,即“跨语言二进制代码和源代码匹配”,并针对这一问题生成了新的数据集。同时,该论文提出了一种新方法“XLIR”,它基于在自然语言处理领域广泛应用的神经网络Transformer,实现了一种用于二进制代码和源代码的编码器,并使用二进制代码和源代码的LLVM架构中间表示(LLVM Intermediate Representations,LLVM-IR)作为输入,在不同的数据集上对编码器进行预训练和调优训练。在调优训练中,该方法使用三元组损失函数(Triplet Loss,TL)对编码器进行约束训练,使匹配对的嵌入向量的相似度尽可能高,同时使非匹配对的嵌入向量的相似度尽可能低,从而可以在代码匹配阶段根据嵌入向量的相似度得分来判断是否匹配。

为了验证模型XLIR的有效性,该研究在生成的数据集之上,对跨语言、单语言的二进制代码-源代码匹配,以及跨语言源代码匹配三个任务进行了综合性的实验。实验结果显示,该论文提出的基于中间表示的XLIR在所有三个任务中的精度、召回率和F1分数都显著优于其它最新的方法。

该成果"Cross-Language Binary-Source Code Matching with Intermediate Representations"在2021年12月被29th edition of the IEEE International Conference on Software Analysis, Evolution and Reengineering (SANER 2022)录用,该会议是中国计算机协会认定的B类国际会议,在国外的CORE Ranking为A。

  • 论文链接:

    https://ieeexplore.ieee.org/document/9825768


背景与动机

源代码-二进制代码匹配,通过衡量源代码和二进制代码之间的相似性来匹配源代码和二进制代码,在很多软件安全和软件版权保护相关任务中发挥着重要作用,例如恶意软件检测、漏洞搜索和逆向工程。一方面,给定一个二进制代码片段,检索出相关的源代码片段对逆向工程很好的参考作用;另一方面,给定易受攻击的源代码,检查其是否包含在其它二进制文件中对于漏洞评估和检测很有意义。

据我们所知,当前大多数工作主要聚焦于单一模态内的代码匹配,例如源代码-源代码匹配或二进制代码-二进制代码匹配,也有一些研究工作在尝试处理源代码-二进制代码匹配问题。尽管这些工作都取得了很大进展,但所有当前的工作都是针对单一的编程语言开发的,用于匹配同一编程语言的源代码和二进制代码,而处理以不同编程语言的源代码-二进制代码匹配在之前的研究中几乎没有进展。在实践中,软件应用程序通常以不同的编程语言编写,以适应不同的平台。因此,跨多种编程语言的源代码-二进制代码匹配在实际场景中很有用。例如,当我们发现一个易受攻击的二进制代码时,有必要检索所有可能编写它们的编程语言的相关源代码片段,以便更好地评估和防范漏洞。为了填补这一研究空白,我们首次提出了跨语言源代码-二进制代码匹配问题。

源代码-二进制代码问题匹配的关键挑战是弥合高级编程语言和低级机器代码之间的语义鸿沟,当前的方法主要旨在以端到端的方式对齐二进制代码和源代码的语义嵌入(Embedding)。在编译系统中,中间表示(Intermediate Representations,IR)旨在支持多种前端编程语言(例如C、Rust和 Java)和多种后端架构(例如ARM和MIPS),通常独立于编程语言和目标平台结构,通过共享相似的词汇表和语法结构,可以显著地减少不同代码之间的差异。下图体现了源代码和二进制代码这两种模态的代码转化为IR之后显著的语义相关性:

在这个例子中,一个while循环在源代码文件和二进制文件中都进行了实现,但由于它们处于不同的模态,仅仅从文本外观很难找到它们的语义相似性。当在实验中分别使用编译器工具LLVM Clang和RetDec分别将源代码和二进制代码转换为LLVM-IR之后,则可以从他们的LLVM-IR中找到一些线索。图(右)显示了从源代码和二进制代码生成的部分LLVM-IR,它们都代表了实现进行10次while循环的语义:判断变量和10的大小,若小于10则跳转到对应的分支标签进行对变量的递增操作,否则跳转到返回分支,程序结束。从这个角度可以看出,代码的中间表示有助于统一多种编程语言和不同计算机体系结构中的源代码和二进制代码的表示。


设计与实现

受两种模态代码对应IR的在语义上的相关性启发,本文提出了一种基于代码中间表示和Transformer 的新方法XLIR,用于进行跨语言源代码-二进制代码匹配任务。在工作中,我们采用LLVM-IR作为源代码和二进制代码的中间表示。LLVM-IR已广泛用于编译器优化、程序分析、错误检测和验证,可以从多种高级编程语言(例如C/C++和Java)以及低级机器代码转化得到。

为了得到IR的嵌入表示,我们设计了一个基于Transformer的神经网络,首先通过掩码语言模型(Masked Language Model)以及对比学习模型在外部大规模LLVM-IR语料库上进行预训练,然后在任务集上将源代码和二进制代码对应的LLVM-IR都嵌入映射到一个公共空间,使用三元组损失函数(triplet loss)来对模型进行优化训练:

其中,b,s+,s-分别表示二进制代码、源代码正样本和源代码负样本。同时,我们采用余弦值作为相似度指标:

下图描述了整个工作流程:

目前,没有可用于评估跨语言源代码-二进制代码匹配的数据集。为了解决这个问题,我们基于公共数据集CLCDSA生成了一个新数据集。生成方法是将原数据集的数据对中一种编程语言的源代码编译成二进制代码,同时保持另一种编程语言的源代码不进行转变,这样就构成了一个源代码-二进制代码数据对。特别地,我们使用不同的编译器(即GCC 和LLVM Clang),结合多个不同的优化选项(即-O0、-O1、-O2和-O3),将每个源文件编译成跨多个平台(即,x86-32、x86-64、arm-32和 arm-64)的目标二进制代码文件。因此,每个源代码文件被编译成32个不同的目标代码文件。在单语言的源代码-二进制代码任务中,我们从公共数据集 POJ-104生成新的数据集进行实验。数据集POJ-104是一个从各种在线代码竞赛平台收集来的,由用C和C++编写的大约50000个程序组成的公共数据集。

模型的预训练是在从Github上取得的大代码库上进行的,使用的是常见的掩码语言模型和对比学习,进行实际任务的时候将参数转移到任务模型中。给定一个LLVM-IR语料库,首先使用字节对编码 (BPE) 将每个LLVM-IR分词为token序列。我们首先将两个token序列的连接作为输入,定义为c1={w1,w2,...,wn和c2={u1,u2,...,um,其中n和m分别表示两个序列的长度。这两个序列总是由一个特殊的分隔符[SEP]连接起来的。每个序列的第一个和最后一个token分别用一个特殊的分类标记[CLS]和一个结束标记[EOS]填充,然后将连接的句子输入到Transformer编码器中。在掩码语言建模中,输入句子中的token被随机采样并替换为特殊标记[MASK]。


实验与结论

为了验证我们的模型,我们不仅在跨语言的源代码-二进制代码匹配数据集上进行实验,还将我们的模型扩展到单语言的源代码-二进制代码匹配和跨语言的源代码-源代码匹配实验中,而且我们还对模型的主要模块进行了消融实验。实验结果都显示出我们模型显著优于以前的工具集,同时验证了模型设计的合理和有效性。

由于跨语言的源代码-二进制代码匹配问题的挑战性,我们的XLIR仍有很大的提升空间。在未来的工作中,我们将设计更有效的机制来进一步提高代码匹配的准确性。我们还计划扩展我们的方法以支持更小的匹配检测粒度,例如对单个函数或小代码片段的匹配。


详细内容请参见:

Yi Gui, Yao Wan, Hongyu Zhang, Huifang Huang, Yulei Sui, Guandong Xu, Zhiyuan Shao, Hai Jin: Cross-Language Binary-Source Code Matching with Intermediate Representations. SANER 2022: 601-612



网友评论已有0条评论, 我也要评论

发表评论

*

* (保密)

Ctrl+Enter 快捷回复