A quick and dirty guide to "Fuzzing with AFL for fun and maybe a little profit"
Step 1: The Setup
Whether you're doing this for fun, as a new hobby or in the course of your job duties, getting started with AFL is easier than you think.
First, you're going to need a Linux machine. For simplicity's sake, we'll use a $5 VPS from DigitalOcean or Vultr. Both are fine choices for what we're about to embark on, but if you've already got a local Linux machine or a VM setup, you're ahead of the curve.
Note: You may see me running as root in some screenshots, don't fuzz as root.
For this guide we'll be using Debian, so first let's ensure the system is up to date:
apt-get update && apt-get upgrade
Next, we'll install a few necessities:
apt-get install build-essential git gdb autotools-dev automake libtool texinfo
And we'll need the latest version of AFL:
Extract that with a quick
tar zxf afl-latest.tgz and then
From there we'll run
make clean all to build the
afl-g++ wrappers and optionally
sudo make install if you want to install AFL.
Step 2: Pre-fuzzing software compilation
Now comes time to pick a target, and for this quick tutorial I'm going to choose something easy: GNU binutils. I say easy, but binutils can be a pain in the ass to compile, so hopefully by following my instructions I will save you some of that pain. (;
Grab binutils using git:
cd ~ && git clone git://sourceware.org/git/binutils-gdb.git binutils && cd binutils
Build binutils using the wrappers we built in step 1:
CC=afl-gcc CXX=afl-g++ AFL_USE_ASAN=1 LDFLAGS="-ldl" ./configure
LDFLAGS="-ldl" the compilation may fail with an error like
undefined reference to symbol 'dlsym@@GLIBC_2.0' which required some Google-fu to solve. Easy peasy thanks to Stack Overflow! (;
If there are no errors, type
AFL_USE_ASAN=1 LDFLAGS="-ldl" make and it will start compiling:
It might take a minute to compile so be patient. Once it is done, we can start fuzzing and hopefully find a bug.
Step 3: Fuzzing your target
Now that we have all of the important stuff out of the way, let's fire up AFL and see how many bugs we can find. binutils probably isn't the best choice because a lot of people fuzz it, but for this tutorial it will do just fine. Since you're already in
~/binutils, go ahead and
cd binutils and look for a target using
find . -maxdepth 1 -perm -111 -type f and you might get output that looks like this:
readelf is a good target because it reads ELF format files and displays information about them (and AFL comes with a sample ELF file for fuzzing). Here is what normal
readelf output looks like with a normal ELF format file:
Lots of information we really don't care about in the long run, but still nice to know what "normal" looks like. To start fuzzing this target, we're going to use the following commands:
cd ~/binutils/binutils && mkdir tmp && cd tmp
afl-fuzz -m none -i ~/afl-2.41b/testcases/others/elf -o output_dir ../readelf -a @@
-m none instructs AFL to not set a memory limit, which is essential when dealing with ASAN.
Once you've done that, you'll be presented with the following AFL status screen and you're now successfully fuzzing an open source application.
Stay tuned for follow-up articles where we look at triaging crashes, llvm mode and more!
Step 4: Profit!!!111
I hope you enjoyed this quick and dirty guide to fuzzing with AFL. As always, you can support me on Patreon, via PayPal, Bitcoin
1HnyFwSJDjWFexD7oRr4HGTFwD8N6NsrfX or Ethereum
A million thanks to @lcamtuf for providing such a great tool to the infosec community.