其他分享
首页 > 其他分享> > AFL++: Combining Incremental Steps of Fuzzing Research 翻译

AFL++: Combining Incremental Steps of Fuzzing Research 翻译

作者:互联网

文章目录

简述

略。

这篇文章中第二节,最新技术,值得关注。


翻译

下载地址(pdf/slider):AFL++: Combining Incremental Steps of Fuzzing Research

0. 摘要

在本文中,我们介绍了AFL++,这是一个由社区驱动的开源工具,它结合了最新的模糊研究,使研究具有可比性,可重复性,可组合性,并且-最重要的是-可用的 。它提供了多种新功能,例如,在Custom Mutator API (传统的突变API),能够增加模糊测试处理策略。有了它,特定目标的变异也可以由经验丰富的安全测试人员编写。我们希望AFL ++不仅成为当前的,而且也成为未来研究的新基准工具,可以与其他技术结合来评估最新技术的有效性。本文对hand-picked fuzzing technologies (手工模糊测试技术)进行了评估:亮点的事实是,虽然每种新颖的模糊测试方法都可以提高某些目标的性能,但会降低其他目标的性能。 这是未来的模糊研究在评估中应该考虑的地方。

1. 介绍

关于模糊测试的研究是一个蓬勃发展的领域。 模糊测试以完全自动化的方式发现了各种错误。 近年来,模糊测试在信息安全领域引起了极大的兴趣,并激发了各个领域的进步。 在Shoshitaishvili等人进行的测试中,符号辅助的模糊测试识别出的漏洞几乎是符号执行的三倍1

旨在改善模糊性的已开发技术的数量不断增加2——有时甚至根本没有完整功能的代码。 此外,模糊技术通常是独立地开发的,因此将它们组合起来可能是一个漫长的过程。 对于行业和OSS(Open Source Software)社区来说,很难决定哪个研究值得关注。取而代之的是,他们可能会坚持基本的设置,即使现代研究会更快地找到更多针对其目标的错误。 另一方面,研究人员自己可能很难评估他们的新颖工具,并可能发现自己无法将功能与兼容的技术相结合,从而解决了模糊测试中不同但相关的问题。例如为他们的变异子选择最近的种子调度。 如果新的反馈概念无法与解决其他问题(例如克服困难的比较指令)的现有技术结合使用,则可能无法发挥其全部潜力,从而减少由于统计数据不佳而导致的论文研究影响

在本文中,我们试图通过提高广泛可用的,研究支持的,模糊测试的标准,并为研究人员提供可扩展的API来解决这些问题我们提出了一种新颖的模糊测试框架AFL++。 未来的研究可以使用AFL ++作为新的基准。 它使研究人员可以评估其提案与已经在AFL ++中实现的最新正交功能的组合,从而大大减少了实现工作。 同时,它为行业专业人士提供了一系列基于最新研究的,易于使用的功能,可以极大地改善模糊测试的结果。AFL++是流行的覆盖率指导的模糊测试器AFL 3的重新设计版本,AFL已被证明是学术界和行业工作的坚实基础。

之所以选择AFL作为基础,是因为在该项目开始之初,它已经没有维护18个月了,与此同时,许多社区提供了补丁和学术支持。 因此,这提供了一个完美的开始。 对于LIBFUZZERHONGGFUZZ来说,这是不可能的,因为它们一直保持着活跃状态,并且相比之下,它们并没有得到很大的支持和增强(除了ENTROPIC [^9]和Vranken的增强4)。

虽然AFL++最初是作为AFL补丁和补丁的集合,但随着时间的流逝,我们重新实施了非基于afl的研究,例如REDQUEEN [^5],以及对AFL的研究级扩展,以使其可以用于AFL++。 然后,我们在此最新技术的基础上添加了新颖的功能,本文还将对此进行讨论。

总而言之,本文将对一年的活跃,开放源代码模糊测试进行深入分析,讨论所吸取的教训,并讨论新颖的Custom Mutator API(一种实现新颖的模糊研究的方法)。

(想法是希望开发不同的接口,来整合多种模糊测试技术,但目前仅开发出和突变相关的API?)

1.1 贡献

  1. 我们提出AFL ++,将最近的模糊研究纳入一个可用的工具中。
  2. 我们将讨论AFL ++新颖的Custom Mutator API,这是一种易于实现且面向未来的方法,用于实施和合并未来的研究。
  3. 使用AFL ++,我们可以相互评估彼此结合的技术和功能。我们展示了每种技术的目标依赖性如何——对未来的研究非常重要。

AFL ++和所有相关工件都是开源软件,可以在GitHub上找到:https://github.com/AFLplusplus 这项研究的测试案例可以在FuzzBench5上找到

2. 最新技术

American Fuzzy Lop(AFL)3是有史以来使用最广泛,最成功的覆盖指导模糊器之一。它是与模糊测试相关的各种出版物的当前基准。 在本节中,我们将讨论American Fuzzy Lop以及过去几年中为改进此模糊器的特定方面而进行的深入研究,但要尽可能简洁。 本节中介绍的概念与AFL ++直接相关,将在第三节中介绍。

