CCS‘ 17 Designing New Operating Primitives to Improve Fuzzing Performance
①论文摘要 |
②论文介绍 |
在本文中,做出了以下贡献:
②论文背景 |
模糊解释:
模糊化是一种广泛应用的软件测试技术,用于查找不适用的缺陷。它通过向目标程序注入随机变化的输入来测试软件,并监视目标的行为是否异常(例如,崩溃、跟踪、挂起或断言失败)。触发异常行为的输入报告为潜在错误。
为了快速检测bug,各种技术被提议通过智能策略明智地改变输入,并有效地探索程序状态。特别是,流行的模糊器,比如使用过去的代码覆盖率来确定当前的变化输入是否有趣,并将其用作下一次执行的反馈。为了获得覆盖率信息,模糊器需要检测系统仿真层。通常,模糊器从一组种子输入开始,运行目标程序,并根据过去执行的反馈(例如覆盖率或崩溃)改变输入。整个过程被称为模糊循环,模糊器可以在一定的时间内迭代,或者直到达到饱和点。
模糊回路包括以下步骤:
AFL设计:
AFL是最先进的引信,它发现了许多重要的安全漏洞的非平凡的,现实世界的软件。现在,本文将重点介绍法兰的具体设计,以及其设计考虑多核系统的性能和可扩展性。
总体设计和工作流程:
可扩展模糊的危险:在模糊循环中,模糊器使用几个操作系统原语,当缩放模糊器以并行运行多个实例时,这些原语开始成为性能瓶颈,导致端到端性能比单个模糊度差。本文详细介绍了引信过程每个阶段的潜在系统瓶颈。
AFL的可扩展性:
作者的主要工作:
提出了一个新的系统调用snapshot(),它是一个轻量级的、可伸缩的、替代了模糊化。下图 Illustrates是一个如何使用快照系统调用的简化示例。Snapshot()创建进程的快照之后,进程可以继续执行。根据请求,snapshot()将进程的状态恢复为快照状态。其原型如下:
快照系统调用: |
命令是指“抓拍”,在快照时,用户可以注册一个回调函数、回调和一个共享地址范围的向量,共享的回调操作系统应该保持完整。例如,在模糊处理的情况下,shared_addrin指示模糊处理和目标处理之间共享的跟踪位图。当快照过程终止时,操作系统将调用注册的回调函数。目前,我们不支持嵌套的快照。Snapshot比Fork更轻、更可伸缩。它甚至比pthread_create有更好的性能,因为它不需要分配和释放线程堆栈,而pthread_create需要线程堆栈。
模糊化上下文中,作者将一个完整的模糊测试分为三个阶段,描述快照在不同阶段如何与内核和目标进程协作。
①在作者的设计中,在执行任何模糊运行之前,首先需要保存用户空间执行上下文,或者具体地说,保存所有当前寄存器值和信号掩码。然后它进入一个循环,继续等待来自Fuzzer实例的新的模糊请求。在接收到请求时,进程使用快照保留其内核上下文(beg_snapshot)并注册回调函数:callback()。这个用户回调函数作为每一个模糊执行的结尾,稍后我们将更详细地描述它。
②模糊化过程中:要求页复制,目标进程在返回快照后,继续使用运行时参数和环境变量执行其真正的主函数,当目标应用程序运行时,由于我们对页权限的只读修改,每个内存写操作(在页边界处)都会触发一个页错误。如之前所述,适用于任何可写页面。在我们修改的页面错误处理程序中,我们首先检查错误地址是否在最初的快照页面中。如果是这种情况,那么页面数据的副本将被修改并链接到具有额外写入权限的相应PTE。对于没有相应物理页面的未分配页面,我们只需要安装新页面,并使用额外的写入权限更新相应的PTE。最后,我们刷新TLB条目以保持一致性。
③在模糊化之后:快照恢复。在终止快照进程之前,我们调用注册回调函数。在正常终止的情况下,即从main()返回,它首先将退出状态通知其父进程,即控制引信实例。为了处理targetprocess callssexit()终止的情况,我们修改了sys_exit_group的entry函数,并检查进程是否快照。如果是这样,它会调用用户空间中注册的回调函数。另一方面,如果目标进程在执行的中间超时或崩溃,它将收到相应的信号,在默认情况下终止受害者进程。为了将异常状态通知给父进程并避免重新创建目标进程,我们的插入指令注册了一个特定的处理程序,用于每次注册时的每个关键信号。
双文件系统服务: |
作者引入了第二个操作原语双文件系统服务,为模糊化提供高效、可扩展的文件操作,其核心思想是利用Neithera Fuzzer实例和目标实例都需要这样一个强大的一致性模型。只有Fuzzer实例需要一致性,以便将突变状态序列化到持久存储中以获得持久性。在意外故障(例如电源或系统崩溃)时,预计测试用例会丢失,但Fuzzer始终可以在可接受的时间段内复制它们。新的文件系统服务提供了文件系统的两级分层:一个内存文件系统,另一个磁盘文件系统。
在引信之间有效地共享测试用例信息(如文件名和跟踪位图)的共享内存测试用例日志示例。通过共享测试用例信息,模糊器可以判断其他模糊器创建的测试用例是否有用,而无需重新执行测试用例或重新枚举测试用例目录。从概念上讲,测试用例日志是一个固定大小的循环日志,支持push()和pop()操作。与传统的循环日志不同,一旦所有迷糊器执行mpop()操作,就会从日志中删除元素。
共享内存测试用例日志 |
最先进的定标引信: |
遵循模糊循环的所有应用程序模糊器都可以从至少一个操作原语中获益。下表总结了这些原则在最近几年开发的10种已知的开源引信上的适用性。作者首先解释了这3种操作原则如何普遍提高应用引信的性能。其中,美国AFL和LibFuzzer两种典型的引信被广泛使用并成功地发现了大量的缺陷。它们也为许多后来的研究工作和模糊7奠定了基础。
共享内存测试用例日志界面概述。应用模糊器可以利用这些接口在运行实例之间共享测试用例,实现可扩展的协同模糊。模糊器实例调用push test case()以将其生成的测试用例的元数据(例如,文件名、跟踪位图)保存到其测试用例日志中,并调用epop testcase()以引用其他模糊器实例生成的测试用例的信息。因此,不再需要目录枚举和测试用例重新执行。
在Linux v4.8.10上实现并应用了作者的设计决策。我们为模糊器实现了一个新的x86_64系统快照,以克隆目标程序的一个实例。它支持快照运行进程的内存和其他系统状态,并将快照进程回滚到其原始状态。快照的系统调用号为329,它的实现涉及750行代码(loc),引入linux内核。快照还需要进行页面故障处理过程的协作。NEL以便在模糊运行期间跟踪内存更新。我们还修改了内核中用户进程的退出和信号处理例程,以防止快照在运行时意外终止,同时确保进程在不在快照中的情况下能够以预期的方式正常处理这些信号。这些变化涉及到内核源代码中不同位置的大约100个loc散射,我们还开发了一个库,其中包含大约100个loc的共享内存测试用例日志的6个接口。特别是,测试用例日志是作为Linux中的/dev/shmutility支持的posix共享内存对象来实现的。此外,我们还编写了一个100 loc的简单双文件系统服务守护程序,它可以由模糊器为分区上的私有工作目录启动,并定期刷新测试用例。
下图显示了原始版本和我们优化版本的flby每秒执行次数模糊了谷歌的模糊器测试套件plus libjpeg 1到120核。在相应的情况下,从90个核开始,每个模糊实例都超时,这导致没有进一步的执行,因为没有有效的输入测试案例用于由于AFL的库存版本中存在严重的性能瓶颈而导致的突变。
下图显示了LibFuzzer在1到120核上模糊Google的模糊器测试套件的原始版本和优化版本的每秒执行次数。
根据执行次数和模糊LibFuzzer所花费的时间来评估共享内存测试用例日志。下图显示了新执行的数量和在同步阶段花费的时间百分比。
对oursnapshot()系统调用againstfork()系统调用和pthread_create()函数的计算。下图显示了模糊LibFuzzer时impactofsnapshot()系统调用。下图显示了用于创建新进程的所有原语的可伸缩性,以及优化数据库,同时模糊LibFuzzer。
下图反应文件系统对该文优化版本的LibFuzzer的影响。
①适用的引信:我们只分析和改进了一般应用程序模糊器的性能和可扩展性,这些模糊器可以用具体的输入值来处理目标。我们的操作原语可能对许多其他模糊工具带来的好处较小,这些模糊工具主要用于符号执行、污染分析或指令模拟,以发现安全漏洞。操作系统核心引信也是超范围的,这些引信可能存在不同的性能瓶颈,需要相应的解决方案。
②跨平台实施:我们在Linux平台上实现了设计选择的工作原型。然而,由于MacOS和Windows应用程序的流行,对在它们中查找错误的需求更大。我们将在不久的将来把我们的实现移植到这两个平台上。
20199118 2019-2020-2 《网络攻防实践》综合实践
原文:https://www.cnblogs.com/dkycjy/p/13234909.html