basic events

This commit is contained in:
Andrea Fioraldi 2020-11-23 13:06:24 +01:00
parent 0a22db2db9
commit 21de5efc98
9 changed files with 175 additions and 125 deletions

View File

@ -10,12 +10,9 @@ use core::default::Default;
use core::option::Option; use core::option::Option;
use hashbrown::HashMap; use hashbrown::HashMap;
#[cfg(feature = "std")] // TODO PathBuf for no_std and change filename to PathBuf
use std::fs::File; //#[cfg(feature = "std")]
#[cfg(feature = "std")] //use std::path::PathBuf;
use std::io::Write;
#[cfg(feature = "std")]
use std::path::Path;
// TODO: Give example // TODO: Give example
/// Metadata for a testcase /// Metadata for a testcase

View File

@ -10,15 +10,15 @@ use core::marker::PhantomData;
use hashbrown::HashMap; use hashbrown::HashMap;
use crate::corpus::{Corpus, HasCorpus, Testcase}; use crate::corpus::{Corpus, HasCorpus, Testcase};
use crate::events::EventManager; use crate::events::{EventManager, LoadInitialEvent};
use crate::executors::Executor; use crate::executors::Executor;
use crate::feedbacks::Feedback; use crate::feedbacks::Feedback;
use crate::generators::Generator; use crate::generators::Generator;
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::Observer; use crate::observers::Observer;
use crate::stages::Stage; use crate::stages::Stage;
use crate::utils::Rand; use crate::utils::{current_milliseconds, Rand};
use crate::AflError; use crate::{fire_event, AflError};
// TODO FeedbackMetadata to store histroy_map // TODO FeedbackMetadata to store histroy_map
@ -40,6 +40,22 @@ where
/// Set executions /// Set executions
fn set_executions(&mut self, executions: usize); 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 /// Get all the metadatas into an HashMap
fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>>; fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>>;
@ -141,7 +157,7 @@ pub fn generate_initial_inputs<S, G, C, E, I, R, EM>(
rand: &mut R, rand: &mut R,
state: &mut S, state: &mut S,
generator: &mut G, generator: &mut G,
_events: &mut EM, events: &mut EM,
num: usize, num: usize,
) -> Result<(), AflError> ) -> Result<(), AflError>
where where
@ -151,12 +167,14 @@ where
E: Executor<I>, E: Executor<I>,
I: Input, I: Input,
R: Rand, R: Rand,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
{ {
for _ in 0..num { for _ in 0..num {
let input = generator.generate(rand)?; let input = generator.generate(rand)?;
state.load_initial_input(input)?; state.load_initial_input(input)?;
fire_event!(events, LoadInitialEvent)?;
} }
events.process(state)?;
Ok(()) Ok(())
} }
@ -168,6 +186,7 @@ where
R: Rand, R: Rand,
{ {
executions: usize, executions: usize,
start_time: u64,
metadatas: HashMap<&'static str, Box<dyn StateMetadata>>, metadatas: HashMap<&'static str, Box<dyn StateMetadata>>,
// additional_corpuses: HashMap<&'static str, Box<dyn Corpus>>, // additional_corpuses: HashMap<&'static str, Box<dyn Corpus>>,
observers: Vec<Rc<RefCell<dyn Observer>>>, observers: Vec<Rc<RefCell<dyn Observer>>>,
@ -209,6 +228,13 @@ where
self.executions = executions 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<dyn StateMetadata>> { fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>> {
&self.metadatas &self.metadatas
} }
@ -252,6 +278,7 @@ where
pub fn new(corpus: C, executor: E) -> Self { pub fn new(corpus: C, executor: E) -> Self {
StdState { StdState {
executions: 0, executions: 0,
start_time: current_milliseconds(),
metadatas: HashMap::default(), metadatas: HashMap::default(),
observers: vec![], observers: vec![],
feedbacks: vec![], feedbacks: vec![],
@ -265,7 +292,7 @@ where
pub trait Engine<S, EM, E, C, I, R> pub trait Engine<S, EM, E, C, I, R>
where where
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
@ -289,6 +316,7 @@ where
for stage in self.stages_mut() { for stage in self.stages_mut() {
stage.perform(rand, state, events, testcase.clone())?; stage.perform(rand, state, events, testcase.clone())?;
} }
events.process(state)?;
Ok(idx) Ok(idx)
} }
@ -302,7 +330,7 @@ where
pub struct StdEngine<S, EM, E, C, I, R> pub struct StdEngine<S, EM, E, C, I, R>
where where
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
@ -315,7 +343,7 @@ where
impl<S, EM, E, C, I, R> Engine<S, EM, E, C, I, R> for StdEngine<S, EM, E, C, I, R> impl<S, EM, E, C, I, R> Engine<S, EM, E, C, I, R> for StdEngine<S, EM, E, C, I, R>
where where
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
@ -333,7 +361,7 @@ where
impl<S, EM, E, C, I, R> StdEngine<S, EM, E, C, I, R> impl<S, EM, E, C, I, R> StdEngine<S, EM, E, C, I, R>
where where
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
@ -351,6 +379,7 @@ where
mod tests { mod tests {
use alloc::boxed::Box; use alloc::boxed::Box;
use std::io::stderr;
use crate::corpus::{Corpus, InMemoryCorpus, Testcase}; use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
use crate::engines::{Engine, StdEngine, StdState}; use crate::engines::{Engine, StdEngine, StdState};
@ -377,7 +406,7 @@ mod tests {
let executor = InMemoryExecutor::<BytesInput>::new(harness); let executor = InMemoryExecutor::<BytesInput>::new(harness);
let mut state = StdState::new(corpus, executor); 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 engine = StdEngine::new();
let mut mutator = StdScheduledMutator::new(); let mut mutator = StdScheduledMutator::new();

View File

@ -1,4 +1,4 @@
use super::EventManager; // use super::EventManager;
pub struct LLMP {} pub struct LLMP {}

View File

@ -3,32 +3,46 @@ pub mod llmp_translated; // TODO: Abstract away.
pub mod shmem_translated; pub mod shmem_translated;
pub use crate::events::llmp::LLMP; pub use crate::events::llmp::LLMP;
use core::any::{Any, TypeId}; use core::any::Any;
//use core::any::TypeId;
use core::fmt::Display; 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; use crate::AflError;
pub trait Event: Display + Any {} pub trait Event: Display + Any {}
pub trait EventManager { pub trait EventManager<S, C, E, I, R>
where
S: State<C, E, I, R>,
C: Corpus<I, R>,
E: Executor<I>,
I: Input,
R: Rand,
{
/// Check if this EventaManager support a given Event type /// Check if this EventaManager support a given Event type
fn enabled<E: Event>(&self) -> bool; fn enabled<T>(&self) -> bool
/* fn enabled<E: Event>(&self) -> bool { where
match TypeId::of::<E>() { T: Event;
TypeId::of::<MyEvent>() => true,
_ => false,
}
} */
/// Fire an Event /// Fire an Event
fn fire<E: Event>(&mut self, event: E) -> Result<(), AflError>; fn fire<T>(&mut self, event: T) -> Result<(), AflError>
where
T: Event;
/// Lookup for incoming events and process them. /// Lookup for incoming events and process them.
/// Return the number of processes events or an error /// Return the number of processes events or an error
fn lookup(&mut self) -> Result<usize, AflError>; fn process(&mut self, state: &mut S) -> Result<usize, AflError>;
} }
// e.g. fire_event!(manager, MyEvent, myparam1, ...) // e.g. fire_event!(manager, MyEvent, myparam1, ...)
#[macro_export]
macro_rules! fire_event { macro_rules! fire_event {
($manager:expr, $event:ty, $( $x:expr ),+ ) => { ($manager:expr, $event:ty, $( $x:expr ),+ ) => {
{ {
@ -50,53 +64,96 @@ macro_rules! fire_event {
}; };
} }
/* pub struct LoadInitialEvent {}
#[derive(Debug)] impl Event for LoadInitialEvent {}
pub struct MyEvent {} impl Display for LoadInitialEvent {
impl Event for MyEvent {} fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
impl MyEvent { write!(f, "Load")
}
}
impl LoadInitialEvent {
pub fn new() -> Self { pub fn new() -> Self {
MyEvent {} LoadInitialEvent {}
} }
} }
pub fn my_event_test<M: EventManager>(manager: &mut M) {
fire_event!(manager, MyEvent).unwrap();
}
*/
pub struct NewTestcaseEvent {} pub struct NewTestcaseEvent {}
impl Event for NewTestcaseEvent {} impl Event for NewTestcaseEvent {}
impl Display for NewTestcaseEvent { impl Display for NewTestcaseEvent {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 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<W>
where
impl EventManager for LoggerEventManager { W: Write,
fn enabled<E: Event>(&self) -> bool { {
let _new_testcase = TypeId::of::<NewTestcaseEvent>(); events: Vec<Box<dyn Event>>,
match TypeId::of::<E>() { writer: W,
_new_testcase => true,
//_ => false,
}
} }
fn fire<E: Event>(&mut self, _event: E) -> Result<(), AflError> { impl<S, C, E, I, R, W> EventManager<S, C, E, I, R> for LoggerEventManager<W>
#[cfg(feature = "std")] where
println!("{}", _event); S: State<C, E, I, R>,
C: Corpus<I, R>,
E: Executor<I>,
I: Input,
R: Rand,
W: Write,
{
fn enabled<T>(&self) -> bool
where
T: Event,
{
true
/*let _load = TypeId::of::<LoadInitialEvent>();
let _new = TypeId::of::<NewTestcaseEvent>();
match TypeId::of::<T>() {
_load => true,
_new => true,
_ => false,
}*/
}
fn fire<T>(&mut self, event: T) -> Result<(), AflError>
where
T: Event,
{
self.events.push(Box::new(event));
Ok(()) Ok(())
} }
fn lookup(&mut self) -> Result<usize, AflError> { fn process(&mut self, state: &mut S) -> Result<usize, AflError> {
Ok(0) 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 { impl<W> LoggerEventManager<W>
pub fn new() -> Self { where
LoggerEventManager {} W: Write,
{
pub fn new(writer: W) -> Self {
LoggerEventManager {
events: vec![],
writer: writer,
}
} }
} }

View File

@ -15,7 +15,7 @@ use core::cell::RefCell;
pub trait Stage<S, EM, E, C, I, R> pub trait Stage<S, EM, E, C, I, R>
where where
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,

View File

@ -4,8 +4,9 @@ use core::marker::PhantomData;
use crate::corpus::testcase::Testcase; use crate::corpus::testcase::Testcase;
use crate::engines::State; use crate::engines::State;
use crate::events::EventManager; use crate::events::{EventManager, NewTestcaseEvent};
use crate::executors::Executor; use crate::executors::Executor;
use crate::fire_event;
use crate::inputs::Input; use crate::inputs::Input;
use crate::mutators::Mutator; use crate::mutators::Mutator;
use crate::stages::Corpus; use crate::stages::Corpus;
@ -19,7 +20,7 @@ pub trait MutationalStage<M, S, EM, E, C, I, R>: Stage<S, EM, E, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
@ -52,6 +53,9 @@ where
.mutate(rand, state.corpus_mut(), &mut input, i as i32)?; .mutate(rand, state.corpus_mut(), &mut input, i as i32)?;
let (interesting, new_testcase) = state.evaluate_input(input)?; let (interesting, new_testcase) = state.evaluate_input(input)?;
if !new_testcase.is_none() {
fire_event!(events, NewTestcaseEvent)?;
}
self.mutator_mut() self.mutator_mut()
.post_exec(interesting, new_testcase, i as i32)?; .post_exec(interesting, new_testcase, i as i32)?;
@ -65,7 +69,7 @@ pub struct StdMutationalStage<M, S, EM, E, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
@ -80,7 +84,7 @@ impl<M, S, EM, E, C, I, R> MutationalStage<M, S, EM, E, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
@ -101,7 +105,7 @@ impl<M, S, EM, E, C, I, R> Stage<S, EM, E, C, I, R> for StdMutationalStage<M, S,
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,
@ -122,7 +126,7 @@ impl<M, S, EM, E, C, I, R> StdMutationalStage<M, S, EM, E, C, I, R>
where where
M: Mutator<C, I, R>, M: Mutator<C, I, R>,
S: State<C, E, I, R>, S: State<C, E, I, R>,
EM: EventManager, EM: EventManager<S, C, E, I, R>,
E: Executor<I>, E: Executor<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
I: Input, I: Input,

View File

@ -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 /// fake rand, for testing purposes
#[cfg(test)] #[cfg(test)]
#[derive(Copy, Clone, Debug, Default)] #[derive(Copy, Clone, Debug, Default)]
@ -197,42 +210,6 @@ impl XKCDRand {
} }
} }
/*
/// A very basic HasRand
pub struct StdHasRand<R>
where
R: Rand,
{
rand: Rc<RefCell<R>>,
}
/// A very basic HasRand
impl<R> HasRand for StdHasRand<R>
where
R: Rand,
{
type R = R;
/// Get the rand rc refcell
fn rand(&self) -> &Rc<RefCell<R>> {
&self.rand
}
}
/// A very basic HasRand
impl<R> StdHasRand<R>
where
R: Rand,
{
/// Create a new StdHasRand, cloning the refcell
pub fn new(rand: &Rc<RefCell<R>>) -> Self {
Self {
rand: Rc::clone(rand),
}
}
}
*/
/// Get the next higher power of two /// Get the next higher power of two
pub const fn next_pow2(val: u64) -> u64 { pub const fn next_pow2(val: u64) -> u64 {
let mut out = val.wrapping_sub(1); let mut out = val.wrapping_sub(1);
@ -246,7 +223,7 @@ pub const fn next_pow2(val: u64) -> u64 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::utils::{next_pow2, HasRand, Rand, StdRand}; use crate::utils::{next_pow2, Rand, StdRand};
#[test] #[test]
fn test_rand() { fn test_rand() {
@ -271,17 +248,6 @@ mod tests {
assert!(rand.between(11, 20) > 10); 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] #[test]
fn test_next_pow2() { fn test_next_pow2() {
assert_eq!(next_pow2(0), 0); assert_eq!(next_pow2(0), 0);

View File

@ -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] use afl::corpus::InMemoryCorpus;
extern crate alloc;
use alloc::boxed::Box;
use alloc::rc::Rc;
use core::cell::RefCell;
use afl::corpus::{Corpus, InMemoryCorpus, Testcase};
use afl::engines::{generate_initial_inputs, Engine, State, StdEngine, StdState}; use afl::engines::{generate_initial_inputs, Engine, State, StdEngine, StdState};
use afl::events::LoggerEventManager; use afl::events::LoggerEventManager;
use afl::executors::inmemory::InMemoryExecutor; use afl::executors::inmemory::InMemoryExecutor;
use afl::executors::{Executor, ExitKind}; use afl::executors::{Executor, ExitKind};
use afl::feedbacks::{create_history_map, MaxMapFeedback}; use afl::feedbacks::{create_history_map, MaxMapFeedback};
use afl::generators::{Generator, RandPrintablesGenerator}; use afl::generators::RandPrintablesGenerator;
use afl::inputs::bytes::BytesInput;
use afl::mutators::scheduled::HavocBytesMutator; use afl::mutators::scheduled::HavocBytesMutator;
use afl::observers::StdMapObserver; use afl::observers::StdMapObserver;
use afl::stages::mutational::StdMutationalStage; use afl::stages::mutational::StdMutationalStage;
@ -45,7 +40,7 @@ pub extern "C" fn afl_libfuzzer_main() {
let corpus = InMemoryCorpus::new(); let corpus = InMemoryCorpus::new();
let mut generator = RandPrintablesGenerator::new(4096); 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( let edges_observer = Rc::new(RefCell::new(StdMapObserver::new_from_ptr(
unsafe { __lafl_edges_map }, unsafe { __lafl_edges_map },

View File

@ -13,14 +13,16 @@ int target_func(const uint8_t *buf, size_t size) {
case 1: case 1:
if (buf[1] == 0x44) { if (buf[1] == 0x44) {
__builtin_trap(); //__builtin_trap();
return 8;
} }
break; break;
case 0xff: case 0xff:
if (buf[2] == 0xff) { if (buf[2] == 0xff) {
if (buf[1] == 0x44) { if (buf[1] == 0x44) {
*(char *)(0xdeadbeef) = 1; //*(char *)(0xdeadbeef) = 1;
return 9;
} }
} }