Skip to content

RustamSubkhankulov/mini-fuzz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mini-fuzz

Overview

This repository is a small, self-contained fuzzing demo designed to be readable and presentable quickly.

It includes:

  • a mutation-based fuzzer for CLI programs (tools/fuzz.py)
  • a crash minimizer using delta debugging (ddmin) + byte-level simplifications (tools/reduce.py)
  • three vulnerable/buggy C targets (targets/*.c) with seed corpus (seeds/*)

Dependencies

Required:

  • cmake (3.16+ recommended)
  • C compiler: cc / clang / gcc
  • a CMake backend: make or ninja
  • python3 (standard library only)
  • POSIX sh (for tools/repro.sh)

Optional:

  • clang-format (only for the cformat build target)
  • black python package (only for the pyformat build target)

Description

  • Tools:

    • tools/fuzz.py - mutation-based fuzzer:
      • loads initial corpus from --seeds
      • repeatedly mutates inputs (bit flips, overwrite chunk, insert/delete, append)
      • runs target with timeout
      • detects crash by signal termination (returncode < 0)
      • saves crashes and “interesting” inputs
    • tools/reduce.py - crash minimizer:
      • validates input reproduces a crash (returncode < 0)
      • ddmin: chunk deletions that preserve the crash
      • byte-level simplification: replace bytes with simple values + single-byte deletions
      • outputs minimized input and a reduction log
    • tools/gen_bin_seeds.py - generates safe binary seeds for bin_parser into seeds/bin_parser/ during the build.
  • Targets:

    • targets/cmd_parser.c - Text command parser target with a stack overflow bug.
    • targets/bin_parser.c - Binary format parser with a destination buffer overflow bug.

Build

cmake -S . -B build
cmake --build build

Binaries are produced in build/bin/

Building with sanitizers (optional):

cmake -S . -B build -DSAN=ON
cmake --build build

Cleanup

  • Clean build artifacts only: cmake --build build --target clean
  • Remove out/ (fuzzer output): cmake --build build --target clean-out
  • Remove generated seeds/bin_parser/: cmake --build build --target clean-seeds
  • Remove build dir + out/ + generated bin seeds: cmake --build build --target distclean

Target interface (stdin vs file mode)

All C targets accept the same options:

  • stdin mode: ./build/bin/<target> --stdin < input.bin
  • file mode: ./build/bin/<target> --file input.bin

The fuzzer and reducer use the same two modes.

Example targets and vulnerabilities

1) cmd_parser (stdin): command parser with stack overflow

Behavior:

  • supports commands like PING, ADD ..., and SET ...
  • SET <arg> copies <arg> into a fixed 64-byte stack buffer

Bug:

  • uses unsafe strcpy(fr.buf, arg) with no bounds check
  • a stack-adjacent guard is checked; if overwritten, the program forces a deterministic SIGSEGV

Seeds:

  • seeds/cmd_parser/seed1.txt: SET ... input close to buffer boundary
  • seeds/cmd_parser/seed2.txt: PING

Expected crash symptom:

  • terminated by a signal (often SIGSEGV)
  • in Python: returncode < 0 (often -11 on Linux)

2) bin_parser (file): binary format parser with destination overflow

Format:

  • bytes 0..3: ASCII "BINF"
  • byte 4: payload_len (u8)
  • bytes 5..: payload

Bug:

  • checks the source length (n >= 5 + payload_len)
  • then copies payload_len bytes into a fixed 16-byte stack buffer via memcpy
  • missing check payload_len <= 16 → destination overflow
  • guard corruption forces deterministic SIGSEGV

Seeds:

  • generated by tools/gen_bin_seeds.py into seeds/bin_parser/
  • the payload is long, but payload_len starts at 15/16 (safe)
  • mutating only the length byte upward commonly triggers the overflow quickly

Expected crash symptom:

  • terminated by a signal (often SIGSEGV)
  • in Python: returncode < 0

Fuzzing: how to run, what files are produced

Crash definition used by fuzzer/reducer

A run is considered a crash if:

  • it did not time out, and
  • the process was terminated by a signal → returncode < 0

Timeouts are treated as hangs (counted by the fuzzer, not stored as crashes).

Output layout

If you fuzz with --out out/<name>, the fuzzer creates:

  • out/<name>/crashes/

    • id_000001.bin, id_000002.bin, ...
    • id_000001.bin.info (contains returncode, signal, duration_s)
  • out/<name>/corpus/

    • id_000001.bin, ...
    • “interesting” inputs saved by a cheap behavioral fingerprint heuristic

Run fuzzing via CMake helper targets

cmake --build build --target run-fuzz-cmd
cmake --build build --target run-fuzz-bin

Run fuzzing directly

cmd_parser (stdin):

python3 tools/fuzz.py --target build/bin/cmd_parser --mode stdin \
  --seeds seeds/cmd_parser --out out/cmd_parser

bin_parser (file):

python3 tools/fuzz.py --target build/bin/bin_parser --mode file \
  --seeds seeds/bin_parser --out out/bin_parser

What to expect:

  • periodic stats:
    • [stat] iters=... exec/s=... corpus=... crashes=... hangs=...
  • when a crash is found:
    • [CRASH] saved: out/.../crashes/id_XXXXXX.bin (signal=SIG... rc=...)

Minimizing: ddmin + byte-level simplification

Run reduction

Example for cmd_parser (stdin mode):

python3 tools/reduce.py --target build/bin/cmd_parser --mode stdin \
  --input out/cmd_parser/crashes/id_000001.bin \
  --out   out/cmd_parser/minimized.bin \
  --log   out/cmd_parser/reduce.log

Example for bin_parser (file mode):

python3 tools/reduce.py --target build/bin/bin_parser --mode file \
  --input out/bin_parser/crashes/id_000001.bin \
  --out   out/bin_parser/minimized.bin \
  --log   out/bin_parser/reduce.log

Outputs:

  • minimized input: .../minimized.bin
  • reduction log: .../reduce.log (shows successful ddmin deletions and byte-level steps)

Reproducing crashes (original or minimized)

Use tools/repro.sh:

stdin mode:

sh tools/repro.sh --target build/bin/cmd_parser --mode stdin \
  --input out/cmd_parser/minimized.bin

file mode:

sh tools/repro.sh --target build/bin/bin_parser --mode file \
  --input out/bin_parser/minimized.bin

Expected behavior:

  • the process terminates by a signal (shell may print “Segmentation fault” / “Floating point exception”)

About

Mini-fuzzer with crash-input minimizer

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors