-
Notifications
You must be signed in to change notification settings - Fork 11
How to use Maxfuzz
This guide assumes you have Docker, docker-compose and make installed. For more on getting set up, please check out our Development Environment Setup wiki page
First, build the base Maxfuzz Docker image: make build
Then spin up a local instance of Maxfuzz, running some sample fuzzers: make deploy-dev
This launches a basic fuzzer that fuzzes some vulnerable C code, which can be found in ./fuzzers/vulnerable/
.
Upon deploying the fuzzer locally you should see some crashes appear fairly quickly in ./sync/afl-vulnerable/crashes/
.
As these crashers are uncovered by AFL, you should see corresponding logs from the Docker containers in the docker-compose view.
-
run
ruby new_fuzzer.rb <go|afl> <new_fuzzer_name>
-
Follow the instructions in
<new_fuzzer_name>/README.md
Take a look at ./fuzzers/vulnerable/
for an example.
Each AFL fuzzer definition consists of three key components:
-
Test harness: this file should include the library you wish to test, receive input appropriately, and then call the desired methods to fuzz. For an example of a simple harness that takes input and passes it to an imported method, take a look at
asan-opencv-2/harness.cpp
, a basic test harness that passes input to OpenCV'simdecode
method. -
Compilation instructions: defined in
build_steps
andenvironment
, these instructions describe how to compile and link the test harness with the libraries necessary. Dependencies can either be included in the repository, or downloaded at runtime viabuild_steps
if they come from a trusted source. -
Example inputs: AFL works best with a small selection of valid input files from which to begin it's fuzz generation. Ensure that these input files are as small as possible, don't cause your code to crash, and that they produce varied results (i.e. don't provide files that will take the same path through the code). Place them in the
examples
directory.
For details on how to write these files, check out the Fuzzer Reference page.
Take a look at ./fuzzers/go-ethereum
for an example.
Each Gofuzz fuzzer definition consists of two key components:
-
Gofuzz zip file: the zip file compiled by
go-fuzz-build
. -
Run instructions: defined in
build_steps
andenvironment
. For gofuzz, thebuild_steps
file remains empty. The only required addition is setting theGO_FUZZ_ZIP
variable inenvironment
.
For more details, check out the Fuzzer Reference page.
To spin up a local instance of Maxfuzz from the latest stable release, running some sample fuzzers (found in ./fuzzers/
): make deploy-stable
First, build the base Maxfuzz Docker image: make build
Then spin up a local instance of Maxfuzz, running some sample fuzzers (found in ./fuzzers/
): make deploy-dev
To ensure everything is cleaned up: make teardown
Since everything is self-contained in a Docker Container, deploying a fuzzer is as simple as spinning up a VM using Amazon ECS (or equivalent) - just be sure to send all crashes to an S3 Bucket, so they're not lost when you restart your VM.
Maxfuzz currently has two components to it: fuzzers and reproducers.
For Gofuzz, you only need to deploy a fuzzer (by starting up a Docker container that runs the command /root/fuzzer-files/<your fuzzer name>/start
). Since Gofuzz automatically saves command output, nothing else is necessary.
For AFL, you must deploy both a fuzzer and a reproducer to take full advantage of Maxfuzz. The reproducer takes the inputs that have been found to crash the code, and re-runs the code against these inputs to save the stacktrace and output. Start the fuzzer with /root/fuzzer-files/<your fuzzer name>/start
and the reproducer with /root/fuzzer-files/<your fuzzer name>/start reproduce
, each in their own container.
The two boxes talk via a Redis instance. You can see an example of this configuration in /docker-compose-dev.yml
, and read more about configuring this Redis connection in the Environment Variables section further down.
Running make deploy-(stable|dev)
with the default docker-compose configuration launches a basic fuzzer that fuzzes some vulnerable C code, which can be found in /fuzzers/vulnerable/
.
Upon deploying the fuzzer locally you should see some crashes appear fairly quickly under /sync/afl-vulnerable/crashes/
. These will appear in the form of files containing the input that crashes the code, along with .output
files that show you the corresponding stacktrace.
As these crashers are uncovered by fuzzers, you should see corresponding logs from the Docker containers in the docker-compose view, as Maxfuzz uncovers bugs and passes them to the reproduction box to save their stacktrace.
When crashes are found, they are sent either to the local sync directory (when S3 Syncing is turned off), or to the specified AWS S3 Bucket (when configured to do so - see the next section on Environment Variables).
The filenames are formatted as follows:
<fuzzer instance name>_<afl/gofuzz-generated filename>_<time of crash>_<current git SHA>(.output)
Where files without .output
contain the actual input that produces a bug, with the .output
file containing the stacktrace and output as a result of the crash.
Maxfuzz has the following environment variables for configuration:
File management:
-
MAXFUZZ_ENABLE_S3
:0
to save crashes to/root/sync
in the Docker container (which can then be volumed out to save to local filesystem), or1
to save crashes & backups to S3 -
AWS_ACCESS_KEY_ID
: ID for AWS key - used to talk to S3 -
AWS_SECRET_ACCESS_KEY
: Secret AWS key - used to talk to S3 -
CRASH_BUCKET
: S3 bucket name -
AWS_REGION
: defaults tous-east-1
Other:
-
REDIS_QUEUE_URL
: URL for a redis queue, used to transmit data about crash reproduction between fuzzer container and reproduction container -
MAXFUZZ_ENV
: set totest
to stub out actual Amazon S3 method calls, and stub out redis calls - used when running unit tests -
NO_REPRODUCTION
:1
to not attempt to reproduce AFL crashes. Can be used in testing to turn off extra functionality