-
-
Notifications
You must be signed in to change notification settings - Fork 330
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Tcp manager, initial commit * no tokio by default * Allow Any broker type * Add tcp_manager example * fix CI
- Loading branch information
Showing
15 changed files
with
1,892 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
libpng-* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[package] | ||
name = "libfuzzer_libpng_tcp_manager" | ||
version = "0.10.1" | ||
authors = ["Andrea Fioraldi <[email protected]>", "Dominik Maier <[email protected]>"] | ||
edition = "2021" | ||
|
||
[features] | ||
default = ["std"] | ||
std = [] | ||
# Forces a crash | ||
crash = [] | ||
|
||
[profile.release] | ||
lto = true | ||
codegen-units = 1 | ||
opt-level = 3 | ||
debug = true | ||
|
||
[build-dependencies] | ||
cc = { version = "1.0", features = ["parallel"] } | ||
which = { version = "4.0.2" } | ||
|
||
[dependencies] | ||
libafl = { path = "../../libafl/", features = ["default", "tcp_manager"] } | ||
# libafl = { path = "../../libafl/", features = ["default"] } | ||
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer", "sancov_cmplog"] } | ||
# TODO Include it only when building cc | ||
libafl_cc = { path = "../../libafl_cc/" } | ||
mimalloc = { version = "*", default-features = false } | ||
|
||
[lib] | ||
name = "libfuzzer_libpng" | ||
crate-type = ["staticlib"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
# Variables | ||
[env] | ||
FUZZER_NAME='fuzzer_libpng' | ||
PROJECT_DIR = { script = ["pwd"] } | ||
CARGO_TARGET_DIR = { value = "${PROJECT_DIR}/target", condition = { env_not_set = ["CARGO_TARGET_DIR"] } } | ||
LIBAFL_CC = '${CARGO_TARGET_DIR}/release/libafl_cc' | ||
LIBAFL_CXX = '${CARGO_TARGET_DIR}/release/libafl_cxx' | ||
FUZZER = '${CARGO_TARGET_DIR}/release/${FUZZER_NAME}' | ||
|
||
[tasks.unsupported] | ||
script_runner="@shell" | ||
script=''' | ||
echo "Cargo-make not integrated yet on this" | ||
''' | ||
|
||
# libpng | ||
[tasks.libpng] | ||
linux_alias = "libpng_unix" | ||
mac_alias = "libpng_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.libpng_unix] | ||
condition = { files_not_exist = ["./libpng-1.6.37"]} | ||
script_runner="@shell" | ||
script=''' | ||
curl https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz --output libpng-1.6.37.tar.xz | ||
tar -xvf libpng-1.6.37.tar.xz | ||
''' | ||
|
||
# Compilers | ||
[tasks.cxx] | ||
linux_alias = "cxx_unix" | ||
mac_alias = "cxx_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.cxx_unix] | ||
command = "cargo" | ||
args = ["build" , "--release"] | ||
|
||
[tasks.cc] | ||
linux_alias = "cc_unix" | ||
mac_alias = "cc_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.cc_unix] | ||
command = "cargo" | ||
args = ["build" , "--release"] | ||
|
||
[tasks.crash_cxx] | ||
linux_alias = "crash_cxx_unix" | ||
mac_alias = "crash_cxx_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.crash_cxx_unix] | ||
command = "cargo" | ||
args = ["build" , "--release", "--features=crash"] | ||
|
||
[tasks.crash_cc] | ||
linux_alias = "crash_cc_unix" | ||
mac_alias = "crash_cc_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.crash_cc_unix] | ||
command = "cargo" | ||
args = ["build" , "--release", "--features=crash"] | ||
|
||
# Library | ||
[tasks.lib] | ||
linux_alias = "lib_unix" | ||
mac_alias = "lib_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.lib_unix] | ||
script_runner="@shell" | ||
script=''' | ||
cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes | ||
cd "${PROJECT_DIR}" | ||
make -C libpng-1.6.37 CC="${CARGO_TARGET_DIR}/release/libafl_cc" CXX="${CARGO_TARGET_DIR}/release/libafl_cxx" | ||
''' | ||
dependencies = [ "libpng", "cxx", "cc" ] | ||
|
||
# Library | ||
[tasks.crash_lib] | ||
linux_alias = "crash_lib_unix" | ||
mac_alias = "crash_lib_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.crash_lib_unix] | ||
script_runner="@shell" | ||
script=''' | ||
cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes | ||
cd "${PROJECT_DIR}" | ||
make -C libpng-1.6.37 CC="${CARGO_TARGET_DIR}/release/libafl_cc" CXX="${CARGO_TARGET_DIR}/release/libafl_cxx" | ||
''' | ||
dependencies = [ "libpng", "crash_cxx", "crash_cc" ] | ||
|
||
# Harness | ||
[tasks.fuzzer] | ||
linux_alias = "fuzzer_unix" | ||
mac_alias = "fuzzer_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.fuzzer_unix] | ||
command = "${CARGO_TARGET_DIR}/release/libafl_cxx" | ||
args = ["${PROJECT_DIR}/harness.cc", "${PROJECT_DIR}/libpng-1.6.37/.libs/libpng16.a", "-I", "${PROJECT_DIR}/libpng-1.6.37/", "-o", "${FUZZER_NAME}", "-lm", "-lz"] | ||
dependencies = [ "lib", "cxx", "cc" ] | ||
|
||
# Crashing Harness | ||
[tasks.fuzzer_crash] | ||
linux_alias = "fuzzer_crash_unix" | ||
mac_alias = "fuzzer_crash_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.fuzzer_crash_unix] | ||
command = "${CARGO_TARGET_DIR}/release/libafl_cxx" | ||
args = ["${PROJECT_DIR}/harness.cc", "${PROJECT_DIR}/libpng-1.6.37/.libs/libpng16.a", "-I", "${PROJECT_DIR}/libpng-1.6.37/", "-o", "${FUZZER_NAME}_crash", "-lm", "-lz"] | ||
dependencies = [ "crash_lib", "crash_cxx", "crash_cc" ] | ||
|
||
# Run the fuzzer | ||
[tasks.run] | ||
linux_alias = "run_unix" | ||
mac_alias = "run_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.run_unix] | ||
script_runner = "@shell" | ||
script=''' | ||
./${FUZZER_NAME} & | ||
sleep 0.2 | ||
./${FUZZER_NAME} 2>/dev/null | ||
''' | ||
dependencies = [ "fuzzer" ] | ||
|
||
|
||
# Run the fuzzer with a crash | ||
[tasks.crash] | ||
linux_alias = "crash_unix" | ||
mac_alias = "crash_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.crash_unix] | ||
script_runner = "@shell" | ||
script=''' | ||
./${FUZZER_NAME}_crash & | ||
sleep 0.2 | ||
./${FUZZER_NAME}_crash 2>/dev/null | ||
''' | ||
dependencies = [ "fuzzer_crash" ] | ||
|
||
|
||
|
||
# Test | ||
[tasks.test] | ||
linux_alias = "test_unix" | ||
mac_alias = "test_mac" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.test_unix] | ||
script_runner = "@shell" | ||
script=''' | ||
rm -rf libafl_unix_shmem_server || true | ||
(timeout 11s ./${FUZZER_NAME} >fuzz_stdout.log 2>/dev/null || true) & | ||
sleep 0.2 | ||
timeout 10s ./${FUZZER_NAME} >/dev/null 2>/dev/null || true | ||
if [ -z "$(grep "corpus: 30" fuzz_stdout.log)" ]; then | ||
echo "Fuzzer does not generate any testcases or any crashes" | ||
exit 1 | ||
else | ||
echo "Fuzzer is working" | ||
fi | ||
''' | ||
dependencies = [ "fuzzer" ] | ||
|
||
[tasks.test_mac] | ||
script_runner = "@shell" | ||
script=''' | ||
rm -rf libafl_unix_shmem_server || true | ||
(timeout 11s ./${FUZZER_NAME} >fuzz_stdout.log 2>/dev/null || true) & | ||
sleep 0.2 | ||
timeout 10s ./${FUZZER_NAME} >/dev/null 2>/dev/null || true | ||
''' | ||
dependencies = [ "fuzzer" ] | ||
|
||
# Clean up | ||
[tasks.clean] | ||
linux_alias = "clean_unix" | ||
mac_alias = "clean_unix" | ||
windows_alias = "unsupported" | ||
|
||
[tasks.clean_unix] | ||
# Disable default `clean` definition | ||
clear = true | ||
script_runner="@shell" | ||
script=''' | ||
rm -f ./${FUZZER_NAME} | ||
make -C libpng-1.6.37 clean | ||
cargo clean | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# Libfuzzer for libpng | ||
|
||
This folder contains an example fuzzer for libpng, using LLMP for fast multi-process fuzzing and crash detection. | ||
|
||
In contrast to other fuzzer examples, this setup uses `fuzz_loop_for`, to occasionally respawn the fuzzer executor. | ||
While this costs performance, it can be useful for targets with memory leaks or other instabilities. | ||
If your target is really instable, however, consider exchanging the `InProcessExecutor` for a `ForkserverExecutor` instead. | ||
|
||
It also uses the `introspection` feature, printing fuzzer stats during execution. | ||
|
||
To show off crash detection, we added a `ud2` instruction to the harness, edit harness.cc if you want a non-crashing example. | ||
It has been tested on Linux. | ||
|
||
## Build | ||
|
||
To build this example, run | ||
|
||
```bash | ||
cargo build --release | ||
``` | ||
|
||
This will build the library with the fuzzer (src/lib.rs) with the libfuzzer compatibility layer and the SanitizerCoverage runtime functions for coverage feedback. | ||
In addition, it will also build two C and C++ compiler wrappers (bin/libafl_c(libafl_c/xx).rs) that you must use to compile the target. | ||
|
||
The compiler wrappers, `libafl_cc` and `libafl_cxx`, will end up in `./target/release/` (or `./target/debug`, in case you did not build with the `--release` flag). | ||
|
||
Then download libpng, and unpack the archive: | ||
```bash | ||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz | ||
tar -xvf libpng-1.6.37.tar.xz | ||
``` | ||
|
||
Now compile libpng, using the libafl_cc compiler wrapper: | ||
|
||
```bash | ||
cd libpng-1.6.37 | ||
./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes | ||
make CC="$(pwd)/../target/release/libafl_cc" CXX="$(pwd)/../target/release/libafl_cxx" -j `nproc` | ||
``` | ||
|
||
You can find the static lib at `libpng-1.6.37/.libs/libpng16.a`. | ||
|
||
Now, we have to build the libfuzzer harness and link all together to create our fuzzer binary. | ||
|
||
``` | ||
cd .. | ||
./target/release/libafl_cxx ./harness.cc libpng-1.6.37/.libs/libpng16.a -I libpng-1.6.37/ -o fuzzer_libpng -lz -lm | ||
``` | ||
|
||
Afterward, the fuzzer will be ready to run. | ||
Note that, unless you use the `launcher`, you will have to run the binary multiple times to actually start the fuzz process, see `Run` in the following. | ||
This allows you to run multiple different builds of the same fuzzer alongside, for example, with and without ASAN (`-fsanitize=address`) or with different mutators. | ||
|
||
## Run | ||
|
||
The first time you run the binary, the broker will open a tcp port (currently on port `1337`), waiting for fuzzer clients to connect. This port is local and only used for the initial handshake. All further communication happens via shared map, to be independent of the kernel. Currently, you must run the clients from the libfuzzer_libpng directory for them to be able to access the PNG corpus. | ||
|
||
``` | ||
./fuzzer_libpng | ||
[libafl/src/bolts/llmp.rs:407] "We're the broker" = "We\'re the broker" | ||
Doing broker things. Run this tool again to start fuzzing in a client. | ||
``` | ||
|
||
And after running the above again in a separate terminal: | ||
|
||
``` | ||
[libafl/src/bolts/llmp.rs:1464] "New connection" = "New connection" | ||
[libafl/src/bolts/llmp.rs:1464] addr = 127.0.0.1:33500 | ||
[libafl/src/bolts/llmp.rs:1464] stream.peer_addr().unwrap() = 127.0.0.1:33500 | ||
[LOG Debug]: Loaded 4 initial testcases. | ||
[New Testcase #2] clients: 3, corpus: 6, objectives: 0, executions: 5, exec/sec: 0 | ||
< fuzzing stats > | ||
``` | ||
|
||
As this example uses in-process fuzzing, we added a Restarting Event Manager (`setup_restarting_mgr`). | ||
This means each client will start itself again to listen for crashes and timeouts. | ||
By restarting the actual fuzzer, it can recover from these exit conditions. | ||
|
||
In any real-world scenario, you should use `taskset` to pin each client to an empty CPU core, the lib does not pick an empty core automatically (yet). | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.