diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index 1d350ac179..f554ef7244 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -89,7 +89,7 @@ where println!("Loading file {:?} ...", &path); let bytes = std::fs::read(&path)?; let input = BytesInput::new(bytes); - let fitness = self.evaluate_input(&input, engine.executor_mut())?; + let fitness = self.evaluate_input(&input, engine.executor_mut(), corpus, manager)?; if self.add_if_interesting(corpus, input, fitness)?.is_none() { println!("File {:?} was not interesting, skipped.", &path); } @@ -224,10 +224,15 @@ where where E: Executor + HasObservers, OT: ObserversTuple, + C: Corpus, + EM: EventManager, { executor.pre_exec_observers()?; - executor.run_target(&input, &self, &corpus, &mut event_mgr)?; + executor.pre_exec(&self, corpus, event_mgr, input)?; + executor.run_target(input)?; + executor.post_exec(&self, corpus, event_mgr, input)?; + self.set_executions(self.executions() + 1); executor.post_exec_observers()?; @@ -307,7 +312,7 @@ where let mut added = 0; for _ in 0..num { let input = generator.generate(rand)?; - let fitness = self.evaluate_input(&input, engine.executor_mut())?; + let fitness = self.evaluate_input(&input, engine.executor_mut(), corpus, manager)?; if !self.add_if_interesting(corpus, input, fitness)?.is_none() { added += 1; } diff --git a/afl/src/executors/inmemory.rs b/afl/src/executors/inmemory.rs index 6389619bc4..b0cdb54c11 100644 --- a/afl/src/executors/inmemory.rs +++ b/afl/src/executors/inmemory.rs @@ -1,6 +1,5 @@ -use alloc::boxed::Box; -use core::{ffi::c_void, ptr}; use os_signals::set_oncrash_ptrs; +use core::marker::PhantomData; use crate::{ corpus::Corpus, @@ -24,88 +23,96 @@ use self::os_signals::reset_oncrash_ptrs; use self::os_signals::setup_crash_handlers; /// The inmem executor harness -type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; -type OnCrashFunction = dyn FnMut(ExitKind, &I, &State, &C, &mut EM); +type HarnessFunction = fn(&E, &[u8]) -> ExitKind; /// The inmem executor simply calls a target function, then returns afterwards. -pub struct InMemoryExecutor +pub struct InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, - C: Corpus, - EM: EventManager, - FT: FeedbacksTuple, - R: Rand, { /// The name of this executor instance, to address it from other components name: &'static str, /// The harness function, being executed for each fuzzing loop execution - harness_fn: HarnessFunction, + harness_fn: HarnessFunction, /// The observers, observing each run observers: OT, - /// A special function being called right before the process crashes. It may save state to restore fuzzing after respawn. - on_crash_fn: Box>, + phantom: PhantomData, } -impl Executor for InMemoryExecutor +impl Executor for InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, - C: Corpus, - EM: EventManager, - FT: FeedbacksTuple, - R: Rand, { - #[inline] - fn run_target( + + fn pre_exec( &mut self, - input: &I, - state: State, + state: &State, corpus: &C, - event_mgr: &EM, - ) -> Result { - #[cfg(unix)] + event_mgr: &mut EM, + input: &I, + ) -> Result<(), AflError> where + R: Rand , + FT: FeedbacksTuple, + C: Corpus, + EM: EventManager, + { + #[cfg(unix)] unsafe { set_oncrash_ptrs::( state, corpus, event_mgr, input, - &mut self.on_crash_fn, ); } - let bytes = input.target_bytes(); - let ret = (self.harness_fn)(self, bytes.as_slice()); + Ok(()) + } + + fn post_exec( + &mut self, + _state: &State, + _corpus: &C, + _event_mgr: &mut EM, + _input: &I, + ) -> Result<(), AflError> where + R: Rand , + FT: FeedbacksTuple, + C: Corpus, + EM: EventManager, { #[cfg(unix)] unsafe { reset_oncrash_ptrs::(); } + Ok(()) + } + + #[inline] + fn run_target( + &mut self, + input: &I, + ) -> Result { + let bytes = input.target_bytes(); + let ret = (self.harness_fn)(self, bytes.as_slice()); Ok(ret) } } -impl Named for InMemoryExecutor +impl Named for InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, - C: Corpus, - EM: EventManager, - FT: FeedbacksTuple, - R: Rand, { fn name(&self) -> &str { self.name } } -impl HasObservers for InMemoryExecutor +impl HasObservers for InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, - C: Corpus, - EM: EventManager, - FT: FeedbacksTuple, - R: Rand, { #[inline] fn observers(&self) -> &OT { @@ -118,14 +125,10 @@ where } } -impl InMemoryExecutor +impl InMemoryExecutor where I: Input + HasTargetBytes, OT: ObserversTuple, - C: Corpus, - EM: EventManager, - FT: FeedbacksTuple, - R: Rand, { /// Create a new in mem executor. /// Caution: crash and restart in one of them will lead to odd behavior if multiple are used, @@ -135,15 +138,18 @@ where /// * `on_crash_fn` - When an in-mem harness crashes, it may safe some state to continue fuzzing later. /// Do that that in this function. The program will crash afterwards. /// * `observers` - the observers observing the target during execution - pub fn new( + pub fn new( name: &'static str, - harness_fn: HarnessFunction, + harness_fn: HarnessFunction, observers: OT, - on_crash_fn: Box>, _state: &State, _corpus: &C, _event_mgr: &mut EM, - ) -> Self { + ) -> Self where + R: Rand , + FT: FeedbacksTuple, + C: Corpus, + EM: EventManager, { #[cfg(feature = "std")] unsafe { setup_crash_handlers::(); @@ -151,9 +157,9 @@ where Self { harness_fn, - on_crash_fn, observers, name, + phantom: PhantomData } } } @@ -200,7 +206,6 @@ pub mod unix_signals { corpus::Corpus, engines::State, events::EventManager, - executors::inmemory::{ExitKind, OnCrashFunction}, feedbacks::FeedbacksTuple, inputs::Input, observers::ObserversTuple, @@ -209,13 +214,12 @@ pub mod unix_signals { /// Pointers to values only needed on crash. As the program will not continue after a crash, /// we should (tm) be okay with raw pointers here, - static mut corpus_ptr: *const c_void = ptr::null_mut(); - static mut state_ptr: *const c_void = ptr::null_mut(); - static mut event_mgr_ptr: *mut c_void = ptr::null_mut(); + static mut CORPUS_PTR: *const c_void = ptr::null_mut(); + static mut STATE_PTR: *const c_void = ptr::null_mut(); + static mut EVENT_MGR_PTR: *mut c_void = ptr::null_mut(); /// The (unsafe) pointer to the current inmem input, for the current run. /// This is neede for certain non-rust side effects, as well as unix signal handling. - static mut current_input_ptr: *const c_void = ptr::null(); - static mut on_crash_fn_ptr: *mut c_void = ptr::null_mut(); + static mut CURRENT_INPUT_PTR: *const c_void = ptr::null(); pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash( _sig: c_int, @@ -229,7 +233,7 @@ pub mod unix_signals { I: Input, R: Rand, { - if current_input_ptr == ptr::null() { + if CURRENT_INPUT_PTR == ptr::null() { println!( "We died accessing addr {}, but are not in client... Exiting.", info.si_addr() as usize @@ -243,10 +247,10 @@ pub mod unix_signals { #[cfg(feature = "std")] let _ = stdout().flush(); - let input = (current_input_ptr as *const I).as_ref().unwrap(); - let corpus = (corpus_ptr as *const C).as_ref().unwrap(); - let state = (event_mgr_ptr as *const State).as_ref().unwrap(); - let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap(); + /*let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); + let corpus = (CORPUS_PTR as *const C).as_ref().unwrap(); + let state = (EVENT_MGR_PTR as *const State).as_ref().unwrap(); + let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap(); if !on_crash_fn_ptr.is_null() { (*(on_crash_fn_ptr as *mut Box>))( @@ -256,7 +260,7 @@ pub mod unix_signals { corpus, manager, ); - } + }*/ std::process::exit(139); } @@ -274,15 +278,15 @@ pub mod unix_signals { R: Rand, { dbg!("TIMEOUT/SIGUSR2 received"); - if current_input_ptr.is_null() { + if CURRENT_INPUT_PTR.is_null() { dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting"); return; } - let input = (current_input_ptr as *const I).as_ref().unwrap(); - let corpus = (corpus_ptr as *const C).as_ref().unwrap(); - let state = (event_mgr_ptr as *const State).as_ref().unwrap(); - let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap(); + /*let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); + let corpus = (CORPUS_PTR as *const C).as_ref().unwrap(); + let state = (EVENT_MGR_PTR as *const State).as_ref().unwrap(); + let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap(); if !on_crash_fn_ptr.is_null() { (*(on_crash_fn_ptr as *mut Box>))( @@ -292,7 +296,7 @@ pub mod unix_signals { corpus, manager, ); - } + }*/ /* TODO: If we want to be on the safe side, we really need to do this: match manager.llmp { @@ -317,8 +321,7 @@ pub mod unix_signals { state: &State, corpus: &C, event_mgr: &mut EM, - input: I, - on_crash_handler: &mut Box>, + input: &I, ) where EM: EventManager, C: Corpus, @@ -327,20 +330,18 @@ pub mod unix_signals { I: Input, R: Rand, { - current_input_ptr = input as *const _ as *const c_void; - corpus_ptr = corpus as *const _ as *const c_void; - state_ptr = state as *const _ as *const c_void; - event_mgr_ptr = event_mgr as *mut _ as *mut c_void; - on_crash_fn_ptr = on_crash_handler as *mut _ as *mut c_void; + CURRENT_INPUT_PTR = input as *const _ as *const c_void; + CORPUS_PTR = corpus as *const _ as *const c_void; + STATE_PTR = state as *const _ as *const c_void; + EVENT_MGR_PTR = event_mgr as *mut _ as *mut c_void; } #[inline] pub unsafe fn reset_oncrash_ptrs() { - current_input_ptr = ptr::null(); - corpus_ptr = ptr::null(); - state_ptr = ptr::null(); - event_mgr_ptr = ptr::null_mut(); - on_crash_fn_ptr = ptr::null_mut(); + CURRENT_INPUT_PTR = ptr::null(); + CORPUS_PTR = ptr::null(); + STATE_PTR = ptr::null(); + EVENT_MGR_PTR = ptr::null_mut(); } // TODO clearly state that manager should be static (maybe put the 'static lifetime?) diff --git a/afl/src/executors/mod.rs b/afl/src/executors/mod.rs index cef91a313c..a9cd1f3eea 100644 --- a/afl/src/executors/mod.rs +++ b/afl/src/executors/mod.rs @@ -7,6 +7,10 @@ use core::marker::PhantomData; use crate::{ engines::State, + corpus::Corpus, + feedbacks::FeedbacksTuple, + events::EventManager, + utils::Rand, inputs::{HasTargetBytes, Input}, observers::ObserversTuple, tuples::{MatchNameAndType, MatchType, Named, TupleList}, @@ -74,30 +78,52 @@ pub trait Executor: Named where I: Input, { - /// Instruct the target about the input and run - fn run_target( + fn pre_exec( &mut self, - input: &I, - state: &State, - corpus: &C, - event_mgr: &EM, + _state: &State, + _corpus: &C, + _event_mgr: &mut EM, + _input: &I, + ) -> Result<(), AflError> where + R: Rand , + FT: FeedbacksTuple, + C: Corpus, + EM: EventManager, { Ok(()) } + + fn post_exec( + &mut self, + _state: &State, + _corpus: &C, + _event_mgr: &mut EM, + _input: &I, + ) -> Result<(), AflError> where + R: Rand , + FT: FeedbacksTuple, + C: Corpus, + EM: EventManager, { Ok(()) } + + /// Instruct the target about the input and run + fn run_target( + &mut self, + input: &I ) -> Result; + } pub trait ExecutorsTuple: MatchType + MatchNameAndType where I: Input, { - fn for_each(&self, f: fn(&dyn Executor)); - fn for_each_mut(&mut self, f: fn(&mut dyn Executor)); + //fn for_each(&self, f: fn(&dyn Executor)); + //fn for_each_mut(&mut self, f: fn(&mut dyn Executor)); } impl ExecutorsTuple for () where I: Input, { - fn for_each(&self, _f: fn(&dyn Executor)) {} - fn for_each_mut(&mut self, _f: fn(&mut dyn Executor)) {} + //fn for_each(&self, _f: fn(&dyn Executor)) {} + //fn for_each_mut(&mut self, _f: fn(&mut dyn Executor)) {} } impl ExecutorsTuple for (Head, Tail) @@ -106,7 +132,7 @@ where Tail: ExecutorsTuple + TupleList, I: Input, { - fn for_each(&self, f: fn(&dyn Executor)) { + /*fn for_each(&self, f: fn(&dyn Executor)) { f(&self.0); self.1.for_each(f) } @@ -114,7 +140,7 @@ where fn for_each_mut(&mut self, f: fn(&mut dyn Executor)) { f(&mut self.0); self.1.for_each_mut(f) - } + }*/ } #[cfg(test)] diff --git a/afl/src/stages/mutational.rs b/afl/src/stages/mutational.rs index ea0c6cacf0..1937769fd7 100644 --- a/afl/src/stages/mutational.rs +++ b/afl/src/stages/mutational.rs @@ -61,7 +61,7 @@ where self.mutator_mut() .mutate(rand, corpus, &mut input_mut, i as i32)?; - let fitness = state.evaluate_input(&input_mut, engine.executor_mut())?; + let fitness = state.evaluate_input(&input_mut, engine.executor_mut(), corpus, manager)?; self.mutator_mut() .post_exec(fitness, &input_mut, i as i32)?;