Ringkasan & Hubungan ke Vault
Fuzzing adalah jembatan antara Reverse Engineering (menemukan bug secara manual) dan Exploit Development (mengeksploitasi bug). Dengan fuzzing sistematis, lo bisa menemukan vulnerability pada skala yang gak mungkin dicapai manual. Catatan ini melengkapi hardware-hacking-re dengan automated bug discovery, dan malware-analysis-reverse-engineering-playbook dengan teknik exploit development modern.
Domain: Cyber Security / Vulnerability Research Tags: fuzzing afl libfuzzer symbolic-execution exploit-dev kernel
Daftar Isi
- Fundamental Fuzzing
- AFL++ Deep-Dive
- libFuzzer & Sanitizer Integration
- Structure-Aware Fuzzing
- Kernel Fuzzing dengan syzkaller
- Network & Protocol Fuzzing
- Hardware & Firmware Fuzzing
- Symbolic Execution & SMT Solvers
- CI/CD Fuzzing & OSS-Fuzz
- Crash Triage & Exploitability
- Workflow End-to-End
- Koneksi ke Vault
1. Fundamental Fuzzing
1.1 Apa Itu Fuzzing?
Fuzzing = memberikan input invalid/semi-valid/random ke program, lalu observasi apakah program crash/hang/leak. Tujuan: menemukan bugs yang gak kelihatan dari static analysis.
┌─────────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────┐
│ Seed Corpus │───→│ Mutator │───→│ Target │───→│ Monitor │
└─────────────┘ └──────────────┘ └──────────┘ └──────────┘
↑ │
│ ┌───────┴───────┐
└───────────┤ Coverage Info │
└───────────────┘
1.2 Jenis Fuzzing
| Jenis | Cara Kerja | Contoh Tool | Kelebihan | Kekurangan |
|---|---|---|---|---|
| Black-box | Input random, no instrumentation | zzuf, radamsa | No code changes needed | Coverage rendah |
| White-box | Symbolic execution, constraint solving | SAGE, Triton | Coverage maksimal | Scalability buruk |
| Grey-box (CG) | Coverage feedback, lightweight instrumentasi | AFL++, libFuzzer, Honggfuzz | Best balance speed/coverage | Butuh source atau binary instrumentation |
| Mutational | Mutate existing seed (bitflip, havoc, splice) | AFL++ (default) | Simple, works | Bisa stuck di path |
| Generational | Generate input from grammar/template | Peach, libprotobuf-mutator | Input valid structure | Butuh grammar definition |
| Grammar-based | Input dari grammar specification | Dharma, Nautilus | Deep protocol coverage | Grammar development effort |
1.3 Coverage Metrics
- Edge Coverage: count berapa kali edge A→B dieksekusi (standard AFL++)
- Hit Count: seberapa sering edge dieksekusi (bucketed: 1, 2, 4, 8, 16+)
- Line Coverage: line per line (gcov/lcov)
- Function Coverage: function mana yang dipanggil
- Branch Coverage: kedua sisi branch dieksekusi
1.4 Mutator Strategies
AFL++ mutator stages:
- Deterministic: sequential bitflips (1/2/4 bit), arithmetic add/sub, interest value, dictionary insertion — lama tapi exploration awal
- Havoc (default): random bitflips + insert + delete + splice + overwrite — kerjaan utama fuzzer
- Splice: kawin dua seed di titik potong random
- Custom mutator: lo bisa kasih mutator sendiri via
AFL_CUSTOM_MUTATOR_LIBRARY
Bitflip: 01001010 → 01011010
Arithmetic: b"\x2a\x00\x00\x00" → b"\x2b\x00\x00\x00"
Interest: b"\x01\x02\x03\x04" → b"\xff\xff\xff\xff" (nilai boundary)
Splice: seed_a[0:len/2] + seed_b[len/2:]
Dictionary: ["GET", "POST", "Host:", ...] — common protocols
2. AFL++ Deep-Dive
2.1 Arsitektur AFL++
┌──────────┐
│ afl-fuzz │ ←───────┐
└────┬─────┘ │
│ │
┌─────────┴─────────┐ │
│ Fork Server │ │
│ (LLVM/PCGUARD) │ │
└─────────┬─────────┘ │
│ │
┌───────────┴───────────┐ │
│ Instrumented Target │ │
│ (queue/*.cur_input) │───┘
└───────────────────────┘
2.2 Instrumentasi
| Metode | Command | Kecepatan | Use Case |
|---|---|---|---|
| LLVM LTO | afl-clang-lto | ★★★★★ | Source available, best speed |
| LLVM PCGUARD | afl-clang-fast | ★★★★ | Source available |
| GCC | afl-gcc-fast | ★★★ | GCC projects |
| QEMU | afl-qemu-trace | ★★ | Binary-only (x86/ARM) |
| Unicorn | afl-unicorn | ★ | Binary only, pure emulation |
| FRIDA | afl-frida | ★★ | Binary only, persistent mode |
2.3 Basic Command
# 1. Compile dengan AFL++ instrumentation
export AFL_USE_ASAN=1
export AFL_CC=afl-clang-lto
./configure --cc="$AFL_CC"
make -j$(nproc)
# 2. Fuzz
afl-fuzz -i seeds/ -o findings/ -- ./target @@
# 3. Parallel fuzzing (N core)
afl-fuzz -i seeds/ -o findings/ -M master -- ./target @@
afl-fuzz -i seeds/ -o findings/ -S slave1 -- ./target @@
afl-fuzz -i seeds/ -o findings/ -S slave2 -- ./target @@
# 4. Minimize crash
afl-tmin -i crash_file -o minimized_crash -- ./target @@2.4 AFL++ Performance Tunables
# Power schedule (default: explore)
export AFL_FAST_CAL=1 # quick calibration
export AFL_CMPLOG=1 # Redqueen style input-to-state solving
export AFL_NO_CPU_RED=1 # supress CPU throttle warning
export AFL_EXPAND_HAVOC_NOW=1 # langsung pake havoc, skip deterministic
export AFL_SKIP_BIN_CHECK=1 # skip binary check (untuk QEMU mode)
# Crash exploration mode
export AFL_BENCH_UNTIL_CRASH=1 # stop setelah crash pertama2.5 CMPLOG / Redqueen
Redqueen = teknik yang menemukan hubungan input-to-state. Contoh: program ngecek input[0] == 0xdeadbeef. Fuzzer biasa butuh 2^32 percobaan untuk guess magic byte. CMPLOG menggunakan QEMD mode untuk compare instruction trace, lalu patch input langsung dengan magic value.
export AFL_CMPLOG=1
afl-fuzz -i seeds/ -o findings/ -x dictionary.dict -- ./target @@Ini alasan kenapa AFL++ bisa nge-bypass checksum dan magic value checks yang biasanya jadi bottleneck fuzzer.
2.6 Persistent Mode (LLVM)
Daripade fork server per input, persistent mode jalanin target dalam loop tanpa fork. 10-50× faster.
int main() {
char buf[1024];
while (__AFL_LOOP(10000)) { // 10.000 iteration sebelum re-fork
size_t len = read(0, buf, sizeof(buf) - 1);
process_input(buf, len);
}
return 0;
}afl-clang-lto -o persistent_target persistent_target.c
afl-fuzz -i seeds/ -o findings/ -- ./persistent_target3. libFuzzer & Sanitizer Integration
3.1 libFuzzer Concepts
libFuzzer = in-process fuzzer yang jalan di LLVM. Beda dengan AFL++ (fork-based), libFuzzer panggil target function langsung dalam loop.
libFuzzer process:
┌──────────────────────────────────┐
│ ┌──────────┐ ┌────────────┐ │
│ │ Fuzzer │──→│ Target Func │ ←───── Coverage feedback
│ │ Engine │ │ (LLVM inst) │ │
│ └──────────┘ └────────────┘ │
│ ↑ │ │
│ └──────────────┘ │
└──────────────────────────────────┘
3.2 Basic Usage
// Fuzz target: LLVM akan panggil function ini
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
parse_input(data, size); // target lo
return 0;
}# Compile
clang++ -fsanitize=fuzzer,address -o fuzzer_target fuzzer_target.cpp
# Run
./fuzzer_target -max_len=1024 -jobs=8 corpus/3.3 Sanitizer Integration
| Sanitizer | Flag | Deteksi |
|---|---|---|
| AddressSanitizer (ASAN) | -fsanitize=address | Buffer overflow, uaf, double free |
| UndefinedBehavior (UBSAN) | -fsanitize=undefined | Shift overflow, integer overflow |
| MemorySanitizer (MSAN) | -fsanitize=memory | Uninitialized memory |
| LeakSanitizer (LSAN) | -fsanitize=leak | Memory leak |
| ControlFlowIntegrity (CFI) | -fsanitize=cfi | CFI violation |
| HWASAN | -fsanitize=hwaddress | Hardware-assisted ASAN (ARM) |
# Best practice: ASAN + UBSAN + coverage
CFLAGS="-fsanitize=fuzzer,address,undefined -fno-omit-frame-pointer"
export CFLAGS3.4 libFuzzer Advanced
// Custom mutator (struct-aware fuzzing)
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size,
size_t max_size, unsigned int seed) {
Packet pkt;
pkt.ParseFromArray(data, size); // Protobuf-aware mutation
// Mutate packet fields
pkt.set_type(pkt.type() ^ (rand() & 0xff));
pkt.SerializeToArray(data, max_size);
return pkt.ByteSizeLong();
}
// Corpus splitting
// Set environment variable:
// FUZZER_CORPUS_DIR=/path/to/corpus — detects new coverage3.5 Comparison: AFL++ vs libFuzzer
| Aspect | AFL++ | libFuzzer |
|---|---|---|
| Process model | Fork-based (fork per run) | In-process (function call) |
| Speed | ~1K exec/s (heavy target) | ~100K exec/s (same target) |
| Instrumentation | LLVM, GCC, QEMU, FRIDA, Unicorn | LLVM only |
| Binary-only | ✅ (QEMU/FRIDA) | ❌ |
| Parallel | Multi-instance via -S | Built-in -jobs=8 |
| Custom mutator | .so library | LLVMFuzzerCustomMutator |
| Corpus pruning | Built-in cmin | Auto-minimize |
| Network target | ❌ (but can wrap) | ❌ (but can wrap) |
4. Structure-Aware Fuzzing
4.1 Kenapa Perlu?
Fuzzer biasa generate byte random. Untuk protokol kompleks (TLS, DNS, HTTP/2), byte random mentah gak akan tembus parsing layer pertama. Structure-aware fuzzing generate input yang secara format valid, cuma semantic-nya corrupt.
Mutational (byte-level): "\x01\xff\x00\xab\x12" → parsing fails di byte 0
Grammar-based (structure): "GET /index.html HTTP/1.1\r\nHost: ..." → valid HTTP
4.2 libprotobuf-mutator
// 1. Define protobuf schema
message Packet {
enum Type { SYN = 0; ACK = 1; DATA = 2; FIN = 3; }
required Type type = 1;
required uint32 seq = 2;
optional bytes payload = 3;
}
// 2. Fuzz target with protobuf-aware mutator
#include <libprotobuf-mutator/src/libfuzzer.h>
DEFINE_PROTO_FUZZER(const Packet& packet) {
process_packet(packet);
}4.3 Grammar-based: Nautilus & Dharma
Nautilus memungkinkan lo define grammar dalam Python:
grammar = {
"http_request": [["method", " ", "url", " ", "version", "\r\n", "header", "\r\n"]],
"method": ["GET", "POST", "PUT", "DELETE"],
"url": ["/", "/index.html", "/api/v1/data"],
"version": ["HTTP/1.0", "HTTP/1.1"],
"header": [["Host: example.com"], ["Content-Length: ", num]],
}5. Kernel Fuzzing dengan syzkaller
5.1 Arsitektur syzkaller
Host Machine Target VM/Device
┌─────────────────┐ ┌──────────────────┐
│ syz-manager │ SSH/RPC │ syz-fuzzer │
│ ├── Program gen │──────────→│ ├── syscall exec │
│ ├── Corpus DB │ ◄────────│ └── coverage rep │
│ ├── Crash DB │ RPC └──────────────────┘
│ └── Dashboard │
└─────────────────┘
5.2 Syzlang — Syscall Description Language
// File: linux/system.syz
include <uapi/linux/socket.h>
resource fd[sock_fd]: -1
open$socket(family flags[32], type flags[32], proto flags[32]) fd
{
syscall openat(AT_FDCWD, filename ptr[in, string], flags flags[open_flags], mode flags[open_mode])
}
// Lebih complex — ioctl untuk network device
ioctl$SIOCGIFINDEX(fd fd, cmd const[SIOCGIFINDEX], arg ptr[in, struct ifreq])
{
syscall ioctl(fd, cmd, arg)
}
struct ifreq {
ifr_name array[char, IFNAMSIZ]
ifr_ifindex int32
}5.3 Setup syzkaller
# Minimal config (linux qemu)
cat > my.cfg << 'EOF'
{
"name": "linux-kernel",
"target": "linux/amd64",
"http": ":56700",
"workdir": "/workdir",
"kernel_obj": "/linux/linux-6.1",
"kernel_src": "/linux/linux-6.1",
"sandbox": "none",
"procs": 4,
"type": "qemu",
"vm": {
"count": 2,
"cpu": 2,
"mem": 2048,
"kernel": "/linux/arch/x86/boot/bzImage",
"image": "/linux/image/stretch.img"
}
}
EOF
# Run
bin/syz-manager -config=my.cfg6. Network & Protocol Fuzzing
6.1 boofuzz (Network Protocol Fuzzer)
from boofuzz import *
session = Session(target=Target(connection=TCPSocketConnection("192.168.1.1", 80)))
define_protocol(session)
session.fuzz()
def define_protocol(session):
s_initialize("HTTP_REQUEST")
s_static("GET ")
s_string("index.html")
s_static(" HTTP/1.1\r\n")
s_static("Host: ")
s_string("example.com")
s_static("\r\n\r\n")6.2 AFLnet (Stateful Protocol Fuzzing)
AFLnet menambahkan state-aware fuzzing untuk protokol network:
Fuzzer tahu state machine target!
State: HANDSHAKE → AUTH → REQUEST → RESPONSE
AFLnet track transitions antar state, dan fuzz per state
7. Hardware & Firmware Fuzzing
7.1 Firmware Rehosting — firmadyne / FirmAFL
Untuk fuzz firmware embedded, lo perlu rehost (emulate) firmware-nya:
# firmadyne workflow
python3 scripts/makeImage.py -i firmware.bin -o /tmp/images/
sudo python3 scratch/run.sh /tmp/images/firmware_image
# Sekarang firmware jalan di QEMU → fuzz via AFLnet
afl-fuzz -i seeds/ -o findings/ -Q -- ./qemu-system-arm ...Masalah utama: firmware gak selalu boot di QEMU (butuh hardware check, peripheral driver). Solusi partial: patch firmware atau emulate peripheral minimal.
7.2 Nyx / Fuzzware — Binary-Only HW Fuzzing
Fuzzware = automated firmware fuzzing tanpa manual rehosting. Menggunakan Unicorn engine + QEMU + symbolic execution untuk auto-model peripheral.
firmware.bin → Fuzzware → model peripheral → fuzz dengan AFL++
Use case: IoT router firmware, IOT devices, embedded Linux.
8. Symbolic Execution & SMT Solvers
8.1 Kenapa Kombinasi Fuzzing + Symbolic?
Fuzzing mencapai code coverage tinggi secara cepat, tapi gak bisa ngehandle constraint kompleks (checksum, complex branch conditions). Symbolic execution bisa solve constraint, tapi lambat. Hybrid: fuzzer untuk exploration → symbolic execution untuk path yang stuck.
8.2 Angr — Symbolic Execution Framework
import angr
# Load binary
proj = angr.Project("vuln_binary", auto_load_libs=False)
# Symbolic dari stdin
state = proj.factory.entry_state(
stdin=angr.SimFile("/dev/stdin")
)
# Symbolic exploration
simgr = proj.factory.simulation_manager(state)
simgr.explore(find=0x400000 + 0x1234) # target address (win function)
if simgr.found:
found_state = simgr.found[0]
stdin_input = found_state.posix.stdin.concretize()
print(f"Found input: {stdin_input}")8.3 Z3 SMT Solver
from z3 import *
# Solve: find input such that buf[i] * 5 == 100
buf = [BitVec(f'buf_{i}', 8) for i in range(16)]
s = Solver()
for i in range(4):
s.add(buf[i] * 5 == 100) # buf[i] == 20
s.add(buf[0] == ord('A')) # specific constraint
if s.check() == sat:
model = s.model()
print([model[buf[i]] for i in range(4)])Z3 Theories untuk binary analysis:
- QF_BV: quantifier-free bitvector — arithmetic, bitwise, shift
- QF_ABV: arrays + bitvector — memory modeling
- QF_FPBV: floating point + bitvector
- Strings: string constraints (path explosion risk)
8.4 Fuzzing + Symbolic = Driller / FirmAFL
Driller (untuk binary) = AFL++ untuk exploration → Angr untuk solve constraint path:
AFL: alur sederhana → coverage → continue
Angr: AFL stuck di path X → symbolic execute X → solve constraint → inject seed → AFL lanjut
9. CI/CD Fuzzing & OSS-Fuzz
9.1 OSS-Fuzz Workflow
Google OSS-Fuzz = continuous fuzzing untuk open source.
┌────────────┐ ┌───────────┐ ┌───────────┐ ┌──────────┐
│ Developer │───→│ OSS-Fuzz │───→│ Cluster │───→│ Issue │
│ (PR/build) │ │ BuildBot │ │ Fuzz (GCE)│ │ Tracker │
└────────────┘ └───────────┘ └───────────┘ └──────────┘
│
↓
┌──────────┐
│ Coverage │
│ Report │
└──────────┘
9.2 ClusterFuzzLite (Modern)
# .github/workflows/fuzz.yml
name: Fuzzing
on: [push, pull_request]
jobs:
fuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build fuzzers
run: |
docker build -t fuzzer -f Dockerfile.fuzz .
- uses: google/clusterfuzzlite@v1
with:
fuzz_seconds: 30010. Crash Triage & Exploitability
10.1 Crash Classification
| Class | Description | Action |
|---|---|---|
| Exploitable | Control RIP, arbitrary write | Prioritize analysis |
| Probably Exploitable | Controlled dereference | Manual analysis |
| May be Exploitable | Partial control | Low priority |
| Unknown | No clear exploitation primitive | Dedup & log |
| Not Exploitable | Null deref, assertion | Inform dev |
10.2 Bang — Crash Analysis Tool
# AFL++ crash explorer
afl-crash-analyzer -i findings/default/crashes/ -- ./target @@
# Manual stack analysis
gdb --batch -ex "run < crash_file" -ex "bt" ./target
# Symbolicate crash
addr2line -e ./target -f -C 0x40123410.3 Exploitability Heuristic
| Signal | Context | Exploitable? |
|---|---|---|
| SIGSEGV | RIP = offset of input buffer | ✅ Almost guaranteed |
| SIGSEGV | RIP = 0x4141414141414141 | ✅ ROP chain possible |
| SIGSEGV | RIP = controlled but limited | ⚠️ Partial overwrite possible |
| SIGABRT | ASAN: heap-buffer-overflow | ✅ Depends on primitive |
| SIGABRT | ASAN: stack-buffer-overflow | ✅ Often ROP-able |
| SIGSEGV | RIP = NULL (null deref) | ❌ Usually denial-of-service |
11. Workflow End-to-End
11.1 Target Selection
Prioritas target berdasarkan:
- Attack surface: network-facing, parsing user input
- Complexity: complex parsers (PDF, video, image) → high bug density
- Criticality: kernel modules, privilege boundary
- History: pernah punya CVE → pasti masih ada bug lain
11.2 End-to-End Pipeline
Phase 1: Reconnaissance
├── Static analysis target (Ghidra/IDA)
├── Identify input surface (file format, protocol, API)
├── Collect seed corpus (valid input samples)
└── Write harness / wrapper
Phase 2: Instrumentation
├── Source available → LLVM (AFL++ / libFuzzer)
├── Binary only (ELF) → QEMU mode / FRIDA
├── Binary only (PE) → WinAFL DynamoRIO
└── Kernel → syzkaller
Phase 3: Fuzzing
├── Single-core (exploration)
├── Multi-core (farming: 1 master + N slaves)
├── Parallel with cross-pollination
└── CI/CD integration (ClusterFuzzLite)
Phase 4: Triage
├── Deduplicate (stack hash)
├── Minimize (afl-tmin)
├── Exploitability classification
└── CVE assignment readiness
Phase 5: Exploitation
├── Control flow analysis
├── ROP chain / heap spray
├── Exploit PoC
└── Disclosure / report
11.3 Resource Sizing
| Target Type | Suggested Core | Duration | Success Rate |
|---|---|---|---|
| Command-line parser | 1-4 core | 1-24 jam | ★★★ High |
| Library (libpng, libxml) | 4-8 core | 1-7 hari | ★★★ High |
| Network protocol | 8-16 core | 1-30 hari | ★★ Medium |
| Kernel syscall | 16-32 core + VM | 7-90 hari | ★★ Medium |
| Firmware (QEMU rehost) | 4-8 core | 1-60 hari | ★ Low (emu issue) |
12. Koneksi ke Vault
Related Notes
| Note | Hubungan |
|---|---|
| hardware-hacking-re | Target fuzzing: firmware, UART, JTAG — fuzzing automation |
| malware-analysis-reverse-engineering-playbook | RE workflow → fuzzing target identification |
| incident-response-framework | Vulnerability discovery → responsible disclosure |
| web-hacking-exploitation | Web fuzzing methodology → Ffuf, Burp Intruder |
| purple-team-osi-killchain | Fuzzing di phase reconnaissance + weaponization |
| c2-server-fix | Persistence mechanisms bisa divalidasi via fuzzing |
Tool Comparison Summary
Tool Target Type Difficulty Cost
─────────────────────────────────────────────────────────
AFL++ Binary/ELF/Linux Medium Free
libFuzzer ELF Libraries Low Free
syzkaller Linux Kernel High Free (VM)
boofuzz Network Protocols Medium Free
Peach Network/File High $$$ (Pro)
WinAFL Windows PE Medium Free
Honggfuzz ELF/Linux Low Free
Angr RE/Analysis High Free
FirmAFL Firmware Very High Free (QEMU)
ClusterFuzzLite CI/CD Medium Free
📚 Referensi
- AFL++ documentation: https://aflplus.plus/
- libFuzzer tutorial: https://llvm.org/docs/LibFuzzer.html
- syzkaller: https://github.com/google/syzkaller
- OSS-Fuzz: https://github.com/google/oss-fuzz
- Angr: https://angr.io/
- Z3 Prover: https://github.com/Z3Prover/z3
- “Fuzzing: Brute Force Vulnerability Discovery” — Sutton, Greene, Amini
- Fuzzware: https://fuzzware.io/