🐍 Experimentations in trying to find 0-days in numpy
Inspired by Murmus CTF's live streams on fuzzing numpy, I decided to write my own custom fuzzer as well, and try to fuzz numpy.
This repository contains my explorations and experimentations in trying to fuzz numpy. Over time, I might expand into fuzzing other parts of CPython itself (or other libraries for Python).
Run ./first_run.sh
to download and compile CPython and Numpy with
ASAN (address sanitizer).
Then, use ./wrapper.sh
to start the fuzzer, and watch the crashing
inputs get dropped into the crashes
directory.
The fuzzer consists of multiple parts working in unison to lead to effective finding of bugs.
-
We have the ASAN compilation for both CPython and numpy (see
./first_run.sh
). This allows us to catch even subtle errors (that might take longer to manifest as a crash), such as heap corruption etc. -
We have a harness that handles crashing applications (see
harness/harness.c
). Specifically, it is compiled as a shared object (.so
file) which is loaded into python usingctypes
and it sets up signal handlers for SIGABRT (signifying an error caught by ASAN) and SIGSEGV (more serious error; missed by ASAN for some reason). It also uses an mmap'd region where testcases can be registered before running, thereby allowing the crashed process to be able to cleanly store the crashing input. -
We have the the main fuzzer itself that handles repeatedly trying newly generated testcases and puts all the different parts of the fuzzer together (see
fuzzer/main.py
). -
We have the generator, whose job is to keep track of the corpus, generate cases to test out, keep track of valid cases to increase corpus, etc. (see
fuzzer/generator.py
). -
We have the wrapper utility (see
./wrapper.sh
) which repeatedly calls the fuzzer with the right configuration for ASAN etc, in order to get a whole host of bugs rather than stopping after just one bug that otherwise be done by the main fuzzer.