From 6793d48dbd2ad3e1307c4073def3fa6f8b36304b Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Fri, 8 Mar 2024 14:04:23 +0100 Subject: [PATCH] extract ABBs --- fuzzers/FRET/src/systemstate/helpers.rs | 23 ++++ fuzzers/FRET/src/systemstate/mod.rs | 143 ++++++++++++++++++++++++ 2 files changed, 166 insertions(+) diff --git a/fuzzers/FRET/src/systemstate/helpers.rs b/fuzzers/FRET/src/systemstate/helpers.rs index 08a80d07d4..0e5f36be5b 100644 --- a/fuzzers/FRET/src/systemstate/helpers.rs +++ b/fuzzers/FRET/src/systemstate/helpers.rs @@ -7,11 +7,13 @@ use libafl::prelude::UsesInput; use libafl_qemu::Emulator; use libafl_qemu::GuestAddr; use libafl_qemu::GuestPhysAddr; +use libafl_qemu::GuestReg; use libafl_qemu::QemuHooks; use libafl_qemu::edges::QemuEdgesMapMetadata; use libafl_qemu::emu; use libafl_qemu::hooks; use libafl_qemu::Hook; +use crate::systemstate::extract_abbs_from_trace; use crate::systemstate::RawFreeRTOSSystemState; use crate::systemstate::CURRENT_SYSTEMSTATE_VEC; use crate::systemstate::NUM_PRIOS; @@ -152,6 +154,27 @@ where fn post_exec(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) { trigger_collection(emulator,(None, None), self); + unsafe { + let c = emulator.cpu_from_index(0); + let pc = c.read_reg::(15).unwrap();; + CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].edge = (Some(pc),None); + CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].capture_point = (CaptureEvent::End,"Breakpoint"); + } + // Find the first ISREnd of vPortSVCHandler and drop anything before + unsafe { + let mut index = 0; + while index < CURRENT_SYSTEMSTATE_VEC.len() { + if CaptureEvent::ISREnd == CURRENT_SYSTEMSTATE_VEC[index].capture_point.0 && CURRENT_SYSTEMSTATE_VEC[index].capture_point.1 == "xPortPendSVHandler" { + break; + } + index += 1; + } + CURRENT_SYSTEMSTATE_VEC.drain(..index); + } + unsafe { + let abbs = extract_abbs_from_trace(&CURRENT_SYSTEMSTATE_VEC); + println!("{:?}", abbs); + } } } diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index 7de704a19b..1da810d219 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -1,5 +1,7 @@ //! systemstate referes to the State of a FreeRTOS fuzzing target use std::collections::hash_map::DefaultHasher; +use std::fmt; +use hashbrown::HashSet; use libafl_bolts::HasRefCnt; use libafl_bolts::AsSlice; use libafl_qemu::GuestAddr; @@ -195,3 +197,144 @@ impl HasRefCnt for FreeRTOSSystemStateMetadata { } libafl_bolts::impl_serdeany!(FreeRTOSSystemStateMetadata); + +#[derive(Default, Serialize, Deserialize, Clone)] +pub struct AtomicBasicBlock { + start: GuestAddr, + ends: HashSet, +} +impl fmt::Display for AtomicBasicBlock { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut ends_str = String::new(); + for end in &self.ends { + ends_str.push_str(&format!("0x{:#x}, ", end)); + } + write!(f, "AtomicBasicBlock {{ start: 0x{:#x}, ends: [{}]}}", self.start, ends_str.trim().trim_matches(',')) + } +} +impl fmt::Debug for AtomicBasicBlock { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut ends_str = String::new(); + for end in &self.ends { + ends_str.push_str(&format!("{:#x}, ", end)); + } + write!(f, "AtomicBasicBlock {{ start: {:#x}, ends: [{}]}}", self.start, ends_str.trim().trim_matches(',')) + } +} + + + +fn get_task_names(trace: &Vec) -> HashSet { + let mut ret: HashSet<_, _> = HashSet::new(); + for state in trace { + ret.insert(state.current_task.0.task_name.to_string()); + } + ret +} + +fn extract_abbs_from_trace(trace: &Vec) -> HashMap> { + let mut abbs_of_task : HashMap> = HashMap::new(); + let mut last_abb_of_task : HashMap = HashMap::new(); + // iterate over all states and extract atomic basic blocks + // an atomic base block has a single entry and multiple exits + // the cuts between blocks are api calls + // when capture_point is APIEnd, the destination of the edge is the start of an atomic block + // so the next APIStart with the same current_tcb.pcTaskName is the end of the atomic block + for i in 0..trace.len() { + let tmp = unsafe { std::mem::transmute::<[i8; 10],[u8; 10]>(trace[i].current_tcb.pcTaskName) }; + let curr_name : String = std::str::from_utf8(&tmp).expect("TCB name was not utf8").chars().filter(|x| *x != '\0').collect::(); + let last : Option<&usize> = last_abb_of_task.get(&curr_name); + match trace[i].capture_point.0 { + CaptureEvent::APIStart => { + // end the last atomic block + if let Some(&l) = last { + let start = trace[l].edge.1.unwrap(); + let end = trace[i].edge.0.unwrap(); + match abbs_of_task.get_mut(&curr_name) { + Some(v) => { + match v.iter_mut().find(|x| x.start==start) { + Some(abb) => { + abb.ends.insert(end); + } + None => { + let mut t = HashSet::new(); + t.insert(end); + v.push(AtomicBasicBlock {start, ends: t}); + } + }; + }, + None => { + let mut v = Vec::new(); + let mut t = HashSet::new(); + t.insert(end); + v.push(AtomicBasicBlock {start, ends: t}); + abbs_of_task.insert(curr_name, v); + } + } + } else { + // first API call of this task + let mut v = Vec::new(); + let mut t = HashSet::new(); + let end = trace[i].edge.0.unwrap(); + t.insert(end); + v.push(AtomicBasicBlock {start: 0, ends: t}); + abbs_of_task.insert(curr_name, v); + } + }, + CaptureEvent::APIEnd => { + match last { + Some(&l) => { + //assert!(trace[l].capture_point.0 == CaptureEvent::APIStart); + }, + None => (), + } + last_abb_of_task.insert(curr_name, i); + }, + CaptureEvent::ISRStart => { + }, + CaptureEvent::ISREnd => { + }, + CaptureEvent::End => { + // end the last atomic block + if let Some(&l) = last { + let start = trace[l].edge.1.unwrap(); + let end = trace[i].edge.0.unwrap(); + match abbs_of_task.get_mut(&curr_name) { + Some(v) => { + match v.iter_mut().find(|x| x.start==start) { + Some(abb) => { + abb.ends.insert(end); + } + None => { + let mut t = HashSet::new(); + t.insert(end); + v.push(AtomicBasicBlock {start, ends: t}); + } + }; + }, + None => { + let mut v = Vec::new(); + let mut t = HashSet::new(); + t.insert(end); + v.push(AtomicBasicBlock {start, ends: t}); + abbs_of_task.insert(curr_name, v); + } + } + } else { + // first API call of this task + let mut v = Vec::new(); + let mut t = HashSet::new(); + let end = trace[i].edge.0.unwrap(); + t.insert(end); + v.push(AtomicBasicBlock {start: 0, ends: t}); + abbs_of_task.insert(curr_name, v); + } + }, + CaptureEvent::Undefined => { + }, + } + } + abbs_of_task +} + +libafl_bolts::impl_serdeany!(AtomicBasicBlock); \ No newline at end of file