2.1 American Fuzzy Lop

AFL是一种突变的,覆盖率指导的模糊器。 它变异了一组测试用例,以达到程序中以前未曾探索的点。 发生这种情况时,触发新覆盖率的测试用例将保存为测试用例队列的一部分。

2.1.1 覆盖率引导反馈

AFL的覆盖率反馈是一种混合度量,将边覆盖率与一次运行中相应边执行了多少次计数相结合。 如果输入为边缘探索了至少一个新的边,则认为该输入很有趣(即保存到队列中)。 这些存储区或命中计数在执行期间记录到共享位图,其中每个字节代表一个边。 该地图的大小是有限的,因此可能发生冲突。 AFL采用加权最小集合覆盖率的近似值,以覆盖率方面的速度和大小作为权重,以维护一组受欢迎的测试用例。
使用覆盖率反馈AFL还针对队列中的每个测试用例,尝试减小测试用例的大小并提高目标速度,同时在称为修整的阶段中保持完整的覆盖率。

2.1.2 突变

AFL的突变分为两类:确定性突变和破坏性突变。 确定性阶段包括测试用例内容的单个确定性突变,例如位翻转,加法,用一组常见有趣值(例如-1,INT_MAX等)中的整数替换等。 在破坏中,突变是随机堆积的,并且还包括测试用例大小的变化(例如,添加或删除输入的一部分)。 此外,在随后的阶段,AFL可以将两个测试用例合并为一个,并在所谓的拼接阶段进行破坏。

2.1.3 Forkserver 机制

为了避免execve() 的开销,AFL使用了所谓的forkserver机制。 模糊器将通过IPC机制控制的forkserver注入目标。 每当AFL需要执行测试用例时,它都会编写输入,然后告诉目标派生自己。 子进程将执行测试用例,父进程将等待此时间。 forkserver还可以稍后在目标中进行fork。 在这种情况下,模糊器不会支付每次运行昂贵的初始化和启动例程的费用。

2.1.4 Persistent 模式

持久模式大大提高了性能。 因为已知fork() 是瓶颈,所以对于持久模式,目标不会针对每个测试用例进行分叉。 取而代之的是,可以将循环修补到目标中,每次迭代执行一个测试用例。要进行工作,每次迭代都需要留出最少的状态变化。

2.2 聪明的调度

现代的覆盖率指导的模糊器可以实现不同的优先级排序算法,以调度模糊处理管道中的各种元素。 调度程序的目标通常是通过智能测试用例选择来提高总体覆盖率和错误检测

2.2.1 AFLFast

Böhme等人的AFLFAST 6, 说明需要强调低频路径以探索更多分支并发现更多错误。 他们对AFL进行了一些改进,不仅强调了通用路径,而且还旨在揭示其他程序行为。 它们突出了两个问题:

  1. 为了给低频路径施加压力,模糊器应以哪种顺序采摘种子?
  2. 我们可以调整每个种子产生的输入量(能量,比重)吗?

作者通过一套新颖的搜索策略解决了第一个问题,并通过引入六个功率调度表来解决第二个问题,该功率表可以根据模糊过程中收集的参数来计算输入量。

2.2.2 MOpt

作为种子调度的一个水平问题,MOPT 7引入了突变调度。 在研究中,Lyu等人使用定制的粒子群优化算法探索了赋予突变算子不同概率的可能性。 这种优化提高了模糊器快速发现覆盖范围的能力。 在对AFL的补丁程序中,作者将模糊测试阶段分为以下两个模块。 Pilot ,一个评估操作的模块,根据有效性分配概率。 Code 模块采用Pilot 分配的概率,生成变异。

2.3 绕开路障(Bypassing Roadblocks)

传统上,覆盖率指导的模糊测试器受阻于探索其背后代码的障碍。 典型的障碍是larger comparisons(较大的比较?),例如字符串和校验和检查。为了解决这个问题,进行了一系列研究。(译者注:这大段理解不了先跳过白泽 --读论文丨REDQUEEN)

2.3.1 LAF-Intel

LAF-INTEL 8是一项旨在通过将硬多字节比较分为多个单字节比较来绕过硬多字节比较的工作。 这样,这些比较可以逐字节传递,而覆盖率指导的模糊器则接收每个部分的反馈。 最初的实现是一组LLVM传递,拆分了整数比较,但是当在编译时知道其中一个参数时,也调用了字符串比较函数(例如strcmp)。 在细节上,LAFIntel:

  1. > =(和<=)运算符简化为>(<)和==比较的链;
  2. 将有符号整数比较更改为一系列仅符号比较和无符号比较;
  3. 将所有宽度为64、32或16位的无符号整数比较拆分为8位多重比较的链;

2.3.2 RedQueen

