Safe Penetration Testing Labs · advanced · ~25 min
Write a libFuzzer entry point that exercises one parser thoroughly.
A fuzz harness exposes one function to libFuzzer / AFL++. The fuzzer mutates inputs; the harness calls the parser. Crashes are written to disk as 'corpus' for replay and debugging.
Fuzzing is the highest-leverage way to find memory-safety bugs in parsers. Pair with ASan — every bug becomes a clean, reproducible crash with a backtrace.
The entry point. int LLVMFuzzerTestOneInput(const uint8_t *, size_t). Compiled into a *-fuzz binary linked against libFuzzer.
Determinism. The harness must not depend on global state, time, or randomness. Same input → same crash.
Cleanup. Every allocation in the harness must be freed. Otherwise you mis-attribute leaks to the parser.
Crash artefacts. libFuzzer writes the offending input to crash-<sha1>. Replay with ./fuzz crash-<sha1> under gdb / ASan.
Pentester mindset. A 5-line harness around your validator can find every memory-safety bug in it in an hour. Add fuzzing to the CI pipeline for every parser you ship.
Defensive coding habit. Compile harness with -fsanitize=address,undefined,fuzzer. Run with -max_total_time=300 for CI.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
Fuzzing throws millions of pseudo-random inputs at a function and
watches for crashes. The standard C API is int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size).
You write that function to call into the parser you want to exercise.
With ASan+UBSan on, every crash is a bug to investigate.
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
char *copy = malloc(size + 1);
memcpy(copy, data, size); copy[size] = '\0';
valid_username(copy); /* the parser under test */
free(copy);
return 0;
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size == 0) return 0; /* skip empty */
char *copy = (char *)malloc(size + 1); /* +1 for NUL */
if (!copy) return 0;
memcpy(copy, data, size);
copy[size] = '\0'; /* string-safe */
valid_username(copy); /* under test */
free(copy); /* no leaks */
return 0;
}
Run a crash repro: ./parser-fuzz crash-abc.... Combine with -fsanitize=address for an instant report.
The harness is also subject to memory rules — leaks here ruin fuzzing.
OSS-Fuzz (Google's fuzzing-as-a-service), every major C codebase's CI, the parsers in nginx / curl / openssl all have harnesses.
valid_username in a fuzz harness. 2. Build with -fsanitize=fuzzer,address. 3. Run for 60s; investigate any crash.5 lines wrap a parser. ASan finds the bugs. libFuzzer generates the inputs.