small improvements
This commit is contained in:
parent
b3b8e81190
commit
9a1251875f
@ -1,5 +1,6 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
|
use libafl_qemu::QemuClockObserver;
|
||||||
use libafl::feedbacks::Feedback;
|
use libafl::feedbacks::Feedback;
|
||||||
use crate::worst::HitImprovingFeedback;
|
use crate::worst::HitImprovingFeedback;
|
||||||
use crate::worst::HitFeedback;
|
use crate::worst::HitFeedback;
|
||||||
@ -152,7 +153,7 @@ pub fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut crashes = out_dir.clone();
|
let mut crashes = out_dir.clone();
|
||||||
crashes.push("crashes");
|
crashes.push("wcets");
|
||||||
out_dir.push("queue");
|
out_dir.push("queue");
|
||||||
|
|
||||||
let in_dir = PathBuf::from(res.value_of("in").unwrap().to_string());
|
let in_dir = PathBuf::from(res.value_of("in").unwrap().to_string());
|
||||||
@ -292,6 +293,7 @@ fn fuzz(
|
|||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
let clock_observer = QemuClockObserver::default();
|
||||||
|
|
||||||
// Create an observation channel using cmplog map
|
// Create an observation channel using cmplog map
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", unsafe { &mut cmplog::CMPLOG_MAP }, true);
|
let cmplog_observer = CmpLogObserver::new("cmplog", unsafe { &mut cmplog::CMPLOG_MAP }, true);
|
||||||
@ -387,7 +389,7 @@ fn fuzz(
|
|||||||
//QemuAsanHelper::new(),
|
//QemuAsanHelper::new(),
|
||||||
QemuSysSnapshotHelper::new()
|
QemuSysSnapshotHelper::new()
|
||||||
),
|
),
|
||||||
tuple_list!(edges_observer, time_observer),
|
tuple_list!(edges_observer, time_observer, clock_observer),
|
||||||
&mut fuzzer,
|
&mut fuzzer,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut mgr,
|
&mut mgr,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![feature(iter_advance_by)]
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub mod fuzzer;
|
pub mod fuzzer;
|
||||||
pub mod showmap;
|
pub mod showmap;
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
|
use crate::worst::DumpMapFeedback;
|
||||||
|
use crate::worst::DummyFeedback;
|
||||||
|
use libafl::corpus::Corpus;
|
||||||
|
use libafl::state::HasCorpus;
|
||||||
|
use libafl::Fuzzer;
|
||||||
|
use libafl::mutators::BitFlipMutator;
|
||||||
|
use libafl::stages::StdMutationalStage;
|
||||||
use libafl_qemu::QemuInstrumentationFilter;
|
use libafl_qemu::QemuInstrumentationFilter;
|
||||||
use crate::system_trace::QemuSystemStateHelper;
|
use crate::system_trace::QemuSystemStateHelper;
|
||||||
use libafl::feedbacks::CrashFeedback;
|
use libafl::feedbacks::CrashFeedback;
|
||||||
@ -258,7 +265,7 @@ fn fuzz(
|
|||||||
let feedback = DumpMapFeedback::with_dump(dump_edges);
|
let feedback = DumpMapFeedback::with_dump(dump_edges);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
let objective = QemuClockIncreaseFeedback::new();
|
let objective = DummyFeedback::new(false);
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -330,67 +337,28 @@ fn fuzz(
|
|||||||
true => seed_dir.clone().read_dir().expect("Directory not a directory?").next().expect("Directory empty?").expect("File not in directory?").path(),
|
true => seed_dir.clone().read_dir().expect("Directory not a directory?").next().expect("Directory empty?").expect("File not in directory?").path(),
|
||||||
false => seed_dir.clone()
|
false => seed_dir.clone()
|
||||||
};
|
};
|
||||||
|
// let secondinput = match seed_dir.clone().is_dir() {
|
||||||
|
// true => {
|
||||||
|
// let mut a = seed_dir.clone().read_dir().expect("Directory not a directory?");
|
||||||
|
// a.advance_by(1);
|
||||||
|
// a.next().unwrap().expect("File not in directory?").path()
|
||||||
|
// },
|
||||||
|
// false => seed_dir.clone()
|
||||||
|
// };
|
||||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&firstinput).expect("Could not load file")).expect("Evaluation failed");
|
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&firstinput).expect("Could not load file")).expect("Evaluation failed");
|
||||||
|
// fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&secondinput).expect("Could not load file")).expect("Evaluation failed");
|
||||||
|
// println!("Nach Eval");
|
||||||
|
// if state.corpus().count() < 1 {
|
||||||
|
// state
|
||||||
|
// .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
|
||||||
|
// .unwrap_or_else(|_| {
|
||||||
|
// println!("Failed to load initial corpus at {:?}", &seed_dir);
|
||||||
|
// return;
|
||||||
|
// });
|
||||||
|
// println!("We imported {} inputs from disk.", state.corpus().count());
|
||||||
|
// }
|
||||||
|
// fuzzer
|
||||||
|
// .fuzz_one(&mut tuple_list!(StdMutationalStage::new(BitFlipMutator::new())), &mut executor, &mut state, &mut mgr)
|
||||||
|
// .expect("Error in the fuzzing loop");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================== Debugging Feedback
|
|
||||||
/// A [`Feedback`] meant to dump the edgemap for debugging.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct DumpMapFeedback {
|
|
||||||
dumpfile: Option<PathBuf>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, S> Feedback<I, S> for DumpMapFeedback
|
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
S: HasClientPerfMonitor,
|
|
||||||
{
|
|
||||||
fn is_interesting<EM, OT>(
|
|
||||||
&mut self,
|
|
||||||
_state: &mut S,
|
|
||||||
_manager: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
_observers: &OT,
|
|
||||||
_exit_kind: &ExitKind,
|
|
||||||
) -> Result<bool, Error>
|
|
||||||
where
|
|
||||||
EM: EventFirer<I>,
|
|
||||||
OT: ObserversTuple<I, S>,
|
|
||||||
{
|
|
||||||
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
|
|
||||||
.expect("HitcountsMapObserver not found");
|
|
||||||
match &self.dumpfile {
|
|
||||||
Some(s) => {
|
|
||||||
fs::write(s,ron::to_string(&observer.edgemap).expect("Error serializing hashmap")).expect("Can not dump to file");
|
|
||||||
self.dumpfile = None
|
|
||||||
},
|
|
||||||
None => println!("{:#?}",observer.edgemap),
|
|
||||||
};
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Named for DumpMapFeedback {
|
|
||||||
#[inline]
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
"HitFeedback"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DumpMapFeedback {
|
|
||||||
/// Creates a new [`HitFeedback`]
|
|
||||||
#[must_use]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {dumpfile: None}
|
|
||||||
}
|
|
||||||
pub fn with_dump(dumpfile: Option<PathBuf>) -> Self {
|
|
||||||
Self {dumpfile: dumpfile}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DumpMapFeedback {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
use std::fs;
|
||||||
use libafl::observers::VariableMapObserver;
|
use libafl::observers::VariableMapObserver;
|
||||||
use hashbrown::{HashMap};
|
use hashbrown::{HashMap};
|
||||||
use libafl::observers::ObserversTuple;
|
use libafl::observers::ObserversTuple;
|
||||||
@ -182,7 +184,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
|
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
|
||||||
let hit_target = mean_sum_of_squares <= 1.0;
|
let hit_target = mean_sum_of_squares <= self.target_msd;
|
||||||
|
eprintln!("hit target: {} {} {:?}",hit_target,mean_sum_of_squares, _input);
|
||||||
if hit_target {
|
if hit_target {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
@ -312,7 +315,7 @@ where
|
|||||||
}
|
}
|
||||||
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
|
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
|
||||||
let hit_target = mean_sum_of_squares <= self.best_msd;
|
let hit_target = mean_sum_of_squares <= self.best_msd;
|
||||||
eprintln!("in worst, {}",hit_target);
|
eprintln!("improving: {}",hit_target);
|
||||||
if hit_target {
|
if hit_target {
|
||||||
self.best_msd = mean_sum_of_squares;
|
self.best_msd = mean_sum_of_squares;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@ -341,4 +344,115 @@ impl Default for HitImprovingFeedback {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(HashMap::new())
|
Self::new(HashMap::new())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================== Debugging Feedback
|
||||||
|
/// A [`Feedback`] meant to dump the edgemap for debugging.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DumpMapFeedback {
|
||||||
|
dumpfile: Option<PathBuf>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, S> Feedback<I, S> for DumpMapFeedback
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
S: HasClientPerfMonitor,
|
||||||
|
{
|
||||||
|
fn is_interesting<EM, OT>(
|
||||||
|
&mut self,
|
||||||
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
|
_input: &I,
|
||||||
|
_observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I>,
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
{
|
||||||
|
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
|
||||||
|
.expect("HitcountsMapObserver not found");
|
||||||
|
match &self.dumpfile {
|
||||||
|
Some(s) => {
|
||||||
|
fs::write(s,ron::to_string(&observer.edgemap).expect("Error serializing hashmap")).expect("Can not dump to file");
|
||||||
|
self.dumpfile = None
|
||||||
|
},
|
||||||
|
None => ()//println!("{:#?}",observer.edgemap),
|
||||||
|
};
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for DumpMapFeedback {
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"HitFeedback"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DumpMapFeedback {
|
||||||
|
/// Creates a new [`HitFeedback`]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {dumpfile: None}
|
||||||
|
}
|
||||||
|
pub fn with_dump(dumpfile: Option<PathBuf>) -> Self {
|
||||||
|
Self {dumpfile: dumpfile}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DumpMapFeedback {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================== Debugging Feedback
|
||||||
|
/// A [`Feedback`] meant to dump the edgemap for debugging.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DummyFeedback {
|
||||||
|
response: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, S> Feedback<I, S> for DummyFeedback
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
S: HasClientPerfMonitor,
|
||||||
|
{
|
||||||
|
fn is_interesting<EM, OT>(
|
||||||
|
&mut self,
|
||||||
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
|
_input: &I,
|
||||||
|
_observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I>,
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
{
|
||||||
|
eprintln!("Input was: {:?}",_input);
|
||||||
|
Ok(self.response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for DummyFeedback {
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"DummyFeedback"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DummyFeedback {
|
||||||
|
/// Creates a new [`HitFeedback`]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new(response: bool) -> Self {
|
||||||
|
Self {response: response}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DummyFeedback {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new(true)
|
||||||
|
}
|
||||||
}
|
}
|
@ -28,6 +28,16 @@ use libafl::events::EventFirer;
|
|||||||
use libafl::state::HasClientPerfMonitor;
|
use libafl::state::HasClientPerfMonitor;
|
||||||
use libafl::inputs::Input;
|
use libafl::inputs::Input;
|
||||||
use libafl::feedbacks::Feedback;
|
use libafl::feedbacks::Feedback;
|
||||||
|
use libafl::SerdeAny;
|
||||||
|
use libafl::state::HasMetadata;
|
||||||
|
use libafl::corpus::testcase::Testcase;
|
||||||
|
|
||||||
|
//========== Metadata
|
||||||
|
#[derive(Debug, Serialize, Deserialize, SerdeAny)]
|
||||||
|
pub struct QemuIcountMetadata {
|
||||||
|
runtime: i64,
|
||||||
|
}
|
||||||
|
// libafl::impl_serdeany!(QemuIcountMetadata);
|
||||||
|
|
||||||
//========== Observer
|
//========== Observer
|
||||||
|
|
||||||
@ -55,7 +65,11 @@ impl QemuClockObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, S> Observer<I, S> for QemuClockObserver {
|
impl<I, S> Observer<I, S> for QemuClockObserver
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
S: HasMetadata,
|
||||||
|
{
|
||||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
self.last_runtime=0;
|
self.last_runtime=0;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -63,6 +77,12 @@ impl<I, S> Observer<I, S> for QemuClockObserver {
|
|||||||
|
|
||||||
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
unsafe { self.last_runtime = emu::libafl_get_clock() };
|
unsafe { self.last_runtime = emu::libafl_get_clock() };
|
||||||
|
// if !_state.has_metadata::<QemuIcountMetadata>() {
|
||||||
|
// _state.add_metadata(QemuIcountMetadata{runtime: self.last_runtime()});
|
||||||
|
// println!("Added Metadata");
|
||||||
|
// } else {
|
||||||
|
// println!("Found Metadata");
|
||||||
|
// }
|
||||||
println!("Observer Clock: {}",self.last_runtime());
|
println!("Observer Clock: {}",self.last_runtime());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -84,12 +104,13 @@ impl Default for QemuClockObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//========== Observer
|
//========== Feedback
|
||||||
|
|
||||||
/// A [`Feedback`] rewarding increasing the execution cycles on Qemu.
|
/// A [`Feedback`] rewarding increasing the execution cycles on Qemu.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QemuClockIncreaseFeedback {
|
pub struct QemuClockIncreaseFeedback {
|
||||||
maximum: i64
|
maximum: i64,
|
||||||
|
last_runtime: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, S> Feedback<I, S> for QemuClockIncreaseFeedback
|
impl<I, S> Feedback<I, S> for QemuClockIncreaseFeedback
|
||||||
@ -111,12 +132,26 @@ where
|
|||||||
{
|
{
|
||||||
let observer = _observers.match_name::<QemuClockObserver>("clock")
|
let observer = _observers.match_name::<QemuClockObserver>("clock")
|
||||||
.expect("QemuClockObserver not found");
|
.expect("QemuClockObserver not found");
|
||||||
if observer.last_runtime() >= self.maximum {
|
if observer.last_runtime() > self.maximum {
|
||||||
self.maximum = observer.last_runtime();
|
self.maximum = observer.last_runtime();
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||||
|
#[inline]
|
||||||
|
fn append_metadata(&mut self, _state: &mut S, testcase: &mut Testcase<I>) -> Result<(), Error> {
|
||||||
|
testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Discard the stored metadata in case that the testcase is not added to the corpus
|
||||||
|
#[inline]
|
||||||
|
fn discard_metadata(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Named for QemuClockIncreaseFeedback {
|
impl Named for QemuClockIncreaseFeedback {
|
||||||
@ -130,7 +165,7 @@ impl QemuClockIncreaseFeedback {
|
|||||||
/// Creates a new [`HitFeedback`]
|
/// Creates a new [`HitFeedback`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {maximum: 0}
|
Self {maximum: 0, last_runtime: 0}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user