Complete Fuzzing Tutorial (AFL++, libFuzzer, Kernel & IoT Fuzzing)

Complete Fuzzing Tutorial: From Zero to CVE Discovery

A complete beginner-to-expert guide to fuzzing. Every concept explained line-by-line. No shortcuts. No assumptions.


Philosophy

This is not a “quick start guide.” This is the resource you need if you want to actually understand fuzzing from first principles.

  • Every line of code is explained
  • Every concept builds on the previous one
  • No “just run this command” — you’ll understand WHY
  • Blog length doesn’t matter — depth does

If you’re coming from GitHub READMEs that say “just run afl-fuzz -i in -o out ./target” and you’re thinking “but WHY?” — this series is for you.


Phase 1 — The Mental Model (Foundation)

You cannot use tools effectively without understanding the underlying model. These blogs build your intuition from zero.

# Blog Title What You’ll Understand
What Is Fuzzing and Why Does It Actually Work? What Is Fuzzing and Why Does It Actually Work? The fundamental question: why does throwing random data at a program find bugs? The mental model that makes everything else make sense.
How a Fuzzer Works: Mutations, Seeds, and Corpus Explained How a Fuzzer Works: Mutations, Seeds, and Corpus Explained Before touching AFL++ or any tool, understand the internal loop: how does a fuzzer decide what input to try next? What is a corpus? What is a seed?
The Taxonomy: Every Type of Fuzzing Explained Black-box, grey-box, white-box, coverage-guided, mutation-based, generation-based. The complete map of fuzzing approaches.
4 What Happens Inside a Program When It Crashes Segmentation faults, stack traces, registers, memory corruption. You need to understand what a crash IS before you can find one.
5 Sanitizers: Detecting Bugs BEFORE They Crash AddressSanitizer, UndefinedBehaviorSanitizer, MemorySanitizer. What they do at compile-time, how they instrument your binary, why fuzzing without sanitizers misses 90% of bugs.

Phase 2 — Your First Fuzzing Lab (Hands-On Setup)

Now that you understand the theory, it’s time to get your hands dirty. But we go SLOW. Every installation step explained.

# Blog Title What You’ll Build
6 Setting Up Your Fuzzing Environment From Scratch Installing AFL++ on Ubuntu/macOS/WSL. Installing clang. Understanding compiler wrappers. Troubleshooting afl-clang-fast not found. Setting up your directory structure (in/, out/, crashes/).
7 Your First 5-Minute Fuzz Run (Complete Walkthrough) Compiling a simple vulnerable C program with AFL++. Creating a seed corpus. Running afl-fuzz for the first time. Reading the TUI (what every number means). Understanding execs/sec, corpus count, unique crashes.
8 Reading AFL++ Output: What Those Numbers Actually Mean Deep dive into the AFL++ status screen. What is pending, pend fav, own finds, imported? What is stability? When is your fuzzer stuck? How to diagnose performance issues.

Phase 3 — AFL++ Deep Dive (The Engine Room)

You’ve run AFL++. Now it’s time to understand HOW it works under the hood.

# Blog Title What You’ll Learn
9 AFL++ Architecture: How Coverage-Guided Fuzzing Actually Works The feedback loop. How AFL++ instruments your binary. What is edge coverage vs. block coverage. The bitmap. The shared memory region. How AFL++ knows if an input discovered new code paths.
10 Compiling Targets with afl-clang-fast (Line-by-Line) What happens when you run afl-clang-fast target.c -o target? How does the compiler wrapper inject instrumentation? What are the compile flags (-fsanitize=address, -g, -O0)? When to use each.
11 AFL++ Mutation Algorithms: Deterministic Stage Bitflips, byte flips, arithmetic mutations, interesting values. How AFL++ systematically mutates inputs in the deterministic stage. Why this stage comes first.
12 AFL++ Mutation Algorithms: Havoc and Splicing Random mutations, stacked mutations, splicing inputs together. When AFL++ switches from deterministic to havoc. Why both stages matter.
13 The Corpus: Seeds, Queue, Crashes, and Hangs What is a seed? What is the queue? How does AFL++ decide which inputs to keep? What is corpus minimization? How afl-cmin works.
14 Dictionaries: Teaching the Fuzzer About Your File Format When random mutations aren’t enough. Creating a dictionary file. How AFL++ uses tokens from the dictionary. When dictionaries matter (file formats, protocols).
15 Parallel Fuzzing: Running Multiple AFL++ Instances Master/slave mode. Syncing corpora between instances. How to scale fuzzing across CPU cores. The -M and -S flags.

