update to 0.13.0 API

This commit is contained in:
Alwin Berger 2024-06-19 13:30:36 +02:00
parent df7333b764
commit 5fad373199
17 changed files with 313 additions and 235 deletions

View File

@ -11,8 +11,9 @@ use libafl::{
fuzzer::{StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
observers::{Observer,VariableMapObserver},
state::{StdState, HasNamedMetadata},
state::{StdState},
Error,
common::HasNamedMetadata,
observers::ObserversTuple, prelude::UsesInput,
};
use serde::{Deserialize, Serialize};
@ -22,7 +23,7 @@ use libafl_qemu::{
emu,
emu::Emulator,
executor::QemuExecutor,
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
helpers::{QemuHelper, QemuHelperTuple, HasInstrumentationFilter},
};
use libafl::events::EventFirer;
use libafl::state::MaybeHasClientPerfMonitor;
@ -30,13 +31,14 @@ use libafl::prelude::State;
use libafl::inputs::Input;
use libafl::feedbacks::Feedback;
use libafl::SerdeAny;
use libafl::state::HasMetadata;
use libafl::common::HasMetadata;
use libafl::corpus::testcase::Testcase;
use core::{fmt::Debug, time::Duration};
// use libafl::feedbacks::FeedbackState;
// use libafl::state::HasFeedbackStates;
use std::time::{SystemTime, UNIX_EPOCH};
use std::path::PathBuf;
use std::borrow::Cow;
pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH;
@ -60,7 +62,7 @@ pub struct QemuIcountMetadata {
#[derive(Debug, Serialize, Deserialize, SerdeAny)]
pub struct MaxIcountMetadata {
pub max_icount_seen: u64,
pub name: String,
pub name: Cow<'static, str>,
}
// impl FeedbackState for MaxIcountMetadata
@ -74,8 +76,8 @@ pub struct MaxIcountMetadata {
impl Named for MaxIcountMetadata
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -86,7 +88,7 @@ impl MaxIcountMetadata
pub fn new(name: &'static str) -> Self {
Self {
max_icount_seen: 0,
name: name.to_string(),
name: Cow::from(name),
}
}
}
@ -106,7 +108,7 @@ pub struct IcHist (pub Vec<(u64, u128)>, pub (u64,u128));
/// A simple observer, just overlooking the runtime of the target.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct QemuClockObserver {
name: String,
name: Cow<'static, str>,
start_tick: u64,
end_tick: u64,
dump_path: Option<PathBuf>
@ -117,7 +119,7 @@ impl QemuClockObserver {
#[must_use]
pub fn new(name: &'static str, dump_path: Option<PathBuf>) -> Self {
Self {
name: name.to_string(),
name: Cow::from(name),
start_tick: 0,
end_tick: 0,
dump_path
@ -149,7 +151,7 @@ where
}
fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> {
unsafe { self.end_tick = emu::icount_get_raw() };
unsafe { self.end_tick = libafl_qemu::sys::icount_get_raw() };
if let Some(td) = &self.dump_path {
// println!("clock post {}", self.end_tick);
// println!("Number of Ticks: {} <- {} {}",self.end_tick - self.start_tick, self.end_tick, self.start_tick);
@ -187,7 +189,7 @@ where
impl Named for QemuClockObserver {
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -195,7 +197,7 @@ impl Named for QemuClockObserver {
impl Default for QemuClockObserver {
fn default() -> Self {
Self {
name: String::from("clock"),
name: Cow::from(String::from("clock")),
start_tick: 0,
end_tick: 0,
dump_path: None
@ -210,7 +212,7 @@ impl Default for QemuClockObserver {
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ClockTimeFeedback {
exec_time: Option<Duration>,
name: String,
name: Cow<'static, str>,
}
impl<S> Feedback<S> for ClockTimeFeedback
@ -238,9 +240,10 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item
#[inline]
fn append_metadata<OT>(
fn append_metadata<EM, OT>(
&mut self,
_state: &mut S,
_manager: &mut EM,
observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error> {
@ -259,8 +262,8 @@ where
impl Named for ClockTimeFeedback {
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -270,7 +273,7 @@ impl ClockTimeFeedback {
pub fn new(name: &'static str) -> Self {
Self {
exec_time: None,
name: name.to_string(),
name: Cow::from(name.to_string()),
}
}
@ -279,7 +282,7 @@ impl ClockTimeFeedback {
pub fn new_with_observer(observer: &QemuClockObserver) -> Self {
Self {
exec_time: None,
name: observer.name().to_string(),
name: observer.name().clone(),
}
}
}
@ -287,7 +290,7 @@ impl ClockTimeFeedback {
/// A [`Feedback`] rewarding increasing the execution cycles on Qemu.
#[derive(Debug)]
pub struct QemuClockIncreaseFeedback {
name: String,
name: Cow<'static, str>,
}
impl<S> Feedback<S> for QemuClockIncreaseFeedback
@ -322,7 +325,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item
#[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
// testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime});
Ok(())
}
@ -337,7 +340,7 @@ where
impl Named for QemuClockIncreaseFeedback {
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -346,7 +349,7 @@ impl QemuClockIncreaseFeedback {
/// Creates a new [`HitFeedback`]
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {name: String::from(name)}
Self {name: Cow::from(String::from(name))}
}
}

View File

@ -4,13 +4,13 @@ use core::time::Duration;
use std::{env, path::PathBuf, process::{self, abort}, io::{Read, Write}, fs::{self, OpenOptions}, cmp::{min, max}, mem::transmute_copy, collections::btree_map::Range, ptr::addr_of_mut, ffi::OsStr};
use hashbrown::HashMap;
use libafl_bolts::{
core_affinity::Cores, current_nanos, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsMutSlice, AsSlice
core_affinity::Cores, current_nanos, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice
};
use libafl::{
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::{ExitKind, TimeoutExecutor}, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, observers::VariableMapObserver, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HasBytesVec, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, HasMetadata, HasNamedMetadata, StdState}, Error, Evaluator
common::{HasMetadata, HasNamedMetadata}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::ExitKind, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator
};
use libafl_qemu::{
edges::{self, edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM}, elf::EasyElf, emu::{libafl_qemu_remove_native_breakpoint, libafl_qemu_set_native_breakpoint, Emulator}, GuestAddr, GuestPhysAddr, QemuExecutor, QemuHooks, QemuInstrumentationFilter, Regs
edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf::EasyElf, emu::Emulator, GuestAddr, GuestPhysAddr, QemuExecutor, QemuFilterList, QemuHooks, Regs, StdInstrumentationFilter
};
use rand::{SeedableRng, StdRng, Rng};
use crate::{
@ -25,6 +25,8 @@ use petgraph::graph::NodeIndex;
use petgraph::prelude::DiGraph;
use crate::systemstate::stg::STGFeedbackState;
use crate::clock::QEMU_ICOUNT_SHIFT;
use libafl::inputs::HasMutatorBytes;
use libafl_qemu::Qemu;
// Constants ================================================================================
@ -373,8 +375,8 @@ let app_fn_ranges = get_all_fn_symbol_ranges(&elf, app_range.clone());
let mut isr_ranges : HashMap<String,std::ops::Range<GuestAddr>> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect();
systemstate::helpers::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_ranges.insert(y.0,y.1));}); // add used defined isr
let denylist=isr_ranges.values().map(|x| x.clone()).collect();
let denylist = QemuInstrumentationFilter::DenyList(denylist); // do not count isr jumps, which are useless
let denylist : Vec<_> =isr_ranges.values().map(|x| x.clone()).collect();
let denylist = QemuFilterList::DenyList(denylist); // do not count isr jumps, which are useless
#[cfg(feature = "observe_systemstate")]
let mut isr_addreses : HashMap<GuestAddr, String> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect();
#[cfg(feature = "observe_systemstate")]
@ -421,22 +423,22 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// "-semihosting",
// "--semihosting-config",
// "enable=on,target=native",
"-snapshot",
"-drive",
"if=none,format=qcow2,file=dummy.qcow2",
// "-snapshot",
// "-drive",
// "if=none,format=qcow2,file=dummy.qcow2",
].into_iter().map(String::from).collect();
let env: Vec<(String, String)> = env::vars().collect();
let emu = Emulator::new(&args, &env).expect("Emulator creation failed");
let emu = Qemu::init(&args, &env).expect("Emulator creation failed");
if let Some(main_addr) = main_addr {
unsafe {
libafl_qemu_set_native_breakpoint(main_addr);
emu.run();
libafl_qemu_remove_native_breakpoint(main_addr);
}
}
// if let Some(main_addr) = main_addr {
// unsafe {
// emu.set_breakpoint(main_addr);
// emu.run();
// emu.remove_breakpoint(main_addr);
// }
// }
unsafe { libafl_qemu_set_native_breakpoint(breakpoint); }// BREAKPOINT
unsafe { emu.set_breakpoint(breakpoint); }// BREAKPOINT
// The wrapped harness function, calling out to the LLVM-style harness
let mut harness = |input: &BytesInput| {
@ -475,7 +477,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// If the execution stops at any point other then the designated breakpoint (e.g. a breakpoint on a panic method) we consider it a crash
let mut pcs = (0..emu.num_cpus())
.map(|i| emu.cpu_from_index(i))
.map(|cpu| -> Result<u32, String> { cpu.read_reg(Regs::Pc) });
.map(|cpu| -> Result<u32, _> { cpu.read_reg(Regs::Pc) });
match pcs
.find(|pc| (breakpoint..breakpoint + 5).contains(pc.as_ref().unwrap_or(&0)))
{
@ -496,14 +498,14 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
addr_of_mut!(MAX_EDGES_NUM)
)};
#[cfg(feature = "observer_hitcounts")]
let edges_observer = HitcountsMapObserver::new(edges_observer);
let edges_observer = HitcountsMapObserver::new(edges_observer).track_indices();
#[cfg(feature = "observe_systemstate")]
let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice(
"stg",
stg_map_mut_slice(),
addr_of_mut!(MAX_STG_NUM)
)};
)}.track_indices();
#[cfg(feature = "observe_systemstate")]
let systemstate_observer = QemuSystemStateObserver::new();
@ -576,7 +578,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
#[cfg(feature = "sched_afl",)]
let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new());
#[cfg(feature = "sched_stg")]
let scheduler = LongestTraceScheduler::new(GraphMaximizerCorpusScheduler::new(QueueScheduler::new()));
let scheduler = LongestTraceScheduler::new(GraphMaximizerCorpusScheduler::new(&stg_coverage_observer,QueueScheduler::new()));
#[cfg(feature = "sched_genetic")]
let scheduler = GenerationScheduler::new();
@ -587,7 +589,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
#[cfg(feature = "observe_systemstate")]
let qhelpers = (QemuSystemStateHelper::new(api_addreses,api_ranges,isr_addreses,isr_ranges,curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,scheduler_lock,scheduler_running, critical_section,input_counter_ptr,app_range.clone()), qhelpers);
#[cfg(feature = "observe_edges")]
let qhelpers = (QemuEdgeCoverageHelper::new(denylist), qhelpers);
let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
let qhelpers = (QemuStateRestoreHelper::new(), qhelpers);
let mut hooks = QemuHooks::new(emu.clone(),qhelpers);
@ -600,18 +602,18 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
let observer_list = (clock_time_observer, observer_list);
// Create a QEMU in-process executor
let executor = QemuExecutor::new(
let mut executor = QemuExecutor::new(
&mut hooks,
&mut harness,
observer_list,
&mut fuzzer,
&mut state,
&mut mgr,
timeout
)
.expect("Failed to create QemuExecutor");
// Wrap the executor to keep track of the timeout
let mut executor = TimeoutExecutor::new(executor, timeout);
executor.break_on_timeout();
let mutations = havoc_mutations();
// Setup an havoc mutator with a mutational stage
@ -641,7 +643,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
if let Some(se) = seed {
unsafe {
let mut rng = StdRng::seed_from_u64(se);
for i in 0..1000 {
for i in 0..10 {
let inp = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
}
@ -740,10 +742,10 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// Initialize QEMU
let args: Vec<String> = env::args().collect();
let env: Vec<(String, String)> = env::vars().collect();
let emu = Emulator::new(&args, &env).expect("Emu creation failed");
let emu = Qemu::init(&args, &env).expect("Emu creation failed");
if let Some(main_addr) = main_addr {
unsafe { libafl_qemu_set_native_breakpoint(main_addr); }// BREAKPOINT
unsafe { emu.set_breakpoint(main_addr); }// BREAKPOINT
}
unsafe {
emu.run();

View File

@ -6,14 +6,15 @@ use std::cmp::{max, min};
use hashbrown::HashMap;
use libafl_bolts::rands::{
StdRand, RandomSeed,
StdRand, random_seed,
Rand
};
use libafl::{
corpus::{self, Corpus}, fuzzer::Evaluator, mark_feature_time, prelude::{new_hash_feedback, CorpusId, HasBytesVec, MutationResult, Mutator, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasMetadata, HasNamedMetadata, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error
common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, fuzzer::Evaluator, inputs::HasMutatorBytes, mark_feature_time, prelude::{new_hash_feedback, CorpusId, MutationResult, Mutator, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error
};
use libafl::prelude::State;
use crate::{clock::{IcHist, QEMU_ISNS_PER_USEC}, fuzzer::{DO_NUM_INTERRUPT, FIRST_INT, MAX_NUM_INTERRUPT}, systemstate::{stg::{STGFeedbackState, STGNodeMetadata}, CaptureEvent, ExecInterval, FreeRTOSSystemStateMetadata, ReducedFreeRTOSSystemState}};
use libafl::state::HasCurrentTestcase;
pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC;
// one isn per 2**4 ns
@ -77,32 +78,28 @@ where
EM: UsesState<State = Z::State>,
Z: Evaluator<E, EM>,
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata,
<Z::State as UsesInput>::Input: HasBytesVec
<Z::State as UsesInput>::Input: HasMutatorBytes
{
fn perform(
&mut self,
fuzzer: &mut Z,
executor: &mut E,
state: &mut Self::State,
manager: &mut EM,
corpus_idx: CorpusId,
manager: &mut EM
// corpus_idx: CorpusId,
) -> Result<(), Error> {
let mut _input = state
.corpus()
.get(corpus_idx)?
.borrow_mut().clone();
let mut newinput = _input.input_mut().as_mut().unwrap().clone();
let mut myrand = StdRand::new();
myrand.set_seed(state.rand_mut().next());
let mut _input = state.current_testcase()?.clone();
let mut newinput = _input.input().as_ref().unwrap().clone();
let mut do_rerun = false;
// if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
{
// need our own random generator, because borrowing rules
let mut myrand = StdRand::new();
let mut target_bytes : Vec<u8> = vec![];
{
let input = _input.input_mut().as_ref().unwrap();
let input = _input.input().as_ref().unwrap();
target_bytes = input.bytes().to_vec();
let tmp = &mut state.rand_mut();
myrand.set_seed(tmp.next());
}
// produce a slice of absolute interrupt times
@ -129,7 +126,7 @@ where
if interrupt_offsets[0] as u64 > maxtick { // place interrupt in reachable range
do_rerun = true;
for _ in 0..num_interrupts {
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64)).try_into().expect("ticks > u32")));
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick as usize, u32::MAX as usize)).try_into().expect("ticks > u32")));
}
} else {
// let choice = myrand.between(1,100);
@ -261,8 +258,8 @@ where
).collect();
if untouched.len() > 0 {
let tmp = interrupt_offsets[i];
let choice = myrand.choose(untouched);
interrupt_offsets[i] = myrand.between(choice.0.start_tick, choice.0.end_tick)
let choice = myrand.choose(untouched).unwrap();
interrupt_offsets[i] = myrand.between(choice.0.start_tick as usize, choice.0.end_tick as usize)
.try_into().expect("tick > u32");
do_rerun = true;
}
@ -274,7 +271,7 @@ where
continue;
}
}
let replacement = myrand.choose(alternatives);
let replacement = myrand.choose(alternatives).unwrap();
if (old_hit.map_or(false, |x| x == replacement)) {
// use the old value
// println!("chose old value, do nothing i: {} {}",i,interrupt_offsets[i]);
@ -285,8 +282,8 @@ where
old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick)
} else { 0 };
let tmp = interrupt_offsets[i];
interrupt_offsets[i] = (myrand.between(replacement.0.start_tick,
replacement.0.end_tick) + extra).try_into().expect("ticks > u32");
interrupt_offsets[i] = (myrand.between(replacement.0.start_tick as usize,
replacement.0.end_tick as usize) + extra as usize).try_into().expect("ticks > u32");
// println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
do_rerun = true;
}
@ -324,8 +321,8 @@ where
let mut n : Vec<u8> = vec![];
n = [prefix.concat(), suffix].concat();
newinput.bytes_mut().clear();
newinput.bytes_mut().append(&mut n);
newinput.drain(..);
newinput.extend(&n);
}
// InterruptShifterMutator::mutate(&mut mymut, state, &mut input, 0)?;
if do_rerun {
@ -333,6 +330,14 @@ where
}
Ok(())
}
fn restart_progress_should_run(&mut self, state: &mut Self::State) -> Result<bool, Error> {
Ok(true)
}
fn clear_restart_progress(&mut self, state: &mut Self::State) -> Result<(), Error> {
Ok(())
}
}
impl<E, EM, Z> UsesState for InterruptShiftStage<E, EM, Z>

View File

@ -1,11 +1,12 @@
use libafl::prelude::UsesInput;
use libafl_qemu::CPUArchState;
use libafl_qemu::sys::CPUArchState;
use libafl_qemu::Emulator;
use libafl_qemu::FastSnapshot;
use libafl_qemu::FastSnapshotPtr;
use libafl_qemu::Qemu;
use libafl_qemu::QemuExecutor;
use libafl_qemu::QemuHelper;
use libafl_qemu::QemuHelperTuple;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use libafl_qemu::QemuHooks;
use libafl_qemu::{
@ -17,7 +18,7 @@ pub struct QemuStateRestoreHelper {
has_snapshot: bool,
use_snapshot: bool,
saved_cpu_states: Vec<CPUArchState>,
fastsnap: Option<FastSnapshot>
fastsnap: Option<FastSnapshotPtr>
}
impl QemuStateRestoreHelper {
@ -56,17 +57,17 @@ where
{
}
fn post_exec<OT>(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
fn post_exec<OT>(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
// unsafe { println!("snapshot post {}",emu::icount_get_raw()) };
}
fn pre_exec(&mut self, emulator: &Emulator, _input: &S::Input) {
fn pre_exec(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input) {
// only restore in pre-exec, to preserve the post-execution state for inspection
#[cfg(feature = "snapshot_restore")]
{
#[cfg(feature = "snapshot_fast")]
match self.fastsnap {
Some(s) => emulator.restore_fast_snapshot(s),
Some(s) => unsafe { emulator.restore_fast_snapshot(s) },
None => {self.fastsnap = Some(emulator.create_fast_snapshot(true));},
}
#[cfg(not(feature = "snapshot_fast"))]

View File

@ -2,7 +2,7 @@ use libafl::SerdeAny;
use libafl_bolts::ownedref::OwnedSlice;
use libafl::inputs::BytesInput;
use libafl::prelude::UsesInput;
use libafl::state::HasNamedMetadata;
use libafl::common::HasNamedMetadata;
use std::path::PathBuf;
use crate::clock::QemuClockObserver;
use libafl::corpus::Testcase;
@ -17,7 +17,7 @@ use libafl::feedbacks::Feedback;
use libafl_bolts::Named;
use libafl::Error;
use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use serde::{Deserialize, Serialize};
use super::ExecInterval;
@ -28,28 +28,38 @@ use petgraph::prelude::DiGraph;
use petgraph::graph::NodeIndex;
use petgraph::Direction;
use std::cmp::Ordering;
use std::borrow::Cow;
//============================= Feedback
/// Shared Metadata for a systemstateFeedback
#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone, Default)]
#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)]
pub struct SystemStateFeedbackState
{
name: Cow<'static, str>,
known_traces: HashMap<u64,(u64,u64,usize)>, // encounters,ticks,length
longest: Vec<ReducedFreeRTOSSystemState>,
}
impl Named for SystemStateFeedbackState
{
#[inline]
fn name(&self) -> &str {
"systemstate"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl Default for SystemStateFeedbackState
{
fn default() -> Self {
Self {name: Cow::from("systemstate".to_string()), known_traces: HashMap::new(), longest: Vec::new() }
}
}
/// A Feedback reporting novel System-State Transitions. Depends on [`QemuSystemStateObserver`]
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NovelSystemStateFeedback
{
name: Cow<'static, str>,
last_trace: Option<Vec<ReducedFreeRTOSSystemState>>,
// known_traces: HashMap<u64,(u64,usize)>,
}
@ -80,7 +90,7 @@ where
Some(s) => s,
None => {
let n=SystemStateFeedbackState::default();
state.named_metadata_map_mut().insert(n, "systemstate");
state.named_metadata_map_mut().insert("systemstate",n);
state.named_metadata_map_mut().get_mut::<SystemStateFeedbackState>("systemstate").unwrap()
}
};
@ -117,7 +127,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item
#[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
let a = self.last_trace.take();
match a {
Some(s) => testcase.metadata_map_mut().insert(FreeRTOSSystemStateMetadata::new(s)),
@ -137,8 +147,15 @@ where
impl Named for NovelSystemStateFeedback
{
#[inline]
fn name(&self) -> &str {
"systemstate"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl Default for NovelSystemStateFeedback
{
fn default() -> Self {
Self {name: Cow::from("NovelSystemStateFeedback".to_string()), last_trace: None }
}
}
@ -147,6 +164,7 @@ impl Named for NovelSystemStateFeedback
#[derive(Debug)]
pub struct DumpSystraceFeedback
{
name: Cow<'static, str>,
dumpfile: Option<PathBuf>,
dump_metadata: bool,
last_states: Option<HashMap<u64, ReducedFreeRTOSSystemState>>,
@ -185,7 +203,7 @@ where
}
/// Append to the testcase the generated metadata in case of a new corpus item
#[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
if !self.dump_metadata {return Ok(());}
// let a = self.last_trace.take();
// match a {
@ -206,8 +224,8 @@ where
impl Named for DumpSystraceFeedback
{
#[inline]
fn name(&self) -> &str {
"Dumpsystemstate"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -216,13 +234,13 @@ impl DumpSystraceFeedback
/// Creates a new [`DumpSystraceFeedback`]
#[must_use]
pub fn new() -> Self {
Self {dumpfile: None, dump_metadata: false, last_trace: None, last_states: None }
Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, dump_metadata: false, last_trace: None, last_states: None }
}
pub fn with_dump(dumpfile: Option<PathBuf>) -> Self {
Self {dumpfile: dumpfile, dump_metadata: false, last_trace: None, last_states: None}
Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: dumpfile, dump_metadata: false, last_trace: None, last_states: None}
}
pub fn metadata_only() -> Self {
Self {dumpfile: None, dump_metadata: true, last_trace: None, last_states: None}
Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, dump_metadata: true, last_trace: None, last_states: None}
}
}
@ -230,6 +248,7 @@ impl DumpSystraceFeedback
#[derive(Debug, Default)]
pub struct SystraceErrorFeedback
{
name: Cow<'static, str>,
dump_case: bool
}
@ -255,7 +274,7 @@ where
}
/// Append to the testcase the generated metadata in case of a new corpus item
#[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, _observers: &OT, _testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
Ok(())
}
@ -269,8 +288,8 @@ where
impl Named for SystraceErrorFeedback
{
#[inline]
fn name(&self) -> &str {
"SystraceErrorFeedback"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -278,6 +297,6 @@ impl SystraceErrorFeedback
{
#[must_use]
pub fn new(dump_case: bool) -> Self {
Self {dump_case}
Self {name: Cow::from(String::from("SystraceErrorFeedback")), dump_case}
}
}

View File

@ -1,7 +1,7 @@
#![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,deref_nullptr)]
use serde::{Deserialize, Serialize};
// Manual Types
use libafl_qemu::Emulator;
use libafl_qemu::{Emulator, Qemu};
/*========== Start of generated Code =============*/
pub type char_ptr = ::std::os::raw::c_uint;
@ -88,7 +88,7 @@ pub type TCB_t = tskTCB;
/*========== End of generated Code =============*/
pub trait emu_lookup {
fn lookup(emu: &Emulator, addr: ::std::os::raw::c_uint) -> Self;
fn lookup(emu: &Qemu, addr: ::std::os::raw::c_uint) -> Self;
}
@ -104,7 +104,7 @@ pub enum rtos_struct {
macro_rules! impl_emu_lookup {
($struct_name:ident) => {
impl $crate::systemstate::freertos::emu_lookup for $struct_name {
fn lookup(emu: &Emulator, addr: ::std::os::raw::c_uint) -> $struct_name {
fn lookup(emu: &Qemu, addr: ::std::os::raw::c_uint) -> $struct_name {
let mut tmp : [u8; std::mem::size_of::<$struct_name>()] = [0u8; std::mem::size_of::<$struct_name>()];
unsafe {
emu.read_mem(addr.into(), &mut tmp);

View File

@ -1,14 +1,14 @@
use libafl::SerdeAny;
/// Feedbacks organizing SystemStates as a graph
use libafl::inputs::HasBytesVec;
use libafl_bolts::rands::RandomSeed;
// use libafl::inputs::HasBytesVec;
use libafl_bolts::rands::random_seed;
use libafl_bolts::rands::StdRand;
use libafl::mutators::Mutator;
use libafl::mutators::MutationResult;
use libafl::prelude::HasTargetBytes;
use libafl::prelude::UsesInput;
use libafl::state::HasNamedMetadata;
use libafl::common::HasNamedMetadata;
use libafl::state::UsesState;
use libafl::prelude::State;
use core::marker::PhantomData;
@ -35,7 +35,7 @@ use libafl::feedbacks::Feedback;
use libafl_bolts::Named;
use libafl::Error;
use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use serde::{Deserialize, Serialize};
use super::ExecInterval;
@ -46,6 +46,7 @@ use petgraph::prelude::DiGraph;
use petgraph::graph::NodeIndex;
use petgraph::Direction;
use std::cmp::Ordering;
use std::borrow::Cow;
use libafl_bolts::rands::Rand;
@ -148,14 +149,14 @@ impl SysGraphMetadata {
Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0}
}
}
impl AsSlice for SysGraphMetadata {
/// Convert the slice of system-states to a slice of hashes over enumerated states
fn as_slice(&self) -> &[usize] {
self.indices.as_slice()
}
// impl AsSlice for SysGraphMetadata {
// /// Convert the slice of system-states to a slice of hashes over enumerated states
// fn as_slice(&self) -> &[usize] {
// self.indices.as_slice()
// }
type Entry = usize;
}
// type Entry = usize;
// }
impl HasRefCnt for SysGraphMetadata {
fn refcnt(&self) -> isize {
@ -169,8 +170,8 @@ impl HasRefCnt for SysGraphMetadata {
libafl_bolts::impl_serdeany!(SysGraphMetadata);
pub type GraphMaximizerCorpusScheduler<CS> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,SysGraphMetadata>;
pub type GraphMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,SysGraphMetadata,O>;
//============================= Graph Feedback
@ -181,7 +182,7 @@ pub struct SysGraphFeedbackState
pub graph: DiGraph<SysGraphNode, ()>,
entrypoint: NodeIndex,
exit: NodeIndex,
name: String,
name: Cow<'static, str>
}
impl SysGraphFeedbackState
{
@ -193,7 +194,7 @@ impl SysGraphFeedbackState
exit.base.current_task.task_name="End".to_string();
let entry = graph.add_node(entry);
let exit = graph.add_node(exit);
Self {graph: graph, entrypoint: entry, exit: exit, name: String::from("SysMap")}
Self {graph: graph, entrypoint: entry, exit: exit, name: Cow::from(String::from("SysMap"))}
}
fn insert(&mut self, list: Vec<ReducedFreeRTOSSystemState>, input: &Vec<u8>) {
let mut current_index = self.entrypoint;
@ -251,7 +252,7 @@ impl SysGraphFeedbackState
impl Named for SysGraphFeedbackState
{
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -278,12 +279,12 @@ impl SysGraphFeedbackState
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct SysMapFeedback
{
name: String,
name: Cow<'static, str>,
last_trace: Option<Vec<NodeIndex>>,
}
impl SysMapFeedback {
pub fn new() -> Self {
Self {name: String::from("SysMapFeedback"), last_trace: None }
Self {name: Cow::from(String::from("SysMapFeedback")), last_trace: None }
}
}
@ -313,7 +314,7 @@ where
Some(s) => s,
None => {
let n=SysGraphFeedbackState::default();
state.named_metadata_map_mut().insert(n, "SysMap");
state.named_metadata_map_mut().insert("SysMap",n);
state.named_metadata_map_mut().get_mut::<SysGraphFeedbackState>("SysMap").unwrap()
}
};
@ -324,7 +325,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item
#[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
let a = self.last_trace.take();
match a {
Some(s) => testcase.metadata_map_mut().insert(SysGraphMetadata::new(s)),
@ -343,7 +344,7 @@ where
impl Named for SysMapFeedback
{
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -9,6 +9,7 @@ use libafl_qemu::Emulator;
use libafl_qemu::GuestAddr;
use libafl_qemu::GuestPhysAddr;
use libafl_qemu::GuestReg;
use libafl_qemu::Qemu;
use libafl_qemu::QemuHooks;
use libafl_qemu::edges::QemuEdgesMapMetadata;
use libafl_qemu::emu;
@ -26,7 +27,7 @@ use super::freertos;
use super::CaptureEvent;
use libafl_qemu::{
helper::{QemuHelper, QemuHelperTuple},
helpers::{QemuHelper, QemuHelperTuple},
// edges::SAVED_JUMP,
};
@ -120,14 +121,14 @@ where
}
// TODO: refactor duplicate code
fn pre_exec(&mut self, _emulator: &Emulator, _input: &S::Input) {
fn pre_exec(&mut self, _emulator: libafl_qemu::Qemu, _input: &S::Input) {
unsafe {
CURRENT_SYSTEMSTATE_VEC.clear();
}
}
fn post_exec<OT>(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
trigger_collection(emulator,(0, 0), CaptureEvent::End, self);
fn post_exec<OT>(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
trigger_collection(&emulator,(0, 0), CaptureEvent::End, self);
unsafe {
let c = emulator.cpu_from_index(0);
let pc = c.read_reg::<i32, u32>(15).unwrap();
@ -148,7 +149,7 @@ where
}
}
fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emulator, target: GuestAddr) -> freertos::List_t {
fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &libafl_qemu::Qemu, target: GuestAddr) -> freertos::List_t {
let read : freertos::List_t = freertos::emu_lookup::lookup(emulator, target);
let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
@ -187,7 +188,7 @@ fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emul
}
#[inline]
fn trigger_collection(emulator: &Emulator, edge: (GuestAddr, GuestAddr), event: CaptureEvent, h: &QemuSystemStateHelper) {
fn trigger_collection(emulator: &libafl_qemu::Qemu, edge: (GuestAddr, GuestAddr), event: CaptureEvent, h: &QemuSystemStateHelper) {
let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
let mut systemstate = RawFreeRTOSSystemState::default();
@ -272,7 +273,7 @@ where
S: UsesInput,
QT: QemuHelperTuple<S>,
{
let emulator = hooks.emulator();
let emulator = hooks.qemu();
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
let src = read_rec_return_stackframe(emulator, 0xfffffffc);
trigger_collection(emulator, (src, pc), CaptureEvent::ISRStart, h);
@ -324,7 +325,7 @@ where
QT: QemuHelperTuple<S>,
{
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
let emulator = hooks.emulator();
let emulator = hooks.qemu();
if id == 1 { // API call
trigger_collection(emulator, (src, dest), CaptureEvent::APIStart, h);
// println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator));
@ -353,19 +354,19 @@ where
//============================= Utility functions
fn get_icount(emulator : &Emulator) -> u64 {
fn get_icount(emulator : &libafl_qemu::Qemu) -> u64 {
unsafe {
// TODO: investigate why can_do_io is not set sometimes, as this is just a workaround
let c = emulator.cpu_from_index(0);
let can_do_io = (*c.raw_ptr()).neg.can_do_io;
(*c.raw_ptr()).neg.can_do_io = true;
let r = emu::icount_get_raw();
let r = libafl_qemu::sys::icount_get_raw();
(*c.raw_ptr()).neg.can_do_io = can_do_io;
r
}
}
fn read_rec_return_stackframe(emu : &Emulator, lr : GuestAddr) -> GuestAddr {
fn read_rec_return_stackframe(emu : &libafl_qemu::Qemu, lr : GuestAddr) -> GuestAddr {
let lr_ = lr & u32::MAX-1;
if lr_ == 0xfffffffc || lr_ == 0xFFFFFFF8 || lr_ == 0xFFFFFFF0 {
unsafe {

View File

@ -242,14 +242,14 @@ where
s.finish()
}
impl AsSlice for FreeRTOSSystemStateMetadata {
/// Convert the slice of system-states to a slice of hashes over enumerated states
fn as_slice(&self) -> &[usize] {
self.indices.as_slice()
}
// impl AsSlice for FreeRTOSSystemStateMetadata {
// /// Convert the slice of system-states to a slice of hashes over enumerated states
// fn as_slice(&self) -> &[usize] {
// self.indices.as_slice()
// }
type Entry = usize;
}
// type Entry = usize;
// }
impl HasRefCnt for FreeRTOSSystemStateMetadata {
fn refcnt(&self) -> isize {

View File

@ -12,6 +12,7 @@ use crate::systemstate::CaptureEvent;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::borrow::Cow;
use super::{ AtomicBasicBlock, ExecInterval};
use super::{
@ -26,7 +27,7 @@ use super::{
/// The Qemusystemstate Observer retrieves the systemstate
/// that will get updated by the target.
#[derive(Serialize, Deserialize, Debug, Default)]
#[derive(Serialize, Deserialize, Debug)]
#[allow(clippy::unsafe_derive_deserialize)]
pub struct QemuSystemStateObserver
{
@ -35,7 +36,7 @@ pub struct QemuSystemStateObserver
pub last_trace: Vec<ExecInterval>,
pub last_input: Vec<u8>,
pub success: bool,
name: String,
name: Cow<'static, str>,
}
impl<S> Observer<S> for QemuSystemStateObserver
@ -74,9 +75,8 @@ where
impl Named for QemuSystemStateObserver
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -90,9 +90,13 @@ impl HasLen for QemuSystemStateObserver
impl QemuSystemStateObserver {
pub fn new() -> Self {
Self{last_run: vec![], last_trace: vec![], last_input: vec![], name: "systemstate".to_string(), last_states: HashMap::new(), success: false }
Self{last_run: vec![], last_trace: vec![], last_input: vec![], name: Cow::from("systemstate".to_string()), last_states: HashMap::new(), success: false }
}
}
impl Default for QemuSystemStateObserver {
fn default() -> Self {
Self::new()
}
}
//============================= Parsing helpers

View File

@ -11,7 +11,8 @@ use libafl::{
corpus::{Corpus, Testcase},
inputs::UsesInput,
schedulers::{Scheduler, TestcaseScore, minimizer::DEFAULT_SKIP_NON_FAVORED_PROB },
state::{HasCorpus, HasMetadata, HasRand, UsesState, State},
state::{HasCorpus, HasRand, UsesState, State},
common::HasMetadata,
Error, SerdeAny, prelude::CorpusId,
};
@ -39,7 +40,7 @@ impl LongestTracesMetadata {
#[derive(Debug, Clone)]
pub struct LongestTraceScheduler<CS> {
base: CS,
skip_non_favored_prob: u64,
skip_non_favored_prob: usize,
}
impl<CS> UsesState for LongestTraceScheduler<CS>
@ -102,7 +103,7 @@ where
.metadata_map()
.get::<STGNodeMetadata>().map_or(0, |x| x.nodes.len());
let m = self.get_update_trace_length(state,l);
state.rand_mut().below(m) > l as u64
state.rand_mut().below(m as usize) > l
} && state.rand_mut().below(100) < self.skip_non_favored_prob
{
idx = self.base.next(state)?;
@ -130,7 +131,7 @@ where
pub fn new(base: CS) -> Self {
Self {
base,
skip_non_favored_prob: DEFAULT_SKIP_NON_FAVORED_PROB,
skip_non_favored_prob: (DEFAULT_SKIP_NON_FAVORED_PROB * 100.0) as usize,
}
}
}

View File

@ -2,17 +2,18 @@
use hashbrown::HashSet;
use libafl::SerdeAny;
/// Feedbacks organizing SystemStates as a graph
use libafl::inputs::HasBytesVec;
// use libafl::inputs::HasBytesVec;
use libafl_bolts::ownedref::OwnedMutSlice;
use libafl_bolts::AsIter;
use petgraph::graph::EdgeIndex;
use std::fs;
use libafl_bolts::rands::RandomSeed;
use libafl_bolts::rands::random_seed;
use libafl_bolts::rands::StdRand;
use libafl::mutators::Mutator;
use libafl::mutators::MutationResult;
use libafl::prelude::HasTargetBytes;
use libafl::prelude::UsesInput;
use libafl::state::HasNamedMetadata;
use libafl::common::HasNamedMetadata;
use libafl::state::UsesState;
use libafl::prelude::State;
use petgraph::dot::Config;
@ -40,9 +41,9 @@ use libafl::state::MaybeHasClientPerfMonitor;
use libafl::feedbacks::Feedback;
use libafl_bolts::Named;
use libafl::Error;
use libafl_qemu::edges::EDGES_MAP_SIZE;
use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE;
use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use serde::{Deserialize, Serialize};
use super::feedbacks::SystemStateFeedbackState;
@ -63,6 +64,9 @@ use libafl_bolts::rands::Rand;
use crate::clock::FUZZ_START_TIMESTAMP;
use std::time::SystemTime;
use std::{fs::OpenOptions, io::Write};
use std::borrow::Cow;
use std::ops::Deref;
use std::ops::DerefMut;
//============================= Data Structures
#[derive(Serialize, Deserialize, Clone, Debug, Default, Hash)]
@ -144,6 +148,7 @@ impl STGEdge {
#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)]
pub struct STGFeedbackState
{
name: Cow<'static, str>,
// aggregated traces as a graph
pub graph: DiGraph<STGNode, STGEdge>,
systemstate_index: HashMap<u64, ReducedFreeRTOSSystemState>,
@ -179,6 +184,7 @@ impl Default for STGFeedbackState {
let index = HashMap::from([(h_entry, entrypoint), (h_exit, exitpoint)]);
STGFeedbackState {
name: Cow::from("stgfeedbackstate".to_string()),
graph,
stgnode_index: index,
entrypoint,
@ -196,8 +202,8 @@ impl Default for STGFeedbackState {
impl Named for STGFeedbackState
{
#[inline]
fn name(&self) -> &str {
"stgfeedbackstate"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -238,13 +244,31 @@ impl STGNodeMetadata {
Self {indices, intervals, nodes, abbs, aggregate, top_abb_counts, edges, tcref: 0}
}
}
impl AsSlice for STGNodeMetadata {
/// Convert the slice of system-states to a slice of hashes over enumerated states
fn as_slice(&self) -> &[usize] {
self.indices.as_slice()
}
type Entry = usize;
// impl AsSlice for STGNodeMetadata {
// /// Convert the slice of system-states to a slice of hashes over enumerated states
// fn as_slice(&self) -> &[usize] {
// self.indices.as_slice()
// }
// type Entry = usize;
// type SliceRef = &[usize];
// }
impl Deref for STGNodeMetadata {
type Target = [usize];
/// Convert to a slice
fn deref(&self) -> &[usize] {
&self.indices
}
}
impl DerefMut for STGNodeMetadata {
/// Convert to a slice
fn deref_mut(&mut self) -> &mut [usize] {
&mut self.indices
}
}
impl HasRefCnt for STGNodeMetadata {
@ -259,8 +283,8 @@ impl HasRefCnt for STGNodeMetadata {
libafl_bolts::impl_serdeany!(STGNodeMetadata);
pub type GraphMaximizerCorpusScheduler<CS> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,STGNodeMetadata>;
pub type GraphMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,STGNodeMetadata,O>;
// AI generated, human verified
fn count_occurrences<T>(vec: &Vec<T>) -> HashMap<&T, usize>
@ -294,7 +318,7 @@ where
//============================= Graph Feedback
pub static mut STG_MAP: [u16; EDGES_MAP_SIZE] = [0; EDGES_MAP_SIZE];
pub static mut STG_MAP: [u16; EDGES_MAP_SIZE_IN_USE] = [0; EDGES_MAP_SIZE_IN_USE];
pub static mut MAX_STG_NUM: usize = 0;
pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> {
OwnedMutSlice::from_raw_parts_mut(STG_MAP.as_mut_ptr(), STG_MAP.len())
@ -304,7 +328,7 @@ pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> {
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct StgFeedback
{
name: String,
name: Cow<'static, str>,
last_node_trace: Option<Vec<NodeIndex>>,
last_edge_trace: Option<Vec<EdgeIndex>>,
last_intervals: Option<Vec<ExecInterval>>,
@ -468,7 +492,7 @@ where
Some(s) => s,
None => {
let n=STGFeedbackState::default();
state.named_metadata_map_mut().insert(n, "stgfeedbackstate");
state.named_metadata_map_mut().insert("stgfeedbackstate",n);
state.named_metadata_map_mut().get_mut::<STGFeedbackState>("stgfeedbackstate").unwrap()
}
};
@ -565,7 +589,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item
#[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
let nodes = self.last_node_trace.take();
let edges = self.last_edge_trace.take();
match nodes {
@ -584,7 +608,7 @@ where
impl Named for StgFeedback
{
#[inline]
fn name(&self) -> &str {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}

View File

@ -17,7 +17,7 @@ use libafl::state::{MaybeHasClientPerfMonitor, HasCorpus, UsesState};
use libafl::prelude::State;
use libafl::inputs::Input;
use libafl::feedbacks::Feedback;
use libafl::state::HasMetadata;
use libafl::common::HasMetadata;
use libafl_qemu::edges::QemuEdgesMapMetadata;
use libafl::observers::MapObserver;
use serde::{Deserialize, Serialize};
@ -35,10 +35,12 @@ use libafl::{
use crate::clock::QemuClockObserver;
use crate::systemstate::FreeRTOSSystemStateMetadata;
use std::borrow::Cow;
//=========================== Scheduler
pub type TimeMaximizerCorpusScheduler<CS> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, MapIndexesMetadata>;
pub type TimeMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, MapIndexesMetadata, O>;
/// Multiply the testcase size with the execution time.
/// This favors small and quick testcases.
@ -64,11 +66,11 @@ where
}
}
pub type LenTimeMaximizerCorpusScheduler<CS> =
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>, MapIndexesMetadata>;
pub type LenTimeMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>, MapIndexesMetadata, O>;
pub type TimeStateMaximizerCorpusScheduler<CS> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, FreeRTOSSystemStateMetadata>;
pub type TimeStateMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, FreeRTOSSystemStateMetadata, O>;
/// Multiply the testcase size with the execution time.
/// This favors small and quick testcases.
@ -98,6 +100,7 @@ where
/// A Feedback reporting if the Input consists of strictly decreasing bytes.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SortedFeedback {
name: Cow<'static, str>
}
impl<S> Feedback<S> for SortedFeedback
@ -146,8 +149,8 @@ where
impl Named for SortedFeedback {
#[inline]
fn name(&self) -> &str {
"Sorted"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -155,7 +158,7 @@ impl SortedFeedback {
/// Creates a new [`HitFeedback`]
#[must_use]
pub fn new() -> Self {
Self {}
Self {name: Cow::from("Sorted".to_string()),}
}
}
@ -170,6 +173,7 @@ impl Default for SortedFeedback {
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeReachedFeedback
{
name: Cow<'static, str>,
target_time: u64,
}
@ -199,8 +203,8 @@ where
impl Named for ExecTimeReachedFeedback
{
#[inline]
fn name(&self) -> &str {
"ExecTimeReachedFeedback"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -210,7 +214,7 @@ where
/// Creates a new [`ExecTimeReachedFeedback`]
#[must_use]
pub fn new(target_time : u64) -> Self {
Self {target_time: target_time}
Self {name: Cow::from("ExecTimeReachedFeedback".to_string()), target_time: target_time}
}
}
@ -220,6 +224,7 @@ pub static mut EXEC_TIME_COLLECTION : Vec<u32> = Vec::new();
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeCollectorFeedback
{
name: Cow<'static, str>
}
impl<S> Feedback<S> for ExecTimeCollectorFeedback
@ -249,8 +254,8 @@ where
impl Named for ExecTimeCollectorFeedback
{
#[inline]
fn name(&self) -> &str {
"ExecTimeCollectorFeedback"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -260,21 +265,27 @@ where
/// Creates a new [`ExecTimeCollectorFeedback`]
#[must_use]
pub fn new() -> Self {
Self {}
Self {name: Cow::from("ExecTimeCollectorFeedback".to_string())}
}
}
/// Shared Metadata for a SysStateFeedback
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeCollectorFeedbackState
{
name: Cow<'static, str>,
collection: Vec<u32>,
}
impl Named for ExecTimeCollectorFeedbackState
{
#[inline]
fn name(&self) -> &str {
"ExecTimeCollectorFeedbackState"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl Default for ExecTimeCollectorFeedbackState {
fn default() -> Self {
Self {name: Cow::from("ExecTimeCollectorFeedbackState".to_string()), collection: Vec::new()}
}
}
@ -283,6 +294,7 @@ impl Named for ExecTimeCollectorFeedbackState
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeIncFeedback
{
name: Cow<'static, str>,
longest_time: u64,
last_is_longest: bool
}
@ -315,9 +327,10 @@ where
Ok(false)
}
}
fn append_metadata<OT>(
fn append_metadata<EM, OT>(
&mut self,
_state: &mut S,
_manager: &mut EM,
observers: &OT,
testcase: &mut Testcase<<S as UsesInput>::Input>,
) -> Result<(), Error> {
@ -334,8 +347,8 @@ where
impl Named for ExecTimeIncFeedback
{
#[inline]
fn name(&self) -> &str {
"ExecTimeReachedFeedback"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -345,7 +358,7 @@ where
/// Creates a new [`ExecTimeReachedFeedback`]
#[must_use]
pub fn new() -> Self {
Self {longest_time: 0, last_is_longest: false}
Self {name: Cow::from("ExecTimeReachedFeedback".to_string()), longest_time: 0, last_is_longest: false}
}
}
@ -353,6 +366,7 @@ where
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AlwaysTrueFeedback
{
name: Cow<'static, str>
}
impl<S> Feedback<S> for AlwaysTrueFeedback
@ -379,8 +393,8 @@ where
impl Named for AlwaysTrueFeedback
{
#[inline]
fn name(&self) -> &str {
"AlwaysTrueFeedback"
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
@ -391,6 +405,7 @@ where
#[must_use]
pub fn new() -> Self {
Self {
name: Cow::from("AlwaysTrueFeedback".to_string())
}
}
}

View File

@ -16,9 +16,4 @@ extern_c_checked! {
pub fn icount_get_raw() -> u64;
pub fn libafl_start_int_timer();
pub fn libafl_add_jmp_hook(
gen: Option<extern "C" fn(u64, GuestAddr, GuestAddr) -> u64>, // data,src,dest
exec: Option<extern "C" fn(u64, GuestAddr, GuestAddr, u64)>, // data,src,dest,id
data: u64
) -> usize;
}

View File

@ -24,7 +24,7 @@ use crate::{
helpers::QemuHelperTuple,
qemu::{MemAccessInfo, Qemu, SKIP_EXEC_HOOK},
sys::TCGTemp,
BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, HookId, InstructionHookId, ReadHookId,
BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, HookId, InstructionHookId, ReadHookId, JmpHookId,
WriteHookId,
};
#[cfg(emulation_mode = "usermode")]
@ -370,9 +370,9 @@ where
}
}
static mut JMP_HOOKS: Vec<HookState<1>> = vec![];
create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1);
create_exec_wrapper!(jmp, (src: GuestAddr, dst: GuestAddr, id: u64), 0, 1);
static mut JMP_HOOKS: Vec<Pin<Box<HookState<1, JmpHookId>>>> = vec![];
create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1, JmpHookId);
create_exec_wrapper!(jmp, (src: GuestAddr, dst: GuestAddr, id: u64), 0, 1, JmpHookId);
@ -1410,28 +1410,36 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr, GuestAddr, u64)>,
extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr, id: u64),
>,
) -> HookId {
) -> JmpHookId {
unsafe {
let gen = get_raw_hook!(
generation_hook,
jmp_gen_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr) -> u64
unsafe extern "C" fn(&mut HookState<1, JmpHookId>, src: GuestAddr, dest: GuestAddr) -> u64
);
let exec = get_raw_hook!(
execution_hook,
jmp_0_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr, id: u64)
unsafe extern "C" fn(&mut HookState<1, JmpHookId>, src: GuestAddr, dest: GuestAddr, id: u64)
);
JMP_HOOKS.push(HookState {
id: HookId(0),
JMP_HOOKS.push(Box::pin(HookState {
id: JmpHookId(0),
gen: hook_to_repr!(generation_hook),
post_gen: HookRepr::Empty,
execs: [hook_to_repr!(execution_hook)],
});
}));
let id = self
.emulator
.add_jmp_hooks(JMP_HOOKS.last_mut().unwrap(), gen, exec);
JMP_HOOKS.last_mut().unwrap().id = id;
.qemu
.add_jmp_hooks(JMP_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
gen,
exec
);
JMP_HOOKS
.last_mut()
.unwrap()
.as_mut()
.get_unchecked_mut()
.id = id;
id
}
}

View File

@ -85,22 +85,7 @@ create_hook_id!(Cmp, libafl_qemu_remove_cmp_hook, true);
create_hook_id!(PreSyscall, libafl_qemu_remove_pre_syscall_hook, false);
create_hook_id!(PostSyscall, libafl_qemu_remove_post_syscall_hook, false);
create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false);
pub fn add_jmp_hooks<T: Into<HookData>>(
&self,
data: T,
gen: Option<extern "C" fn(T, GuestAddr, GuestAddr) -> u64>,
exec: Option<extern "C" fn(T, GuestAddr, GuestAddr, u64)>,
) -> HookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<extern "C" fn(u64, GuestAddr, GuestAddr) -> u64> =
core::mem::transmute(gen);
let exec: Option<extern "C" fn(u64, GuestAddr, GuestAddr, u64)> = core::mem::transmute(exec);
let num = libafl_add_jmp_hook(gen, exec, data);
HookId(num)
}
}
create_hook_id!(Jmp, libafl_qemu_remove_jmp_hook, true);
#[derive(Debug)]
pub enum QemuInitError {
@ -251,7 +236,7 @@ pub struct MemAccessInfo {
#[derive(Debug, Clone, Copy)]
#[repr(transparent)]
pub struct CPU {
ptr: CPUStatePtr,
pub ptr: CPUStatePtr,
}
#[derive(Debug, Clone, PartialEq)]
@ -1028,6 +1013,22 @@ impl Qemu {
pub fn host_page_size(&self) -> usize {
unsafe { libafl_qemu_sys::libafl_qemu_host_page_size() }
}
pub fn add_jmp_hooks<T: Into<HookData>>(
&self,
data: T,
gen: Option<unsafe extern "C" fn(T, GuestAddr, GuestAddr) -> u64>,
exec: Option<unsafe extern "C" fn(T, GuestAddr, GuestAddr, u64)>,
) -> JmpHookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<unsafe extern "C" fn(u64, GuestAddr, GuestAddr) -> u64> =
core::mem::transmute(gen);
let exec: Option<unsafe extern "C" fn(u64, GuestAddr, GuestAddr, u64)> = core::mem::transmute(exec);
let num = libafl_qemu_sys::libafl_add_jmp_hook(gen, exec, data);
JmpHookId(num)
}
}
}
impl ArchExtras for Qemu {

View File

@ -8,9 +8,7 @@ use std::{
use bytes_utils::SegmentedBuf;
use libafl_qemu_sys::{
libafl_load_qemu_snapshot, libafl_page_from_addr, libafl_qemu_current_paging_id,
libafl_save_qemu_snapshot, qemu_cleanup, qemu_main_loop, vm_start, GuestAddr, GuestPhysAddr,
GuestUsize, GuestVirtAddr,
libafl_load_qemu_snapshot, libafl_page_from_addr, libafl_qemu_current_paging_id, libafl_save_qemu_snapshot, libafl_start_int_timer, qemu_cleanup, qemu_main_loop, vm_start, GuestAddr, GuestPhysAddr, GuestUsize, GuestVirtAddr
};
use num_traits::Zero;