二进制代码相似性检测


title: 二进制代码相似性检测
date: 2021年1月25日

二进制分析属于信息安全业界逆向工程中的一种技术,通过利用可执行的机器代码(二进制)来分析应用程序的控制结构和运行方式,有助于信息安全从业人员更好地分析各种漏洞、病毒以及恶意软件,从而找到相应的解决方案。
  • 二进制程序函数识别是二进制分析的基础,对于软件漏洞分析与修复,甚至恶意软件检测、协议逆向等都至关重要。由于二进制代码缺少高级语言程序中的信息,函数的识别往往比较困难,现有的反汇编分析工具具有识别正确率低的缺陷。

  • 二进制代码相似性的概念源于软件分析技术,目前还没有标准和权威的定义。通常认为,如果一段代码是由另一段代码复制或经过一定规则变换而来的,就认为它们是相似的。

  • 二进制代码相似性的研究对象分为源代码和二进制代码。

  • 二进制代码的相似性是指由同一或相似的源代码编译得到的不同二进制代码是相似的。
    在这里插入图片描述

  • 二进制代码相似性检测通常应用于但不限于代码预测(即根据现有的代码预测可能的代码修改和更新,提供代码模板推荐)、知识产权保护(即发现代码中未经授权的代码的复用和克隆,协助软件所有者保护知识产权或规避潜在的侵权行为)、漏洞搜索(如脆弱代码搜索,软件漏洞追踪和定位)。

  • 二进制代码相似性常被作为一种辅助分析技术,由于其在提升代码质量和提高代码分析效率方面效果显著,近年来逐渐成为学术界的研究热点。

下面简单介绍一下二进制代码相似性检测技术的分类:

1. 基于文本的检测

  • 基于文本的检测技术历史最悠久,实现最简单,它们有的对二进制代码只做简单的预处理。例如,一类方法首先模糊通用寄存器名和内存地址,然后提取指令的操作码和操作数,或者提取字符串以生成标识符序列,最后通过子序列匹配来判断不同代码是否相似,这类方法可以进一步被归纳为基于标识符的检测。例如,Karta作为著名的静态反编译程序IDAPro的二进制程序匹配插件,首先利用唯一的数值常数和字符串等标识符来设置库的锚点函数,然后通过在二进制文件中查找锚点函数来缩小搜索范围,最后利用标识来进一步确定静态编译的开源库的确切版本并匹配函数符号,其也可以在这一步骤使用函数调用列表来匹配一组相似函数。DarunGrim2是基于指纹哈希匹配的二进制文件比较工具,它忽略汇编代码中的操作数,将程序基本块的指令序列的哈希值作为相似特征,此外,它还以程序中符号名称的匹配作为辅助手段。还有方法甚至不对二进制代码进行反汇编,直接比较程序的二进制字节流是否相近,这类方法可以进一步被归纳为基于字节流的检测。值得注意的是一种名为αDiff的检测方法,该方法使用了当今热门的神经网络技术,利用二维卷积神经网络(Convolutional Neural Network, CNN) 对程序的二进制字节进行嵌入(嵌入既可以指神经网络将其他形式的输入转换为向量形式的输出的过程,也可以指神经网络的输出,即高维向量),并综合函数出入度和调用表的统计特征来构建特征向量,用向量之间的距离来度量程序间的相似性。虽然该方法取得了良好的检测效果,但本文认为,由于其将二进制代码视为线性字节流,其本质上仍属于基于文本的检测。

  • 基于文本的检测因为不考虑程序的语法和语义等信息,所以其原理和实现较其他技术更简单,其时空复杂度也较低。该类技术主要针对未应用复杂混淆手段的代码克隆和复用,由于该类检测方法容易实现对抗检测,常作为一种高效的辅助检测手段。

在这里插入图片描述

