diff --git a/fuzzers/generic_inmemory/Cargo.toml b/fuzzers/generic_inmemory/Cargo.toml new file mode 100644 index 0000000000..1780bf34d9 --- /dev/null +++ b/fuzzers/generic_inmemory/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "generic_inmemory" +version = "0.3.2" +authors = ["Andrea Fioraldi ", "Dominik Maier "] +edition = "2018" + +[features] +default = ["std"] +std = [] + +[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" + +[dependencies] +libafl = { path = "../../libafl/" } +libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "sancov_cmplog", "libfuzzer"] } +# TODO Include it only when building cc +libafl_cc = { path = "../../libafl_cc/" } +clap = { version = "3.0.0-beta.2", features = ["default", "yaml"] } + +[lib] +name = "generic_inmemory" +crate-type = ["staticlib"] diff --git a/fuzzers/generic_inmemory/README.md b/fuzzers/generic_inmemory/README.md new file mode 100644 index 0000000000..8028d0d543 --- /dev/null +++ b/fuzzers/generic_inmemory/README.md @@ -0,0 +1,3 @@ +# Generic In-Memory Fuzzer + +This is a generic in-memory fuzzer based on LibAFL diff --git a/fuzzers/generic_inmemory/fuzz.c b/fuzzers/generic_inmemory/fuzz.c new file mode 100644 index 0000000000..7eea9f3b30 --- /dev/null +++ b/fuzzers/generic_inmemory/fuzz.c @@ -0,0 +1,15 @@ +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size >= 8 && *(uint32_t*)Data == 0xaabbccdd) + abort(); +} + +/* +int main() { + + char buf [10] = {0}; + LLVMFuzzerTestOneInput(buf, 10); + +}*/ diff --git a/fuzzers/generic_inmemory/src/bin/libafl_cc.rs b/fuzzers/generic_inmemory/src/bin/libafl_cc.rs new file mode 100644 index 0000000000..b37778565c --- /dev/null +++ b/fuzzers/generic_inmemory/src/bin/libafl_cc.rs @@ -0,0 +1,37 @@ +use libafl_cc::{ClangWrapper, CompilerWrapper, LIB_EXT, LIB_PREFIX}; +use std::env; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 { + let mut dir = env::current_exe().unwrap(); + dir.pop(); + + let mut cc = ClangWrapper::new("clang", "clang++"); + cc.from_args(&args) + .unwrap() + .add_link_arg("-Wl,--whole-archive".into()) + .unwrap() + .add_link_arg( + dir.join(format!("{}generic_inmemory.{}", LIB_PREFIX, LIB_EXT)) + .display() + .to_string(), + ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) + .unwrap(); + // Libraries needed by libafl on Windows + #[cfg(windows)] + cc.add_link_arg("-lws2_32".into()) + .unwrap() + .add_link_arg("-lBcrypt".into()) + .unwrap() + .add_link_arg("-lAdvapi32".into()) + .unwrap(); + cc.run().unwrap(); + } else { + panic!("LibAFL CC: No Arguments given"); + } +} diff --git a/fuzzers/generic_inmemory/src/bin/libafl_cxx.rs b/fuzzers/generic_inmemory/src/bin/libafl_cxx.rs new file mode 100644 index 0000000000..a05b141849 --- /dev/null +++ b/fuzzers/generic_inmemory/src/bin/libafl_cxx.rs @@ -0,0 +1,38 @@ +use libafl_cc::{ClangWrapper, CompilerWrapper, LIB_EXT, LIB_PREFIX}; +use std::env; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 { + let mut dir = env::current_exe().unwrap(); + dir.pop(); + + let mut cc = ClangWrapper::new("clang", "clang++"); + cc.is_cpp() + .from_args(&args) + .unwrap() + .add_link_arg("-Wl,--whole-archive".into()) + .unwrap() + .add_link_arg( + dir.join(format!("{}generic_inmemory.{}", LIB_PREFIX, LIB_EXT)) + .display() + .to_string(), + ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) + .unwrap(); + // Libraries needed by libafl on Windows + #[cfg(windows)] + cc.add_link_arg("-lws2_32".into()) + .unwrap() + .add_link_arg("-lBcrypt".into()) + .unwrap() + .add_link_arg("-lAdvapi32".into()) + .unwrap(); + cc.run().unwrap(); + } else { + panic!("LibAFL CC: No Arguments given"); + } +} diff --git a/fuzzers/generic_inmemory/src/clap-config.yaml b/fuzzers/generic_inmemory/src/clap-config.yaml new file mode 100644 index 0000000000..15fe5a941a --- /dev/null +++ b/fuzzers/generic_inmemory/src/clap-config.yaml @@ -0,0 +1,41 @@ +name: generic_inmemory +author: "Andrea Fioraldi , Dominik Maier " +args: + - cores: + long: cores + about: "Spawn a client in each of the provided cores. Broker runs in the 0th core. 'all' to select all available cores. 'none' to run a client without binding to any core. eg: '1,2-4,6' selects the cores 1,2,3,4,6." + value_name: CORES + required: true + takes_value: true + - broker_port: + long: broker_port + about: "Choose the broker TCP port, default is 1337" + value_name: PORT + takes_value: true + - remote_broker_addr: + long: remote_broker_addr + about: "Specify a remote broker" + value_name: REMOTE + takes_value: true + - input: + long: input + about: "Set an initial corpus directory" + value_name: INPUT + multiple: true + takes_value: true + - output: + long: output + about: "Set the output directory, default is CWD" + value_name: OUTPUT + takes_value: true + - timeout: + long: timeout + about: "Set the execution timeout in milliseconds, default 10000" + value_name: TIMEOUT + takes_value: true + - dict: + long: dict + about: "Feed the fuzzer with an user-specified dictionary of tokens" + value_name: DICT + multiple: true + takes_value: true diff --git a/fuzzers/generic_inmemory/src/lib.rs b/fuzzers/generic_inmemory/src/lib.rs new file mode 100644 index 0000000000..829f727147 --- /dev/null +++ b/fuzzers/generic_inmemory/src/lib.rs @@ -0,0 +1,245 @@ +//! A libfuzzer-like fuzzer with llmp-multithreading support and restarts +//! The `launcher` will spawn new processes for each cpu core. + +use clap::{load_yaml, App}; +use core::time::Duration; +use std::{env, path::PathBuf}; + +use libafl::{ + bolts::{ + current_nanos, + launcher::Launcher, + os::parse_core_bind_arg, + rands::StdRand, + shmem::{ShMemProvider, StdShMemProvider}, + tuples::{tuple_list, Merge}, + }, + corpus::{ + Corpus, InMemoryCorpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, + QueueCorpusScheduler, + }, + executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor}, + feedback_or, + feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, + fuzzer::{Fuzzer, StdFuzzer}, + generators::RandBytesGenerator, + inputs::{BytesInput, HasTargetBytes}, + mutators::scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, + mutators::token_mutations::{I2SRandReplace, Tokens}, + observers::{HitcountsMapObserver, StdMapObserver, TimeObserver}, + stages::{StdMutationalStage, TracingStage}, + state::{HasCorpus, HasMetadata, StdState}, + stats::MultiStats, +}; + +use libafl_targets::{ + libfuzzer_initialize, libfuzzer_test_one_input, CmpLogObserver, CMPLOG_MAP, EDGES_MAP, + MAX_EDGES_NUM, +}; + +/// The main fn, `no_mangle` as it is a C main +#[no_mangle] +pub fn main() { + // Registry the metadata types used in this fuzzer + // Needed only on no_std + //RegistryBuilder::register::(); + + let workdir = env::current_dir().unwrap(); + + let yaml = load_yaml!("clap-config.yaml"); + let matches = App::from(yaml).get_matches(); + + let cores = parse_core_bind_arg(&matches.value_of("cores").unwrap()) + .expect("No valid core count given!"); + let broker_port = matches + .value_of("broker_port") + .map(|s| s.parse().expect("Invalid broker port".into())) + .unwrap_or(1337); + let remote_broker_addr = matches + .value_of("remote_broker_addr") + .map(|s| s.parse().expect("Invalid broker address".into())); + let input_dirs: Vec = matches + .values_of("input") + .map(|v| v.map(|s| PathBuf::from(s)).collect()) + .unwrap_or(vec![]); + let output_dir = matches + .value_of("output") + .map(|s| PathBuf::from(s)) + .unwrap_or(workdir.clone()); + let dicts: Vec<&str> = matches + .values_of("dict") + .map(|v| v.collect()) + .unwrap_or(vec![]); + let timeout_ms = matches + .value_of("timeout") + .map(|s| s.parse().expect("Invalid timeout".into())) + .unwrap_or(10000); + // let cmplog_enabled = matches.is_present("cmplog"); + + println!("Workdir: {:?}", workdir.to_string_lossy().to_string()); + + #[cfg(target_os = "android")] + AshmemService::start().expect("Failed to start Ashmem service"); + let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory"); + + let stats = MultiStats::new(|s| println!("{}", s)); + + let mut run_client = |state: Option>, mut mgr| { + // Create an observation channel using the coverage map + let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] }; + let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges)); + + // Create an observation channel to keep track of the execution time + let time_observer = TimeObserver::new("time"); + + // Create the Cmp observer + let cmplog = unsafe { &mut CMPLOG_MAP }; + let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true); + + // The state of the edges feedback. + let feedback_state = MapFeedbackState::with_observer(&edges_observer); + + // Feedback to rate the interestingness of an input + // This one is composed by two Feedbacks in OR + let feedback = feedback_or!( + // New maximization map feedback linked to the edges observer and the feedback state + MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false), + // Time feedback, this one does not need a feedback state + TimeFeedback::new_with_observer(&time_observer) + ); + + // A feedback to choose if an input is a solution or not + let objective = feedback_or!(CrashFeedback::new(), TimeoutFeedback::new()); + + // If not restarting, create a State from scratch + let mut state = state.unwrap_or_else(|| { + StdState::new( + // RNG + StdRand::with_seed(current_nanos()), + // Corpus that will be evolved, we keep it in memory for performance + InMemoryCorpus::new(), + // Corpus in which we store solutions (crashes in this example), + // on disk so the user can get them after stopping the fuzzer + OnDiskCorpus::new(output_dir.clone()).unwrap(), + // States of the feedbacks. + // They are the data related to the feedbacks that you want to persist in the State. + tuple_list!(feedback_state), + ) + }); + + // Create a PNG dictionary if not existing + if state.metadata().get::().is_none() { + for dict in &dicts { + state.add_metadata(Tokens::from_tokens_file(dict)?); + } + } + + // A minimization+queue policy to get testcasess from the corpus + let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(QueueCorpusScheduler::new()); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); + + // The wrapped harness function, calling out to the LLVM-style harness + let mut harness = |input: &BytesInput| { + let target = input.target_bytes(); + let buf = target.as_slice(); + libfuzzer_test_one_input(buf); + ExitKind::Ok + }; + + // Create the executor for an in-process function with one observer for edge coverage and one for the execution time + let mut executor = TimeoutExecutor::new( + InProcessExecutor::new( + &mut harness, + tuple_list!(edges_observer, time_observer), + &mut fuzzer, + &mut state, + &mut mgr, + )?, + Duration::from_millis(timeout_ms), + ); + + // Secondary harness due to mut ownership + let mut harness = |input: &BytesInput| { + let target = input.target_bytes(); + let buf = target.as_slice(); + libfuzzer_test_one_input(buf); + ExitKind::Ok + }; + + // Setup a tracing stage in which we log comparisons + let tracing = TracingStage::new(InProcessExecutor::new( + &mut harness, + tuple_list!(cmplog_observer), + &mut fuzzer, + &mut state, + &mut mgr, + )?); + + // Setup a randomic Input2State stage + let i2s = + StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); + + // Setup a basic mutator + let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); + let mutational = StdMutationalStage::new(mutator); + + // The order of the stages matter! + let mut stages = tuple_list!(tracing, i2s, mutational); + + // The actual target run starts here. + // Call LLVMFUzzerInitialize() if present. + let args: Vec = env::args().collect(); + if libfuzzer_initialize(&args) == -1 { + println!("Warning: LLVMFuzzerInitialize failed with -1") + } + + // In case the corpus is empty (on first run), reset + if state.corpus().count() < 1 { + if input_dirs.len() == 0 { + // Generator of printable bytearrays of max size 32 + let mut generator = RandBytesGenerator::new(32); + + // Generate 8 initial inputs + state + .generate_initial_inputs( + &mut fuzzer, + &mut executor, + &mut generator, + &mut mgr, + 8, + ) + .expect("Failed to generate the initial corpus"); + println!( + "We imported {} inputs from the generator.", + state.corpus().count() + ); + } else { + println!("Loading from {:?}", &input_dirs); + // Load from disk + state + .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &input_dirs) + .unwrap_or_else(|_| { + panic!("Failed to load initial corpus at {:?}", &input_dirs) + }); + println!("We imported {} inputs from disk.", state.corpus().count()); + } + } + + fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?; + Ok(()) + }; + + Launcher::builder() + .shmem_provider(shmem_provider) + .stats(stats) + .run_client(&mut run_client) + .cores(&cores) + .broker_port(broker_port) + .remote_broker_addr(remote_broker_addr) + //.stdout_file(Some("/dev/null")) + .build() + .launch() + .expect("Launcher failed"); +} diff --git a/fuzzers/libfuzzer_libmozjpeg/Makefile b/fuzzers/libfuzzer_libmozjpeg/Makefile new file mode 100644 index 0000000000..0cd43ea86e --- /dev/null +++ b/fuzzers/libfuzzer_libmozjpeg/Makefile @@ -0,0 +1,88 @@ +PWD=`pwd` +FUZZER_NAME="fuzzer_mozjpeg" + +PHONY: all + +all: fuzzer + +mozjpeg-4.0.3: + wget https://github.com/mozilla/mozjpeg/archive/v4.0.3.tar.gz + tar -xzvf v4.0.3.tar.gz + +target/release/libafl_cxx: src/* src/bin/* + # Build the libpng libfuzzer library + cargo build --release + +libafl_cxx: target/release/libafl_cxx + +libafl_cc: target/release/libafl_cxx + +mozjpeg-4.0.3-compiled: mozjpeg-4.0.3 libafl_cc + cd $(PWD)/mozjpeg-4.0.3 && cmake --disable-shared . -DCMAKE_C_COMPILER=$(abspath $(PWD)/../target/release/libafl_cc) -DCMAKE_CXX_COMPILER=$(abspath $(PWD)/../target/release/libafl_cxx) -G "Unix Makefiles" + $(MAKE) -C $(PWD)/mozjpeg-4.0.3 + + +fuzzer: mozjpeg-4.0.3-compiled libafl_cxx + # Build the mozjpeg libfuzzer library + cargo build --release + + # Build the mozjpeg harness + target/release/libafl_cxx \ + $(PWD)/harness.cc \ + $(PWD)/mozjpeg-4.0.3/*.a \ + -I$(PWD)/mozjpeg-4.0.3/ \ + -o $(FUZZER_NAME) \ + -lm -lz + +clean: + rm ./$(FUZZER_NAME) + $(MAKE) -C mozjpeg-4.0.3 clean + +run: all + ./$(FUZZER_NAME) & + sleep 0.2 + ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + +short_test: all + timeout 11s ./$(FUZZER_NAME) & + sleep 0.2 + timeout 10s taskset -c 0 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 10s taskset -c 1 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 10s taskset -c 2 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 10s taskset -c 3 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + +test: all + timeout 60s ./$(FUZZER_NAME) & + sleep 0.2 + timeout 59s taskset 0x00000001 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 59s taskset 0x00000002 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 59s taskset 0x00000004 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 59s taskset 0x00000008 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000010 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000020 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000040 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000080 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000100 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000200 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000400 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000800 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00001000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00002000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00004000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00008000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00010000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00020000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00040000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00080000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00100000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00200000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00400000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00800000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x01000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x02000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x04000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x08000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x10000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x20000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x40000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x80000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & diff --git a/fuzzers/libfuzzer_libmozjpeg/src/bin/libafl_cc.rs b/fuzzers/libfuzzer_libmozjpeg/src/bin/libafl_cc.rs index 8bc7675165..0162b98a95 100644 --- a/fuzzers/libfuzzer_libmozjpeg/src/bin/libafl_cc.rs +++ b/fuzzers/libfuzzer_libmozjpeg/src/bin/libafl_cc.rs @@ -10,17 +10,18 @@ fn main() { let mut cc = ClangWrapper::new("clang", "clang++"); cc.from_args(&args) .unwrap() - .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) - .unwrap() - .add_arg("-fPIC".into()) + .add_link_arg("-Wl,--whole-archive".into()) .unwrap() .add_link_arg( dir.join(format!("{}libfuzzer_libmozjpeg.{}", LIB_PREFIX, LIB_EXT)) .display() .to_string(), ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) .unwrap(); - // Libraries needed by libafl on Windows #[cfg(windows)] cc.add_link_arg("-lws2_32".into()) .unwrap() diff --git a/fuzzers/libfuzzer_libmozjpeg/src/bin/libafl_cxx.rs b/fuzzers/libfuzzer_libmozjpeg/src/bin/libafl_cxx.rs index 164de2fb7a..73bca7be22 100644 --- a/fuzzers/libfuzzer_libmozjpeg/src/bin/libafl_cxx.rs +++ b/fuzzers/libfuzzer_libmozjpeg/src/bin/libafl_cxx.rs @@ -11,15 +11,17 @@ fn main() { cc.is_cpp() .from_args(&args) .unwrap() - .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) - .unwrap() - .add_arg("-fPIC".into()) + .add_link_arg("-Wl,--whole-archive".into()) .unwrap() .add_link_arg( dir.join(format!("{}libfuzzer_libmozjpeg.{}", LIB_PREFIX, LIB_EXT)) .display() .to_string(), ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) .unwrap(); // Libraries needed by libafl on Windows #[cfg(windows)] diff --git a/fuzzers/libfuzzer_libpng/Cargo.toml b/fuzzers/libfuzzer_libpng/Cargo.toml index 5c38cd2133..ea42326b89 100644 --- a/fuzzers/libfuzzer_libpng/Cargo.toml +++ b/fuzzers/libfuzzer_libpng/Cargo.toml @@ -22,7 +22,7 @@ num_cpus = "1.0" [dependencies] libafl = { path = "../../libafl/", features = ["default"] } # libafl = { path = "../../libafl/", features = ["default"] } -libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer"] } +libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer", "sancov_cmplog"] } # TODO Include it only when building cc libafl_cc = { path = "../../libafl_cc/" } diff --git a/fuzzers/libfuzzer_libpng/Makefile b/fuzzers/libfuzzer_libpng/Makefile index 44e026dce2..fe388109bc 100644 --- a/fuzzers/libfuzzer_libpng/Makefile +++ b/fuzzers/libfuzzer_libpng/Makefile @@ -1,7 +1,7 @@ PWD=`pwd` FUZZER_NAME="fuzzer_libpng" -PHONY: all clean +PHONY: all all: fuzzer @@ -34,6 +34,10 @@ fuzzer: libpng-1.6.37/.libs/libpng16.a libafl_cxx -o $(FUZZER_NAME) \ -lm -lz +clean: + rm ./$(FUZZER_NAME) + $(MAKE) -C libpng-1.6.37 clean + run: all ./$(FUZZER_NAME) & sleep 0.2 diff --git a/fuzzers/libfuzzer_libpng/src/bin/libafl_cc.rs b/fuzzers/libfuzzer_libpng/src/bin/libafl_cc.rs index dc65a9a57b..5af597bfac 100644 --- a/fuzzers/libfuzzer_libpng/src/bin/libafl_cc.rs +++ b/fuzzers/libfuzzer_libpng/src/bin/libafl_cc.rs @@ -10,13 +10,17 @@ fn main() { let mut cc = ClangWrapper::new("clang", "clang++"); cc.from_args(&args) .unwrap() - .add_arg("-fsanitize-coverage=trace-pc-guard".into()) + .add_link_arg("-Wl,--whole-archive".into()) .unwrap() .add_link_arg( dir.join(format!("{}libfuzzer_libpng.{}", LIB_PREFIX, LIB_EXT)) .display() .to_string(), ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) .unwrap(); // Libraries needed by libafl on Windows #[cfg(windows)] diff --git a/fuzzers/libfuzzer_libpng/src/bin/libafl_cxx.rs b/fuzzers/libfuzzer_libpng/src/bin/libafl_cxx.rs index 2183682d96..72e06e3baa 100644 --- a/fuzzers/libfuzzer_libpng/src/bin/libafl_cxx.rs +++ b/fuzzers/libfuzzer_libpng/src/bin/libafl_cxx.rs @@ -11,13 +11,17 @@ fn main() { cc.is_cpp() .from_args(&args) .unwrap() - .add_arg("-fsanitize-coverage=trace-pc-guard".into()) + .add_link_arg("-Wl,--whole-archive".into()) .unwrap() .add_link_arg( dir.join(format!("{}libfuzzer_libpng.{}", LIB_PREFIX, LIB_EXT)) .display() .to_string(), ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) .unwrap(); // Libraries needed by libafl on Windows #[cfg(windows)] diff --git a/fuzzers/libfuzzer_libpng_launcher/Makefile b/fuzzers/libfuzzer_libpng_launcher/Makefile new file mode 100644 index 0000000000..fe388109bc --- /dev/null +++ b/fuzzers/libfuzzer_libpng_launcher/Makefile @@ -0,0 +1,88 @@ +PWD=`pwd` +FUZZER_NAME="fuzzer_libpng" + +PHONY: all + +all: fuzzer + +libpng-1.6.37: + 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 + +target/release/libafl_cxx: src/* src/bin/* + # Build the libpng libfuzzer library + cargo build --release + +libafl_cxx: target/release/libafl_cxx + +libafl_cc: target/release/libafl_cxx + +libpng-1.6.37/.libs/libpng16.a: libpng-1.6.37 libafl_cc + cd libpng-1.6.37 && ./configure && cd .. + $(MAKE) -C libpng-1.6.37 CC=$(realpath target/release/libafl_cc) CXX=$(realpath target/release/libafl_cxx) + + +fuzzer: libpng-1.6.37/.libs/libpng16.a libafl_cxx + # Build the libpng libfuzzer library + cargo build --release + + # Build the libpng harness + target/release/libafl_cxx \ + $(PWD)/harness.cc \ + $(PWD)/libpng-1.6.37/.libs/libpng16.a \ + -I$(PWD)/libpng-1.6.37/ \ + -o $(FUZZER_NAME) \ + -lm -lz + +clean: + rm ./$(FUZZER_NAME) + $(MAKE) -C libpng-1.6.37 clean + +run: all + ./$(FUZZER_NAME) & + sleep 0.2 + ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + +short_test: all + timeout 11s ./$(FUZZER_NAME) & + sleep 0.2 + timeout 10s taskset -c 0 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 10s taskset -c 1 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 10s taskset -c 2 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 10s taskset -c 3 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + +test: all + timeout 60s ./$(FUZZER_NAME) & + sleep 0.2 + timeout 59s taskset 0x00000001 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 59s taskset 0x00000002 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 59s taskset 0x00000004 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + timeout 59s taskset 0x00000008 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000010 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000020 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000040 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000080 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000100 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000200 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000400 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00000800 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00001000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00002000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00004000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00008000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00010000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00020000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00040000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00080000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00100000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00200000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00400000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x00800000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x01000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x02000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x04000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x08000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x10000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x20000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x40000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & + # timeout 59s taskset 0x80000000 ./$(FUZZER_NAME) >/dev/null 2>/dev/null & diff --git a/fuzzers/libfuzzer_libpng_launcher/src/bin/libafl_cc.rs b/fuzzers/libfuzzer_libpng_launcher/src/bin/libafl_cc.rs index dc65a9a57b..5af597bfac 100644 --- a/fuzzers/libfuzzer_libpng_launcher/src/bin/libafl_cc.rs +++ b/fuzzers/libfuzzer_libpng_launcher/src/bin/libafl_cc.rs @@ -10,13 +10,17 @@ fn main() { let mut cc = ClangWrapper::new("clang", "clang++"); cc.from_args(&args) .unwrap() - .add_arg("-fsanitize-coverage=trace-pc-guard".into()) + .add_link_arg("-Wl,--whole-archive".into()) .unwrap() .add_link_arg( dir.join(format!("{}libfuzzer_libpng.{}", LIB_PREFIX, LIB_EXT)) .display() .to_string(), ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) .unwrap(); // Libraries needed by libafl on Windows #[cfg(windows)] diff --git a/fuzzers/libfuzzer_libpng_launcher/src/bin/libafl_cxx.rs b/fuzzers/libfuzzer_libpng_launcher/src/bin/libafl_cxx.rs index 2183682d96..72e06e3baa 100644 --- a/fuzzers/libfuzzer_libpng_launcher/src/bin/libafl_cxx.rs +++ b/fuzzers/libfuzzer_libpng_launcher/src/bin/libafl_cxx.rs @@ -11,13 +11,17 @@ fn main() { cc.is_cpp() .from_args(&args) .unwrap() - .add_arg("-fsanitize-coverage=trace-pc-guard".into()) + .add_link_arg("-Wl,--whole-archive".into()) .unwrap() .add_link_arg( dir.join(format!("{}libfuzzer_libpng.{}", LIB_PREFIX, LIB_EXT)) .display() .to_string(), ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) .unwrap(); // Libraries needed by libafl on Windows #[cfg(windows)] diff --git a/fuzzers/libfuzzer_reachability/src/bin/libafl_cc.rs b/fuzzers/libfuzzer_reachability/src/bin/libafl_cc.rs index dc65a9a57b..5af597bfac 100644 --- a/fuzzers/libfuzzer_reachability/src/bin/libafl_cc.rs +++ b/fuzzers/libfuzzer_reachability/src/bin/libafl_cc.rs @@ -10,13 +10,17 @@ fn main() { let mut cc = ClangWrapper::new("clang", "clang++"); cc.from_args(&args) .unwrap() - .add_arg("-fsanitize-coverage=trace-pc-guard".into()) + .add_link_arg("-Wl,--whole-archive".into()) .unwrap() .add_link_arg( dir.join(format!("{}libfuzzer_libpng.{}", LIB_PREFIX, LIB_EXT)) .display() .to_string(), ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) .unwrap(); // Libraries needed by libafl on Windows #[cfg(windows)] diff --git a/fuzzers/libfuzzer_reachability/src/bin/libafl_cxx.rs b/fuzzers/libfuzzer_reachability/src/bin/libafl_cxx.rs index 2183682d96..72e06e3baa 100644 --- a/fuzzers/libfuzzer_reachability/src/bin/libafl_cxx.rs +++ b/fuzzers/libfuzzer_reachability/src/bin/libafl_cxx.rs @@ -11,13 +11,17 @@ fn main() { cc.is_cpp() .from_args(&args) .unwrap() - .add_arg("-fsanitize-coverage=trace-pc-guard".into()) + .add_link_arg("-Wl,--whole-archive".into()) .unwrap() .add_link_arg( dir.join(format!("{}libfuzzer_libpng.{}", LIB_PREFIX, LIB_EXT)) .display() .to_string(), ) + .unwrap() + .add_link_arg("-Wl,-no-whole-archive".into()) + .unwrap() + .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()) .unwrap(); // Libraries needed by libafl on Windows #[cfg(windows)] diff --git a/libafl/src/stats/mod.rs b/libafl/src/stats/mod.rs index 876b8715df..42a38ae475 100644 --- a/libafl/src/stats/mod.rs +++ b/libafl/src/stats/mod.rs @@ -196,6 +196,48 @@ pub trait Stats { } } +/// Stats that print exactly nothing. +/// Not good for debuging, very good for speed. +pub struct NopStats { + start_time: Duration, + client_stats: Vec, +} + +impl Stats for NopStats { + /// the client stats, mutable + fn client_stats_mut(&mut self) -> &mut Vec { + &mut self.client_stats + } + + /// the client stats + fn client_stats(&self) -> &[ClientStats] { + &self.client_stats + } + + /// Time this fuzzing run stated + fn start_time(&mut self) -> time::Duration { + self.start_time + } + + fn display(&mut self, _event_msg: String, _sender_id: u32) {} +} + +impl NopStats { + /// Create new [`NopStats`] + pub fn new() -> Self { + Self { + start_time: current_time(), + client_stats: vec![], + } + } +} + +impl Default for NopStats { + fn default() -> Self { + Self::new() + } +} + /// Tracking stats during fuzzing. #[derive(Clone, Debug)] pub struct SimpleStats diff --git a/libafl_targets/src/lib.rs b/libafl_targets/src/lib.rs index 4d9130ab0c..c1a442e6e0 100644 --- a/libafl_targets/src/lib.rs +++ b/libafl_targets/src/lib.rs @@ -8,6 +8,11 @@ pub mod sancov_pcguard; #[cfg(any(feature = "sancov_pcguard_edges", feature = "sancov_pcguard_hitcounts"))] pub use sancov_pcguard::*; +#[cfg(any(feature = "sancov_cmplog", feature = "sancov_value_profile"))] +pub mod sancov_cmp; +#[cfg(any(feature = "sancov_cmplog", feature = "sancov_value_profile"))] +pub use sancov_cmp::*; + #[cfg(feature = "libfuzzer")] pub mod libfuzzer; #[cfg(feature = "libfuzzer")] diff --git a/libafl_targets/src/sancov_cmp.rs b/libafl_targets/src/sancov_cmp.rs new file mode 100644 index 0000000000..9f78b643e2 --- /dev/null +++ b/libafl_targets/src/sancov_cmp.rs @@ -0,0 +1,15 @@ +extern "C" { + + pub fn __sanitizer_cov_trace_cmp1(v0: u8, v1: u8); + pub fn __sanitizer_cov_trace_cmp2(v0: u16, v1: u16); + pub fn __sanitizer_cov_trace_cmp4(v0: u32, v1: u32); + pub fn __sanitizer_cov_trace_cmp8(v0: u64, v1: u64); + + pub fn __sanitizer_cov_trace_const_cmp1(v0: u8, v1: u8); + pub fn __sanitizer_cov_trace_const_cmp2(v0: u16, v1: u16); + pub fn __sanitizer_cov_trace_const_cmp4(v0: u32, v1: u32); + pub fn __sanitizer_cov_trace_const_cmp8(v0: u64, v1: u64); + + pub fn __sanitizer_cov_trace_switch(val: u64, cases: *const u64); + +}