diff --git a/afl/src/events/mod.rs b/afl/src/events/mod.rs index 93dcc56511..6dcfdec263 100644 --- a/afl/src/events/mod.rs +++ b/afl/src/events/mod.rs @@ -858,7 +858,13 @@ where #[cfg(feature = "std")] pub fn setup_restarting_state( mgr: &mut LlmpEventManager, -) -> Result<(Option>, LlmpRestartingEventManager), AflError> +) -> Result< + ( + Option>, + LlmpRestartingEventManager, + ), + AflError, +> where I: Input, C: Corpus, @@ -908,16 +914,18 @@ where None => { println!("First run. Let's set it all up"); // Mgr to send and receive msgs from/to all other fuzzer instances - let client_mgr = - LlmpEventManager::::existing_client_from_env(ENV_FUZZER_BROKER_CLIENT_INITIAL)?; + let client_mgr = LlmpEventManager::::existing_client_from_env( + ENV_FUZZER_BROKER_CLIENT_INITIAL, + )?; (None, LlmpRestartingEventManager::new(client_mgr, sender)) } // Restoring from a previous run, deserialize state and corpus. Some((_sender, _tag, msg)) => { println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len()); - let (state, mgr): (State, LlmpEventManager) = deserialize_state_mgr(&msg)?; - + let (state, mgr): (State, LlmpEventManager) = + deserialize_state_mgr(&msg)?; + (Some(state), LlmpRestartingEventManager::new(mgr, sender)) } }; diff --git a/afl/src/state/mod.rs b/afl/src/state/mod.rs index 88b6522349..a35f90d936 100644 --- a/afl/src/state/mod.rs +++ b/afl/src/state/mod.rs @@ -80,15 +80,13 @@ where R: Rand, FT: FeedbacksTuple, { - pub fn load_from_directory( + pub fn load_from_directory( &mut self, executor: &mut E, - generator: &mut G, manager: &mut EM, in_dir: &Path, ) -> Result<(), AflError> where - G: Generator, C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, @@ -114,29 +112,27 @@ where println!("File {:?} was not interesting, skipped.", &path); } } else if attr.is_dir() { - self.load_from_directory(executor, generator, manager, &path)?; + self.load_from_directory(executor, manager, &path)?; } } Ok(()) } - pub fn load_initial_inputs( + pub fn load_initial_inputs( &mut self, executor: &mut E, - generator: &mut G, manager: &mut EM, in_dirs: &[PathBuf], ) -> Result<(), AflError> where - G: Generator, C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, EM: EventManager, { for in_dir in in_dirs { - self.load_from_directory(executor, generator, manager, in_dir)?; + self.load_from_directory(executor, manager, in_dir)?; } manager.fire( self, diff --git a/fuzzers/libfuzzer_libpng/harness.cc b/fuzzers/libfuzzer_libpng/harness.cc index a615f70a43..baf1544e6d 100644 --- a/fuzzers/libfuzzer_libpng/harness.cc +++ b/fuzzers/libfuzzer_libpng/harness.cc @@ -20,6 +20,8 @@ #include +#define HAS_BUG 1 + #define PNG_INTERNAL #include "png.h" diff --git a/fuzzers/libfuzzer_libpng/src/mod.rs b/fuzzers/libfuzzer_libpng/src/mod.rs index 87054b7fcf..f4a5413f4d 100644 --- a/fuzzers/libfuzzer_libpng/src/mod.rs +++ b/fuzzers/libfuzzer_libpng/src/mod.rs @@ -1,3 +1,6 @@ +//! A libfuzzer-like fuzzer with llmp-multithreading support and restarts +//! The example harness is built for libpng. + #[macro_use] extern crate clap; @@ -6,6 +9,7 @@ use std::{env, path::PathBuf, process::Command}; use afl::{ corpus::{Corpus, InMemoryCorpus}, + events::setup_restarting_state, events::{LlmpEventManager, SimpleStats}, executors::{inprocess::InProcessExecutor, Executor, ExitKind}, feedbacks::MaxMapFeedback, @@ -17,8 +21,7 @@ use afl::{ stages::mutational::StdMutationalStage, state::{HasCorpus, State}, tuples::tuple_list, - utils::{ StdRand}, - events::setup_restarting_state, + utils::StdRand, AflError, Fuzzer, StdFuzzer, }; @@ -116,7 +119,7 @@ pub fn main() { /// The actual fuzzer fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { let mut rand = StdRand::new(0); - let mut generator = RandPrintablesGenerator::new(32); + /// TODO: Don't the stats need to be serialized, too? let stats = SimpleStats::new(|s| println!("{}", s)); let mut mgr = LlmpEventManager::new_on_port_std(stats, broker_port)?; @@ -126,27 +129,33 @@ fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { mgr.broker_loop()?; } - println!("We're a client, let's fuzz :)"); - - // Call LLVMFUzzerInitialize() if present. - unsafe { - if afl_libfuzzer_init() == -1 { - println!("Warning: LLVMFuzzerInitialize failed with -1") - } - } - let edges_observer = StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { __lafl_edges_map }, unsafe { __lafl_max_edges_size as usize }); - let (state_opt, mut restarting_mgr) = setup_restarting_state(&mut mgr).expect("Failed to setup the restarter".into()); + let mut mutator = HavocBytesMutator::new_default(); + mutator.set_max_size(4096); + let stage = StdMutationalStage::new(mutator); + let mut fuzzer = StdFuzzer::new(tuple_list!(stage)); + + // The restarting state will spawn the same process again as child, then restartet it each time it crashes. + let (state_opt, mut restarting_mgr) = + setup_restarting_state(&mut mgr).expect("Failed to setup the restarter".into()); let mut state = match state_opt { Some(s) => s, - None => State::new(InMemoryCorpus::new(), tuple_list!(MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer))) + None => State::new( + InMemoryCorpus::new(), + tuple_list!(MaxMapFeedback::new_with_observer( + &NAME_COV_MAP, + &edges_observer + )), + ), }; - // Create the engine + println!("We're a client, let's fuzz :)"); + + // Create the executor let mut executor = InProcessExecutor::new( "Libfuzzer", harness, @@ -155,29 +164,35 @@ fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { &mut restarting_mgr, ); + // The actual target run starts here. + + // Call LLVMFUzzerInitialize() if present. + unsafe { + if afl_libfuzzer_init() == -1 { + println!("Warning: LLVMFuzzerInitialize failed with -1") + } + } + // in case the corpus is empty (on first run), reset if state.corpus().count() < 1 { match input { Some(x) => state - .load_initial_inputs(&mut executor, &mut generator, &mut restarting_mgr, &x) + .load_initial_inputs(&mut executor, &mut restarting_mgr, &x) .expect(&format!("Failed to load initial corpus at {:?}", &x)), None => (), } println!("We imported {} inputs from disk.", state.corpus().count()); } + /* if state.corpus().count() < 1 { println!("Generating random inputs"); + let mut generator = RandPrintablesGenerator::new(32); state .generate_initial_inputs(&mut rand, &mut executor, &mut generator, &mut restarting_mgr, 4) .expect("Failed to generate initial inputs"); println!("We generated {} inputs.", state.corpus().count()); } - - let mut mutator = HavocBytesMutator::new_default(); - mutator.set_max_size(4096); - - let stage = StdMutationalStage::new(mutator); - let mut fuzzer = StdFuzzer::new(tuple_list!(stage)); + */ fuzzer.fuzz_loop(&mut rand, &mut executor, &mut state, &mut restarting_mgr) }