论文阅读笔记Binary Code Summarization: Benchmarking ChatGPT/GPT-4 and Other Large Language Models

摘要

二进制代码总结,虽然对于理解代码语义非常有价值,但由于其劳动密集的特性,具有挑战性。本研究深入探讨了大型语言模型(LLMs)在理解二进制代码方面的潜力。为此,作者提出了BinSum,一个包含超过557,000个二进制函数的全面基准和数据集,并引入了一种新颖的提示合成和优化方法。为了更准确地衡量LLM的性能,作者还提出了一种超越传统精确匹配方法的新语义相似度度量。作者对知名LLM进行了广泛评估,包括ChatGPT、GPT-4、Llama 2和Code Llama,揭示了10个关键见解。此评估生成了40亿推理令牌,总费用为11,418美元,使用了873个NVIDIA A100 GPU小时。作者的发现突显了LLMs在这一领域的转变潜力以及尚需克服的挑战。

Introduction

对于二进制分析和逆向工程而言,理解二进制代码至关重要,它深入研究软件的复杂细节以了解其功能[73]。尽管逆向工程的范围和结果可能因任务而异,例如恶意软件分析[52, 52]、漏洞识别[34, 47]和符号恢复[40, 59],但其基本目标保持一致:重建程序的逻辑并获取适用于特定任务目标的见解[48]。与代码理解和自然语言的交汇相呼应,VirusTotal最近推出了“Code Insight”,采用Google的Sec-PaLM生成潜在恶意代码段的自然语言摘要,提升了安全分析人员对威胁的理解和检测能力[11]。

尽管在自动化各种二进制分析任务方面已取得了显著进展[24, 68],但对于二进制代码语义的逆向工程仍然是一个需要人类专业知识的过程[48]。这项任务具有挑战性,需要相当的技能和时间投入,特别是考虑到缺乏高级语义,如符号名称和数据类型。例如,对于31名逆向工程专业人士平均需要约40分钟的时间来理解少于150行代码的恶意反编译代码[79]。诸如DARPA网络战大挑战(CGC)[7]的努力推动了计算机自主推理程序二进制的能力方面的进步。然而,这些自动化解决方案仍然远远不能与人类逆向工程专家的专业知识相媲美。

机器学习的最新进展,特别是大型语言模型(LLMs)的出现,如ChatGPT和GPT-4 [51],为解决这些挑战提供了一个有希望的途径。这些模型已经开启了“强人工智能”的潜力,使得能够进行与人类智能和理解密切相似的交互。LLMs的能力已经在二进制分析任务中引发了开创性的变革。值得注意的例子包括二进制符号恢复[28, 40]和内存别名分析[61]。此外,LLMs,尤其是像ChatGPT这样先进的模型,已经在文本/源代码理解和总结方面展示了有希望的结果[70, 81]。LLMs在各个领域的涌现和广泛应用提出了一个紧迫的问题:大型语言模型,包括ChatGPT、GPT-4和其他LLMs,能否有效地总结二进制代码的语义?

1.1 Challenges

评估LLMs在二进制代码总结中的全部潜力并不是一项简单的任务,原因如下面的挑战所示。

  1. 缺乏真实世界数据集。首先,与易于获取的文本和源代码语料库(例如CommonCrawl [6]和BigCode [41])不同,缺乏一个包含实际编译设置的各种二进制文件的全面大规模二进制代码总结数据集,使得数据集具有地面实况,这是一个重要的障碍。此外,虽然现有的LLMs只接受类似文本的输入,但二进制代码可以用不同的格式表示,例如汇编和反编译代码,这使得确定LLMs的最适输入变得具有挑战性。

  2. 黑盒模型中的语义差距。像ChatGPT和GPT-4这样的模型在广泛的文本数据语料库上进行预训练,其中包括稀疏表示的二进制代码。这导致了预训练和作者任务之间的语义差距,即二进制代码总结。此外,LLMs通常通过微调或提示策略来适应下游任务[46]。然而,微调LLMs对资源要求较高,因此对于闭源的ChatGPT和GPT-4来说,在计算上是不可行的。对于提示,已经发现使用不同提示指导LLMs可能产生不同的性能[84]。对于作者的任务,设计有效的提示以最大程度地提高LLMs的性能仍然具有挑战性,考虑到LLMs的黑盒性质,很难解释哪些特征或词汇对总结结果贡献最大。

3、相同语义的多样输出。LLMs生成自然语言的输出,因此生成的二进制代码摘要以模糊的文本格式呈现,其中包含语义上相似但在语法上不同的表达,例如缩写和同义词。准确评估这样的摘要结果是必要的,但也带来了一系列的困难。例如,相同的语义可以在相同情况下和LLM生成的摘要中以不同的单词、短语和句子来表达。

1.2 insight

应对上述挑战,作者提出对LLMs在二进制代码理解中的能力进行系统探索。具体而言,作者的研究基于以下关键见解:

  1. 利用代码注释作为具有不同二进制表示的真实情况。开发人员通常用注释来解释源代码的程序员意图和代码功能,因此大多数现有关于源代码摘要[67]和二进制代码摘要[23]的研究都将代码注释用作地面实况。此外,商业现成的二进制文件(COTS)使用不同的设置编译,即跨计算机体系结构和优化级别。在这样多样化的二进制文件中,现有的二进制分析工作使用了不同的二进制代码表示,例如XDA中的原始字节 [60],SymLM中的汇编代码 [40]和DITRY中的反编译代码 [28]。因此,作者使用代码注释构建了一个大规模数据集,作为二进制编译为4个体系结构和4个优化级别的地面实况摘要,从中进一步生成了4种不同的二进制表示。

  2. 利用上下文提示合成和优化。对于作者的任务,由有经验的二进制分析或提示工程专业人员制作的提示可能会使LLMs表现出色。然而,这种方法受到主观性的限制,可能无法充分优化LLMs的性能。与此同时,LLMs最近展示了自动提示合成和优化的巨大潜力。具体而言,LLMs具有类似于人类提示工程师的能力 [84],并展示了自我改进的能力 [37]。因此,作者建议首先在LLMs自己生成的上下文中搜索提示候选项池,然后优化LLM生成的和人工制作的提示,最后选择在作者的任务上评估获得最佳性能的提示。

  3. 使用语义嵌入计算相似性。常用的评估代码摘要的度量标准(例如BLEU [54],METEOR [26]和ROUGE [45])主要侧重于n-grams的精确匹配。然而,它们未能捕捉缩写、同义词和在语法上不同但在语义上相似的表达中相同的语义。对LLM生成的二进制代码摘要的评估应在语义层面进行。因此,作者建议使用语义嵌入计算相似性来评估LLMs的性能。

1.3 Contributions and Findings

这些见解指导了作者的研究设计,产生了10个关键的测量结果(R1-R10)(以及6个额外的发现(F1-F6))。接下来,作者概述主要贡献:

一个大规模、开源且全面的二进制代码摘要数据集:作者精心策划了44个开源项目(总共包含11,475,734行代码),这些项目编译成了在4个体系结构(即x86、x64、ARM和MIPS)和4个优化级别(O0-O3)上的二进制文件。通过作者的注释提取和函数-注释匹配,作者获得了557,664个基于注释的地面实况摘要的二进制函数。作者还生成了四种二进制代码表示,包括原始字节、汇编代码、中间表示(IR)以及反编译代码(带和不带调试符号),以及它们的源代码。

• 创新技术:为了生成最大化LLM性能的最佳提示,作者设计了一个包括上下文提示合成、提示变体生成、提示优化和任务特定提示选择的四步过程。此外,作者还引入了一种基于新颖的语义嵌入的评估度量,通过计算从预训练的LLM生成的语义嵌入为作者的任务的地面实况和LLM生成的摘要之间的语义相似性。

