American Fuzzy Lop is a set of utilities that aid in fuzzing applications for bugs, some of which can be exploitable. This blog post will be the first of two or three that cover using AFL to automatically find bugs in software. Using a real world example, we will set up AFL, compile and instrument the software to fuzz, then go over any results we find.
We will be fuzzing a version of tcpdump which is contains a few heap overrun bugs in the parsing code of pcap files. But before we begin, we should set up our system with AFL. I prefer to have AFL work within a chroot to keep my base system clean, so the first thing we will do is set up a small Ubuntu chroot that we can install AFL and the vulnerable software in.
First, let’s create a directory to contain all of the things we will need to start fuzzing. I simply call my directory
mkdir afl cd afl
Then, within the
afl directory, I keep a small bash script that creates a chroot of the
trusty version of Ubuntu.
debootstrap --variant=buildd trusty chroot http://mirror.pnl.gov/ubuntu/ mount -o bind /proc chroot/proc mount -o bind /dev chroot/dev mount -o bind /dev/pts chroot/dev/pts mount -o bind /dev/ptmx chroot/dev/ptmx cp /etc/resolv.conf chroot/etc/resolv.conf cp /etc/apt/sources.list chroot/etc/apt/sources.list chroot chroot/ apt-get update chroot chroot/ apt-get upgrade -y chroot chroot/ apt-get install vim screen -y chroot chroot/ apt-get install build-essential -y rm afl-latest.tgz wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz cp afl-latest.tgz chroot/root
This bash script, which I called
build_chroot, first creates the chroot with
debootstrap. It then mounts my
/dev/ptmx into the chroot so that I can have internet and use screen within the chroot. After mounting the directories and devices into the chroot, I copy over the
resolv.conf and the
sources.list from my system into the chroot. After these have been set up, within the chroot environment, I update and upgrade the system with apt, then install some basic packages,
build-essential. Once all is said and done, I download the latest version of
afl then copy it into the
/root directory of the chroot for installation later.
Next, I need to enter the chroot environment, install afl, and set up the environment a bit more so we can build and instrument the software we will be fuzzing,
sudo chroot chroot cd /root tar xzf afl-latest.tgz cd afl-1.83b/ make && make install apt-get build-dep tcpdump apt-get install wget cd .. wget http://www.tcpdump.org/release/tcpdump-4.6.2.tar.gz tar xzf tcpdump-4.6.2.tar.gz
I now have afl installed within the chroot, as well as the source code for
tcpdump downloaded and decompressed in
/root. Now I need to build and instrument
tcpdump using the
afl-gcc binary. Basically,
afl-gcc will insert assembly instructions into the resulting
tcpdump binary that will provide feedback to another afl binary,
afl-fuzz. I will use
afl-fuzz later on. To build
tcpdump with afl instead of the default
gcc compiler, I will set the
CC environment variable to the
afl-gcc binary I installed previously.
cd tcpdump-4.6.2 CC=afl-gcc ./configure make
While building, you will see a few extra messages printed to the screen from
afl-gcc that look like the following:
afl-cc 1.83b by <firstname.lastname@example.org> afl-as 1.83b by <email@example.com> [+] Instrumented 497 locations (64-bit, non-hardened mode, ratio 100%).
If you see these messages during compilation, this means you are compiling and instrumenting the
tcpdump binary with the
gcc wrapper installed by afl,
afl-gcc. Once completed, you should have an instrumented
tcpdump binary at the root of the tcpdump-4.6.2 folder. Now I can begin fuzzing
tcpdump. The archive of afl source code contains some example files you can use when fuzzing applications, and one of these files is a very small pcap file. This is what I will use as my single testcase to mutate and feed to
cd /root mkdir testcases findings cp afl-1.83b/testcases/others/pcap/small_capture.pcap testcases/
Now we can begin fuzzing
afl-fuzz -i testcases/ -o findings/ tcpdump-4.6.2/tcpdump -nr @@
afl-fuzz binary requires you to tell it where the testcases to feed and mutate will exist with the
-i argument. The
-o argument is where
afl-fuzz will save its current state and any files that result in hangs or crashes in the application. Running this command, you may get an error about the system being configured to send core dump notifications to an external utility. To disable this and let the fuzzing continue, run the following command and try again:
echo core >/proc/sys/kernel/core_pattern
If all went well, you should see a 1337 UI detailing afl’s current fuzzing status like the following:
The next post will cover starting and tracking a master fuzz process and multiple slave processes, then tracking down and verifying crashes.