proof of concept syscall-hook tcb tracer

This commit is contained in:
Alwin Berger 2022-01-23 22:23:14 +01:00
parent 29f89b4b29
commit 44a32398d9
5 changed files with 148 additions and 25 deletions

5
fuzzers/wcet_qemu_sys/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.axf
*.qcow2
demo
*.ron
*.bsp

View File

@ -1,3 +1,4 @@
use serde::{Deserialize, Serialize};
// Manual Types
use libafl_qemu::Emulator;
@ -20,7 +21,7 @@ pub type StackType_t = u32;
pub type UBaseType_t = ::std::os::raw::c_uint;
pub type TickType_t = u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct xLIST_ITEM {
pub xItemValue: TickType_t,
pub pxNext: xLIST_ITEM_ptr,
@ -93,7 +94,7 @@ fn bindgen_test_layout_xLIST_ITEM() {
}
pub type ListItem_t = xLIST_ITEM;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct xMINI_LIST_ITEM {
pub xItemValue: TickType_t,
pub pxNext: xLIST_ITEM_ptr,
@ -144,7 +145,7 @@ fn bindgen_test_layout_xMINI_LIST_ITEM() {
}
pub type MiniListItem_t = xMINI_LIST_ITEM;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Default)]
pub struct xLIST {
pub uxNumberOfItems: UBaseType_t,
pub pxIndex: ListItem_t_ptr,
@ -194,7 +195,7 @@ fn bindgen_test_layout_xLIST() {
);
}
pub type List_t = xLIST;
pub type TaskHandle_t = *mut tskTaskControlBlock;
pub type TaskHandle_t = ::std::os::raw::c_uint;
pub const eTaskState_eRunning: eTaskState = 0;
pub const eTaskState_eReady: eTaskState = 1;
pub const eTaskState_eBlocked: eTaskState = 2;
@ -203,7 +204,7 @@ pub const eTaskState_eDeleted: eTaskState = 4;
pub const eTaskState_eInvalid: eTaskState = 5;
pub type eTaskState = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct xTASK_STATUS {
pub xHandle: TaskHandle_t,
pub pcTaskName: char_ptr,
@ -322,14 +323,14 @@ fn bindgen_test_layout_xTASK_STATUS() {
}
pub type TaskStatus_t = xTASK_STATUS;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct tskTaskControlBlock {
pub pxTopOfStack: StackType_t_ptr,
pub xStateListItem: ListItem_t,
pub xEventListItem: ListItem_t,
pub uxPriority: UBaseType_t,
pub pxStack: StackType_t_ptr,
pub pcTaskName: [::std::os::raw::c_char; 10usize],
pub pcTaskName: [::std::os::raw::c_uchar; 10usize],
pub uxBasePriority: UBaseType_t,
pub uxMutexesHeld: UBaseType_t,
pub ulNotifiedValue: [u32; 1usize],

View File

@ -3,6 +3,7 @@ pub mod fuzzer;
pub mod showmap;
pub mod worst;
pub mod freertos;
pub mod system_trace;
use libafl_qemu::{
edges,
edges::QemuEdgeCoverageHelper,

View File

@ -1,5 +1,6 @@
//! A singlethreaded QEMU fuzzer that can auto-restart.
use crate::system_trace::QemuSystemStateHelper;
use libafl::feedbacks::CrashFeedback;
use std::path::Path;
use libafl_qemu::QemuExecutor;
@ -208,6 +209,21 @@ fn fuzz(
.expect("Symbol pxReadyTasksLists not found");
// let task_queue_addr = virt2phys(task_queue_addr,&elf.goblin());
println!("Task Queue at {:#x}", task_queue_addr);
let shv = elf
.resolve_symbol("xPortSysTickHandler", 0)
.expect("Symbol xPortSysTickHandler not found");
let shv = virt2phys(shv,&elf.goblin());
println!("SysTick at {:#x}", shv);
let shv = elf
.resolve_symbol("vPortSVCHandler", 0)
.expect("Symbol vPortSVCHandler not found");
let shv = virt2phys(shv,&elf.goblin());
println!("SVChandle at {:#x}", shv);
let shv = elf
.resolve_symbol("xPortPendSVHandler", 0)
.expect("Symbol xPortPendSVHandler not found");
let shv = virt2phys(shv,&elf.goblin());
println!("PendHandle at {:#x}", shv);
@ -274,12 +290,12 @@ fn fuzz(
emu.run();
//====== experiment inspecting the current tcb
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(&emu, curr_tcb_pointer.try_into().unwrap());
println!("Current TCB addr: {:x}",curr_tcb_addr);
let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(&emu,curr_tcb_addr);
println!("Current TCB: {:?}",current_tcb);
let ready_queue : freertos::List_t = freertos::emu_lookup::lookup(&emu,task_queue_addr.try_into().unwrap());
println!("Ready Queue: {:?}",ready_queue);
// let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(&emu, curr_tcb_pointer.try_into().unwrap());
// println!("Current TCB addr: {:x}",curr_tcb_addr);
// let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(&emu,curr_tcb_addr);
// println!("Current TCB: {:?}",current_tcb);
// let ready_queue : freertos::List_t = freertos::emu_lookup::lookup(&emu,task_queue_addr.try_into().unwrap());
// println!("Ready Queue: {:?}",ready_queue);
}
ExitKind::Ok
@ -293,7 +309,8 @@ fn fuzz(
QemuEdgeCoverageHelper::new(),
// QemuCmpLogHelper::new(),
// QemuAsanHelper::new(),
QemuSysSnapshotHelper::new()
QemuSysSnapshotHelper::new(),
QemuSystemStateHelper::new()
),
tuple_list!(edges_observer),
&mut fuzzer,
@ -305,17 +322,6 @@ fn fuzz(
false => seed_dir.clone()
};
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&firstinput).expect("Could not load file")).expect("Evaluation failed");
// fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&firstinput).expect("Could not load file")).expect("Evaluation failed");
// let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
// let mut stages = tuple_list!(StdMutationalStage::new(mutator));
// if state.corpus().count() < 1 {
// state
// .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
// .expect("Failed to load initial corpus");
// println!("We imported {} inputs from disk.", state.corpus().count());
// }
// fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)
// .expect("Error in the fuzzing loop");
return Ok(());
}

View File

@ -0,0 +1,110 @@
use crate::freertos;
use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
use serde::{Deserialize, Serialize};
use libafl_qemu::{
emu::Emulator,
executor::QemuExecutor,
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
};
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct QemuSystemStateMetadata {
pub tcbs: Vec<freertos::TCB_t>,
// pub map: HashMap<u64, u64>,
// pub current_id: u64,
}
impl QemuSystemStateMetadata {
#[must_use]
pub fn new() -> Self {
Self {
tcbs: Vec::new(),
// map: HashMap::new(),
// current_id: 0,
}
}
}
libafl::impl_serdeany!(QemuSystemStateMetadata);
#[derive(Debug)]
pub struct QemuSystemStateHelper {
filter: QemuInstrumentationFilter,
}
impl QemuSystemStateHelper {
#[must_use]
pub fn new() -> Self {
Self {
filter: QemuInstrumentationFilter::None,
}
}
#[must_use]
pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter) -> Self {
Self { filter }
}
#[must_use]
pub fn must_instrument(&self, addr: u64) -> bool {
self.filter.allowed(addr)
}
}
impl Default for QemuSystemStateHelper {
fn default() -> Self {
Self::new()
}
}
impl<I, S> QemuHelper<I, S> for QemuSystemStateHelper
where
I: Input,
S: HasMetadata,
{
fn init<'a, H, OT, QT>(&self, executor: &QemuExecutor<'a, H, I, OT, QT, S>)
where
H: FnMut(&I) -> ExitKind,
OT: ObserversTuple<I, S>,
QT: QemuHelperTuple<I, S>,
{
executor.hook_block_execution(exec_syscall_hook::<I, QT, S>);
}
}
pub fn exec_syscall_hook<I, QT, S>(
emulator: &Emulator,
helpers: &mut QT,
state: &mut S,
pc: u64,
)
where
S: HasMetadata,
I: Input,
QT: QemuHelperTuple<I, S>,
{
// if pc == 0x2e8 { //vPortSVCHandler
// if pc == 0x3c4 { //SystemTick
if pc == 0x37c { //xPortPendSVHandler
if let Some(h) = helpers.match_first_type::<QemuSystemStateHelper>() {
if !h.must_instrument(pc) {
return;
}
}
if state.metadata().get::<QemuSystemStateMetadata>().is_none() {
state.add_metadata(QemuSystemStateMetadata::new());
}
let meta = state
.metadata_mut()
.get_mut::<QemuSystemStateMetadata>()
.unwrap();
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, 0x20006ff0.try_into().unwrap());
// println!("Current TCB addr: {:x}",curr_tcb_addr);
let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(emulator,curr_tcb_addr);
println!("{}", std::str::from_utf8(&current_tcb.pcTaskName).unwrap());
meta.tcbs.push(current_tcb);
let id = meta.tcbs.len();
}
}