拓展阅读

开源 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息)

开源 Junit performance rely on junit5 and jdk8+.(java 性能测试框架。性能测试。压测。测试报告生成。)

test fuzz-01-模糊测试(Fuzz Testing)

test fuzz-02-模糊测试 JQF + Zest Semantic Fuzzing for Java

test fuzz-03-模糊测试 Atheris A Coverage-Guided, Native Python Fuzzer

test fuzz-04-模糊测试 jazzer Coverage-guided, in-process fuzzing for the JVM

test fuzz-05-模糊测试 kelinci AFL-based fuzzing for Java

test fuzz-06-模糊测试 AFL american fuzzy lop - a security-oriented fuzzer

test fuzz-07-模糊测试 libfuzzer

AFL

快速开始

===================== AFL快速入门指南 =====================

您应该阅读docs/README。这相当简短。如果您确实无法阅读,以下是快速入门的方法:

1) 使用’make’编译AFL。如果构建失败,请查看docs/INSTALL获取提示。

2) 查找或编写一个相当快速且简单的程序,该程序从文件或stdin获取数据,以测试的方式处理数据,然后干净地退出。如果测试网络服务,请修改它以在前台运行并从stdin读取。在对使用校验和的格式进行模糊测试时,请注释掉校验和验证代码。

该程序在遇到故障时必须正确崩溃。注意自定义的SIGSEGV或SIGABRT处理程序和后台进程。有关检测非崩溃缺陷的提示,请参阅docs/README的第11节。

3) 使用afl-gcc编译要进行模糊测试的程序/库。这样做的常见方法是:

   CC=/path/to/afl-gcc CXX=/path/to/afl-g++ ./configure --disable-shared
   make clean all

如果程序构建失败,请联系afl-users@googlegroups.com

4) 获取一个小而有效的输入文件,使该程序有意义。当进行冗长语法(SQL、HTTP等)的模糊测试时,还需要创建一个词典,如dictionaries/README.dictionaries中所述。

5) 如果程序从stdin读取,请像这样运行’afl-fuzz’:

   ./afl-fuzz -i testcase_dir -o findings_dir -- \
     /path/to/tested/program [...程序的命令行...]

如果程序从文件中读取输入,您可以在程序的命令行中放置@@;AFL将为您放入一个自动生成的文件名。

6) 通过迅速查阅docs/status_screen.txt来调查fuzzer UI中显示的任何红色内容。

就是这样。坐下来,放松一下,然后(如果有时间的话)尝试浏览以下文件:

  • docs/README - AFL的一般介绍,
  • docs/perf_tips.txt - 如何更快地进行模糊测试的简单提示,
  • docs/status_screen.txt - UI中显示的细节的解释,
  • docs/parallel_fuzzing.txt - 在多个核上运行AFL的建议。

美国模糊簇(American Fuzzy Lop)

构建状态

由Michal Zalewski(lcamtuf@google.com)最初开发。

如果您没有时间阅读此文件,请参阅QuickStartGuide.txt。

1) 引导模糊测试的挑战

模糊测试是在现实世界软件中识别安全问题的最强大和经过验证的策略之一;它负责迄今为止在安全关键软件中发现的绝大多数远程代码执行和特权升级错误。

不幸的是,模糊测试也相对较浅;盲目的、随机的变异使得很难达到测试代码中的某些代码路径,使得某些漏洞无法通过这种技术得到解决。

已经有许多尝试解决这个问题的方法。早期的一种方法是由Tavis Ormandy首创的语料库提炼。该方法依赖于覆盖信号,从大规模、高质量的候选文件语料库中选择一部分有趣的种子,然后通过传统方法对它们进行模糊测试。该方法运行效果非常好,但需要这样的语料库是readily available。此外,块覆盖测量只提供对程序状态的非常简单的理解,对于在长期内引导模糊测试的效果而言,其用处较小。

