
* starting to fix macos linker bugs * mdetailed error prints * start shmem service manually * not a doc comment * Some fixes * only send exit msg to shmemservice when start was successful * incorporated shmem service into provider * removed unused imports * trying to fix fuzzers * fixed build * check if join_handle is_some * more debug prints * fixed shmem service autolaunch * fixed macos linker * ignoring broken libpng testcase on macos for now (see #252) * fmt * try to fix missing llvm_config (see #253) * empty issue template added * Mmanually look for llvm-config on MacOS * fixing CI * fixed docs * ignoring libmozjpg for CI, see #254
132 lines
5.0 KiB
Rust
132 lines
5.0 KiB
Rust
use core::time::Duration;
|
|
use libafl::{
|
|
bolts::{
|
|
current_nanos,
|
|
rands::StdRand,
|
|
shmem::{ShMem, ShMemProvider, StdShMemProvider},
|
|
tuples::tuple_list,
|
|
},
|
|
corpus::{
|
|
Corpus, InMemoryCorpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus,
|
|
QueueCorpusScheduler,
|
|
},
|
|
events::SimpleEventManager,
|
|
executors::forkserver::{ForkserverExecutor, TimeoutForkserverExecutor},
|
|
feedback_and_fast, feedback_or,
|
|
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
|
fuzzer::{Fuzzer, StdFuzzer},
|
|
inputs::BytesInput,
|
|
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
|
observers::{ConstMapObserver, HitcountsMapObserver, TimeObserver},
|
|
stages::mutational::StdMutationalStage,
|
|
state::{HasCorpus, StdState},
|
|
stats::SimpleStats,
|
|
};
|
|
use std::path::PathBuf;
|
|
|
|
#[allow(clippy::similar_names)]
|
|
pub fn main() {
|
|
let corpus_dirs = vec![PathBuf::from("./corpus")];
|
|
|
|
const MAP_SIZE: usize = 65536;
|
|
|
|
//Coverage map shared between observer and executor
|
|
let mut shmem = StdShMemProvider::new().unwrap().new_map(MAP_SIZE).unwrap();
|
|
//let the forkserver know the shmid
|
|
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
|
let mut shmem_map = shmem.map_mut();
|
|
|
|
// Create an observation channel using the signals map
|
|
let edges_observer = HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::new(
|
|
"shared_mem",
|
|
&mut shmem_map,
|
|
));
|
|
|
|
// Create an observation channel to keep track of the execution time
|
|
let time_observer = TimeObserver::new("time");
|
|
|
|
// The state of the edges feedback.
|
|
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
|
|
// The state of the edges feedback for crashes.
|
|
let objective_state = MapFeedbackState::new("crash_edges", MAP_SIZE);
|
|
|
|
// Feedback to rate the interestingness of an input
|
|
// This one is composed by two Feedbacks in OR
|
|
let feedback = feedback_or!(
|
|
// New maximization map feedback linked to the edges observer and the feedback state
|
|
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
|
// Time feedback, this one does not need a feedback state
|
|
TimeFeedback::new_with_observer(&time_observer)
|
|
);
|
|
|
|
// A feedback to choose if an input is a solution or not
|
|
// We want to do the same crash deduplication that AFL does
|
|
let objective = feedback_and_fast!(
|
|
// Must be a crash
|
|
CrashFeedback::new(),
|
|
// Take it onlt if trigger new coverage over crashes
|
|
MaxMapFeedback::new(&objective_state, &edges_observer)
|
|
);
|
|
|
|
// create a State from scratch
|
|
let mut state = StdState::new(
|
|
// RNG
|
|
StdRand::with_seed(current_nanos()),
|
|
// Corpus that will be evolved, we keep it in memory for performance
|
|
InMemoryCorpus::<BytesInput>::new(),
|
|
// Corpus in which we store solutions (crashes in this example),
|
|
// on disk so the user can get them after stopping the fuzzer
|
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
|
// States of the feedbacks.
|
|
// They are the data related to the feedbacks that you want to persist in the State.
|
|
tuple_list!(feedback_state, objective_state),
|
|
);
|
|
|
|
// The Stats trait define how the fuzzer stats are reported to the user
|
|
let stats = SimpleStats::new(|s| println!("{}", s));
|
|
|
|
// The event manager handle the various events generated during the fuzzing loop
|
|
// such as the notification of the addition of a new item to the corpus
|
|
let mut mgr = SimpleEventManager::new(stats);
|
|
|
|
// A minimization+queue policy to get testcasess from the corpus
|
|
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
|
|
|
// A fuzzer with feedbacks and a corpus scheduler
|
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
|
|
|
// Create the executor for the forkserver
|
|
let mut executor = TimeoutForkserverExecutor::new(
|
|
ForkserverExecutor::new(
|
|
"../../libafl_tests/src/forkserver_test.o".to_string(),
|
|
&[],
|
|
tuple_list!(edges_observer, time_observer),
|
|
)
|
|
.unwrap(),
|
|
Duration::from_millis(5000),
|
|
)
|
|
.expect("Failed to create the executor.");
|
|
|
|
// In case the corpus is empty (on first run), reset
|
|
if state.corpus().count() < 1 {
|
|
state
|
|
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
|
|
.unwrap_or_else(|err| {
|
|
panic!(
|
|
"Failed to load initial corpus at {:?}: {:?}",
|
|
&corpus_dirs, err
|
|
)
|
|
});
|
|
println!("We imported {} inputs from disk.", state.corpus().count());
|
|
}
|
|
|
|
// Setup a mutational stage with a basic bytes mutator
|
|
let mutator = StdScheduledMutator::new(havoc_mutations());
|
|
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
|
|
|
|
fuzzer
|
|
.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)
|
|
.expect("Error in the fuzzing loop");
|
|
}
|