Skip to main content
All articles
Tutorial
February 14, 202610 min read

AFL++ Tutorial: Getting Started with Coverage-Guided Fuzzing

A hands-on AFL++ guide: instrument your target, build a starter corpus, tune for executions-per-second, and triage the first crashes that land.

AFL++ (American Fuzzy Lop plus plus) is the most widely deployed coverage-guided fuzzer in the security research community. It's a community-maintained fork of Michal Zalewski's original AFL with significant improvements to mutation strategies, instrumentation, scheduling, and performance.

Installing AFL++

sudo apt-get install -y build-essential python3-dev cmake git \
    flex bison libglib2.0-dev libpixman-1-dev

git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make distrib
sudo make install

Instrumenting Your Target

AFL++ needs coverage feedback from the target binary. Recompile with AFL++'s compiler wrapper, which instruments every branch at compile time:

# With AddressSanitizer (recommended)
AFL_USE_ASAN=1 CC=afl-cc ./configure --disable-shared
make -j$(nproc)

# Or compile a single file directly
afl-cc -o my_parser my_parser.c

The default backend is PCGUARD (based on LLVM SanitizerCoverage). For targets you cannot recompile, QEMU mode (afl-fuzz -Q) instruments binaries dynamically at runtime.

Building a Seed Corpus

Coverage-guided fuzzing needs a starting corpus — a set of valid, small inputs that exercise diverse code paths. Use afl-cmin to remove redundant inputs:

# Remove redundant inputs that cover the same code paths
afl-cmin -i seeds/ -o seeds_min/ -- ./my_parser @@

# Minimize individual seeds for faster fuzzing
afl-tmin -i seeds_min/sample.bin -o seeds_opt/sample.bin -- ./my_parser @@

Running AFL++

# Single-core run
afl-fuzz -i seeds/ -o findings/ -- ./my_parser @@

# Multi-core: one main + N-1 secondary instances
afl-fuzz -i seeds/ -o findings/ -M main    -- ./my_parser @@
afl-fuzz -i seeds/ -o findings/ -S worker1 -- ./my_parser @@
afl-fuzz -i seeds/ -o findings/ -S worker2 -- ./my_parser @@

The @@ placeholder is replaced with each generated input path. Crashes are written to findings/default/crashes/ and the corpus to findings/default/queue/.

Reading the Status Screen

Key metrics to watch on the AFL++ TUI:

  • exec speed: executions per second. Under 100/s means you need persistent mode or the target is too slow.
  • total paths: unique code paths discovered. Should grow steadily; stagnation means you need a better corpus or dictionary.
  • crashes: total crashes found. Each file in the crashes directory is a unique reproducer.
  • map density: how full the coverage bitmap is. Over 70% may require a larger map size.

Persistent Mode: 10–100x Faster

Persistent mode is the single biggest performance improvement. Instead of forking a new process for each input, AFL++ reuses the same process across many inputs:

#include "afl-fuzz.h"

int main(int argc, char **argv) {
    // One-time initialization here
    __AFL_INIT();

    while (__AFL_LOOP(1000)) {
        ssize_t len = read(0, buf, sizeof(buf));
        parse_input(buf, len);
    }
    return 0;
}

Triaging Crashes

# Reproduce with AddressSanitizer output
ASAN_OPTIONS=abort_on_error=1 ./my_parser findings/crashes/id:000001,*

# Or use GDB for targets built without ASan
gdb -ex run -ex bt --args ./my_parser findings/crashes/id:000001,*

AddressSanitizer prints a detailed report: error type, allocation site, and full stack trace. AFL++ crash filenames include a signal indicator and an edge hash for first-pass deduplication.

Scaling with Managed Fuzzing

Running AFL++ on a single machine finds bugs, but real campaigns run on dozens or hundreds of cores for days or weeks. The infrastructure overhead — provisioning instances, syncing corpora, collecting and deduplicating crashes — is substantial. Managed fuzzing platforms handle all of that with crash reports delivered to a dashboard in real time.

Ready to start fuzzing?

Skip the infrastructure setup. Fuzze.rs runs AFL++, libFuzzer, Centipede, and Honggfuzz at scale — just upload your binary and get crash reports in real time. First month 50% off.