ELF Fuzzer is a command-line fuzzing tool written in Rust for testing Linux ELF binaries. It implements mutation-based fuzzing with a persistent corpus, simple edge-coverage guidance via ptrace, automatic input minimization, crash detection, and deduplication. The fuzzer runs the target binary in a controlled child process, feeds it mutated inputs on stdin, and monitors for abnormal termination signals.
It is intended for discovering crashes in command-line tools, parsers, or any ELF executable that reads binary or text data from standard input.
- Parallel fuzzing with Rayon for maximum throughput
- Corpus loading, saving, and extension based on new coverage
- Structured mutation engine with bit flips, byte flips, arithmetic changes, block insert/delete, magic-value overwrites, and format-string insertion
- Dictionary learning of ASCII tokens from interesting inputs
- Splicing between corpus entries
- Delta-debugging-style minimization (chunk removal followed by byte removal)
- Coverage tracking using edge hashes derived from RIP values
- Crash deduplication by signal and instruction pointer (RIP)
- JSON crash logging with registers and input
- Optional GDB backtrace extraction for crash analysis
- Replay mode for reproducing and analyzing saved crash inputs
- Core-dump support and resource-limit configuration
The fuzzer is specifically tuned to discover the following classes of bugs:
- Buffer overflows (triggered by long runs of repeating characters A-E and magic values such as 0x41414141)
- Format-string vulnerabilities (inserted patterns like %x%x%x%x, %n%n%n%n, %s%s%s%s)
- Integer overflows and arithmetic errors (via wrapping arithmetic mutations)
- Memory-corruption crashes (SIGSEGV, SIGABRT, SIGILL, SIGFPE, SIGBUS)
- Null-pointer dereferences and out-of-bounds accesses
- Any other crash caused by malformed input that leads to abnormal termination
Because it combines random generation, dictionary tokens, splicing, and targeted mutations, it is effective against text parsers, protocol handlers, and simple file-format processors.
- Linux (x86_64)
- Rust stable toolchain
- GDB (optional, only for stack traces)
- The target binary must be an ELF executable that reads from stdin
-
Clone the repository:
git clone https://github.com/rhjddjdbc/elf_fuzzer.git cd elf_fuzzer -
Build the release binary:
cargo build --release
The resulting binary is located at target/release/elf_fuzzer.
Basic fuzzing run:
target/release/elf_fuzzer /path/to/target_binary --iterations 10000 --timeout 5
Replay a saved crash:
target/release/elf_fuzzer /path/to/target_binary --replay corpus_min/seed_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.bin
Available command-line options:
--replay <FILE>: Replay a specific crash file--iterations <N>: Number of fuzz iterations (default: 100)--timeout <SECS>: Timeout per execution in seconds (default: 5)--corpus_dir <DIR>: Directory for the main corpus (default: corpus)--min_dir <DIR>: Directory for minimized crashes (default: corpus_min)
After fuzzing finishes, inspect:
crash_log.jsonfor all unique crashescorpus/for the full test corpuscorpus_min/for minimized crashing inputscorefiles (if generated) for GDB analysis
src/main.rs: CLI entry point and parallel fuzzing loopsrc/runner.rs: ptrace-based execution, crash detection, coverage recordingsrc/fuzzer.rs: input generation, mutation, splicing, and iteration logicsrc/minimizer.rs: chunk- and byte-level reductionsrc/corpus.rs/src/corpus_manager.rs: corpus loading and managementsrc/dictionary.rs: token extraction and reusesrc/analyzer.rs/src/report.rs: crash analysis and logging
GPL-3.0