Phase 4 — Writing Your First Fuzzing Harness

Theory is over. Now you write code that makes fuzzing possible.

# Blog Title What You’ll Build
16 What Is a Fuzzing Harness and Why You Need One The gap between “the program” and “the fuzzable interface.” Why you can’t just fuzz ./program. What a harness does. File-based vs in-memory harnesses.
17 Writing Your First AFL++ Harness (Complete Example) A vulnerable C function. Writing the harness that feeds AFL++ input into it. Compiling with instrumentation. Running the fuzz. Finding the crash. Line-by-line code walkthrough.
18 Writing Harnesses for libFuzzer (In-Process Fuzzing) The LLVMFuzzerTestOneInput function. How libFuzzer differs from AFL++. When to use libFuzzer vs AFL++. Writing a libFuzzer harness for the same target.
19 Harness Design Patterns: Handling State and Setup What if your target needs initialization? What if it has global state? How to handle setup/teardown in a harness. Avoiding “poisoned” state across fuzzing iterations.
20 Fuzzing File Format Parsers (Real-World Example) Choosing a real target (PNG parser, JSON parser, etc.). Writing the harness. Building the seed corpus. Running the fuzz campaign. Triaging the crashes.

Phase 5 — libFuzzer Deep Dive

AFL++ is not the only fuzzer. libFuzzer has different strengths.

# Blog Title What You’ll Learn
21 libFuzzer vs AFL++: When to Use Each In-process vs fork-server model. Speed differences. Coverage differences. Use cases for each.
22 libFuzzer Instrumentation: How SanitizerCoverage Works What -fsanitize=fuzzer actually does. The coverage hooks. How libFuzzer tracks edges.
23 libFuzzer Corpus Management and Merging How libFuzzer builds its corpus. Merging corpora with merge=1. Minimizing with -minimize_crash=1.
24 Writing Custom Mutators for libFuzzer When default mutations aren’t enough. Implementing a custom mutator. Guiding libFuzzer toward specific input structures.

Phase 6 — Honggfuzz (The Underrated Fuzzer)

Honggfuzz is less popular but extremely powerful. You need to know it.

# Blog Title What You’ll Learn
25 Honggfuzz: Why It’s Different (And When to Use It) Persistent mode. Feedback-driven fuzzing without AFL++'s instrumentation. Hardware-based coverage (Intel PT). Multi-threaded by default.
26 Setting Up and Running Honggfuzz Installation. Compiling targets with hfuzz-clang. Running your first Honggfuzz campaign. Reading the output.
27 Honggfuzz + Intel PT: Coverage Without Instrumentation What is Intel PT? How Honggfuzz uses it for coverage feedback. When this matters (closed-source binaries).

Phase 7 — Crash Triage and Bug Analysis

You found crashes. Now what? Most beginners stop here. You won’t.

# Blog Title What You’ll Learn
28 Triaging Crashes: Unique vs Duplicate You have 500 crash files. Are they all unique bugs? How to deduplicate crashes. Using afl-collect, stack hashes, sanitizer output.
29 Reading AddressSanitizer Output (Line-by-Line) What does “heap-buffer-overflow on address 0x…” mean? Stack traces. Shadow bytes. How to map the crash back to your source code.
30 From Crash to Root Cause: Debugging with GDB Loading the crash input into GDB. Examining registers. Walking the stack. Finding the exact line where the overflow happens.
31 Writing a Bug Report (CVE-Quality) What makes a good bug report? Proof-of-concept. Root cause analysis. Impact assessment. Reproduction steps. Submitting to vendors.

Phase 8 — Coverage Analysis (When Your Fuzzer Gets Stuck)

Your fuzzer has been running for 6 hours. No new paths. Is it stuck? How do you know?

# Blog Title What You’ll Learn
32 What Is Code Coverage and Why It Matters Line coverage, branch coverage, edge coverage. The difference. Why fuzzers care about edges, not lines.
33 Generating Coverage Reports with lcov Instrumenting your target with --coverage. Running your corpus through it. Generating HTML reports with lcov and genhtml. Reading the reports to find unreached code.
34 When Your Fuzzer Is Stuck: Diagnosing Coverage Plateaus Your corpus hasn’t grown in hours. What does this mean? Is the target fully explored? Or is there a barrier (checksums, magic bytes, complex branching)?
35 Breaking Through: Solving Coverage Barriers Identifying the barrier (checksums, CRCs, magic headers). Surgical harness changes. Custom mutators. Dictionaries. When to give up on a target.

