The Fuzzing Project – Beginner’s Guide to Fuzzing Part 3: Instrumented fuzzing with american fuzzy lop

Tutorial – Beginner’s Guide to Fuzzing

Part 3: Instrumented fuzzing with american fuzzy lop

Part 1: zzuf   
Part 2: Address Sanitizer   
Part 3: american fuzzy lop

Fuzzing with simple fuzzers like zzuf will expose easy to find bugs, but
there are much more advanced fuzzing strategies. One is to write fuzzers
that are aware of the file format used. You may for example try to set
all fields in a file header to maximum or minimum values. However format
aware fuzzing is cumbersome, because you’ll need a fuzzer for every input
format you are fuzzing.

Compile-time instrumented fuzzing goes another route: It adds instructions
to an application’s code that allow the fuzzer to detect code paths in the
application. It can then use promising fuzzing samples that expose large
parts of the code for further fuzzing.

american fuzzy lop (afl) does
instrumented fuzzing and is probably the best
fuzzing tool available at the moment. When installed it will provide you
wrappers for gcc that add the instrumentation code. The use of afl
can lead to quite surprising results.

Let’s assume again you have a tool that uses an autoconf-based configure
script. Compile your code with afl:

./configure CC="afl-gcc" CXX="afl-g++" --disable-shared; make

Again we use –disable-shared to statically compile if possible and
avoid LD_PRELOAD calls.

Now we need one or several input samples. Preferrably they should be
small. We place them in a directory we will call in. Now we start
afl-fuzz:

afl-fuzz -i in -o out [path_to_tool] @@

The @@ is replaced by the fuzzed input files. If you skip that it
will pass the fuzzed file on the standard input.
When we do this afl-fuzz will usually complain that you should change
your CPUFREQ settings to performance because the automatic frequency
scaling by the Linux kernel doesn’t work well with afl. You can do this
by running this command as root:

echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

Alternatively you can also just tell afl to ignore the CPUFREQ settings:

AFL_SKIP_CPUFREQ=1 afl-fuzz -i in -o out [path_to_tool] @@

You may also get a warning that your terminal is too small, in this case just make
your terminal window a bit larger. When we’re done we will see an interface like this:

afl-fuzz

When everything is done correct you should see new paths every now and then. If
total paths stays at 1 you probably have set up something wrong. The most interesting
value is the uniq crashes. There you will see if you found any segfaults, most of them
will likely be memory access errors.

The samples that create crashes will be collected in out/crashes. You will also
find potential hangs in out/hangs, however you should check if they really hang your
tool. The default timeout of afl is quite low so you’ll see a lot of false positives
here.

american fuzzy lop does a lot of file writes (hundreds or thousands per second).
this
blog post suggests using a ram disk to avoid too much stress for your SSD. This
is probably a good idea.

american fuzzy lop and Address Sanitizer

We learned in part 2 that Address Sanitizer can greatly improve your bug finding
capabilities and in this chapter that american fuzzy lop is one of the most advanced
fuzzers available. Obviously what we’d like to do is get the power of both.

Unfortunately this comes with a number of difficulties. Address Sanitizer needs
a lot of virtual memory and by default afl will limit the amount of memory a fuzzed
software gets. The easiest way around this is to just disable the memory limit (-m none).
However be warned: Your fuzzed software may actually try to really allocate and use a lot
of memory due to your fuzzed samples. This may lead to random crashes in your system.
You shouldn’t do any important work while doing so.

To enable the use of Address Sanitizer you need to set the environment variable
AFL_USE_ASAN to 1 during compilation:

AFL_USE_ASAN=1 ./configure CC=afl-gcc CXX=afl-g++ LD=afl-gcc--disable-shared
AFL_USE_ASAN=1 make

Fuzzing itself is the same as above. Please note that using Address Sanitizer
will give you fuzzing samples that often won’t crash the vanilla application. To
help upstream developers it’s wise to include the address sanitizer crash dump
to help them in their analysis.

Please note that using afl with Address Sanitizer will significantly slow down
your fuzzing efforts. But it will likely still find more bugs.

That’s it. Please also consult the official
american fuzzy lop documentation.
Now start the fuzzing!

Part 1: zzuf   
Part 2: Address Sanitizer   
Part 3: american fuzzy lop