input corpus
收集语料库
对于模糊测试工具而言,浅谈我们需要为其准备一个或多个起始的何进输入案例 ,这些案例通常能够很好的行有效测试目标程序的预期功能,这样我们就可以尽可能多的规整覆盖目标程序。
收集语料的浅谈来源多种多样 。通常目标程序会包含一些测试用例 ,何进我们可以将其做位我们初始语料的行有效一部分,此外互联网上也有些公开的规整语料库你可以收集他们做为你的需要 。
关于语料库的源码下载浅谈主动性选择 ,这个更多需要你对fuzzing 目标内部结构的何进了解 。例如你当你要fuzzing的行有效目标对随着输入的规模内存变化非常敏感 ,那么制作一批很大的规整文件与较小的文件可能是一个策略,具体是浅谈否是否有效取决于你经验、以及对目标的何进理解。
此外 ,云计算行有效需要注意控制语料库的规模,太过庞大的语料库并不是好的选择,太过潘达的语料库会拖慢fuzzing的效率,尽可能用相对较小的语料覆盖更多目标代码的预期功能即可。语料库唯一化
我们在上一小节最后提到一点 ,太过庞大的语料库会因为有太多的测试用例重复相同的建站模板路径覆盖 ,这会减慢fuzzing的效率 。因此人们制作了一个工具,能够使语料库覆盖的路径唯一化 ,简单的说就算去除重复的种子输入,缩减语料库的规模 ,同时保持相当的测试路径效果。
在AFL++中可以使用工具afl-cmin从语料库中去除不会产生新路径和覆盖氛围的重复输入,并且AFL++官方提示强烈建议我们对语料库唯一化 ,免费模板这是一个几乎不会产生坏处的友谊操作。
具体的使用如下:将收集到的所有种子文件放入一个目录中,例如 INPUTS运行 afl-cmin:字典
其实将字典放到这一个大节下面不是很合适,因为字典可以归类为一种辅助技巧,不过因为字典影响输入,所以我就将其划到这里了。
关于是否使用字典,取决于fuzzing的目的与目标。源码库例如fuzzing的目标是ftp服务器,我们fuzzing的目的是站在用户的视角仅能输入命令 ,因此我们的输入其中很大一部分可以规范到ftp提供的命令,我们更多的是通过重复测试各种命令的组合来测试目标ftp服务器在各种场景都能正确运行。
又比如,模板下载当你fuzzing一个很复杂的目标时,它通常提供一个非常非常丰富的命令行参数,每一次运行时组合不同的参数可能会有更好的覆盖效果,因此可以将你需要启用的参数标记为字典添加进命令行参数列表中 。
最后 ,目标程序可能经常有常量的比较和验证,而这些环节通常会使得fuzzing停滞在此,因为模糊器的变异策略通常对应常量的猜测是非常低效的。我们可以收集目标程序中使用到的常量 ,定义为一个字典提供给模糊器 。但目前对于AFL++来说有更好的方法解决这种需求 ,而无需定义字典,后面我们会介绍这些方法。 复制# 模糊器默认的变异策略通常难以命中if分支为true的情况 ,因为input做为64位 ,其值的空间太大了 ,根本难以猜测。 if (input = 0x1122336644587) { crash(); } else { OK(); }1.2.3.4.5.6.7.编译前的准备
选择最佳的编译器
如我们上一节中谈到收集程序常量定义字典时,事实上收集常量并生成字典这个事情,在编译时完全可以顺便将其解决。没错,功能强大的编译器可以使我们在编译期间获得非常多有用的功能。对于AFL++的编译器选择,官方提供了一个简单的选择流程,如下
复制+--------------------------------+ | clang/clang++ 11+ is available | --> use LTO mode (afl-clang-lto/afl-clang-lto++) +--------------------------------+ see [https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.lto.md](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.lto.md) | | if not, or if the target fails with LTO afl-clang-lto/++ | v +---------------------------------+ | clang/clang++ 3.8+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++) +---------------------------------+ see [https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.llvm.md](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.llvm.md) | | if not, or if the target fails with LLVM afl-clang-fast/++ | v +--------------------------------+ | gcc 5+ is available | -> use GCC_PLUGIN mode (afl-gcc-fast/afl-g++-fast) +--------------------------------+ see [https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.gcc_plugin.md](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.gcc_plugin.md) and [https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.instrument_list.md](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.instrument_list.md) | | if not, or if you do not have a gcc with plugin support | v use GCC mode (afl-gcc/afl-g++) (or afl-clang/afl-clang++ for clang)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.若你的LLVM和clang版本大于等于11 ,那么你可以启用LLVM LTO模式,使用afl-clang-lto/afl-clang-lto++,该模式通常是最佳的。随后依次是afl-clang-fast/afl-clang-fast++和afl-gcc-fast/afl-g++-fast 。
关于为什么LTO模式通常是最佳的,其中一个原因是它解决了原版AFL中边碰撞的情况 ,提供了无碰撞的边(edge)检测