A Move source code level fuzzer.
# Rebuild is necessary for using your uid
make build-docker
# The run script will run commands in the docker container
./run make
If you have Rust and cargo installed locally, you can simply run make
.
The fuzz targets lives in fuzz/fuzz_targets
:
Target | Oracle | Fuzzing Engine |
---|---|---|
v1v2.rs |
Compiler V1 vs. V2 | libFuzzer |
opt_noopt.rs |
Optimization On vs. Off | libFuzzer |
hfuzz_v1v2.rs |
Compiler V1 vs. V2 | honggfuzz |
afl_v1v2.rs |
Compiler V1 vs. V2 | afl++ |
random.rs |
Compiler V1 vs. V2 | Pure random input |
./scripts/fuzz.sh <fuzz_target> [total_hour] [jobs] [max_input_len] [timeout]
# For example
./scripts/fuzz.sh v1v2 24 32 4 3
# This will run the `v1v2` target for 24 hours using 32 cores,
# with randomly created seeds whose size doesn't exceed 4KB.
# For each input, it will timeout after 3 seconds.
# If a fuzz target starts with `afl++`, the script will spawn nodes in a tmux session:
./scripts/fuzz.sh afl-v1v2 24
# This will create a tmux session `afl_fuzzing` where each node occupies a window.
The script will keep a copy of log under logs
.
Note that the script will automatically spawn tmux sessions for running AFL++
fuzzing sessions so be careful using AFL inside a tmux session.
For libFuzzer, crashing inputs are stored in fuzz/artifacts/<fuzz_target>
.
For AFL++, they are stored in fuzz/afl/<fuzz_target>_out/fuzzer#/crashes
.
After running a fuzzing session, the coverage of all stored corpus can be generated by:
./scripts/coverage.sh <fuzz_target> [base_dir]
If the fuzzing session was run on the local machine, you can ignore base_dir
.
If you want to generate the coverage from a different corpus (e.g. generated from another machine),
use the base_dir
to specify the directory that contains fuzz/
where corpus
is stored for libFuzzer,
or afl
is stored for AFL++.
This will create an HTML report at [base_dir/]coverage/<fuzz_target>/index.html
.
For libFuzzer results, you can use the scipts/coverage_graph.py
to draw a coverage over time graph:
python scripts/coverage_graph.py path/to/log
MoveSmith depend on the following crates for fuzzing:
cargo install cargo-fuzz
cargo install cargo-afl
cargo install cargo-binutils
cargo install honggfuzz
To generate human-readable coverage reports, we need llvm
coverage tools.
They can be installed with:
cargo install cargo-binutils
rustup component add --toolchain nightly llvm-tools-preview
We also need a demangler installed:
cargo install rustfilt
To run AFL++ targets, you need to install [cargo-afl][cargo-afl]:
cargo install cargo-afl
To plot AFL++ statistics, you might need to install gnuplot
:
brew install gnuplot
To view AFL++ coverage over time, you can use
cargo afl plot fuzz/afl/<fuzz_target>_out/fuzzer0 <ouput_dir>
to plot several key statistics.
They can be viewed at <output_dir>/index.html
.
.
├── enuminto // Helper crate
├── framework // The core generation framework
├── fuzz
│ └── fuzz_targets // All the fuzz targets
├── msmith // The Move generators, states, and peripherals
│ └── src
│ ├── cli // The `msmith` command line tool
│ ├── codegen // Turn MoveAST to text format Move code
│ ├── execution // Execution engine using transactional test
│ ├── generators // Move generators
│ └── states // Move states
└── scripts // Helper scripts for running fuzzing and collecting coverage