APP下载

基于机器学习的二进制代码相似性分析技术综述*

2022-10-16韩烨孙治赵童王炳文

通信技术 2022年9期
关键词:二进制相似性代码

韩烨,孙治,赵童,王炳文

(1.中电科网络空间安全研究院有限公司,河北 保定 071800;2.中国电子科技网络信息安全有限公司,四川 成都 610041;3.中国电子科技集团公司第三十研究所,四川 成都 610041)

0 引言

在软件开发的过程中,开发人员为节省时间和精力,常会从开源社区中搜索符合要求的开源代码进行重用。这种做法虽然能够大大缩短软件的开发周期,却会造成极大的安全隐患。一旦被重用的代码中包含某个安全漏洞,该漏洞就会在复用这段代码的项目之间广泛传播,产生巨大的安全危害。

利用代码相似性分析技术,安全人员能够将软件中的代码与已知缺陷代码进行比对,从而及早发现已知的安全漏洞。软件代码通常可以分为源代码与二进制代码两种。由于软件知识产权保护等原因,软件的源代码通常难以获得,因此针对二进制代码的相似性分析技术的应用更加广泛[1]。然而,二进制代码的相似性检测与源代码相比更加困难,因为大量程序中的语义信息会在编译过程中消失,包括函数名、变量名、注释信息以及数据结构的定义等。即使是在源代码相同的情况下,编译时如果采用不同的编译器与编译优化配置,或存在跨指令架构的情况,也会使生成的二进制代码存在差别。此外,代码混淆技术也可以应用于二进制代码,用于隐藏原始的代码,使其变得更加难以识别[2]。如何解决跨编译器、跨优化、跨架构、抗混淆等问题,一直是二进制代码的相似性分析技术的研究热点与难点。

传统的二进制代码相似性分析技术通常基于序列匹配或图匹配的方法。基于序列匹配的方法首先对二进制代码进行反汇编,利用汇编指令的操作码与操作数生成标识符序列,其次通过子序列匹配的方法判断标识符序列的相似性。这类方法局限在代码的文本特征,几乎不涉及代码语义与内在的逻辑关系,因此分析结果极易受到程序细微差别的干扰,难以实现跨编译器、跨优化、跨架构、抗混淆的代码相似性分析。基于图匹配的二进制代码相似性分析方法首先将二进制代码表示为程序控制流图(Control Flow Graph,CFG)等中间表示,其次利用图匹配的方法判断上述图形中间表示的相似性。这类方法虽然分析准确度较高,且可以根据不同任务采用不同的匹配算法与策略,但计算量庞大,难以同时兼顾准确度和速度。此外,由于图匹配算法多为两两匹配算法,在面对大规模查询任务时,计算量会随代码库规模成几何倍数增长,因此难以适应大规模的查询任务。

另一些方法根据二进代码运行时的行为对其相似性进行分析,但这类方法首先需要运行二进制程序,由于程序的运行条件并非总是具备,因此这类方法的应用场景相对有限,很多时候不能满足人们的需要。

随着机器学习与深度学习技术在计算机视觉、自然语言处理、数据挖掘、推荐系统等领域的成功应用,研究人员开始尝试将机器学习方法应用于二进制代码相似性分析。基于机器学习的二进制代码相似性分析方法能够对代码的语义与逻辑信息进行抽象表示,因此具有较高的分析准确性。此外,基于机器学习的二进制代码相似性分析方法还具有以下优点:

(1)计算高效。运行时间与需要处理的代码规模呈线性关系,适用于大规模数据集。

(2)迁移性好。可以利用不同的数据对模型进行训练,以适应不同的应用场景或任务。

(3)泛化性强。能够在一定程度上消除代码编译过程引入的差异以及代码混淆带来的影响。

本文针对基于机器学习的二进制代码相似性分析方法展开综述。第1节简要介绍了基于机器学习的二进制代码相似性分析流程;第2节与第3节分别从特征与模型两个方面对现有方法进行总结;第4节针对软件供应链安全审查问题探讨该技术领域未来的发展趋势;最后对全文进行总结。

1 基于机器学习的二进制代码相似性检测流程

基于机器学习的二进制代码相似性分析流程如图1 所示。

图1 基于机器学习的二进制代码相似性分析流程

在对二进制代码进行相似性分析时,首先需要利用反编译软件对二进制代码进行解析,生成二进制代码的中间表示,常用的二进制代码中间表示包括代码字符串或序列、代码图形结构以及抽象语法树等。在生成中间表示的过程中,需要确定二进制代码相似性度量的最小单元,本文涉及的方法大多将函数作为相似性比较的最小单元,这是由于函数通常是程序中最小的功能实现单元。生成二进制代码的中间表示之后,便可以从代码的中间表示中提取代码特征。虽然代码的特征类型纷繁复杂,但总的来说只有两种提取方式:一种是以人工的方式选择或构造代码的特征量,再利用特征工程技术对特征量进行筛选;另一种是利用深度学习方法对代码特征进行自动抽取。前者需要研究者具备丰富的领域知识,后者需要大量的模型训练样本。在完成二进制代码的特征提取后,即可将特征输入机器学习模型,利用机器学习模型对代码特征进行融合,进而进行代码的相似性度量,最后将二进制代码的相似性分析结果输出。二进制代码的相似性分析结果通常用于不同二进制代码的相似性判别与相似代码的检索。

