Sitemap

Fuzzing with AFL++: Exercise 1 (simple_crash)

4 min readJan 28, 2026

--

In this post, I walk through Exercise 1 from the Fuzzing-Module repository by Alex Maleno, using AFL++ inside a containerized environment. The goal of this exercise is simple but powerful: compile a vulnerable program with AFL++ instrumentation, fuzz it, and analyze the resulting crashes.

Environment Setup

The exercise is executed inside a container that already contains AFL++. I mount the exercise directory into the container so that the source code is available at runtime.

podman run --rm -it -v $(pwd)/Fuzzing-Module/exercise1:/target <afl++-image>

Inside the container, the project structure looks like this:

/target
├── CMakeLists.txt
└── simple_crash.cpp

Understanding the Target Program

The target binary is built from simple_crash.cpp. It reads user input from stdin and contains a deliberate crash condition. When a specific input pattern is reached, the program aborts, making it ideal for fuzzing.

The program is stdin-based, which means AFL++ can fuzz it without any special harness.

Press enter or click to view image in full size

Building the Target with AFL++ Instrumentation

To enable coverage-guided fuzzing, the program must be compiled using AFL++ compilers.

mkdir build
cd build
CC=/AFLplusplus/afl-clang-fast \
CXX=/AFLplusplus/afl-clang-fast++ \
cmake ..
make
Press enter or click to view image in full size
Press enter or click to view image in full size

During compilation, AFL++ reports instrumentation details:

  • LLVM PCGUARD mode is enabled
  • 34 locations are instrumented
  • No collisions detected

This confirms the binary is ready for fuzzing.

The final instrumented binary is:

./simple_crash

Sanity Check

Before fuzzing, I manually execute the binary to confirm it works:

./simple_crash
enter input string: test

The program accepts input and exits normally. This is a good sign.

Creating the Initial Seed Corpus

AFL++ requires at least one seed input to start fuzzing. I create a small corpus of random inputs using /dev/urandom:

mkdir seeds
cd seeds
for i in {0..4}; do dd if=/dev/urandom of=seed_$i bs=64 count=10; done

This results in five initial seed files:

seed_0 seed_1 seed_2 seed_3 seed_4

Launching AFL++

With the instrumented binary and seeds ready, I start fuzzing:

/AFLplusplus/afl-fuzz \
-i /target/build/seeds \
-o out \
-m none \
-d -- /target/build/simple_crash

Key options:

  • -i – input corpus
  • -o – output directory
  • -m none – disable memory limit (container-friendly)
  • -d – deterministic mode (deprecated but still works)

AFL++ immediately begins execution and coverage discovery.

Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size

AFL++ Runtime Observations

After a few minutes, AFL++ reports:

  • Total crashes: 3
  • Corpus count: 21
  • Coverage density: ~40%
  • Exec speed: ~60 exec/sec

This confirms that AFL++ successfully discovered crashing inputs very quickly.

Inspecting the Output Directory

The output directory follows the standard AFL++ structure:

out/default/
├── crashes/
├── queue/
├── hangs/
├── fuzzer_stats
└── plot_data

Inside crashes/, I find multiple crashing inputs:

id:000000,sig:06,src:000003,time:221,execs:101,op:havoc,rep:1
id:000001,sig:06,src:000003,time:377,execs:114,op:havoc,rep:11
id:000002,sig:06,src:000003,time:1241,execs:198,op:havoc,rep:14

Each file represents a unique crashing test case.

Press enter or click to view image in full size

Reading the Crash Metadata

The README.txt inside the crashes/ directory explains how the crash was found and how to reproduce it:

Command line used to find this crash:
/AFLplusplus/afl-fuzz -i seeds -o out -m none -d -- simple_crash
Press enter or click to view image in full size

AFL++ also recommends using afl-tmin to minimize crashing inputs.

Reproducing the Crash Manually

To validate the crash outside AFL++, I feed the crashing input directly to the program:

cat out/default/crashes/id:000000* | ./simple_crash
Press enter or click to view image in full size

Thanks for reading,

Can

--

--

Can Özkan
Can Özkan

Written by Can Özkan

Security Researcher, Penetration Tester, and Reverse Engineer