其他更复杂的研究方法集中在技术,如程序流分析(”concolic execution”)、符号执行或静态分析。所有这些方法在实验环境中极具前景,但在实际使用中往往受到可靠性和性能问题的困扰,目前对于“愚蠢”的模糊测试技术并没有提供可行的替代方案。

2) afl-fuzz的方法

American Fuzzy Lop是一个蛮力模糊测试器,结合了一个非常简单但非常坚固的基于仪器的遗传算法。

它使用修改过的边缘覆盖形式,轻松捕捉程序控制流的微妙的、局部规模的变化。

简化一下,总体算法可以概括如下:

将用户提供的初始测试案例加载到队列中,

从队列中取下一个输入文件,

尝试将测试案例修剪到不改变程序测量行为的最小大小,

使用平衡且经过深入研究的各种传统模糊策略重复变异文件,

如果生成的变异导致仪器记录的新状态转换,将变异输出作为队列中的新条目添加。

转到第2步。

发现的测试案例还定期被剔除,以消除已被新的、覆盖面更广的发现所淘汰的测试案例,并经历其他几个基于仪器的努力最小化步骤。

作为模糊测试过程的副产品,该工具创建了一小部分有趣测试案例的自包含语料库。这些对于为其他耗费人力或资源的测试方案提供种子非常有用,例如用于对浏览器、办公应用程序、图形套件或封闭源工具进行压力测试。

该模糊器经过彻底测试,提供的性能远远优于盲目模糊测试或仅覆盖工具。

3) 为AFL添加程序仪表

当源代码可用时,可以通过一个附带工具将仪表插入,该工具可作为gcc或clang的可插拔替代品,适用于第三方代码的任何标准构建过程。

仪表的性能影响相对较小;与afl-fuzz实施的其他优化一起,大多数程序可以进行模糊测试,速度甚至比传统工具更快。

重新编译目标程序的正确方式可能因构建过程的具体细节而异,但几乎通用的方法是:

$ CC=/path/to/afl/afl-gcc ./configure
$ make clean all

对于C++程序,您还需要设置CXX=/path/to/afl/afl-g++。

clang包装器(afl-clang和afl-clang++)可以以相同的方式使用;clang用户还可以选择利用更高性能的仪表模式,如llvm_mode/README.llvm中所述。

在测试库时,您需要找到或编写一个简单的程序,该程序从stdin或文件中读取数据并将其传递给被测试的库。在这种情况下,必须将此可执行文件链接到仪表库的静态版本,或确保在运行时加载正确的.so文件(通常通过设置LD_LIBRARY_PATH)。最简单的选择是使用静态构建,通常可以通过以下方式实现:

$ CC=/path/to/afl/afl-gcc ./configure --disable-shared

在调用’make’时设置AFL_HARDEN=1将导致CC包装器自动启用代码加固选项,从而更容易检测到简单的内存错误。Libdislocator是AFL附带的一个辅助库(参见libdislocator/README.dislocator),可帮助发现堆破坏问题。

PS. ASAN用户建议查阅notes_for_asan.txt文件以获取重要注意事项。

4) 为仪表二进制应用程序

当源代码不可用时,fuzzer为黑盒二进制提供了实验性支持,实现了在较少知名的“用户空间仿真”模式下进行快速即时仪表。

这是通过在较少知名的“用户空间仿真”模式中运行的QEMU的版本完成的。

QEMU是一个与AFL分开的项目,但您可以通过执行以下操作方便地构建该功能:

$ cd qemu_mode
$ ./build_qemu_support.sh

有关附加说明和注意事项,请参见qemu_mode/README.qemu。

这种模式的速度大约比编译时仪表慢2-5倍,不太适合并行化,并可能有一些其他特 quirks。

5) 选择初始测试案例

为了正确运行,模糊测试工具需要一个或多个包含目标应用程序通常预期的输入数据示例的起始文件。有两个基本规则:

  1. 保持文件小。小于1 KB是理想的,尽管不是严格必需的。关于大小为何重要的讨论,请参见perf_tips.txt。

  2. 仅在它们在功能上彼此不同的情况下使用多个测试案例。在对图像库进行模糊测试时,使用五十张不同的度假照片是没有意义的。

