CKGFuzzer:通过代码知识库强化基于LLM的模糊测试驱动生成
原创 FuzzWiki 2025-07-14 11:31 四川

基本信息
原文名称:CKGFuzzer: LLM-Based Fuzz Driver Generation Enhanced By Code Knowledge Graph
原文作者:Hanxiang Xu, Wei Ma, Ting Zhou, Yanjie Zhao, Kai Chen
原文链接:https://arxiv.org/abs/2411.11532
发表期刊:2024 arxiv(在投)
一、引言
近年来,大型语言模型(llm)的编程能力引起了极大的关注。模糊测试是一种高效的技术,在提高软件可靠性和检测漏洞方面起着关键作用。然而,传统的模糊测试工具依赖于手工制作的模糊驱动程序,这可能会限制测试的效率和有效性。为了应对这一挑战,我们提出了一种自动化模糊测试方法,该方法由代码知识图驱动,并由基于llm的智能代理系统(称为CKGFuzzer)提供支持。我们将模糊驱动程序创建作为代码生成任务,利用代码存储库的知识图在模糊循环中自动化生成过程,同时不断地细化模糊驱动程序和输入种子。通过程序间分析构建代码知识图,图中的每个节点代表一个代码实体,如函数或文件。知识图增强的CKGFuzzer不仅可以有效解决模糊驱动中的编译错误,生成针对特定API使用场景的输入种子,还可以分析模糊驱动崩溃报告,帮助开发人员提高代码质量。通过查询代码库的知识图和从API使用场景中学习,我们可以更好地识别测试目标,并了解每个模糊驱动程序的特定目的。我们使用八个开源软件项目来评估我们的方法。实验结果表明,与最先进的技术相比,CKGFuzzer在代码覆盖率方面平均提高了8.73%。此外,CKGFuzzer将崩溃案例分析中的人工审查工作量减少了84.4%,并在测试库中成功检测到11个真正的bug(包括9个以前未报告的bug)。我们的研究通过改进模糊驱动生成策略和输入种子分析,提高了模糊测试的整体性能,为漏洞修复和软件质量改进提供了更有效的解决方案。
二、研究动机
本文的研究动机主要有两点:
1.现有的基于大模型的库模糊测试驱动生成工具大多是zero-shot 的,本文借鉴RAG 思想,为模糊测试驱动的生成从目标库中提取相关的context,以辅助和增强大模型生成有效测试驱动的能力
2.使用大模型生成的模糊测试驱动缺少对应的种子,本文利用大模型来为模糊测试驱动生成对应的种子。
3.使用生成的驱动进行Fuzz 得到的Crash 可能来自API 的误用,也可能是真实的bug。针对Crash 的分析费时费力。本文利用大模型实现Crash 的自动化分析。
三、概述

图 1 CKGFuzze 工作流
最初,CKGFuzzer解析得到目标库中的api,从被测项目中提取代码的知识图谱并生成其嵌入。这个解析过程包括两个步骤:首先,解析抽象语法树,其次,执行过程间程序分析。解析器提取关键信息,如数据结构、函数实现、函数签名和调用关系。
接下来,CKGFuzzer对于库中的每个API,基于调用关系或功能相似性,获取API组合并生成相应的模糊驱动程序。CKGFuzzer然后尝试编译这些生成的模糊驱动程序并解决出现的编译错误。
在驱动程序生成和修复过程中,我们为CKGFuzzer提供了一个动态更新的库使用知识库。一旦成功编译了fuzz驱动程序,CKGFuzzer就会执行它们,同时监视每个库文件的代码覆盖率。它采用代码覆盖引导的迭代过程来改变无法覆盖新路径的API组合。这个迭代过程会一直持续下去,直到发现新的代码路径或耗尽突变预算为止。
最后,CKGFuzzer使用思维链推理来分析在模糊测试期间产生的任何崩溃。为了验证这些崩溃的有效性,我们引用了一个llm生成的知识库,其中包含与cwe相关的真实源代码示例。
四、模块设计
1.目标库代码知识图谱的创建

