Lesson pack 25 · Advanced · 120 minutes
Fuzzing and crash triage
Stop reading for the bug and make the crash come to you - then work out which crashes are the same bug and which one is exploitable.
Print this page for a paper plan - the navigation and links drop out.Student-facing version
Before the session
- Nothing to install. Students need a browser and https://ctfpal.com. Confirm the room can reach it once; after that it works offline.
- Read the lesson yourself first - about 12 minutes.
- Have one worked example ready to paste. The classroom link builder on the instructor page turns it into a URL that opens preloaded.
Objectives
Written as things a student can do afterwards, so they can be assessed rather than asserted.
- Write a harness that reaches the interesting code in as few layers as possible
- Build a seed corpus and say why each seed is there
- Explain what coverage instrumentation buys, and what it costs on a slow target
- Turn a sanitiser report into a one-line statement of the bug's class and location
- De-duplicate crashes by root cause rather than by stack hash
- Judge exploitability from the primitive rather than from the crash message
Running order (120 min)
| Time | What happens |
|---|---|
| 0:00-0:12 | Frame the problemWhat the category looks like when you meet it cold, and why the naive approach fails. |
| 0:12-0:36 | Teach the methodThe technique itself, on the board or from the lesson. No tools open yet. |
| 0:36-1:06 | Demonstrate liveSame technique, in the workspace, on your worked example. Narrate every choice. |
| 1:06-1:48 | Practice setStudents work the challenges. Circulate rather than present. |
| 1:48-2:00 | Checkpoint and wrapCollect the artefact, name what comes next. |
Tools used
- ELF, PE and Mach-O binary analyzer - Parse headers, sections, imports, and symbols from Linux, Windows, and macOS binaries, with C++ symbol demangling and gadget discovery.https://ctfpal.com/?tool=elf-pe-analyzer
- Cyclic pattern generator and offset finder - Generate a de Bruijn sequence and find the exact overflow offset from a crashed register value - the pwntools cyclic workflow, in the browser.https://ctfpal.com/?tool=cyclic-pattern-generator
- Buffer overflow offset finder - Find the exact number of bytes before the saved return address using a de Bruijn pattern and the value from a single crash.https://ctfpal.com/?tool=buffer-overflow-offset
- Struct pack and unpack (p32, p64, u32, u64) - Convert integers to little-endian byte strings and back at 8, 16, 32, and 64 bits - the pwntools p32/p64 helpers without the install.https://ctfpal.com/?tool=struct-pack-unpack
- Pwntools exploit script generator - Generate a working pwntools template with the right context, process or remote connection, and the boilerplate every exploit repeats.https://ctfpal.com/?tool=pwntools-script-generator
Reading
- Coverage-guided fuzzing: making the crash come to you - 6 min. When a pwn or rev challenge hands you a parser and asks for the bug, you can read every line - or you can let AFL++ find the crash while you sleep. Harnesses, corpus, sanitizers, and what to do when the fuzzer gets stuck on a checksum.
- Integer bugs: overflow, signedness, truncation, and the off-by-one - 6 min. The length check that passes because the length wrapped, the negative index that survives a bounds check, and the 16-bit truncation that turns 65,540 into 4. Where arithmetic bugs come from and how to spot them in a decompiler.
Practice set
Real picoCTF challenges tagged with this module’s techniques, easiest first. Assign the first three in class and the rest as homework.
- fixme1.py - Beginner picoMini 2022, easy
- fixme2.py - Beginner picoMini 2022, easy
- Flag Hunters - picoCTF 2025, easy
- Glitch Cat - Beginner picoMini 2022, easy
- runme.py - Beginner picoMini 2022, easy
- Rust fixme 1 - picoCTF 2025, easy
- CVE-XXXX-XXXX - picoCTF 2022, medium
- file-run1 - picoCTF 2022, medium
- file-run2 - picoCTF 2022, medium
- Bizz Fuzz - picoCTF 2021, hard
- Checkpass - picoCTF 2021, hard
- Easy as GDB - picoCTF 2021, hard
Checkpoint (gradeable)
Take a small parsing target, produce a harness and a seed corpus, run it to a crash, and hand in the minimised input plus a one-sentence root cause.
Deliberately a produced artefact rather than a quiz question: it is either there or it is not, which makes it fast to mark and hard to bluff. Every tool in ctfpal is deterministic, so two students who did the work correctly hand in the same value.
Where the room gets stuck
The lesson students resist is that harness quality dominates everything else. Show two runs on the same target - one through the CLI, one through a direct call into the parser - and let the coverage numbers make the argument.
- Fuzzing the whole program through its normal entry point. Most of the run is spent in argument parsing and setup; the harness exists to skip that.
- Counting crashes. A thousand crashes are usually a handful of bugs, and until they are de-duplicated the number means nothing.
- Treating a sanitiser report as an exploit. Heap-buffer-overflow READ of size 1 and WRITE of size 8 are very different findings.
- Judging a corpus by how many files are in it. A thousand near-identical seeds explore one path; a corpus is doing its job when each seed reaches code the others do not, which is a coverage measurement rather than a count.
- Fuzzing a target built without sanitisers. Corruption that does not happen to crash passes unnoticed, so the run finds the loud bugs and silently misses the class this module is about.
If a student wants the subject, not the answer
Chapter-level references, so a student can be pointed at twenty pages rather than at a book. Nothing here is required to complete the module.
- From Day Zero to Zero Day, Eugene Lim. Chapter 7, Quick and Dirty Fuzzing. The cheapest useful fuzzer, which is the one that should exist before any sophisticated one does.
- From Day Zero to Zero Day, Eugene Lim. Chapter 8, Coverage-Guided Fuzzing. Instrumentation, corpora and scheduling explained in the order you actually need them.
- From Day Zero to Zero Day, Eugene Lim. Chapter 3, Automated Variant Analysis. What to do after the first bug: the same mistake is usually present three more times.
- Practical Binary Analysis, Dennis Andriesse. Chapter 12, Principles of Symbolic Execution. The other way to reach deep code, and an honest account of where it stops scaling.
- Bug Bounty Bootcamp, Vickie Li. Chapter 25, Automatic Vulnerability Discovery Using Fuzzers. The same technique aimed at web targets, where the oracle is a response rather than a signal.
If you finish early
- Hand out a challenge from the cross-CTF index in this category - each one has published solutions to compare afterwards.
- Run the same input through Identify and let the class argue with the ranking. Disagreeing with a confidence score is where the technique actually lands.
- Ask a student to break their own example - construct an input that defeats the tool, and explain why.
Take this into a room
Markdown files, built here in your browser. They print, they open in anything, and they carry the challenge text - so the session works with no network in the room.