在随附此工具的testcases/子目录中,您可以找到许多良好的起始文件示例。

PS. 如果有大量的数据可用于筛选,您可能希望使用afl-cmin实用程序来识别在目标二进制文件中执行不同代码路径的功能上不同的文件子集。

6) 对二进制文件进行模糊测试

模糊测试过程本身由afl-fuzz实用程序执行。该程序需要一个只读目录,其中包含初始测试案例,一个用于存储其发现的地方,以及要测试的二进制文件的路径。

对于直接从stdin接受输入的目标二进制文件,通常的语法是:

$ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program [...params...]

对于从文件中获取输入的程序,使用’@@’标记目标命令行中应放置输入文件名的位置。模糊测试工具将为您替换这个:

$ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program @@

您还可以使用-f选项将变异后的数据写入特定文件。如果程序期望特定的文件扩展名等,这将很有用。

非仪表二进制文件可以在QEMU模式(在命令行中添加-Q)或传统的盲目模糊测试模式(指定-n)中进行模糊测试。

您可以使用-t和-m来覆盖执行过程的默认超时和内存限制;可能需要触及这些设置的一些罕见的目标包括编译器和视频解码器。

有关优化模糊测试性能的提示,请参见perf_tips.txt。

请注意,afl-fuzz首先执行一系列确定性的模糊测试步骤,这可能需要几天时间,但往往会产生整洁的测试案例。

如果您希望立即获得快速而简单的结果 - 类似于zzuf和其他传统的模糊测试工具 - 请在命令行中添加-d选项。

7) 解释输出

请参阅status_screen.txt文件,了解如何解释显示的统计信息并监视进程的运行状况。如果UI元素中有任何突出显示的内容,一定要查看此文件。

模糊测试过程将继续进行,直到按下Ctrl-C。最少要允许模糊测试工具完成一个队列周期,这可能需要几个小时到一周左右的时间。

在实时更新的输出目录中创建了三个子目录:

  • queue/ - 每个独特执行路径的测试案例,以及用户提供的所有起始文件。这是第2节提到的综合体。在将此综合体用于任何其他目的之前,您可以使用afl-cmin工具将其缩小到更小的大小。该工具将找到一个提供等效边覆盖的文件子集。

  • crashes/ - 导致被测试程序接收到致命信号(例如SIGSEGV、SIGILL、SIGABRT)的唯一测试案例。这些条目按接收到的信号分组。

  • hangs/ - 导致被测试程序超时的唯一测试案例。在被分类为挂起之前的默认时间限制是1秒和-t参数值中的较大者。该值可以通过设置AFL_HANG_TMOUT进行微调,但这很少是必要的。

如果相关执行路径涉及任何先前记录的故障中未见的状态转换,则崩溃和挂起被视为“唯一的”。如果可以通过多种方式到达单个错误,那么在过程初期可能会有一些计数膨胀,但这应该很快就会减少。

与崩溃和挂起相关的文件名与父队列条目(非故障)相关联。这应有助于调试。

当您无法重现afl-fuzz发现的崩溃时,最有可能的原因是您没有设置与工具使用的相同的内存限制。请尝试:

$ LIMIT_MB=50
$ ( ulimit -Sv $[LIMIT_MB << 10]; /path/to/tested_binary ... )

将LIMIT_MB更改为与传递给afl-fuzz的-m参数相匹配。在OpenBSD上,还要将-Sv更改为-Sd。

任何现有的输出目录也可以用于恢复中止的作业,请尝试:

$ ./afl-fuzz -i- -o existing_output_dir [...etc...]

如果已安装gnuplot,还可以使用afl-plot为任何活动的模糊测试任务生成一些漂亮的图表。有关此操作的示例,请参见http://lcamtuf.coredump.cx/afl/plot/。

