add feedback for improving msd
This commit is contained in:
parent
d2d2862727
commit
d4d86927b7
@ -1,5 +1,9 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! 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::stats::SimpleStats;
|
||||||
use libafl::events::SimpleEventManager;
|
use libafl::events::SimpleEventManager;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
@ -113,6 +117,11 @@ pub fn main() {
|
|||||||
.help("Timeout for each individual execution, in milliseconds")
|
.help("Timeout for each individual execution, in milliseconds")
|
||||||
.default_value("1000"),
|
.default_value("1000"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("edges")
|
||||||
|
.long("libafl-edges")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
.try_get_matches_from(filter_qemu_args())
|
.try_get_matches_from(filter_qemu_args())
|
||||||
{
|
{
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
@ -165,8 +174,12 @@ pub fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let kernel = PathBuf::from(res.value_of("k").unwrap().to_string());
|
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");
|
.expect("An error occurred while fuzzing");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,6 +205,7 @@ fn fuzz(
|
|||||||
logfile: PathBuf,
|
logfile: PathBuf,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
kernel: PathBuf,
|
kernel: PathBuf,
|
||||||
|
dump_edges: Option<PathBuf>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
env::remove_var("LD_LIBRARY_PATH");
|
env::remove_var("LD_LIBRARY_PATH");
|
||||||
|
|
||||||
@ -286,16 +300,28 @@ fn fuzz(
|
|||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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!(
|
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),
|
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||||
MapHitIncreaseFeedback::new(),
|
HitImprovingFeedback::new(target_map.clone())
|
||||||
// Time feedback, this one does not need a feedback state
|
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
|
||||||
);
|
);
|
||||||
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = {
|
let mut state = {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
|
use libafl::feedbacks::CrashFeedback;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use libafl::corpus::Corpus;
|
use libafl::corpus::Corpus;
|
||||||
@ -234,7 +235,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 = HitFeedback::new();
|
let objective = CrashFeedback::new();
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
|
@ -10,6 +10,7 @@ use libafl::state::HasMetadata;
|
|||||||
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
||||||
use libafl::observers::MapObserver;
|
use libafl::observers::MapObserver;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{
|
bolts::{
|
||||||
@ -145,7 +146,10 @@ where
|
|||||||
|
|
||||||
/// A [`HitFeedback`] reports as interesting when all predicted worst case edges have been matched.
|
/// A [`HitFeedback`] reports as interesting when all predicted worst case edges have been matched.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[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
|
impl<I, S> Feedback<I, S> for HitFeedback
|
||||||
where
|
where
|
||||||
@ -168,26 +172,17 @@ where
|
|||||||
// let observer = _observers.match_name::<HitcountsMapObserver<O>>("edges").expect("SelectedEdgeObserver not found");
|
// let observer = _observers.match_name::<HitcountsMapObserver<O>>("edges").expect("SelectedEdgeObserver not found");
|
||||||
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
|
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
|
||||||
.expect("HitcountsMapObserver not found");
|
.expect("HitcountsMapObserver not found");
|
||||||
let mut hit_target: bool = true;
|
if self.target_map.len() == 0 { return Ok(true) };
|
||||||
//check if we've hit any targets.
|
|
||||||
// let inc : u64 = (0x401180);
|
let mut sum_of_square_difference : u64 = 0; // does not include found edges not in target
|
||||||
// let call1 : u64 = (0x40119f);
|
for (edg, val) in &self.target_map {
|
||||||
// let call2 : u64 = (0x4011b0);
|
match observer.edgemap.get(&edg) {
|
||||||
// let call3 : u64 = (0x4011c8);
|
Some(x) => sum_of_square_difference+=((cmp::max(*x,*val)-cmp::min(*x,*val)) as u64).pow(2),
|
||||||
let to_check : Vec<(u64,u64)> = vec![
|
None => sum_of_square_difference+=(*val as u64).pow(2),
|
||||||
(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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 {
|
if hit_target {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
@ -206,14 +201,14 @@ impl Named for HitFeedback {
|
|||||||
impl HitFeedback {
|
impl HitFeedback {
|
||||||
/// Creates a new [`HitFeedback`]
|
/// Creates a new [`HitFeedback`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new(target_map: HashMap<(u64,u64),u8>, target_msd: f64) -> Self {
|
||||||
Self {}
|
Self {target_map: target_map, target_msd: target_msd}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for HitFeedback {
|
impl Default for HitFeedback {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new(HashMap::new(),0.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,3 +269,76 @@ impl Default for MapHitIncreaseFeedback {
|
|||||||
Self::new()
|
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())
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user