SecureFlow Fuzzer is a coverage-guided fuzzing engine that automatically discovers bugs and vulnerabilities in software. It instruments target binaries to track code coverage, then uses that feedback to guide input mutation toward unexplored code paths. Built on the battle-tested AFL++ architecture, it implements a fork server protocol for efficient target execution and a custom mutator plugin API for domain-specific fuzzing.
graph LR
A[Target Binary] --> B[Compiler Wrapper]
B --> C[Instrumented Binary]
C --> D[Fork Server]
D --> E[Fuzzer Core]
E --> F[Mutator]
F --> G[Test Input]
G --> D
D --> H[Coverage Bitmap]
H --> I[Queue Manager]
I --> E
The fuzzer instruments binaries at compile time to record edge coverage via a shared memory bitmap. The fork server avoids the overhead of re-executing program startup on every test case. The queue manager schedules inputs based on coverage novelty, and the mutator engine generates new test cases through bit-level and structural mutations.
- Coverage-guided mutation engine — feedback-driven fuzzing that prioritizes unexplored code paths
- Fork server protocol — efficient target execution by forking from a pre-initialized process
- Shared memory coverage bitmap — low-overhead edge coverage tracking via shared memory
- CmpLog/Redqueen input-to-state mutation — magic byte inference for bypassing comparisons
- Custom mutator plugin API — extend with domain-specific mutation strategies via shared libraries
- Test case minimization — reduce crash-triggering inputs to minimal reproducers
- Corpus management — deduplicate and minimize seed corpora with
afl-cmin
# Build
make source-only
# Instrument your target
./afl-cc -o target target.c
# Run the fuzzer
./afl-fuzz -i input_dir -o output_dir -- ./target @@# 1. Instrument the target with coverage tracking
export CC=./afl-cc
export CXX=./afl-c++
./configure && make
# 2. Prepare a seed corpus
mkdir -p inputs
echo "hello" > inputs/seed1
# 3. Start fuzzing
./afl-fuzz -i inputs -o findings -m none -- ./target @@
# 4. Minimize a crash-triggering input
./afl-tmin -i findings/crashes/crash_001 -o minimized -- ./target @@
# 5. Analyze coverage on an input
./afl-showmap -o /dev/null -- ./target < minimized
# 6. Minimize the corpus
./afl-cmin.bash -i findings/queue -o corpus_min -- ./target @@secureflow-fuzzer/
├── src/
│ ├── afl-fuzz.c # Main fuzzer entry point
│ ├── afl-fuzz-one.c # Per-input mutation and execution loop
│ ├── afl-fuzz-bitmap.c # Coverage bitmap analysis
│ ├── afl-fuzz-state.c # Fuzzer state management
│ ├── afl-forkserver.c # Fork server protocol implementation
│ ├── afl-sharedmem.c # Shared memory setup and management
│ ├── afl-fuzz-run.c # Target execution and timeout handling
│ ├── afl-fuzz-queue.c # Corpus queue and scheduling
│ ├── afl-performance.c # Performance measurement utilities
│ ├── afl-cc.c # Compiler wrapper with auto-instrumentation
│ ├── afl-fuzz-redqueen.c # Redqueen/CmpLog input-to-state mutations
│ ├── afl-fuzz-cmplog.c # CmpLog shared memory interface
│ ├── afl-fuzz-mutators.c # Custom mutator plugin API
│ ├── afl-tmin.c # Test case minimizer
│ ├── afl-analyze.c # Input structure analyzer
│ ├── afl-showmap.c # Single-run coverage mapper
│ └── afl-gotcpu.c # CPU affinity management
├── include/
│ ├── afl-fuzz.h # Core fuzzer state and data structures
│ ├── config.h # Tunable constants and configuration
│ ├── types.h # Primitive type definitions
│ └── afl-mutations.h # Custom mutator plugin API definitions
├── instrumentation/
│ ├── afl-llvm-pass.so.cc # LLVM instrumentation pass
│ ├── afl-compiler-rt.o.c # Compiler runtime for coverage tracking
│ ├── SanitizerCoverageLTO.so.cc # LTO-mode sanitizer coverage
│ └── afl-llvm-dict2file.so.cc # Auto-dictionary generation pass
├── test/
│ ├── test-basic.sh # Basic fuzzer functionality tests
│ ├── test-compcov.c # Comparison coverage test target
│ ├── test-custom-mutator.c # Custom mutator API test
│ └── test-performance.sh # Performance benchmarks
├── afl-cmin.bash # Corpus minimizer script
└── Makefile # Build system
Building this project deepened my understanding of coverage-guided fuzzing internals:
- Fork server design: Instead of exec'ing the target for every input, AFL's fork server forks from a pre-initialized process, saving the overhead of dynamic linking, constructors, and startup code. This can make fuzzing 5-10x faster.
- Bitmap analysis: The coverage bitmap is a 64KB shared memory region where each byte represents an edge (src_block XOR dst_block). The fuzzer checks if any byte transitioned from zero to non-zero after each run — that indicates new coverage. Calibrating the bitmap sensitivity avoids both false positives and missed paths.
- Mutation scheduling: The queue scheduler assigns energy (number of mutations) to each corpus entry based on execution speed, bitmap coverage, and how recently it was discovered. Entries that cover unique edges and execute quickly receive more mutations.
- CmpLog/Redqueen: Rather than blindly mutating bytes to match magic constants, CmpLog records every comparison operand at runtime via a dedicated shared memory region. The Redqueen algorithm then replaces input bytes that match comparison operands with the expected values, dramatically improving the fuzzer's ability to pass checksums and magic bytes.
Built upon AFL++ by the AFL++ community — https://github.com/AFLplusplus/AFLplusplus (Apache 2.0 License).
This project is licensed under the Apache License 2.0.