Evaluating
This paper proposed some evaluating guidelines from 5 aspects, including multiple runs, performance measurement, time out(running time for once), seed choices and target program. I’ll illustrate those guidelines below.
Multiple Runs
因为大多数的Fuzzer都采用了随机变异算法,所以如果在evaluating阶段对特定的<种子,运行参数,时间,等等>只运行一次,那么这个结果是不能代表其真实情况的。论文中的figure-2展示了当使用AFL和AFLFast再所有运行环境相同的情况下运行多次时发现crashes数量。可以从图中看到运行多次后其最大值和最小值差距比较大。
但是如果运行多次之后就会有多个不同的运行结果,如何找出一个结果来代表这种运行环境下的一般性的运行结果呢?
文中提到了permtation test和 bootstrap-based tests(自助抽样法)。
Performance Measurement
理想的来说Fuzzer性能的度量标准是发现了多少个bug。但是Fuzzer直接获取到的是导致崩溃的测试用例数,而不是bug数量,这两个之间不是一对一的关系(因为两个不同的输入可以触发相同的bug)。那么如何获取到真实bug的数量呢?
文中提到的手动方法是:逐个修复bug,直到没有bug出现位置,那么修复的数量就是这些崩溃所导致bug数量。
如果把确定真实bug数量的部分放入到Fuzzer中势必会导致性能下降并且目前似乎也没有自动化且0误差地获取真实bug数量的方法(这一部分是我自己读后的认为的),所以目前的Fuzzer普遍采用对导致崩溃的测试用例去重的方法,如coverage profile,stack hashes以及其他方法(vuzzer Exploitable)。
除此之外还有人使用路径覆盖率作为性能度量的标准,但是路径覆盖率与真实bugs之间的联系太弱不足以证明其效率。
Coverage-profile
这种方法的代表是AFL,如果新发现的一个崩溃满足下述条件,则会被认为是出现了一个新的bug。
- 其执行路径中有一条在之前的所有崩溃中都没出现的路径
- 其执行路径中缺少一条在之前所有的崩溃中出现过的路径
但是文中通过实现数据表明,正式漏洞的数量与fuzzing过程中找到的近视漏洞数量差距非常大,这两者之间的关系非常弱。
stack-hashes
这种方法的代表是AFLGo, 其建立栈调用的哈希值和bug之间的一一对应关系。哈希对象可以是栈中部分调用,例如距离crash发生最近的N个调用。这种方法相对coverge-profile要好很多,但是也存在误判,导致多数或者少数。
Timeout
时间太短不能体现出Fuzzer真实的运行情况。尤其一些特殊的Fuzzer, 例如Skyfile, 只能在较长时间内体现出其优势。并且大多数的文章中并没有说明timeout设置的理由。文章中给出的建议时间时至少24小时
此处的timeout指的是运行fuzzer多久。
Seed Choice
Fuzzing的性能与初始种子有很大的关系。文中使用了空文件、网上下载的文件样例和人工生成的文件作为fuzzing的初始种子来测试种子对于fuzzing的性能影响。结果在figure-3中进行了展示。
文章最后提出的意见是在evaluating时需要使用较多的种子(包括空文件),并且要说明种子的来源。
Target Program
文章在这一部分提出要使用多样化的测试程序,他将程序分为两类,真实程序以及人为编写的测试程序(CGC和LAVA)
文中提到真实程序在用于测试时会有两种问题,第一个:测试程序数量不够,并且没有说明每个程序的代表性;第二个很少有相同的Fuzzer在测试时使用相同的测试程序。第二个问题感觉有点莫名其妙,为什么要使用相同的程序????
Review
感觉文章不算太新颖,但是给人一种另辟新径的感觉。当所有人的关注点都是在如何提高Fuzzer效率时,他们却提出如何更加准确的度量Fuzzer的效率。这一点感觉很不错。
除过Target Program之外,文章对于其余四个点都是通过实验证明了自己对其提出的evaluating guidelines。
唯一让我感觉不足的是在target program中提出的一些意见没有充分理由。