Coldsnap: Python Snapshot Fuzzer
Coldsnap – Python Snapshot Fuzzer Example
coldsnap.py is a python-based snapshot-based ptrace-based fuzzer example. The purpose of this example is to test the performance of snapshot fuzzing entirely in python and to provide an educational example of a snapshot fuzzer. Coldsnap uses ptrace to control the program state for saving state and for guiding the fuzzer through ptrace-applied breakpoints. This example is not meant to be a production-ready fuzzer. Instead, this example should be used as educational material on how to put together a simple snapshot-based fuzzer with coverage guidance in python.
Overview
This fuzzer forks “target” as a child process with ptrace attached as a debugger. It leverages nm, objdump, and /proc/id/maps to locate the .text section of “target”, derive all necessary breakpoint positions in memory, locate the start and stop snapshot points and control the saving/loading of the target memory. I made an effort to comment as much as I could so the python should serve as good documentation on how to build a snapshot-based fuzzer (@h0mbre_ blog Fuzzing Like A Caveman 4 is also good supplemental material). When the fuzzer first executes it applies as many breakpoints as possible, it then continues execution to the startpoint deleting all breakpoints along the way. It then saves the program state at the start point and starts the fuzzing operation. The fuzzing loop creates a fuzzing payload, writes the payload in target memory, and continues execution until it hits the endpoint. At the endpoint, the fuzzer reloads the program state back to the startpoint and creates a new mutation to test. For every test case that results in a new breakpoint hit, the fuzzer captures the mutation into its corpus pool, removes the breakpoint, and continues execution. The mutation in this example is extremely trivial, it is just a byte flip of 2 random payload bytes and good enough to find the crashes. The target example contains 2 unique crashes.
Performance
10,000 – 20,000 Fuzz cases per second depending on your CPU. The fuzzer should find the 2 unique crashes within 10-60 seconds of fuzz time.
The goal of snapshot fuzzing is performance and determinism, While snapshot fuzzing does improve performance by quite an amount, this example is written in python and thus implementations in C or Rust should perform better.
How to install and run (Ubuntu)
Install
- clone this repo and change directory into it
- sudo apt update
- sudo apt install python3 python3-pip build-essential
- sudo pip3 install python-ptrace
- make
Copyright (c) 2020 Evan Custodio