8) 并行模糊测试

每个afl-fuzz实例大致占用一个核心。这意味着在多核系统上,需要并行化才能充分利用硬件。有关如何在多个核心或多台网络机器上对常见目标进行模糊测试的提示,请参阅parallel_fuzzing.txt。

并行模糊测试模式还提供了一种将AFL与其他模糊测试工具、符号或合并执行引擎等进行接口的简单方法。有关提示,请参阅parallel_fuzzing.txt的最后一节。

9) 模糊测试字典

默认情况下,afl-fuzz的变异引擎针对紧凑的数据格式进行了优化,比如图像、多媒体、压缩数据、正则表达式语法或Shell脚本。对于具有特别冗长和冗余措辞的语言(特别是包括HTML、SQL或JavaScript在内的语言),它可能不太适用。

为了避免构建语法感知工具的麻烦,afl-fuzz提供了一种通过语言关键字、魔术头或与目标数据类型相关的其他特殊标记的可选字典来启动模糊测试过程的方法,并在进行过程中使用它来重建基础语法:

http://lcamtuf.blogspot.com/2015/01/afl-fuzz-making-up-grammar-with.html

要使用此功能,首先需要按照dictionaries/README.dictionaries中讨论的两种格式之一创建字典,然后通过命令行中的-x选项将其指向模糊测试工具。

(该子目录中已经提供了一些常见的字典。)

虽然无法提供有关底层语法的更多结构化描述,但根据仅仅基于仪器反馈,模糊测试工具可能会推断出其中的一些。实际上,这在实践中是有效的,参见:

http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html

PS. 即使没有提供显式字典,afl-fuzz仍会通过在确定性字节翻转期间密切观察仪器来尝试提取输入语料库中存在的语法标记。这对于某些类型的解析器和语法来说有效,但并不像-x模式那样好。

如果真的很难找到字典,另一个选择是让AFL运行一段时间,然后使用随AFL一起提供的token capture库。有关详细信息,请参阅libtokencap/README.tokencap。

10) 崩溃分类

基于覆盖率的崩溃分组通常会产生一个小的数据集,可以快速手动或使用非常简单的GDB或Valgrind脚本进行分类。每个崩溃也可以追溯到队列中的父非崩溃测试案例,从而更容易诊断故障。

尽管如此,必须承认,一些模糊测试崩溃可能很难在没有大量调试和代码分析工作的情况下快速评估其可利用性。为了帮助完成此任务,afl-fuzz支持非常独特的“崩溃探测”模式,可以通过-C标志启用。

在此模式下,模糊测试工具将一个或多个崩溃测试案例作为输入,并使用其反馈驱动的模糊测试策略,非常快速地列举在程序保持在崩溃状态的情况下可以到达的所有代码路径。

不导致崩溃的变异将被拒绝;同样,任何不影响执行路径的更改也将被拒绝。

输出是一个小型文件集,可以非常快速地检查攻击者对错误地址的控制程度,或者是否可能越过初始越界读取,并查看底层情况。

哦,还有一件事:关于测试案例最小化,请试试afl-tmin。该工具的操作方式非常简单:

$ ./afl-tmin -i test_case -o minimized_result -- /path/to/program [...]

该工具适用于崩溃和非崩溃测试案例。在崩溃模式中,它将高兴地接受已经过仪器检测和未经仪器检测的二进制文件。在非崩溃模式中,该最小化工具依赖于标准的AFL仪器,以使文件更简单而不改变执行路径。

最小化工具以与afl-fuzz兼容的-m、-t、-f和@@语法方式接受参数。

AFL的另一个最新添加是afl-analyze工具。它接受一个输入文件,尝试顺序翻转字节,并观察测试程序的行为。然后,它根据似乎关键的部分和不关键的部分对输入进行颜色编码;虽然不是百分之百可靠,但它通常可以迅速了解复杂文件格式。有关其操作的更多信息,请参见technical_details.txt末尾。

11) 超越崩溃