2. 基于属性度量的检测

  • 基于属性度量的检测技术关注程序汇编代码中可度量的属性和特征,提取属性和特征的度量值,构成多维向量(该类技术认为该特征向量能够从不同维度标识代码段),以特征向量之间的距离近似来度量代码段之间的相似度大小。这类方法需要确定检测的最小粒度(如基本块或函数),在最小粒度范围内通过对属性和特征的统计计数来获得度量值。度量值可能是但不限于是特定常量和指令等标识、函数的输入和输出等对象的计数。例如,系统discovRE基于跨架构的统计特征缩小相似函数的搜索范围。该方法首先通过人工筛选的特征来构建函数的简单特征向量(这些特征包含算术指令、函数调用、重定向、转移指令、局部变量、基本块、导入函数、所有指令和参数等对象的统计个数),利用kNN(k-Nearest Neighbors)算法计算函数的相似距离,从而实现预筛选可能相似的函数,降低后续基于函数控制流图(Control Flow Graph, CFG)的最大子图同构匹配方法的计算量。BinDiff是一款二进制文件比较工具,能帮助快速查找汇编代码中的差异性和相似性。BinDiff是基于图形和指纹理论开发的IDAPro插件,其函数匹配主要是基于从CFG中得到的NEC 值,即基本块数(Nodes)、边数(Edges)、调用数(Calls)。
  • 基于属性度量的检测方法因为不考虑程序的逻辑结构,所以其统计特征易于实现,但其提取的信息十分有限,因此常作为一种辅助方法。其主要问题是,属性特征是人为设计和筛选的,难以保证各属性都处在不同维度上,不同属性之间可能存在拟合问题,因此盲目地增加属性特征的种类,可能不仅无法有效提高检测的准确度,反而会增加计算开销。

在这里插入图片描述

3. 基于程序逻辑的检测

  • 基于程序逻辑的检测技术,利用列表、树形或图形等数据结构来记录和描绘程序的数据流或控制流信息(该类技术认为所得的中间表示能够捕获程序中一定的语法和语义信息),通过匹配相似的序列、节点或边、公共子树或子图来寻找逻辑或功能相似的程序基本块或函数。
  • 程序的数据逻辑在函数内部体现为数据的流向和运算,在函数外部体现为函数的输入和输出。例如,Multi-MH系统通过基本块的输入和输出行为来掌握其语义,利用签名跨架构来查找具有类似行为的漏洞代码。二进制搜索引擎Bingo利用从符号表达式中生成的输入和输出样例来匹配语义相似的函数。
  • 程序的控制逻辑在函数间可以用函数调用序列来描述,在函数内部可以用CFG来描绘,在基本块级可以用逻辑树来表示。例如,工具HAWK实现了一种基于系统调用依赖图(System Call Dependence Graph, SCDG)胎记的动态检测方法;Pewny等提出的TEDEM方法利用表达式树的编辑距离来度量基本块级别的相似性;discovRE和Genius是比较著名的基于属性优化CFG的二进制相似性检测系统,其采用了各自经优化的图匹配算法;Esh,BinHunt,iBinHunt等工具在基于CFG的基础上,利用了符号执行来确定基本块或函数的相似性。CFG能够有效获取和展示程序的控制流信息,是程序代码的高度抽象,其作为中间表示既可以用于表示源代码,也可以用于表示汇编代码,但是其跨语言的特性,导致无论是源代码的还是二进制代码的相似性检测技术,大多严重依赖CFG作为中间表示,尤其是跨架构的二进制代码检测。
  • 基于程序逻辑的检测方法的优点是准确度较高,可以根据不同的任务采用不同的匹配算法和策略,可伸缩性强。其缺点是时空复杂度高:一方面,数据流和CFG的提取过程代价非常昂贵;另一方面,相似性度量所依赖的图匹配算法的时间复杂度缺少多项式解,图匹配算法又多是两两匹配算法,因此在面对大规模查询任务时,计算量随代码库规模成几何倍数式增长。
  • 上述困难并没有阻止研究人员在该方向上取得突破。针对该问题,一种办法是从中间表示CFG入手,利用其他辅助检测技术来为CFG引入轻量级且易于度量的属性,从而简化CFG的节点。例如discovRE利用轻量级的统计特征来筛选候选函数,降低图匹配算法的任务量。另一种办法是从图匹配算法入手,采用近似图匹配算法来提高检测效率,在准确度和速度之间进行折中,但该方法受限于图匹配算法的效率,对检测效率的提升有限。近年来,研究人员开始将神经网络技术跨学科地应用到该领域,以用于解决传统图匹配算法遇到的效率瓶颈问题。其中最具代表性的是Qian等提出的Genius系统,该系统利用机器学习的谱聚类算法来对函数的CFG进行分类并生成码本(Codebook),再对码本进行编码,将相似函数的搜索问题转化为特征编码的搜索问题,极大地提高了效率并兼顾了结果的准确度。至此二进制代码相似性检测技术再一次实现了突破,并开拓了新的发展方向,相关研究越来越多地关注代码中更高级也更复杂的语义信息。