最近,基于KAFL [^36]的REDQUEEN [5]探索了绕过硬比较和校验和检查的可能性,就像文献[35] [^12] [^33] [^44]中其他先前的著作一样,但没有使用昂贵的方法 污点跟踪[46]或符号执行[6,37]等技术。 该模糊器关注于定义为“输入到状态”(I2S)的比较,这是一种比较类型,与输入中至少一个操作数的输入直接相关。 作者表明,许多障碍比较都是这种类型的,并开发了一种定位和绕过它们的技术。 REDQUEEN首先在其着色阶段增加输入中的熵,用随机数据替换字节,同时保持测试用例的覆盖范围。 这样,通过观察I2S比较的操作数,模糊器可以减少猜测的数量,以定位其在输入中的位置。 然后,REDQUEEN更改输入,以替换从比较中提取的I2S令牌,并再次使用此信息来定位校验和检查并将其修补。 在每个模糊测试阶段的最后,REDQUEEN再次使用I2S替换来修复新生成的有趣输入的校验和。 如果失败,则将修补的校验和检测为误判,将其删除。

2.4 突变结构化输入

模糊测试器的一个常见问题是,它们可能会生成大多数无效的输入,从而使解析阶段之后的程序状态不可访问。 解决方案是使用输入模型,有效地减少生成的输入的空间。 这允许基于反馈的模糊器探索程序中的深层路径。(译者注:这大段理解不了先跳过)

2.4.1 AFLSmart

Pham等引入了AFL的结构化模糊测试:AFLSMART [^34]。 AFLSMART使用PEACH [^14] pits 作为输入模型格式,这是结构化黑盒模糊测试的一种广泛使用的规范。 这种选择使得可以重复使用为PEACH编写的协议规范。 AFLSMART在第一次从队列中提取测试用例时对其进行解析。 它以延迟的方式完成了延迟,这使得AFLSMART可以回退到AFL,前提是它足够擅长探索覆盖范围而又不浪费时间进行解析。 解析步骤的结果是代表AST的虚拟结构。 AFLSMART引入了更高阶的结构突变,从而改变了虚拟结构而不是原始字节。 可以将其配置为仅使用这些结构突变,或者将其与Havoc中的其他结构突变堆叠在一起。

3 模糊测试的新基准

在本节中,我们将解释AFL ++的工程背景。 AFL ++的核心是AFL的一个分支版本,它是学术模糊研究的一部分基础模糊器,并且在业界也得到了广泛的使用。本节描述了AFL ++最重要的内容。 AFL ++不限于此处讨论的功能。 可用性和工程学方面较小的进步超出了本文的范围。 要深入了解这一小而有效的改进,请参阅AFL ++文档[^18]。

3.1 种子调度

AFL++合并了AFLFAST,and extends it with additional power schedules。 这包括来自AFLFAST的所有调度:fast,coe,explore,quad,lin,exploit。 这些调度是以下变量的函数:

  1. 从队列中选择种子的次数;
  2. 具有相同覆盖率的种子,生成输入的数量;
  3. 通常生成的具有相同覆盖率的测试用例的平均数量;

默认策略为探索。 除此之外,AFL ++还添加了mmopt和rare调度策略。 Mmopt会增加最新种子的比重,以帮助更深入地研究新发现的路径。 与其他计划不同,Rare忽略了种子的运行时间,并且将重点放在边缘很少被其他种子覆盖的种子上,这是一种有效的指标,如图[^24] [^10]所示。

3.2 突变

与AFL的传统确定性和Havoc管道相比,AFL ++包含更多的变异器。 突变器可以与其他结合使用。

3.2.1 自定义的突变API

AFL ++可以轻松地扩展到学术界的新研究中,并适合于发现漏洞的特定目标。为此,它提供了一个不断增长的API。 当前状态如下。

自定义突变器允许进行模糊的研究,以便在AFL ++之上构建新颖的调度,变异和最小化,而无需像许多当前工具那样分叉和修补AFL。 最初的支持是由Holler的AFL fork[^19]独立开发的,但后来扩展了许多新功能。 可以使用与C ABI兼容的语言编写插件,甚至可以使用Python原型制作插件。例如,使用当前的API,可以将AFLSMART 完全重写为AFL ++插件。 当前可以实现以下功能:

afl_custom_(de)init 每个自定义突变器可以使用这些自解释函数来初始化或取消初始化模块,afl_custom_init和afl_custom_deinit。 AFL ++的伪随机生成器种子将传递给init。 然后,自定义变量器应确保给定相同种子时,模糊结果可重现。

afl_custom_queue_get 是一个回调,它确定自定义模糊器是否应该对当前队列条目进行模糊处理。 在此例程中,用户还可以为输入(例如,用于结构化模糊的虚拟结构)执行关联的元数据的初始化。、

afl_custom_fuzz 在给定的输入上执行自定义突变。 它接受其他测试用例。

afl_custom_havoc_mutation 对给定的输入执行单个自定义突变。 此突变与破坏阶段的其他突变堆叠在一起。 afl_custom_havoc_mutation_probability返回自定义突变在浩劫中启用调整的概率(默认为6%,受AFLSMART启发)