• 广泛的度量:作者专注于四个最先进的LLMs:GPT-4、ChatGPT(GPT-3.5)、Llama 2 [71] 和 Code Llama [66],它们在下游任务中展现了显著的影响和先进的性能,同时还包括现有的二进制代码摘要模型 BinT5 [23]。作者的四组关键评估总共生成了4,058,297,977个标记,花费了11,418美元和873个NVIDIA A100 GPU小时,得出了以下结果。首先,从二进制文件中剥离调试符号可能导致显著的语义损失(55.0%)(R1),而反编译代码是LLMs理解二进制代码的最佳表示(R2)。其次,在LLMs中,ChatGPT 和 Code Llama 分别在带和不带调试符号的情况下表现最佳,(R3)。 Code Llama 在一直优于 Llama 2,Code Llama 是通过微调 Llama 2 得到的基础模型,但仅对反编译代码进行微调并不能为 BinT5 提供令人满意的性能(R4)。此外,作者的效率研究显示,ChatGPT 和 Llama 2 模型分别比 GPT-4 和 Code Llama 模型快2.9倍和1.5倍(R5)。第三,针对四种计算机体系结构,LLMs 在带和不带符号的反编译代码上在 x64 和 MIPS 二进制上表现最佳,分别取得高达16.0%的更高分数(R6)。然而,对于不同优化级别,LLMs之间存在较小的性能差距(R7)。对不同反编译器(Ghidra、Hex-Rays 和 Angr)的输出的评估表明,LLMs 在 Hex-Rays 反编译代码上表现最佳,分数提高了60.7%(R8)。

作者进一步研究了哪些符号(即函数名称、变量名称和数据类型)对二进制代码语义做出了最大贡献,发现函数名称对这一语义贡献最大(R9)。最后,作者还研究了不同的提示工程技术,即零次尝试、少次尝试和思路链提示,针对作者的任务,并确定零次尝试提示是在综合考虑性能和成本时最佳的(R10)。除了度量结果,作者还通过案例研究(附录 §A.6、§A.7 和 §A.10)获得了六个发现(F1-F6),涉及LLM对二进制代码、GPT-4总结以及LLM总结漏洞的理解程度。作者的代码和数据集已在 https://github.com/xinjin95/BinSum 上发布。

2 Design

在这一部分,作者介绍了作者如何测量LLMs的二进制代码摘要能力的详细设计。请注意,类似于现有的研究[23, 33, 67, 75],作者专注于在函数级别对二进制代码进行摘要。为了清晰起见,作者将这一任务形式化为:给定从二进制可执行文件中提取的二进制函数 𝑓,以文本表示 𝑥𝑓 ∈ X,该表示可以呈现为原始字节、汇编代码、中间表示(IR)代码或反编译代码,作者将其与预定的提示 𝐼 连接,从而得到一个增强的输入 𝑥′𝑓= {𝐼; 𝑥𝑓}。使用此输入,一个二进制代码摘要系统,M: X → Y,生成一个自然语言摘要 𝑦 ∈ Y,概括了 𝑓 的语义要点。

作者对二进制代码摘要任务的研究遵循三个关键步骤:
(i) 作者首先通过编译开源代码库构建了一个全面的二进制代码摘要数据集,生成了在不同架构和优化级别下的多样化二进制文件。然后对这些二进制文件进行进一步处理,得到四种不同的二进制代码表示。
(ii) 接下来,作者遵循一个四步程序,通过任务特定的评估来合成、优化和选择最合适的提示。(iii) 最后,作者使用作者提出的语义摘要评估度量,在作者的数据集上评估了四个最先进的生成式LLMs和现有的二进制代码摘要模型(BinT5 [23])。在接下来的子章节中,作者提供这三个步骤的详细设计。

2.1 Dataset Construction

作者的研究旨在全面了解LLMs,这需要一个具有真实情况的庞大二进制代码数据集。在构建这样一个数据集之前,作者探索了现有的可以直接使用的数据集。据作者所知,BinT5是唯一研究与作者相同任务的工作 [23],但其重点在于反编译代码。其发布的数据1仅包括x86二进制文件,并在优化级别上分布不均衡,即O0-O3二进制文件的大致比例为1:2:6:2。作者得出结论,尽管这样的数据集在某种程度上有用,但未能满足作者获得深刻见解的目标。因此,作者选择从头开始构建一个数据集,以符合作者的研究目标,如图1所示。
在这里插入图片描述

二进制编译和剥离Binary Compilation and Stripping。作者的初始步骤涉及从GNU软件 [8] 中策划公共源项目,包括先前研究广泛使用的一些知名项目 [40, 43, 59],如coreutils、binutils和findutils。表3中列出了44个GNU项目的全面列表,涵盖了总共11,475,734行代码。选择这些GNU软件项目的原因是它们得到了良好的开发和维护。然后,作者使用GCC7.5将它们编译成四个体系结构(x86、x64、ARM和MIPS)和四个优化级别(O0-O3),从而产生具有调试信息的8,760个唯一的二进制文件。接下来,作者通过移除符号生成另外8,760个剥离符号的二进制文件。值得注意的是,对于ARM和MIPS二进制文件,作者在过程中使用了交叉编译器和剥离工具(详见§A.2)。

Source Code Comment Extraction 源代码注释提取。如 §1 中所提到的,作者决定使用开发人员编写的注释作为真实情况。然而,作者的二进制文件不包含任何注释,因为这些注释已经被编译器的预处理器移除了。因此,作者需要从源代码中提取代码注释以注解二进制函数,这是一个全新的任务,因此尚未为此设计公开可用的工具。因此,作者首先构建了一个源代码解析器来实现这一点。具体而言,对于具有调试信息的二进制文件的DWARF条目中的每个二进制函数,作者定位并使用其在源代码中对应函数的注释作为真实情况。

然而,这个过程需要精确识别注释和源代码函数,尤其是函数名称,这带来了几个挑战。首先,开发人员通常不仅为函数编写注释,还为其他代码元素编写注释,比如宏定义、语句和基本块,如图2所示。很难辨别专门用于函数的注释。例如,图2中仅在第11和12行的注释是目标函数yylex_destroy的所需注释。此外,与在一行中定义签名不同,此示例显示了一个多行签名定义(第13到15行),这意味着基于简单文本解析的方法可能无法识别所需的函数名称。此外,除了在源(.c)文件中进行注释外,开发人员还会在头文件(.h)中进行注释,这进一步增加了问题的复杂性。

幸运的是,作者已经开发了一个自动化的源代码注释解析器(图1中的步骤❷),以解决所有这些挑战,如图3所示,基于srcML [30] 和 ANTLR [55]。具体而言,对450个GNU源函数的手动研究发现:(i) 头文件中的注释通常在相应的源文件函数定义中重复出现;(ii) C函数注释主要放置在它们的签名上方,使用’//‘和’/ * * /'分别表示单行和多行注释。基于这些观察,作者的解析器旨在从源文件中提取函数和注释。函数识别模块通过ANTLR构建抽象语法树(AST),将AST转换为带有srcML的XML文档,并定位XML标记的函数,输出函数签名(𝑠𝑖𝑔𝑓)和行范围(𝑙𝑜𝑐𝑓)。同时,注释解析模块使用正则表达式识别注释文本(𝑡𝑒𝑥𝑡𝑐)及其行范围(𝑙𝑜𝑐𝑐)。为了将函数与注释关联起来,作者配对注释和后续函数,其行号是相邻连续的,得到匹配的函数-注释条目。值得注意的是,作者在分析中排除内部函数注释(例如,第17和21行的注释)。因为这样的注释不能完全概括函数的语义。此外,将这些注释映射到二进制代码中相应的块是非常具有挑战性的,因为缺乏指示性的符号。