Phase 9 — OSS-Fuzz and Continuous Fuzzing

Now you understand harnesses, coverage, and tools. Time to see how Google fuzzes the entire internet.

# Blog Title What You’ll Learn
36 What Is OSS-Fuzz and Why Google Runs It 24/7 Continuous fuzzing infrastructure. ClusterFuzz. How OSS-Fuzz has found 10,000+ bugs. Why your project should be on it.
37 OSS-Fuzz Architecture: How It Actually Works Docker containers. Build scripts. ClusterFuzz orchestration. Reproducing crashes. The full pipeline from code commit to bug report.
38 Integrating Your Project into OSS-Fuzz Writing a build.sh script. Creating a Dockerfile. Defining fuzzing targets. Submitting a pull request. Getting your project accepted.
39 ClusterFuzz Deep Dive: The Engine Behind OSS-Fuzz How ClusterFuzz distributes fuzzing jobs. Crash deduplication at scale. Bisecting regressions. The feedback loop from fuzzing to developers.

Phase 10 — Kernel Fuzzing (syzkaller)

Userland is easy. The kernel is where it gets serious.

# Blog Title What You’ll Learn
40 Why Kernel Fuzzing Is Completely Different System calls vs library functions. The kernel doesn’t crash — it panics. State dependencies. Why you can’t just fuzz the kernel like a normal program.
41 syzkaller: Architecture and Design Coverage-guided kernel fuzzing. Virtual machines. The executor. The syscall descriptions. How syzkaller generates valid syscall sequences.
42 Setting Up syzkaller (Step-by-Step) Building syzkaller from source. Creating a VM image. Configuring the kernel with KASAN. Running your first syzkaller campaign.
43 Writing Syscall Descriptions for syzkaller The syzlang language. Describing syscall arguments, structures, dependencies. Teaching syzkaller about a new subsystem.
44 Linux Kernel Fuzzing in Practice Running syzkaller against a real kernel subsystem. Reading kernel panics. Bisecting kernel bugs. Reporting to LKML.

Phase 11 — Binary-Only Fuzzing (No Source Code)

Everything so far assumed you had source code. What if you don’t?

# Blog Title What You’ll Learn
45 The Challenge of Binary-Only Fuzzing No instrumentation. No sanitizers. No coverage. Emulation overhead. Why binary fuzzing is slow.
46 AFL++ QEMU Mode: Fuzzing Closed-Source Binaries How QEMU mode works. User-mode emulation. QEMU’s instrumentation. Setting up afl-qemu-trace. Performance trade-offs.
47 Intel PT for Fast Binary Coverage Hardware-assisted coverage. How Intel Processor Trace works. Using Honggfuzz with Intel PT. When this is faster than QEMU.
48 WinAFL: Fuzzing Windows Closed-Source Applications DynamoRIO instrumentation. Persistent mode on Windows. Choosing a target function. Running WinAFL against a Windows DLL.

Phase 12 — Advanced Fuzzing Techniques

You’ve mastered the basics. These are the cutting-edge techniques.

# Blog Title What You’ll Learn
49 Structure-Aware Fuzzing: Beyond Random Bytes When random mutations fail (structured inputs like XML, protocol messages). Grammar-based fuzzing. Protobuf fuzzing.
50 Snapshot Fuzzing: Fuzzing from the Middle What is snapshot fuzzing? Saving execution state. Restoring and fuzzing from a snapshot. When this matters (deep program states, complex setup).
51 Differential Fuzzing: Finding Logic Bugs Fuzzing two implementations of the same spec. Comparing outputs. Finding semantic differences. Use cases: OpenSSL vs BoringSSL, PDF parsers.
52 LibAFL: Building Custom Fuzzers The LibAFL framework. When AFL++ isn’t enough. Writing your own fuzzer with Rust. Custom feedback mechanisms, custom mutators, custom schedulers.
53 AI-Assisted Fuzzing: LLMs for Seed Generation Using GPT/Claude to generate valid input seeds. When this works (complex file formats). When it doesn’t (pure randomness still wins).

Phase 13 — Network Protocol Fuzzing

Programs don’t just parse files. They parse network traffic too.

