论文名称 | 发表时间 | 发表期刊 | 期刊等级 | 研究单位 |
How Machine Learning Is Solving the Binary Function Similarity Problem | 2022年 | USENIX | 安全顶会 | 思科公司 |
0. 摘要
研究背景:在各种不同的问题中,精准计算两段二进制代码相似性(代码相似性检测)的能力发挥着非常重要的作用。安全、编程语言分析、机器学习等多个研究社区,专注于这一主题长达五年之久,并且发表了数百篇关于该主题的论文。
现存问题:从微观角度来讲,相关研究从可重复性到结果透明性均存在不同程度的问题。从宏观角度来讲,现有研究大部分关心非常具体的细分领域,无法有效的推广到整个研究领域。
研究内容:对代码相似性检测领域的最新研究进行测试,(1)系统化现有的研究体系,(2)对三类代码相似性检测技术进行深入研究,(3)构建新的数据集对上述三类技术进行测试,(4)针对该领域提出新问题并解答。
1. 引言
二进制函数相似性检测定义:二进制函数相似性检测是将一堆函数的二进制表示作为输入,并输出可以表示它们之间“相似性”的一个数值。由于,(1)软件使用不同的工具链、编译器优化、编译器标志进行编译,(2)物联网设备等场景中,软件被编译为不同的架构,二进制函数的相似性的有效检测变得相当困难。
二进制函数相似性检测的现实意义:二进制函数相似性检测在不同的系统安全领域起着非常重要的作用,(1)逆向工程师使用二进制代码相似性检测方法将目标函数与先前生成的数据库中的函数进行匹配,(2)运维人员使用二进制代码相似性检测方法将目标函数与漏洞函数进行匹配,(3)该技术还与binary diffing与binary patch相关。
二进制相似性检测研究面临的挑战:(1)研究内容复现困难,提供源代码的研究较少,且这些源代码大都存在可用性差的问题。(2)评估结果透明性差,不同研究采用不同的评价指标,无法有效比较不同的研究成果。某些工作建立在特定的pipelines,无法确定pipeline对实验结果的影响(3)前面的两个挑战导致二进制代码相似性研究方向发散,同一领域内存在数十种不同的技术。
2. 二进制函数相似性检测问题
二进制相似检测旨在计算一个数值,该数值可以表示两个二进制之间的“相似性”。其中,二进制代码是由编译器生成的机器码,二进制代码可以是二进制函数、二进制基本块、二进制程序(一般为二进制函数),由同一份源码编译而成的不同二进制函数(不同架构,不同编译器设置)被定义为同源二进制函数。
2.1 函数相似性检测
函数相似性检测方法:直接检测 vs. 间接检测
函数相似性检测可分为直接检测与间接检测两大类,直接检测通过原始输入数据或原始输入数据的特征实现函数相似性检测,间接检测通过输入特征的低维表示实现函数相似性检测。
直接检测:这类方法需要从看似不相关的输入特征(原始数据或原始输入数据的特征表示)中识别出相似性指标,由于存在无法通过输入特征线性表示的相似性指标,研究人员建议使用机器学习方法进行相似性检测。常见的机器学习方法包括,贝叶斯网络、卷积神经网络、图匹配网络、前馈神经网络。
为了找到相似的函数,这些方法需要搜索整个数据集,并将目标函数与数据集中的所有函数进行比较,这不是一个可扩展的方案。许多方法实施索引策略,如基于树的数据结构、局部敏感哈希、布隆过滤器、自定义过滤器、聚类技术、分布式搜索方法等。
间接检测:这类方法将输入特征映射到“压缩”的低维表示,可以使用距离度量(欧几里得距离、余弦距离)轻松地相互比较。这些解决方案运行有效地一对多比较。例如,如果需要将目标函数与整个数据集进行比较,可以首先将数据集中的所有函数映射到其各自的低维表示,然后对目标函数执行相同地操作,最后通过使用近似最近邻等有效技术来比较这些表示。
间接检测中输入特征的低维表示:模糊哈希 vs. 嵌入技术
通过间接检测实现函数相似性检测的过程中,一般通过模糊哈希或者嵌入技术生成输入特征的低维表示。模糊哈希算法不同于传统加密哈希算法,通过专门的设计将相似的输入值映射到相似的哈希值。嵌入技术属于机器学习技术,通过机器学习模型将语义相似的输入映射到低维空间中相近的点。
模糊哈希:Pagani等人深入研究模糊哈希对原始可执行文件低维表示的有效性,发现原始字节的微小变化会显著影响低维输出。Thomas等人提出定制化更强的FunctionSimSearch技术,通过模糊哈希实现原始可执行文件的高效表示。
嵌入技术:机器学习模型的目标是学习如何生成嵌入向量,以最大化同源函数之间的相似性并最小化非同源函数之间的相似性。常见的嵌入技术包括代码嵌入技术于图嵌入技术。
常见的嵌入技术:代码嵌入技术 vs. 图嵌入技术
代码嵌入技术:许多研究人员尝试采用现有的自然语言处理(NLP)技术,通过将汇编代码视为文本来解决二进制函数相似性检测的问题。这些解决方法处理标记流(例如指令、助记符、操作数、标准化指令)并输出对应的嵌入向量,其具体实现可分为三类:(1)基于word2vec,这类方法不能直接应用于跨架构二进制函数相似性检测;(2)基于seq2seq,允许将不同架构的语义映射到相同的嵌入空间;(3)基于预训练的LLM模型,根据预训练中学习到的知识辅助二进制函数相似性检测。
汇编代码嵌入通常受到它们可以处理的不同指令数量以及可以作为模型输入提供的最大指令数量的影响。常见的嵌入方法包括,指令级嵌入、基本块级嵌入、函数级嵌入,指令级嵌入和基本块级嵌入有时作为函数相似性计算算法的输入或复杂模型的一部分。
图嵌入技术:图嵌入技术非常适合捕获基于函数控制流图的特征,这些特征本质上是跨架构的。 这些嵌入可以通过自定义算法或更复杂的机器学习技术生成,例如图神经网络(GNN)。 机器学习社区最近的一些方法提出了 GNN 的变体,例如 GMN。 这些变体能够在向量空间中产生可比较的嵌入,其特殊性是这些嵌入对作为模型输入提供的两个图的信息进行编码。
图嵌入方法通常还对图的相应节点中每个基本块的信息进行编码,以增加更多的表现力。 例如,一些解决方案计算每个节点的一组属性,从而产生属性控制流图(ACFG),它可以手动设计,也可以以无监督的方式自动学习。 其他作者使用前面讨论的一些技术来利用其他嵌入计算层(例如,在基本块级别)。
2.2 函数表示
二进制函数本质上是特定体系结构的机器码和数据相对应的字节流。从这个原始输入开始,研究人员使用了多种方法来提取更高级的信息,这些信息可用于判断两个函数是否为同源函数。下面列举一些二进制函数表示方法,这些函数表示的抽象级别递增排序。
原始字节:一些解决方案直接使用原始二进制信息作为相似性度量的起点,或者将原始字节与控制流图(CFG)或调用图(CG)获得的其他信息结合起来。
汇编代码:汇编代码相较于原始字节具有更高的抽象程度,Asm2Vec与Trex等方法将直接将汇编代码作为输入,实现同源代码相似性检测。也有一些方法从汇编代码中提取特征,进而实现同源代码相似性检测。
标准化汇编代码:汇编代码通常对常量值(立即数,地址等)进行编码,这回导致操作和操作数的潜在组合数量非常多,一些研究通过抽象掉一些这周可变性实现汇编代码的标准化。作为汇编代码的变体,标准化后的汇编代码也可以使用汇编代码的表示方法。
中间表示:有些方法通过将二进制表示提升为中间表示(IR),在更高的抽象级别上工作。IR的优点包括:(1)可以统一语义上等效但语法上不同的指令的表示,(2)可以过滤掉不同架构的不相关工件,(3)可以实现代码结构的简化。现有的工作采用了许多不同的中间表示,例如LLVM、VEX、IDA microcode。
函数结构:为了捕获函数的内部结构,许多方法提取函数的控制流图(CFG)。有些使用从基本块获得的数据来丰富CFG,即属性控制流图(ACFG)。除此之外,一些工作根据CFG提供的结构信息计算替代特征。
数据流:汇编级算数表达式的实现可以采用不同的形式来实现相同的语义。为了处理这些场景,之前的工作建议首先根据数据流依赖关系计算程序切片,然后对其进行规范化并将其用作捕获函数行为的特征。
动态执行:一些方法通过执行函数对并从输入和输出之间的关系中提取特征,另一些方法提取从完整或部分执行跟踪派生的语义特征,其他方法利用仿真或混合技术提取特征。
符号执行:一些方法依赖符号执行来捕获目标函数的行为,并确定所有可能路径下其输入与输出的关系。
3. 二进制函数相似性检测代表性研究
我们工作的主要贡献之一是为许多关键方法提供参考实现,并通过在通用且全面的数据集上进行实验来比较它们。 理想情况下,人们会评估尽可能多的方法,但显然重新实施所有方法是不可行的。 同样重要的是要理解,虽然有数百篇关于该主题的论文,但其中许多论文提出了相同技术的微小变化,并且新颖解决方案的数量要少得多。在本节中,我们首先讨论我们的选择标准,然后介绍我们实施和评估的一组技术。
3.1 代表性研究选择标准
可扩展性和现实世界的适用性:我们对有潜力扩展到大型数据集并且适用于现实世界用例的方法感兴趣。 因此,我们不评估本质上很慢的方法,只关注直接比较,例如基于动态分析、符号执行或高复杂性图相关算法的方法。
关注代表性方法而不是具体论文:有许多研究工作提出了同一方法的微小变化,例如通过重用以前的技术,同时稍微改变所使用的功能。 这通常会导致相似的整体准确度,这使得它们对于我们的比较来说不太有趣。
覆盖不同的研究群体:关于二进制函数相似性问题的研究贡献来自不同的研究团体以及学术界和工业界。 不幸的是,通常的情况是,特定社区中的研究论文仅根据同一社区的提案进行评估,有时仅根据同一作者的先前作品进行评估。 因此,在我们的评估中,我们希望纳入来自系统安全、编程语言分析和机器学习社区的代表性研究。 为了完整起见,我们还考虑了行业提出的方法。
优先考虑最新趋势:虽然该研究领域的首次贡献可以追溯到十多年前,但最近人们的兴趣激增。 此外,这些最近的出版物中的大多数都以某种方式采用了基于机器学习的技术。 据报道,这些技术反过来优于以前的所有方法。 一些研究人员认为基本方法和机器学习技术一样有效,但我们的评估表明,只有在考虑简单的评估场景时才是这种情况。 因此,虽然我们确实考虑了各种类型的方法,但我们确实优先考虑这些最新的、更有前途的研究趋势。
3.2 代表性研究选择方法
根据我们的分析,我们确定了 30 种技术,如图 1 所示,然后我们从中选择了 10 种代表性解决方案进行研究。
图1左侧显示了函数相似性检测领域的主要研究机构,以及这些研究机构发布的研究成果。这些群体来自学术界和工业界,其中谷歌和腾讯在这一领域比较活跃。左图中的边代表相关成果与其他成果的对比。图1右侧对这些研究成果的发布时间与函数的表示方法进行了分类,其中横轴代表相关成果的函数表示方法,纵轴表示相关成果的发表时间。除此之外,还通过不同颜色表示不同的相似性计算检测方法(模糊哈希、图嵌入、代码嵌入)。
Ctalog1[BYTES][FUZZY][MONO]:基于MinHash局部敏感哈希的模糊哈希方法,该算法将函数字节作为输入并生成固定长度的签名。该方法不具备跨架构检测能力,这项工作来自非学术社区(IDA插件)。
FunctionSimSearch[CFG][FUZZY][CROSS]:使用SimHash算法来计算模糊哈希值,该模糊哈希结合了CFG、助记符和汇编代码中提取的立即值。该方法具有跨架构检测能力,该方法是由业内研究人员开发的。
Gemini[ACFG][GRAPH][CROSS]:使用GNN(Structure2vec)来计算从函数ACFG(具有基本块级属性的控制流图)开始的函数嵌入。这个方法标志着一个里程碑,因为它是第一个利用具有Siamese架构的GNN来学习函数相似性的工作。
Li et al. 2019.[ACFG][GRAPH][CROSS]:由机器学习社区的行业研究人员(DeepMind和Google)提出,通过一种新颖的图匹配模型来计算图对之间的相似度。这种方法提出了两个来自机器学习社区的前沿模型,并显示了有希望的结果。
Zeek[IR][NEURAL][CROSS]:在基本块级别对提升代码 (VEX IR) 执行数据流分析(切片)并计算链。然后,训练两层全连接神经网络来学习跨架构相似性任务。这种方法是结合了中间表示、数据流分析和机器学习的最先进的建议。
Asm2Vec[ASM][CODE][CROSS]:该模型模型源自paragraph2vec的 PV-DM 变体,是原始word2vec模型的扩展。 Asm2Vec 引入了更精细的指令级拆分和嵌入结构,以克服汇编指令的词汇外 (OOV) 问题的局限性。这种方法是完全无监督的,并且在单一架构实验中取得了最先进的结果。
SAFE[ASM][CODE][CROSS]:SAFE使用的自注意力语句编码器,学习跨架构函数嵌入。这种方法代表了 seq2seq 模型中的 NLP 编码器,与 Asm2Vec 相比,它是专门为学习跨架构相似性而设计的。
Massarelli et al., 2019.[ASM+CFG][CODE][CROSS]:使用与Gemini相同的GNN,但它改变了块级特征,从手动设计的特征切换到无监督的特征。这种方法很有趣,因为它是 Gemini 的演变,并且结合了指令级嵌入、基本块编码器和 GNN 的优点。
CodeCMR/BinaryAI[IR+CFG][CODE][CROSS]:将中间表示与 NLP 编码器相结合以获得基本块嵌入,并使用 GNN 来获得图嵌入。两个 LSTM 对函数中的字符串和整数数据进行编码。函数嵌入是三者的串联,并且二进制模型是端到端训练的。
Trex[ASM][CODE][CROSS]:一个动态组件,可以提取函数轨迹,这对于学习函数语义至关重要。作者根据这些痕迹对 ML 模型进行预训练,并将学到的知识转移到匹配语义相似的函数。匹配阶段完全基于静态特征,而仅在预训练期间才需要生成微痕迹的仿真。这种跨架构解决方案构建在 Transformer 之上,Transformer 是 NLP 中最先进的深度学习模型。
4. 二进制函数相似性检测评估
4.1 执行环境
为了实现对不同二进制函数相似性检测研究方法进行公平的比较,通过统一的方法实现了评估的每个阶段。这些阶段包括:二进制分析、特征提取、机器学习实现。
- 通过IDA Pro7.3实现二进制分析
- 通过一组使用IDA Pro APIs、Capstone、NetwokX的Python脚本实现特征提取
- 在Tensorflow1.14中实现所有神经网络模型(Trex除外,它在Fairseq之上构建),使用Gensim3.8来实现Asm2Vec并运行指令嵌入模型
在配备 Ubuntu 18.04、Intel Xeon Gold 6230(80 个虚拟核心 @2.10 GHz)、128GB DDR4 RAM 和 1 个 Nvidia RTX2080 Ti GPU(1350MHz、11GB GDDR6、13.45 TFLOPS FP32)的工作站上运行所有实验
4.2 使用数据集
创建了两个新数据集Dataset-1和Dataset-2,旨在捕获现实世界软件的复杂性和可变性,同时涵盖二进制函数相似性的不同挑战:(1)多个编译器系列和版本,(2)多个编译器优化级别,(3)多种架构和位数,(4)不同性质的软件。我们使用Dataset-1来训练机器学习模型,并使用两个数据集来测试待评估的方法。
4.3 评估的实验设置
进行了广泛的实验来评估所选方法机器几种变体的准确性。具体来说,确定了六个不同的任务进行评估:(1)XO:函数对具有不同的编译优化级别,但编译器、编译器版本和体系结构相同;(2)XC:函数对具有不同的编译器、编译器版本和编译优化级别,但架构和位数相同;(3)XC+XB:函数对具有不同的编译器、编译器版本、编译优化级别和位数,但架构相同;(4)XA:函数对具有不同的体系结构和位数,但具有相同的编译器、编译器版本和编译优化级别;(5)XA+XO:函数对具有不同的体系结构、位数和编译优化级别,但编译器和编译器版本相同;(6)XM:函数对来自任意体系结构、位数、编译器、编译器版本和编译优化级别;
前三个任务评估仅限于单一架构的二进制函数相似性检测,适用于恶意软件分析和协作逆向工程等领域。第四个任务与始终相同的编译器和编译器选项的固件镜像的分析相关。第五个任务旨在支持Dataset-2,该数据集仅使用一组编译器和编译器版本镜像编译。第六个任务最具挑战性,包括整个数据集的比较。在评估中,我们还考虑了XM的三个子数据集:小型函数数据集XM-S(少于20个基本块)、中型函数数据集XM-M(20到100个函数基本块)和大型函数数据集XM-L(大于100个函数基本块)。
每个任务根据两种不同的测试进行评估:(1)ROC曲线的曲线下面积AUC,它是模型在所有可能的分类阈值上的性能的聚合度量;(2)两个常用的排名指标,MRR和Recall@K,MRR对于评估那些需要通过大型数据库搜索候选函数的应用程序中的模型性能非常有用,例如在漏洞研究用例中。
我们为每个任务构建了一个包含 50k 个正对和 50k 个负对的数据集,Dataset-1 和 Dataset-2 中总共有 700k 个函数对。对于排名测试,我们选择了 1,400 个正对和 140k 个负对,即每个正对有 100 个负对。总的来说,我们的测试涵盖了 438,981 个独特的二元函数,并且限制为至少有五个基本块。 在每个任务中,根据相应的约束进行随机采样(例如,在交叉优化中,正负对属于同一架构)。
为了使我们的评估更有意义,我们选择删除重复的函数(通过检查它们的名称和指令的哈希值)。 我们还注意到,“配对选择”方面对于正确评估至关重要。 不幸的是,最近的几项工作使用不同的方式来选择这些对,使他们的训练任务变得更加容易或更加困难。 例如,在[36]中,研究人员在保持相同的编译器选项的同时生成了负对。 在另一个示例(VulSeeker [25])中,负对是随机生成的,并且它们不会对编译器选项以及锚函数的存在进行任何检查。 这些不一致阻碍了公平比较的潜力,而且常常被忽视。
通过遵循该研究领域的常见做法,我们使用两个专门设计的数据集以最通用的方式对所选方法进行评估。 我们注意到,直接评估安全应用程序的方法通常具有挑战性,特别是在漏洞发现和恶意软件聚类的情况下,因为它需要创建准确的地面实况,这是功能相似性试图解决的问题 第一名。
4.4 模糊哈希相关研究的评估
对Catalog1与FunctionSimSearch这两种基于模糊哈希的二进制函数相似性检测方法进行评估,。其中,Catalog1 使用原始字节作为输入特征,根据哈希函数的大小可分为两种(大小分别为16和126)。FunctionSimSearch (FSS) 使用组合图基数 (G)、助记符 (M) 和立即数 (I):我们通过逐步启用不同类型的输入特征(包括它们的加权线性组合 w)来进行不同的测试,正如我们在原始实现中发现的那样(G:1.00,I :4.00,M:0.05)。
当一次仅考虑一个自由变量时,即使是模糊哈希等简单方法也是有效的:“原始”字节被证实是用于相同架构比较的良好特征,而图基则在跨架构比较中有效。对于 Catalog1,签名大小越大,性能越好,但它们受到实现中包含的哈希函数总数的限制。
在 XC 任务中(表 2),Catalog1 和 FSS 具有相同的 AUC。对于 FSS,仅图基数 (G) 配置在除 XC 和 XO 之外的所有任务中都是最好的,其中使用带有助记符的图基数 (G+M) 具有更高的 AUC。此外,FSS 似乎在更大的函数上也表现得更好,这可能是因为可以提取更多数量的不同图基。最后,在 XA 任务中,当使用助记符和立即数等附加功能时,FSS 准确性会降低,令人惊讶的是,这三个功能的加权线性组合并没有比其他基本配置产生更好的结果。 Catalog1 是两种方法中最快的,而 FSS 由于特征提取阶段较长,速度慢了约 3 倍。
4.5 机器学习相关研究的评估
我们使用从 Dataset-1 中提取的通用训练数据集(Trex [60] 除外)并使用与 XM 任务类似的标准来创建正样本和负样本来评估所有选定的方法。 然而,值得注意的是,通过使用特定于任务的训练数据,可以进一步改善每项任务的结果。 我们确实进行了此评估,但我们忽略了结果,因为我们注意到对最通用数据 (XM) 的训练实现了接近每项任务最佳性能的整体性能。
比较机器学习模型,尤其是深度神经网络,是一项具有挑战性的任务,因为有几个变量可能会影响最终结果,包括模型实现和配置(例如,层数或循环神经网络的类型)、不同的超参数(例如, 、学习率和批量大小)、损失函数、优化器和训练周期数。 为了在我们的比较中尽可能统一,所有模型都使用从 256,625 个独特的二元函数中提取的相同随机生成数据进行训练。 此外,我们进行了大量的实验来评估不同的特征集、不同的模型配置、超参数和损失函数。 每个模型的结果都可以通过使用广泛的网格搜索方法来改进,我们提出的结果可以用作未来工作的起点。
结果表明,GNN 在所有指标和所有任务中都实现了最佳值。我们还注意到大多数机器学习模型在 AUC 上进行比较时的表现非常相似,但在排名指标(MRR10 和召回@1)上表现不同,如图 2 所示。
Trex比较:我们的结果表明,在 XO 任务上,Trex 具有与 Asm2Vec 以及其他 word2vec 变体相同的 AUC、相似的 MRR10 和 recall@1,略低于 GNN 和 GMN。 这巩固了语言模型在相同架构任务中表现出色的发现。 然而,与 Asm2Vec 不同的是,Trex 在 XA 和 XA+XO 任务中也保留了相同的性能,这显示了 Transformer 在(跨语言)跨架构设置中的强大功能。 我们确认 Trex 提高了 XO 任务(0.94 vs. 0.90)和 XA+XO 任务(0.94 vs. 0.91)中的 SAFE 性能。 我们的测试还表明,在 GPU 上运行的 Trex 的推理比我们的多进程 Asm2Vec 实现更快(100 个函数为 3.92 秒 vs. 8.51 秒)。
GNNs比较:Gemini 和 Li 等人提出的方法使用具有不同消息传递和聚合层变体的 GNN ,我们比较使用基本块特征(操作码的词袋 (BoW))和不使用特征的两个变体。 结果表明,Li 等人的 GNN 变体。 在所有任务中,比 Gemini 使用的 GNN (s2v) 都有显着改进。 然而,两个变体的执行时间仍然相似(不使用任何功能时为 1.48 秒与 1.40 秒)。
GNN (s2v) 特征集比较:Gemini 使用名为 Structure2vec (s2v)的 GNN 模型,并具有手动设计的特征。 我们的目标是了解这些特征对于根本没有特征向量或使用另一组特征(例如操作码的词袋(BoW))的重要性。 表 3 和表 4 中的结果表明,手动设计的特征仅在 XA 任务中的小型和大型函数上表现更好,并且BoW在所有不同指标中表现相似,甚至对不同的 K 值具有更好的召回率, 如图 2 所示。此外,由于 Gemini 中的特征提取阶段较长,执行时间也有所不同(1.66 秒与 7.18 秒)。 这意味着更复杂和更难以提取的特征不一定优于更基本的表示。 200 个操作码的 BoW 的特征数量是 Gemini 的 20 倍,这导致 GNN 的节点神经网络的输入矩阵更大。 我们还测试了 1024 个操作码的 BoW,但结果没有显着改善,这意味着这些附加功能对函数的表示没有显着贡献。
最后,我们想要测试使用指令嵌入作为 GNN 特征是否有助于提高 AUC,如[45]中所示。 我们的结果表明,归一化汇编上的指令嵌入没有比操作码或手动设计特征的词袋更高的 AUC(只有 RNN 基本块编码器达到类似的 AUC),MRR10 和召回@1 也较低,并且 训练时间大幅增加。
使用文本编码器对函数进行建模:SAFE[49]使用基于指令嵌入的句子编码器,AUC优于具有无监督特征的GNN(s2v)。 与Gemini[76]相比,AUC相似,但MRR10和recall@1较低。 SAFE 在小型函数上效果更好,并且当最大指令长度从 150 增加到 250 时,结果确实有所改善(表 3)。 然而,SAFE 需要面对词汇外(OOV)词的挑战。 如第 2 节中所述,其他方法(例如 InnerEye [82] 或 Mirror )应用不同的装配标准化技术来缓解此问题。 为了说明这一挑战,我们测量了 SAFE 中 OOV 指令的影响,我们观察到 x86-64 是受 OOV 问题影响最大的架构(不到 30% 的函数没有 OOV 字),这可能是由于其 CISC 指令集 ,其次是MIPS,最后是ARM,超过40%的功能没有一个OOV字。
Asm2Vec 和其他 paragraph2vec 模型:表 3 和表 4 显示了 Asm2Vec [14] 与 paragraph2vec [38] 的 PV-DM 和 PV-DBOW 变体的比较结果。 所有三个模型的性能相似,与 GNN [40] 相比,使用特定的单一架构方法并没有带来任何优势。 我们注意到结果受到几个因素的强烈影响,包括指令词汇量的大小、随机游走的数量和一些实现细节。 在训练过程中,我们选择了 1M 个令牌(1.9M 中),最小频率为 5,其中大多数是数字偏移量或十六进制地址。 降低该阈值确实可以改善结果,但也会增加词汇量和训练时间。 在推理时,我们没有更改词汇表,尽管这些无监督方法可以从新的推理词汇表中受益,而不会导致结果无效。 在我们的测试中,所有三个模型都共享相同的词汇。 我们还注意到,所有三种变体在只有一个变量空闲的情况下都实现了较高的 AUC,例如表 4 中的 XO 任务,但当同时考虑多个编译变量时,AUC 会下降,例如表 3 中的 XC 任务, 编译器、版本和优化发生变化的地方。
效率比较:我们还跟踪了这些方法对于训练(表 8)和测试时间(即推理时间)(表 4)的效率。 我们重点讨论第二个,因为训练模型主要是一次性的工作。 就推理时间而言,SAFE [49] 似乎是机器学习模型中最快的,处理 100 个函数只需 1.46 秒。 [40] 中的 GMN 和 GNN 具有相似的运行时间,并且运行时间最低,但是 GMN 仅处理输入中的一对函数。 具有 Gemini 特征的 GNN (s2v) [76] 比具有操作码特征的版本慢 4 倍:原因是特征提取时间较长。 Zeek [67] 推理时间也受到较长的特征提取和处理时间的影响,并且它是所有方法中最慢的。 由于额外的模型复杂性导致推理时间较长,因此具有无监督特征的 GNN (s2v) 在 RNN 变体中速度较慢。 同样,由于 NLP 模型的复杂性,Trex 也受到推理时间较长的影响。 最后,Asm2Vec [14] 是最慢的之一,因为它需要 10 轮推理才能提取新的函数嵌入。 有趣的是,由于特定的指令嵌入结构,Asm2Vec 比其他 paragraph2vec 模型慢。
CodeCMR/BinaryAI评估:在我们的评估中,我们还纳入了腾讯最近发表的一篇论文 CodeCMR [79]。 尝试复制这项工作及其前身时遇到了几个问题(中有更多详细信息),但作者很友善地帮助我们对数据集进行评估。 我们承认这种评估与我们为其余方法所做的重新实施工作不一致。 然而,我们相信 CodeCMR 非常有趣且有前途,我们发现将其添加到我们的论文中很有价值。 我们还注意到,另一种选择是尝试重新实施这种方法,但我们认为,由于系统的高度复杂性和许多“隐藏”的问题,对我们重新实施的准确性充满信心将极具挑战性。 论文中未讨论的变量。 我们现在讨论我们的评估的见解。
由于他们模型的最终目标是将二进制文件与源代码进行匹配,为了训练和测试我们的数据,他们隔离了模型中仅处理函数二进制数据的部分。 我们与他们分享了数据集子集的预处理版本,其中包含 ARM 和 x86 函数(32 位和 64 位),使用 IDAPro 和 HexRays 反编译器进行预处理。
提取的数据由带有 IDA 微代码指令的属性 CFG、整数个 ctree 以及来自函数数据的字符串组成。 为了进行基线比较,我们运行中的 GNN 模型,使用 200 个最常见操作码的词袋和 80 个 IDA 微代码指令的词袋作为基本块特征。
结果如表 5 所示。使用 IDA 微码指令 BoW 的 GNN 模型比使用操作码 BoW 的 GNN 模型具有更高的 AUC,但第二个模型对于大 K 值具有更高的召回率(图 3)。 一般来说,BinaryAI/CodeCMR 模型的所有指标都高于我们测试的其他模型。 如果这些结果得到社区独立研究的验证,这可能是一个非常有前途的研究方向。 事实上,2We 只能处理数据集的一个子集,因为我们无法访问最新版本的 HexRays MIPS 反编译器许可证(BinaryAI 插件需要 IDA 7.3 或更高版本)。 而且,HexRays仅支持MIPS 32位代码的反编译。 BinaryAI/CodeCMR 模型引入了多项创新。 首先,它将多个构建组件(即一个 NLP 编码器、一个 GNN 和两个 LSTM)合并到一个模型中,并使用端到端策略联合训练所有内容。 其次,作者在论文中表明,训练策略(例如,使用距离加权采样)和损失函数(例如,三元组损失[66])发挥着重要作用,并且可以产生显着的性能改进。