small improvements

This commit is contained in:
Alwin Berger 2022-02-03 21:19:17 +01:00
parent b3b8e81190
commit 9a1251875f
5 changed files with 191 additions and 71 deletions

View File

@ -1,5 +1,6 @@
//! A singlethreaded QEMU fuzzer that can auto-restart.
use libafl_qemu::QemuClockObserver;
use libafl::feedbacks::Feedback;
use crate::worst::HitImprovingFeedback;
use crate::worst::HitFeedback;
@ -152,7 +153,7 @@ pub fn main() {
}
}
let mut crashes = out_dir.clone();
crashes.push("crashes");
crashes.push("wcets");
out_dir.push("queue");
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
let time_observer = TimeObserver::new("time");
let clock_observer = QemuClockObserver::default();
// Create an observation channel using cmplog map
let cmplog_observer = CmpLogObserver::new("cmplog", unsafe { &mut cmplog::CMPLOG_MAP }, true);
@ -387,7 +389,7 @@ fn fuzz(
//QemuAsanHelper::new(),
QemuSysSnapshotHelper::new()
),
tuple_list!(edges_observer, time_observer),
tuple_list!(edges_observer, time_observer, clock_observer),
&mut fuzzer,
&mut state,
&mut mgr,

View File

@ -1,3 +1,4 @@
#![feature(iter_advance_by)]
#[cfg(target_os = "linux")]
pub mod fuzzer;
pub mod showmap;

View File

@ -1,5 +1,12 @@
//! 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 crate::system_trace::QemuSystemStateHelper;
use libafl::feedbacks::CrashFeedback;
@ -258,7 +265,7 @@ fn fuzz(
let feedback = DumpMapFeedback::with_dump(dump_edges);
// 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
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(),
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(&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(());
}
//=========================== 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()
}
}

View File

@ -1,3 +1,5 @@
use std::path::PathBuf;
use std::fs;
use libafl::observers::VariableMapObserver;
use hashbrown::{HashMap};
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 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 {
Ok(true)
} else {
@ -312,7 +315,7 @@ where
}
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;
eprintln!("in worst, {}",hit_target);
eprintln!("improving: {}",hit_target);
if hit_target {
self.best_msd = mean_sum_of_squares;
Ok(true)
@ -341,4 +344,115 @@ impl Default for HitImprovingFeedback {
fn default() -> Self {
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)
}
}

View File

@ -28,6 +28,16 @@ use libafl::events::EventFirer;
use libafl::state::HasClientPerfMonitor;
use libafl::inputs::Input;
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
@ -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> {
self.last_runtime=0;
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> {
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());
Ok(())
}
@ -84,12 +104,13 @@ impl Default for QemuClockObserver {
}
}
//========== Observer
//========== Feedback
/// A [`Feedback`] rewarding increasing the execution cycles on Qemu.
#[derive(Debug)]
pub struct QemuClockIncreaseFeedback {
maximum: i64
maximum: i64,
last_runtime: i64,
}
impl<I, S> Feedback<I, S> for QemuClockIncreaseFeedback
@ -111,12 +132,26 @@ where
{
let observer = _observers.match_name::<QemuClockObserver>("clock")
.expect("QemuClockObserver not found");
if observer.last_runtime() >= self.maximum {
if observer.last_runtime() > self.maximum {
self.maximum = observer.last_runtime();
return Ok(true);
}
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 {
@ -130,7 +165,7 @@ impl QemuClockIncreaseFeedback {
/// Creates a new [`HitFeedback`]
#[must_use]
pub fn new() -> Self {
Self {maximum: 0}
Self {maximum: 0, last_runtime: 0}
}
}