CKGFuzzer 中的代码知识图谱由三种节点组成:
1)文件节点D
2)函数节点F
3)外部函数LIBRARY FUNCTION
其中的边有两种
1)D -> F 的 包含 关系
2)F -> F 的call 关系。特别地,CKG会为外部函数创建 LIBARRY FUNCTION 节点 和 LIBRARY CALL 的边
其中,F 节点包含 源代码、签名、摘要(summary) 等属性。D 节点包含 摘要(summary) 属性。
2.API 组合的生成
(API Combination Generation)

图 2 API 组合生成算法
算法如上图所示。借助嵌入生成和相似度匹配的方法,根据 query 搜寻相关的 chunks 。根据 Chunks 迭代地优化 query 的答案 repsponse 。 最后从 response 提取出相关的 API 组合。
3.模糊测试驱动生成
(Fuzz Driver Generation)
本文通过构建提示词,指导大模型进行模糊测试驱动的生成。我们的提示词策略强调模糊驱动程序生成的几个关键方面:
1)任务定义:LLM的任务是生成一个模糊驱动程序来测试提供的API组合。提示符指定每个API必须在函数LLVMFuzzerTestOneInput中调用,以确保API集的全面测试覆盖率。
2)API上下文:提示符包括API源代码、头和自然语言摘要。这为LLM提供了必要的上下文,以正确利用api并根据其功能和约束管理其输入和输出。
3)错误处理:为了防止模糊驱动程序本身不稳定,这可能导致崩溃并降低整体模糊效率,提示符包括明确的指令,用于稳健的错误处理和仔细的内存管理。
4.动态程序修复
(Dynamic Program Repair)

图3 模糊测试驱动修复
算法如上图所示。为了实现动态程序修复,我们首先初始化一个知识库,其中包含正确的库API用法,该知识库由来自OSS-Fuzz的fuzz驱动程序示例和库的头文件构建。值得注意的是,虽然OSSFuzz代码侧重于单个API,但我们的方法处理API组合。头文件有助于解决由于缺少include语句而导致的错误。当CKGFuzzer遇到编译失败时,它处理编译器错误消息并构造一个查询来搜索外部知识库,以查找错误API或代码片段的正确用法。CKGFuzzer继续查询知识库并迭代地应用修复,直到fuzz驱动程序成功编译或达到最大迭代限制。
此外,所有成功编译的模糊驱动程序都被插入到知识库中,动态更新正确API使用模式的存储库。这种动态更新策略确保知识库随着时间的推移而发展,逐渐扩展到涵盖跨不同库的更广泛的API使用场景。因此,我们的方法在修复错误方面保持了高水平的适应性和准确性,减少了反复编译失败的机会。
5.输入种子池的初始化
(Input Bank Initialization)
在模糊测试开始之前,我们通过使用llm为每个模糊驱动程序生成输入种子来初始化输入库。输入生成过程从对模糊驱动程序的数据流的详细分析开始,在这里我们提取变量之间的价值流关系。随后,我们提取与模糊驱动程序交互的API函数签名,这有助于理解预期输入的结构和约束。
6.覆盖率引导的变异
(Coverage Guided Mutationr)

