Installation
Relevant source files
The following files were used as context for generating this wiki page:
AFL++ is a sophisticated fuzzer with multiple components and instrumentation modes tailored for different targets. Proper installation and compilation are crucial for effective fuzzing. This guide covers the primary installation methods, from a quick setup using Docker to a comprehensive source build that enables specialized modes like LLVM, QEMU, and Unicorn.
While Docker provides a convenient way to get started, building from source is the recommended approach. It offers full control over which components are built, allowing you to enable powerful features like LTO (Link Time Optimization) mode for collision-free coverage, QEMU mode for binary-only targets, and Unicorn mode for emulating and fuzzing arbitrary code snippets.
Sources: README.md:37-43, instrumentation/README.lto.md:1-10
Installation Methods
There are two main ways to install AFL++: using a pre-built Docker image or compiling from source.
This diagram shows the two main installation paths: a quick setup via Docker or a more flexible build from source, which allows for the compilation of various optional instrumentation modes.
Sources: README.md:37-43
Quick Installation with Docker
For a fast and easy setup, you can use the official AFL++ Docker image from Docker Hub. This image contains a complete build with all standard components. It is available for both x86_64 and arm64 architectures.
To pull and run the latest stable image:
docker pull aflplusplus/aflplusplus
docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus
A development image with the most recent changes from the dev branch is also available:
docker pull aflplusplus/aflplusplus:dev
Sources: README.md:37-46
Building from Source (Recommended)
Building from source provides the most flexibility and is the recommended method. It allows you to compile specialized instrumentation modes required for different fuzzing scenarios.
Prerequisites
Before building, ensure you have the necessary dependencies for the components you intend to use.
| Component | Dependencies | Source File |
|---|---|---|
| QEMU Mode | libtool, glib2-devel | qemu_mode/README.md:20-22 |
| Unicorn Mode | cargo, rustc (>= 1.87.0), python3, setuptools, maturin | unicorn_mode/build_unicorn_support.py:28-44 |
| GCC Plugin Mode | gcc-VERSION-plugin-dev | instrumentation/README.gcc_plugin.md:30-32 |
| LTO Mode | LLVM >= 12, llvm-ar, llvm-ranlib, llvm-as | instrumentation/README.lto.md:5-7, 72-74 |
Core Build Process
The core AFL++ utilities can be built by running make in the root directory.
make
For a clean build, you can use:
make clean all
Sources: README.md:52-55
If you plan to contribute to the project, it's required to format the source code before submitting a pull request:
make code-format
Sources: CONTRIBUTING.md:5-8
The build process creates several compiler wrappers (e.g., afl-clang-fast, afl-clang-lto, afl-gcc-fast) which are used to instrument target applications. These wrappers automatically select the appropriate compiler and instrumentation mode based on their name, environment variables, or command-line arguments.
Sources: src/afl-cc.c:1010-1014
Building Instrumentation Modes
AFL++'s power comes from its various instrumentation modes. These must be built separately after the core components.
LLVM Mode (including LTO)
LLVM mode provides high-performance, compiler-level instrumentation. LTO (Link Time Optimization) mode is a special variant that offers collision-free coverage and a 10-25% speed gain. It requires LLVM 12 or newer.
- Set LLVM Path: Point the
LLVM_CONFIGenvironment variable to yourllvm-configbinary.export LLVM_CONFIG=llvm-config-19 - Build AFL++:
make sudo make install - Compile Target with LTO: When compiling your target, use
afl-clang-ltoand specify the LLVM toolchain for archiving and symbol table generation.
Some build systems may also require setting the linker explicitly (e.g.,CC=afl-clang-lto CXX=afl-clang-lto++ \ AR=llvm-ar RANLIB=llvm-ranlib AS=llvm-as \ ./configure makeLD=afl-clang-lto).
Sources: instrumentation/README.lto.md:5-7, 59-70, 72-78
QEMU Mode
QEMU mode is used for fuzzing binary-only targets without source code. It uses a patched version of QEMU for user-mode emulation and instrumentation.
To build QEMU mode, run the provided build script:
cd qemu_mode
./build_qemu_support.sh
The script handles downloading, patching, and compiling QEMU.
This diagram illustrates the build process for QEMU mode, including options for cross-architecture and static compilation.
Sources: qemu_mode/README.md:16-18, qemu_mode/README.md:25-34
You can customize the QEMU build with these environment variables:
| Variable | Description |
|---|---|
CPU_TARGET | Specifies the target architecture (e.g., i386, arm, aarch64). Necessary for cross-architecture fuzzing. |
HOST | The cross-compiler prefix to use (e.g., arm-linux-gnueabi). |
STATIC | If set to 1, compiles a statically-linked QEMU binary. |
Sources: qemu_mode/README.md:25-34
Unicorn Mode
Unicorn mode allows fuzzing of arbitrary binary code snippets by leveraging the Unicorn Engine.
To build Unicorn mode support, run the Python build script:
cd unicorn_mode
./build_unicorn_support.py
This script performs several steps:
- Checks for dependencies like
cargo,rustc, and Python build tools. - Checks out the
unicornaflsubmodule corresponding to the version specified inUNICORNAFL_VERSION. - Builds and installs the Python bindings using
maturin. - Builds the C/C++ static and dynamic libraries (
libunicornafl.a,libunicornafl.so/.dylib). - Copies the required headers and libraries into the
unicorn_mode/includeandunicorn_mode/libdirectories.
This diagram outlines the automated build process for Unicorn mode support.
Sources: unicorn_mode/build_unicorn_support.py:1-125, unicorn_mode/README.md:23-28
GCC Plugin Mode
This mode uses a GCC plugin for instrumentation. It is an alternative to LLVM but is generally considered less performant.
- Install Dependencies: Install the plugin development headers for your GCC version. On Debian-based systems, this is typically
gcc-VERSION-plugin-dev. - Build AFL++: Run
makein the root directory. This will createafl-gcc-fastandafl-g++-fast. - Compile Target: Use the
afl-gcc-fastwrappers to compile your target.CC=/path/to/afl-gcc-fast CXX=/path/to/afl-g++-fast ./configure make
Sources: instrumentation/README.gcc_plugin.md:28-48
Compile-Time Configuration
Several key behaviors of AFL++ and its instrumentation are controlled by macros defined in config.h. While most users will not need to change these, they offer fine-grained control for advanced use cases.
| Macro | Default Value | Description |
|---|---|---|
DEFAULT_SHMEM_SIZE | 8 * 1024 * 1024 | Default size of the shared memory map in bytes. Can be overridden with AFL_MAP_SIZE. |
EXEC_TIMEOUT | 1000U | Default execution timeout in milliseconds. This is an upper bound that is auto-scaled at runtime. |
MAP_SIZE_POW2 | 16 | Sets the coverage map size to 2^16 (65536 entries). Requires recompiling the target if changed. |
MAX_FILE | 1 * 1024 * 1024L | Maximum input file size in bytes that the fuzzer will process. |
HAVOC_CYCLES | 256U | Baseline number of random tweaks during the 'havoc' mutation stage. |
Sources: config.h:28-29, 131-133, 238-246, 183-184, 151-152
Summary
AFL++ offers a flexible installation process that can be tailored to the specific needs of a fuzzing campaign. For quick evaluation, the Docker image is sufficient. For serious fuzzing, a source build is essential to enable powerful instrumentation modes like LTO for speed and coverage quality, QEMU for binary-only targets, and Unicorn for specialized emulation-based fuzzing. Each mode has its own build process and dependencies, which are managed by dedicated scripts within the repository.
Sources: README.md:37-43, 48-50