moved fuzzer
This commit is contained in:
parent
21235e846e
commit
08a6196f6c
187
afl/src/lib.rs
187
afl/src/lib.rs
@ -28,8 +28,125 @@ pub mod utils;
|
||||
|
||||
use alloc::string::String;
|
||||
use core::fmt;
|
||||
use corpus::Corpus;
|
||||
use events::EventManager;
|
||||
use executors::{Executor, HasObservers};
|
||||
use feedbacks::FeedbacksTuple;
|
||||
use inputs::Input;
|
||||
use observers::ObserversTuple;
|
||||
use stages::StagesTuple;
|
||||
use state::{HasCorpus, State};
|
||||
use std::marker::PhantomData;
|
||||
#[cfg(feature = "std")]
|
||||
use std::{env::VarError, io, num::ParseIntError, string::FromUtf8Error};
|
||||
use utils::{current_milliseconds, Rand};
|
||||
|
||||
/// The main fuzzer trait.
|
||||
pub trait Fuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
where
|
||||
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn stages(&self) -> &ST;
|
||||
|
||||
fn stages_mut(&mut self) -> &mut ST;
|
||||
|
||||
fn fuzz_one(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
) -> Result<usize, AflError> {
|
||||
let (_, idx) = state.corpus_mut().next(rand)?;
|
||||
|
||||
self.stages_mut()
|
||||
.perform_all(rand, executor, state, manager, idx)?;
|
||||
|
||||
manager.process(state)?;
|
||||
Ok(idx)
|
||||
}
|
||||
|
||||
fn fuzz_loop(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
) -> Result<(), AflError> {
|
||||
let mut last = current_milliseconds();
|
||||
loop {
|
||||
self.fuzz_one(rand, executor, state, manager)?;
|
||||
let cur = current_milliseconds();
|
||||
if cur - last > 60 * 100 {
|
||||
last = cur;
|
||||
manager.update_stats(state.executions(), state.executions_over_seconds())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StdFuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
where
|
||||
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
stages: ST,
|
||||
phantom: PhantomData<(EM, E, OT, FT, C, I, R)>,
|
||||
}
|
||||
|
||||
impl<ST, EM, E, OT, FT, C, I, R> Fuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
for StdFuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
where
|
||||
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn stages(&self) -> &ST {
|
||||
&self.stages
|
||||
}
|
||||
|
||||
fn stages_mut(&mut self) -> &mut ST {
|
||||
&mut self.stages
|
||||
}
|
||||
}
|
||||
|
||||
impl<ST, EM, E, OT, FT, C, I, R> StdFuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
where
|
||||
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
pub fn new(stages: ST) -> Self {
|
||||
Self {
|
||||
stages: stages,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Main error struct for AFL
|
||||
#[derive(Debug)]
|
||||
@ -112,3 +229,73 @@ impl From<ParseIntError> for AflError {
|
||||
Self::Unknown(format!("Failed to parse Int: {:?}", err))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: no_std test
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, InMemoryCorpus, Testcase},
|
||||
executors::{Executor, ExitKind, InMemoryExecutor},
|
||||
inputs::{BytesInput, Input},
|
||||
mutators::{mutation_bitflip, ComposedByMutations, StdScheduledMutator},
|
||||
stages::StdMutationalStage,
|
||||
state::{HasCorpus, State},
|
||||
tuples::tuple_list,
|
||||
utils::StdRand,
|
||||
Fuzzer, StdFuzzer,
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::events::{LoggerEventManager, SimpleStats};
|
||||
|
||||
fn harness<E: Executor<I>, I: Input>(_executor: &E, _buf: &[u8]) -> ExitKind {
|
||||
ExitKind::Ok
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzzer() {
|
||||
let mut rand = StdRand::new(0);
|
||||
|
||||
let mut corpus = InMemoryCorpus::<BytesInput, StdRand>::new();
|
||||
let testcase = Testcase::new(vec![0; 4]).into();
|
||||
corpus.add(testcase);
|
||||
|
||||
let mut state = State::new(corpus, tuple_list!());
|
||||
|
||||
let mut event_manager = LoggerEventManager::new(SimpleStats::new(|s| {
|
||||
println!("{}", s);
|
||||
}));
|
||||
|
||||
let mut executor = InMemoryExecutor::new(
|
||||
"main",
|
||||
harness,
|
||||
tuple_list!(),
|
||||
//Box::new(|_, _, _, _, _| ()),
|
||||
&mut state,
|
||||
&mut event_manager,
|
||||
);
|
||||
|
||||
let mut mutator = StdScheduledMutator::new();
|
||||
mutator.add_mutation(mutation_bitflip);
|
||||
let stage = StdMutationalStage::new(mutator);
|
||||
let mut fuzzer = StdFuzzer::new(tuple_list!(stage));
|
||||
|
||||
for i in 0..1000 {
|
||||
fuzzer
|
||||
.fuzz_one(&mut rand, &mut executor, &mut state, &mut event_manager)
|
||||
.expect(&format!("Error in iter {}", i));
|
||||
}
|
||||
|
||||
let state_serialized = postcard::to_allocvec(&state).unwrap();
|
||||
let state_deserialized: State<InMemoryCorpus<BytesInput, _>, BytesInput, StdRand, ()> =
|
||||
postcard::from_bytes(state_serialized.as_slice()).unwrap();
|
||||
assert_eq!(state.executions(), state_deserialized.executions());
|
||||
|
||||
let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap();
|
||||
let corpus_deserialized: InMemoryCorpus<BytesInput, StdRand> =
|
||||
postcard::from_bytes(corpus_serialized.as_slice()).unwrap();
|
||||
assert_eq!(state.corpus().count(), corpus_deserialized.count());
|
||||
}
|
||||
}
|
||||
|
@ -482,27 +482,34 @@ where
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
||||
/*
|
||||
// Insert a dictionary token
|
||||
/* TODO
|
||||
/// Insert a dictionary token
|
||||
pub fn mutation_tokeninsert<I, M, R, S>(
|
||||
mutator: &mut M,
|
||||
rand: &mut R,
|
||||
_: &mut S,
|
||||
state: &mut S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
M: HasMaxSize,
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
S: HasMetadata,
|
||||
{
|
||||
if mutator.tokens.size() == 0 { return Ok(MutationResult::Skipped); }
|
||||
let tokens: Vec<Vec<u8>> = state.metadata().get().unwrap();
|
||||
if mutator.tokens.size() == 0 {
|
||||
return Ok(MutationResult::Skipped);
|
||||
}
|
||||
let token = &mutator.tokens[rand.below(token.size())];
|
||||
let token_len = token.size();
|
||||
let size = input.bytes().len();
|
||||
let off = if size == 0 {
|
||||
0
|
||||
} else {
|
||||
rand.below(core::cmp::min(size, (mutator.max_size() - token_len) as u64)) as usize
|
||||
rand.below(core::cmp::min(
|
||||
size,
|
||||
(mutator.max_size() - token_len) as u64,
|
||||
)) as usize
|
||||
} as usize;
|
||||
|
||||
input.bytes_mut().resize(size + token_len, 0);
|
||||
@ -510,27 +517,29 @@ where
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
||||
// Overwrite with a dictionary token
|
||||
pub fn mutation_tokenreplace<M, C, I, R>(
|
||||
/// Overwrite with a dictionary token
|
||||
pub fn mutation_tokenreplace<I, M, R, S>(
|
||||
mutator: &mut M,
|
||||
rand: &mut R,
|
||||
_: &C,
|
||||
state: &S,
|
||||
input: &mut I,
|
||||
) -> Result<MutationResult, AflError>
|
||||
where
|
||||
M: HasMaxSize,
|
||||
I: Input + HasBytesVec,
|
||||
R: Rand,
|
||||
S: HasMetadata,
|
||||
{
|
||||
if mutator.tokens.size() > len || !len { return Ok(MutationResult::Skipped); }
|
||||
if mutator.tokens.size() > len || !len {
|
||||
return Ok(MutationResult::Skipped);
|
||||
}
|
||||
let token = &mutator.tokens[rand.below(token.size())];
|
||||
let token_len = token.size();
|
||||
let size = input.bytes().len();
|
||||
let off rand.below((mutator.max_size() - token_len) as u64)) as usize;
|
||||
let off = rand.below((mutator.max_size() - token_len) as u64) as usize;
|
||||
mem_move(input.bytes_mut(), token, 0, off, len);
|
||||
Ok(MutationResult::Mutated)
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
pub fn mutation_bytesinsert<I, M, R, S>(
|
||||
|
@ -303,8 +303,10 @@ where
|
||||
scheduled.add_mutation(mutation_bytescopy);
|
||||
scheduled.add_mutation(mutation_bytesswap);
|
||||
|
||||
/*scheduled.add_mutation(mutation_tokeninsert);
|
||||
scheduled.add_mutation(mutation_tokenreplace);*/
|
||||
/* TODO
|
||||
scheduled.add_mutation(mutation_tokeninsert);
|
||||
scheduled.add_mutation(mutation_tokenreplace);
|
||||
*/
|
||||
|
||||
// TODO: custom dictionary (redqueen etc.)
|
||||
|
||||
|
@ -17,7 +17,6 @@ use crate::{
|
||||
inputs::Input,
|
||||
observers::ObserversTuple,
|
||||
serde_anymap::{SerdeAny, SerdeAnyMap},
|
||||
stages::StagesTuple,
|
||||
utils::{current_milliseconds, Rand},
|
||||
AflError,
|
||||
};
|
||||
@ -370,180 +369,3 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Fuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
where
|
||||
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn stages(&self) -> &ST;
|
||||
|
||||
fn stages_mut(&mut self) -> &mut ST;
|
||||
|
||||
fn fuzz_one(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
) -> Result<usize, AflError> {
|
||||
let (_, idx) = state.corpus_mut().next(rand)?;
|
||||
|
||||
self.stages_mut()
|
||||
.perform_all(rand, executor, state, manager, idx)?;
|
||||
|
||||
manager.process(state)?;
|
||||
Ok(idx)
|
||||
}
|
||||
|
||||
fn fuzz_loop(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
executor: &mut E,
|
||||
state: &mut State<C, I, R, FT>,
|
||||
manager: &mut EM,
|
||||
) -> Result<(), AflError> {
|
||||
let mut last = current_milliseconds();
|
||||
loop {
|
||||
self.fuzz_one(rand, executor, state, manager)?;
|
||||
let cur = current_milliseconds();
|
||||
if cur - last > 60 * 100 {
|
||||
last = cur;
|
||||
manager.update_stats(state.executions(), state.executions_over_seconds())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StdFuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
where
|
||||
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
stages: ST,
|
||||
phantom: PhantomData<(EM, E, OT, FT, C, I, R)>,
|
||||
}
|
||||
|
||||
impl<ST, EM, E, OT, FT, C, I, R> Fuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
for StdFuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
where
|
||||
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn stages(&self) -> &ST {
|
||||
&self.stages
|
||||
}
|
||||
|
||||
fn stages_mut(&mut self) -> &mut ST {
|
||||
&mut self.stages
|
||||
}
|
||||
}
|
||||
|
||||
impl<ST, EM, E, OT, FT, C, I, R> StdFuzzer<ST, EM, E, OT, FT, C, I, R>
|
||||
where
|
||||
ST: StagesTuple<EM, E, OT, FT, C, I, R>,
|
||||
EM: EventManager<I>,
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
pub fn new(stages: ST) -> Self {
|
||||
Self {
|
||||
stages: stages,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: no_std test
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, InMemoryCorpus, Testcase},
|
||||
executors::{Executor, ExitKind, InMemoryExecutor},
|
||||
inputs::{BytesInput, Input},
|
||||
mutators::{mutation_bitflip, ComposedByMutations, StdScheduledMutator},
|
||||
stages::StdMutationalStage,
|
||||
state::{Fuzzer, State, StdFuzzer},
|
||||
tuples::tuple_list,
|
||||
utils::StdRand,
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::events::{LoggerEventManager, SimpleStats};
|
||||
|
||||
use super::HasCorpus;
|
||||
|
||||
fn harness<E: Executor<I>, I: Input>(_executor: &E, _buf: &[u8]) -> ExitKind {
|
||||
ExitKind::Ok
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzzer() {
|
||||
let mut rand = StdRand::new(0);
|
||||
|
||||
let mut corpus = InMemoryCorpus::<BytesInput, StdRand>::new();
|
||||
let testcase = Testcase::new(vec![0; 4]).into();
|
||||
corpus.add(testcase);
|
||||
|
||||
let mut state = State::new(corpus, tuple_list!());
|
||||
|
||||
let mut event_manager = LoggerEventManager::new(SimpleStats::new(|s| {
|
||||
println!("{}", s);
|
||||
}));
|
||||
|
||||
let mut executor = InMemoryExecutor::new(
|
||||
"main",
|
||||
harness,
|
||||
tuple_list!(),
|
||||
//Box::new(|_, _, _, _, _| ()),
|
||||
&mut state,
|
||||
&mut event_manager,
|
||||
);
|
||||
|
||||
let mut mutator = StdScheduledMutator::new();
|
||||
mutator.add_mutation(mutation_bitflip);
|
||||
let stage = StdMutationalStage::new(mutator);
|
||||
let mut fuzzer = StdFuzzer::new(tuple_list!(stage));
|
||||
|
||||
for i in 0..1000 {
|
||||
fuzzer
|
||||
.fuzz_one(&mut rand, &mut executor, &mut state, &mut event_manager)
|
||||
.expect(&format!("Error in iter {}", i));
|
||||
}
|
||||
|
||||
let state_serialized = postcard::to_allocvec(&state).unwrap();
|
||||
let state_deserialized: State<InMemoryCorpus<BytesInput, _>, BytesInput, StdRand, ()> =
|
||||
postcard::from_bytes(state_serialized.as_slice()).unwrap();
|
||||
assert_eq!(state.executions, state_deserialized.executions);
|
||||
|
||||
let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap();
|
||||
let corpus_deserialized: InMemoryCorpus<BytesInput, StdRand> =
|
||||
postcard::from_bytes(corpus_serialized.as_slice()).unwrap();
|
||||
assert_eq!(state.corpus().count(), corpus_deserialized.count());
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,10 @@ use afl::{
|
||||
observers::StdMapObserver,
|
||||
shmem::{AflShmem, ShMem},
|
||||
stages::mutational::StdMutationalStage,
|
||||
state::{Fuzzer, HasCorpus, State, StdFuzzer},
|
||||
state::{HasCorpus, State},
|
||||
tuples::tuple_list,
|
||||
utils::{deserialize_state_corpus_mgr, StdRand},
|
||||
AflError,
|
||||
AflError, Fuzzer, StdFuzzer,
|
||||
};
|
||||
|
||||
/// The llmp connection from the actual fuzzer to the process supervising it
|
||||
|
Loading…
x
Reference in New Issue
Block a user