Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Unified Collaborative Fuzzing Platform (UCFP)

UCFP is a plugin-based framework for collaborative fuzzing: running several fuzzers on the same target at the same time and coordinating them. It is the implementation of the master's thesis A Unified Framework For Collaborative Fuzzing (Chi-Feng Tsai, National Taiwan University, 2025).

Collaborative fuzzing approaches such as EnFuzz, autofz and RcFuzz differ along two dimensions: how they share CPU time between fuzzers (resource allocation) and how they share seeds between fuzzers (seed synchronization). UCFP turns each part of such a system into a replaceable component, so that existing approaches can be reproduced and new ones built by combining or writing plugins:

Component Role Included
Fuzzer Runs one fuzzer in a Docker container; can be scaled, paused and given seeds afl, aflfast, aflplusplus, aflplusplus_cmplog, angora, fairfuzz, laf_intel, learnafl, mopt, qsym, radamsa
Evaluator Analyzes every new seed found by any fuzzer afl_coverage (edge coverage), basic_evaluation (crash, execution time, memory)
Global seed pool Stores every seed and its evaluation mongo (MongoDB)
Resource allocation policy Decides how many CPUs each fuzzer gets single_fuzzer, equal, round_robin, autofz_rsc_alloc, rcfz_rsc_alloc
Seed synchronization policy Decides which seeds are sent to which fuzzers no_sync, broadcast, autofz_seed_sync
Other Anything else, e.g. monitoring coverage_over_time, docker_stats

The thesis evaluates the overhead of running each of the 11 fuzzers through the framework (with single_fuzzer, no_sync, mongo, both evaluators, coverage_over_time and docker_stats) on jq, objdump and exiv2. The other policies are implemented and were used during development, but their fuzzing performance is not evaluated in the thesis. Run pdm run ucfp list to see every available component.

Requirements

  • Linux with Docker (the user running UCFP must be able to use Docker)
  • Python 3.10 or newer (developed and tested on Python 3.10.12) and PDM
  • sudo to prepare the system for fuzzing (fuzz-init.sh)
  • Enough disk space for the Docker images: each fuzzer gets its own image per target

Quick start: fuzz jq with AFL++

git clone <this repository> unified-collaborative-fuzzing-platform
cd unified-collaborative-fuzzing-platform
pdm install

# target programs from UniBench and initial seeds from UNIFUZZ
mkdir -p build && cd build
wget https://github.com/unifuzz/unibench/archive/refs/heads/master.zip
unzip master.zip && rm master.zip
cd unibench-master && unzip jq-1.5.zip && cd ../..
git clone https://github.com/unifuzz/seeds.git initialseed/seeds

# prepare the system (core dumps, CPU governor, ASLR, ...); undo with `sudo ./fuzz-restore.sh`
sudo ./fuzz-init.sh

pdm run ucfp build --config examples/jq-single.toml    # build the Docker images
pdm run ucfp fuzz --config examples/jq-single.toml     # fuzz for 10 minutes (Ctrl+C to stop early)
pdm run ucfp export --config examples/jq-single.toml -o results/jq-single   # seeds and crashes
pdm run ucfp cleanup --config examples/jq-single.toml --session --all       # remove the containers

All commands are run from the repository root: paths in the configuration files are relative to the current directory.

Usage

pdm run ucfp <command> --config <file> [options]
Command Description
build Build the Docker images of the components in the config (--force to rebuild, --all for every plugin)
fuzz Run a fuzzing session for fuzzing.timeout seconds
export -o <dir> Write the seeds (seeds/), crashing seeds (crashes/) and their evaluation (seeds.json) of a finished session
cleanup Remove the session's containers (--session) and/or the built images (--build), for --all components in the config or one --component-name
list List the available components and their dependencies (--config is optional)

python -m ucfp <command> works as well. Any configuration value can be overridden from the command line, which is convenient for scripting experiments:

pdm run ucfp fuzz --config examples/jq-round-robin.toml \
  --config-override-str fuzzing.session_name=jq-rr-2 \
  --config-override-int fuzzing.timeout=3600 \
  --config-override-eval 'fuzzing.components.fuzzer=["aflplusplus", "mopt"]'

The configuration is checked before anything is built or started, and all problems are reported at once (unknown components, components in the wrong place, missing dependencies, missing paths, ...).

Output

  • ucfp export writes the seeds of a session. Crashes are detected by the basic_evaluation evaluator, which runs every seed on the uninstrumented target.
  • coverage_over_time and docker_stats write JSON files and plots to their output.folder (the current directory by default).
  • Logs go to stdout, and also to a file if system.log_also_to_file = true.
  • With system.persistent = true, the containers (including the seed pool) are kept after the session ends, so it can be exported or inspected. They are replaced when the same session is run again, and removed by ucfp cleanup --session.

Preparing other targets

The example configs in examples/ cover the targets used in the thesis:

Target Source Seeds (initialseed/seeds/general_evaluation/)
jq-1.5 UniBench: build/unibench-master/jq-1.5 json
objdump (binutils-2.28) UniBench: build/unibench-master/binutils-2.28 obj
ffmpeg-4.0.1 UniBench: build/unibench-master/ffmpeg-4.0.1 (the build command applies an upstream patch and installs nasm) ffmpeg100
exiv2-0.27 UniBench's exiv2-0.26 does not build, so use the official release (below) jpg
# UniBench targets: extract the archive you need inside build/unibench-master
cd build/unibench-master && tar xf binutils-2.28.tar.gz && tar xf ffmpeg-4.0.1.tar.gz && cd ../..

# exiv2-0.27
cd build && wget https://github.com/Exiv2/exiv2/archive/refs/tags/0.27.tar.gz && tar xf 0.27.tar.gz && rm 0.27.tar.gz && cd ..

To fuzz another program, copy an example and change the [build] section: where the source code is, how to build it (build_command runs inside each fuzzer's image with CC/CXX set to the fuzzer's compilers), where the initial seeds are, and the command line to run (@@ is replaced by the input file). Angora cannot build ffmpeg, and library targets (is_library = true, libFuzzer harnesses) are not supported yet.

Documentation

Development

pdm run lint    # isort + black

There is no unit test suite. tests/ contains scripts that exercise real components and need Docker and built images, e.g. pdm run python -m tests.test_scale_order_and_ensure_alive.

Known issues

  • Pressing Ctrl+C while fuzzers are being scaled may raise an uncaught exception.
  • Sessions cannot be resumed: running a session again starts from scratch with new containers. Some fuzzers would also ignore their existing output when restarted.
  • The global seed pool records when a seed was first seen, but not which fuzzer found it.
  • Only a single machine is supported (communication.type = "single_machine").

Contributors

  • Chi-Feng Tsai: design and implementation of the framework and most plugins
  • s1imlix: the RcFuzz resource allocation policy (rsc_alloc_rcfuzz), the QSYM fuzzer (fuzzer_qsym) and the AFL++ CMPLOG fuzzer (fuzzer_aflplusplus_cmplog); literature survey, tool integration and running experiments for the thesis

Citation

If you use UCFP in your research, please cite the thesis:

@mastersthesis{tsai2025ucfp,
  author = {Tsai, Chi-Feng},
  title  = {A Unified Framework For Collaborative Fuzzing},
  school = {National Taiwan University},
  year   = {2025},
  doi    = {10.6342/NTU202503807}
}

License

MIT, see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages