From f26582ed75dea4b9f55ca4d27b4721bd30fc119a Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Wed, 3 Apr 2024 10:19:37 +0200 Subject: [PATCH] un-hardcode rtos api functions --- fuzzers/FRET/src/fuzzer.rs | 92 +++++++++++++++++++------ fuzzers/FRET/src/systemstate/helpers.rs | 36 +++++----- fuzzers/FRET/src/systemstate/mod.rs | 2 +- 3 files changed, 92 insertions(+), 38 deletions(-) diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index ab4b989a96..d665a3afa0 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -78,7 +78,7 @@ pub fn try_load_symbol(elf : &EasyElf, symbol : &str, do_translation : bool) -> } else {ret} } -pub fn get_function_range(elf: &EasyElf, symbol: &'static str) -> Option> { +pub fn get_function_range(elf: &EasyElf, symbol: &str) -> Option> { let gob = elf.goblin(); let mut funcs : Vec<_> = gob.syms.iter().filter(|x| x.is_function()).collect(); @@ -98,7 +98,7 @@ pub fn get_function_range(elf: &EasyElf, symbol: &'static str) -> Option sym.st_value); if let Some(sym_end) = sym_end { - println!("{} {:#x}..{} {:#x}", gob.strtab.get_at(sym.st_name).unwrap_or(""),addr, gob.strtab.get_at(sym_end.st_name).unwrap_or(""),sym_end.st_value & !0x1); + // println!("{} {:#x}..{} {:#x}", gob.strtab.get_at(sym.st_name).unwrap_or(""),addr, gob.strtab.get_at(sym_end.st_name).unwrap_or(""),sym_end.st_value & !0x1); return Some(addr..((sym_end.st_value & !0x1) as GuestAddr)); } return None; @@ -109,6 +109,29 @@ pub fn get_function_range(elf: &EasyElf, symbol: &'static str) -> Option) -> HashMap> { + let mut api_addreses : HashMap> = HashMap::new(); + + let gob = elf.goblin(); + + let mut funcs : Vec<_> = gob.syms.iter().filter(|x| x.is_function() && api_range.contains(&x.st_value.try_into().unwrap())).collect(); + funcs.sort_unstable_by(|x,y| x.st_value.cmp(&y.st_value)); + + for sym in &funcs { + let sym_name = gob.strtab.get_at(sym.st_name); + if let Some(sym_name) = sym_name { + if let Some(r) = get_function_range(elf, sym_name) { + api_addreses.insert(sym_name.to_string(), r); + } + } + } + for i in api_addreses.iter() { + println!("{} {:#x}..{:#x}", i.0, i.1.start, i.1.end); + } + + return api_addreses; +} + extern "C" { static mut libafl_interrupt_offsets : [u32; 32]; static mut libafl_num_interrupts : usize; @@ -199,7 +222,7 @@ macro_rules! do_dump_case { macro_rules! do_dump_times { ($state:expr, $cli:expr, $c:expr) => { if $cli.dump_times { - let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"times"} else {$c}); + let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"time"} else {$c}); let mut file = std::fs::OpenOptions::new() .read(true) .write(true) @@ -353,6 +376,12 @@ pub fn fuzz() { #[cfg(feature = "systemstate")] let app_range = app_start..app_end; #[cfg(feature = "systemstate")] + let api_start = load_symbol(&elf, "__API_CODE_START__", false); + #[cfg(feature = "systemstate")] + let api_end = load_symbol(&elf, "__API_CODE_END__", false); + #[cfg(feature = "systemstate")] + let api_range = api_start..api_end; + #[cfg(feature = "systemstate")] dbg!(app_range.clone()); let breakpoint = elf @@ -375,27 +404,48 @@ pub fn fuzz() { unsafe {RNG_SEED = str::parse::(&seed).expect("SEED_RANDOM must be an integer.");} } - #[cfg(feature = "systemstate")] - let mut api_addreses : HashMap = HashMap::new(); - #[cfg(feature = "systemstate")] - for s in systemstate::helpers::API_SYMBOLS { - if let Some(sb) = try_load_symbol(&elf, &s, false) { - api_addreses.insert(sb,s); - } - } - #[cfg(feature = "systemstate")] - let mut isr_addreses : HashMap = HashMap::new(); - #[cfg(feature = "systemstate")] - for s in systemstate::helpers::ISR_SYMBOLS { - if let Some(sb) = try_load_symbol(&elf, &s, false) { - isr_addreses.insert(sb & !1,s); + let mut api_ranges = get_all_fn_symbol_ranges(&elf, api_range); + + let mut isr_ranges : HashMap> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect(); + let mut isr_addreses : HashMap = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect(); + + for i in systemstate::helpers::ISR_SYMBOLS { + if isr_ranges.get(&i.to_string()).is_none() { + if let Some(fr) = get_function_range(&elf, i) { + isr_addreses.insert(fr.start, i.to_string()); + isr_ranges.insert(i.to_string(), fr); + } } } - #[cfg(feature = "systemstate")] - let mut api_ranges : Vec<(&'static str,std::ops::Range)> = systemstate::helpers::API_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect(); - #[cfg(feature = "systemstate")] - let mut isr_ranges : Vec<(&'static str,std::ops::Range)> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect(); + let api_addreses : HashMap = api_ranges.iter().map(|(k,v)| (v.start,k.clone())).collect(); + + let api_ranges : Vec<_> = api_ranges.into_iter().collect(); + let isr_ranges : Vec<_> = isr_ranges.into_iter().collect(); + + // println!("all: {}, api: {}, isr: {}", api_ranges.len(), systemstate::helpers::API_SYMBOLS.len(), systemstate::helpers::ISR_SYMBOLS.len()); + + // #[cfg(feature = "systemstate")] + // let mut api_addreses : HashMap = HashMap::new(); + // #[cfg(feature = "systemstate")] + // for s in systemstate::helpers::API_SYMBOLS { + // if let Some(sb) = try_load_symbol(&elf, &s, false) { + // api_addreses.insert(sb,s); + // } + // } + // #[cfg(feature = "systemstate")] + // let mut isr_addreses : HashMap = HashMap::new(); + // #[cfg(feature = "systemstate")] + // for s in systemstate::helpers::ISR_SYMBOLS { + // if let Some(sb) = try_load_symbol(&elf, &s, false) { + // isr_addreses.insert(sb & !1,s); + // } + // } + + // #[cfg(feature = "systemstate")] + // let mut api_ranges : Vec<(&'static str,std::ops::Range)> = systemstate::helpers::API_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect(); + // #[cfg(feature = "systemstate")] + // let mut isr_ranges : Vec<(&'static str,std::ops::Range)> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect(); // Client setup ================================================================================ diff --git a/fuzzers/FRET/src/systemstate/helpers.rs b/fuzzers/FRET/src/systemstate/helpers.rs index bf65068056..123643a075 100644 --- a/fuzzers/FRET/src/systemstate/helpers.rs +++ b/fuzzers/FRET/src/systemstate/helpers.rs @@ -84,11 +84,11 @@ pub const ISR_SYMBOLS : &'static [&'static str] = &[ #[derive(Debug)] pub struct QemuSystemStateHelper { // Address of API functions - api_fn_addrs: HashMap, - api_fn_ranges: Vec<(&'static str, std::ops::Range)>, + api_fn_addrs: HashMap, + api_fn_ranges: Vec<(String, std::ops::Range)>, // Address of interrupt routines - isr_addrs: HashMap, - isr_ranges: Vec<(&'static str, std::ops::Range)>, + isr_addrs: HashMap, + isr_ranges: Vec<(String, std::ops::Range)>, tcb_addr: GuestAddr, ready_queues: GuestAddr, delay_queue: GuestAddr, @@ -102,10 +102,10 @@ pub struct QemuSystemStateHelper { impl QemuSystemStateHelper { #[must_use] pub fn new( - api_fn_addrs: HashMap, - api_fn_ranges: Vec<(&'static str, std::ops::Range)>, - isr_addrs: HashMap, - isr_ranges: Vec<(&'static str, std::ops::Range)>, + api_fn_addrs: HashMap, + api_fn_ranges: Vec<(String, std::ops::Range)>, + isr_addrs: HashMap, + isr_ranges: Vec<(String, std::ops::Range)>, tcb_addr: GuestAddr, ready_queues: GuestAddr, delay_queue: GuestAddr, @@ -165,7 +165,7 @@ where 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"); + CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].capture_point = (CaptureEvent::End,"Breakpoint".to_string()); } // Find the first ISREnd of vPortSVCHandler and drop anything before unsafe { @@ -227,25 +227,28 @@ fn trigger_collection(emulator: &Emulator, edge: (Option,Option { if let Some(src) = edge.0 { // Both set, can be API Call/Ret if let Some(s) = h.api_fn_addrs.get(&src) { // API End - systemstate.capture_point=(CaptureEvent::APIEnd, s); + systemstate.capture_point=(CaptureEvent::APIEnd, s.to_string()); + if !h.app_range.contains(&dest) { + println!("API Not found: {:#x} {:#x}", src, dest); + } } else if let Some(s) = h.api_fn_addrs.get(&dest) { // API Call - systemstate.capture_point=(CaptureEvent::APIStart, s); + systemstate.capture_point=(CaptureEvent::APIStart, s.to_string()); } else { println!("API Not found: {:#x}", src); } } else { // No source, must be ISR if let Some(s) = h.isr_addrs.get(&dest) { // ISR Start - systemstate.capture_point=(CaptureEvent::ISRStart, s); + systemstate.capture_point=(CaptureEvent::ISRStart, s.to_string()); } else { println!("ISR call Not found: {:#x}", dest); } @@ -405,7 +408,8 @@ where } } else if id == 2 { // API return let h = hooks.helpers().match_first_type::().expect("QemuSystemHelper not found in helper tupel"); - if in_any_range(&h.api_fn_ranges, dest).is_none() { + // Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space. + if in_any_range(&h.api_fn_ranges, dest).is_none() && in_any_range(&h.isr_ranges, dest).is_none() { let emulator = hooks.emulator(); let mut edge = (None, None); @@ -427,7 +431,7 @@ where } } -pub fn in_any_range<'a>(ranges: &'a Vec<(&str, Range)>, addr : GuestAddr) -> Option<&'a std::ops::Range> { +pub fn in_any_range<'a>(ranges: &'a Vec<(String, Range)>, addr : GuestAddr) -> Option<&'a std::ops::Range> { for (_,r) in ranges { if r.contains(&addr) {return Some(r);} } diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index ec7020a78b..509a3258f2 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -53,7 +53,7 @@ pub struct RawFreeRTOSSystemState { dumping_ground: HashMap, input_counter: u32, edge: (Option,Option), - capture_point: (CaptureEvent,&'static str) + capture_point: (CaptureEvent,String) } /// List of system state dumps from QemuHelpers static mut CURRENT_SYSTEMSTATE_VEC: Vec = vec![];