un-hardcode rtos api functions

This commit is contained in:
Alwin Berger 2024-04-03 10:19:37 +02:00
parent c013628017
commit f26582ed75
3 changed files with 92 additions and 38 deletions

View File

@ -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<std::ops::Range<GuestAddr>> {
pub fn get_function_range(elf: &EasyElf, symbol: &str) -> Option<std::ops::Range<GuestAddr>> {
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<std::op
// look for first function after addr
let sym_end = funcs.iter().find(|x| x.st_value > 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<std::op
return None;
}
pub fn get_all_fn_symbol_ranges(elf: &EasyElf, api_range: std::ops::Range<GuestAddr>) -> HashMap<String,std::ops::Range<GuestAddr>> {
let mut api_addreses : HashMap<String,std::ops::Range<GuestAddr>> = 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::<u64>(&seed).expect("SEED_RANDOM must be an integer.");}
}
#[cfg(feature = "systemstate")]
let mut api_addreses : HashMap<GuestAddr,&'static str> = 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);
let mut api_ranges = get_all_fn_symbol_ranges(&elf, api_range);
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();
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();
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 isr_addreses : HashMap<GuestAddr,&'static str> = 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<GuestAddr>)> = 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<GuestAddr>)> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect();
let api_addreses : HashMap<GuestAddr, String> = 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<GuestAddr,&'static str> = 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<GuestAddr,&'static str> = 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<GuestAddr>)> = 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<GuestAddr>)> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect();
// Client setup ================================================================================

View File

@ -84,11 +84,11 @@ pub const ISR_SYMBOLS : &'static [&'static str] = &[
#[derive(Debug)]
pub struct QemuSystemStateHelper {
// Address of API functions
api_fn_addrs: HashMap<GuestAddr, &'static str>,
api_fn_ranges: Vec<(&'static str, std::ops::Range<GuestAddr>)>,
api_fn_addrs: HashMap<GuestAddr, String>,
api_fn_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
// Address of interrupt routines
isr_addrs: HashMap<GuestAddr, &'static str>,
isr_ranges: Vec<(&'static str, std::ops::Range<GuestAddr>)>,
isr_addrs: HashMap<GuestAddr, String>,
isr_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
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<GuestAddr, &'static str>,
api_fn_ranges: Vec<(&'static str, std::ops::Range<GuestAddr>)>,
isr_addrs: HashMap<GuestAddr, &'static str>,
isr_ranges: Vec<(&'static str, std::ops::Range<GuestAddr>)>,
api_fn_addrs: HashMap<GuestAddr, String>,
api_fn_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
isr_addrs: HashMap<GuestAddr, String>,
isr_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
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::<i32, u32>(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<GuestAddr>,Option<Guest
// ISR End
if let Some(src) = edge.0 {
if let Some(s) = h.isr_addrs.get(&src) {
systemstate.capture_point=(CaptureEvent::ISREnd, s);
systemstate.capture_point=(CaptureEvent::ISREnd, s.to_string());
} else {
println!("ISR Ret Not found: {:#x}", src);
systemstate.capture_point=(CaptureEvent::ISREnd, "");
systemstate.capture_point=(CaptureEvent::ISREnd, "".to_string());
}
}
},
Some(dest) => {
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::<QemuSystemStateHelper>().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<u32>)>, addr : GuestAddr) -> Option<&'a std::ops::Range<GuestAddr>> {
pub fn in_any_range<'a>(ranges: &'a Vec<(String, Range<u32>)>, addr : GuestAddr) -> Option<&'a std::ops::Range<GuestAddr>> {
for (_,r) in ranges {
if r.contains(&addr) {return Some(r);}
}

View File

@ -53,7 +53,7 @@ pub struct RawFreeRTOSSystemState {
dumping_ground: HashMap<u32,freertos::rtos_struct>,
input_counter: u32,
edge: (Option<GuestAddr>,Option<GuestAddr>),
capture_point: (CaptureEvent,&'static str)
capture_point: (CaptureEvent,String)
}
/// List of system state dumps from QemuHelpers
static mut CURRENT_SYSTEMSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![];