afl_custom_post_process 在某些情况下,从自定义变量返回的变异数据的格式不适合直接使用此输入执行目标。 例如,当使用libprotobuf-mutator时,返回的数据为protobuf格式,该格式与给定的语法相对应,首先需要将其转换为目标的纯文本格式。在这种情况下,或者为了固定校验和和大小,用户可以定义afl_custom_post_process 函数 。

afl_custom_queue_new_entry 在将新的测试用例添加到队列后调用,这是将元数据存储在磁盘上的有用钩子。

Trimming Support 在AFL ++(第2.1.1节)中实现的通用修整例程可能会破坏复杂格式的结构。 当目标可以处理部分输入(引起覆盖)然后在其余输入上出错时,尤其如此。 在这种情况下,实施自定义修整例程很有意义。 该API由多种方法组成,因为在每个修整步骤之后,覆盖位图必须在修整之前与该贴图相对。

afl_custom_init_trim 在每次微调操作开始时调用,并接收初始缓冲区。 它应该返回此输入上可能的迭代步骤数(例如,如果输入中有n个元素应被删除,则返回n-1)。 如果实施的修整算法不允许确定(剩余)步数,则可以返回1表示可以进行进一步的修整,而afl_custom_post_trim返回0时将执行。

afl_custom_trim 每次微调操作都会调用。 它存储当前状态,因此可以节省每次迭代的重新分析步骤。 它应返回调整后的输入缓冲区,其中返回的数据长度不得超过初始输入数据的长度。

afl_custom_post_trim 在每次修剪操作之后调用,以告知修剪步骤是否成功(以相同的覆盖率而言)。 此方法必须返回下一个修剪迭代索引(从0到afl_custom_init_trim 中返回的最大步骤数)。

3.2.2 输入到状态的突变

AFL ++基于REDQUEEN的 InputTo-State(I2S)实现了一个转换器。 除了上述内容外,我们还进行了一些优化,以改进原始实现。

首先,着色(colorization)对于增加输入字节的熵似乎非常有效,但是,例如,如果临界字段(例如大小字段)被随机地突变,则可以大大降低模糊器的速度。 我们扩展了着色功能,不仅在覆盖位图的哈希值保持不变时,而且在执行速度保持在原始速度的2倍范围内时。 这种改善似乎和REDQUEEN的病理学目标有所不同。

另一个扩展是个概率的模糊。 如果模糊器在尝试绕过比较时未能生成有趣的输入,则下次该比较将以较低的可能性进行模糊处理。 这样可以避免在看似I2S但却不是的无法解决的比较上花费过多时间。

CmpLog Instrumentation 像最初的REDQUEEN实现一样,此mutator不使用断点记录比较操作数,而是使用类似于Fioraldi等人使用的共享表。 用于WEIZZ [^15]。 每次比较将其最后256次执行的操作数记录在Fuzzer与Target共享的256 MB表中。

该表的第一部分维护每个比较的元数据,例如大小,ID和实际执行次数。 就缓存位置而言,可以有效地遍历512 KB的总大小。 如果不使用比较,元数据就足以注册,并且永远不会访问与操作数相对应的内存。 该工具可用于LLVM和QEMU工具。

3.2.3 MOpt 突变器

AFL ++实现了MOPT的Core和Pilot模式。 除此之外,MOPT已针对AFL ++进行了修补,因此可以与Input-To-State mutator组合使用。 最重要的是,AFL ++支持将MOPT与标准突变模式进行交织。

3.3 Instrumentations

AFL ++支持多种仪器后端:LLVM,GCC,QEMU,Unicorn和QBDI。 最重要的是,它提供了一个代理模块,该模块可以适合于将测试用例转发到目标,并为afl-fuzz提供任何类型的覆盖,甚至包括远程覆盖和非覆盖,例如ampere 消耗或JTAG的分支地址。

表1展示了第3节中针对每个仪器后端讨论的最重要功能的实现状态。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGGmCW98-1611146363632)(/home/dacao/Nutstore Files/我的坚果云/图书馆/计算机/网络安全/论文/woot20-afl++.assets/表1支持特点.png)]

NeverZero 正交于用于仪器的后端,我们对AFL的命中率机制进行了优化。 使用字节作为位图条目的一个问题是边缘执行的计数可能溢出。 发生这种情况时,我们观察到,如果边缘以256的倍数命中-相应的位图条目溢出到0-模糊器处于不一致状态。 我们尝试通过两个解决方案(NeverZero和饱和计数器)解决此问题。 第一种避免总是将进位标志添加到位图条目上而导致溢出到0,因此,如果至少一次执行边沿,则该条目永远不会为0。第二种则在计数器达到255时冻结计数器。在一系列实验中,我们观察到NeverZero非常有效,并且在覆盖率和速度方面都提高了AFL(现在的种子选择考虑了以前隐藏的边缘)。 但是,饱和计数器会降低AFL的整体效果。 在大多数可用的仪器上,我们选择将NeverZero设置为AFL ++的默认值。AFL ++存储库的一个分支中仍然可以使用饱和计数器,以进行进一步的研究或复制。

3.3.1 LLVM