图4 覆盖率引导的变异
在模糊测试过程中,CKGFuzzer监视每个模糊驱动程序实现的代码覆盖率。它分析整个库的覆盖率数据,并识别与整个库相比覆盖率较低的文件。对于每个低覆盖率文件,将提取定义的API函数,并根据文件的覆盖率排名生成一个优先级列表,称为低覆盖率API列表。
然后,这个低覆盖率API列表用于指导LLM在模糊驱动程序中突变和重组当前API组合。其目标是通过关注未开发的api来探索新的执行路径并增加代码覆盖率。如算法3所示,突变过程是迭代的:CKGFuzzer根据低覆盖率API列表继续查询具有新API组合的LLM,直到覆盖新的分支或计算资源耗尽。
7. 崩溃分析
(Crash Analysis)
针对崩溃的自动化分析包括以下三步:
1)源代码提取:分析开始于隔离发生崩溃的特定代码区域。这包括提取模糊驱动程序源代码的相关部分,以及可能影响崩溃的任何相关API调用。
2)错误模式假设:在提取相关代码后,LLM系统地分析代码中常见编程错误的模式。这些模式可能包括不安全的内存操作、不正确的变量赋值、不正确的控制流条件等等。在这个阶段,LLM形成了关于哪些代码模式可能导致崩溃的初步假设,并为更深入的探索建立了一个可能的错误源列表。
3)基于cwe的模式匹配:基于潜在错误模式的假设,LLM构建有针对性的查询来搜索基于cwe的知识库。这个知识库包含超过100个特定于C/ c++程序的真实CWE漏洞,提供了关于已知问题的丰富信息。
五、评估
1.CKGFuzzer相比其他Fuzzer 的有效性

图 5 覆盖率评估
我们选取了八个开源库进行评估:c-ares、cjson、curl、lcms、libpcap、libtiff、libvpx 和 zlib。这些库因其 API 使用的多样性以及在各类软件项目中的广泛应用而被选中。我们将 CKGFuzzer 与其他开源模糊测试器进行了比较,重点对比了基于覆盖率引导的模糊测试器(OSS-Fuzz)和基于大语言模型的模糊测试器(PromptFuzz)。
在评估过程中,我们在每个库上运行来自OSS-Fuzz 的模糊测试驱动程序,持续 24 小时。所使用的生成模型为DeepSeek-V2-Coder。如果某个库在 OSS-Fuzz 中包含多个模糊测试驱动,我们会为每个驱动分配相同的时间预算,以确保总模糊测试时间为 24 小时。对于 PromptFuzz,我们使用了与 CKGFuzzer 相同的 API 列表,并将模糊测试的时间也控制为 24 小时。
随后,我们根据代码覆盖率对CKGFuzzer 的有效性进行了评估。CKGFuzzer、PromptFuzz 和 OSS-Fuzz 的代码覆盖率结果如图5所示。在与其他模糊测试器的对比中,CKGFuzzer 在所测试的 8 个库中,有 6 个取得了最高的分支覆盖率。这种优越性在很大程度上归功于 CKGFuzzer 所生成的结构化 API 组合,这些组合来自一个全面的代码知识图谱,使得 CKGFuzzer 能够捕捉 API 之间复杂的关系与语义依赖,从而生成更具意义的模糊测试驱动程序。
2.每种智能体对CKGFUzzer 有效性的贡献

图 6 消融实验表
我们评估的组件包括API组合生成、编译修复和API组合突变的代码知识图谱。
1)代码知识图:为了评估代码知识图对CKGFuzzer生成的模糊驱动质量的影响,我们将其与使用库中基于文本的API知识的变体进行了比较。这种变体通过查询由API源代码和API摘要组成的基于文本的知识库来生成API组合。图6的实验结果表明,纯文本检索变体比CKGFuzzer实现了更低的代码覆盖率,这突出了代码知识图在生成高质量模糊驱动方面的有效性。
2)编译修复:在CKGFuzzer中,我们引入了动态程序修复组件来修复遇到编译错误的fuzzer驱动程序。在本节中,我们设计实验来评估CKGFuzzer修复编译错误的有效性以及动态程序修复组件对模糊性能的影响。首先,我们创建了两个变体:一个没有任何编译错误修复(没有修复),另一个仅依赖LLM进行程序修复(仅LLM修复)。表2的实验结果显示,未修复的平均编译成功率仅为57.39%(458/798),说明CKGFuzzer很难直接生成可编译的模糊驱动程序。另一方面,仅llm修复将编译成功率提高到77.19%(616/798),显示了llm在程序修复方面的巨大潜力。然而,CKGFuzzer的编译成功率为93.99%(750/798),突出了动态程序修复组件在修复模糊驱动程序编译错误方面的有效性。

