A Crash Analytics System for Boofuzz Fuzz Runs (TRUN, GTER, and Additional Commands)
This project implements a complete fuzzing analytics database system for crashes discovered while fuzzing the vulnerable VChat server using Boofuzz.
It transforms raw fuzzing output into a clean, normalized SQLite database that supports querying, analysis, visualization, and multi-run comparison.
This project was developed as part of a database course, but it also serves as a real-world example of cybersecurity data engineering, fuzzing instrumentation, and structured crash analysis.
Boofuzz generates valuable but unstructured output when fuzzing a program:
- Thousands of test cases
- Crash events
- Packet payloads (text and binary)
- Event logs
- Internal “steps” describing send/receive operations
This project ingests those raw artifacts and converts them into a normalized relational schema suitable for:
- Querying
- Analysis
- Visualization
- Comparing fuzz runs
- Understanding which inputs cause program instability
The ingestion pipeline supports multiple fuzz runs, such as:
TRUNGTER- (Any other VChat command you fuzz)
Each run is tracked independently in the final vchat_fuzz_analysis.db.
This project uses a clean four-table schema:
fuzz_runs (1) ───────< test_cases (1) ───────< crashes (1) ───────< crash_inputs
Represents one fuzzing session.
| Column | Description |
|---|---|
| run_id (PK) | Unique fuzz run ID |
| start_time | Timestamp when ingestion occurred |
| end_time | Optional |
| total_cases | Number of test cases in this run |
| total_crashes | Number of crashes detected |
| Column | Description |
|---|---|
| case_id (PK) | Unique ID for test case |
| run_id (FK) | References fuzz_runs |
| case_number | Sequential test case number |
| case_name | Mutation name (e.g., TRUN:[TRUN-STRING:35]) |
| timestamp | Timestamp extracted from fuzz data |
| Column | Description |
|---|---|
| crash_id (PK) | Crash event ID |
| case_id (FK) | The test case that caused the crash |
| run_id (FK) | The fuzz run containing this crash |
| timestamp | Crash timestamp |
| crash_reason | Detected reason (e.g., connection reset, monitor failure) |
| Column | Description |
|---|---|
| input_id (PK) | Unique payload ID |
| crash_id (FK) | References crashes |
| payload (BLOB) | Crash-causing payload (binary or text) |
| payload_size | Size in bytes |
┌──────────────┐ ┌────────────────┐ ┌───────────────┐ ┌─────────────────┐
│ fuzz_runs │ 1 ∞ │ test_cases │ 1 ∞ │ crashes │ 1 1 │ crash_inputs │
├──────────────┤ ├────────────────┤ ├───────────────┤ ├─────────────────┤
│ run_id (PK) │◄────── │ case_id (PK) │◄────── │ crash_id (PK) │◄────── │ input_id (PK) │
│ start_time │ │ run_id (FK) │ │ case_id (FK) │ │ payload (BLOB) │
│ total_cases │ │ case_number │ │ run_id (FK) │ │ payload_size │
│ total_crashes│ │ case_name │ │ timestamp │ └─────────────────┘
└──────────────┘ └────────────────┘ │ crash_reason │
└───────────────┘
The ingestion script (ingest2.py) performs:
- "connection reset"
- "check failed"
- "exception thrown"
steps.data(raw BLOBs)- Fuzz logs (
fuzz_log.csv) as a fallback
This allows you to ingest:
- TRUN fuzz run
- GTER fuzz run
- Any future fuzz runs
All into the same analysis database.
python ingest.py
The script will:
- Read the original Boofuzz database
- Read fuzz logs if available
- Detect crash events
- Extract payloads
- Insert everything into
vchat_fuzz_analysis.db
Below are some examples
SELECT
tc.case_id,
tc.case_number,
tc.case_name,
tc.run_id,
c.crash_reason,
c.timestamp AS crash_time
FROM crashes c
JOIN test_cases tc ON tc.case_id = c.case_id
ORDER BY tc.case_number;SELECT
fr.run_id,
fr.start_time,
fr.total_cases,
fr.total_crashes
FROM fuzz_runs fr
WHERE fr.total_crashes = 0
ORDER BY fr.run_id;
SELECT
c.crash_id,
tc.case_number,
tc.case_name,
ci.payload_size,
ci.payload
FROM crash_inputs ci
JOIN crashes c ON c.crash_id = ci.crash_id
JOIN test_cases tc ON tc.case_id = c.case_id
ORDER BY ci.payload_size DESC;SELECT
tc.case_name,
c.crash_reason,
ci.payload_size,
ci.payload
FROM crash_inputs ci
JOIN crashes c ON c.crash_id = ci.crash_id
JOIN test_cases tc ON tc.case_id = c.case_id
WHERE tc.case_name LIKE 'TRUN%'
ORDER BY ci.payload_size DESC;
MIT License