How to compile and run AFL Fuzzer on M1 Mac with Apple Silicon (for x86 instrumentation support)
American Fuzzy Lop (AFL) is without doubt one of the most famous fuzzers. The project started by Michał Zalewski of Google has revolutionised the field of fuzzers. In this short write-up I want to introduce you to how I compiled the AFL++ fuzzer on my MacBook Pro with M1 chip (Apple Silicon) and got it fuzzing! :)
Two things before we go on:
- I am compiling AFL++ rather than the original AFL repository from Google, which is lagging behind in latest features. AFL++ on the other hand is frequently updated and is much faster..
- As I write this article, the latest version of AFL++ is 3.01a
AFL++ when compiled for the Apple’s ARM processor, only supports non-instrumented fuzzing; which means it is as good as using any dumb fuzzer. Also, the Qemu mode is currently not supported for the MacOS.
Hence to get better out of the AFL++ fuzzer, we need to compile it for the x86_64 architecture, which need a bit of work.
Here’s the steps I followed to get the AFL++ running on my M1 Mac:
Step1: Install Xcode Command Line tools
$ xcode-select --install
Step 2: Install brew and llvm
The llvm provided with the MacOS xcode-tools is not sufficient. Hence download the latest one from brew.
$ sudo mkdir /opt/homebrew
$ sudo chown -R $(whoami) /opt/homebrew
$ cd /opt
$ curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
$ /opt/homebrew/bin/brew update
$ /opt/homebrew/bin/brew install llvm
Step 3: Clone the AFL++ git repo
$ git clone https://github.com/AFLplusplus/AFLplusplus
$ cd AFLplusplus/
Step 4: Switch the Terminal to x86_64
As AFL++ cannot be compiled for the ARM architecture, it is needed to switch the Terminal to support x86_64 support. This can be done easily on the MacOS with the Rosetta 2! Just run the following command:
$ env /usr/bin/arch -x86_64 /bin/zsh —-login
P.S: to easily switch between x86_64 and ARM in Terminal, you can read my other article: How to switch the Terminal between x86_64 and arm64
To make sure your Terminal is running with Rosetta 2 for x86_64 architecture, type:
$ arch
and you should see the following:
Step 5: Export the llvm path
$ export PATH=”/opt/homebrew/opt/llvm/bin:$PATH”
Step 6: Compile with make!!
Make sure you are in the right directory and have followed all the above steps.. Then just:
$ make
If everything goes well, then you will see the following:
That’s it! You have successfully compiled AFL++ and can now run it..
Let’s test it out by running a simple deadbeef program — or what I call the hello world of fuzzers!
Running the Fuzzer!
If you have previously run the AFL fuzzer on the intel Macs, I’m sure you would have used the afl-clang to instrument and compile your code. However, the latest release of AFL++ doesn’t work anymore on the ARM Macs.
AFL++ with the 3.00c release introduced ‘afl-cc’ which has combined all the compilers (gcc, clang.. ). Hence you need to use this to instrument your code.
That being said, to test the instrumentation and fuzzing, I use the simple deadbeef C-program. If you have been into fuzzers, I’m certain you would have come across this program by now.
I saved the following code as test.c
#include <stdio.h>
#include <stdlib.h>int main(int argc, char **argv) {char ptr[20];
if(argc>1){
FILE *fp = fopen(argv[1], “r”);
fgets(ptr, sizeof(ptr), fp);} else { fgets(ptr, sizeof(ptr), stdin);
} printf(“%s”, ptr);
if(ptr[0] == ‘d’) {
if(ptr[1] == ‘e’) {
if(ptr[2] == ‘a’) {
if(ptr[3] == ‘d’) {
if(ptr[4] == ‘b’) {
if(ptr[5] == ‘e’) {
if(ptr[6] == ‘e’) {
if(ptr[7] == ‘f’) {
abort();
}
else printf(“%c”,ptr[7]);
} else printf(“%c”,ptr[6]);
} else printf(“%c”,ptr[5]);
} else printf(“%c”,ptr[4]);
} else printf(“%c”,ptr[3]);
} else printf(“%c”,ptr[2]);
} else printf(“%c”,ptr[1]);
} else printf(“%c”,ptr[0]); return 0;
}
Step 1: Instrument the code
$ ./afl-cc test.c -o test.o
Step 2: Let’s fuzz!
Create a directory with a testcase/input for the program, and an output directory to save to fuzzing results.
$ mkdir input
$ echo "hello" > input/testcase.txt
$ mkdir output
Start the fuzzer!
$ ./afl-fuzz -i input -o output ./test.o @@
That’s it! Enjoy fuzzing with AFL++ with guided fuzzing!
Cheers!