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.zipInstalls 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.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
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
| Fuzzer | Best For | Complexity |
|---|---|---|
| AFL++ | Multi-core fuzzing, diverse mutations, mature projects | Medium |
| libFuzzer | Quick setup, single-threaded, simple harnesses | Low |
| LibAFL | Custom fuzzers, research, advanced use cases | High |
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++.
| Method | When to Use | Supported Compilers |
|---|---|---|
| Ubuntu/Debian repos | Recent Ubuntu, basic features only | Ubuntu 23.10: Clang 14 & GCC 13<br>Debian 12: Clang 14 & GCC 12 |
| Docker (from Docker Hub) | Specific AFL++ version, Apple Silicon support | As of 4.35c: Clang 19 & GCC 11 |
| Docker (from source) | Test unreleased features, apply patches | Configurable in Dockerfile |
| From source | Avoid Docker, need specific patches | Adjustable 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 -i \
--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++
The examples below use docker mode, apart from the system configuration commands that have to reach the host kernel. Swap in host to run any of them against an AFL++ installed on the machine itself. The wrapper joins everything after the mode argument into a single shell string, so quoting does not survive: an argument containing a space (-x "my dict.dict") arrives word-split. Rename such files without spaces, or edit the wrapper for that run.
The missing -t is deliberate. docker run -ti aborts with the input device is not a TTY whenever stdin is not a terminal, which covers CI jobs and anything an agent or script drives. afl-fuzz notices there is no terminal and prints plain status lines in place of the full-screen UI. A program that insists on a terminal, such as watch, has to run on the host side of the wrapper instead. $$ expands to the wrapper's PID, so parallel instances get distinct container names rather than colliding on a single afl_fuzzing. docker ps truncates the COMMAND column, so every row looks alike; use docker ps --no-trunc to tell the instances apart before stopping one.
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 afl-system-config
afl-system-config tunes the kernel it runs against, so run it on the machine that hosts the campaign. ./afl++ docker afl-system-config reaches the same settings through the wrapper's --privileged container, which is the only route when AFL++ is installed via Docker alone.
For maximum performance, disable kernel security mitigations (requires grub bootloader, not supported in Docker):
./afl++ host afl-persistent-config
update-grub
reboot
./afl++ host 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
| Do | Don't |
|---|---|
| Reset global state between runs | Rely on state from previous runs |
| Handle edge cases gracefully | Exit on invalid input |
| Keep harness deterministic | Use random number generators |
| Free allocated memory | Create memory leaks |
| Validate input sizes | Process 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++ docker afl-clang-fast++ -DNO_MAIN=1 -O2 -fsanitize=fuzzer harness.cc main.cc -o fuzz
GCC Compilation
./afl++ 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++ 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.
| Flag | Purpose |
|---|---|
-DNO_MAIN=1 | Skip main function when using libFuzzer harness |
-O2 | Production optimization level (recommended for fuzzing) |
-fsanitize=fuzzer | Enable libFuzzer compatibility mode and adds the fuzzer runtime when linking executable |
-fsanitize=fuzzer-no-link | Instrument 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++ 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++ docker afl-fuzz -i seeds -o out -- ./fuzz
Setting Environment Variables
./afl++ docker AFL_FAST_CAL=1 afl-fuzz -i seeds -o out -- ./fuzz
Interpreting Output
AFL++ reports these statistics either way, but how you read them depends on the
mode. The wrapper's docker run -i gives the container no TTY, so afl-fuzz
drops the full-screen UI and writes plain status lines to the log instead — the
fields below appear there, and in state/<instance>/fuzzer_stats. To get the
interactive UI, run host mode in a terminal, or add -t to the wrapper for a
run you are watching by hand.
| Output | Meaning |
|---|---|
| execs/sec | Execution speed - higher is better |
| cycles done | Number of queue passes completed |
| corpus count | Number of unique test cases in queue |
| saved crashes | Number 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
---
*Content truncated.*
When not to use it
- →Small, simple single-threaded applications
- →Projects without C/C++ source code access
Prerequisites
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.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| aflpp (this skill) | 1 | 3mo | Review | Advanced |
| address-sanitizer | 1 | 3mo | Review | Intermediate |
| libafl | 1 | 3mo | Review | Advanced |
| unity-mcp-orchestrator | 17 | 6mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by trailofbits
View all by trailofbits →You might also like
address-sanitizer
trailofbits
AddressSanitizer detects memory errors during fuzzing. Use when fuzzing C/C++ code to find buffer overflows and use-after-free bugs.
libafl
trailofbits
LibAFL is a modular fuzzing library for building custom fuzzers. Use for advanced fuzzing needs, custom mutators, or non-standard fuzzing targets.
unity-mcp-orchestrator
CoplayDev
Orchestrate Unity Editor via MCP (Model Context Protocol) tools and resources. Use when working with Unity projects through MCP for Unity - creating/modifying GameObjects, editing scripts, managing scenes, running tests, or any Unity Editor automation. Provides best practices, tool schemas, and workflow patterns for effective Unity-MCP integration.
xss-testing
Ed1s0nZ
XSS跨站脚本攻击测试的专业技能
libfuzzer
trailofbits
Coverage-guided fuzzer built into LLVM for C/C++ projects. Use for fuzzing C/C++ code that can be compiled with Clang.
smart-contract-engineer
jw3b-dev
Expert in Solidity, Foundry, EVM security. Specializes in gas optimization, upgradeable patterns, and fuzz testing.