https://www.cnblogs.com/xuesu/p/14551924.html
http://www.hackdig.com/03/hack-77659.htm
用 AFL 玩超级玛丽:通过Fuzzing探索程序空间状态以发现更多执行路径
摘要
目前fuzzing的技术仍无法全自动地、高效地解决复杂状态机的问题。当前大多数方法仅限于添加字典或新的种子作为输入来引导fuzzer。在处理复杂程序时,这些“人机交互”机制无法发现代码库的新部分。
在本文中,作者提出了IJON,这是一种注释机制(annotation mechanism),分析人员可以使用它来指导fuzzer。与上述两种技术相比,此方法可以根据代表程序内部状态的数据对程序的行为进行更系统的探索,使得用户可以使用很少的注释(通常是一行)来帮助fuzzer解决以前无法解决的挑战。作者扩展了各种基于AFL的fuzzer,使其能够用指导提示来注释目标应用程序的源代码。
评估表明,这种简单的注释能够解决当前基于fuzzer或符号执行的工具无法克服的问题。例如,通过作者的扩展,fuzzer能够玩并解决诸如Super Mario Bros.之类的游戏,或者解决诸如哈希映射查找之类的更复杂模式。为了进一步展示注释的功能,作者结合使用AFL和IJON来发现新颖的安全性问题以及以前需要自定义和全面语法的问题。最后,证明使用IJON和AFL可以解决CGC数据集中的许多挑战,这些数据集可以抵抗目前为止的所有全自动和人工指导的尝试。
一方面,我们实现了一种将注释应用于目标应用程序的方法。另一方面,我们扩展了ijon和目标之间的通信通道。
问题
目前fuzzing难以解决一些条件,比如需要复杂状态自动机的
改进反馈机制
将反馈机制扩展到代码覆盖范围之外以避免陷入停滞状态而提出的各种方法。值得注意的是,
LAF-INTEL[1]是通过将大型比较指令拆分为多个较小指令来解决魔法字节类型约束(例如,if(input==0xdeadbeef))的早期方法。后来,在一个名为STEELIX[32]的工具中使用动态二进制插装实现了同样的想法。将多字节比较指令拆分为多个单字节指令,使模糊器能够在每次操作数的单个字节匹配时找到新的覆盖范围。
ANGORA[14]为每个函数分配一个随机标识符。它使用这些标识符通过包含当前执行上下文哈希的第三个字段扩展覆盖率元组。为了计算这个散列,它使用XOR操作组合了已调用但尚未返回的函数(即活动函数)的所有标识符。这允许在不同的调用上下文中使用“相同”覆盖率。例如,此方法有助于解决对strcmp函数的多个调用。然而,这种方法的缺点(即,认为所有调用上下文都是唯一的)是,在某些情况下,这会创建大量实际上并不有趣的输入。因此,ANGORA需要比AFL更大的位图。
设计
我们设计了一组注释,以使分析师能够影响模糊器的反馈功能。我们的目标是使分析人员可以使用这些注释为模糊过程提供高级指导。
在交互式的模糊测试会话中,分析人员会不时检查代码覆盖率,以识别似乎难以覆盖的分支。然后,分析人员可以确定模糊器无法取得进展的原因。找到障碍后,分析人员可以开始第二次模糊测试会话,重点是使用自定义注释解决此障碍。
批注本身是目标应用程序的一个小补丁,通常由提供额外反馈信息的一行(有时是两行)代码组成。当模糊器解决路障时,长时间运行的模糊会话会从临时会话中选择会产生新覆盖的输入,并继续进行模糊检测,从而克服了困难的情况。
我们设计了四个可用于注释源代码的通用原语:
1)我们允??许分析人员选择与解决当前问题相关的代码区域。
2)我们允许直接访问AFL位图以存储其他值。位图条目可以直接设置或递增,因此可以将状态值公开给反馈功能。
3)我们使分析师能够影响覆盖范围的计算。这允许相同的边缘覆盖范围导致不同的位图覆盖范围。这允许在不同状态下创建更细粒度的反馈。
4)我们引入了一个原语,该原语允许用户添加爬山优化[48]。
- IJON-Enable
IJON-ENABLE(和IJON-DISABLE)注释可用于启用和禁用覆盖率反馈。这样,我们可以有效地排除代码库的某些部分,或者引导模糊程序仅在满足某些条件的情况下探索代码。 - IJON-INCandIJON-SET
IJON-INC和IJON-SET注释可用于增加或设置位图中的特定条目。这有效地允许将状态中的新值视为等于新代码覆盖率。分析师可以使用此注释有选择地向模糊程序公开状态的各个方面。因此,模糊程序可以探索这个变量的许多不同值。实际上,此注释在代码覆盖范围之外添加了一种反馈机制。fuzzer现在还可以通过其测试用例获得新的数据覆盖率。此注释可用于在我们前面描述的所有三种场景中提供反馈。 - IJON-STATE
为了产生更细粒度的反馈,我们可以研究状态和代码覆盖率的笛卡尔乘积。为了实现这一点,我们提供了第三个原语,它能够改变边缘覆盖率本身的计算。与ANGORA相似,我们使用第三个名为“虚拟状态”的组件扩展了edge元组。在计算任何边的位图索引时,也会考虑此虚拟状态组件。此注释称为IJON-STATE。每当虚拟状态更改时,任何边缘都会触发新的覆盖。必须小心使用该原语:如果虚拟状态的数量增长过大,模糊器将被大量输入淹没,从而有效地减慢模糊过程。 - IJON-MAX
在某些情况下,我们希望针对特定目标进行优化,或者状态空间太大,无法完全覆盖。在这种情况下,我们可能不关心一组不同的值,或者希望放弃所有中间值。为了在这种情况下实现有效的模糊化,我们提供了一个称为IJON-MAX的最大化原语。它有效地将模糊化程序转换为一个基于爬山的通用黑盒优化器。要使多个值最大化,请选择多个(默认情况下为512)
未来工作
在这篇文章中,我们描述了一种交互式模糊化方法。虽然这提供了引导模糊化过程的新方法,但它需要手动检查测试覆盖率,了解约束难以解决的原因,并手动创建合适的注释。这种手动操作会给分析人员带来一定的成本,但我们的评估表明,这种方法可以克服当前模糊程序的几个障碍。例如,很明显,无论是语法还是字典都不能帮助模糊者解决超级马里奥级别的问题。此外,找到好的种子输入并不容易。在这种情况下,适用于此目标的记录和重放机制(如HACRS或DYNODROID版本)可能会有所帮助,但在许多其他情况下(如二进制格式),可能不会。IJON中使用的注释目前是手动添加的。设计只为困难的单个约束自动推断注释的方法将是有趣的。一些现有的模糊化方法使用我们描述的注释子集。例如,LAF-INTEL可以通过在比较中注释相等字节数来表示。类似地,ANGORA已经为所有覆盖范围实现了基于调用堆栈的虚拟状态。然而,所有这些工具都不加区别地使用额外的反馈。因此,它们仅限于低信息增益反馈机制。以类似的方式使用更精确的反馈将导致更大的队列并降低性能。识别IJON注释的自动化技术可以利用比LAF-INTEL和ANGORA更强大的注释,因为它们应用很少。最后,现在,注释需要源代码访问。原则上,没有理由不能为仅二进制目标实现类似的注释。将IJON与仅二进制模糊器集成将是一件有趣的事情。
作者实际上引入了“注释机制”来为分析人员提供与fuzzer更有效的交互方式,通过简单的几行注释就能解决现有fuzzer无法解决的困难问题。
作者设计了一套源码注释原语,其实就是给源码加个一两行补丁代码,用来干预Fuzzer的反馈功能。在可交互的Fuzzing会话中,分析人员可以人工介入去分析一直无法触达的执行路径,然后为其增加补丁代码解决路径探索障碍的问题。
afl-gcc或afl-clang本身就是对gcc/clang编译器的封装,添加一些编译选项,以及代码插桩的功能,作者为其编写了个链接库,以实现前面所说的注释原语,包括一些自定义函数和宏等,通过它能够访问AFL用于存储覆盖信息的位图(其实是个哈希表),直接添加和设置条目上去,将状态值直接反馈给Fuzzer。同时,也允许相同的edge coverage存储到不同的覆盖位图中,因为不同的状态值可能触发的是同一处edge coverage,这代表它能够实现更细粒度的反馈,为此它还提供扩展用于存储覆盖位置的共享内存区域。对于状态空间爆炸的问题,也会提供"爬山算法”(hill-climbing)作出优化选择。