在这里插入图片描述

4. 基于语义的检测

  • 以上方法多将中间表示的内容(承载的信息)与其形式(存储的数据结构)合并,将基于图形结构的相似性检测技术归入基于语义的检测中。这种分类方法多应用于源代码相似性检测技术,虽然对二进制代码相似性检测技术的分类具有借鉴意义,但本文认为这样既不能很好地涵盖近几年来二进制代码相似性检测领域的最新成果,也不能清晰地反映该领域的发展趋势。本文总结的原因有:(1)虽然高级数据结构(例如树形和图形结构)用于描述高级程序信息具有先天优势,但二者不能划等号,因为高级数据结构可以分解或转化为低级数据结构(例如列表或高维向量),程序语义等高级信息同样可以用低级数据结构来进行描绘;(2)“语义”的概念来自自然语言,若将汇编语言的指令看作“单词”,基本块看作“句子”,则得到相应的二进制代码的“词法”和“语法”概念,函数则具有完整的“语义”,但是CFG主要包含程序的控制流信息,该信息仅是函数所包含的丰富语义信息的一部分;(3)近几年出现的基于机器翻译或深度神经网络的程序语义相似性检测技术,才是直接关注函数语义信息的检测技术,虽然它们有的仍然使用CFG作为中间表示,但相比传统的基于CFG的检测方法却有了本质的不同,其不同在于新方法的检测速度较传统方法的提升了几个数量级。有的方法甚至完全摒弃了前述的3类基本检测技术。
  • 本文所指的基于语义的检测技术,是通过捕获程序汇编代码中的语义信息,比较函数或组件的语义差异,来实现相似性度量的。这类方法通常借鉴自然语言处理(Natural Language Processing, NLP)、图像识别或其他领域的技术,利用深度神经网络来实现程序语义的嵌入,通过对嵌入向量的比较或查询操作,来实现大规模任务的处理。其二进制代码的中间表示包括规范化的汇编文本、其他中间语言或CFG,神经网络模型多采用暹罗架构(Siamese Architecture),利用程序代码的大规模特点构造来训练样本库,相关领域的专家和先验知识可能不是必须的。Xu等于2017年提出了第一个基于神经网络生成的二进制函数CFG嵌入的方法,其在名为Gemini的系统中,利用改进的Structure2vec模型(Structure2vec结构感知模型的灵感来自图形模型推理算法,该算法根据图的拓扑结构递归地聚合得到特定于顶点的特征向量)来构成暹罗架构网络,将函数的CFG嵌入高维向量,通过计算向量的余弦距离来度量函数间相似性。Ding等提出的Asm2vec模型,是基于改进的PV-DM模型(PV-DM神经网络模型是为文本数据而设计的,基于文档中的标识学习文档表征的)的汇编代码表征学习模型。该模型利用自定义的函数内联和随机漫步机制,将函数的CFG建模为汇编指令的线性序列,以该汇编文本为输入,不需要任何先验知识,学习指令的语义,构建指令嵌入向量,最终得到函数的语义嵌入向量。Asm2vec是第一个将表征学习作为汇编代码构建特征向量的方案,具有优秀的抗混淆和抗编译器优化特性,但其还不能用于跨架构比较。Luca等提出的SAFE网络,先利用NLP的Word2vec模型(Word2vec是谷歌于2013年推出的一款NLP工具,其特点是能将单词向量化,定量度量单词之间的关系)来实现汇编语言的指令嵌入,再利用循环神经网络(Recurrent Neural Network, RNN)来捕获指令序列的上下文关系,最终实现函数的嵌入,SAFE摒弃了CFG作为中间表示,汇编代码的语义信息直接由深度神经网络嵌入到高维向量中,这样既省去了耗时的CFG提取过程,又避免了人为偏见的引入。SAFE模型利用RNN网络构建了暹罗架构并采用有监督的学习方法来训练模型,虽然其可以由程序自动随机构造正样本对和副样本对,但针对跨架构检测任务的训练,随着系统支持指令架构种类的增加,理论上,其训练样本库的规模需要根据不同架构的组合成倍地扩大,这就限制了该模型的可扩展性。GeneDiff是第一个使用语义表征模型来学习二进制代码中间语言从而实现跨架构克隆检测研究的方法。它借助动态分析VEXIR(VEX IR是动态分析框架Valgrind的中间语言,是一种二地址形式的中间表示,支持多种指令架构)的中间语言消除了不同指令架构之间的差异,通过改进的PV-DM模型来为函数的VEX-IR生成语义以嵌入向量。因为每一条汇编指令会被翻译成多条VEX指令,所以该模型将由同一条汇编指令翻译而来的多条VEX指令组合看作一个单词,将基本块看作句子,将函数看作段落,使用向量间的余弦距离来度量函数间相似度。
  • 除了检测速度和准确度的提升,将神经网络应用于相似性检测任务的优势还在于,传统检测方法所采用的匹配算法通常是固定不变的,神经网络可以针对不同任务进行再训练,应用场景更广阔;此外,神经网络不但可以自行学习和选择特征,还可以习得人工方法很难确定的不同特征对相似度影响的权重,从而降低甚至避免人工设计和筛选特征带来的拟合。这类技术在发展过程中也遇到了一些难题:(1)跨学科知识的交叉应用给检测技术的突破带来了新思路和启发,同时对研究人员的知识储备和转化能力提出了更高的要求,现有技术所使用的神经网络模型多是其他领域成果改进而来的,因此相似性检测需要更多针对自身实际的基础进行理论创新;(2)神经网络训练需要大量的训练数据,如何针对不同任务构造高质量的训练集仍然充满挑战;(3)神经网络的输出,嵌入向量的每一维的具体含义还无法进行科学的解释,且其结果无法用符号化的表达式或定理证明。

