Skip to main content

Fuzzing Engine

Sogen includes a powerful fuzzing engine that leverages its snapshot and state management capabilities to perform high-performance coverage-guided fuzzing of Windows applications.

Overview

The fuzzing engine works by:
  1. Emulating the target application to a specific point (the target function)
  2. Creating a snapshot of the emulator state
  3. Spawning multiple fuzzer instances across CPU cores
  4. Each instance restores the snapshot, injects fuzzed input, and tracks code coverage
  5. Crashes and new coverage paths are automatically detected

Fuzzer Executable

Sogen provides a dedicated fuzzer.exe utility for fuzzing applications. The fuzzer requires the Rust-based Icicle backend to be enabled at compile time.

Basic Usage

Command Line Options

The -d flag enables GDB stub integration, allowing you to attach a debugger to inspect crashes.

How the Fuzzing Engine Works

1. Target Function Setup

The fuzzer looks for an exported function named vulnerable in your target executable:
The emulator runs until it hits the vulnerable function, then stops and captures the state.

2. State Serialization

The entire emulator state is serialized and shared across fuzzer instances:

3. Parallel Execution

The fuzzer spawns multiple workers based on CPU core count:
Each worker gets its own emulator instance restored from the snapshot.

4. Input Injection

Fuzzed data is injected via registers before execution:
This follows the Windows x64 calling convention where:
  • RCX = pointer to fuzzed input buffer
  • RDX = size of fuzzed input

5. Coverage Tracking

The fuzzer tracks which basic blocks have been executed:
New basic blocks are reported to the fuzzing engine to guide input generation.

6. Crash Detection

Exceptions and crashes are automatically caught:

Implementing a Fuzzable Target

To make your application fuzzable with Sogen:

1. Export a Target Function

2. Compile Your Target

Build your target application as a standard Windows executable or DLL with the vulnerable export.

3. Run the Fuzzer

The fuzzer will:
  • Load your executable
  • Run until the vulnerable function
  • Take a snapshot
  • Start fuzzing with automatic input generation

Fuzzer Architecture

Executer Interface

Each fuzzer worker implements the fuzzer::executer interface:

Fuzzing Handler

The main fuzzing logic implements fuzzer::fuzzing_handler:

Performance Optimization

Snapshot vs. Deserialization

The fuzzer uses fast in-memory snapshots instead of full deserialization:
This provides significantly faster reset times compared to full state deserialization.

Memory Management

The fuzzer allocates memory for each input and cleans up automatically:

Backend Requirements

The fuzzer requires the Icicle backend (Rust-based emulation):
See the Custom Backends page for build configuration details.

Example: Fuzzing a Parser

Here’s a complete example of a fuzzable parser:
Compile and fuzz:
The fuzzer will discover the crash when it generates input starting with “FUZZ” and larger than 16 bytes.

Troubleshooting

”Fuzzer requires rust code to be enabled”

You need to build Sogen with Rust support enabled:

No Coverage Increase

Ensure:
  • Your vulnerable function is actually being called
  • The function performs different operations based on input
  • The emulator isn’t hitting infinite loops

Out of Memory

Reduce concurrency:

Next Steps