开始测试

相比于示例中比较简单的用法,对于实际项目,可能需要对测试过程做更多的定制。 本章节会介绍测试中常用的参数。这些参数可以任意组合,以达到您的测试需求。 在命令行中输入 wfuzz fuzz --help 也可以看到更详细的参数列表。

多测试入口

如果您的程序比较复杂,从单一的测试入口,可能不能达到满意的覆盖率。 如果针对每个测试入口,编译一个二进制文件,可能会增加构建系统配置的复杂性。

WINGFUZZ支持在同一个二进制文件中,定义多个测试入口,并且连接到同一个可执行文件中。 后续在测试的时候,可以指定某一个测试入口执行。

您可以使用下方的例程来测试多入口功能,将下面的内容存为 multi-entrypoint.cpp 文件:

#include <wfuzz.h>

int add(int a, int b) {
    return a + b;
}

int sub(int a, int b) {
    return a - b;
}

WFUZZ_TEST_ENTRYPOINT(add);
WFUZZ_TEST_ENTRYPOINT(sub);

使用WINGFUZZ编译器编译上面的程序:

wfuzz-c++ -o multi-entrypoint multi-entrypoint.cpp

编译完成后,启动测试:

wfuzz fuzz multi-entrypoint

您会发现此时测试并未启动,而是显示了一个提示:

There are multiple candidate entries. Use -e/--entrypoint argument to choose one from them:
    add
    sub

这个错误提示的意思就是说该程序中有多个测试入口,需要用户指定一个入口才能开始测试。 wfuzz fuzz 命令支持用 -e--entrypoint 指定测试入口。 如果想要测试其中的 add 函数,可以使用下面的命令:

wfuzz fuzz multi-entrypoint -e add

使用这个命令后,就可以开始测试了,此时平台上,进入应用multi-entrypoint后,看到正在测试的模块名称是add。 如果想要测试sub函数,将上面命令行参数改为 -e sub 即可

指定测试时间

由于模糊测试的运行是反复迭代的,因此可以一直运行下去。 默认的启动参数并未限制测试的时间,如果用户想要停止,只能使用 Ctrl-C 键中断当前的测试。

如果您想通过脚本自动运行模糊测试,一般情况您可能会希望测试跑一段时间后就停止。 我们提供了 -t--timeout 参数,可以限制测试的运行时间。 该参数后面可以跟一个数字,单位是秒。

【我的第一次模糊测试】章节中提供的运行命令为例, 如果想要加上时间限制,可以使用下面的命令:

wfuzz fuzz first-fuzz --timeout 300

这里限制了时间长度为300秒,运行到这个时间后就会结束测试。

并行化测试

使用默认参数启动测试的情况下,我们只会启动一个目标程序。 如果您的测试机器性能比较强,有比较多的核心可用于测试,则利用多核心测试可以明显的提高测试效率。

我们提供了 -j--jobs 参数,可以设置测试的并行数量。该参数后面可以跟一个数字,数值就是并行的数量。

一般情况下,如果想要充分利用机器资源,可以使用(CPU数量-1)作为并行的数量,保留一个核心给WINGFUZZ SDK用于用例分析。

【我的第一次模糊测试】章节中提供的运行命令为例, 如果想要加上并行测试,可以使用下面的命令:

wfuzz fuzz first-fuzz -j4

此时会同时启动4个模糊测试器和目标程序。 在网站上可以看到这4个模糊测试器的详细信息:

  1. 在网站上的“应用测试” -> “测试列表”中找到这个测试
  2. 点击列表最右边的“查看报告”链接。
  3. 在“测试详情” -> “节点分布数” 下方点击“查看详情”
  4. 在打开的页面中,可以看到模糊测试器列表,此处可以查看每个测试器的详细状态。

初始种子

模糊测试算法类似于遗传算法,会从一个简单的初始输入开始,进行一些随机的修改,生成新的输入。 最初用到的测试输入集合就是初始种子。 初始种子库对于测试效果的影响是比较明显的。

默认情况下,我们的模糊测试器会随机生成比较简单的初始输入。 但如果程序需要比较复杂的输入,此时默认初始种子的效果可能就不太好。 此时可以手动生成一些输入文件,用它们作为初始的种子。 例如,可以使用单元测试的输入样例,作为初始种子。

另一种情况是,我们的程序经过一段时间测试之后,会有一个代码覆盖率。 通过分析这个覆盖率可以检查测试的效果,是否覆盖到了我们关心的代码位置。 如果有我们关心的地方未覆盖到,说明这个分支的条件比较复杂,全自动的生成方式可能不容易进入这个分支。 此时,我们可以在初始种子中加入一个样例,这个样例可以覆盖到此分支。 后续的测试中,模糊测试器就会对这个样例进行修改变异,生成更多的样例,就能更好的测到这部分代码。

初始种子库是一个目录,这个目录中的每个文件会被系统视为一个种子。 以【我的第一次模糊测试】章节中提供的运行命令为例, 如果想要指定初始种子库,可以使用下面的命令,其中 DIR 是初始种子库的目录路径。

wfuzz fuzz first-fuzz -i DIR

项目/模块名称

项目模块名称是在网站上显示的名称。 在每次测试开始的时候,SDK会先从平台获取到之前跑过的输入样例,进行一次回归。 这个回归就是按照项目模块名称来查找的。

另外,我们在测出程序缺陷的时候,会进行去重,去重也是按照项目模块为单位进行的。 不属于同一个项目/模块的问题,即使内容完全一样,也不会被认为是重复的。

默认情况下,我们会使用可执行文件的名称作为项目名称, 使用测试函数的名称作为模块名称。 如果想要修改默认行为,可以使用以下的参数:

  • -p / --project 参数可以设定项目名称。
  • -m / --module 参数可以设定模块名称。

【我的第一次模糊测试】章节中提供的运行命令为例, 如果想要更换项目模块名称,可以使用下面的命令:

wfuzz fuzz first-fuzz -p first-fuzz-2 -m echo2

此时运行起来后,在平台上看到的项目名称就是 first-fuzz-2,模块名称是 echo2。 如果您之前启动过first-fuzz,此时在平台上可以看到两个项目。 它们的数据是不同的,发现的缺陷也是分开的。