
A linux system call fuzzer using TriforceAFL
新增:如果你想尝试 TriforceAFL 和 TLSF,Richard Johnson 创建了一个 Dockerfile,可同时安装两者(甚至还会为你构建一个 Linux 内核)。可在此处获取 https://hub.docker.com/r/moflow/afl-triforce/tags/。
这是一组用于使用 AFL 和 QEMU 对 Linux x86_64 内核执行系统调用模糊测试的文件。要使用它,你需要从 https://github.com/nccgroup/TriforceAFL 获取 TriforceAFL,以及一个待模糊测试的内核镜像。脚本假定 TriforceAFL 位于 $TAFL 或 ../TriforceAFL/ 中(注意:构建 testAfl 需要存在 ../TriforceAFL/config.h)。
构建方法:
make
要运行,首先将内核安装到 ./kern/bzImage,并将 /proc/kallsyms 提取到 ./kern/kallsyms。设置环境变量 K=kern 以指向你的内核。然后运行:
make inputs
./runFuzz -M M0
请注意,runFuzz 脚本需要一个 master 或 slave 名称,因为它始终以 master/slave 模式运行。更多用法信息请参阅 runFuzz 脚本。
另请注意,这只会创建一小组示例输入。要测试大量重要的系统调用,你可能需要为每个系统调用生成一个示例,或者至少为每种系统调用“形态”生成一个示例。这些示例应放在 inputs/ 中。示例见 gen2.py。
要复现测试用例(例如崩溃),运行:
./runTest inputs/ex1
./runTest outputs/crashes/id*
你也可以使用 -t 选项在模拟环境之外运行驱动程序,使用 -vv 进行详细日志记录,并使用 -x 不实际执行系统调用:
./driver -tvvx < inputs/ex1
strace ./driver -t < inputs/ex1
有时,能够启动内核并交互式地运行测试会很有用。为此,请按需编辑 rootTemplate 文件(例如,向根文件系统添加更多测试工具),然后运行:
./runCmd
除 shell 之外的其他命令可以通过将其作为命令行参数指定给 runCmd 来调用。注意:使用完 shell 后,按 ^A-c 获取 QEMU 提示符并输入 quit。
使用启用了调试符号编译的内核进行调试最为简单。使用 runTest 启动内核并通过驱动程序运行测试,或使用 runCmd 从 shell 手动运行测试用例。编辑你的运行脚本,在启动 afl-qemu-system-trace 时加入 -s 选项。这将在 TCP 端口 1234 上启用 gdb 支持。使用 getvmlinux 从你的 bzImage 内核中提取 vmlinux 内核镜像,并在系统启动后运行 gdb:
cp kern/bzImage .
./getvmlinux
gdb ./vmlinux
target remote :1234
break somefunction
continue
你可以在 runTest 导致崩溃后连接调试器,或者在你手动于 runCmd 中触发 bug 之前连接。
请注意,Linux 源码默认在开启优化的情况下编译。这可能会使调试变得令人困惑和困难。你可以逐个文件地禁用优化,方法是编辑文件所在子目录的 Linux make 文件,并在 Makefile 中添加 CFLAGS_name.o = -O0。例如,编辑 kernel/Makefile 并添加 CFLAGS_sys_ni.o = -O0 将在构建 kernel/sys_ni.o 时禁用优化。
getSyms shell 脚本使用 runCmd 执行 cat /proc/kallsyms,并将其提取到名为 kallsyms 的本地文件中。这通常用于为模糊测试准备你的内核:
K=yourKernDir ./getSyms 以获取 kallsymsmv kallsyms yourKernDir 以安装它注意:在对 Linux 2.* 内核进行模糊测试时,你需要启用 CPU 定时器。当定时器未启用时,panic 和日志检测似乎无法正常工作,并且 panic 会导致挂起。要启用定时器,请在 driver.c 中调用 startForkserver(1) 而不是 startForkserver(0)。此问题似乎不会发生在 Linux3.* 和 Linux4.* 内核中。