我们从LLVM [^23] 3.4直到LLVM 11都支持,在撰写本文时,它处于beta版本。 在LLVM模式下,除了边缘覆盖率[^43]外,AFL ++还支持一系列覆盖率指标:

上下文相关的边缘覆盖 (Context-sensitive Edge Coverage) 边缘覆盖是将每个块的分配ID与callee的唯一ID进行异或。 该解决方案首先在[^12]中进行了探索,并且在代码覆盖率方面似乎很有效,但代价是冲突更多,速度更低。

Ngram 在记录边沿时不会考虑前一个块和目标块,而模糊器会考虑目标块和N-1个前块,其中N是2到16之间的一个数字。

除了LLVM传递可用于覆盖反馈的工具外,AFL ++还提供了其他几个传递。 包括所有LAFINTEL通道,并具有实验模式,该功能还可拆分浮点比较,而浮点比较在视频解码器或Javascript解释器等软件中非常丰富。 此外,改进了字符串比较功能分析,以便在分配固定字符串时能够处理全局变量和局部变量。 如前面部分所述,CmpLog传递也可用。 广泛使用的功能(例如Fratrik [29])是要检测的文件列表,最早由[19]引入。 在LLVM模式下,用户可以为仪器指定特定的源模块。 例如,这对于处理许多输入格式的目标非常有用,而用户只想专注于其中一种。 在持久模式下,除了将输入传递到AFL(stdin或文件)中的目标的标准方法外,AFL ++还可以通过共享内存传递新的测试用例。 在我们的初始测试中,此配置将持久模式的速度提高了2倍,相对于fork模式,整体速度提高了10到20倍。

AFL ++ LLVM模式还实现了INSTRIM [^20]补丁,并结合了所有先前公开的功能。在LLVM中进行检测时,INSTRIM是选择基本块的有效方法。 由于基于Dominator Tree的分析,它避免放置无用的仪器。它可以将大多数目标上的仪器位置数量减少到至少标准仪器的一半,因此可以提高速度性能上的模糊器。

3.3.2 GCC

除了旧的afl-gcc包装器外,AFL ++还附带了一个GCC插件。 它包括对延迟初始化和持久模式的支持,例如AFL LLVM模式。 受支持的功能与LLVM不兼容,但是AFL ++中计划了其他功能,达到最终目的功能。

3.3.3 QEMU

2.1版仅用于二进制模糊测试的AFL QEMU补丁在AFL ++中几乎完全被基于QEMU 3.1.1的一组更好的补丁所取代。 与其他仅基于二进制的工具相比,例如基于二进制补丁的回写[^13],QEMU模式在仿真时添加了工具。 现在,在QEMU中选择一个块时,不再在仿真器的上下文中记录基本块转换,而是使用帮助程序内联了对记录例程的调用。 这样,我们可以重新启用AFL禁用的链接块(如[^8]首先以线程不安全的方式显示),平均速度提高2-3倍。 使用帮助程序还可以使用线程本地存储,这是TCG [^3]不支持的概念。 最近,我们的QEMU模式由Fioraldi和QAsan [16]进行了扩展,以结合基于动态二进制翻译的AddressSanitizer实现来支持针对堆违规的清理[38]。

CompareCoverage 为了缩小源级和二进制级模糊测试之间的功能差距,AFL ++ QEMU模式可以使用CompareCoverage [^31]以类似于LAFINTEL的方式拆分比较。 与LLVM传递不同,该代码不会被修改,但是会钩住所有比较,并会比较每个操作数的每个字节,如果相等,则会增加一个不同的位图条目。 该工具类似于基于Popcnt 的LIBFUZZER的工具,但在字节级别上,产生的输入量很少,以避免路径爆炸,这个问题使LIBFUZZER的值配置文件模式在某些目标上的效率低于正常模式。 它可以配置为仅拆分具有立即数操作数的整数比较,所有整数比较或所有整数和浮点比较。

Persistent Mode 与旧的QEMU模式不同,AFL ++的QEMU模式支持持久模式。 有两种主要方法可以实现此目的:

  1. 循环一个函数:像WINAFL [^17]一样,用户可以指定一个函数的地址,并且模糊器会自动在持久化循环中使用该函数修补返回地址。 该地址也可以不是函数的第一条指令,但是在这种配置下,用户必须在堆栈上提供偏移量,以正确定位要修补的返回地址。
  2. 指定入口和出口点:用户可以指定循环的第一条指令和最后一条指令的地址,QEMU将在运行时发出代码以在这些地址之间生成循环;

此模式甚至可以达到10倍加速,因此建议您尽可能使用此模式。

3.3.4 Unicornafl

对于模糊类二进制二进制文件(如固件),AFL ++包含了Voss [^40]的afl-unicorn分支,这为Unicorn Engine [^30]添加了AFL支持,称为unicornafl。 Voss的原始版本在最初的基本块上启动了forkserver,并且只能通过垃圾收集的python来使用,而AFL ++的unicornafl添加了低级C API,Rust和Python绑定,可以直接与AFL ++进行交互。 Unicorn已经包含用于设置页面映射,读取和写入内存和寄存器,添加挂钩以及在不同条件下启动和停止执行的API。 特定于AFL ++的API允许该工具随时启动快速持久模式,并设置多个出口和后模糊处理程序以检测崩溃。

