DeepState 现已支持集成式模糊测试 - The Trail of Bits 博客
Alan Cao, Francis Lewis High School, Queens, NY
2019年9月3日
fuzzing, internship-projects
我们自豪地宣布,已将集成式模糊测试(ensemble fuzzing)集成到 DeepState 中,这是我们基于模糊测试和符号执行的单元测试框架。集成式模糊测试允许测试人员在单个测试活动中执行多个具有不同启发式算法的模糊器,同时保持跨模糊器队列同步生成输入种子的架构。
这个新的集成式模糊器包括一个新的 deepstate-ensembler
工具和几个由新的开源 DeepState 前端 API/SDK 驱动的知名模糊器引擎。该 SDK 使开发人员能够为 DeepState 集成前端执行器,并为我们的集成器工具提供种子同步支持。
智能模糊器的谬误
模糊器是安全研究人员工具箱中最有效的工具之一。近年来,它们被广泛研究以构建更好的启发式算法或策略,用于探索程序。然而,有一点仍然很清楚:模糊器的启发式算法很少能达到其宣传的效果。当将所谓的智能模糊器扩展到现实世界的程序时,它们的性能常常会下降,我们最终不得不回归到“笨拙”的标准工具,如 AFL 和 LibFuzzer。
由于我们过去已经探讨过评估模糊测试研究的主题,让我们换个角度,探索将各种模糊器启发式算法结合起来以最大化模糊器性能的可能性,而不在测试工作流程中浪费时间。这导致了我夏季实习项目的内容:将集成式模糊测试集成到 DeepState 中。
什么是集成式模糊测试?
集成式模糊测试的见解是,虽然某些启发式算法在特定环境下效果很好,但将它们结合起来应该比仅使用单一策略的单个模糊器产生更好的结果。这个想法最初由 Chen 等人的 EnFuzz 论文提出,然而,目前没有可用的开源或商业实现。
我们的集成式模糊器实现遵循 EnFuzz 中实现的架构,如下所示:
给定一组预定的多样化基础模糊器,每个都有各自的本地种子队列,我们可以集成一个全局异步和本地同步(GALS)的种子同步机制,在执行周期中将有趣的种子从本地队列拉取到共享的全局队列。因此,当基础模糊器的启发式算法无法提高覆盖率或发现有趣的输入种子时,它可以在下一个执行周期中从全局队列中拉取其他模糊器的种子。此外,一旦测试活动终止,我们可以从集成器接收任何关于基础模糊器性能、崩溃分类/去重或其他后处理统计信息的模糊测试反馈。
通过使用集成式模糊测试和我们已经强大的用于模糊测试/符号执行的单元测试框架 DeepState,我们能够在测试过程中解决以下问题:
- 模糊器性能多样性——不同的模糊器启发式算法是否贡献了不同的有用种子,从而最大化提高覆盖率和发现崩溃的潜力?
- 模糊器工作流程——我们如何在简化工作流程的同时进行详尽的模糊测试和/或符号执行?
- 不变性一致性——不同的模糊器是否返回不同的结果,表明我们的测试中可能存在非确定性的来源?
启动前端
由于 DeepState 已经支持 Eclipser 作为后端,我们选择首先构建一个前端 API,开发人员可以为模糊器后端编写前端包装器。这协调了运行的模糊器进程,并执行编译时插桩、预处理和后处理以及种子同步。它还通过统一我们构建工具的方式来实现功能,从而简化了模糊测试环境的设置。
下面的代码片段展示了一个 AFL 前端包装器的示例。它继承自基础的 DeepStateFrontend
类,并包含定义模糊器相关功能的方法。
AFL 的前端包装器示例。 一个继承的方法 pre_exec
允许用户在执行前进行健全性检查。检查环境属性(即核心转储模式)和参数解析。
为了构建前端包装器,我们的模糊器对象应具有以下方法:
每个模糊器都有自己的集成方法,它提供了一个专门的 rsync
调用来从全局和本地队列目录推送和拉取种子:
用于种子同步的集成方法。 每个 __sync_seeds()
调用都会调用一个专门的 rsync
命令在本地和全局队列目录之间传输种子。
构建完成后,我们可以这样使用前端包装器:
|
|
有关模糊器前端 API 以及如何实现自己的前端的更详细说明,请参阅本教程。DeepState 已有用于 AFL、libFuzzer、Angora、Eclipser 和 Honggfuzz 的前端执行器。
https://asciinema.org/a/262023
构建集成器
使用统一的 API,我们现在可以构建一个集成式模糊器,它配置前端对象并同时执行模糊器,同时保持种子同步。
首先,获取一个 DeepState 测试工具输入,并通过每个前端对象暴露的 compile()
调用,将多个插桩后的二进制文件“集成编译”到带有我们模糊器的工作空间目录。
使用“集成编译”策略配置带有二进制文件的测试工作空间。
完成后,每个并行模糊器进程通过 run()
实例化。由于每个前端包装器通过 ensemble()
调用 rsync
风格的同步,集成器只需在指定的同步周期(以秒为单位)后从每个前端调用它来同步种子。
这个实现出奇地简单,用 Python 编写了大约 300 行代码。以下是在我们的测试示例之一 Crash.cpp
上运行集成器的快速演示。
全部模糊测试!
受 Google 的 fuzzer-test-suite 和前述模糊器性能测试工作的启发,我们决定一个由 DeepState 驱动的测试套件 deepstate-test-suite
可以帮助进行模糊器性能 A/B 测试和实际的错误搜寻。借助我们易于使用的模糊器和集成器,让我们评估它们在现实世界测试用例基准上的表现!
大数漏洞是一类特别有趣的错误,因为边缘情况更难发现,甚至是概率性的。这使得它们成为 DeepState 属性测试的理想目标。
我们为基础模糊器和集成器模糊器进行了基准测试,以评估它们在重现现有测试用例和现实世界大数漏洞(TweetNaCl 中的进位传播错误)方面的性能。遵循这篇模糊测试评估论文中的评估方法,使用来自良好初始输入的 10 个崩溃实例测量每个测试用例的平均时间:
这些结果提供了关于模糊器多样性的一些有趣见解。在较小的封闭测试用例(如 Runlen 示例)上运行更智能的模糊器(如 Angora 和 Eclipser)效果很好。然而,当扩展到现实世界软件中的实际错误发现环境时(如 TweetNaCl 错误),它们的性能会下降。集成式模糊器的性能表明它能够很好地扩展以适应这两种测试用例。
集成式模糊测试的未来是什么?
集成式模糊测试是一种强大的技术,可以扩展到现实世界的软件库和程序。将集成式模糊器集成到 DeepState 中,通过简化的工作流程增强了单元测试的能力,并为许多其他研究和工程工作开辟了可能性。
根据我们当前的基准测试结果,我们不能肯定地说集成式模糊测试是最好的模糊测试策略,但值得注意的是,在评估模糊器时总是存在随机性和概率行为的元素。有效的集成式模糊测试可能依赖于基础模糊器的选择——根据分析的目标类型或错误类别来确定调用哪些模糊器以及何时调用。
也许我们当前的模糊器集成在重现大数漏洞方面有效,但它们在其他类别的错误上是否同样有效?如果我们以特定顺序调用模糊器,是否会更加有效?这些问题可以通过对不同目标进行更多基准测试来更准确地回答。
感谢!
在 Trail of Bits 担任安全工程实习生一直是一次美妙的经历。与优秀的员工和实习生一起工作真正推动了我对安全研究的理解,以及我们如何将深刻的学术研究转化为可工作的软件实现,就像我之前使用 Manticore 分析加密原语的工作一样。我特别兴奋能在纽约大学继续这项工作,我将在春季开始学习!
如果您喜欢这篇文章,请分享:
Twitter LinkedIn GitHub Mastodon Hacker News
页面内容
智能模糊器的谬误
什么是集成式模糊测试?
启动前端
构建集成器
全部模糊测试!
集成式模糊测试的未来是什么?
感谢!
近期文章
Trail of Bits 的 Buttercup 在 AIxCC 挑战赛中获得第二名
Buttercup 现已开源!
AIxCC 决赛:记录
攻击者的提示注入工程:利用 GitHub Copilot
发现 NVIDIA Triton 中的内存损坏(作为新员工)
© 2025 Trail of Bits.
使用 Hugo 和 Mainroad 主题生成。