模糊测试是一种出色而且未充分利用的技术,用于发现非崩溃设计和实现错误。通过修改目标程序,调用abort(),可以发现一些有趣的错误,比如:

  • 两个大整数库在给定相同的模糊生成输入时产生不同的输出。
  • 图像库在多次解码相同输入图像时产生不同的输出。
  • 序列化/反序列化库在迭代序列化和反序列化模糊提供的数据时无法产生稳定的输出。
  • 压缩库在对特定块进行压缩然后解压缩时产生与输入文件不一致的输出。

实施这些或类似的健全性检查通常需要很少的时间;如果您是特定软件包的维护者,可以使此代码与 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION(与libfuzzer共享的标志)或 #ifdef __AFL_COMPILER(仅适用于AFL)相关联。

12) 常识风险

请记住,与许多其他计算密集型任务类似,模糊测试可能会对您的硬件和操作系统产生压力。特别是:

  • 您的 CPU 将变热,并且需要足够的冷却。在大多数情况下,如果冷却不足或不正常工作,CPU 速度将被自动调节。尽管如此,特别是在不太适合的硬件(笔记本电脑、智能手机等)上进行模糊测试时,不排除有可能出现问题。
  • 目标程序可能会异常地占用几吉字节的内存或用垃圾文件填满磁盘空间。AFL尝试强制执行基本内存限制,但无法阻止每一种可能的意外。归根结底,您不应该在数据丢失的风险不可接受的系统上进行模糊测试。
  • 模糊测试涉及对文件系统进行数十亿次读写。在现代系统上,这通常会被大量缓存,导致相当适度的“物理”I/O - 但有许多因素可能改变这个方程。您有责任监视潜在的问题;在非常重的I/O情况下,许多HDD和SSD的寿命可能会缩短。
  • 在Linux上监视磁盘I/O的好方法是使用 ‘iostat’ 命令:
$ iostat -d 3 -x -k [...可选磁盘标识符...]

13) 已知限制和改进空间

以下是AFL的一些最重要的注意事项:

  • AFL通过检查由于信号(SIGSEGV、SIGABRT等)而导致的第一个生成的进程死亡来检测故障。安装这些信号的自定义处理程序的程序可能需要将相关代码注释掉。同样,模糊测试目标生成的子进程中的错误可能会逃避检测,除非您手动添加一些代码来捕获。
  • 与任何其他蛮力工具一样,如果使用加密、校验和、加密签名或压缩来完全包装要测试的实际数据格式,模糊测试的覆盖范围就会受到限制。
  • 为了解决这个问题,您可以注释掉相关的检查(参见experimental/libpng_no_checksum/以获取灵感);如果不可能,您还可以编写一个后处理器,如experimental/post_library/中所述。
  • ASAN和64位二进制存在一些不幸的权衡。这并不是afl-fuzz的任何特定错误;请参阅notes_for_asan.txt以获取提示。
  • 暂时不支持模糊测试网络服务、后台守护程序或需要与用户界面交互才能正常工作的交互式应用程序。您可能需要进行简单的代码更改,使它们表现得更加传统。Preeny也可能提供相对简单的选项,参见:https://github.com/zardus/preeny
  • 修改基于网络的服务的一些建议技巧也可以在这里找到:https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop
  • AFL不输出人类可读的覆盖数据。如果要监视覆盖范围,请使用Michael Rash的afl-cov:https://github.com/mrash/afl-cov
  • 有时,有思想的机器反抗其创造者。如果发生这种情况,请咨询 http://lcamtuf.coredump.cx/prep/。此外,请参阅INSTALL获取特定于平台的提示。

    chat

详细介绍下 AFL

AFL(American Fuzzy Lop)是一款由Michał Zalewski开发的用于模糊测试(Fuzz Testing)的开源工具。它专注于发现软件应用中的安全漏洞和异常行为,是一种自动化的测试技术。