在这里插入图片描述

5. 小结

| 技术分类 | 关注信息 | 中间表示 | 优点 | 缺点 |
| :------: | :------: | :------: |:------: |
| 基于文本 | 汇编文本、字节流 | 字符串、标识符序列、高维向量 | 方法实现简单,检测时空复杂度低 | 不考虑程序的语法和语义等信息;检测准确度较低 |
| 基于属性度量 | 可度量属性 | 度量值、多维向量 | 度量算法简单,方法易于实现,检测速度快 | 不考虑程序逻辑信息;不同属性间可能存在过度拟合问题,准确度难以保证 |
| 基于程序逻辑 | 控制流、数据流 | 抽象语法树、控制流程图、函数调用图、输入输出表、数据依赖图 | 准确度高于基于文本和属性度量的检测;能够识别细微语法变化 | 中间表示转换过程复杂;匹配算法复杂度高 |
| 基于语义 | 程序语义 | 属性控制流图、语义嵌入向量 | 能够识别程序语义差异;机器学习避免引入人为偏见;能够适应不同任务需求;检测效率高 | 需要大量语义训练样本;语义嵌入向量各维度的意义无法解释 |
习避免引入人为偏见;能够适应不同任务需求;检测效率高 | 需要大量语义训练样本;语义嵌入向量各维度的意义无法解释 |

猜你喜欢

转载自blog.csdn.net/cherrychen2019/article/details/113111093