该API提供uc_afl_forkserver_start,这是在特定时间点启动fork服务器的特定调用,可在进行模糊测试之前有效冻结当前状态,并告诉AFL ++开始生成输入。

特殊的uc_afl_fuzz函数可作为一站式服务,直接读取每个测试用例的输入-支持持久模式。 目标固件在父进程中保持相同状态,每个模糊测试用例均针对仿真器的分叉副本执行。 此外,forkserver包含一个受AFL QEMU模式启发的Unicorn JIT缓存机制。 Unicornafl将仪器直接修补到已翻译的块中,从而减少了间接跳转的需求,从而像QEMU模式中所讨论的那样重新启用了优化的块链接。 函数uc_afl_fuzz:

  1. 加载当前输入。
  2. 调用place_input_callback。 此处,线束应将输入写入仿真器内存中的适当位置。 对于持久模式,仿真器必须在此步骤中重置其他状态更改。
  3. 仿真,直到到达其中一个出口,通过挂钩取消执行或发生非法状态。
  4. 检查Unicorn返回,并(可选)调用crash_validation_callback,可以在其中进行额外的后处理以发现崩溃。
  5. 对于持久模式,请循环回到步骤3。

fuzz函数还获取将停止仿真的退出列表,是否在没有Unicorn错误条件的情况下也应调用验证回调的标志以及一个附加的整数计数器,该标志指示持久模式在再次分叉之前是否应循环(以及循环频率)。 Maier等能够在AFL++ 之上使用它来模糊内核[^26]甚至是蜂窝基带rtos [^27]。

3.3.5 QBDI

AFL ++可以使用LLVM对具有编译器检测功能的Android库进行模糊处理,但也可以检测封闭源代码库。 它支持与QuarksLab的QBDI动态二进制工具[21]框架一起用于Android本机库。 AFL ++的源发行版附带一个示例,使用法和扩展非常简单。

3.4平台支持

AFL ++保留了对多个操作系统和发行版的支持。 除了GNU / Linux之外,该模糊器还可以在Android,iOS,macOS,FreeBSD,OpenBSD,NetBSD上运行,并打包在Debian,Ubuntu,NixOS,Arch Linux,FreeBSD,Kali Linux等几种流行的发行版中。 为了获得广泛的支持,必须将许多功能(例如libdislocator,捕获内存错误的AFL分配器)移植到多个不同的操作系统,并使用以前不支持的分配例程(例如posix_memalign())进行扩展。 最重要的是,AFL ++的QEMU [7]模式具有Wine [1]模式,可以模糊GNU / Linux上兼容的Win32二进制文件。

3.5 Snapshot LKM

众所周知,基于fork()的AFL状态恢复机制是大量目标的性能瓶颈。 因此,AFL ++集成了Linux内核模块,其灵感来自Xu的Perffuzz [^45]。 Perffuzz实现了用于进程快照和还原的轻量级机制。 与fork相比,使用我们模块的单个内核的平均性能提高了2倍,但是由于fork()内核实现中的锁定,在许多内核上运行并行模糊测试时,差异会增加。 使用快照而不是fork不需要重新编译目标程序。 相反,一旦加载了驱动程序,就会自动检测到模块的存在。

4 评估用例

本节深入介绍了Sect中讨论的某些技术的模糊性能。 第三节中已发表的研究报告,也是AFL ++的可用部分。 为了展示AFL ++的实际效果,我们还讨论了在各自的分叉工具中无法实现的组合,例如RedQueen和MOpt的强大组合。

对于本节中的评估,我们将AFL ++与FuzzBench 5一起使用来再现和评估最新技术(FuzzBench的评估)。 AFL ++可用于比较各种模糊测试概念。在下文中,我们重点介绍了过去几个月在各种测试中收集的一些有趣的见解。 这些是示例运行,组合和评估,借助AFL ++作为基线的新工具可以在FuzzBench的帮助下完成这些评估。

由于AFL ++中包含的功能范围将超出本文的范围,因此我们选择了6种特定的配置:

  1. [Default] 默认AFL设置,并进行了一些特定的修复和改进。
  2. MOp 一个非常有效的突变器。
  3. Ngram4 另一种工具,将4个基本块解释为唯一路径。
  4. RedQueen Cmplog / RedQueen,这是模糊器的另一个反馈通道,可以到达更深的深度。
  5. Ngram4, Rare Ngram4仪器与Rare Schedule 配对,这是AFL ++中的独特组合。
  6. MOpt, RedQueen MOpt突变与RedQueen配对-AFL ++中的另一个独特组合

使用FuzzBench服务5收集了此处讨论的最终数据。 FuzzBench是Google的一项新颖服务,它对固定的21个目标集进行模糊评估,最初对所有感兴趣的项目分别进行24小时和23小时的评估。 每次运行大约要重做20次,以达到有意义的边缘覆盖率中位数,因为模糊测试中的随机性可能会产生意外的强力单次运行,但好的模糊测试应始终产生良好的结果。