# Blog Title What You’ll Learn
54 Network Protocol Fuzzing: The Unique Challenges State machines. Handshakes. Session state. Why you can’t just throw random bytes at a TCP socket.
55 Boofuzz: The Network Fuzzing Framework Protocol definitions. Primitives, blocks, sessions. Building a protocol model. Running a Boofuzz campaign against a network service.
56 Fuzzing TLS Implementations Why TLS is hard to fuzz. State dependencies. Certificate validation. Building a harness for OpenSSL/BoringSSL.
57 Fuzzing Custom Protocols (Unknown Binary Protocols) Reverse engineering a protocol from network captures. Inferring the state machine. Writing a fuzzer without a spec.

Phase 14 — Android Fuzzing

Mobile devices are everywhere. Here’s how to fuzz them.

# Blog Title What You’ll Learn
58 Android Attack Surface for Fuzzers Native libraries. HAL interfaces. The Binder IPC mechanism. Where bugs hide in Android.
59 Fuzzing Android Native Libraries with AFL++ Cross-compiling for ARM. Running AFL++ on-device vs in an emulator. Pushing inputs, pulling crashes.
60 Fuzzing the Android Binder Interface What is Binder? Parcels and transactions. Writing a harness for a Binder service.
61 Fuzzing Android Apps (Java/Kotlin Layer) Fuzzing at the Java layer. Monkey testing vs coverage-guided fuzzing. Tools: Jazzer, JQF.

Phase 15 — IoT and Firmware Fuzzing

IoT devices are notoriously insecure. Here’s how to fuzz them.

# Blog Title What You’ll Learn
62 IoT Fuzzing: The Unique Challenges Embedded systems. Limited resources. No debuggers. Proprietary protocols. Extracting firmware.
63 Emulating Firmware with QEMU for Fuzzing Extracting firmware from devices. Loading into QEMU. Setting up a virtual environment. Fuzzing in emulation.
64 Fuzzing Network Services on IoT Devices Identifying network-facing services. Building harnesses for UPnP, MQTT, CoAP. Running AFL++ QEMU mode against them.
65 Fuzzing Bootloaders and Firmware Parsers OTA update parsers. Bootloader vulnerabilities. Fuzzing the update mechanism. Building a corpus from real firmware images.

Phase 16 — Real-World Fuzzing Workflows

How professionals actually run fuzzing campaigns in production.

# Blog Title What You’ll Learn
66 The Professional Fuzzing Workflow (End-to-End) Target selection. Harness writing. Corpus building. Campaign planning. Triage automation. Reporting. The complete process.
67 Fuzzing for 1 Hour vs 1 Week vs 1 Month What to expect at each time scale. When to stop. Diminishing returns. How long is “long enough”?
68 Building a Seed Corpus: Quality vs Quantity Manually creating seeds. Scraping seeds from test suites. Minimizing your corpus. When more seeds hurt performance.
69 Automating Crash Triage at Scale You have 10,000 crashes. You can’t manually analyze them. Scripting deduplication. Prioritizing by severity. Building a triage pipeline.
70 From Fuzzing Campaign to CVE Submission You found a real bug. Now what? Root cause analysis. Impact assessment. Writing the disclosure. Vendor coordination. Getting your CVE ID.

Phase 17 — Building Your Own Fuzzing Infrastructure

You’re no longer just using tools. You’re building systems.

# Blog Title What You’ll Learn
71 Designing a Private Fuzzing Cluster Hardware requirements. Orchestration (Docker, Kubernetes). Distributed fuzzing. Centralized crash reporting.
72 Integrating Fuzzing into CI/CD Running fuzzing in GitHub Actions. Automated regression testing. Catching bugs before they ship.
73 Fuzzing Metrics: What to Measure Execs/sec, crashes/hour, coverage growth rate, unique crashes. Tracking performance over time. When metrics lie.
74 Building a Custom Fuzzer with LibAFL (Advanced) When existing fuzzers aren’t enough. Using LibAFL to build domain-specific fuzzers. Custom feedback, schedulers, mutators. A complete example.
75 The Complete Fuzzing Lab: Hardware, VMs, Automation The ultimate setup. Dedicated hardware. VM orchestration. Automated triage. Reporting dashboard. What a professional fuzzing lab looks like.

Total: 75 Blogs

Every concept explained from zero.
Every line of code walked through.
No assumptions. No shortcuts.

This is the fuzzing course that should exist.


How to Use This Roadmap

  1. Start at Blog 1. Do not skip.
  2. Do the hands-on exercises. Reading is not enough.
  3. Don’t rush. Each blog builds on the previous ones.
  4. If you’re confused, re-read the previous blog. The foundation matters.

By Blog 75, you will understand fuzzing better than 95% of people who claim to “do fuzzing.”


This is not a sprint. This is a marathon. But you will finish it.