在获取了源代码函数-注释对之后,作者必须使用这些注释为二进制函数进行注解。作者提出的匹配方法基于两个见解:(i) 具有调试信息的二进制文件通过DWARF条目提供函数名称和地址。在掌控源代码的情况下,作者确保生成DWARF符号,并从未剥离的二进制文件中保留函数地址;(ii) 内部二进制函数具有独特的、不冲突的名称,充当标识符,有助于与源代码函数-注释对匹配。基于这些见解,作者使用Ghidra [21] 解析DWARF条目,获取二进制函数的名称和边界(起始和结束地址)。然后,作者从每个源代码函数-注释条目的签名(𝑠𝑖𝑔𝑓)中提取函数名称。最终的匹配过程(图1中的步骤❸)使用函数名称将二进制函数地址与其相关的源代码注释配对。这种方法在具有调试符号的8,760个二进制文件中识别了557,664个二进制函数的注释。在图1的步骤❹中,为二进制函数生成了四种表示:原始字节、汇编代码、IR代码和反编译代码(详见§3)。

小番外:

DWARF(Debugging With Attributed Record Formats)是一种用于调试信息的标准格式。在软件开发中,特别是在编译后的可执行文件中,DWARF格式用于存储与源代码的调试信息相关的数据。这些信息包括源代码文件名、行号、变量名、函数名等,以便在调试过程中能够将机器码映射回源代码。

DWARF条目指的是在DWARF调试信息中的一个记录或条目。这些记录包含了与程序执行和源代码之间关系密切的信息,通常由编译器在构建可执行文件时生成。在调试时,开发人员可以使用这些信息来追踪和理解程序的执行,进行断点设置,查看变量的值等。

2.2 Prompt Synthesis and Optimization

正如在第1.2节中讨论的,作者已经观察到使用提示来指导LLMs以zero-shot方式生成摘要的巨大潜力。然而,用于二进制代码摘要的理想提示仍然是隐含的但必要的,因为LLMs对输入提示非常敏感 [84]。一个直观的解决方案是从经验丰富的提示工程师或二进制分析专业人员那里获取提示,但这种方法有其局限性。首先,人类提示创建者可能受到他们的知识和创造力的限制,导致次优的提示。此外,LLMs可能表现出与人类期望不符的行为 [84]。最后,不清楚这些提示是否能够优化LLMs的性能,因为LLMs是黑盒的。在图4中,作者提出了一个四步的解决方案,包括:(1)上下文提示合成,(2)提示变体生成,(3)提示优化和(4)任务特定提示选择。

(1) 上下文提示合成。 在这种方法中,作者利用LLMs在二进制代码摘要的上下文中自行生成一组候选提示。这种设计选择受到了人类用户在面对新任务时与LLMs互动的方式的启发。在这种情况下,人类用户通常需要尝试各种提示以引出期望的响应。由于提示搜索空间几乎是无限的,手动生成大量提示非常具有挑战性。同时,LLMs本身已经展现出非常有前途的文本生成能力 [51],这激发了作者提出自动提示合成方法的动力。形式上,作者考虑由数据集 D = {𝑥𝑖,𝑦𝑖} 𝑁 𝑖=1 指定的二进制代码摘要任务,其中包含一个针对模型 M 的提示,其中 𝑥𝑖 和 𝑦𝑖 分别是输入二进制代码和代码摘要。作者的目标是生成一个合适的提示,表示为 𝑝,在这种情况下,当 M 给定连接的输入(𝑝; 𝑥)时,M 生成相应的输出 𝑦。作者将这个任务视为一个优化问题,找到最优的提示 𝑝ˆ。这个优化的中心点是在所有潜在的 (𝑥, 𝑦) 对上最大化期望得分 𝑆M (𝑝, 𝑥, 𝑦):
在这里插入图片描述

其中 𝑆M (·) 可以通过多种方式计算,例如聚合的令牌概率 [84] 和束搜索概率 [44]。然而,作者观察到像ChatGPT这样基于API的LLMs是黑盒生成器。也就是说,LLM的输出不包含任何概率产品;因此,这些基于概率的得分函数无法应用于作者的任务。作为替代,作者直接将由最大化自回归预测概率生成的前1个LLM生成的提示作为 𝑝ˆ,这可以表示 𝑆M (𝑝, 𝑥, 𝑦) 的最大分数。除了合成的提示,作者还包括人工创建的提示,以增加作者的提示候选池的大小和多样性,如图4所示。

(2) 提示变体生成。 在作者初始的提示候选池中,可能会有这种合成方法不足的情况,可能是因为缺乏多样性或没有足够高分的候选提示。针对这类问题,作者生成语义上类似于候选提示的提示变体,如图4所示。这种方法主要是在当前最佳候选附近探索搜索空间。因此,它使作者能够创建更有可能产生良好结果的新提示。

(3) 提示优化。 为了进一步提高LLMs在二进制代码摘要的上下文中的性能,作者引入了一种策略,使用LLMs自身优化先前合成的提示及其变体。作者的设计选择受到先前研究的启发,该研究表明LLMs可以优化线性回归和旅行推销员问题 [80],并且LLMs也能够自我改进 [37]。在作者的任务中,利用LLMs进行提示优化的优势在于它们理解自然语言的能力,即使作者能够通过高层次的文本指令传达作者的提示优化目标,而无需正式的规范。鉴于候选提示,作者指导LLMs通过元指令充当提示优化器。这个元指令包含目标函数,即最大化性能,和解决方案约束,即二进制代码摘要任务的上下文,如图4所示。

(4) 任务特定提示选择。在通过提示合成和优化生成提示候选池之后,后续的选择步骤变得至关重要,以确定作者任务中最有前途的候选提示。这个过程与Upper Confidence Bound (UCB) 优化中最佳臂识别问题紧密相关 [63]。在这个背景下,臂对应于提示候选,每个臂的隐藏值表示其在作者任务中的性能,臂拉动操作对应于使用随机选择的数据点评估提示。最终目标是识别出性能最佳的臂,同时最小化达到此结果所需的拉动努力次数。

在整个数据集上评估每个候选提示是一项资源密集型的过程,成本昂贵且难以承受。受以前高效估算提示性能的研究的启发 [84],作者通过在从作者的数据集中随机选择的数据样本子集上评估它们来评估提示候选。图4展示了作者的进行方式:作者首先通过使用每个提示候选和测试二进制样本连接查询LLMs生成二进制代码摘要。然后,通过计算与实际情况的语义相似性分数来评估生成的摘要(有关评估器详细信息,请参见§2.3)。最后,选择具有最佳分数的提示作为作者后续评估的最终提示。

2.3 Testing and Semantic Evaluation

作者的目标是评估现有LLMs在作者的任务上的表现。为此,作者采用了一个两步的过程:(1) LLM在二进制代码摘要上的测试和 (2) 语义摘要相似性评估。

(1) LLM在二进制代码摘要上的测试。

为了生成摘要,作者将选定的提示与测试二进制代码样本连接以准备模型输入。这种配置基本上使作者处于零射击设置中,同时考虑性能和成本方面的考虑(有关不同提示设置的评估,请参见§4.5)。由于LLMs是生成模型,它们可以生成不同长度的摘要。然而,过于冗长的摘要通常被认为是低质量的 [39]。因此,作者对目标模型的响应长度设置了限制。例如,作者在提示中明确指定这些限制,并使用指令“以 𝑁 个字摘要…”,其中 𝑁 是作者数据集中实际摘要的平均字数。作者观察到作者的测试模型在生成摘要时表现出自适应长度的行为。也就是说,它们倾向于生成长度接近预定长度限制的摘要,表现出一种能够智能调整长度的能力,而不是僵化地遵循预定长度限制。考虑到二进制代码样本的固有多样性,这是有益的。

(2) 语义摘要相似性评估。

