diff --git a/afl/src/corpus/testcase.rs b/afl/src/corpus/testcase.rs index 1512233e47..ee40ac419b 100644 --- a/afl/src/corpus/testcase.rs +++ b/afl/src/corpus/testcase.rs @@ -10,12 +10,9 @@ use core::default::Default; use core::option::Option; use hashbrown::HashMap; -#[cfg(feature = "std")] -use std::fs::File; -#[cfg(feature = "std")] -use std::io::Write; -#[cfg(feature = "std")] -use std::path::Path; +// TODO PathBuf for no_std and change filename to PathBuf +//#[cfg(feature = "std")] +//use std::path::PathBuf; // TODO: Give example /// Metadata for a testcase diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index e5faeffe12..c4440f42da 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -10,15 +10,15 @@ use core::marker::PhantomData; use hashbrown::HashMap; use crate::corpus::{Corpus, HasCorpus, Testcase}; -use crate::events::EventManager; +use crate::events::{EventManager, LoadInitialEvent}; use crate::executors::Executor; use crate::feedbacks::Feedback; use crate::generators::Generator; use crate::inputs::Input; use crate::observers::Observer; use crate::stages::Stage; -use crate::utils::Rand; -use crate::AflError; +use crate::utils::{current_milliseconds, Rand}; +use crate::{fire_event, AflError}; // TODO FeedbackMetadata to store histroy_map @@ -40,6 +40,22 @@ where /// Set executions fn set_executions(&mut self, executions: usize); + fn start_time(&self) -> u64; + fn set_start_time(&mut self, ms: u64); + + fn executions_over_seconds(&self) -> u64 { + let elapsed = current_milliseconds() - self.start_time(); + if elapsed == 0 { + return 0; + } + let elapsed = elapsed / 1000; + if elapsed == 0 { + 0 + } else { + (self.executions() as u64) / elapsed + } + } + /// Get all the metadatas into an HashMap fn metadatas(&self) -> &HashMap<&'static str, Box>; @@ -141,7 +157,7 @@ pub fn generate_initial_inputs( rand: &mut R, state: &mut S, generator: &mut G, - _events: &mut EM, + events: &mut EM, num: usize, ) -> Result<(), AflError> where @@ -151,12 +167,14 @@ where E: Executor, I: Input, R: Rand, - EM: EventManager, + EM: EventManager, { for _ in 0..num { let input = generator.generate(rand)?; state.load_initial_input(input)?; + fire_event!(events, LoadInitialEvent)?; } + events.process(state)?; Ok(()) } @@ -168,6 +186,7 @@ where R: Rand, { executions: usize, + start_time: u64, metadatas: HashMap<&'static str, Box>, // additional_corpuses: HashMap<&'static str, Box>, observers: Vec>>, @@ -209,6 +228,13 @@ where self.executions = executions } + fn start_time(&self) -> u64 { + self.start_time + } + fn set_start_time(&mut self, ms: u64) { + self.start_time = ms + } + fn metadatas(&self) -> &HashMap<&'static str, Box> { &self.metadatas } @@ -252,6 +278,7 @@ where pub fn new(corpus: C, executor: E) -> Self { StdState { executions: 0, + start_time: current_milliseconds(), metadatas: HashMap::default(), observers: vec![], feedbacks: vec![], @@ -265,7 +292,7 @@ where pub trait Engine where S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -289,6 +316,7 @@ where for stage in self.stages_mut() { stage.perform(rand, state, events, testcase.clone())?; } + events.process(state)?; Ok(idx) } @@ -302,7 +330,7 @@ where pub struct StdEngine where S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -315,7 +343,7 @@ where impl Engine for StdEngine where S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -333,7 +361,7 @@ where impl StdEngine where S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -351,6 +379,7 @@ where mod tests { use alloc::boxed::Box; + use std::io::stderr; use crate::corpus::{Corpus, InMemoryCorpus, Testcase}; use crate::engines::{Engine, StdEngine, StdState}; @@ -377,7 +406,7 @@ mod tests { let executor = InMemoryExecutor::::new(harness); let mut state = StdState::new(corpus, executor); - let mut events_manager = LoggerEventManager::new(); + let mut events_manager = LoggerEventManager::new(stderr()); let mut engine = StdEngine::new(); let mut mutator = StdScheduledMutator::new(); diff --git a/afl/src/events/llmp.rs b/afl/src/events/llmp.rs index 7c2e865b76..ba61178fc2 100644 --- a/afl/src/events/llmp.rs +++ b/afl/src/events/llmp.rs @@ -1,4 +1,4 @@ -use super::EventManager; +// use super::EventManager; pub struct LLMP {} diff --git a/afl/src/events/mod.rs b/afl/src/events/mod.rs index 2b32eb7df6..d5b1b3c95a 100644 --- a/afl/src/events/mod.rs +++ b/afl/src/events/mod.rs @@ -3,32 +3,46 @@ pub mod llmp_translated; // TODO: Abstract away. pub mod shmem_translated; pub use crate::events::llmp::LLMP; -use core::any::{Any, TypeId}; +use core::any::Any; +//use core::any::TypeId; use core::fmt::Display; +// TODO use core version +use std::io::Write; +use crate::corpus::Corpus; +use crate::engines::State; +use crate::executors::Executor; +use crate::inputs::Input; +use crate::utils::Rand; use crate::AflError; pub trait Event: Display + Any {} -pub trait EventManager { +pub trait EventManager +where + S: State, + C: Corpus, + E: Executor, + I: Input, + R: Rand, +{ /// Check if this EventaManager support a given Event type - fn enabled(&self) -> bool; - /* fn enabled(&self) -> bool { - match TypeId::of::() { - TypeId::of::() => true, - _ => false, - } - } */ + fn enabled(&self) -> bool + where + T: Event; /// Fire an Event - fn fire(&mut self, event: E) -> Result<(), AflError>; + fn fire(&mut self, event: T) -> Result<(), AflError> + where + T: Event; /// Lookup for incoming events and process them. /// Return the number of processes events or an error - fn lookup(&mut self) -> Result; + fn process(&mut self, state: &mut S) -> Result; } // e.g. fire_event!(manager, MyEvent, myparam1, ...) +#[macro_export] macro_rules! fire_event { ($manager:expr, $event:ty, $( $x:expr ),+ ) => { { @@ -50,53 +64,96 @@ macro_rules! fire_event { }; } -/* -#[derive(Debug)] -pub struct MyEvent {} -impl Event for MyEvent {} -impl MyEvent { - pub fn new() -> Self { - MyEvent {} +pub struct LoadInitialEvent {} +impl Event for LoadInitialEvent {} +impl Display for LoadInitialEvent { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Load") } } - -pub fn my_event_test(manager: &mut M) { - fire_event!(manager, MyEvent).unwrap(); +impl LoadInitialEvent { + pub fn new() -> Self { + LoadInitialEvent {} + } } -*/ pub struct NewTestcaseEvent {} impl Event for NewTestcaseEvent {} impl Display for NewTestcaseEvent { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "[NewTestcase] idx: ") + write!(f, "New") + } +} +impl NewTestcaseEvent { + pub fn new() -> Self { + NewTestcaseEvent {} } } -pub struct LoggerEventManager {} +pub struct LoggerEventManager +where + W: Write, +{ + events: Vec>, + writer: W, +} -impl EventManager for LoggerEventManager { - fn enabled(&self) -> bool { - let _new_testcase = TypeId::of::(); - match TypeId::of::() { - _new_testcase => true, - //_ => false, - } +impl EventManager for LoggerEventManager +where + S: State, + C: Corpus, + E: Executor, + I: Input, + R: Rand, + W: Write, +{ + fn enabled(&self) -> bool + where + T: Event, + { + true + /*let _load = TypeId::of::(); + let _new = TypeId::of::(); + match TypeId::of::() { + _load => true, + _new => true, + _ => false, + }*/ } - fn fire(&mut self, _event: E) -> Result<(), AflError> { - #[cfg(feature = "std")] - println!("{}", _event); + fn fire(&mut self, event: T) -> Result<(), AflError> + where + T: Event, + { + self.events.push(Box::new(event)); Ok(()) } - fn lookup(&mut self) -> Result { - Ok(0) + fn process(&mut self, state: &mut S) -> Result { + let num = self.events.len(); + for event in &self.events { + writeln!( + &mut self.writer, + "#{}\t[{}] corp: {} exec/s: {}", + state.executions(), + event, + state.corpus().entries().len(), + state.executions_over_seconds() + )?; + } + self.events.clear(); + Ok(num) } } -impl LoggerEventManager { - pub fn new() -> Self { - LoggerEventManager {} +impl LoggerEventManager +where + W: Write, +{ + pub fn new(writer: W) -> Self { + LoggerEventManager { + events: vec![], + writer: writer, + } } } diff --git a/afl/src/stages/mod.rs b/afl/src/stages/mod.rs index e951caca52..65894faa02 100644 --- a/afl/src/stages/mod.rs +++ b/afl/src/stages/mod.rs @@ -15,7 +15,7 @@ use core::cell::RefCell; pub trait Stage where S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, diff --git a/afl/src/stages/mutational.rs b/afl/src/stages/mutational.rs index 65f5021448..38e7db2eae 100644 --- a/afl/src/stages/mutational.rs +++ b/afl/src/stages/mutational.rs @@ -4,8 +4,9 @@ use core::marker::PhantomData; use crate::corpus::testcase::Testcase; use crate::engines::State; -use crate::events::EventManager; +use crate::events::{EventManager, NewTestcaseEvent}; use crate::executors::Executor; +use crate::fire_event; use crate::inputs::Input; use crate::mutators::Mutator; use crate::stages::Corpus; @@ -19,7 +20,7 @@ pub trait MutationalStage: Stage where M: Mutator, S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -52,6 +53,9 @@ where .mutate(rand, state.corpus_mut(), &mut input, i as i32)?; let (interesting, new_testcase) = state.evaluate_input(input)?; + if !new_testcase.is_none() { + fire_event!(events, NewTestcaseEvent)?; + } self.mutator_mut() .post_exec(interesting, new_testcase, i as i32)?; @@ -65,7 +69,7 @@ pub struct StdMutationalStage where M: Mutator, S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -80,7 +84,7 @@ impl MutationalStage where M: Mutator, S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -101,7 +105,7 @@ impl Stage for StdMutationalStage, S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, @@ -122,7 +126,7 @@ impl StdMutationalStage where M: Mutator, S: State, - EM: EventManager, + EM: EventManager, E: Executor, C: Corpus, I: Input, diff --git a/afl/src/utils.rs b/afl/src/utils.rs index b6be491b46..e02d23f1a0 100644 --- a/afl/src/utils.rs +++ b/afl/src/utils.rs @@ -165,6 +165,19 @@ impl Xoshiro256StarRand { } } +#[cfg(feature = "std")] +pub fn current_milliseconds() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64 +} + +#[cfg(not(feature = "std"))] +pub fn current_milliseconds() -> u64 { + 1000 +} + /// fake rand, for testing purposes #[cfg(test)] #[derive(Copy, Clone, Debug, Default)] @@ -197,42 +210,6 @@ impl XKCDRand { } } -/* -/// A very basic HasRand -pub struct StdHasRand -where - R: Rand, -{ - rand: Rc>, -} - -/// A very basic HasRand -impl HasRand for StdHasRand -where - R: Rand, -{ - type R = R; - - /// Get the rand rc refcell - fn rand(&self) -> &Rc> { - &self.rand - } -} - -/// A very basic HasRand -impl StdHasRand -where - R: Rand, -{ - /// Create a new StdHasRand, cloning the refcell - pub fn new(rand: &Rc>) -> Self { - Self { - rand: Rc::clone(rand), - } - } -} -*/ - /// Get the next higher power of two pub const fn next_pow2(val: u64) -> u64 { let mut out = val.wrapping_sub(1); @@ -246,7 +223,7 @@ pub const fn next_pow2(val: u64) -> u64 { #[cfg(test)] mod tests { - use crate::utils::{next_pow2, HasRand, Rand, StdRand}; + use crate::utils::{next_pow2, Rand, StdRand}; #[test] fn test_rand() { @@ -271,17 +248,6 @@ mod tests { assert!(rand.between(11, 20) > 10); } - /* - #[test] - fn test_has_rand() { - let rand = StdRand::new(0).into(); - let has_rand = StdHasRand::new(&rand); - - assert!(has_rand.rand_below(100) < 100); - assert_eq!(has_rand.rand_below(1), 0); - } - */ - #[test] fn test_next_pow2() { assert_eq!(next_pow2(0), 0); diff --git a/fuzzers/libfuzzer/src/lib.rs b/fuzzers/libfuzzer/src/lib.rs index 4c366ebff3..17fb1e6409 100644 --- a/fuzzers/libfuzzer/src/lib.rs +++ b/fuzzers/libfuzzer/src/lib.rs @@ -1,20 +1,15 @@ -#![cfg_attr(not(feature = "std"), no_std)] +use std::boxed::Box; +use std::cell::RefCell; +use std::io::stderr; +use std::rc::Rc; -#[macro_use] -extern crate alloc; - -use alloc::boxed::Box; -use alloc::rc::Rc; -use core::cell::RefCell; - -use afl::corpus::{Corpus, InMemoryCorpus, Testcase}; +use afl::corpus::InMemoryCorpus; use afl::engines::{generate_initial_inputs, Engine, State, StdEngine, StdState}; use afl::events::LoggerEventManager; use afl::executors::inmemory::InMemoryExecutor; use afl::executors::{Executor, ExitKind}; use afl::feedbacks::{create_history_map, MaxMapFeedback}; -use afl::generators::{Generator, RandPrintablesGenerator}; -use afl::inputs::bytes::BytesInput; +use afl::generators::RandPrintablesGenerator; use afl::mutators::scheduled::HavocBytesMutator; use afl::observers::StdMapObserver; use afl::stages::mutational::StdMutationalStage; @@ -45,7 +40,7 @@ pub extern "C" fn afl_libfuzzer_main() { let corpus = InMemoryCorpus::new(); let mut generator = RandPrintablesGenerator::new(4096); - let mut events = LoggerEventManager::new(); + let mut events = LoggerEventManager::new(stderr()); let edges_observer = Rc::new(RefCell::new(StdMapObserver::new_from_ptr( unsafe { __lafl_edges_map }, diff --git a/fuzzers/libfuzzer/test/test.c b/fuzzers/libfuzzer/test/test.c index cca0f8e78c..1e8eb75bbc 100755 --- a/fuzzers/libfuzzer/test/test.c +++ b/fuzzers/libfuzzer/test/test.c @@ -13,14 +13,16 @@ int target_func(const uint8_t *buf, size_t size) { case 1: if (buf[1] == 0x44) { - __builtin_trap(); + //__builtin_trap(); + return 8; } break; case 0xff: if (buf[2] == 0xff) { if (buf[1] == 0x44) { - *(char *)(0xdeadbeef) = 1; + //*(char *)(0xdeadbeef) = 1; + return 9; } }