From 069c559804318d97b6e46602fe50b07bb195bea3 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Sat, 31 Oct 2020 12:17:57 +0100 Subject: [PATCH] scheduled mutator --- src/inputs/bytes.rs | 2 +- src/inputs/mod.rs | 1 + src/mutators/mod.rs | 21 +++---- src/mutators/scheduled.rs | 118 ++++++++++++++++++++++++++++++++------ 4 files changed, 113 insertions(+), 29 deletions(-) diff --git a/src/inputs/bytes.rs b/src/inputs/bytes.rs index 9119ff513a..04594c5f37 100644 --- a/src/inputs/bytes.rs +++ b/src/inputs/bytes.rs @@ -3,7 +3,7 @@ use crate::AflError; #[derive(Clone, Debug, Default)] pub struct BytesInput { - bytes: Vec, + pub bytes: Vec, } impl Input for BytesInput { diff --git a/src/inputs/mod.rs b/src/inputs/mod.rs index 36c005d4bf..c8854a4d60 100644 --- a/src/inputs/mod.rs +++ b/src/inputs/mod.rs @@ -1,4 +1,5 @@ pub mod bytes; +pub use bytes::BytesInput; use std::fs::File; use std::io::Read; diff --git a/src/mutators/mod.rs b/src/mutators/mod.rs index 823c16a0d8..8887039322 100644 --- a/src/mutators/mod.rs +++ b/src/mutators/mod.rs @@ -1,24 +1,21 @@ use crate::inputs::Input; +use crate::utils::Rand; +use crate::corpus::Corpus; use crate::AflError; pub mod scheduled; pub use scheduled::ScheduledMutator; -pub trait Mutator { - //fn rand(&self) -> &Box; - //fn rand_mut(&self) -> &mut Box; +pub trait Mutator { - fn mutate(&mut self, input: &mut dyn Input) -> Result<(), AflError> { - self.mutate_at((-1) as i32, input) - } + fn rand(&mut self) -> &mut Box; - fn mutate_at(&mut self, stage_idx: i32, input: &mut dyn Input) -> Result<(), AflError>; + fn mutate(&mut self, input: &mut InputT, stage_idx: i32) -> Result<(), AflError>; - fn post_exec(&mut self, is_interesting: bool) -> Result<(), AflError> { - self.post_exec_at((-1) as i32, is_interesting) - } - - fn post_exec_at(&mut self, _stage_idx: i32, _is_interesting: bool) -> Result<(), AflError> { + fn post_exec(&mut self, _is_interesting: bool, _stage_idx: i32) -> Result<(), AflError> { Ok(()) } + + fn corpus(&mut self) -> &mut Option>; + } diff --git a/src/mutators/scheduled.rs b/src/mutators/scheduled.rs index ac1d4c5d1c..b79be05ba5 100644 --- a/src/mutators/scheduled.rs +++ b/src/mutators/scheduled.rs @@ -1,34 +1,45 @@ use crate::mutators::Mutator; -use crate::inputs::Input; +use crate::utils::Rand; +use crate::corpus::Corpus; +use crate::inputs::{Input, BytesInput}; use crate::AflError; -type MutationFunction = fn(&mut dyn ScheduledMutator, &mut dyn Input) -> Result<(), AflError>; +type MutationFunction = fn(&mut MutatorT, &mut InputT) -> Result<(), AflError>; -pub trait ScheduledMutator: Mutator { - fn iterations(&self, _input: &dyn Input) -> u64 { - //1 << (1 + self.rand_mut().below(7)) - return 1; +pub trait ScheduledMutator: Mutator { + fn iterations(&mut self, _input: &InputT) -> u64 { + 1 << (1 + self.rand().below(7)) } - fn schedule(&self, _input: &dyn Input) -> Result { - if self.mutations_count() == 0 { + fn schedule(&mut self, _input: &InputT) -> Result, AflError> { + let count = self.mutations_count() as u64; + if count == 0 { return Err(AflError::Empty("no mutations".to_string())); } - self.get_mutation_by_idx(1 /* self.rand_mut().below(self.mutations_count()) */) + let idx; + { + idx = self.rand().below(count) as usize; + } + self.mutation_by_idx(idx) } - fn get_mutation_by_idx(&self, index: usize) -> Result; + fn mutation_by_idx(&self, index: usize) -> Result, AflError>; fn mutations_count(&self) -> usize; + + fn add_mutation(&mut self, mutation: MutationFunction); + } -pub struct BaseScheduledMutator { - mutations: Vec +pub struct DefaultScheduledMutator { + rand: Box, + corpus: Option>, + mutations: Vec> } -impl ScheduledMutator for BaseScheduledMutator { +impl ScheduledMutator for DefaultScheduledMutator { - fn get_mutation_by_idx(&self, index: usize) -> Result { + fn mutation_by_idx(&self, index: usize) -> Result, AflError> { if index >= self.mutations.len() { return Err(AflError::Unknown("oob".to_string())); } @@ -39,11 +50,19 @@ impl ScheduledMutator for BaseScheduledMutator { self.mutations.len() } + fn add_mutation(&mut self, mutation: MutationFunction) { + self.mutations.push(mutation) + } + } -impl Mutator for BaseScheduledMutator { +impl Mutator for DefaultScheduledMutator { - fn mutate_at(&mut self, _stage_idx: i32, input: &mut dyn Input) -> Result<(), AflError> { + fn rand(&mut self) -> &mut Box { + &mut self.rand + } + + fn mutate(&mut self, input: &mut InputT, _stage_idx: i32) -> Result<(), AflError> { let num = self.iterations(input); for _ in 0..num { self.schedule(input)?(self, input)?; @@ -51,4 +70,71 @@ impl Mutator for BaseScheduledMutator { Ok(()) } + fn corpus(&mut self) -> &mut Option> { + &mut self.corpus + } + +} + +impl DefaultScheduledMutator { + pub fn new(rand: Box) -> Self { + DefaultScheduledMutator { + rand: rand, + corpus: None, + mutations: vec![] + } + } + + pub fn new_all(rand: Box, corpus: Option>, mutations: Vec>) -> Self { + DefaultScheduledMutator { + rand: rand, + corpus: corpus, + mutations: mutations + } + } +} + +pub fn mutation_bitflip>(mutator: &mut MutatorT, input: &mut BytesInput) -> Result<(), AflError> { + let bit = mutator.rand().below(input.bytes.len() as u64) as usize; + input.bytes[bit >> 3] ^= (128 >> (bit & 7)) as u8; + Ok(()) +} + +pub struct HavocMutator> { + scheduled: ScheduledMutatorT, +} + +impl> Mutator for HavocMutator { + + fn rand(&mut self) -> &mut Box { + self.scheduled.rand() + } + + fn mutate(&mut self, input: &mut BytesInput, stage_idx: i32) -> Result<(), AflError> { + self.scheduled.mutate(input, stage_idx) + } + + fn corpus(&mut self) -> &mut Option> { + self.scheduled.corpus() + } + +} + +impl> HavocMutator { + pub fn new(mut scheduled: ScheduledMutatorT) -> Self { + scheduled.add_mutation(mutation_bitflip); + HavocMutator { + scheduled: scheduled + } + } +} + +impl HavocMutator> { + pub fn new_default(rand: Box) -> Self { + let mut scheduled = DefaultScheduledMutator::new(rand); + scheduled.add_mutation(mutation_bitflip); + HavocMutator { + scheduled: scheduled + } + } } \ No newline at end of file