以下是 AFL 的一些关键特点和工作原理:

  1. 模糊测试: AFL 是一种基于模糊测试的工具。模糊测试是一种通过向程序输入提供随机或半随机数据(模糊数据)来发现程序漏洞的测试方法。AFL 通过变异输入数据,观察程序的反应,以此来推导程序的执行路径和发现潜在的安全问题。

  2. 变异策略: AFL 使用一种称为”mutation-based”的变异策略。它通过修改输入数据集合中的测试用例,生成新的测试用例。这些变异通常是基于现有输入的变化,例如位翻转、插入、删除等。AFL 根据每个输入的执行路径来调整变异的策略,使得更有可能探索到新的执行路径。

  3. 基于覆盖率的反馈: AFL 使用基于代码覆盖率的反馈来指导模糊测试。它会监控程序执行的路径覆盖率,并优先选择那些能够导致新的执行路径的输入进行变异。这种方式下,AFL 能够更加智能地调整测试用例,集中测试在程序的未探索路径上。

  4. 高效的并行化: AFL 支持高效的并行化,可以在多个 CPU 核心上同时运行。这有助于提高模糊测试的效率,快速发现潜在的问题。

  5. 定制性: AFL 允许用户通过指定一些选项来定制测试的行为。这包括设置最大执行时间、指定输出目录、调整变异策略等。

总体来说,AFL 是一个强大而灵活的模糊测试工具,广泛用于发现各种软件应用中的安全漏洞和错误。其基于代码覆盖率的反馈机制使得测试更加聚焦于程序的边缘情况,提高了漏洞发现的效率。

详细介绍一下 AFL 的核心概念

AFL(American Fuzzy Lop)是一种基于模糊测试的漏洞发现工具,其核心概念包括:

  1. 变异引擎(Mutation Engine): AFL 的核心是其高效的变异引擎,负责生成输入的变异版本。它使用多种策略,包括位翻转、算术变异、字节翻转等,通过不同方式改变原始输入,以生成具有潜在问题的新输入。

  2. 路径导向(Path Guiding): AFL 采用路径导向的模糊测试方法。在测试过程中,AFL 收集程序执行的路径信息。通过观察不同输入导致的执行路径,AFL 可以智能地选择变异,以生成更有可能导致新路径的输入。这有助于更全面地探索程序的执行空间。

  3. 基于覆盖率的反馈(Coverage-based Feedback): AFL 使用覆盖率信息来评估测试输入的质量。更具体地说,AFL 通过监控执行路径的覆盖情况来判断输入是否有助于发现新的执行路径。这种覆盖率反馈帮助 AFL 重点关注能够触发新代码路径的输入。

  4. Queue(队列): AFL 使用队列来管理待测试的输入集。初始时,队列包含一个或多个基本输入。随着测试的进行,AFL 会不断地生成新的变异输入,并将其加入队列。队列采用优先级机制,更能导致新路径的输入具有更高的优先级。

  5. 持久性(Persistence): AFL 具有持久性,能够在多次执行中保持其状态。这允许 AFL 在长时间内运行,不断提炼输入以发现更深层次的问题。

  6. 自动字典生成: AFL 自动构建输入字典,包含在变异时使用的种子(seed)。这有助于确保测试输入是有效的,并且在字典中存储了导致新路径的有效变异。

总体而言,AFL 的成功在于其巧妙的变异引擎和路径导向策略,使其能够高效而智能地发现程序中的漏洞和问题。

详细介绍一下 AFL 的基于覆盖率的反馈(Coverage-based Feedback)

AFL(American Fuzzy Lop)的基于覆盖率的反馈是其模糊测试的核心机制之一。

这种反馈机制基于程序的执行路径覆盖率,帮助导向输入的变异以更好地探索程序的不同执行路径。

