Home
Relevant source files
The following files were used as context for generating this wiki page: - [README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/README.md) - [CONTRIBUTING.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/CONTRIBUTING.md) - [src/afl-fuzz.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz.c) - [src/afl-fuzz-init.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-init.c) - [config.h](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/config.h) - [instrumentation/README.lto.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/instrumentation/README.lto.md) - [qemu_mode/README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/qemu_mode/README.md) - [unicorn_mode/README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/unicorn_mode/README.md) - [nyx_mode/README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/nyx_mode/README.md) - [frida_mode/Scripting.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/frida_mode/Scripting.md) - [custom_mutators/README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/custom_mutators/README.md) - [src/README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/README.md)AFL++ is a superior fork of the original American Fuzzy Lop (AFL) fuzzer, developed by Michal "lcamtuf" Zalewski. It incorporates numerous enhancements, including increased speed, more effective mutation strategies, improved instrumentation, and support for custom modules. AFL++ is designed to be a powerful and flexible tool for automated software testing and vulnerability discovery. It is maintained by a team of contributors and is distributed under the Apache-2.0 License.
This page provides a high-level overview of AFL++, including how to get started, its core architecture, various fuzzing modes, and key features. For more detailed information, please refer to the specific documentation files linked throughout this document.
Sources: README.md:3-20
Getting Started
Installation
The quickest way to get AFL++ running is by using the official Docker image, which is available for both x86_64 and arm64 architectures.
docker pull aflplusplus/aflplusplus
docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus
This image contains a pre-built version of AFL++ with all its components. For users who prefer to build from source, which is the recommended approach, please refer to the detailed instructions in docs/INSTALL.md.
Sources: README.md:40-46
Quick Start Fuzzing
This guide provides a basic workflow for fuzzing a target application with available source code.
- Compile the Target: Use the AFL++ compiler wrappers (
afl-cc/afl-c++) to build the target program. This injects the necessary instrumentation.CC=/path/to/afl-cc CXX=/path/to/afl-c++ ./configure --disable-shared make clean all - Prepare Initial Corpus: Gather a small set of valid input files (seeds) for the target program. For verbose syntaxes like SQL or HTTP, a dictionary is also highly recommended.
- Run
afl-fuzz: Start the fuzzer with the seed directory (-i), an output directory (-o), and the command to execute the target.- If the program reads from stdin:
./afl-fuzz -i seeds_dir -o output_dir -- /path/to/tested/program - If the program reads from a file, use
@@as a placeholder for the input file path:./afl-fuzz -i seeds_dir -o output_dir -- /path/to/program @@
- If the program reads from stdin:
- Analyze Results: Crashes and hangs are saved in the
crashes/andhangs/subdirectories within the output directory. These can be replayed for debugging.
The following diagram illustrates the basic fuzzing workflow.
Sources: README.md:57-89
Core Architecture
AFL++ operates by repeatedly mutating input files and feeding them to a target program to discover new execution paths and trigger crashes.
Fuzzing Loop
The core of afl-fuzz is a loop that performs the following steps:
- Select an Input: An input is chosen from the queue, typically favoring those that are small, fast, or have discovered unique paths.
- Mutate: The input is subjected to a series of mutation strategies, including deterministic and "havoc" stages.
- Execute Target: The mutated input is fed to the instrumented target program.
- Analyze Coverage: The fuzzer checks a shared memory region to see if the execution triggered any new code paths (edges) in the program's control flow graph.
- Save Interesting Inputs: If a new path is found, the input is saved to the queue for future mutation. If a crash or hang is detected, the input is saved for user analysis.
Sources: src/afl-fuzz.c:10082-10150
Instrumentation and the Fork Server
To achieve high performance, AFL++ relies on two key mechanisms:
- Instrumentation: Code is instrumented at compile-time (or dynamically in binary-only modes) to record which code paths are executed. This is done by updating a shared memory bitmap (
__AFL_SHM_ID). Each byte in the map corresponds to an edge in the control flow graph. - Fork Server: To avoid the overhead of repeatedly starting the target process, AFL++ uses a fork server. The target process is started once, stops just before executing the main code, and then
fork()s a new child for each fuzzing iteration. This significantly speeds up the process, especially for programs with slow initialization.
The diagram below shows the interaction between the fuzzer, the fork server, and the target process.
Fuzzing Modes
AFL++ supports various instrumentation modes to handle different types of targets.
| Mode | afl-fuzz Flag | Description | Use Case |
|---|---|---|---|
| LTO Mode | (none, use afl-clang-lto) | Link-Time Optimization instrumentation. Provides fast, collision-free coverage. | Recommended for source-available targets. |
| GCC Plugin | (none, use afl-gcc-fast) | Instrumentation via a GCC plugin. | Alternative to Clang/LLVM for source-available targets. |
| QEMU Mode | -Q | User-mode QEMU for dynamic binary instrumentation. 2-5x slower than source instrumentation. | Fuzzing closed-source binaries when source is unavailable. |
| Unicorn Mode | -U | Uses the Unicorn Engine to emulate and instrument code snippets. Requires a custom harness. | Fuzzing arbitrary binary code snippets or firmware. |
| Frida Mode | -O | Uses Frida for dynamic instrumentation, configurable with JavaScript. | Fuzzing complex applications, including mobile and GUI apps. |
| Nyx Mode | -X / -Y | Full-system emulation with KVM for snapshot-based fuzzing. | Fuzzing kernels or complex targets that are difficult to run in persistent mode. |
Sources: instrumentation/README.lto.md:10-16, qemu_mode/README.md:10-21, unicorn_mode/README.md:12-21, frida_mode/Scripting.md:3-9, nyx_mode/README.md:3-10, src/afl-fuzz.c:202-218
Key Features and Configuration
Custom Mutators
AFL++ allows users to extend its mutation capabilities by providing custom mutators. This is useful for structure-aware fuzzing where knowledge of the input format can lead to more effective mutations.
Custom mutators can be written in C/C++ and loaded as a shared library, or implemented in Python.
- Shared Library: Set
AFL_CUSTOM_MUTATOR_LIBRARYto the path of your.sofile. - Python Module: Set
AFL_PYTHON_MODULEto the name of your Python module.
You can also set AFL_CUSTOM_MUTATOR_ONLY=1 to disable AFL++'s built-in mutators and rely solely on your custom one.
Sources: custom_mutators/README.md:6-12, src/afl-fuzz.c:433-437, test/test-custom-mutators.sh:18-28
CmpLog and Redqueen
CmpLog is a feature inspired by Redqueen that helps solve "magic byte" comparisons in the target binary. When enabled, it logs comparison operands and uses this information to infer values that would satisfy cmp instructions, thereby unlocking new code paths.
CmpLog is enabled with the -c flag in afl-fuzz. For binary-only targets in QEMU mode, this is highly effective.
Sources: src/afl-fuzz.c:166-172, qemu_mode/README.md:82-89
Dictionaries
For targets that parse text-based formats (e.g., XML, SQL), providing a dictionary of keywords and tokens can significantly improve fuzzing efficiency. Dictionaries can be specified with the -x option.
AFL++ also features an autodictionary capability in LTO mode, which automatically extracts string constants from the target binary during compilation to create a dictionary.
Sources: src/afl-fuzz.c:184-191, instrumentation/README.lto.md:86-91
Compile-Time Configuration
Several key behaviors of AFL++ are controlled by macros in config.h. Modifying these requires recompiling the fuzzer.
| Macro | Default Value | Description |
|---|---|---|
MAP_SIZE_POW2 | 16 | The size of the coverage bitmap, as a power of 2 (2^16 = 65536 bytes). |
EXEC_TIMEOUT | 1000U | Default timeout for each execution in milliseconds. |
MAX_FILE | 1 * 1024 * 1024L | Maximum size of an input file in bytes (1MB). |
HAVOC_CYCLES | 256U | The baseline number of random tweaks in the "havoc" mutation stage. |
DEFAULT_SHMEM_SIZE | 8 * 1024 * 1024 | Default shared memory map size in bytes (8MB). |
Sources: config.h:312-318, config.h:202-205, config.h:294-298, config.h:232-233, config.h:39-44
Project Structure
The AFL++ repository is organized into several key directories.
*src/**: Contains the source code for the main AFL++ tools like afl-fuzz, afl-cc, and afl-analyze.
instrumentation/: Home to compiler wrappers (afl-clang-fast,afl-gcc-fast) and instrumentation passes like LTO mode.custom_mutators/: Provides examples and infrastructure for building custom mutators in C and Python.utils/: A collection of helper scripts and tools, such asafl_proxyfor network fuzzing andautodict_qlfor dictionary generation.testcases/: A set of small, optimized seed files for various common data formats.qemu_mode/,unicorn_mode/,frida_mode/,nyx_mode/: Contain the build scripts and support code for their respective binary-only and full-system fuzzing modes.
Sources: src/README.md, instrumentation/README.instrument_list.md:1-5, custom_mutators/README.md:3-5, utils/README.md, testcases/README.md:3-5, qemu_mode/README.md:10-15, unicorn_mode/README.md:12-17
Contributing
Contributions to AFL++ are welcome. Key guidelines include:
- All pull requests must be made against the
devbranch. - Source files must be formatted using
make code-formatbefore submission. - The coding style should follow the original AFL style (e.g., no camel case, use of AFL macros like
WARNFandFATAL).
Sources: CONTRIBUTING.md:5-17