在基于机器学习的二进制代码相似性检测流程中,代码特征提取与机器学习模型训练是两个最重要的步骤。基于机器学习的二进制代码相似性分析方法的准确性很大程度上取决于代码特征的选取与机器学习模型的设计,因此本文从这两个方面分别展开论述,对现有基于机器学习的二进制代码相似性分析方法进行总结。

2 面向相似性检测的二进制代码特征选取

利用机器学习技术实现二进制代码的相似性分析,首先需要将二进制代码表示为数值化的特征向量。利用不同的特征向量生成方法可以对代码不同维度的信息进行提取。为全面系统地梳理基于机器学习的二进制代码相似性分析技术的各分支,本文根据生成特征向量时是否需要提取二进制代码的图形结构,将其划分为代码序列特征与代码图特征两类。

2.1 代码序列特征

代码序列特征可以分为直接从原始字节数据中提取的特征与利用反汇编代码生成的特征两种。直接从原始字节数据中提取特征向量的方法虽然简单直接,但稳定性差,细微地代码修改即可对相似性分析结果造成较大影响。目前,这类方法主要应用于跨版本的二进制程序相似性分析与恶意程序检测,鲜少涉及跨平台与跨编译选项的应用场景。

文献[3]将二进制程序中各函数的原始字节数据转化为特征向量与特征信号,并利用特征向量的相似系数与特征信号的相关系数在二进制程序的不同版本中查找对应的函数。文献[4]首先对恶意软件样本的原始字节进行特征提取,其次利用特征哈希的方法降低特征空间的维度,研究恶意软件样本之间的相似性。此外,卷积神经网络等深度学习技术,也可用于为原始字节数据生成特征向量[5],实现二进制代码的相似性分析。

与直接从原始字节数据中生成代码特征向量的方法相比,利用反汇编代码生成代码特征向量的方法在二进制代码相似性分析中的应用更加普遍。

一些研究者从函数的汇编指令中提取统计特征作为函数的特征表示,包括函数中常量与被调用函数的数量等。文献[6]、文献[7]首先根据汇编指令的功能对其进行分类,例如是否处理字符串,是否处理堆内存等;其次统计程序函数中每个类别的汇编指令的数量,作为函数特征输入机器学习模型。另一些研究者从函数的汇编指令中提取代码的特征属性作为函数的特征描述,包括函数的局部变量与形参的大小、函数返回值的类型、程序中引入的外部函数名与外部函数的输入等[8-10]。这类特征在输入机器学习模型之前,通常首先需要进行标准化与归一化。

近年来,一些研究者仿照自然语言的处理方法为函数与基本块的汇编指令序列生成嵌入向量,利用这些嵌入向量在数据集中实现相似代码的检索[11-13]。这类方法成功的原因在于利用深度学习模型提取了二进制代码的深层语义特征,从而使相似函数的判定更加可靠。

值得注意的是,一些二进制代码相似性分析方法在利用代码序列特征进行分析的同时,融合了代码图特征[6,8-9],这种方法能够突破单纯使用代码序列特征的局限性,进一步改善分析效果。

2.2 代码图特征

与代码序列特征相比,代码的图特征显得更加常用,这是因为这一类特征在表达代码语义信息的同时,可以在一定程度上反映代码的结构信息。程序控制流图是代码图特征最主要的来源。

一些研究者从程序控制流图中提取统计特征作为函数特征,例如控制流图中节点与边的数量等[8-9]。文献[14]中提出了三维控制流图(Threedimensional Control Flow Graph,3D-CFG)的概念,将CFG 中的每个节点表示为一个三维的向量,将两个3D-CFG 质心之间的距离作为两个函数之间的相似性度量。文献[6]与文献[15]从CFG 中提取图的能量、偏度以及圈复杂度等作为函数特征。文献[16]通过计算循环头与循环尾的数量以及代表向前与向后传递的控制流的边的数量,从CFG 的环路中提取函数特征,对代码结构进行描述。

文献[6]、文献[16]与文献[17]同时利用程序控制流图和函数调用图对二进制程序进行特征提取。利用函数调用图进行特征提取通常基于对程序中主调函数与被调函数数量的统计,计算函数调用图中对应内部函数调用与外部库函数调用的节点的入度与出度,从而实现与程序控制流图的有效互补。

