Add tool detection to build.rs, improve README (#43)
Co-authored-by: Dominik Maier <domenukk@gmail.com>
This commit is contained in:
parent
f4d5c045b4
commit
24a033de31
@ -1,119 +1,138 @@
|
|||||||
// build.rs
|
// build.rs
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
path::Path,
|
path::Path,
|
||||||
process::{exit, Command},
|
process::{exit, Command},
|
||||||
};
|
};
|
||||||
|
|
||||||
const LIBPNG_URL: &str =
|
use which::which;
|
||||||
"https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz";
|
|
||||||
|
const LIBPNG_URL: &str =
|
||||||
fn main() {
|
"https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz";
|
||||||
if cfg!(windows) {
|
|
||||||
println!("cargo:warning=Skipping libpng frida example on Windows");
|
fn build_dep_check(tools: &[&str]) {
|
||||||
exit(0);
|
for tool in tools.into_iter() {
|
||||||
}
|
println!("Checking for build tool {}...", tool);
|
||||||
|
|
||||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
match which::which(tool) {
|
||||||
let cwd = env::current_dir().unwrap().to_string_lossy().to_string();
|
Ok(path) => println!("Found build tool {}", path.to_str().unwrap()),
|
||||||
let out_dir = out_dir.to_string_lossy().to_string();
|
Err(_) => {
|
||||||
let out_dir_path = Path::new(&out_dir);
|
println!("ERROR: missing build tool {}", tool);
|
||||||
std::fs::create_dir_all(&out_dir).expect(&format!("Failed to create {}", &out_dir));
|
exit(1);
|
||||||
|
}
|
||||||
println!("cargo:rerun-if-changed=../libfuzzer_runtime/rt.c",);
|
};
|
||||||
println!("cargo:rerun-if-changed=harness.cc");
|
}
|
||||||
|
}
|
||||||
let libpng = format!("{}/libpng-1.6.37", &out_dir);
|
|
||||||
let libpng_path = Path::new(&libpng);
|
|
||||||
let libpng_tar = format!("{}/libpng-1.6.37.tar.xz", &cwd);
|
fn main() {
|
||||||
|
if cfg!(windows) {
|
||||||
// Enforce clang for its -fsanitize-coverage support.
|
println!("cargo:warning=Skipping libpng frida example on Windows");
|
||||||
let clang = match env::var("CLANG_PATH") {
|
exit(0);
|
||||||
Ok(path) => path,
|
}
|
||||||
Err(_) => "clang".to_string(),
|
|
||||||
};
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
let clangpp = format!("{}++", &clang);
|
let cwd = env::current_dir().unwrap().to_string_lossy().to_string();
|
||||||
std::env::set_var("CC", &clang);
|
let out_dir = out_dir.to_string_lossy().to_string();
|
||||||
std::env::set_var("CXX", &clangpp);
|
let out_dir_path = Path::new(&out_dir);
|
||||||
let ldflags = match env::var("LDFLAGS") {
|
std::fs::create_dir_all(&out_dir).expect(&format!("Failed to create {}", &out_dir));
|
||||||
Ok(val) => val,
|
|
||||||
Err(_) => "".to_string(),
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
};
|
println!("cargo:rerun-if-changed=../libfuzzer_runtime/rt.c",);
|
||||||
|
println!("cargo:rerun-if-changed=harness.cc");
|
||||||
// println!("cargo:warning=output path is {}", libpng);
|
|
||||||
if !libpng_path.is_dir() {
|
build_dep_check(&["clang", "clang++", "wget", "tar", "make"]);
|
||||||
if !Path::new(&libpng_tar).is_file() {
|
|
||||||
println!("cargo:warning=Libpng not found, downloading...");
|
let libpng = format!("{}/libpng-1.6.37", &out_dir);
|
||||||
// Download libpng
|
let libpng_path = Path::new(&libpng);
|
||||||
Command::new("wget")
|
let libpng_tar = format!("{}/libpng-1.6.37.tar.xz", &cwd);
|
||||||
.arg("-c")
|
|
||||||
.arg(LIBPNG_URL)
|
// Enforce clang for its -fsanitize-coverage support.
|
||||||
.arg("-O")
|
let clang = match env::var("CLANG_PATH") {
|
||||||
.arg(&libpng_tar)
|
Ok(path) => path,
|
||||||
.status()
|
Err(_) => "clang".to_string(),
|
||||||
.unwrap();
|
};
|
||||||
}
|
let clangpp = format!("{}++", &clang);
|
||||||
Command::new("tar")
|
std::env::set_var("CC", &clang);
|
||||||
.current_dir(&out_dir_path)
|
std::env::set_var("CXX", &clangpp);
|
||||||
.arg("xvf")
|
let ldflags = match env::var("LDFLAGS") {
|
||||||
.arg(&libpng_tar)
|
Ok(val) => val,
|
||||||
.status()
|
Err(_) => "".to_string(),
|
||||||
.unwrap();
|
};
|
||||||
Command::new(format!("{}/configure", &libpng))
|
|
||||||
.current_dir(&libpng_path)
|
// println!("cargo:warning=output path is {}", libpng);
|
||||||
.args(&[
|
if !libpng_path.is_dir() {
|
||||||
"--disable-shared",
|
if !Path::new(&libpng_tar).is_file() {
|
||||||
&format!("--host={}", env::var("TARGET").unwrap())[..],
|
println!("cargo:warning=Libpng not found, downloading...");
|
||||||
])
|
// Download libpng
|
||||||
.env("CC", &clang)
|
Command::new("wget")
|
||||||
.env("CXX", &clangpp)
|
.arg("-c")
|
||||||
.env(
|
.arg(LIBPNG_URL)
|
||||||
"CFLAGS",
|
.arg("-O")
|
||||||
"-O3 -g -D_DEFAULT_SOURCE -fPIC -fno-omit-frame-pointer",
|
.arg(&libpng_tar)
|
||||||
)
|
.status()
|
||||||
.env(
|
.unwrap();
|
||||||
"CXXFLAGS",
|
}
|
||||||
"-O3 -g -D_DEFAULT_SOURCE -fPIC -fno-omit-frame-pointer",
|
Command::new("tar")
|
||||||
)
|
.current_dir(&out_dir_path)
|
||||||
.env(
|
.arg("xvf")
|
||||||
"LDFLAGS",
|
.arg(&libpng_tar)
|
||||||
//format!("-g -fPIE -fsanitize=address {}", ldflags),
|
.status()
|
||||||
format!("-g -fPIE {}", ldflags),
|
.unwrap();
|
||||||
)
|
Command::new(format!("{}/configure", &libpng))
|
||||||
.status()
|
.current_dir(&libpng_path)
|
||||||
.unwrap();
|
.args(&[
|
||||||
Command::new("make")
|
"--disable-shared",
|
||||||
.current_dir(&libpng_path)
|
&format!("--host={}", env::var("TARGET").unwrap())[..],
|
||||||
.status()
|
])
|
||||||
.unwrap();
|
.env("CC", &clang)
|
||||||
}
|
.env("CXX", &clangpp)
|
||||||
|
.env(
|
||||||
let status = cc::Build::new()
|
"CFLAGS",
|
||||||
.cpp(true)
|
"-O3 -g -D_DEFAULT_SOURCE -fPIC -fno-omit-frame-pointer",
|
||||||
.get_compiler()
|
)
|
||||||
.to_command()
|
.env(
|
||||||
.current_dir(&cwd)
|
"CXXFLAGS",
|
||||||
.arg("-I")
|
"-O3 -g -D_DEFAULT_SOURCE -fPIC -fno-omit-frame-pointer",
|
||||||
.arg(&libpng)
|
)
|
||||||
//.arg("-D")
|
.env(
|
||||||
//.arg("HAS_DUMMY_CRASH=1")
|
"LDFLAGS",
|
||||||
.arg("-fPIC")
|
//format!("-g -fPIE -fsanitize=address {}", ldflags),
|
||||||
.arg("-shared")
|
format!("-g -fPIE {}", ldflags),
|
||||||
.arg(if env::var("CARGO_CFG_TARGET_OS").unwrap() == "android" {
|
)
|
||||||
"-static-libstdc++"
|
.status()
|
||||||
} else {
|
.unwrap();
|
||||||
""
|
Command::new("make")
|
||||||
})
|
.current_dir(&libpng_path)
|
||||||
.arg("-o")
|
.status()
|
||||||
.arg(format!("{}/libpng-harness.so", &out_dir))
|
.unwrap();
|
||||||
.arg("./harness.cc")
|
}
|
||||||
.arg(format!("{}/.libs/libpng16.a", &libpng))
|
|
||||||
.arg("-l")
|
let status = cc::Build::new()
|
||||||
.arg("z")
|
.cpp(true)
|
||||||
.status()
|
.get_compiler()
|
||||||
.unwrap();
|
.to_command()
|
||||||
assert!(status.success());
|
.current_dir(&cwd)
|
||||||
|
.arg("-I")
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
.arg(&libpng)
|
||||||
}
|
//.arg("-D")
|
||||||
|
//.arg("HAS_DUMMY_CRASH=1")
|
||||||
|
.arg("-fPIC")
|
||||||
|
.arg("-shared")
|
||||||
|
.arg(if env::var("CARGO_CFG_TARGET_OS").unwrap() == "android" {
|
||||||
|
"-static-libstdc++"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
})
|
||||||
|
.arg("-o")
|
||||||
|
.arg(format!("{}/libpng-harness.so", &out_dir))
|
||||||
|
.arg("./harness.cc")
|
||||||
|
.arg(format!("{}/.libs/libpng16.a", &libpng))
|
||||||
|
.arg("-l")
|
||||||
|
.arg("z")
|
||||||
|
.status()
|
||||||
|
.unwrap();
|
||||||
|
assert!(status.success());
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -8,11 +8,24 @@ edition = "2018"
|
|||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = []
|
std = []
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
#[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" }
|
||||||
|
num_cpus = "1.0"
|
||||||
|
=======
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
debug = true
|
debug = true
|
||||||
|
>>>>>>> dev
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../../libafl/" }
|
libafl = { path = "../../libafl/" }
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
# Libfuzzer for libpng
|
# Libfuzzer for libpng
|
||||||
|
|
||||||
This folder contains an example fuzzer for libpng, using LLMP for fast multi-process fuzzing and crash detection.
|
This folder contains an example fuzzer for libpng, using LLMP for fast multi-process fuzzing and crash detection.
|
||||||
To show off crash detection, we added a ud2 instruction to the harness, edit harness.cc if you want a non-crashing example.
|
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.
|
It has been tested on Linux.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
You will need `clang` and `clang++` along with basic build dependencies for this example to compile.
|
||||||
|
To build this example, run `cargo build --example libfuzzer_libpng --release`.
|
||||||
|
This will call [the build.rs](./build.rs), which in turn downloads a libpng archive from the web.
|
||||||
|
Then, it will link [the fuzzer](./src/fuzzer.rs) against [the C++ harness](./harness.cc) and the instrumented `libpng`.
|
||||||
|
Afterwards, the fuzzer will be ready to run, from `../../target/examples/libfuzzer_libpng`.
|
||||||
|
=======
|
||||||
To build this example, run `cargo build --release`.
|
To build this example, run `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.
|
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 build also two C and C++ compiler wrappers (bin/c(c/xx).rs) that you must use to compile the target.
|
In addition, it will build also two C and C++ compiler wrappers (bin/c(c/xx).rs) that you must use to compile the target.
|
||||||
@ -29,12 +36,30 @@ Now, we have to build the libfuzzer harness and link all togheter to create our
|
|||||||
```
|
```
|
||||||
|
|
||||||
Afterwards, the fuzzer will be ready to run simply executing `./fuzzer`.
|
Afterwards, the fuzzer will be ready to run simply executing `./fuzzer`.
|
||||||
|
>>>>>>> dev
|
||||||
|
|
||||||
## Run
|
## 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.
|
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.
|
||||||
|
|
||||||
|
```
|
||||||
|
cargo run --release --example libfuzzer_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 >
|
||||||
|
```
|
||||||
|
|
||||||
Each following execution will run a fuzzer client.
|
|
||||||
As this example uses in-process fuzzing, we added a Restarting Event Manager (`setup_restarting_mgr`).
|
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.
|
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.
|
By restarting the actual fuzzer, it can recover from these exit conditions.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user