为了评估LLMs生成的二进制代码摘要,作者的目标是估计它们与真实摘要的一致性。为此,作者注意到之前的源代码和二进制代码摘要研究 [23, 67] 都使用基于精确匹配的度量标准,如BLEU [54]、METEOR [26] 和ROUGE [45]。作者发现这些度量标准在捕捉摘要的基本语义方面存在不足(请参见F4和附录§A.6)。作为替代,作者提出基于语义测量来解决这个问题。为此,作者观察到预训练的LLMs,如BERT和XLNet,在文本语义建模任务中取得了成功 [49]。因此,作者可以使用这些预训练模型作为语义测量,计算LLM生成的摘要与实际摘要之间的语义相似性。
形式上,给定表示生成的摘要 𝑆 = {𝑤1,𝑤2, …,𝑤𝑛} 和实际摘要参考 ˆ𝑆 = {𝑤ˆ1,𝑤ˆ2, …,𝑤ˆ𝑚} 的两个单词序列,预训练LLM生成语义嵌入,分别为 𝑆 和 ˆ𝑆 的每个标记:E (𝑆) = {𝑒𝑤1, 𝑒𝑤2, …, 𝑒𝑤𝑛} 和 E ( ˆ𝑆) = {𝑒𝑤ˆ1, 𝑒𝑤ˆ2, …, 𝑒𝑤ˆ𝑚},其中 𝑒𝑤 ∈ R
𝑁 是标记 𝑤 的嵌入。然后,通过汇总它们的标记嵌入,计算代表 𝑆 和 ˆ𝑆 整体语义的嵌入 𝑒𝑆 ∈ R𝑁 和𝑒𝑆ˆ ∈ R𝑁。
在这里插入图片描述

这里,作者使用均值池化作为聚合函数,该函数在文本嵌入任务中表现出优越的结果 [65]。最后,作者通过余弦相似性函数计算生成的摘要与实际摘要参考之间的语义相似性,按照最佳实践进行 [50]:
在这里插入图片描述

语义相似性得分 𝑠𝑖𝑚(𝑆, ˆ𝑆) 量化了生成摘要与摘要参考之间的一致性。更高的相似性得分表示生成的摘要质量更高。图5说明了计算这种语义相似性得分的过程。

在这里插入图片描述

3 IMPLEMENTATION

数据集构建。如第2.1节所示,作者通过编译44个开源项目,总共有11,475,734行代码(附录中的表3有更多细节),构建了一个二进制代码摘要数据集。作者的数据集包含557,664个具有实际摘要的二进制函数。这些函数来自各种二进制文件,并且它们在架构(x64、x86、ARM、MIPS)和优化级别(O0-O3)上的分布在附录的表4中供读者参考。对于数据集中的每个函数,作者生成了四种二进制代码表示以及源代码:

• 原始字节是基于函数的起始和结束地址直接从二进制文件中提取的(见第2.1节)。
• 汇编代码是通过使用capstone [2]和pyelftools [18]库解析ELF二进制文件生成的。
• IR代码是由作者的IDA插件生成的IDA微代码,该插件建立在ida_hexrays.gen_microcode API [13]之上,作者遵循了之前的二进制分析研究 [82, 83],使用了被广泛采用的IDA微代码作为IR代码。
• 反编译代码包括由Ghidra、Hex-rays和Angr生成的输出,分别使用getDecompiledFunction [17]、idaapi.decompile [14]和angr.analyses.Decompiler [1] API。作者选择了Ghidra和Hex-rays,因为它们是知名的反编译器。另一方面,选择Angr是因为它在二进制分析方面具有快速增长和全面的能力。
• 源代码是通过解析源文件根据函数的起始和结束行号生成的。请注意,作者排除了函数注释,以避免在测试LLMs的摘要功能时泄露信息。

提示的合成和评估。 作者基于作者的提示合成和优化方法生成了一组320个提示候选项。正如第2.2节中任务特定提示选择部分所提到的,评估在整个二进制汇总数据集上的所有提示候选项是代价高昂的,因此不切实际。因此,作者从数据集中随机选择了1000个二进制函数样本,使用每个提示候选项进行二进制代码汇总。表5呈现了按语义相似性排名的前40个提示。作者选择了最佳提示进行后续评估。为了公平比较,作者对所有模型使用相同的提示,除了BinT5,它只接受反编译代码作为输入(详见§A.5以获取更多详细信息)。

评估指标。 作者的评估指标包括作者在§2.3中提出的语义相似性指标。具体而言,作者在Pytorch [56]、SentenceTransformers [65]、Scipy [72]和Sentencepiece [42]的基础上实现了作者的评估框架。对于摘要编码器模型,作者使用了预训练的all-mpnet-base-v2模型,在14个文本嵌入任务中表现最佳 [19]。为了在Equation 2中高效计算𝑒𝑆和𝑒𝑆ˆ,作者将令牌嵌入存储在Chroma向量数据库 [4]中。计算出的语义相似性分数范围从-1到1,其中接近1的分数表示LLM生成的代码摘要质量很高。除了作者提出的度量,作者还计算并报告了BLEU [54]、METEOR [26]和ROUGE-L [45]的分数,以促进未来的研究,因为这些度量先前已在源代码和二进制代码摘要研究中使用过 [23, 67, 75]。 BLEU、METEOR和ROUGE-L的计算细节在附录§A.4中。 BLEU、METEOR和ROUGE-L的分数在0到1之间缩放,数值较高表示摘要质量更高。

目标LLMs。作者感兴趣的LLMs包括GPT-4、ChatGPT、Llama 2(7B)、Llama 2(13B)、Code Llama(7B)、Code Llama(13B)和BinT5 [23],如表1所示,它在许多NLP和与代码相关的任务中表现出卓越性能[15, 51, 71]。为了测试GPT-4和ChatGPT,作者使用OpenAI的聊天完成API(openai.Completion.create)[16],它们调用的是gpt-4-0613和gpt-3.5-turbo-16k-0613后端模型,对应于2023年6月13日发布的0613快照。为了获得一致的结果,作者将温度参数[16]设置为0.1,该参数控制模型的多样性和创造性输出。此外,作者将top_p和n都设置为1,以获得top-1的结果[16]。关于参数stop和max_tokens,作者选择了默认值[16],允许模型自主确定何时结束其响应。为了提高推理速度,作者实施了多线程,分别使用了五个和六个并行线程进行GPT-4和ChatGPT的推理,同时确保符合OpenAI设定的速率限制[22]。

作者从Huggingface下载了Llama模型,包括meta-llama/Llama-2-7b-chat-hf、meta-llama/Llama-2-13b-chat-hf、codellama/CodeLlama-7b-Instruct-hf和codellama/CodeLlama-13b-Instruct-hf [5, 12]。为了运行这些模型,作者基于Pytorch [56]、transformers [78]、Scikit-learn [58]和DeepSpeed [64]实现了一个推理框架。为了进行高效的推理,作者启用了BF16的混合精度,并将批处理大小设置为6。作者直接使用它们的分词器和预训练模型权重。作者将温度设置为0.1,将top_k和top_p都设置为1,以获得最佳摘要。对于BinT5,它只接受反编译代码,因此作者只用它来总结反编译代码。作者将其推理批处理大小设置为64,使用其最大上下文大小,即512。

4 EVALUATION

在本节中,作者展示了作者的评估结果。虽然围绕这个测量有很多研究问题(RQ),但作者试图回答以下几个问题:

  • RQ1:LLMs在多大程度上能理解二进制代码?二进制代码的哪些输入对LLM的输出影响更大?
  • RQ2:哪个LLM在二进制代码理解方面表现最好?哪个LLM比其他LLMs更高效?
  • RQ3:不同的计算机体系结构和优化级别如何影响LLMs的性能?
  • RQ4:除了二进制代码输入之外,还有哪些因素影响LLMs的理解能力?

