Qemu native hooks refactoring (#2480)
* qemu native hooks refactoring (companion patch of qemu-libafl-bridge#82) * update stubs
This commit is contained in:
parent
2287afc59b
commit
00806b177d
@ -82,10 +82,24 @@ const WRAPPER_HEADER: &str = r#"
|
||||
#include "qemu/plugin-memory.h"
|
||||
|
||||
#include "libafl/exit.h"
|
||||
#include "libafl/hook.h"
|
||||
#include "libafl/jit.h"
|
||||
#include "libafl/utils.h"
|
||||
|
||||
#include "libafl/hook.h"
|
||||
|
||||
#include "libafl/hooks/tcg/backdoor.h"
|
||||
#include "libafl/hooks/tcg/block.h"
|
||||
#include "libafl/hooks/tcg/cmp.h"
|
||||
#include "libafl/hooks/tcg/edge.h"
|
||||
#include "libafl/hooks/tcg/instruction.h"
|
||||
#include "libafl/hooks/tcg/read_write.h"
|
||||
#include "libafl/hooks/cpu_run.h"
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#include "libafl/hooks/thread.h"
|
||||
#include "libafl/hooks/syscall.h"
|
||||
#endif
|
||||
|
||||
"#;
|
||||
|
||||
pub fn generate(
|
||||
|
@ -11,7 +11,7 @@ use crate::cargo_add_rpath;
|
||||
|
||||
pub const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
|
||||
pub const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
|
||||
pub const QEMU_REVISION: &str = "24abc2a717226bedc047167f639aef0edc9ce92d";
|
||||
pub const QEMU_REVISION: &str = "86d38fbfa7e632b3a4a14def14a11b9b9ba1642d";
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct BuildResult {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,11 @@
|
||||
/* 1.81.0-nightly */
|
||||
/* qemu git hash: 712661c8200804c0bb0750f237048c6c3da2d863 */
|
||||
/* 1.82.0-nightly */
|
||||
/* qemu git hash: 8f61fadbec181bfcbd305ba92a86a41376a476f7 */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
pub const _STDINT_H: u32 = 1;
|
||||
pub const _FEATURES_H: u32 = 1;
|
||||
pub const _DEFAULT_SOURCE: u32 = 1;
|
||||
pub const __GLIBC_USE_ISOC2X: u32 = 0;
|
||||
pub const __GLIBC_USE_ISOC23: u32 = 0;
|
||||
pub const __USE_ISOC11: u32 = 1;
|
||||
pub const __USE_ISOC99: u32 = 1;
|
||||
pub const __USE_ISOC95: u32 = 1;
|
||||
@ -23,12 +23,13 @@ pub const __WORDSIZE: u32 = 64;
|
||||
pub const __WORDSIZE_TIME64_COMPAT32: u32 = 1;
|
||||
pub const __SYSCALL_WORDSIZE: u32 = 64;
|
||||
pub const __TIMESIZE: u32 = 64;
|
||||
pub const __USE_TIME_BITS64: u32 = 1;
|
||||
pub const __USE_MISC: u32 = 1;
|
||||
pub const __USE_ATFILE: u32 = 1;
|
||||
pub const __USE_FORTIFY_LEVEL: u32 = 0;
|
||||
pub const __GLIBC_USE_DEPRECATED_GETS: u32 = 0;
|
||||
pub const __GLIBC_USE_DEPRECATED_SCANF: u32 = 0;
|
||||
pub const __GLIBC_USE_C2X_STRTOL: u32 = 0;
|
||||
pub const __GLIBC_USE_C23_STRTOL: u32 = 0;
|
||||
pub const _STDC_PREDEF_H: u32 = 1;
|
||||
pub const __STDC_IEC_559__: u32 = 1;
|
||||
pub const __STDC_IEC_60559_BFP__: u32 = 201404;
|
||||
@ -37,17 +38,17 @@ pub const __STDC_IEC_60559_COMPLEX__: u32 = 201404;
|
||||
pub const __STDC_ISO_10646__: u32 = 201706;
|
||||
pub const __GNU_LIBRARY__: u32 = 6;
|
||||
pub const __GLIBC__: u32 = 2;
|
||||
pub const __GLIBC_MINOR__: u32 = 39;
|
||||
pub const __GLIBC_MINOR__: u32 = 40;
|
||||
pub const _SYS_CDEFS_H: u32 = 1;
|
||||
pub const __glibc_c99_flexarr_available: u32 = 1;
|
||||
pub const __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI: u32 = 0;
|
||||
pub const __HAVE_GENERIC_SELECTION: u32 = 1;
|
||||
pub const __GLIBC_USE_LIB_EXT2: u32 = 0;
|
||||
pub const __GLIBC_USE_IEC_60559_BFP_EXT: u32 = 0;
|
||||
pub const __GLIBC_USE_IEC_60559_BFP_EXT_C2X: u32 = 0;
|
||||
pub const __GLIBC_USE_IEC_60559_BFP_EXT_C23: u32 = 0;
|
||||
pub const __GLIBC_USE_IEC_60559_EXT: u32 = 0;
|
||||
pub const __GLIBC_USE_IEC_60559_FUNCS_EXT: u32 = 0;
|
||||
pub const __GLIBC_USE_IEC_60559_FUNCS_EXT_C2X: u32 = 0;
|
||||
pub const __GLIBC_USE_IEC_60559_FUNCS_EXT_C23: u32 = 0;
|
||||
pub const __GLIBC_USE_IEC_60559_TYPES_EXT: u32 = 0;
|
||||
pub const _BITS_TYPES_H: u32 = 1;
|
||||
pub const _BITS_TYPESIZES_H: u32 = 1;
|
||||
|
@ -5,7 +5,7 @@ use std::ptr::addr_of_mut;
|
||||
use std::{fmt::Debug, marker::PhantomData, mem::transmute, pin::Pin, ptr};
|
||||
|
||||
use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple};
|
||||
use libafl_qemu_sys::{CPUArchStatePtr, FatPtr, GuestAddr, GuestUsize, TCGTemp};
|
||||
use libafl_qemu_sys::{CPUArchStatePtr, CPUStatePtr, FatPtr, GuestAddr, GuestUsize, TCGTemp};
|
||||
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
use crate::qemu::{
|
||||
@ -20,6 +20,7 @@ use crate::qemu::{
|
||||
PreSyscallHookClosure, PreSyscallHookFn,
|
||||
};
|
||||
use crate::{
|
||||
cpu_run_post_exec_hook_wrapper, cpu_run_pre_exec_hook_wrapper,
|
||||
modules::{EmulatorModule, EmulatorModuleTuple},
|
||||
qemu::{
|
||||
block_0_exec_hook_wrapper, block_gen_hook_wrapper, block_post_gen_hook_wrapper,
|
||||
@ -33,11 +34,11 @@ use crate::{
|
||||
write_4_exec_hook_wrapper, write_gen_hook_wrapper, BackdoorHook, BackdoorHookClosure,
|
||||
BackdoorHookFn, BackdoorHookId, BlockExecHook, BlockGenHook, BlockHookId, BlockPostGenHook,
|
||||
CmpExecHook, CmpGenHook, CmpHookId, EdgeExecHook, EdgeGenHook, EdgeHookId, Hook, HookRepr,
|
||||
HookState, InstructionHook, InstructionHookClosure, InstructionHookFn, InstructionHookId,
|
||||
QemuHooks, ReadExecHook, ReadExecNHook, ReadGenHook, ReadHookId, WriteExecHook,
|
||||
InstructionHook, InstructionHookClosure, InstructionHookFn, InstructionHookId, QemuHooks,
|
||||
ReadExecHook, ReadExecNHook, ReadGenHook, ReadHookId, TcgHookState, WriteExecHook,
|
||||
WriteExecNHook, WriteGenHook, WriteHookId,
|
||||
},
|
||||
MemAccessInfo, Qemu,
|
||||
CpuPostRunHook, CpuPreRunHook, CpuRunHookId, HookState, MemAccessInfo, Qemu,
|
||||
};
|
||||
|
||||
macro_rules! get_raw_hook {
|
||||
@ -119,11 +120,13 @@ where
|
||||
|
||||
instruction_hooks: Vec<Pin<Box<(InstructionHookId, FatPtr)>>>,
|
||||
backdoor_hooks: Vec<Pin<Box<(BackdoorHookId, FatPtr)>>>,
|
||||
edge_hooks: Vec<Pin<Box<HookState<1, EdgeHookId>>>>,
|
||||
block_hooks: Vec<Pin<Box<HookState<1, BlockHookId>>>>,
|
||||
read_hooks: Vec<Pin<Box<HookState<5, ReadHookId>>>>,
|
||||
write_hooks: Vec<Pin<Box<HookState<5, WriteHookId>>>>,
|
||||
cmp_hooks: Vec<Pin<Box<HookState<4, CmpHookId>>>>,
|
||||
edge_hooks: Vec<Pin<Box<TcgHookState<1, EdgeHookId>>>>,
|
||||
block_hooks: Vec<Pin<Box<TcgHookState<1, BlockHookId>>>>,
|
||||
read_hooks: Vec<Pin<Box<TcgHookState<5, ReadHookId>>>>,
|
||||
write_hooks: Vec<Pin<Box<TcgHookState<5, WriteHookId>>>>,
|
||||
cmp_hooks: Vec<Pin<Box<TcgHookState<4, CmpHookId>>>>,
|
||||
|
||||
cpu_run_hooks: Vec<Pin<Box<HookState<CpuRunHookId>>>>,
|
||||
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
pre_syscall_hooks: Vec<Pin<Box<(PreSyscallHookId, FatPtr)>>>,
|
||||
@ -156,6 +159,8 @@ where
|
||||
write_hooks: Vec::new(),
|
||||
cmp_hooks: Vec::new(),
|
||||
|
||||
cpu_run_hooks: Vec::new(),
|
||||
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
pre_syscall_hooks: Vec::new(),
|
||||
|
||||
@ -252,7 +257,7 @@ where
|
||||
generation_hook,
|
||||
edge_gen_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(
|
||||
&mut HookState<1, EdgeHookId>,
|
||||
&mut TcgHookState<1, EdgeHookId>,
|
||||
src: GuestAddr,
|
||||
dest: GuestAddr,
|
||||
) -> u64
|
||||
@ -261,17 +266,17 @@ where
|
||||
let exec = get_raw_hook!(
|
||||
execution_hook,
|
||||
edge_0_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<1, EdgeHookId>, id: u64)
|
||||
unsafe extern "C" fn(&mut TcgHookState<1, EdgeHookId>, id: u64)
|
||||
);
|
||||
|
||||
self.edge_hooks.push(Box::pin(HookState::new(
|
||||
self.edge_hooks.push(Box::pin(TcgHookState::new(
|
||||
EdgeHookId::invalid(),
|
||||
hook_to_repr!(generation_hook),
|
||||
HookRepr::Empty,
|
||||
[hook_to_repr!(execution_hook)],
|
||||
)));
|
||||
|
||||
let hook_state = &mut *ptr::from_mut::<HookState<1, EdgeHookId>>(
|
||||
let hook_state = &mut *ptr::from_mut::<TcgHookState<1, EdgeHookId>>(
|
||||
self.edge_hooks
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
@ -302,14 +307,14 @@ where
|
||||
let gen = get_raw_hook!(
|
||||
generation_hook,
|
||||
block_gen_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<1, BlockHookId>, pc: GuestAddr) -> u64
|
||||
unsafe extern "C" fn(&mut TcgHookState<1, BlockHookId>, pc: GuestAddr) -> u64
|
||||
);
|
||||
|
||||
let postgen = get_raw_hook!(
|
||||
post_generation_hook,
|
||||
block_post_gen_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(
|
||||
&mut HookState<1, BlockHookId>,
|
||||
&mut TcgHookState<1, BlockHookId>,
|
||||
pc: GuestAddr,
|
||||
block_length: GuestUsize,
|
||||
)
|
||||
@ -318,17 +323,17 @@ where
|
||||
let exec = get_raw_hook!(
|
||||
execution_hook,
|
||||
block_0_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<1, BlockHookId>, id: u64)
|
||||
unsafe extern "C" fn(&mut TcgHookState<1, BlockHookId>, id: u64)
|
||||
);
|
||||
|
||||
self.block_hooks.push(Box::pin(HookState::new(
|
||||
self.block_hooks.push(Box::pin(TcgHookState::new(
|
||||
BlockHookId::invalid(),
|
||||
hook_to_repr!(generation_hook),
|
||||
hook_to_repr!(post_generation_hook),
|
||||
[hook_to_repr!(execution_hook)],
|
||||
)));
|
||||
|
||||
let hook_state = &mut *ptr::from_mut::<HookState<1, BlockHookId>>(
|
||||
let hook_state = &mut *ptr::from_mut::<TcgHookState<1, BlockHookId>>(
|
||||
self.block_hooks
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
@ -351,6 +356,53 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cpu_runs(
|
||||
&mut self,
|
||||
pre_exec_hook: CpuPreRunHook<ET, S>,
|
||||
post_exec_hook: CpuPostRunHook<ET, S>,
|
||||
) -> CpuRunHookId {
|
||||
unsafe {
|
||||
let pre_run = get_raw_hook!(
|
||||
pre_exec_hook,
|
||||
cpu_run_pre_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<CpuRunHookId>, cpu: CPUStatePtr)
|
||||
);
|
||||
|
||||
let post_run = get_raw_hook!(
|
||||
post_exec_hook,
|
||||
cpu_run_post_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<CpuRunHookId>, cpu: CPUStatePtr)
|
||||
);
|
||||
|
||||
self.cpu_run_hooks.push(Box::pin(HookState::new(
|
||||
CpuRunHookId::invalid(),
|
||||
hook_to_repr!(pre_exec_hook),
|
||||
hook_to_repr!(post_exec_hook),
|
||||
)));
|
||||
|
||||
let hook_state = &mut *ptr::from_mut::<HookState<CpuRunHookId>>(
|
||||
self.cpu_run_hooks
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut(),
|
||||
);
|
||||
|
||||
let id = self
|
||||
.qemu_hooks
|
||||
.add_cpu_run_hooks(hook_state, pre_run, post_run);
|
||||
|
||||
self.cpu_run_hooks
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.set_id(id);
|
||||
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::similar_names)]
|
||||
pub fn reads(
|
||||
&mut self,
|
||||
@ -366,7 +418,7 @@ where
|
||||
generation_hook,
|
||||
read_gen_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(
|
||||
&mut HookState<5, ReadHookId>,
|
||||
&mut TcgHookState<5, ReadHookId>,
|
||||
pc: GuestAddr,
|
||||
addr: *mut TCGTemp,
|
||||
info: MemAccessInfo,
|
||||
@ -375,35 +427,35 @@ where
|
||||
let exec1 = get_raw_hook!(
|
||||
execution_hook_1,
|
||||
read_0_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr)
|
||||
unsafe extern "C" fn(&mut TcgHookState<5, ReadHookId>, id: u64, addr: GuestAddr)
|
||||
);
|
||||
let exec2 = get_raw_hook!(
|
||||
execution_hook_2,
|
||||
read_1_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr)
|
||||
unsafe extern "C" fn(&mut TcgHookState<5, ReadHookId>, id: u64, addr: GuestAddr)
|
||||
);
|
||||
let exec4 = get_raw_hook!(
|
||||
execution_hook_4,
|
||||
read_2_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr)
|
||||
unsafe extern "C" fn(&mut TcgHookState<5, ReadHookId>, id: u64, addr: GuestAddr)
|
||||
);
|
||||
let exec8 = get_raw_hook!(
|
||||
execution_hook_8,
|
||||
read_3_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr)
|
||||
unsafe extern "C" fn(&mut TcgHookState<5, ReadHookId>, id: u64, addr: GuestAddr)
|
||||
);
|
||||
let execn = get_raw_hook!(
|
||||
execution_hook_n,
|
||||
read_4_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(
|
||||
&mut HookState<5, ReadHookId>,
|
||||
&mut TcgHookState<5, ReadHookId>,
|
||||
id: u64,
|
||||
addr: GuestAddr,
|
||||
size: usize,
|
||||
)
|
||||
);
|
||||
|
||||
self.read_hooks.push(Box::pin(HookState::new(
|
||||
self.read_hooks.push(Box::pin(TcgHookState::new(
|
||||
ReadHookId::invalid(),
|
||||
hook_to_repr!(generation_hook),
|
||||
HookRepr::Empty,
|
||||
@ -416,7 +468,7 @@ where
|
||||
],
|
||||
)));
|
||||
|
||||
let hook_state = &mut *ptr::from_mut::<HookState<5, ReadHookId>>(
|
||||
let hook_state = &mut *ptr::from_mut::<TcgHookState<5, ReadHookId>>(
|
||||
self.read_hooks
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
@ -454,7 +506,7 @@ where
|
||||
generation_hook,
|
||||
write_gen_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(
|
||||
&mut HookState<5, WriteHookId>,
|
||||
&mut TcgHookState<5, WriteHookId>,
|
||||
pc: GuestAddr,
|
||||
addr: *mut TCGTemp,
|
||||
info: MemAccessInfo,
|
||||
@ -463,35 +515,35 @@ where
|
||||
let exec1 = get_raw_hook!(
|
||||
execution_hook_1,
|
||||
write_0_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<5, WriteHookId>, id: u64, addr: GuestAddr)
|
||||
unsafe extern "C" fn(&mut TcgHookState<5, WriteHookId>, id: u64, addr: GuestAddr)
|
||||
);
|
||||
let exec2 = get_raw_hook!(
|
||||
execution_hook_2,
|
||||
write_1_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<5, WriteHookId>, id: u64, addr: GuestAddr)
|
||||
unsafe extern "C" fn(&mut TcgHookState<5, WriteHookId>, id: u64, addr: GuestAddr)
|
||||
);
|
||||
let exec4 = get_raw_hook!(
|
||||
execution_hook_4,
|
||||
write_2_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<5, WriteHookId>, id: u64, addr: GuestAddr)
|
||||
unsafe extern "C" fn(&mut TcgHookState<5, WriteHookId>, id: u64, addr: GuestAddr)
|
||||
);
|
||||
let exec8 = get_raw_hook!(
|
||||
execution_hook_8,
|
||||
write_3_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<5, WriteHookId>, id: u64, addr: GuestAddr)
|
||||
unsafe extern "C" fn(&mut TcgHookState<5, WriteHookId>, id: u64, addr: GuestAddr)
|
||||
);
|
||||
let execn = get_raw_hook!(
|
||||
execution_hook_n,
|
||||
write_4_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(
|
||||
&mut HookState<5, WriteHookId>,
|
||||
&mut TcgHookState<5, WriteHookId>,
|
||||
id: u64,
|
||||
addr: GuestAddr,
|
||||
size: usize,
|
||||
)
|
||||
);
|
||||
|
||||
self.write_hooks.push(Box::pin(HookState::new(
|
||||
self.write_hooks.push(Box::pin(TcgHookState::new(
|
||||
WriteHookId::invalid(),
|
||||
hook_to_repr!(generation_hook),
|
||||
HookRepr::Empty,
|
||||
@ -504,7 +556,7 @@ where
|
||||
],
|
||||
)));
|
||||
|
||||
let hook_state = &mut *ptr::from_mut::<HookState<5, WriteHookId>>(
|
||||
let hook_state = &mut *ptr::from_mut::<TcgHookState<5, WriteHookId>>(
|
||||
self.write_hooks
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
@ -540,7 +592,7 @@ where
|
||||
generation_hook,
|
||||
cmp_gen_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(
|
||||
&mut HookState<4, CmpHookId>,
|
||||
&mut TcgHookState<4, CmpHookId>,
|
||||
pc: GuestAddr,
|
||||
size: usize,
|
||||
) -> u64
|
||||
@ -548,25 +600,25 @@ where
|
||||
let exec1 = get_raw_hook!(
|
||||
execution_hook_1,
|
||||
cmp_0_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u8, v1: u8)
|
||||
unsafe extern "C" fn(&mut TcgHookState<4, CmpHookId>, id: u64, v0: u8, v1: u8)
|
||||
);
|
||||
let exec2 = get_raw_hook!(
|
||||
execution_hook_2,
|
||||
cmp_1_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u16, v1: u16)
|
||||
unsafe extern "C" fn(&mut TcgHookState<4, CmpHookId>, id: u64, v0: u16, v1: u16)
|
||||
);
|
||||
let exec4 = get_raw_hook!(
|
||||
execution_hook_4,
|
||||
cmp_2_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u32, v1: u32)
|
||||
unsafe extern "C" fn(&mut TcgHookState<4, CmpHookId>, id: u64, v0: u32, v1: u32)
|
||||
);
|
||||
let exec8 = get_raw_hook!(
|
||||
execution_hook_8,
|
||||
cmp_3_exec_hook_wrapper::<ET, S>,
|
||||
unsafe extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u64, v1: u64)
|
||||
unsafe extern "C" fn(&mut TcgHookState<4, CmpHookId>, id: u64, v0: u64, v1: u64)
|
||||
);
|
||||
|
||||
self.cmp_hooks.push(Box::pin(HookState::new(
|
||||
self.cmp_hooks.push(Box::pin(TcgHookState::new(
|
||||
CmpHookId::invalid(),
|
||||
hook_to_repr!(generation_hook),
|
||||
HookRepr::Empty,
|
||||
@ -578,7 +630,7 @@ where
|
||||
],
|
||||
)));
|
||||
|
||||
let hook_state = &mut *ptr::from_mut::<HookState<4, CmpHookId>>(
|
||||
let hook_state = &mut *ptr::from_mut::<TcgHookState<4, CmpHookId>>(
|
||||
self.cmp_hooks
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
@ -776,7 +828,12 @@ where
|
||||
|
||||
pub fn thread_creation_function(
|
||||
&mut self,
|
||||
hook: fn(&mut EmulatorModules<ET, S>, Option<&mut S>, tid: u32) -> bool,
|
||||
hook: fn(
|
||||
&mut EmulatorModules<ET, S>,
|
||||
Option<&mut S>,
|
||||
env: CPUArchStatePtr,
|
||||
tid: u32,
|
||||
) -> bool,
|
||||
) -> NewThreadHookId {
|
||||
unsafe {
|
||||
self.qemu_hooks
|
||||
@ -1206,7 +1263,12 @@ where
|
||||
|
||||
pub fn thread_creation_function(
|
||||
&mut self,
|
||||
hook: fn(&mut EmulatorModules<ET, S>, Option<&mut S>, tid: u32) -> bool,
|
||||
hook: fn(
|
||||
&mut EmulatorModules<ET, S>,
|
||||
Option<&mut S>,
|
||||
env: CPUArchStatePtr,
|
||||
tid: u32,
|
||||
) -> bool,
|
||||
) -> NewThreadHookId {
|
||||
self.hooks.thread_creation_function(hook)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use core::{ffi::c_void, fmt::Debug, mem::transmute, ptr};
|
||||
use libafl::{executors::hooks::inprocess::inprocess_get_state, inputs::UsesInput};
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
use libafl_qemu_sys::libafl_dump_core_hook;
|
||||
use libafl_qemu_sys::{CPUArchStatePtr, FatPtr, GuestAddr, GuestUsize};
|
||||
use libafl_qemu_sys::{CPUArchStatePtr, CPUStatePtr, FatPtr, GuestAddr, GuestUsize};
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::{pyclass, pymethods, FromPyObject};
|
||||
|
||||
@ -29,14 +29,21 @@ pub enum HookRepr {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HookState<const N: usize, H: HookId> {
|
||||
pub struct TcgHookState<const N: usize, H: HookId> {
|
||||
id: H,
|
||||
gen: HookRepr,
|
||||
post_gen: HookRepr,
|
||||
execs: [HookRepr; N],
|
||||
}
|
||||
|
||||
impl<const N: usize, H: HookId> HookState<N, H> {
|
||||
#[derive(Debug)]
|
||||
pub struct HookState<H: HookId> {
|
||||
id: H,
|
||||
pre_run: HookRepr,
|
||||
post_run: HookRepr,
|
||||
}
|
||||
|
||||
impl<const N: usize, H: HookId> TcgHookState<N, H> {
|
||||
pub fn new(id: H, gen: HookRepr, post_gen: HookRepr, execs: [HookRepr; N]) -> Self {
|
||||
Self {
|
||||
id,
|
||||
@ -51,6 +58,20 @@ impl<const N: usize, H: HookId> HookState<N, H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: HookId> HookState<H> {
|
||||
pub fn new(id: H, pre_run: HookRepr, post_run: HookRepr) -> Self {
|
||||
Self {
|
||||
id,
|
||||
pre_run,
|
||||
post_run,
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn set_id(&mut self, id: H) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Hook<F, C, R: Clone> {
|
||||
Function(F),
|
||||
Closure(C),
|
||||
@ -129,10 +150,72 @@ macro_rules! create_wrapper {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! create_pre_exec_wrapper {
|
||||
($name:ident, ($($param:ident : $param_type:ty),*), $hook_id:ident) => {
|
||||
paste::paste! {
|
||||
pub extern "C" fn [<$name _pre_exec_hook_wrapper>]<ET, S>(hook: &mut HookState<$hook_id>, $($param: $param_type),*)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
S: Unpin + UsesInput,
|
||||
{
|
||||
unsafe {
|
||||
let modules = EmulatorModules::<ET, S>::emulator_modules_mut_unchecked();
|
||||
|
||||
match &mut hook.pre_run {
|
||||
HookRepr::Function(ptr) => {
|
||||
let func: fn(&mut EmulatorModules<ET, S>, Option<&mut S>, $($param_type),*) =
|
||||
transmute(*ptr);
|
||||
func(modules, inprocess_get_state::<S>(), $($param),*)
|
||||
}
|
||||
HookRepr::Closure(ptr) => {
|
||||
let func: &mut Box<
|
||||
dyn FnMut(&mut EmulatorModules<ET, S>, Option<&mut S>, $($param_type),*),
|
||||
> = transmute(ptr);
|
||||
func(modules, inprocess_get_state::<S>(), $($param),*)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! create_post_exec_wrapper {
|
||||
($name:ident, ($($param:ident : $param_type:ty),*), $hook_id:ident) => {
|
||||
paste::paste! {
|
||||
pub extern "C" fn [<$name _post_exec_hook_wrapper>]<ET, S>(hook: &mut HookState<$hook_id>, $($param: $param_type),*)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
S: Unpin + UsesInput,
|
||||
{
|
||||
unsafe {
|
||||
let modules = EmulatorModules::<ET, S>::emulator_modules_mut_unchecked();
|
||||
|
||||
match &mut hook.post_run {
|
||||
HookRepr::Function(ptr) => {
|
||||
let func: fn(&mut EmulatorModules<ET, S>, Option<&mut S>, $($param_type),*) =
|
||||
transmute(*ptr);
|
||||
func(modules, inprocess_get_state::<S>(), $($param),*);
|
||||
}
|
||||
HookRepr::Closure(ptr) => {
|
||||
let func: &mut Box<
|
||||
dyn FnMut(&mut EmulatorModules<ET, S>, Option<&mut S>, $($param_type),*),
|
||||
> = transmute(ptr);
|
||||
func(modules, inprocess_get_state::<S>(), $($param),*);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! create_gen_wrapper {
|
||||
($name:ident, ($($param:ident : $param_type:ty),*), $ret_type:ty, $execs:literal, $hook_id:ident) => {
|
||||
paste::paste! {
|
||||
pub extern "C" fn [<$name _gen_hook_wrapper>]<ET, S>(hook: &mut HookState<{ $execs }, $hook_id>, $($param: $param_type),*) -> $ret_type
|
||||
pub extern "C" fn [<$name _gen_hook_wrapper>]<ET, S>(hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*) -> $ret_type
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
S: Unpin + UsesInput,
|
||||
@ -163,7 +246,7 @@ macro_rules! create_gen_wrapper {
|
||||
macro_rules! create_post_gen_wrapper {
|
||||
($name:ident, ($($param:ident : $param_type:ty),*), $execs:literal, $hook_id:ident) => {
|
||||
paste::paste! {
|
||||
pub extern "C" fn [<$name _post_gen_hook_wrapper>]<ET, S>(hook: &mut HookState<{ $execs }, $hook_id>, $($param: $param_type),*)
|
||||
pub extern "C" fn [<$name _post_gen_hook_wrapper>]<ET, S>(hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
S: Unpin + UsesInput,
|
||||
@ -193,7 +276,7 @@ macro_rules! create_post_gen_wrapper {
|
||||
macro_rules! create_exec_wrapper {
|
||||
($name:ident, ($($param:ident : $param_type:ty),*), $execidx:literal, $execs:literal, $hook_id:ident) => {
|
||||
paste::paste! {
|
||||
pub extern "C" fn [<$name _ $execidx _exec_hook_wrapper>]<ET, S>(hook: &mut HookState<{ $execs }, $hook_id>, $($param: $param_type),*)
|
||||
pub extern "C" fn [<$name _ $execidx _exec_hook_wrapper>]<ET, S>(hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
S: Unpin + UsesInput,
|
||||
@ -271,11 +354,6 @@ macro_rules! create_hook_types {
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_hook_id!(PostSyscall, libafl_qemu_remove_post_syscall_hook, false);
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false);
|
||||
|
||||
// Instruction hook wrappers
|
||||
create_hook_types!(
|
||||
Instruction,
|
||||
@ -409,6 +487,8 @@ create_hook_types!(
|
||||
) -> GuestAddr
|
||||
);
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_hook_id!(PostSyscall, libafl_qemu_remove_post_syscall_hook, false);
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_wrapper!(
|
||||
post_syscall,
|
||||
(
|
||||
@ -430,12 +510,39 @@ create_wrapper!(
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_hook_types!(
|
||||
NewThread,
|
||||
fn(&mut EmulatorModules<ET, S>, Option<&mut S>, tid: u32) -> bool,
|
||||
Box<dyn for<'a> FnMut(&'a mut EmulatorModules<ET, S>, Option<&'a mut S>, u32) -> bool>,
|
||||
extern "C" fn(*const (), tid: u32) -> bool
|
||||
fn(&mut EmulatorModules<ET, S>, Option<&mut S>, env: CPUArchStatePtr, tid: u32) -> bool,
|
||||
Box<
|
||||
dyn for<'a> FnMut(
|
||||
&'a mut EmulatorModules<ET, S>,
|
||||
Option<&'a mut S>,
|
||||
CPUArchStatePtr,
|
||||
u32,
|
||||
) -> bool,
|
||||
>,
|
||||
extern "C" fn(*const (), env: CPUArchStatePtr, tid: u32) -> bool
|
||||
);
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_wrapper!(new_thread, (tid: u32), bool);
|
||||
create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false);
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
create_wrapper!(new_thread, (env: CPUArchStatePtr, tid: u32), bool);
|
||||
|
||||
// CPU Run hook wrappers
|
||||
create_hook_types!(
|
||||
CpuPreRun,
|
||||
fn(&mut EmulatorModules<ET, S>, Option<&mut S>, cpu: CPUStatePtr),
|
||||
Box<dyn for<'a> FnMut(&'a mut EmulatorModules<ET, S>, Option<&'a mut S>, CPUStatePtr)>,
|
||||
extern "C" fn(*const (), cpu: CPUStatePtr)
|
||||
);
|
||||
create_hook_types!(
|
||||
CpuPostRun,
|
||||
fn(&mut EmulatorModules<ET, S>, Option<&mut S>, cpu: CPUStatePtr),
|
||||
Box<dyn for<'a> FnMut(&'a mut EmulatorModules<ET, S>, Option<&'a mut S>, CPUStatePtr)>,
|
||||
extern "C" fn(*const (), cpu: CPUStatePtr)
|
||||
);
|
||||
create_hook_id!(CpuRun, libafl_qemu_remove_cpu_run_hook, false);
|
||||
create_pre_exec_wrapper!(cpu_run, (cpu: CPUStatePtr), CpuRunHookId);
|
||||
create_post_exec_wrapper!(cpu_run, (addr: CPUStatePtr), CpuRunHookId);
|
||||
create_wrapper!(cpu_run, (cpu: CPUStatePtr));
|
||||
|
||||
// Edge hook wrappers
|
||||
create_hook_types!(
|
||||
@ -714,6 +821,22 @@ impl QemuHooks {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_transmute_annotations)]
|
||||
pub fn add_cpu_run_hooks<T: Into<HookData>>(
|
||||
&self,
|
||||
data: T,
|
||||
pre_exec: Option<unsafe extern "C" fn(T, CPUStatePtr)>,
|
||||
post_exec: Option<unsafe extern "C" fn(T, CPUStatePtr)>,
|
||||
) -> CpuRunHookId {
|
||||
unsafe {
|
||||
let data: u64 = data.into().0;
|
||||
let pre_exec: Option<unsafe extern "C" fn(u64, CPUStatePtr)> = transmute(pre_exec);
|
||||
let post_gen: Option<unsafe extern "C" fn(u64, CPUStatePtr)> = transmute(post_exec);
|
||||
let num = libafl_qemu_sys::libafl_hook_cpu_run_add(pre_exec, post_gen, data);
|
||||
CpuRunHookId(num)
|
||||
}
|
||||
}
|
||||
|
||||
/// `data` can be used to pass data that can be accessed as the first argument in the `gen` and the `exec` functions
|
||||
///
|
||||
/// `gen` gets passed the current programm counter, mutable access to a `TCGTemp` and information about the memory
|
||||
@ -873,11 +996,11 @@ impl QemuHooks {
|
||||
pub fn add_new_thread_hook<T: Into<HookData>>(
|
||||
&self,
|
||||
data: T,
|
||||
callback: extern "C" fn(T, tid: u32) -> bool,
|
||||
callback: extern "C" fn(T, env: CPUArchStatePtr, tid: u32) -> bool,
|
||||
) -> NewThreadHookId {
|
||||
unsafe {
|
||||
let data: u64 = data.into().0;
|
||||
let callback: extern "C" fn(u64, u32) -> bool = transmute(callback);
|
||||
let callback: extern "C" fn(u64, CPUArchStatePtr, u32) -> bool = transmute(callback);
|
||||
let num = libafl_qemu_sys::libafl_add_new_thread_hook(Some(callback), data);
|
||||
NewThreadHookId(num)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user