This is a simple walkthrough to install, setup and run AFL against an open source dumb C program.
What is AFL
American fuzzy lop is a security-oriented fuzzer that employs a novel type of compile-time instrumentation and genetic algorithms to automatically discover clean, interesting test cases that trigger new internal states in the targeted binary. This substantially improves the functional coverage for the fuzzed code. – AFL website
ghozt@maze:~/research/fuzz/afl-2.52b$ make [*] Checking for the ability to compile x86 code... [+] Everything seems to be working, ready to compile. cc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" afl-gcc.c -o afl-gcc -ldl ... [+] All right, the instrumentation seems to be working! [+] LLVM users: see llvm_mode/README.llvm for a faster alternative to afl-gcc. [+] All done! Be sure to review README - it's pretty short and useful. NOTE: If you can read this, your terminal probably uses white background. This will make the UI hard to read. See docs/status_screen.txt for advice. ghozt@maze:~/research/fuzz/afl-2.52b$ sudo make install ... ghozt@maze:~/research/fuzz/afl-2.52b$ afl-gcc --version afl-cc 2.52b by <lcamtuf@google.com> gcc (Ubuntu 12.3.0-1ubuntu1~23.04) 12.3.0 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
In order to fuzz the binary, it must be compiled thanks to our fresh installed afl-gcc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
ghozt@maze:~/research/fuzz/example$ afl-gcc -fno-stack-protector -z execstack vuln.c -o vuln afl-cc 2.52b by <lcamtuf@google.com> vuln.c: In function ‘main’: vuln.c:10:9: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration] 10 | gets(service); | ^~~~ | fgets vuln.c:14:12: warning: implicit declaration of function ‘strcmp’ [-Wimplicit-function-declaration] 14 | if(strcmp(service, "fuzzing") == 0) | ^~~~~~ vuln.c:3:1: note: include ‘<string.h>’ or provide a declaration of ‘strcmp’ 2 | #include <stdlib.h> +++ |+#include <string.h> 3 | afl-as 2.52b by <lcamtuf@google.com> [+] Instrumented 6 locations (64-bit, non-hardened mode, ratio 100%). /usr/bin/ld: /tmp/ccAAiBud.o : dans la fonction « main » : /home/ghozt/research/fuzz/example/vuln.c:10: avertissement : the `gets' function is dangerous and should not be used.
AFL works with tests cases. That mean you have to tell AFL what a legit input looks like. First, we will create two directories, one for the tests cases, and another one to store the fuzzing results:
Now, remember the code, in a code coverage point of view, we have three different paths:
1 2 3 4 5 6 7 8 9 10 11
// First path --> service is invalid if(strcmp(service, "fuzzing") == 0) { // Second path --> service is valid, but passphrase is not if(strcmp(passphrase, "p@s5w0rD") == 0) { // Third path --> All is fine :) printf("Authorized -- Fuzzing in progress\n"); return0; } }
ghozt@maze:~/research/fuzz/example$ afl-fuzz -i testcases -o results vuln afl-fuzz 2.52b by <lcamtuf@google.com> [+] You have 16 CPU cores and 2 runnable tasks (utilization: 12%). [+] Try parallel jobs - see /usr/local/share/doc/afl/parallel_fuzzing.txt. [*] Checking CPU core loadout... [+] Found a free CPU core, binding to #0. [*] Checking core_pattern...
[-] Hmm, your system is configured to send core dump notifications to an external utility. This will cause issues: there will be an extended delay between stumbling upon a crash and having this information relayed to the fuzzer via the standard waitpid() API.
To avoid having crashes misinterpreted as timeouts, please login as root and temporarily modify /proc/sys/kernel/core_pattern, like so:
echo core >/proc/sys/kernel/core_pattern
[-] PROGRAM ABORT : Pipe at the beginning of 'core_pattern' Location : check_crash_handling(), afl-fuzz.c:7275
Some errors need to be fixed. Just follow the output steps:
1 2 3 4
echo core >/proc/sys/kernel/core_pattern cd /sys/devices/system/cpu echo performance | tee cpu*/cpufreq/scaling_governor
It all is ok, the following screen will be displayed:
If you want to fully understand this screen, you should read this documentation
Here we can see that AFL found a uniq crashe. That means one of our three paths can be crashed.
The results are stored in the result/crashes directory and contains input that can crash our binary. Let’s verify it: