add feedback for improving msd

This commit is contained in:
Alwin Berger 2022-01-17 20:51:52 +01:00
parent d2d2862727
commit d4d86927b7
3 changed files with 124 additions and 29 deletions

View File

@ -1,5 +1,9 @@
//! A singlethreaded QEMU fuzzer that can auto-restart.
use libafl::feedbacks::Feedback;
use crate::worst::HitImprovingFeedback;
use crate::worst::HitFeedback;
use hashbrown::HashMap;
use libafl::stats::SimpleStats;
use libafl::events::SimpleEventManager;
use clap::{App, Arg};
@ -113,6 +117,11 @@ pub fn main() {
.help("Timeout for each individual execution, in milliseconds")
.default_value("1000"),
)
.arg(
Arg::new("edges")
.long("libafl-edges")
.takes_value(true),
)
.try_get_matches_from(filter_qemu_args())
{
Ok(res) => res,
@ -165,8 +174,12 @@ pub fn main() {
);
let kernel = PathBuf::from(res.value_of("k").unwrap().to_string());
let edges = match res.value_of("edges") {
Some(st) => Some(PathBuf::from(st.to_string())),
None => None
};
fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel)
fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges)
.expect("An error occurred while fuzzing");
}
@ -192,6 +205,7 @@ fn fuzz(
logfile: PathBuf,
timeout: Duration,
kernel: PathBuf,
dump_edges: Option<PathBuf>,
) -> Result<(), Error> {
env::remove_var("LD_LIBRARY_PATH");
@ -286,16 +300,28 @@ fn fuzz(
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let target_map : HashMap<(u64,u64),u8> = match dump_edges {
None => HashMap::new(),
Some(ref s) => {
let raw = fs::read(s).expect("Can not read dumped edges");
let hmap : HashMap<(u64,u64),u8> = ron::from_str(&String::from_utf8_lossy(&raw)).expect("Can not parse HashMap");
hmap
},
};
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),
MapHitIncreaseFeedback::new(),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
HitImprovingFeedback::new(target_map.clone())
);
// 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),
// MapHitIncreaseFeedback::new(),
// // 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
let objective = CrashFeedback::new();
let objective = HitFeedback::new(target_map,0.0);
// create a State from scratch
let mut state = {

View File

@ -1,5 +1,6 @@
//! A singlethreaded QEMU fuzzer that can auto-restart.
use libafl::feedbacks::CrashFeedback;
use std::fs::File;
use std::path::Path;
use libafl::corpus::Corpus;
@ -234,7 +235,7 @@ fn fuzz(
let feedback = DumpMapFeedback::with_dump(dump_edges);
// A feedback to choose if an input is a solution or not
let objective = HitFeedback::new();
let objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(

View File

@ -10,6 +10,7 @@ use libafl::state::HasMetadata;
use libafl_qemu::edges::QemuEdgesMapMetadata;
use libafl::observers::MapObserver;
use serde::{Deserialize, Serialize};
use std::cmp;
use libafl::{
bolts::{
@ -145,7 +146,10 @@ where
/// A [`HitFeedback`] reports as interesting when all predicted worst case edges have been matched.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct HitFeedback {}
pub struct HitFeedback {
target_map: HashMap<(u64,u64),u8>,
target_msd: f64,
}
impl<I, S> Feedback<I, S> for HitFeedback
where
@ -168,26 +172,17 @@ where
// let observer = _observers.match_name::<HitcountsMapObserver<O>>("edges").expect("SelectedEdgeObserver not found");
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
.expect("HitcountsMapObserver not found");
let mut hit_target: bool = true;
//check if we've hit any targets.
// let inc : u64 = (0x401180);
// let call1 : u64 = (0x40119f);
// let call2 : u64 = (0x4011b0);
// let call3 : u64 = (0x4011c8);
let to_check : Vec<(u64,u64)> = vec![
(0x401190,0x4011c8), // start -> call
(0x40119b,0x4011b0), // cmp -> call
(0x4011b5,0x40119f), // cmp -> call
];
let expected : Vec<u8> = vec![ 1, 1, 1];
let combo = to_check.iter().zip(expected.iter());
for (edg, val) in combo {
// println!("Feedback Len: {} Cap: {}",observer.edgemap.len(),observer.edgemap.capacity());
match observer.edgemap.get(edg) {
Some(x) => hit_target &= val == x,
None =>hit_target = false
if self.target_map.len() == 0 { return Ok(true) };
let mut sum_of_square_difference : u64 = 0; // does not include found edges not in target
for (edg, val) in &self.target_map {
match observer.edgemap.get(&edg) {
Some(x) => sum_of_square_difference+=((cmp::max(*x,*val)-cmp::min(*x,*val)) as u64).pow(2),
None => sum_of_square_difference+=(*val as u64).pow(2),
}
}
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;
if hit_target {
Ok(true)
} else {
@ -206,14 +201,14 @@ impl Named for HitFeedback {
impl HitFeedback {
/// Creates a new [`HitFeedback`]
#[must_use]
pub fn new() -> Self {
Self {}
pub fn new(target_map: HashMap<(u64,u64),u8>, target_msd: f64) -> Self {
Self {target_map: target_map, target_msd: target_msd}
}
}
impl Default for HitFeedback {
fn default() -> Self {
Self::new()
Self::new(HashMap::new(),0.0)
}
}
@ -273,4 +268,77 @@ impl Default for MapHitIncreaseFeedback {
fn default() -> Self {
Self::new()
}
}
//===================================================================
/// A [`HitFeedback`] reports as interesting when all predicted worst case edges have been matched.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct HitImprovingFeedback {
target_map: HashMap<(u64,u64),u8>,
best_msd: f64,
}
impl<I, S> Feedback<I, S> for HitImprovingFeedback
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>,
{
// TODO Replace with match_name_type when stable
// let observer = _observers.match_name::<HitcountsMapObserver<O>>("edges").expect("SelectedEdgeObserver not found");
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
.expect("HitcountsMapObserver not found");
if self.target_map.len() == 0 { return Ok(true) };
let mut sum_of_square_difference : u64 = 0; // does not include found edges not in target
for (edg, val) in &self.target_map {
match observer.edgemap.get(&edg) {
Some(x) => sum_of_square_difference+=((cmp::max(*x,*val)-cmp::min(*x,*val)) as u64).pow(2),
None => sum_of_square_difference+=(*val as u64).pow(2),
}
}
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);
if hit_target {
self.best_msd = mean_sum_of_squares;
Ok(true)
} else {
Ok(false)
}
}
}
impl Named for HitImprovingFeedback {
#[inline]
fn name(&self) -> &str {
"HitFeedback"
}
}
impl HitImprovingFeedback {
/// Creates a new [`HitFeedback`]
#[must_use]
pub fn new(target_map: HashMap<(u64,u64),u8>) -> Self {
Self {target_map: target_map, best_msd: f64::MAX}
}
}
impl Default for HitImprovingFeedback {
fn default() -> Self {
Self::new(HashMap::new())
}
}