开始日期:2021年12月
这是一个基于覆盖引导、基于模拟的灰盒模糊测试器,利用自定义的即时编译器实现接近原生的性能。它的工作原理是将 RISC-V ELF 二进制文件提升为中间表示,然后在执行期间将其 JIT 编译为 x86。在 JIT 编译期间,代码会被插桩,以启用诸如覆盖率跟踪、asan、cmpcov 或基于快照的模糊测试等模糊测试改进功能。

本项目的目标是强调使用模拟环境进行模糊测试的好处。以往存在许多基于模拟的模糊测试器,但它们几乎无一例外地使用 qemu 模拟引擎作为底层模拟。虽然该引擎确实拥有相当成熟的即时编译器并能生成非常好的代码,但它并非为模糊测试而设计。在模糊测试期间, 我们打算每秒运行同一进程数千次。这为 qemu 并未充分利用的专门优化留出了空间,例如为每次进程运行复用相同的内存空间, 并仅通过脏位机制重置有限的内存。
在很多方面,这更像是一个概念验证项目,我希望能通过它来学习编译器内部原理,并拥有一个基于模拟的游乐场来尝试各种模糊测试技术,例如不同的覆盖率指标、种子调度器和基于快照的模糊测试。然而,如果能加入更多的 JIT 优化,最重要的是扩展以支持更流行的架构(如 mips 或 arm),那么它肯定可以有效地模糊测试那些无法通过重新编译进行插桩的闭源代码。
鉴于我目前所做的测试,sfuzz 的开销远低于许多其他流行的模糊测试器,这带来了非常快的性能,尤其是对于小的模糊测试用例。
有关此模糊测试器的特性/选择的更多详细信息,请参阅随附的博客文章 (https://seal9055.com/blog/fuzzing/sfuzz) 以及下面列出的文档文件:
这个模糊测试器完全用 rust 编写,因此克隆仓库后,只需运行 cargo build --release 即可编译。
由于该模糊测试器目前仅支持 RISC-V,因此需要使用以下工具链(或类似工具链)将目标编译为 RISC-V。如果你已经有 RISC-V 二进制文件,那也完全可以。
设置完成后,只需创建输入/输出目录,向输入目录添加一些初始种子文件,然后启动模糊测试器即可。
./sfuzz -i in -o out -- ./test_cases/simple_test @@
可以通过命令行选项传入其他标志,以指定线程数、启用快照模糊测试、向变异器添加字典等。运行 sfuzz 并带上 -h 标志可以列出其他选项。
如果你希望针对不同复杂度的目标测试该模糊测试器,可以使用 tools/program_generator 中的 progrem_generator 自动生成不同复杂度的程序。请注意,你需要一个 RISC-V 工具链来编译目标。
这将设置一个工具链,用于编译可被此项目加载/使用的 riscv 二进制文件。
Riscv compiler/tooling:
sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev \
libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev \
libexpat-dev
git clone https://github.com/riscv/riscv-gnu-toolchain && cd riscv-gnu-toolchain
./configure --prefix=/opt/riscv --with-arch=rv64i
sudo make
Debugger:
gdb-multiarch
此列表代表我计划在未来实现的一组功能。