
* Associated types for Corpus, State * cleanup * fix no_std * drop unused clauses * Corpus * cleanup * adding things * fixed fuzzer * remove phantom data * python * progress? * more more * oof * wow it builds? * python fixes, tests * fix python fun * black fmt for python * clippy, added Nop things * fixes * fix merge * make it compile (#836) * doc-test fixes, prelude-b-gone for cargo-hack compat * fixes for windows, concolic * really fix windows, maybe * imagine using windows * ... * elide I generic when used with S: State * Elide many, many generics, but at what cost? * progress on push * Constraint HasCorpus, HasSolutions at trait definition * remove unused feature * remove unstable usage since we constrained HasCorpus at definition * compiled, but still no type inference for MaxMapFeedback * cleanup inprocess * resolve some std conflicts * simplify map * undo unnecessary cfg specification * fix breaking test case for CI on no-std * fix concolic build failures * fix macos build * fixes for windows build * timeout fixes for windows build * fix pybindings issues * fixup qemu * fix outstanding local build issues * maybe fix windows inprocess * doc fixes * unbridled fury * de-associate State from Feedback, replace with generic as AT inference is not sufficient to derive specialisation for MapFeedback * merge update * refactor + speed up fuzzer builds by sharing build work * cleanup lingering compiler errors * lol missed one * revert QEMU-Nyx change, not sure how I did that * move HasInput to inputs * HasInput => KnowsInput * update bounds to enforce via associated types * disentangle observers with fuzzer * revert --target; update some fuzzers to match new API * resolve outstanding fuzzer build blockers (that I can run on my system) * fixes for non-linux unixes * fix for windows * Knows => Uses, final fixes for windows * <guttural screaming> * fixes for concolic * loosen bound for frida executor so windows builds correctly * cleanup generics for eventmanager/eventprocessor to drop observers requirement * improve inference over fuzz_one and friends * update migration notes * fixes for python bindings * fixes for generic counts in event managers * finish migration notes * post-merge fix Co-authored-by: Addison Crump <addison.crump@cispa.de>
126 lines
4.5 KiB
Rust
126 lines
4.5 KiB
Rust
#[cfg(windows)]
|
|
use std::ptr::write_volatile;
|
|
use std::{
|
|
io::Write,
|
|
path::PathBuf,
|
|
process::{Child, Command, Stdio},
|
|
};
|
|
|
|
use libafl::{
|
|
bolts::{
|
|
current_nanos,
|
|
rands::StdRand,
|
|
shmem::{unix_shmem, ShMem, ShMemId, ShMemProvider},
|
|
tuples::tuple_list,
|
|
AsMutSlice, AsSlice,
|
|
},
|
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
|
events::SimpleEventManager,
|
|
executors::command::CommandConfigurator,
|
|
feedback_and,
|
|
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
|
fuzzer::{Fuzzer, StdFuzzer},
|
|
generators::RandPrintablesGenerator,
|
|
inputs::{HasTargetBytes, Input},
|
|
monitors::SimpleMonitor,
|
|
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
|
observers::{get_asan_runtime_flags, AsanBacktraceObserver, StdMapObserver},
|
|
schedulers::QueueScheduler,
|
|
stages::mutational::StdMutationalStage,
|
|
state::StdState,
|
|
Error,
|
|
};
|
|
|
|
#[allow(clippy::similar_names)]
|
|
pub fn main() {
|
|
let mut shmem_provider = unix_shmem::UnixShMemProvider::new().unwrap();
|
|
let mut signals = shmem_provider.new_shmem(3).unwrap();
|
|
let shmem_id = signals.id();
|
|
|
|
// Create an observation channel using the signals map
|
|
let observer = StdMapObserver::new("signals", signals.as_mut_slice());
|
|
// Create a stacktrace observer
|
|
let bt_observer = AsanBacktraceObserver::new("AsanBacktraceObserver");
|
|
|
|
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
|
|
let mut feedback = MaxMapFeedback::new(&observer);
|
|
|
|
// A feedback to choose if an input is a solution or not
|
|
let mut objective = feedback_and!(CrashFeedback::new(), NewHashFeedback::new(&bt_observer));
|
|
// let mut objective = CrashFeedback::new();
|
|
|
|
// 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::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.
|
|
// The feedbacks can report the data that should persist in the State.
|
|
&mut feedback,
|
|
// Same for objective feedbacks
|
|
&mut objective,
|
|
)
|
|
.unwrap();
|
|
|
|
// The Monitor trait define how the fuzzer stats are displayed to the user
|
|
let mon = SimpleMonitor::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(mon);
|
|
|
|
// A queue policy to get testcases from the corpus
|
|
let scheduler = QueueScheduler::new();
|
|
|
|
// A fuzzer with feedbacks and a corpus scheduler
|
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
|
|
|
// Create the executor for an in-process function with just one observer
|
|
#[derive(Debug)]
|
|
struct MyExecutor {
|
|
shmem_id: ShMemId,
|
|
}
|
|
|
|
impl CommandConfigurator for MyExecutor {
|
|
fn spawn_child<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<Child, Error> {
|
|
let mut command = Command::new("./test_command");
|
|
|
|
let command = command
|
|
.args([self.shmem_id.as_str()])
|
|
.env("ASAN_OPTIONS", get_asan_runtime_flags());
|
|
|
|
command
|
|
.stdin(Stdio::piped())
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped());
|
|
|
|
let child = command.spawn().expect("failed to start process");
|
|
let mut stdin = child.stdin.as_ref().unwrap();
|
|
stdin.write_all(input.target_bytes().as_slice())?;
|
|
Ok(child)
|
|
}
|
|
}
|
|
|
|
let mut executor = MyExecutor { shmem_id }.into_executor(tuple_list!(observer, bt_observer));
|
|
|
|
// Generator of printable bytearrays of max size 32
|
|
let mut generator = RandPrintablesGenerator::new(32);
|
|
|
|
// Generate 8 initial inputs
|
|
state
|
|
.generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 8)
|
|
.expect("Failed to generate the initial corpus");
|
|
|
|
// 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");
|
|
}
|