图 7 覆盖率引导消融实验
此外,我们还评估了两个变体的代码覆盖率表现。表II 的结果显示,无修复版本和仅使用大语言模型修复的版本在代码覆盖率方面均低于 CKGFuzzer。这是因为许多模糊测试驱动程序包含独特的 API 组合,但无法成功编译,因此无法参与模糊测试过程,限制了通过多样化的 API 组合在库中探索新的执行路径的潜力。
3)基于覆盖率的变异机制:CKGFuzzer 利用基于覆盖率引导的变异机制来发现潜在的新 API 组合。为了评估其有效性,我们与一个不进行 API 组合变异的变体进行了对比实验。我们将两个方法的模糊测试时间都固定为 24 小时,以比较它们的覆盖率变化趋势。图 2 展示了 CKGFuzzer 在启用和不启用 API 组合变异的情况下,在不同库中获得的分支覆盖率结果。
3.崩溃分析的效果

图 8 崩溃分析
CKGFuzzer 在模糊测试过程中共发现了 199 个独特的崩溃,其中有 168 个被崩溃分析模块判定为由库 API 的误用引起。为了尽量减少误报,崩溃分析模块会将那些难以明确分类或存在歧义的情况也视为 API 误用导致的崩溃。例如,如果某次崩溃是由于向库 API 传递了不存在或错误的指针,而该 API 本身没有使用防御性编程来验证输入指针的有效性,我们仍将此类情况归类为误用崩溃。
为了验证崩溃分析模块在识别API 误用崩溃方面的准确性,我们从每个库的误用崩溃案例中随机抽取了 10% 进行人工检查。经过审查,我们确认这些崩溃确实都是由于模糊测试驱动程序错误使用 API 所导致的。
六、讨论
1.不同编程语言的适用性
CKGFuzzer 主要是在基于 C 的库上进行评估的,这些库广泛使用,且其 API 文档完善。然而,CKGFuzzer 在其他编程语言(如 Rust、Java 或 Python)中的适用性仍是一个尚未解决的问题。由于每种语言的 API 设计存在差异,CKGFuzzer 可能需要进行相应的调整才能有效应对这些差异。未来的研究可以探索将 CKGFuzzer 适配到这些语言中,从而拓展其应用范围和实用性。
2.代码知识图谱的质量
代码知识图谱在 CKGFuzzer 中起着核心作用,它指导 API 组合的生成,并在基于覆盖率的变异过程中更新 API 组合。代码知识图谱的完整性和准确性对于生成有效的模糊测试驱动程序至关重要。在我们的实验中,拥有更全面代码知识图谱的库表现出更好的覆盖率和更高的模糊测试效率。提升代码知识图谱的自动化构建与验证能力,有助于进一步提升 CKGFuzzer 的性能,确保其准确反映库的 API 结构和使用模式。
七、总结
在本文中,我们提出了CKGFuzzer,一个新的由代码知识图增强的llm驱动的模糊测试框架。CKGFuzzer自动生成模糊驱动程序,并引入了几个关键特性来提高模糊测试的有效性。其中包括一个覆盖引导的突变策略,它迭代地改进API组合以探索新的执行路径,一个动态程序修复机制,它自动解决生成的模糊驱动程序中的编译错误,以及一个崩溃分析模块,它有助于识别运行时失败的根本原因。我们在8个开源项目上的实验表明,CKGFuzzer实现了更好的代码覆盖率,并成功检测了11个真实世界的bug。覆盖引导的突变可以更广泛地探索代码路径,而动态程序修复和崩溃分析模块显著减少了人工干预,使模糊测试过程更加高效和可靠。这些结果突出了利用llm和代码知识图来推进自动化模糊测试的潜力。
—END—


BAZZAFL:通过面向漏洞的种子分组将模糊测试活动导向漏洞