以下是 AFL 基于覆盖率的反馈的详细介绍:

  1. 动态插桩: AFL 在目标程序的二进制代码中插入了动态二进制插桩(Dynamic Binary Instrumentation,DBI)代码。这些插桩代码用于监测程序的执行,记录已经执行的基本块(basic block)和边缘(edge)。

  2. 路径记录: 在运行时,AFL 跟踪程序执行时经过的路径,并将这些路径信息记录在内存中。路径信息包括覆盖的基本块和边缘,形成了执行路径的表示。

  3. 反馈计算: AFL 基于执行路径的覆盖信息计算覆盖率。这包括已经执行的基本块和边缘的数量。此信息被用于评估输入的质量,以及确定哪些路径是有望被更多地探索的。

  4. 路径权重分配: AFL 使用路径权重来指导变异引擎选择输入进行变异。路径权重通常与路径的执行频率和深度相关联。更频繁执行的路径和更深层的路径被赋予更高的权重,使变异引擎更有可能选择那些尚未完全探索的路径。

  5. 概率模型: 基于覆盖率的反馈机制采用概率模型,以确定如何变异输入。通过考虑路径权重,AFL 的变异引擎倾向于生成那些有望导致更高权重路径的变异。这样的概率模型使得 AFL 能够集中测试的注意力,更可能发现新路径。

  6. 自适应变异: 基于覆盖率的反馈机制使 AFL 具有自适应变异的能力。随着测试的进行,AFL 根据覆盖率信息不断调整变异策略,更好地适应程序行为的变化。

总体而言,AFL 的基于覆盖率的反馈机制使得模糊测试更具智能性,能够在测试过程中动态调整测试输入的生成,以更有效地发现程序中的潜在漏洞。

详细介绍一下 AFL 路径导向(Path Guiding)

AFL(American Fuzzy Lop)的路径导向(Path Guiding)是其模糊测试的关键概念,旨在通过智能地引导输入的变异,更有效地探索程序的执行路径。

以下是 AFL 路径导向的详细介绍:

  1. 路径探索: AFL 使用动态二进制插桩(Dynamic Binary Instrumentation,DBI)技术,例如 QEMU 模拟器,来在程序二进制中插入代码,以监控程序的执行路径。在运行时,AFL 记录程序经过的基本块(basic block)和边缘(edge)信息,形成路径图。

  2. 覆盖率信息: 通过监测执行路径,AFL 收集覆盖率信息,即程序中已经执行的基本块和边缘。这些信息用于评估测试输入的质量。目标是寻找输入,能够引导程序执行新的路径,从而增加测试覆盖率。

  3. 优先选择更有潜力的路径: AFL 通过计算路径的频率和深度等指标,为不同的输入分配权重。更频繁执行的路径和更深层的路径具有更高的权重。这使得 AFL 更有可能选择那些尚未完全探索的路径,以便更全面地测试程序。

  4. 基于概率的变异: AFL 的变异引擎使用概率模型来确定如何变异输入。它通过考虑路径权重,倾向于生成那些有望导致更高权重路径的变异。这种基于概率的变异有助于集中测试的注意力,以更有可能地发现新路径。

  5. 灰盒测试: 路径导向实际上是一种灰盒测试方法,因为它结合了白盒测试和黑盒测试的特征。虽然 AFL 不需要源代码,但通过监控二进制代码的执行路径,它能够在测试中更好地理解程序的内部结构。

  6. 自动字典生成: AFL 利用覆盖率信息自动生成输入字典。这个字典包含在变异时使用的输入种子(seed)。在路径导向的框架下,输入字典中存储了能够引导程序执行新路径的有效变异。

总体而言,AFL 的路径导向是一种基于覆盖率的智能模糊测试方法,通过动态分析程序执行路径,以概率为基础的变异策略,以及路径权重的优先级选择,使得测试更加聚焦和高效。

详细介绍一下 AFL 的变异策略

AFL(American Fuzzy Lop)的变异策略是其成功的关键之一。

它采用一种称为”mutation-based”的变异策略,通过对输入进行有针对性的变异来生成新的测试用例。这些变异旨在改变输入,使其更有可能导致程序执行新的路径,从而发现潜在的漏洞和异常行为。

