This page describes how to write new targets for Fuzzbuzz. If you have existing targets for AFL, Libfuzzer, Gofuzz or other open-source fuzzing frameworks, they already work on Fuzzbuzz! Click Here to learn how.
Each target consists of two parts:
a method within your code, that Fuzzbuzz provides test data to - similar to a unit testing framework
an entry in the targets
list of the project's fuzzbuzz.yaml
, which describes how to run the target, and defines the type of errors to look for
To fuzz code written in C, create a new file with the following method:
target.cint FuzzerEntrypoint(const uint8_t *Data, size_t Size) {// Step 1: read Data into desired format// Step 2: run your methods/code with the test data// Step 3: check for errors, and abort if errors are found// return -1 if the Data is irrelevant or invalid}
You can use assert to check for errors as you would in a unit test - Fuzzbuzz will pick up failed assertions as bugs.
To fuzz code written in C++, create a new file with the following method:
target.cppextern "C" int FuzzerEntrypoint(const uint8_t *Data, size_t Size) {// Step 1: read Data into desired format// Step 2: run your methods/code with the test data// Step 3: check for errors, and abort if errors are found// return -1 if the Data is irrelevant or invalid}
You can use assert to check for errors as you would in a unit test - Fuzzbuzz will pick up failed assertions as bugs.
To fuzz code written in Golang, include the following method in your package:
target.gofunc FuzzerEntrypoint(Data []byte) int {// Step 1: read Data into desired format// Step 2: run your methods/code with the test data// Step 3: check for errors, and abort if errors are found// return -1 if the Data is irrelevant or invalid}
Use panics to alert on bugs - Fuzzbuzz will pick up these failures.
To fuzz code written in Python, include the following method in your package:
target.pydef FuzzerEntrypoint(Data): # Data is a buffer of bytes# Step 1: read Data into desired format# Step 2: run your methods/code with the test data# Step 3: check for errors, and abort if errors are found# return -1 if the Data is irrelevant or invalid
You can use Python's assert statement to check for errors as you would in a unit test - Fuzzbuzz will pick up these failures.
Fuzzbuzz can fuzz entire binaries compiled with C or C++, that read data from files, stdin, or sockets. Check the Configuration Section to learn how to fuzz these.
This method should take the test case defined in the array Data
and convert it into the desired test data - for example, if the code or methods you wish to test take 2 integers as input, parse 2 integers from the array of bytes. This interface aims to be as flexible as possible - you can parse any data type from these bytes, populate structs or objects, and generate very complex test structures. If the array of bytes isn't long enough to populate your desired structures, return -1 right away. The fuzzing engine is a quick learner, and will realize more data is required!
This section provides a descriptive overview of fuzzbuzz.yaml
configuration. For full, detailed documentation check out the Configuration Reference.
Every target needs an entry in the targets
list of the project's fuzzbuzz.yaml
:
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedlanguage: ctargets:- name: my-target # this name should be unique within the projectenvironment: # environment specific for this target- VAR=valuesetup: # setup steps specific for this target- make my-targetcorpus: my-target/corpus # a directory containing initial test casesharness: # special language-specific configuration
The name
field is compulsory, and the setup
steps should be used to install needed dependencies. For languages like C and C++, the setup
steps should also be used to compile the target binaries.
The corpus
directory should contain a list of files, each with an input to the Test Method that does not produce in a bug. This field is optional, but examples of tests that pass gives Fuzzbuzz an idea of what a good input looks like, and can make finding new code paths more efficient.
Finally, the harness
field tells Fuzzbuzz how to run the Test Method. This entry requires certain fields depending on the specific language of the target, as described below:
To fuzz C code, compile the file containing FuzzerEntrypoint
along with all other required files and libraries, using the FUZZ_CC
and CFLAGS
environment variables.
For example, if FuzzerEntrypoint
is implemented in my_target.c
and calls a method in my_api.h
:
$FUZZ_CC $CFLAGS my_api.h my_target.c -c
Finally, to compile into a full binary, link with FUZZ_ENGINE
, which provides a main
method as well as the necessary feedback for Fuzzbuzz, using the C++ compiler:
$FUZZ_CXX $CXXFLAGS my_target.o $FUZZ_ENGINE -o ./target
Even for code written in C, remember to link with FUZZ_ENGINE
using the C++ compiler FUZZ_CXX
This is an example of all the above steps combined to fully configure a target written in C:
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedlanguage: ctargets:- name: my-targetenvironment:# you can specify your own CFLAGS/CXXFLAGS, just remember to# use the fuzzbuzz-provided defaults as well- CFLAGS="$CFLAGS -g"setup:- $FUZZ_CC $CFLAGS my_api.h my_target.c -c- $FUZZ_CXX $CXXFLAGS my_target.o $FUZZ_ENGINE -o ./targetcorpus: ./my_target/corpusharness:binary: ./target
To fuzz C++ code, compile the file containing FuzzerEntrypoint
along with all other required files and libraries, using the FUZZ_CXX
and CXXFLAGS
environment variables.
For example, if FuzzerEntrypoint
is implemented in my_target.cpp
and calls a method in my_api.h
:
$FUZZ_CXX $CXXFLAGS my_api.h my_target.cpp -c
Finally, to compile into a full binary, link with FUZZ_ENGINE
, which provides a main
method as well as the necessary feedback for Fuzzbuzz:
$FUZZ_CXX $CXXFLAGS my_target.o $FUZZ_ENGINE -o ./target
This is an example of all the above steps combined to fully configure a target written in C++:
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedlanguage: c++targets:- name: my-targetenvironment:# you can specify your own CFLAGS/CXXFLAGS, just remember to# use the fuzzbuzz-provided defaults as well- CXXFLAGS="$CXXFLAGS -g"setup:- $FUZZ_CXX $CXXFLAGS my_api.h my_target.cpp -c- $FUZZ_CXX $CXXFLAGS my_target.o $FUZZ_ENGINE -o ./targetcorpus: ./my_target/corpusharness:binary: ./target
To fuzz Go code, use the setup
steps to install all the needed dependencies. Use the checkout
field to specify where in the Gopath your code should be placed. This can be set at the root of the fuzzbuzz.yaml
and then overridden for a specific target if needed. Then, specify the package and method to fuzz in the harness
field.
This is an example of the configuration of a target written in Go:
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedlanguage: goversion: "1.11"# checkout specifies where to check your code out# this repository will be placed in the directory:# ~/go/src/github.com/x/ycheckout: github.com/x/ytargets:- name: my-targetsetup:- dep ensure # make sure all dependencies are installedcorpus: ./my_target/corpusharness:# Go targets are flexible - your method doesn't need to# be named FuzzerEntrypointfunction: FuzzerEntrypoint# build tags are optionalbuild_tags: tag1 tag2 tag3# package specifies the package to import the# desired function frompackage: github.com/x/y/z/a/b/c
To fuzz Python code, use the setup
steps to install all the needed dependencies. Use the file
field to specify the Python file that contains the test harness. Then, specify the function to fuzz in the function
field.
This is an example of the configuration of a target written in Go:
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedlanguage: pythonversion: "3.6"setup:- pip3 install -r requirements.txttargets:- name: my-targetharness:# Python targets are flexible - your method doesn't need to# be named FuzzerEntrypointfunction: FuzzerEntrypointfile: tests/fuzz_test_file.py
To fuzz binaries written in C or C++, compile them using the following environment variables:
FUZZ_STANDALONE_CC
and CFLAGS
FUZZ_STANDALONE_CXX
and CXXFLAGS
These compilers ensure that Fuzzbuzz gets the feedback it needs to provide information on code coverage and more complex memory corruption bugs.
Then, in the harness
field, specify whether the binary takes input via stdin
, a network socket
, or from a file
. If the binary takes input from a file, mark the location in the binary's command line where the input file should be placed with a @@
. This will be replaced automatically when fuzzing.
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedtargets:- name: my-targetlanguage: c++environment:# you can specify your own CFLAGS/CXXFLAGS, just remember to# use the fuzzbuzz-provided defaults as well- CXXFLAGS="$CXXFLAGS -g"setup:- $FUZZ_STANDALONE_CXX $CXXFLAGS my_binary.cpp -o ./targetcorpus: ./my_target/corpusharness:binary: ./target @@# input can be one of: stdin, file, socket# currently socket is experimental, and is not available# on the main platforminput: file
You're ready to go! Push your project to Fuzzbuzz and it will detect your targets automatically. Check out the Fuzzing Jobs page to learn how to fuzz your targets on the platform, or keep reading below to learn how Advanced Configuration options can help you get the most out of your code.
Fuzzbuzz provides features that allow you to monitor your target for extreme memory usage, tests that take too long to run, and memory bugs (in certain languages).
You can specify a memory limit (in Megabytes) in your target configuration, and Fuzzbuzz will report any test cases that cause your target to use more memory than the limit.
Usage:
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedtargets:# ---- rest of target config omittedmemory_limit: '1000' # in megabytes
You can specify a timeout (in milliseconds) in your target configuration, and Fuzzbuzz will report any test cases that take longer than the timeout threshold to process.
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedtargets:# ---- rest of target config omittedtimeout: '500' # in milliseconds
Fuzzbuzz exposes the use of sanitizers for C and C++ binaries - these sanitizers monitor your code for certain memory bugs, including buffer overflows and potentially dangerous memory usage.
Currently Fuzzbuzz supports Address Sanitizer. More sanitizers will be provided in the future.
fuzzbuzz.yaml# ---- base, global setup, and global environment omittedtargets:# ---- rest of target config omittedsanitizers:# you can specify custom sanitizer options hereaddress: detect_stack_use_after_return=1:debug=1 # can be left blank
You can learn more about configuring your targets in the Configuration Section.