Skip to content
Evan Nemerson edited this page Jan 6, 2016 · 1 revision

How To

There are lots of ways to fuzz test; this document just describes how I do it. m^2 has written a good guide for how to fuzz compression codecs. It's a bit more detailed than this, and he does things a little different.

Prerequisites

You'll need a C and/or C++ compiler (depending on the library); GCC or clang will do. You may also need to install an additional package for the AddressSanitizer shared library. Packages vary by distribution, but on Fedora:

dnf install gcc g++ american-fuzzy-lop libasan

Compilation

If the implementation uses autotools or CMake, you can generally just use environment variables and/or configure script flags to get the necessary configuration. If the implementation uses Makefiles, though, you'll generally need to modify them.

  • Set the C compiler to afl-gcc, and the C++ compiler to afl-g++
  • Add -fsanitize=address to the C/C++ compiler flags
  • When compiling, make sure the AFL_HARDEN environment variable is set to 1 (e.g., AFL_HARDEN=1 make

Preparing the Input

CompFuzz comes with a few (not nearly enough, help wanted) small files suitable for seeding the fuzzer. I typically compress each file at every level a compressor offers. For example, if a compressor (called "foo") supports levels 1-9, something like this:

mkdir testcases
for i in path/to/compfuzz/input/*; do
  for level in 1 2 3 4 5 6 7 8 9; do
    foo --level $level -o testcases/"$i".$level.foo -i "$i"
  done
done

Next, you'll want to remove test cases which don't add anything. We'll get in to details about what the AFL arguments need to look like soon, but the basic idea is

mkdir minimized
afl-cmin -i testcases -o minimized -- …

That may or may not prune some files out of the dataset (which will speed up the fuzzer).

Invoking AFL

[Mostly TODO]

The basic idea is

afl-fuzz -i minimized -o results -- foo --decompress -i /dev/stdin -o /dev/null

If you're using AddressSanitizer you'll probably get an error message, though. See notes_for_asan.txt (it's probably installed at /usr/share/doc/american-fuzzy-lop/notes_for_asan.txt) for more information. To get around the issue, AFL includes a script:

sudo /usr/share/doc/american-fuzzy-lop/experimental/asan_cgroups/limit_memory.sh \
   -u $USER afl-fuzz -i minimized -o results -m none foo --decompress -i /dev/stdin -o /dev/null

Parallel Fuzzing

Fuzzing is slow. AFL includes support for running multiple fuzzers in parallel. I usually fire up screen, and in the first window I put the master:

sudo /usr/share/doc/american-fuzzy-lop/experimental/asan_cgroups/limit_memory.sh \
   -u $USER afl-fuzz -i minimized -o results -m none -M fuzzer0 foo --decompress -i /dev/stdin -o /dev/null

Then, for additional cores I launch slaves with:

sudo /usr/share/doc/american-fuzzy-lop/experimental/asan_cgroups/limit_memory.sh \
   -u $USER afl-fuzz -i minimized -o results -m none -S fuzzer1 foo --decompress -i /dev/stdin -o /dev/null

(Increment fuzzer1 for each slave).

Finally, you can create an additional window to keep track of everything with something like

while true; do
  clear;
  afl-whatsup results;
  sleep 5;
done
Clone this wiki locally