From 2f7bb8d532849dac69183701252ee5079d96ca6e Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 21 Apr 2021 14:51:51 +0200 Subject: [PATCH] baby fuzzer --- Cargo.toml | 2 +- fuzzers/baby_fuzzer/.gitignore | 1 + fuzzers/baby_fuzzer/Cargo.toml | 22 ++++++++ fuzzers/baby_fuzzer/README.md | 3 ++ fuzzers/baby_fuzzer/src/main.rs | 94 +++++++++++++++++++++++++++++++++ libafl/src/events/simple.rs | 8 +-- 6 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 fuzzers/baby_fuzzer/.gitignore create mode 100644 fuzzers/baby_fuzzer/Cargo.toml create mode 100644 fuzzers/baby_fuzzer/README.md create mode 100644 fuzzers/baby_fuzzer/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 6710352a0e..c755aa1a19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,5 +16,5 @@ exclude = [ "fuzzers/libfuzzer_stb_image", "fuzzers/libfuzzer_libmozjpeg", "fuzzers/frida_libpng", - "fuzzers/qemu_user", + "fuzzers/baby_fuzzer", ] diff --git a/fuzzers/baby_fuzzer/.gitignore b/fuzzers/baby_fuzzer/.gitignore new file mode 100644 index 0000000000..a977a2ca5b --- /dev/null +++ b/fuzzers/baby_fuzzer/.gitignore @@ -0,0 +1 @@ +libpng-* \ No newline at end of file diff --git a/fuzzers/baby_fuzzer/Cargo.toml b/fuzzers/baby_fuzzer/Cargo.toml new file mode 100644 index 0000000000..b464bafe45 --- /dev/null +++ b/fuzzers/baby_fuzzer/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "baby_fuzzer" +version = "0.1.0" +authors = ["Andrea Fioraldi ", "Dominik Maier "] +edition = "2018" + +[features] +default = ["std"] +std = [] + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" +lto = true +codegen-units = 1 +opt-level = 3 +debug = true + +[dependencies] +libafl = { path = "../../libafl/" } diff --git a/fuzzers/baby_fuzzer/README.md b/fuzzers/baby_fuzzer/README.md new file mode 100644 index 0000000000..917277dc7b --- /dev/null +++ b/fuzzers/baby_fuzzer/README.md @@ -0,0 +1,3 @@ +# Baby fuzzer + + diff --git a/fuzzers/baby_fuzzer/src/main.rs b/fuzzers/baby_fuzzer/src/main.rs new file mode 100644 index 0000000000..fbba174e3e --- /dev/null +++ b/fuzzers/baby_fuzzer/src/main.rs @@ -0,0 +1,94 @@ +use std::path::PathBuf; + +use libafl::{ + bolts::tuples::tuple_list, + corpus::{InMemoryCorpus, OnDiskCorpus, QueueCorpusScheduler}, + events::SimpleEventManager, + executors::{inprocess::InProcessExecutor, ExitKind}, + feedbacks::{CrashFeedback, MaxMapFeedback}, + fuzzer::{Fuzzer, StdFuzzer}, + generators::RandPrintablesGenerator, + mutators::scheduled::{havoc_mutations, StdScheduledMutator}, + observers::StdMapObserver, + stages::mutational::StdMutationalStage, + state::State, + stats::SimpleStats, + utils::{current_nanos, StdRand}, +}; + +static mut SIGNALS: [u8; 16] = [0; 16]; + +pub fn main() { + // The closure that we want to fuzz + let mut harness = |buf: &[u8]| { + unsafe { SIGNALS[0] = 1 }; + if buf.len() > 0 && buf[0] == 'a' as u8 { + unsafe { SIGNALS[1] = 1 }; + if buf.len() > 1 && buf[1] == 'b' as u8 { + unsafe { SIGNALS[2] = 1 }; + if buf.len() > 2 && buf[2] == 'c' as u8 { + panic!("=)"); + } + } + } + ExitKind::Ok + }; + + // The Stats trait define how the fuzzer stats are reported to the user + let stats = SimpleStats::new(|s| println!("{}", s)); + + // The event manager handle the various events generated during the fuzzing loop + // such as the notification of the addition of a new item to the corpus + let mut mgr = SimpleEventManager::new(stats); + + // Create an observation channel using the siganls map + let observer = + StdMapObserver::new("signals", unsafe { &mut SIGNALS }, unsafe { SIGNALS.len() }); + + // create a State from scratch + let mut state = State::new( + // RNG + StdRand::with_seed(current_nanos()), + // Corpus that will be evolved, we keep it in memory for performance + InMemoryCorpus::new(), + // Feedbacks to rate the interestingness of an input + tuple_list!(MaxMapFeedback::new(&observer)), + // Corpus in which we store solutions (crashes in this example), + // on disk so the user can get them after stopping the fuzzer + OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(), + // Feedbacks to recognize an input as solution + tuple_list!(CrashFeedback::new()), + ); + + // Setup a basic mutator with a mutational stage + let mutator = StdScheduledMutator::new(havoc_mutations()); + let stage = StdMutationalStage::new(mutator); + + // A fuzzer with just one stage + let mut fuzzer = StdFuzzer::new(tuple_list!(stage)); + + // A queue policy to get testcasess from the corpus + let scheduler = QueueCorpusScheduler::new(); + + // Create the executor for an in-process function with just one observer + let mut executor = InProcessExecutor::new( + "in-process(signals)", + &mut harness, + tuple_list!(observer), + &mut state, + &mut mgr, + ) + .expect("Failed to create the Executor".into()); + + // Generator of printable bytearrays of max size 32 + let mut generator = RandPrintablesGenerator::new(32); + + // Generate 8 initial inputs + state + .generate_initial_inputs(&mut executor, &mut generator, &mut mgr, &scheduler, 8) + .expect("Failed to generate the initial corpus".into()); + + fuzzer + .fuzz_loop(&mut state, &mut executor, &mut mgr, &scheduler) + .expect("Error in the fuzzing loop".into()); +} diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index 1ce7598155..9b2a1ed022 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -84,8 +84,8 @@ where time, executions, } => { - stats.client_stats_mut()[0].update_corpus_size(*corpus_size as u64); - stats.client_stats_mut()[0].update_executions(*executions as u64, *time); + stats.client_stats_mut_for(0).update_corpus_size(*corpus_size as u64); + stats.client_stats_mut_for(0).update_executions(*executions as u64, *time); stats.display(event.name().to_string()); Ok(BrokerEventResult::Handled) } @@ -95,12 +95,12 @@ where phantom: _, } => { // TODO: The stats buffer should be added on client add. - stats.client_stats_mut()[0].update_executions(*executions as u64, *time); + stats.client_stats_mut_for(0).update_executions(*executions as u64, *time); stats.display(event.name().to_string()); Ok(BrokerEventResult::Handled) } Event::Objective { objective_size } => { - stats.client_stats_mut()[0].update_objective_size(*objective_size as u64); + stats.client_stats_mut_for(0).update_objective_size(*objective_size as u64); stats.display(event.name().to_string()); Ok(BrokerEventResult::Handled) }