Uses multi-core fuzzing and mutation strategies to identify vulnerabilities in C/C++ codebases.

Install

mkdir -p .claude/skills/aflpp && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4628" && unzip -o skill.zip -d .claude/skills/aflpp && rm skill.zip

Installs to .claude/skills/aflpp

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

AFL++ is a fork of AFL with better fuzzing performance and advanced features. Use for multi-core fuzzing of C/C++ projects.
123 chars · catalog description✓ has a “when” trigger
Advanced

Key capabilities

  • Executes parallel fuzzing across multiple CPU cores
  • Provides advanced mutation strategies
  • Integrates with clang-based sanitizers
  • Supports custom harness compilation
  • Generates crash reports from binary inputs

How it works

It wraps the target code in a custom harness, compiles it with instrumentation, and runs parallel fuzzing instances using a provided seed corpus.

Inputs & outputs

You give it
Target source code, harness function, and seed corpus directory
You get back
Crash logs and input artifacts

When to use aflpp

  • Perform multi-core fuzzing
  • Audit C/C++ projects for crashes
  • Maximize security coverage in production code

About this skill

AFL++

AFL++ is a fork of the original AFL fuzzer that offers better fuzzing performance and more advanced features while maintaining stability. A major benefit over libFuzzer is that AFL++ has stable support for running fuzzing campaigns on multiple cores, making it ideal for large-scale fuzzing efforts.

When to Use

FuzzerBest ForComplexity
AFL++Multi-core fuzzing, diverse mutations, mature projectsMedium
libFuzzerQuick setup, single-threaded, simple harnessesLow
LibAFLCustom fuzzers, research, advanced use casesHigh

Choose AFL++ when:

  • You need multi-core fuzzing to maximize throughput
  • Your project can be compiled with Clang or GCC
  • You want diverse mutation strategies and mature tooling
  • libFuzzer has plateaued and you need more coverage
  • You're fuzzing production codebases that benefit from parallel execution

Quick Start

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    // Call your code with fuzzer-provided data
    check_buf((char*)data, size);
    return 0;
}

Compile and run:

# Setup AFL++ wrapper script first (see Installation)
./afl++ docker afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
mkdir seeds && echo "aaaa" > seeds/minimal_seed
./afl++ docker afl-fuzz -i seeds -o out -- ./fuzz

Installation

AFL++ has many dependencies including LLVM, Python, and Rust. We recommend using a current Debian or Ubuntu distribution for fuzzing with AFL++.

MethodWhen to UseSupported Compilers
Ubuntu/Debian reposRecent Ubuntu, basic features onlyUbuntu 23.10: Clang 14 & GCC 13<br>Debian 12: Clang 14 & GCC 12
Docker (from Docker Hub)Specific AFL++ version, Apple Silicon supportAs of 4.35c: Clang 19 & GCC 11
Docker (from source)Test unreleased features, apply patchesConfigurable in Dockerfile
From sourceAvoid Docker, need specific patchesAdjustable via LLVM_CONFIG env var

Ubuntu/Debian

Prior to installing afl++, check the clang version dependency of the packge with apt-cache show afl++, and install the matching lld version (e.g., lld-17).

apt install afl++ lld-17

Docker (from Docker Hub)

docker pull aflplusplus/aflplusplus:stable

Docker (from source)

git clone --depth 1 --branch stable https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
docker build -t aflplusplus .

From source

Refer to the Dockerfile for Ubuntu version requirements and dependencies. Set LLVM_CONFIG to specify Clang version (e.g., llvm-config-18).

Wrapper Script Setup

Create a wrapper script to run AFL++ on host or Docker:

cat <<'EOF' > ./afl++
#!/bin/sh
AFL_VERSION="${AFL_VERSION:-"stable"}"
case "$1" in
   host)
        shift
        bash -c "$*"
        ;;
    docker)
        shift
        /usr/bin/env docker run -ti \
            --privileged \
            -v ./:/src \
            --rm \
            --name afl_fuzzing \
            "aflplusplus/aflplusplus:$AFL_VERSION" \
            bash -c "cd /src && bash -c \"$*\""
        ;;
    *)
        echo "Usage: $0 {host|docker}"
        exit 1
        ;;
esac
EOF
chmod +x ./afl++

Security Warning: The afl-system-config and afl-persistent-config scripts require root privileges and disable OS security features. Do not fuzz on production systems or your development environment. Use a dedicated VM instead.

System Configuration

Run after each reboot for up to 15% more executions per second:

./afl++ <host/docker> afl-system-config

For maximum performance, disable kernel security mitigations (requires grub bootloader, not supported in Docker):

./afl++ host afl-persistent-config
update-grub
reboot
./afl++ <host/docker> afl-system-config

Verify with cat /proc/cmdline - output should include mitigations=off.

Writing a Harness

Harness Structure

AFL++ supports libFuzzer-style harnesses:

#include <stdint.h>
#include <stddef.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    // 1. Validate input size if needed
    if (size < MIN_SIZE || size > MAX_SIZE) return 0;

    // 2. Call target function with fuzz data
    target_function(data, size);

    // 3. Return 0 (non-zero reserved for future use)
    return 0;
}

Harness Rules

DoDon't
Reset global state between runsRely on state from previous runs
Handle edge cases gracefullyExit on invalid input
Keep harness deterministicUse random number generators
Free allocated memoryCreate memory leaks
Validate input sizesProcess unbounded input

See Also: For detailed harness writing techniques, patterns for handling complex inputs, and advanced strategies, see the fuzz-harness-writing technique skill.

Compilation

AFL++ offers multiple compilation modes with different trade-offs.

Compilation Mode Decision Tree

Choose your compilation mode:

  • LTO mode (afl-clang-lto): Best performance and instrumentation. Try this first.
  • LLVM mode (afl-clang-fast): Fall back if LTO fails to compile.
  • GCC plugin (afl-gcc-fast): For projects requiring GCC.

Basic Compilation (LLVM mode)

./afl++ <host/docker> afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz

GCC Compilation

./afl++ <host/docker> afl-g++-fast -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz

Important: GCC version must match the version used to compile the AFL++ GCC plugin.

With Sanitizers

./afl++ <host/docker> AFL_USE_ASAN=1 afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz

See Also: For detailed sanitizer configuration, common issues, and advanced flags, see the address-sanitizer and undefined-behavior-sanitizer technique skills.

Build Flags

Note that -g is not necessary, it is added by default by the AFL++ compilers.

FlagPurpose
-DNO_MAIN=1Skip main function when using libFuzzer harness
-O2Production optimization level (recommended for fuzzing)
-fsanitize=fuzzerEnable libFuzzer compatibility mode and adds the fuzzer runtime when linking executable
-fsanitize=fuzzer-no-linkInstrument without linking fuzzer runtime (for static libraries and object files)

Corpus Management

Creating Initial Corpus

AFL++ requires at least one non-empty seed file:

mkdir seeds
echo "aaaa" > seeds/minimal_seed

For real projects, gather representative inputs:

  • Download example files for the format you're fuzzing
  • Extract test cases from the project's test suite
  • Use minimal valid inputs for your file format

Corpus Minimization

After a campaign, minimize the corpus to keep only unique coverage:

./afl++ <host/docker> afl-cmin -i out/default/queue -o minimized_corpus -- ./fuzz

See Also: For corpus creation strategies, dictionaries, and seed selection, see the fuzzing-corpus technique skill.

Running Campaigns

Basic Run

./afl++ <host/docker> afl-fuzz -i seeds -o out -- ./fuzz

Setting Environment Variables

./afl++ <host/docker> AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzz

Interpreting Output

The AFL++ UI shows real-time fuzzing statistics:

OutputMeaning
execs/secExecution speed - higher is better
cycles doneNumber of queue passes completed
corpus countNumber of unique test cases in queue
saved crashesNumber of unique crashes found
stability% of stable edges (should be near 100%)

Output Directory Structure