4.1 Evaluation Setup

  • 评估环境。作者的评估环境包括一台ThinkPad P15台式机和一台Dell云服务器。ThinkPad 台式机配备有Intel i9-10885H vPro CPU(8核,2.4 GHz)、128 GB RAM、1TB 存储和一块NVIDIA Quadro RTX 4000 Max-Q GPU,运行Windows-11。Dell 云服务器配备有AMD EPYC-7643 CPU(88个可用核心,2.3 GHz)、921 GB RAM、12.8 TB 存储和4块NVIDIA A100 GPU,每块GPU具有80 GB VRAM,通过NVLink与RHEL-8.6操作系统协同工作。

  • 模型执行。作者在二进制代码摘要数据集上运行了GPT-4和ChatGPT,分别完成了20天和6天的任务。GPT-4对所有测试样本进行了309,401,126个标记,并生成了总计19,678,448个标记,总计329,079,574个标记,如表1的第一行所报告的。对于ChatGPT,输入样本被标记为296,524,698个,生成了16,338,012个标记,总计312,862,710个标记。就成本而言,作者为查询GPT-4和ChatGPT模型分别花费了10,462.74美元和954.93美元。对于Llama 2和Code Llama模型,它们将作者的输入样本标记为736,413,994个标记,并生成33,195,771、29,699,869、40,016,196和33,323,576个标记作为响应。Llama模型的执行花费了作者857个GPU小时。最后,BinT5生成了326,007,985个标记,其中包括326,007,985个输入标记和8,456,320个输出标记,耗时16个GPU小时。总之,模型执行成本为11,418美元和873个NVIDIA A100 GPU小时。

4.2 RQ1: Effectiveness

为了回答RQ1,作者首先评估了LLMs在不同表示形式的二进制代码上的性能,包括反编译代码、IR代码、汇编代码、原始字节以及源代码,并在图6中呈现了结果,其中BinT5的性能没有包含在内,以进行公正比较,因为它只接受反编译代码。在不同的代码表示形式中,作者发现LLMs在源代码中表现最佳,达到了平均语义相似度得分为0.474。对于反编译代码,作者观察到当从二进制文件中剥离符号时性能显著下降,将语义相似度得分从0.449降至0.202(减少了55.0%)。

结果1(R1) - 剥离调试符号显著降低了反编译代码的语义,降幅为55.0%。

即使有这么大的信息丢失,没有符号的反编译代码仍然优于其他二进制代码表示。具体而言,汇编代码、IR代码和原始字节的平均语义相似度分数分别为0.188、0.185和0.118。这个趋势在其他评估指标中也是一样的,例如平均METEOR分数为对于源代码,反编译代码(调试)、反编译代码(剥离)、IR代码、汇编代码和原始字节分别为0.167、0.141、0.102、0.052、0.066和0.023。

结果2(R2) - 与IR代码、汇编代码和原始字节相比,LLMs在反编译代码上表现最佳。

在获得统计结果后,作者还进行了深入研究,以了解LLMs在多大程度上能够理解二进制代码,以及对特定评分结果的微妙解释。这项研究的结果在附录 §A.6 中呈现,以供感兴趣的读者参考。总体而言,作者对LLM生成的摘要的案例研究进一步确认了由于符号剥离而导致的二进制代码语义恶化(F1)。此外,LLMs倾向于为低级二进制表示(即IR和汇编代码)生成操作摘要,而不是阐明高级功能(F2)。在原始字节的情况下,有趣的是注意到LLM生成的摘要与汇编代码的摘要非常相似,表明了隐式的代码提升行为(F3)。与基于精确匹配的度量标准相比,作者提出的语义评估指标更适用于作者的任务,因为它能够有效捕捉摘要的语义(F4)。

4.3 RQ2: LLM Comparison

为了回答RQ2,作者研究了每个目标LLM的单独性能。在确定反汇编代码对LLMs理解二进制代码最为有效(R2)之后,作者的报告强调了LLMs在反汇编代码上的性能,如图7所示。对于带有符号的反汇编代码,作者发现ChatGPT的性能最佳,平均语义相似度得分为0.543。与此同时,对于剥离了符号的二进制代码,Code Llama模型优于其他所有LLMs,7B和13B模型的平均语义相似度得分为0.284和0.283。令人惊讶的是,GPT-4并不是性能最佳的模型。因此,作者对其结果进行了彻底的审查。总体而言,作者观察到GPT-4能够理解二进制代码。然而,与ChatGPT相比,它更加注重复杂和多余的细节,导致了摘要中的噪音(F5)。附录 §A.7 提供了更详细的分析和具体示例。

Result 3(R3)- 与GPT-4、Llama 2和BinT5相比,ChatGPT和Code Llama在带有符号和剥离了符号的反汇编代码上表现最佳。

Code Llama 是在 Llama 2 [66] 的代码语料库上进行了微调。对于带有符号的反汇编代码,Code Llama 在 7B 和 13B 模型上的性能分别比 Llama 2 提高了 4.57% 和 11.3%。对于来自剥离符号的二进制代码的反汇编代码,Code Llama 模型在 7B 和 13B 模型上进一步超过 Llama 2 模型分别达到 12.3% 和 22.0% 的性能提升。这表明 Code Llama 的微调可以提高其对二进制代码理解的能力。与此同时,BinT5 是通过对反汇编代码进行再训练从 CodeT5 模型微调而来的 [23]。不幸的是,与所有其他LLM相比,BinT5 生成的摘要在带符号和不带符号的二进制文件上都获得了最低的语义相似性得分,即 0.115 和 0.114。值得注意的是,为了在LLM之间进行公正而不偏见的比较,作者已经排除了存在于BinT5的训练数据集中的测试样本(详见§A.8进行更多讨论)。BinT5在带符号和不带符号的二进制文件中的微小性能差异表明,即使在有符号的情况下,它可能仍然无法完全捕捉二进制代码中的复杂语义。更重要的是,作者假设 Code Llama 和 BinT5 中微调的不同影响可能源于它们基础模型的差异,即 Llama 2 和 CodeT5。

结果 4(R4) - Code Llama,从 Llama 2 微调而来,一贯优于 Llama 2(最高得分提高了 22.0%)。然而,从 CodeT5 微调而来的 BinT5 不幸地在所有LLM中取得了最差的表现。

如表1所列,不同的LLM具有不同的模型大小和参数,这可能导致不同的效率。因此,作者评估并比较了目标模型的每个样本的推理时间成本。表2呈现了不同LLM每个样本的平均推理时间。这里,作者有两种不同的评估设置,如第4.1节的模型执行部分所述。对于ChatGPT和GPT-4,它们的执行依赖于OpenAI API调用,很难确定支持它们运行的计算基础架构。它们的直接比较表明ChatGPT比GPT-4快2.9倍。对于其他模型,作者在作者自己的云服务器上运行它们,这使作者可以进行公平比较。在这些模型中,BinT5是所有模型中最快的,例如比Code Llama(13B)快7.8倍。作者还发现,与Llama 2相比,Code Llama的推理时间更长,例如在13B模型上需要1.5倍的时间。除了时间成本之外,作者还观察到开源LLM之间的内存消耗差异。具体而言,7B和13B的Llama模型分别占用42.6GB和61.9GB的GPU VRAM,而BinT5模型仅占用3.4GB的VRAM。

在这里插入图片描述

Result 5(R5)- 与GPT-4相比,ChatGPT更快2.9倍。对于其他LLM,BinT5是最快的模型,而Llama 2比Code Llama更快(最多1.5倍)。

4.4 RQ3: Various Binaries

为了回答RQ3,作者首先研究LLMs在不同计算机体系结构的二进制文件上的性能。图8展示了在不同体系结构(即x86、x64、ARM和MIPS)的二进制文件上的性能。对于带有符号的二进制文件,x86、x64、ARM和MIPS的平均语义相似性分数分别为0.483、0.503、0.497和0.485。在x64二进制文件上的性能比x86二进制文件高出4.14%。对于去除符号的二进制文件,x86、x64、ARM和MIPS二进制文件的相似性分数分别为0.262、0.299、0.276和0.304,其中MIPS二进制文件的性能比x86二进制文件高出16.0%。

结果6(R6)- LLMs在带有符号的x64二进制文件和剥离符号的MIPS二进制文件上表现最佳。跨体系结构的性能差距可以高达16.0%。