文献[18]与文献[19]将数据流图与控制流图相结合,形成一种新的语义流图作为代码的中间表示。这种新的语义流图能够同时表示程序的数据流和控制流信息,因此对轻混淆和重构具有较强的抵抗性。文献[18]从语义流图中提取自反、对称、反对称及传递等关系,构建代码的特征向量表示。文献[19]从基本块中提取不同类别汇编指令的数量作为基本块的数值特征,进而利用深度学习模型将语义流图转化为向量,并将其作为语义流图的特征表示。

一些方法对图特征进行哈希,实现相似函数的快速匹配。文献[20]利用局部敏感哈希算法为函数的属性控制流图(Attributed Control Flow Graph,ACFG)构建相似特征索引。与控制流图一样,属性控制流图的节点与程序中的基本块对应,基本块的语法特征则以节点属性的形式包含在节点中。文献[21]提出的面向CFG 的拓扑感知哈希(Topology-Aware Hashing,TAH)方法首先从CFG 中提取n元混合图形特征,其次在此基础上利用模糊哈希算法将其转化为哈希指纹,实现二进制函数的相似性分析。与其他基于CFG 的相似性分析方法相比,这类方法显得更加高效,可以用于大规模的数据集。

近年来,随着图神经网络的发展,一些研究者利用图神经网络技术生成控制流图的嵌入向量,并利用这些嵌入向量实现相似代码的检索,带来了新的技术突破[22-24]。这类方法可以同时对二进制代码的语义特征和结构特征进行深度抽取,全面表达其逻辑特性,对提高二进制代码相似性分析的准确性具有重要的意义,目前正在成为二进制代码相似性分析领域的研究热点。

3 二进制代码相似性分析模型构建

在对二进制代码进行特征提取后,需要进一步构建机器学习模型,利用提取到的代码特征向量实现相似性分析。一些对算力要求不高的传统机器学习模型已在轻量级二进制代码相似性检测工具中得到了成功的应用。近年来,随着深度学习技术的发展,许多研究者致力于利用深度学习模型使二进制代码的相似性分析结果更加鲁棒、分析过程更加智能。

3.1 传统机器学习模型

文献[25]提出的discovRE 工具采用控制流图图匹配的方法计算函数之间的相似度。为缩减图匹配过程中产生的巨量计算成本,该方法首先利用K邻近算法(K-Nearest Neighbor,KNN)作为预过滤器,快速识别少量候选函数。这种方法能在大型代码库中实现相似函数的高效搜索,但可靠性仍有待提高。

文献[20]提出的Genius 方法将属性控制流图作为函数的原始特征,通过谱聚类(Spectral Clustering)的方法对属性控制流图进行无监督聚类,生成属性控制流图码本;进而将作为原始特征的属性控制流图映射为高维数值向量,向量的每一维表示该属性控制流图到码本中每一个聚类类别的距离。尽管属性控制流图码本在使用过程中只需生成一次,但在生成过程中依然需要进行大量的图匹配,且在计算属性控制流图到码本中每一个聚类类别的距离时也要用到图匹配;因此,利用Genius 进行代码相似性分析时,计算量有时仍然很大。

文献[26]提出了一种基于支持向量机(Support Vector Machine,SVM)和属性控制流图的二进制代码相似性分析方法,该方法能够在函数级别上实现跨架构的已知二进制漏洞搜索。该方法首先提取程序的函数级特征输入支持向量机模型,筛选出少量可疑函数;其次基于可疑函数的属性控制流图计算漏洞函数与可疑函数之间的图相似度。实验表明,该方法可以在实际场景中取得良好的应用效果。

为进一步提高跨架构的已知二进制漏洞搜索效率,文献[27]在函数级别上提出了一种基于支持向量机、K邻近算法与属性控制流图的分阶段漏洞搜索方法。该方法首先利用K邻近算法对待测函数集进行修剪,其次利用支持向量机模型在函数预过滤阶段进行优化。尽管同时使用K邻近算法与支持向量机模型时搜索的准确性比仅使用支持向量机时稍低,但效率得到了显著的提高。

3.2 深度学习模型

与传统机器学习模型相比,以深度神经网络为基础的深度学习模型能够实现从原始特征到输出结果的端到端训练,对专业知识依赖较少。此外,深度学习模型能够在原始特征的基础上学习二进制代码的深度语义特征,有利于实现跨编译器、跨架构、抗混淆的二进制代码相似性分析。

在现有的研究工作中,应用于二进制代码相似性分析的深度学习模型主要可以分为时序模型与图模型两类,前者将代码表示为特征序列作为模型输入,后者将代码表示为图数据结构作为模型输入。