以下是 AFL 的主要变异策略:

  1. Bit Flip(位翻转): AFL 会随机选择输入中的一个或多个位,并进行翻转。这样的变异能够在不改变输入的整体结构的情况下引入细微的变化,有助于发现程序对于输入位的灵敏性。

  2. Arithmetic Mutation(算术变异): AFL 会对输入进行一些基本的算术操作,例如加法、减法、乘法等。这种变异可以导致输入值的增加或减小,从而测试程序对于较大或较小输入的处理情况。

  3. Byte Flip(字节翻转): AFL 可以选择一个或多个字节,并进行翻转。这种变异也是为了引入输入的微小变化,探索程序对于输入字节的敏感性。

  4. Dictionary-based Mutation(基于字典的变异): AFL 可以使用预定义的字典文件,将输入变异为其中的某个条目。这对于测试特定的字符串或格式化输入非常有用。

  5. Splicing(拼接): AFL 会将两个不同的输入的一部分拼接在一起,创建一个新的混合输入。这有助于测试程序对于多种输入的组合情况。

  6. Havoc(大破坏): Havoc 是 AFL 的一种更为激进的变异模式,它会在输入的多个位置引入更大规模的随机变化,包括删除、插入和截断等。这有助于扩大测试范围,发现更多可能的执行路径。

总体而言,AFL 的变异策略是基于对程序执行路径的监控和反馈机制的。

AFL会关注程序对于每个输入的执行路径,倾向于选择那些能够导致新的执行路径的变异策略。

这种基于代码覆盖率的反馈机制使得 AFL 在测试中更加智能和高效。

给出上述变异策略的具体例子

以下是 AFL 变异策略的具体例子:

  1. Bit Flip(位翻转):
    • 原始输入:11001100
    • 变异后的输入:11101100(翻转第四位)
  2. Arithmetic Mutation(算术变异):
    • 原始输入:10
    • 变异后的输入:11(加法变异)
  3. Byte Flip(字节翻转):
    • 原始输入:ABCD
    • 变异后的输入:AxCD(翻转第二个字节)
  4. Dictionary-based Mutation(基于字典的变异):
    • 字典文件内容:
      string1
      example
      test123
      
    • 原始输入:(从字典中选择)test123
    • 变异后的输入:(从字典中选择)example
  5. Splicing(拼接):
    • 原始输入1:abcd
    • 原始输入2:1234
    • 变异后的输入:ab34
  6. Havoc(大破坏):
    • 原始输入:abcdefgh
    • 变异后的输入:12cd5efg(删除ab、插入12、截断efgh

这些例子演示了不同变异策略如何对输入进行修改。AFL 通过多次执行这些变异,观察程序的执行路径,然后选择那些导致新路径的变异。

这使得 AFL 能够智能地探索程序的不同执行情况,从而提高发现潜在漏洞和问题的可能性。

给出 AFL 的深入学习资料,包含网址

AFL(American Fuzzy Lop)是一个广泛使用的模糊测试工具,有许多资源可以帮助你深入学习。

以下是一些学习 AFL 的深入资料和相关网址:

  1. AFL GitHub 仓库:
    • GitHub 仓库包含 AFL 的源代码、文档和最新的发行版。
    • AFL GitHub 仓库
  2. AFL Documentation:
  3. AFL Google Group:
    • AFL 的 Google Group 论坛是一个讨论 AFL 使用和开发的地方。
    • AFL Google Group
  4. AFL Technical Papers:
    • 有关 AFL 技术细节的学术论文,包括原始的论文和后续的更新。
    • AFL Technical Papers
  5. AFL Blog:
    • AFL 的创作者在博客上分享了一些关于 AFL 的见解和使用技巧。
    • AFL Blog

这些资源应该足以帮助你深入学习 AFL,从基本概念到高级用法。记得查阅官方文档和社区讨论,以获取最新的信息和支持。

参考资料

https://github.com/rohanpadhye/jqf