在图9中,作者展示了LLMs应用于具有O0、O1、O2和O3优化级的二进制文件时的性能。对于带有符号的二进制文件,LLMs分别在O0、O1、O2和O3的二进制文件上获得了平均文本相似度分数为0.481、0.477、0.477和0.474。相反,对于剥离符号的二进制文件,这些二进制优化级的平均文本相似度分数为0.269、0.268、0.266和0.270。在两类二进制文件中,作者注意到在不同优化级之间性能只有轻微的差异,O0和O3二进制文件之间的性能差距仅为1.47%。

结果7(R7)- LLMs在不同优化级之间显示出微小的性能差距,例如,在O0和O3二进制文件之间的文本相似度分数仅相差1.47%。

在这里插入图片描述

4.5 RQ4: Other Factors

由于作者已经确定反编译代码是LLMs理解最好的(R2),接下来作者进行进一步调查,找出哪个反编译器生成了最适合代码理解的输出,以回答RQ4。图10展示了LLMs在三种不同反编译器生成的反编译代码上的性能。总体而言,作者发现Hex-rays在带有符号和不带符号的二进制文件上一直优于另外两个反编译器。具体来说,在带有符号的二进制文件中,Hex-rays的输出比Ghidra和Angr分别高出5.41%和21.9%的语义相似度分数。对于剥离符号的二进制文件,它分别比Ghidra和Angr高出60.7%和19.8%。在这些反编译器中,作者观察到Angr明显比其他反编译器慢。例如,使用设置了CFGFast分析的Angr,Angr的反编译时间比Ghira多约15倍,而Ghidra和Hex-rays在相同任务上消耗相近的时间。

在这里插入图片描述

结果8(R8)- Hex-rays生成的反编译代码输出在得分上表现最好,相较于Ghidra和Angr,取得高达60.7%的优势。

观察从剥离符号(R1)中的性能下降,作者深入研究以辨别三种符号类型中的哪一种—数据类型、变量名和函数名—最影响反编译代码语义。从具有所有符号的原始反编译代码作为基准开始,作者通过用非信息性的占位符替换每种符号类型来排他性地剥离它们(详见§A.9)。这产生了三组修改后的反编译代码,每组只替换一种符号类型,而其余保持不变。此外,作者使用来自剥离符号的二进制文件的反编译代码作为移除所有符号的基准。图11展示了在这些变化中LLMs的性能。仅剥离函数名导致性能大幅下降,语义相似度减少了30.3%。变量名和数据类型分别导致了30.0%和19.5%的降低。 此外,作者还发现LLM生成的摘要的语义可以通过有意修改函数名来操纵。为此,作者进行了一项案例研究,并在§A.10中通过函数名操纵识别了LLM生成的摘要的一个漏洞(F6)。
在这里插入图片描述

结果9(R9)- 函数名对于反编译代码的语义贡献最大。仅仅剥离函数名就能够将LLM的性能降低30.3%。

图12展示了不同提示的性能,其中零-shot、few-shot和chain-of-thought提示的平均语义相似度得分分别为0.282、0.312和0.271。与零-shot提示相比,few-shot提示提高了LLM的性能10.6%,而chain-of-thought推理则没有帮助。除了性能上的差异,作者还注意到成本存在相当大的变化。
在这里插入图片描述

图13展示了不同提示的长度分布,其中零-shot、few-shot和chain-of-thought提示的中位数标记数分别为244、1,763和944。few-shot提示的7.23倍更多的标记意味着显著更高的计算成本。例如,由于ChatGPT和GPT-4的使用基于标记数的变化,few-shot提示将花费作者82,552美元来完成表1中列出的相同数量的标记。考虑到作者评估的规模,零-shot学习可能是基于性能和成本平衡的更好解决方案。
在这里插入图片描述

Result 10 (R10) – 在考虑性能和成本的同时,对于作者的大规模任务,零-shot提示优于few-shot和chain-of-thought提示。

小番外

“Zero-shot” 和 “few-shot” 是与机器学习和自然语言处理中的模型训练和评估相关的术语。

  1. Zero-shot learning(零-shot学习)

    • 定义:在模型训练过程中,零-shot学习是指模型在没有直接观察过相关示例的情况下,对新任务或新类别进行推理或泛化的能力。
    • 应用:在自然语言处理中,例如,对于一个文本分类模型,如果该模型能够在没有任何该类别样本的情况下对新类别进行分类,那么就可以说它具有零-shot学习能力。
  2. Few-shot learning(少样本学习)

    • 定义:与零-shot学习不同,few-shot学习允许模型在只有很少样本(通常是很少的训练示例)的情况下学习和推理。这个范畴通常包括有限数量的训练示例,但远少于传统的大规模训练集。
    • 应用:在自然语言处理中,few-shot学习可能涉及模型在只有几个样本的情况下学习执行特定任务,如问题回答或命名实体识别。

在上下文中,作者提到在研究中主要使用"zero-shot prompts",这可能表示在给定的任务中,模型在没有示例输入的情况下进行学习和推理。而"few-shot prompts" 可能包括一些示例输入,帮助模型更好地理解和执行任务。

5 LESSONS LEARNT

二进制代码理解至关重要。 尽管二进制代码摘要仍处于初级阶段[23],但对于二进制代码的自然语言摘要的需求迅速增长[9, 10, 20]。像VirusTotal[20]、Google Cloud[9]和Microsoft Security Copilot[10]等显著实体越来越多地利用LLMs来理解恶意软件/威胁,旨在为安全专业人员生成可立即使用的摘要。然而,二进制代码理解仍然是一个艰巨的挑战,特别是对于剥离了符号信息的二进制文件。在作者的研究中,LLMs要么无法把握完整的语义(F1),要么生成缺乏高级代码语义细微差别的摘要(F2)。二进制代码的多层次性质,以及它们多样的表示形式,使这一挑战更为复杂。例如,LLM在不同的二进制表示形式之间的性能差异(R2)以及对反编译器输出的敏感性(R8)。此外,不同的编译设置,如计算机体系结构,也可能影响LLM的结果(R6)。在探索这个复杂的领域时,作者的研究结果提供了关键的见解,可以指导未来全面理解二进制代码的努力。

利用LLMs需要进一步的进展和探索。 机器学习模型在二进制分析中得到广泛应用,然而许多模型在泛化到未见样本方面面临挑战[28, 40]。相比之下,像ChatGPT和GPT-4这样的LLMs拥有出色的泛化能力,这对于各种各样的现实世界二进制文件至关重要。然而,这些有前途的模型也存在局限性。它们对资源的需求较大,GPT和Llama模型需要昂贵的计算资源和专门的硬件加速器(§4.3)。潜在的解决方案可能在于模型蒸馏和硬件加速技术[32],特别是因为较小的模型已被证明更加资源友好(R5)。LLMs的黑盒特性提出了另一个挑战,使得解读它们的确切行为变得棘手。然而,作者的工作表明,通过改进和优化提示可能是前进的一条道路,正如作者在提示评估中强调的那样(表5和R10)。此外,虽然微调LLMs可以增强对二进制代码的理解,但选择正确的基础模型是至关重要的,正如作者在R4中强调的那样。本质上,虽然LLMs在二进制代码分析中具有巨大的潜力,但它们的有效部署取决于计算挑战,需要选择正确的模型和输入。

增强反编译器对于提高二进制代码理解至关重要。 作者的研究表明,对于LLMs来说,反编译的代码最直观(R2)。增强反编译器,特别是对于剥离符号的二进制文件,具有重要意义。作者的发现表明,二进制剥离可以极大地降低反编译代码的语义(R1)。此外,除了BinT5 [23]之外,所有其他LLMs在有符号和无符号二进制文件上都存在显著的性能差距(图7)。这导致LLMs无法完全捕捉剥离二进制函数的语义(F1)。加强反编译器的一个有希望的方法是符号恢复[25, 28, 40],如图11所示。作者的研究指出,对于影响反编译代码语义的因素,函数名预测[31, 40, 57]尤为重要,因为它对反编译代码的语义贡献至关重要(R9)。二进制函数名的一致性检查也很重要,特别是因为LLM生成的摘要容易受到通过故意更改函数名进行恶意操纵的影响(F6)。目前,Hex-Rays是领先的反编译器,始终产生LLMs表现最佳的输出(R8)。展望未来,作者相信作者研究的见解可以成为改进反编译器的宝贵指导。