从总共21个FuzzBench目标中,由于其特定的特征,我们选择了以下9个目标,它们显示出明显的异常行为。 我们从评估过程中测试并查看的大量AFL ++功能中选择了6个出色的组合,作为评估的一部分进行讨论。 FuzzBench上针对AFL ++特定和常规FuzzBench运行的狂热阅读器,可以使用此处未讨论的所有其他测试用例和目标。 该评估的最终数据来自FuzzBench运行2020-04-21-and-20-aflplusplus2

通过选择的6种组合,我们尝试证明:

RedQueen 在许多地区,RedQueen都可以通过其他配置无法克服的障碍,但是并非所有目标都具有此方法可以提供帮助的说明。 其中之一是libpcap示例,请参见图1g。 在这里,只有RedQueen能够达到任何深度,因为I2S替换允许此配置绕过障碍,而其他配置则无法随机猜测。 在这种情况下,MOpt增变器有助于进一步扩大覆盖范围。 对于OpenThread,RedQueen的性能也非常好,速度很快,请参见图1a,但有趣的是,如果不与MOpt配对。

MOpt MOpt表现出成功或失败-通常是非常有效的,但是如果不是,则性能通常很差,几乎没有中间地带。 对于mbedtls,请参见图1h,MOpt突然开始获得大量的新覆盖。 Mopt能够在运行过程中找到新路径,并且性能远远超过其他任何配置。 由于这发生在中位数的多次运行中,因此这不是一次事件,而是特定于目标的。

harfbuzz目标中的RedQueen和MOpt组合无疑是赢家,请参见图1e,就像libpcap目标中的图1g(其中只有RedQueen达到任何深度)一样,MOpt可以带来积极的结果。 在RedQueen花一些时间追赶的模糊目标中,MOpt证明非常有帮助,请参见图1b。

对于libjpeg-turbo,MOpt对RedQueen的行为有很大影响,几乎完全改变了中位数覆盖图,请参见图1d。

但是,对于lcms目标,可以做一个非常有趣的观察,其中RedQueen的积极作用与MOpt在lcms中的负面作用相反,见图1i。

**Ngram ** Ngram(在我们的测试中长度为4)可能是一种有效的检测方法,可以达到更大的深度,因为分支检测依赖于先前的分支,从而有效地添加了一些状态反馈。 zlib示例就是这种情况,请参见图1i。与几乎所有组合一样,稀有调度有时会比默认AFL ++调度有所改善,有时甚至会更糟。 另一个目标是libxml2,其中MOpt的性能较差,RedQueen几乎没有效果,但是Ngram4的亮度为1c。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LmcxLYOT-1611146363638)(/home/dacao/Nutstore Files/我的坚果云/图书馆/计算机/网络安全/论文/woot20-afl++.assets/coverge.png)]

4.1 AFL++ Optimal

在上一节中,我们评估了AFL ++中实现的一系列模糊技术的有效性以及它们组合在一起时的相互作用。

通常,在real-word模糊测试活动中,这只是第一步,在安全研究人员对不同配置进行首次评估之后,便开始进行微调。

根据我们对FuzzBench的评估,我们针对给定目标执行了AFL ++的精选设置,在运行中我们将其称为AFL ++ Optimal。

这是一个持续的过程,并且随着时间的推移会进一步改善。 反过来,学习将导致模糊器更好的默认设置。 例如,发现SanitizerCoverage是大多数情况下最好的检测选项,因此将其设置为默认值。

我们为21个可用目标中的13个手工制作并启用了AFL ++ Optimal。 这样,每个目标的最高中值覆盖率的百分比的平均归一化分数提高了7%,AFL ++ Optimal通常优于FuzzBench3上的所有其他模糊测试。

5 Future Work

尽管AFL ++项目在过去的一年中取得了良好的进展,但仍有更大的研究和工程问题需要解决。

5.1 Scaling

目前,AFL ++扩展到多个线程还不够理想。 由于它决定使用文件系统来进行测试用例传递,至少是对于不是LLVM的后端,并且由于对某些目标依赖fork()syscall,因此大部分时间都花在了内核上 。 面向快照的Linux内核模式的开发是朝这个方向迈出的第一步。 我们使AFL ++代码完全是线程安全的。 逻辑上的下一步将是多线程支持,从而最大程度地减少并行模糊器之间同步的开销。

5.2 Collision-Free instrumentation

AFL提供的原始操作会以某种潜在的冲突方式哈希当前往返地址的跳转。 这被视为速度和准确性之间的权衡,这是我们在不久的将来为基于源代码和仿真的两种仪器而努力解决的问题。

5.3 Static Analysis for Optimal Fuzz Settings

我们进行本文介绍的研究以优化AFL ++的预设。 当前的目标是使用最常见的最佳检测,变异和调度作为默认配置。 但是,正如我们在Sect4中所示 ,最优在很大程度上取决于目标。

