switch address data type, simplify synbol resolution

This commit is contained in:
Alwin Berger 2023-12-08 11:15:25 +01:00
parent aba83dfb6f
commit 6e0b49bf9b
2 changed files with 51 additions and 60 deletions

View File

@ -64,11 +64,24 @@ fn virt2phys(vaddr: GuestPhysAddr, tab: &EasyElf) -> GuestPhysAddr {
return vaddr;
}
pub fn load_symbol(elf : &EasyElf, symbol : &str, do_translation : bool) -> GuestAddr {
try_load_symbol(elf, symbol, do_translation).expect(&format!("Symbol {} not found", symbol))
}
pub fn try_load_symbol(elf : &EasyElf, symbol : &str, do_translation : bool) -> Option<GuestAddr> {
let ret = elf
.resolve_symbol(symbol, 0);
if do_translation {
Option::map_or(ret, None, |x| Some(virt2phys(x as GuestPhysAddr,&elf) as GuestAddr))
} else {ret}
}
extern "C" {
static mut libafl_interrupt_offsets : [u32; 32];
static mut libafl_num_interrupts : usize;
}
pub fn fuzz() {
unsafe {FUZZ_START_TIMESTAMP = SystemTime::now();}
let mut starttime = std::time::Instant::now();
@ -98,23 +111,11 @@ pub fn fuzz() {
println!("main address = {:#x}", main_addr);
}
let input_addr = elf
.resolve_symbol(
&env::var("FUZZ_INPUT").unwrap_or_else(|_| "FUZZ_INPUT".to_owned()),
0,
)
.expect("Symbol or env FUZZ_INPUT not found") as GuestPhysAddr;
let input_addr = virt2phys(input_addr,&elf) as GuestPhysAddr;
let input_addr = load_symbol(&elf, &env::var("FUZZ_INPUT").unwrap_or_else(|_| "FUZZ_INPUT".to_owned()), true);
println!("FUZZ_INPUT @ {:#x}", input_addr);
let test_length_ptr = elf
.resolve_symbol("FUZZ_LENGTH", 0).map(|x| x as GuestPhysAddr);
let test_length_ptr = Option::map_or(test_length_ptr, None, |x| Some(virt2phys(x,&elf)));
let input_counter_ptr = elf
.resolve_symbol(&env::var("FUZZ_POINTER").unwrap_or_else(|_| "FUZZ_POINTER".to_owned()), 0)
.map(|x| x as GuestPhysAddr);
let input_counter_ptr = Option::map_or(input_counter_ptr, None, |x| Some(virt2phys(x,&elf)));
let input_length_ptr = try_load_symbol(&elf, &env::var("FUZZ_LENGTH").unwrap_or_else(|_| "FUZZ_LENGTH".to_owned()), true);
let input_counter_ptr = try_load_symbol(&elf, &env::var("FUZZ_POINTER").unwrap_or_else(|_| "FUZZ_POINTER".to_owned()), true);
#[cfg(feature = "systemstate")]
let curr_tcb_pointer = elf // loads to the address specified in elf, without respecting program headers
@ -124,34 +125,22 @@ pub fn fuzz() {
#[cfg(feature = "systemstate")]
println!("TCB pointer at {:#x}", curr_tcb_pointer);
#[cfg(feature = "systemstate")]
let task_queue_addr = elf
.resolve_symbol("pxReadyTasksLists", 0)
.expect("Symbol pxReadyTasksLists not found");
let task_delay_addr = elf
.resolve_symbol("pxDelayedTaskList", 0)
.expect("Symbol pxDelayedTaskList not found");
let task_delay_overflow_addr = elf
.resolve_symbol("pxOverflowDelayedTaskList", 0)
.expect("Symbol pxOverflowDelayedTaskList not found");
let task_queue_addr = load_symbol(&elf, "pxReadyTasksLists", false);
let task_delay_addr = load_symbol(&elf, "pxDelayedTaskList", false);
let task_delay_overflow_addr = load_symbol(&elf, "pxOverflowDelayedTaskList", false);
// let task_queue_addr = virt2phys(task_queue_addr,&elf.goblin());
#[cfg(feature = "systemstate")]
println!("Task Queue at {:#x}", task_queue_addr);
#[cfg(feature = "systemstate")]
let svh = elf
.resolve_symbol("xPortPendSVHandler", 0)
.expect("Symbol xPortPendSVHandler not found");
let svh = load_symbol(&elf, "xPortPendSVHandler", false);
// let svh=virt2phys(svh, &elf);
// let svh = elf
// .resolve_symbol("vPortEnterCritical", 0)
// .expect("Symbol vPortEnterCritical not found");
#[cfg(feature = "systemstate")]
let app_start = elf
.resolve_symbol("__APP_CODE_START__", 0)
.expect("Symbol __APP_CODE_START__ not found");
let app_start = load_symbol(&elf, "__APP_CODE_START__", false);
#[cfg(feature = "systemstate")]
let app_end = elf
.resolve_symbol("__APP_CODE_END__", 0)
.expect("Symbol __APP_CODE_END__ not found");
let app_end = load_symbol(&elf, "__APP_CODE_END__", false);
#[cfg(feature = "systemstate")]
let app_range = app_start..app_end;
#[cfg(feature = "systemstate")]
@ -228,9 +217,10 @@ pub fn fuzz() {
len = MAX_INPUT_SIZE;
}
emu.write_phys_mem(input_addr, buf);
if let Some(s) = test_length_ptr {
emu.write_phys_mem(s as u64, &len.to_le_bytes())
// Note: I could not find a difference between write_mem and write_phys_mem for my usecase
emu.write_mem(input_addr, buf);
if let Some(s) = input_length_ptr {
emu.write_mem(s, &len.to_le_bytes())
}
emu.run();
@ -657,7 +647,7 @@ pub fn fuzz() {
emu.run();
let mut buf = [0u8].repeat(MAX_INPUT_SIZE);
emu.read_phys_mem(input_addr, buf.as_mut_slice());
emu.read_mem(input_addr, buf.as_mut_slice());
let dir = env::var("SEED_DIR").map_or("./corpus".to_string(), |x| x);
let filename = if input_dump == "" {"input"} else {&input_dump};

View File

@ -5,6 +5,7 @@ use libafl::prelude::ExitKind;
use libafl::prelude::UsesInput;
use libafl_qemu::Emulator;
use libafl_qemu::GuestAddr;
use libafl_qemu::GuestPhysAddr;
use libafl_qemu::QemuHooks;
use libafl_qemu::edges::QemuEdgesMapMetadata;
use libafl_qemu::emu;
@ -35,25 +36,25 @@ pub static mut NEXT_INPUT : Vec<u8> = Vec::new();
/// A Qemu Helper with reads FreeRTOS specific structs from Qemu whenever certain syscalls occur, also inject inputs
#[derive(Debug)]
pub struct QemuSystemStateHelper {
kerneladdr: u32,
tcb_addr: u32,
ready_queues: u32,
delay_queue: u32,
delay_queue_overflow: u32,
input_counter: Option<u64>,
app_range: Range<u32>,
kerneladdr: GuestAddr,
tcb_addr: GuestAddr,
ready_queues: GuestAddr,
delay_queue: GuestAddr,
delay_queue_overflow: GuestAddr,
input_counter: Option<GuestAddr>,
app_range: Range<GuestAddr>,
}
impl QemuSystemStateHelper {
#[must_use]
pub fn new(
kerneladdr: u32,
tcb_addr: u32,
ready_queues: u32,
delay_queue: u32,
delay_queue_overflow: u32,
input_counter: Option<u64>,
app_range: Range<u32>,
kerneladdr: GuestAddr,
tcb_addr: GuestAddr,
ready_queues: GuestAddr,
delay_queue: GuestAddr,
delay_queue_overflow: GuestAddr,
input_counter: Option<GuestAddr>,
app_range: Range<GuestAddr>,
) -> Self {
QemuSystemStateHelper {
kerneladdr,
@ -94,9 +95,9 @@ where
}
}
fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emulator, target: u32) -> freertos::List_t {
fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emulator, target: GuestAddr) -> freertos::List_t {
let read : freertos::List_t = freertos::emu_lookup::lookup(emulator, target);
let listbytes : u32 = u32::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
let mut next_index = read.pxIndex;
for _j in 0..read.uxNumberOfItems {
@ -127,7 +128,7 @@ fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emul
#[inline]
fn trigger_collection(emulator: &Emulator, h: &QemuSystemStateHelper) {
let listbytes : u32 = u32::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
let mut systemstate = RawFreeRTOSSystemState::default();
unsafe {
// TODO: investigate why can_do_io is not set sometimes, as this is just a workaround
@ -139,10 +140,10 @@ fn trigger_collection(emulator: &Emulator, h: &QemuSystemStateHelper) {
}
let mut buf : [u8; 4] = [0,0,0,0];
match h.input_counter {
Some(s) => unsafe { emulator.read_phys_mem(s, &mut buf); },
Some(s) => unsafe { emulator.read_mem(s, &mut buf); },
None => (),
};
systemstate.input_counter = u32::from_le_bytes(buf);
systemstate.input_counter = GuestAddr::from_le_bytes(buf);
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr);
if curr_tcb_addr == 0 {
@ -163,18 +164,18 @@ fn trigger_collection(emulator: &Emulator, h: &QemuSystemStateHelper) {
// println!("{:?}",std::str::from_utf8(&current_tcb.pcTaskName));
// Extract delay list
let mut target : u32 = h.delay_queue;
let mut target : GuestAddr = h.delay_queue;
target = freertos::emu_lookup::lookup(emulator, target);
systemstate.delay_list = read_freertos_list(&mut systemstate, emulator, target);
// Extract delay list overflow
let mut target : u32 = h.delay_queue_overflow;
let mut target : GuestAddr = h.delay_queue_overflow;
target = freertos::emu_lookup::lookup(emulator, target);
systemstate.delay_list_overflow = read_freertos_list(&mut systemstate, emulator, target);
// Extract priority lists
for i in 0..NUM_PRIOS {
let target : u32 = listbytes*u32::try_from(i).unwrap()+h.ready_queues;
let target : GuestAddr = listbytes*GuestAddr::try_from(i).unwrap()+h.ready_queues;
systemstate.prio_ready_lists[i] = read_freertos_list(&mut systemstate, emulator, target);
}
@ -184,7 +185,7 @@ fn trigger_collection(emulator: &Emulator, h: &QemuSystemStateHelper) {
pub fn exec_syscall_hook<QT, S>(
hooks: &mut QemuHooks<'_, QT, S>,
_state: Option<&mut S>,
_pc: u32,
_pc: GuestAddr,
)
where
S: UsesInput,