文献[5]提出的αDiff 模型直接将程序的二进制字节作为卷积神经网络的输入,生成二进制字节数据的嵌入向量,进而结合函数的出入度和函数调用表分析程序的相似性。文献[11]、文献[12]、文献[13]将程序控制流图分解为多个汇编指令序列,每个指令序列对应程序的一条执行路径。文献[11]在构建复杂的深度神经网络的同时,对词汇间的语义关系和函数的整体特征进行学习,并通过将二者进行融合生成函数的特征向量,用于相似函数的搜索。文献[12]首先利用Word2vec 对每一条汇编指令进行嵌入,其次利用孪生的循环神经网络生成函数的嵌入向量,最后利用对比损失函数(Contrastive Loss Function)使语义相似的函数在特征空间中余弦距离较小。文献[13]首先利用基于负采样的skip-gram 模型将汇编指令表示为数值向量,其次仿照自然语言处理中的机器翻译技术,利用两个长短期记忆网络(Long Short Term Memory Network,LSTM)在不同架构下语义相同的指令序列之间建立对应关系,从而解决跨指令集的相似函数搜索问题。

与时序模型相比,图模型能够对函数各基本块之间的连接关系进行编码,从而更好地利用函数的结构信息。文献[28]提出的Gemini 模型在Genius[20]的基础上,利用深度神经网络实现从属性控制流图到高维向量空间的图嵌入,并利用图嵌入之间的余弦距离实现函数之间的相似性比较,在提高检测效率的同时,大大提高了检测的准确性。文献[19]利用语义感知的深度神经网络对程序语义流图(由数据流图和控制流图共同生成)中每个基本块进行特征编码,然后将每个基本块的特征向量相加作为整个函数的特征向量,利用特征向量之间的余弦距离作为函数的相似性度量。文献[24]构建了一个融合控制流图节点语义信息、节点结构信息以及节点顺序信息的复杂神经网络,并在此基础上讨论了三类信息对二进制代码相似性识别的不同贡献。文献[29]利用图神经网络,结合自顶向下与自底向上两种相似度表征模式,对二进制函数之间的图编辑距离进行预测。文献[22]利用Word2Vec 与随机游走的方法在进程间控制流图上学习基本块的特征表示,利用k-hop 贪婪匹配算法实现二进制程序的相似性检测。文献[30]利用三元损失函数对以属性控制流图为输入的图神经网络进行训练,实现基于属性控制流图的函数相似度排序。

4 未来展望

近年来,软件供应链的安全问题日益凸显,一个软件模块的漏洞在该软件被引入其下游软件的开发流程后,所能造成的影响和潜在破坏力非常大。在无法获得软件源代码的情况下,针对软件二进制代码的相似性分析是对软件供应关系进行细粒度审查的重要手段。

在对软件供应关系进行安全审查时,为实现对软件开发过程中有重用价值的代码片段的全方位覆盖,需要在庞大的二进制代码库中对同源代码进行检索。

基于机器学习的二进制代码相似性分析方法首先将海量代码库中的二进制代码根据其语义与逻辑特征映射到高维特征空间;其次将特征向量预先存储在大规模数据库中;最后在进行重用代码审查时,只需将被检测的二进制代码映射到相同的特征空间,并在数据库中检索与之距离最近者,审查效率较高。因此基于机器学习的二进制代码相似性分析技术很可能在该领域得到大规模的应用,成为该领域的主流技术路线。如何构建能够正确反映二进制代码同源性特征的特征空间将成为该领域核心的技术难题。随着深度学习技术的不断发展,进一步改进模型的结构与训练方法也许会成为解决这一关键技术难题的钥匙。

此外,在对海量数据库中的重用代码进行检索时,将代码序列特征与代码图特征相结合,提取代码不同层面的特征,包括但不限于文本、结构、数据和控制依赖、语义等。对于每种特征采用不同的检索策略进行检索,并对检索结果进行融合,实现相似代码的综合排序,也是提高二进制代码同源性审查准确性的有效方法。这种方法理论上可以大大增加机器学习算法在海量二进制代码检索问题中的实用性,将检测效率和准确性同时提升到满足批量化的软件供应链安全审查的范围。

5 结语

近年来,基于机器学习的二进制代码相似性分析技术日益受到学术界与工业界的青睐。本文从代码特征的选取与机器学习模型的设计两个方面对现有的基于机器学习的二进制代码相似性分析技术进行了梳理,总结了该技术领域的发展脉络。在此基础上,对如何将基于机器学习的二进制代码相似性分析技术应用于海量代码库中的同源代码快速检索进行了探讨。随着软件供应链安全问题的日益凸显,该方向在未来将具有更加重要的研究价值。

猜你喜欢

二进制相似性代码
用二进制解一道高中数学联赛数论题
浅析当代中西方绘画的相似性
有用的二进制
有趣的进度
创世代码
创世代码
创世代码
创世代码
12个毫无违和感的奇妙动物组合
基于隐喻相似性研究[血]的惯用句