save last post interrupt edge in app

This commit is contained in:
Alwin Berger 2022-04-06 21:03:21 +02:00
parent e8b24b0c7a
commit 47a4bc19d4
5 changed files with 89 additions and 6 deletions

View File

@ -269,6 +269,16 @@ fn fuzz(
.expect("Symbol xPortPendSVHandler not found");
let svh = virt2phys(svh,&elf.goblin());
println!("PendHandle at {:#x}", svh);
let app_code_start = elf
.resolve_symbol("__APP_CODE_START__", 0)
.expect("Symbol __APP_CODE_START__ not found");
let app_code_start = virt2phys(app_code_start,&elf.goblin());
let app_code_end = elf
.resolve_symbol("__APP_CODE_END__", 0)
.expect("Symbol __APP_CODE_END__ not found");
let app_code_end = virt2phys(app_code_end,&elf.goblin());
let app_range = app_code_start..app_code_end;
println!("App Code {:x}-{:x}",app_code_start,app_code_end);
@ -349,7 +359,7 @@ fn fuzz(
&mut harness,
&emu,
tuple_list!(
QemuEdgeCoverageHelper::new(),
QemuEdgeCoverageHelper::with_app_range(app_range),
// QemuCmpLogHelper::new(),
// QemuAsanHelper::new(),
QemuSysSnapshotHelper::new(),

View File

@ -1,3 +1,4 @@
use libafl_qemu::edges::QemuEdgesMapMetadata;
use crate::sysstate::RawFreeRTOSSystemState;
use crate::sysstate::CURRENT_SYSSTATE_VEC;
use crate::sysstate::NUM_PRIOS;
@ -11,6 +12,7 @@ use libafl_qemu::{
emu::Emulator,
executor::QemuExecutor,
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
edges::SAVED_JUMP,
};
//============================= Struct definitions
@ -78,7 +80,7 @@ where
pub fn exec_syscall_hook<I, QT, S>(
emulator: &Emulator,
helpers: &mut QT,
_state: &mut S,
state: &mut S,
pc: u64,
)
where
@ -99,6 +101,25 @@ where
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr);
sysstate.current_tcb = freertos::emu_lookup::lookup(emulator,curr_tcb_addr);
unsafe {
match SAVED_JUMP {
Some(s) => {
let meta = state
.metadata_mut()
.get::<QemuEdgesMapMetadata>()
.unwrap();
for (k,v) in meta.map.iter() {
if *v==s {
// println!("Jump Saved {:x}",k.1);
sysstate.last_pc = Some(k.1); /* Currently save APP entry points */
break;
}
}
},
None => (),
}
}
// println!("{:?}",std::str::from_utf8(&current_tcb.pcTaskName));
for i in 0..NUM_PRIOS {

View File

@ -27,6 +27,7 @@ pub struct RawFreeRTOSSystemState {
prio_ready_lists: [freertos::List_t; NUM_PRIOS],
dumping_ground: HashMap<u32,freertos::rtos_struct>,
input_counter: u32,
last_pc: Option<u64>,
}
/// List of system state dumps from QemuHelpers
static mut CURRENT_SYSSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![];
@ -88,13 +89,15 @@ impl RefinedTCB {
pub struct RefinedFreeRTOSSystemState {
start_tick: u64,
end_tick: u64,
last_pc: Option<u64>,
input_counter: u32,
current_task: RefinedTCB,
ready_list_after: Vec<RefinedTCB>,
}
impl PartialEq for RefinedFreeRTOSSystemState {
fn eq(&self, other: &Self) -> bool {
self.current_task == other.current_task && self.ready_list_after == other.ready_list_after
self.current_task == other.current_task && self.ready_list_after == other.ready_list_after &&
self.last_pc == other.last_pc
}
}
@ -102,6 +105,7 @@ impl Hash for RefinedFreeRTOSSystemState {
fn hash<H: Hasher>(&self, state: &mut H) {
self.current_task.hash(state);
self.ready_list_after.hash(state);
self.last_pc.hash(state);
}
}
impl RefinedFreeRTOSSystemState {

View File

@ -130,6 +130,7 @@ for mut i in input.drain(..) {
end_tick: i.qemu_tick,
ready_list_after: collector,
input_counter: i.input_counter,
last_pc: i.last_pc,
});
start_tick=i.qemu_tick;
}

View File

@ -1,3 +1,4 @@
use std::ops::Range;
use hashbrown::{hash_map::Entry, HashMap};
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
pub use libafl_targets::{EDGES_MAP, EDGES_MAP_SIZE, MAX_EDGES_NUM};
@ -31,6 +32,7 @@ libafl::impl_serdeany!(QemuEdgesMapMetadata);
#[derive(Debug)]
pub struct QemuEdgeCoverageHelper {
filter: QemuInstrumentationFilter,
app_range: Option<Range<u64>>,
}
impl QemuEdgeCoverageHelper {
@ -38,18 +40,37 @@ impl QemuEdgeCoverageHelper {
pub fn new() -> Self {
Self {
filter: QemuInstrumentationFilter::None,
app_range: None,
}
}
#[must_use]
pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter) -> Self {
Self { filter }
pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter, app_range: Option<Range<u64>>) -> Self {
Self { filter, app_range }
}
#[must_use]
pub fn with_app_range(app_range: Range<u64>) -> Self {
Self { filter: QemuInstrumentationFilter::None, app_range: Some(app_range) }
}
#[must_use]
pub fn must_instrument(&self, addr: u64) -> bool {
self.filter.allowed(addr)
}
#[must_use]
pub fn must_save(&self, src: u64, dst: u64) -> bool {
match &self.app_range {
None => false,
Some(s) => {
// println!("must_save {} {:x} {:x}",s.contains(&src) != s.contains(&dst),src,dst);
// s.contains(&src) && !s.contains(&dst)
// println!("must_save {} {:x} {:x}",src==0&&dst!=0x9cc,src,dst);
src==0&&dst!=0x9cc
},
}
}
}
impl Default for QemuEdgeCoverageHelper {
@ -70,7 +91,14 @@ where
QT: QemuHelperTuple<I, S>,
{
executor.hook_edge_generation(gen_unique_edge_ids::<I, QT, S>);
executor.emulator().set_exec_edge_hook(trace_edge_hitcount);
match self.app_range {
None => executor.emulator().set_exec_edge_hook(trace_edge_hitcount),
Some(_) => executor.emulator().set_exec_edge_hook(trace_edge_hitcount_and_app_range),
}
}
fn pre_exec(&mut self, _emulator: &Emulator, _input: &I) {
unsafe { SAVED_JUMP=None; }
}
}
@ -83,6 +111,9 @@ fn hash_me(mut x: u64) -> u64 {
x
}
pub static mut MUST_SAVE: [bool; EDGES_MAP_SIZE] = [false; EDGES_MAP_SIZE];
pub static mut SAVED_JUMP: Option<u64> = None;
pub fn gen_unique_edge_ids<I, QT, S>(
_emulator: &Emulator,
helpers: &mut QT,
@ -95,10 +126,12 @@ where
I: Input,
QT: QemuHelperTuple<I, S>,
{
let mut must_save = false;
if let Some(h) = helpers.match_first_type::<QemuEdgeCoverageHelper>() {
if !h.must_instrument(src) && !h.must_instrument(dest) {
return None;
}
must_save = h.must_save(src, dest);
}
if state.metadata().get::<QemuEdgesMapMetadata>().is_none() {
state.add_metadata(QemuEdgesMapMetadata::new());
@ -114,6 +147,9 @@ where
let nxt = (id as usize + 1) & (EDGES_MAP_SIZE - 1);
unsafe {
MAX_EDGES_NUM = max(MAX_EDGES_NUM, nxt);
if must_save {
MUST_SAVE[id as usize] = true;
}
}
Some(id)
}
@ -123,6 +159,9 @@ where
meta.current_id = (id + 1) & (EDGES_MAP_SIZE as u64 - 1);
unsafe {
MAX_EDGES_NUM = meta.current_id as usize;
if must_save {
MUST_SAVE[id as usize] = true;
}
}
Some(id as u64)
}
@ -148,6 +187,14 @@ where
Some(hash_me(src) ^ hash_me(dest))
}
pub extern "C" fn trace_edge_hitcount_and_app_range(id: u64) {
unsafe {
if MUST_SAVE[id as usize] { SAVED_JUMP=Some(id); }
EDGES_MAP[id as usize] = EDGES_MAP[id as usize].wrapping_add(1);
}
}
pub extern "C" fn trace_edge_hitcount(id: u64) {
unsafe {
EDGES_MAP[id as usize] = EDGES_MAP[id as usize].wrapping_add(1);