Differential Fuzzing of Bitcoin implementations and libraries. Note this project is a WIP and might be not stable.
-
To support the flags used in some modules
-fsanitize=address,fuzzer -std=c++20
the minimum clang version required is 10.0 -
For macOS the llvm tools are installed by default, just check that you have the minimum required version 10.0
-
If not installed or lesser than 10.0 just run:
brew install llvm
-
-
For ubuntu/debian it can be installed using the package manager:
sudo apt install clang lld llvm-dev
-
To install it from source check clang_get_started. You must build it with this cmake option:
-DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt"
You can build the modules in two ways: manual or automatic. The automatic method is provided by the auto_build.sh
script, which simplifies the build and clean processes. Additionally, you can use Docker or Docker Compose to run the application without installing dependencies directly on your machine.
The auto_build.sh
script allows you to automatically build the modules based on the flags defined in CXXFLAGS
. It also provides options to clean the builds before compiling.
-
Automatic Build:
- To automatically build the modules, define the flags in
CXXFLAGS
and run the script:This will automatically build theCXXFLAGS="-DLDK -DLND" ./auto_build.sh
LDK
andLND
modules.
- To automatically build the modules, define the flags in
-
Automatic Clean:
- The script supports three cleaning modes before building:
- Full Clean: Cleans all modules before building the selected ones.
CLEAN_BUILD="FULL" CXXFLAGS="-DLDK -DLND" ./auto_build.sh
- Clean: Cleans only the modules that will be built based on
CXXFLAGS
.CLEAN_BUILD="CLEAN" CXXFLAGS="-DLDK -DLND" ./auto_build.sh
- Select Clean: Cleans specific modules defined in
CLEAN_BUILD
, regardless ofCXXFLAGS
.In this case, the script will runCLEAN_BUILD="-DLDK -DBTCD" CXXFLAGS="-DLDK -DLND" ./auto_build.sh
make clean
forLDK
andBTCD
, but will only build the modules defined inCXXFLAGS
(LDK
andLND
).
- Full Clean: Cleans all modules before building the selected ones.
- The script supports three cleaning modes before building:
If you prefer not to install dependencies directly on your machine, you can use Docker to run the application. This method simplifies deployment and ensures a consistent environment.
-
Build the Docker Image:
- Build the Docker image using the provided
docker
:docker build -t bitcoinfuzz .
- Build the Docker image using the provided
-
Run the Container:
- Run the container with the required
FUZZ
andCXXFLAGS
environment variables:docker run -e FUZZ=target_name -e CXXFLAGS="-DLDK -DLND ..." bitcoinfuzz
- Run the container with the required
-
Optional Parameters:
- You can also pass optional parameters:
FUZZ_RUNS
: Specify the number of fuzzing runs (e.g., 50):docker run -e FUZZ=target_name -e CXXFLAGS="-DLDK -DLND ..." -e FUZZ_RUNS=50 bitcoinfuzz
FUZZ_INPUT
: Provide a specific corpus or crash file to test:docker run -e FUZZ=target_name -e CXXFLAGS="-DLDK -DLND ..." -e FUZZ_INPUT=/path/to/input bitcoinfuzz
- You can also pass optional parameters:
-
Accessing Generated Corpus:
- The generated corpus is saved in
/app/data
inside the container. To access it, you can mount a volume:docker run -e FUZZ=target_name -e CXXFLAGS="-DLDK -DLND ..." -v $(pwd)/corpus:/app/data bitcoinfuzz
- The generated corpus is saved in
The docker-compose.yml
file simplifies running multiple fuzzing scenarios. Each scenario is preconfigured with the required modules and environment variables.
-
Run All Scenarios:
- To run all scenarios, simply execute:
docker-compose up
- To run all scenarios, simply execute:
-
Run a Specific Scenario:
- To run a specific scenario (e.g.,
script
), use:docker-compose up script
- To run a specific scenario (e.g.,
-
Optional Parameters:
- You can pass optional parameters like
FUZZ_RUNS
orFUZZ_INPUT
:- Run with a specific number of fuzzing runs:
FUZZ_RUNS=50 docker-compose up script
- Run with a specific input file:
FUZZ_INPUT=/path/to/input docker-compose up script
- Run with a specific number of fuzzing runs:
- You can pass optional parameters like
-
Accessing Generated Corpus:
- The generated corpus for each scenario is saved in the
docker
directory at the same level as thedocker-compose.yml
file. Each scenario has its own subdirectory:docker/ ├── script/ ├── deserialize_block/ ├── script_eval/ ├── deserialize_offer/ ├── descriptor_parse/ ├── miniscript_parse/ ├── script_asm/ ├── deserialize_invoice/ ├── address_parse/ ├── addrv2/ └── psbt_parse/
- To ensure the corpus is saved locally, the
docker-compose.yml
file maps the/app/data
directory inside the container to the corresponding subdirectory indocker
.
- The generated corpus for each scenario is saved in the
If you prefer, you can still build the modules manually. Below are the steps for each module:
-
cd modules/rustbitcoin make cargo && make export CXXFLAGS="$CXXFLAGS -DRUST_BITCOIN"
-
cd modules/rustminiscript make cargo && make export CXXFLAGS="$CXXFLAGS -DRUST_MINISCRIPT"
-
cd modules/btcd make export CXXFLAGS="$CXXFLAGS -DBTCD"
-
To run the fuzzer with
embit
module, you need to install theembit
library.To install the
embit
library, you can use the following command:cd modules/embit pip install -r /requirements.txt
cd modules/embit make export CXXFLAGS="$CXXFLAGS -DEMBIT"
-
cd modules/bitcoin make export CXXFLAGS="$CXXFLAGS -DBITCOIN_CORE"
-
cd modules/ldk make cargo && make export CXXFLAGS="$CXXFLAGS -DLDK"
-
cd modules/lnd make export CXXFLAGS="$CXXFLAGS -DLND"
-
cd modules/nlightning make export CXXFLAGS="$CXXFLAGS -DNLIGHTNING"
-
pip install mako git submodule update --init --recursive external/lightning cd modules/clightning make export CXXFLAGS="$CXXFLAGS -DCLIGHTNING"
Once the modules are compiled, you can compile bitcoinfuzz
an execute it:
-
FUZZ=target_name ./bitcoinfuzz
-
make FUZZ=target_name ./bitcoinfuzz
- sipa/miniscript: sipa/miniscript#140
- rust-miniscript: rust-bitcoin/rust-miniscript#633
- rust-bitcoin: rust-bitcoin/rust-bitcoin#2681
- btcd: btcsuite/btcd#2195 (API mismatch with Bitcoin Core)
- Bitcoin Core: bitcoinfuzz#34
- rust-miniscript: rust-bitcoin/rust-miniscript#696 (not found but reproductive)
- rust-miniscript: bitcoinfuzz#39
- rust-bitcoin: rust-bitcoin/rust-bitcoin#2891
- rust-bitcoin: rust-bitcoin/rust-bitcoin#2879
- btcd: btcsuite/btcd#2199
- rust-bitcoin: bitcoinfuzz#57
- rust-miniscript: CVE-2024-44073
- rust-miniscript: rust-bitcoin/rust-miniscript#785
- rust-miniscript: rust-bitcoin/rust-miniscript#788
- LND: lightningnetwork/lnd#9591
- Embit: diybitcoinhardware/embit#70
- btcd: btcsuite/btcd#2351
- Core Lightning: ElementsProject/lightning#8219
- LND: lightningnetwork/lnd#9808
- Core Lightning: ElementsProject/lightning#8282
- btcd: btcsuite/btcd#2372
- bolts: lightning/bolts#1264
- rust-lightning: lightningdevkit/rust-lightning#3814
- LND: lightningnetwork/lnd#9904
- LND: lightningnetwork/lnd#9915
- Eclair: ACINQ/eclair#3104
- rust-bitcoin: rust-bitcoin/rust-bitcoin#4617