LibAFL, the fuzzer library.
Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust.
LibAFL is written and maintained by
- Andrea Fioraldi andrea@aflplus.plus
- Dominik Maier dominik@aflplus.plus
- s1341 github@shmarya.net
- Dongjia Zhang toka@aflplus.plus
Why LibAFL?
LibAFL gives you many of the benefits of an off-the-shelf fuzzer, while being completely customizable. Some highlight features currently include:
fast
: We do everything we can at compile time, keeping runtime overhead minimal. Users reach 120k execs/sec in frida-mode on a phone (using all cores).scalable
:Low Level Message Passing
,LLMP
for short, allows LibAFL to scale almost linearly over cores, and via TCP to multiple machines.adaptable
: You can replace each part of LibAFL. For example,BytesInput
is just one potential form input: feel free to add an AST-based input for structured fuzzing, and more.multi platform
: LibAFL was confirmed to work on Windows, MacOS, Linux, and Android on x86_64 and aarch64.LibAFL
can be built inno_std
mode to inject LibAFL into obscure targets like embedded devices and hypervisors.bring your own target
: We support binary-only modes, like Frida-Mode, as well as multiple compilation passes for sourced-based instrumentation. Of course it's easy to add custom instrumentation backends.
Overview
LibAFL is a collection of reusable pieces of fuzzers, written in Rust. It is fast, multi-platform, no_std compatible, and scales over cores and machines.
It offers a main crate that provide building blocks for custom fuzzers, libafl, a library containing common code that can be used for targets instrumentation, libafl_targets, and a library providing facilities to wrap compilers, libafl_cc.
LibAFL offers integrations with popular instrumentation frameworks. At the moment, the supported backends are:
- SanitizerCoverage, in libafl_targets
- Frida, in libafl_frida
- QEMU user-mode, in libafl_qemu
Getting started
- Install the Dependecies
-
The Rust development language.
We highly recommend not to use e.g. your Linux distribition package as this is likely outdated. So rather install Rust directly, instructions can be found here. -
LLVM tools
The LLVM tools are needed (newer than LLVM 11.0.0 but older than LLVM 15.0.0) -
Cargo-make
We use cargo-make to build the fuzzers infuzzers/
directory. You can install it with
cargo install cargo-make
- Clone the LibAFL repository with
git clone https://github.com/AFLplusplus/LibAFL
- Build the library using
cargo build --release
- Build the API documentation with
cargo doc
- Browse the LibAFL book (WIP!) with (requires mdbook)
cd docs && mdbook serve
We collect all example fuzzers in ./fuzzers
.
Be sure to read their documentation (and source), this is the natural way to get started!
The best-tested fuzzer is ./fuzzers/libfuzzer_libpng
, a multicore libfuzzer-like fuzzer using LibAFL for a libpng harness.
Resources
-
Our RC3 talk explaining the core concepts
-
Our Fuzzcon Europe talk with a (a bit but not so much outdated) step-by-step discussion on how to build some example fuzzers
-
The Fuzzing101 solutions & series of blog posts by epi
Contributing
For bugs, feel free to open issues or contact us directly. Thank you for your support. <3
Even though we will gladly assist you in finishing up your PR, try to
- keep all the crates compiling with stable rust (hide the eventual non-stable code under
cfg
s) - run
cargo fmt
on your code before pushing - check the output of
cargo clippy --all
or./clippy.sh
- run
cargo build --no-default-features
to check forno_std
compatibility (and possibly add#[cfg(feature = "std")]
) to hide parts of your code.
Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help.