6 THREATS TO VALIDITY

研究范围与二进制多样性。在这项研究中,作者对LLM在二进制代码理解方面的能力进行了广泛的研究,评估了超过557,000个不同架构和优化级别的二进制函数。然而,现实世界的二进制文件超出了作者数据集的范围,包括领域专用的二进制文件,如物联网固件和恶意软件。这些二进制文件通常具有独特的语义,可能会因代码混淆而变得更加复杂。此外,虽然作者的研究评估了特定的二进制代码表示,但它并未涵盖所有可能的表示,比如由其他反编译器或IR代码生成器生成的表示。深入研究这些领域为未来的研究提供了一个有前途的途径。

新型LLMs和提示技术的出现。 作者的研究评估了四个被认为在众多任务中表现出色的主要LLMs [51, 66],以及二进制代码摘要模型BinT5 [23]。然而,随着学术界和工业界不断进步,新的LLMs不断涌现,这些可能也适用于作者的任务。此外,尽管作者的研究采用了一个合成和优化提示的方法,生成了320个提示(§4.1),但仍有可能发现更有效的提示并改进提示工程方法,如基于梯度的提示调整[46]。

代码摘要和语义表示。在作者的研究中,由开发人员编写的代码注释作为作者代码摘要的黄金标准。这些摘要的替代表示形式也存在,例如分析日志或系统调用[36, 53]。然而,这些表示形式是人为生成的,由第三方生成而不是代码创建者生成,可能在语义上不总是与原始代码一致。作者观察到开发人员的注释提供了一个更直观的选择。这符合先前研究中使用的传统方法[23, 33, 38]。类似于众所周知的代码摘要数据集,如CodeSearchNet [38],作者的数据集可能还包含由开发人员引入的语义不一致的噪音[29]。虽然减轻这种噪音仍然是一个开放的问题,但这将是随后研究的一个值得关注的重点。

7 RELATED WORK

LLM用于二进制逆向工程。二进制逆向工程是一项劳动密集型工作,并且在缺乏高级语义的情况下尤为困难,特别是对于剥离了符号的二进制文件。现有的基于LLM的解决方案遵循预训练-微调范式,从大型二进制语料库中学习二进制语义,并将所学知识转移到下游任务,如函数相似性检测 [43, 62, 74]、变量名称和类型推断 [25, 28, 59] 以及函数名称预测 [31, 40, 57]。例如,Trex [62] 在汇编代码和执行跟踪上对roBERTa进行预训练,以检测函数相似性。SymLM [40] 通过学习调用上下文和执行行为来预测函数名称。与现有关注BERT级LLMs的工作不同,作者关注表现出更好的泛化能力和新兴能力的生成式LLMs [76]。

自动代码摘要。自动代码摘要旨在使用自然语言摘要来表达代码片段,通常是方法或函数 [67]。最近,这方面的研究主要集中在源代码上 [33, 35, 75]。例如,CodeT5 [75] 通过对具有语义丰富代码特征(例如标识符)进行预训练,总结代码。GraphCodeBERT通过使用BERT模型对数据流进行建模来总结二进制代码的语义 [35]。除了源代码之外,还有关于二进制代码的研究工作。例如,BinT5在反编译代码上微调CodeT5,以生成自然语言描述 [23]。与现有研究不同,作者是第一个对不同LLMs在二进制代码摘要任务上进行大规模和全面研究的团队。

Appendix

A.1 Source Projects

表3展示了作者用于编译二进制文件的44个开源项目。
在这里插入图片描述

A.2 Cross-compilation and Stripping

作者的编译和剥离过程是在一台64位的Ubuntu机器上进行的。对于与主机机器不同的计算机体系结构,即ARM和MIPS,编译和剥离二进制文件需要使用交叉编译器和交叉剥离工具。为此,作者使用了交叉编译器arm-linux-gnueabihf-gcc和mipsel-linux-gnu-gcc用于ARM和MIPS二进制文件。对于二进制剥离,作者对x86和x64二进制文件使用strip命令。对于ARM和MIPS二进制文件,作者使用arm-linux-gnueabihf-strip和mipsel-linux-gnu-strip。

A.3 Binary Functions with Ground-truth Summaries

表4展示了在计算机体系结构和优化级别方面的二进制函数分布,同时附带有由§2.1中定义的方法提取的真实场景下的摘要。
在这里插入图片描述

A.4 Metrics

一些常见指标,如BLEU,METEOR等

A.5 Prompt Evaluation Results

表5呈现了前40个提示及其评估结果,这些提示是通过作者提出的上下文提示合成和优化方法(见§2.2)生成的。正如在§3中提到的,作者首先由GPT-4生成320个提示,然后在从作者的二进制摘要数据集中随机选择的1000个二进制函数样本上评估每个提示。为了生成这320个提示,作者选择使用GPT-4,因为这些任务本质上涉及测试生成,并且根据OpenAI的文档[51],GPT-4在这个领域表现出色。根据语义相似度分数,作者在随后的评估中选择最佳提示。除了提示文本之外,作者还添加了指令以限制摘要长度,如§2.3中所述。为了简化检索摘要的过程,作者通过向LLM输入添加以下文本来获取结构化摘要输出,例如对于反编译代码摘要,“Input decompiled code:\n < C O D E > <CODE> <CODE>\n Function Summary:”,其中 < C O D E > <CODE> <CODE>填充为测试反编译代码。对于GPT-4、ChatGPT、Llama 2和Code Llama模型,作者使用相同的提示进行公平比较。对于BinT5,它是在反编译代码上进行微调的,没有自然语言指令,因此作者使用相同的输入形式,即反编译代码,作为其测试输入。
在这里插入图片描述

A.6 Case Study of LLM-generated Summaries

在获取了统计结果后,作者对LLMs理解二进制代码的程度以及特定分数结果的微妙解释进行了更深入的研究。为此,作者对LLM生成的摘要进行了一系列案例研究。作者关注LLMs在语义相似度得分最高(第100百分位)、中位数(第50百分位)和最低(第0百分位)的样本。这种调查方法旨在为作者提供在极端和中位数情景下的分布洞见,从而揭示LLM在二进制代码理解方面的鲁棒性。对于源代码,作者总体观察到LLM能够捕捉到大部分其语义(如表6所示)。例如,获得中位数分数的源函数3的摘要显示LLM已经巧妙地识别了“skip characters”和“return the index”的关键语义。
在这里插入图片描述

此外,作者观察到对于带有调试符号的反编译代码的摘要同样表现良好(例如表7中的样本)。然而,对于来自剥离的二进制文件的反编译代码,作者发现LLMs不能生成与实际情况下的摘要语义明确匹配的摘要(如表8所示)。例如,LLMs仅能够捕捉函数2和3的部分或基本语义,尽管它们的得分属于中位数范围。对于函数2,生成的摘要包括“file name canonicalization”的语义,但未包含真实情况的具体细节,如“remov2 dots”。对于函数3,LLM只捕捉到ELF文件格式,失去了所有其他语义信息。

在这里插入图片描述

在这里插入图片描述

结果 1 (F1) – 尽管LLMs在源代码和带有符号的反编译代码方面表现出色,但缺乏调试符号会导致LLMs生成仅包含反编译代码部分或基本语义的摘要。

对于低级别的代码,例如IR代码和汇编代码,作者观察到LLMs主要集中于描述低级操作,而没有提供全面的高级语义摘要。例如,表9呈现了IR代码的摘要和评估分数。在获得最高到最低分数的样本中,LLM生成的摘要主要描述数据移动、算术运算(例如加法和减法)、内存加载/写入以及数据流转换(例如跳转操作)等操作。类似地,作者在表10中的汇编代码中也观察到这样的描述。与IR代码摘要略有不同的是,在汇编代码的最高分的情况下,LLM可以捕捉与字符串数据结构和复制操作相关的基本信息。

发现2(F2)- LLM生成的摘要未能概括IR和汇编代码的高级语义,而是专注于阐明低级别的操作,例如数据移动和算术计算。
在这里插入图片描述

在处理原始字节的情况下,人们预计LLMs会生成描述字节序列的摘要。然而,令人惊讶的是观察到LLM生成的摘要描绘了与IR代码和汇编代码中观察到的操作相似的操作(如表11所示),特别是对于OpenAI模型,即ChatGPT和GPT-4。例如,函数2的摘要描述了堆栈帧操作、函数调用和算术操作,这些操作在原始字节输入中没有明确体现。看起来LLMs通过将原始字节隐式提升为更高级别的表示,比如可以表示上述操作的汇编代码,来生成摘要。

发现3(F3) - 对于原始字节,LLM生成的摘要与汇编代码非常相似,暗示了LLM执行的一种隐式代码提升过程。

除了理解LLMs在单个样本中的性能之外,作者还确认了使用作者提出的语义评估指标的好处。具体来说,正如在§1.1中所述,仅基于完全匹配的度量无法提供精确的评估结果,因为它们无法涵盖摘要的语义细微差别。例如,对于表6中的函数2,BLEU和METEOR分数被计算为0。然而,函数2的生成摘要和地面实况摘要呈现出接近的语义,例如“例行”和“函数”,以及“文件名”和“文件的名称”。这些单词/短语在语法上有所不同,但在语义上是相同的。此外,它的BLEU、METETOR和ROUGE-L的计算分数低于函数4的分数,而函数2的摘要显示出更接近的语义。相比之下,作者的语义评估指标在语义级别计算语义相似性,因此在函数2和函数4之间分配更高的分数,对更接近的语义给予更高的分数。因此,作者认为作者的语义评估指标更适合评估二进制代码摘要。
在这里插入图片描述

发现4(F4)- 作者的语义评估指标能够捕捉二进制代码摘要的基本语义,相比基于精确匹配的度量标准更适合作者的任务。

A.7 Case Study of GPT-4 Results

在RQ2的评估中,令人惊讶的是观察到GPT-4并非最佳模型,特别是在具有符号的二进制文件中,ChatGPT胜过了GPT-4。为此,作者进行了一项案例研究,手动调查了GPT-4的结果。总体而言,作者观察到GPT-4有时更注重嘈杂的细节,而不是捕捉二进制函数的全局语义。表12展示了这三种情况,展示了GPT-4生成的摘要和地面真相以及与之进行比较的ChatGPT生成的摘要。对于函数1,作者发现GPT-4解释了输入二进制代码的实现细节,而不是提供简洁的摘要。这样的解释可以捕捉一些语义,例如它生成的短语“without changing its current position”与地面真相“preserving the value”的语义相似,但这个解释包含了地面真相中没有出现的额外细节。同样,GPT-4为函数2和3生成了额外的细节,如红色文本所示。与GPT-4相比,ChatGPT更少关注不必要的细节,并生成更简洁的摘要,代表了关键的语义。
在这里插入图片描述

A.8 BinT5 Outliers and Sample Leakage

在RQ2的评估中,作者注意到BinT5性能中存在一些异常值,其文本相似度得分超过0.8。这些得分明显高于中位值。通过将这些异常样本的函数名称与BinT5的训练集进行比较,作者发现一些由Ghidra生成的反编译代码样本在BinT5的训练集中。作者已经从作者报告的BinT5结果中删除了这些泄漏的样本。

A.9 Impact of Symbols and Exclusive Symbol Stripping

在RQ4的评估中,作者研究了哪种符号类型(数据类型、变量名和函数名)通过专门剥离每种类型的符号对二进制函数语义的贡献最大。作者首先将带有所有符号的反编译代码视为原始代码。随后,为了分离每种符号类型的影响,作者通过用非信息符号替换它们来消除原始代码中的相应符号。这些非信息符号与剥离二进制文件的反编译器生成的符号的模式相同。具体而言,对于函数名,作者用符号Fun_addr替换原始名称,其中addr是函数的地址。对于变量名,作者用符号Var_idx替换原始名称,其中idx是变量在函数中的索引。对于数据类型,作者用符号undefined替换原始类型。

A.10 Summary Manipulation by Modifying Function Names

虽然作者在R9中已经确定了函数名对二进制代码语义的重要贡献,但作者也注意到了LLM生成的摘要存在一个有趣的漏洞。具体而言,作者观察到这些摘要可以通过修改函数名来操纵。为了详细说明,图14展示了由Ghidra生成的一个去除了所有符号的反编译函数。当作者将选择的提示应用于该函数时,ChatGPT生成一个摘要,如Table 13的第1行所示。然而,当作者进行一个简单的调整时,即更改原始函数名FUN_0000ea01为替代名称,如quick_sort、print_log和DNS_flood,生成的摘要经历了实质性的变化。正如Table 13的第2到4行所示,生成的二进制代码摘要紧密地类似于操纵后的函数名称的语义,但未能准确反映保存在函数体内的真实语义。这一发现突显了LLM生成的摘要对通过更改函数名进行操纵的敏感性。鉴于这一漏洞,攻击者有可能修改恶意二进制文件的DWARF条目,从而误导LLM并逃避对恶意行为的检测。

在这里插入图片描述
在这里插入图片描述

A.11 Other Prompt Engineering Techniques

作者还研究了其他提示工程技术是否能帮助LLMs理解二进制代码。具体而言,作者关注两种流行的技术,包括few-shot学习和chain-of-thought提示。Few-shot提示最初是为了增强GPT-3在其主要领域之外的任务的泛化能力 [27]。这是通过通过上下文指令和演示样本向模型灌输背景知识来实现的。更具体地说,few-shot学习包括在引入测试输入之前加入一个系统指令I,以及 𝑛 个上下文演示对(X𝑑,Y𝑑),其中X𝑑和Y𝑑表示样本输入和输出。这种增强发生在引入测试输入之前:
在这里插入图片描述

其中,系统指令 I 和演示样本(𝑥𝑖𝑑,𝑦𝑖𝑑)与测试输入 𝑥𝑡 连接在一起形成查询输入 𝑥。图15b展示了作者用于执行few-shot提示的示例提示。作者随机抽取了每个测试二进制代码的两对示例二进制函数和摘要,而不是使用固定的演示示例,以避免LLMs学习演示示例中的不变模式。

Chain-of-thought提示被提出来解决将复杂的推理问题分解为中间步骤 [77]。在二进制代码理解的背景下,作者要求LLMs在生成最终的代码摘要之前执行额外的推理输入代码语义的步骤。为此,作者首先发送一个请求,要求LLMs推理代码的语义,作者在其中使用流行的推理提示“让作者一步一步地思考”。在收到响应后,作者解析生成的代码推理结果并将它们连接到第二个请求中,询问代码摘要。图15c展示了作者chain-of-thought提示的示例。基线是零-shot提示。如图15a所示,作者直接将提示与测试代码连接在一起,生成请求作为基线方法。

在这里插入图片描述

小番外

“Chain-of-thought”(思维链)提示是一种通过将推理问题分解为中间步骤来解决复杂推理问题的方法。在二进制代码理解的背景下,该方法要求LLMs在生成最终的代码摘要之前执行额外的推理步骤。

具体而言,在Chain-of-thought提示中,首先发送一个请求,要求LLMs推理代码的语义。为此,使用流行的推理提示,比如“让我们一步一步地思考”。LLMs会生成对于输入代码语义的推理结果。然后,将这个生成的代码推理结果解析并连接到第二个请求中,这个请求询问代码的摘要。在第二个请求中,LLMs被要求生成最终的代码摘要,基于在前一个步骤中生成的中间推理结果。

这个过程旨在促使LLMs更深入地思考输入代码的语义,以便生成更准确、更详细的代码摘要。通过引入中间步骤,这种方法试图提高LLMs对于推理问题的处理能力。

  • 50
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值