对于将来的工作,通过事先对目标进行静态分析来找到适应症,可能会建议采取尽力而为的最佳解决方案-例如,大量的strcmp可能会表明您使用RedQueen等。 这项工作将基于4.1节中讨论的AFL ++ Optimal的结果。

5.4 Plug-in System

尽管Custom Mutator已为研究人员提供了很大的灵活性,但目标是添加其他插件功能来替换或向构建块(例如调度程序,执行程序和队列)添加功能。

除了命中率覆盖率之外,还将支持其他反馈,从头开始重新实现[^42] [^32] [^4]中所示的思想。

6 Conclusion

本文讨论的工具AFL ++试图整合最近的许多主要的模糊研究,将其整合到当前的AFL ++体系结构中是可行的,而我们自己的基准测试表明该技术在现实中已有了改进-在 最少适用于极端情况。

对所有已实现的功能进行基准测试后,按照Sect的规定在一个清晰的环境中进行测试。 从图4可以明显看出,这是模糊研发的重要一步。 每种建议的优化都针对特定目标,而对其他目标的效果可能不尽理想。 评估表明,这对于性能以及研究的可比性都有明显的好处。

最重要的是,AFL ++弥合了学术界和行业之间的鸿沟,以易于使用的方式向所有人提供学术进步。 在AFL ++的帮助下,已经可以发现和修补各种现实世界中的错误,例如社区发现的并在表2中列出的错误。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VjGN13vq-1611146363642)(/home/dacao/Nutstore Files/我的坚果云/图书馆/计算机/网络安全/论文/woot20-afl++.assets/bugs.png)]

在一年多的时间里,由于对AFL ++所做的工作,我们能够对模糊测试获得更多的见解。

AFL ++ Optimal中的AFL ++参数,显示了AFL ++中工具带的功能,每个人都可以使用。 我们希望以AFL ++为平台,为研究人员提供一个快速简便的方法来原型化并实施新的思想和策略。 Custom Mutator API插件系统使新研究思路的原型制作变得容易,并为行业专业人士提供了一种轻松的方法来根据他们的目标定制测试用例,同时仍能从学术研究和功能中受益。 使用其代理,它甚至可以适应全新的目标,服务器,嵌入式目标等。 希望将来的研究可以直接基于AFL ++的API,从而进一步改善最新技术。

最后,我们邀请研究人员为AFL ++本身的发展做出贡献,成为社区感兴趣的工具。AFL ++是(并且将永远是)免费和开源软件。

致谢首先,我们要感谢整个AFL ++社区,在这一年中他们积极提供了补丁,错误修复和新功能。 还要感谢FuzzBench的Jonathan Metzman,Abhishek Arya和LászlóSzekeres以及在其上运行AFL ++评估所提供的支持。

参考文献

见原文。


  1. an Shoshitaishvili, Ruoyu Wang, Christopher Salls, Nick Stephens, Mario Polino, Audrey Dutcher, John Grosen, Siji Feng, Christophe Hauser, Christopher Kruegel, and Giovanni Vigna. SoK: (State of) The Art of War: Offensive Techniques in Binary Analysis. In IEEE Symposium on Security and Privacy, 2016. ↩︎

  2. Valentin J. M. Manès, HyungSeok Han, Choongwoo Han, Sang Kil Cha, Manuel Egele, Edward J. Schwartz, and Maverick Woo. The art, science, and engineering of fuzzing: A survey. arXiv: Cryptography and Security, 2018 ↩︎

  3. Michał Zalewski. American Fuzzy Lop Whitepaper. https://lcamtuf.coredump.cx/afl/ technical_details.txt, 2016. ↩︎ ↩︎

  4. Guido Vranken. libfuzzer-ng: enhanced fork of libFuzzer. https://github.com/guidovranken/ libfuzzer-gv, 2017. ↩︎

  5. László Szekeres Jonathan Metzman, Abhishek Arya. FuzzBench: Fuzzer benchmarking as a service. Google Security Blog, March 2020. ↩︎ ↩︎ ↩︎

  6. Marcel Böhme, Van-Thuan Pham, and Abhik Roychoudhury. Coverage-based greybox fuzzing as markov chain. In Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security, CCS ’16, pages 1032–1043, New York, NY, USA, 2016. Association for Computing Machinery. ↩︎

  7. Chenyang Lyu, Shouling Ji, Chao Zhang, Yuwei Li, WeiHan Lee, Yu Song, and Raheem Beyah. MOPT: Optimized mutation scheduling for fuzzers. In 28th USENIX Security Symposium (USENIX Security 19), pages 1949– 1966, Santa Clara, CA, August 2019. USENIX Association. ↩︎

  8. Circumventing Fuzzing Roadblocks with Compiler Transformations. https://lafintel.wordpress.
    com/2016/08/15/circumventing-fuzzingroadblocks-with-compiler-transformations/, 2016 ↩︎

标签:AFL,afl,++,模糊,Research,测试用例,突变
来源: https://blog.csdn.net/sinat_38816924/article/details/112910305