out/default/
├── cmdline          # How was the SUT invoked?
├── crashes/         # Inputs that crash the SUT
│   └── id:000000,sig:06,src:000002,time:286,execs:13105,op:havoc,rep:4
├── hangs/           # Inputs that hang the SUT
├── queue/           # Test cases reproducing final fuzzer state
│   ├── id:000000,time:0,execs:0,orig:minimal_seed
│   └── id:000001,src:000000,time:0,execs:8,op:havoc,rep:6,+cov
├── fuzzer_stats     # Campaign statistics
└── plot_data        # Data for plotting

Analyzing Results

View live campaign statistics:

./afl++ <host/docker> afl-whatsup out

Create coverage plots:

apt install gnuplot
./afl++ <host/docker> afl-plot out/default out_graph/

Re-executing Test Cases

./afl++ <host/docker> ./fuzz out/default/crashes/<test_case>

Fuzzer Options

OptionPurpose
-G 4000Maximum test input length (default: 1048576 bytes)
-t 1000Timeout in milliseconds for each test case (default: 1000ms)
-m 1000Memory limit in megabytes (default: 0 = unlimited)
-x ./dict.dictUse dictionary file to guide mutations

Environment Variables That Matter

AFL++ has many environment variables, but most are niche. These are the ones that matter in practice.

Always Set These

# Every campaign should use tmpfs — SSDs will thank you, and it's faster
AFL_TMPDIR=/dev/shm

AFL_TMPDIR is a free performance win with no downsides — not setting it wears out your SSD and slows fuzzing.

Slow Targets

# Speeds up calibration ~2.5x — use when targets are slow (e.g., >10 ms/exec)
AFL_FAST_CAL=1

AFL_FAST_CAL reduces calibration time with negligible precision loss. Recommended specifically for slow targets where calibration would otherwise take a long time.

Multi-Core Campaigns

# On the primary (-M) instance only — needed for afl-cmin, not for fuzzing itself
AFL_FINAL_SYNC=1

# On all instances — cache test 

---

*Content truncated.*

When not to use it

  • Small, simple single-threaded applications
  • Projects without C/C++ source code access

Prerequisites

dockerClang or GCCLLVM

Limitations

  • High system resource consumption
  • Requires complex harness setup

How it compares

It enables multi-core hardware utilization for fuzzing, providing significantly higher throughput than standard single-threaded libFuzzer implementations.

Compared to similar skills

aflpp side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
aflpp (this skill)12moReviewAdvanced
address-sanitizer12moReviewIntermediate
libafl12moReviewAdvanced
unity-mcp-orchestrator174moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

More by trailofbits

View all by trailofbits

differential-review

trailofbits

Performs security-focused differential review of code changes (PRs, commits, diffs). Adapts analysis depth to codebase size, uses git history for context, calculates blast radius, checks test coverage, and generates comprehensive markdown reports. Automatically detects and prevents security regressions.

3115

code-maturity-assessor

trailofbits

Systematic code maturity assessment using Trail of Bits' 9-category framework. Analyzes codebase for arithmetic safety, auditing practices, access controls, complexity, decentralization, documentation, MEV risks, low-level code, and testing. Produces professional scorecard with evidence-based ratings and actionable recommendations.

416

modern-python

trailofbits

Configures Python projects with modern tooling (uv, ruff, ty). Use when creating projects, writing standalone scripts, or migrating from pip/Poetry/mypy/black.

427

semgrep-rule-creator

trailofbits

Creates custom Semgrep rules for detecting security vulnerabilities, bug patterns, and code patterns. Use when writing Semgrep rules or building custom static analysis detections.

416

ton-vulnerability-scanner

trailofbits

Scans TON (The Open Network) smart contracts for 3 critical vulnerabilities including integer-as-boolean misuse, fake Jetton contracts, and forward TON without gas checks. Use when auditing FunC contracts.

410

cosmos-vulnerability-scanner

trailofbits

Scans Cosmos SDK blockchains for 9 consensus-critical vulnerabilities including non-determinism, incorrect signers, ABCI panics, and rounding errors. Use when auditing Cosmos chains or CosmWasm contracts.

32

Search skills

Search the agent skills registry