parent
c68b30ae2a
commit
184b69be8e
@ -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 = "2a676d9cd8c474b5c0db1d77d2769e56e2ed8524";
|
||||
pub const QEMU_REVISION: &str = "97bef506eed24ee8d0eda4a07c4419c55dae4acb";
|
||||
|
||||
pub struct BuildResult {
|
||||
pub qemu_path: PathBuf,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 1.87.0-nightly */
|
||||
/* qemu git hash: 2a676d9cd8c474b5c0db1d77d2769e56e2ed8524 */
|
||||
/* qemu git hash: 97bef506eed24ee8d0eda4a07c4419c55dae4acb */
|
||||
/* automatically generated by rust-bindgen 0.71.1 */
|
||||
|
||||
use libc::siginfo_t;
|
||||
@ -8687,37 +8687,131 @@ unsafe extern "C" {
|
||||
unsafe extern "C" {
|
||||
pub fn libafl_hook_new_thread_run(env: *mut CPUArchState, tid: u32) -> bool;
|
||||
}
|
||||
pub const libafl_syshook_ret_tag_LIBAFL_SYSHOOK_RUN: libafl_syshook_ret_tag =
|
||||
libafl_syshook_ret_tag(0);
|
||||
pub const libafl_syshook_ret_tag_LIBAFL_SYSHOOK_SKIP: libafl_syshook_ret_tag =
|
||||
libafl_syshook_ret_tag(1);
|
||||
impl ::std::ops::BitOr<libafl_syshook_ret_tag> for libafl_syshook_ret_tag {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitor(self, other: Self) -> Self {
|
||||
libafl_syshook_ret_tag(self.0 | other.0)
|
||||
}
|
||||
}
|
||||
impl ::std::ops::BitOrAssign for libafl_syshook_ret_tag {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, rhs: libafl_syshook_ret_tag) {
|
||||
self.0 |= rhs.0;
|
||||
}
|
||||
}
|
||||
impl ::std::ops::BitAnd<libafl_syshook_ret_tag> for libafl_syshook_ret_tag {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitand(self, other: Self) -> Self {
|
||||
libafl_syshook_ret_tag(self.0 & other.0)
|
||||
}
|
||||
}
|
||||
impl ::std::ops::BitAndAssign for libafl_syshook_ret_tag {
|
||||
#[inline]
|
||||
fn bitand_assign(&mut self, rhs: libafl_syshook_ret_tag) {
|
||||
self.0 &= rhs.0;
|
||||
}
|
||||
}
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct libafl_syshook_ret_tag(pub ::std::os::raw::c_uint);
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct syshook_ret {
|
||||
pub retval: target_ulong,
|
||||
pub skip_syscall: bool,
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct libafl_syshook_ret {
|
||||
pub tag: libafl_syshook_ret_tag,
|
||||
pub __bindgen_anon_1: libafl_syshook_ret__bindgen_ty_1,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub union libafl_syshook_ret__bindgen_ty_1 {
|
||||
pub syshook_skip_retval: target_ulong,
|
||||
}
|
||||
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
|
||||
const _: () = {
|
||||
["Size of syshook_ret"][::std::mem::size_of::<syshook_ret>() - 16usize];
|
||||
["Alignment of syshook_ret"][::std::mem::align_of::<syshook_ret>() - 8usize];
|
||||
["Offset of field: syshook_ret::retval"][::std::mem::offset_of!(syshook_ret, retval) - 0usize];
|
||||
["Offset of field: syshook_ret::skip_syscall"]
|
||||
[::std::mem::offset_of!(syshook_ret, skip_syscall) - 8usize];
|
||||
["Size of libafl_syshook_ret__bindgen_ty_1"]
|
||||
[::std::mem::size_of::<libafl_syshook_ret__bindgen_ty_1>() - 8usize];
|
||||
["Alignment of libafl_syshook_ret__bindgen_ty_1"]
|
||||
[::std::mem::align_of::<libafl_syshook_ret__bindgen_ty_1>() - 8usize];
|
||||
["Offset of field: libafl_syshook_ret__bindgen_ty_1::syshook_skip_retval"]
|
||||
[::std::mem::offset_of!(libafl_syshook_ret__bindgen_ty_1, syshook_skip_retval) - 0usize];
|
||||
};
|
||||
impl Default for libafl_syshook_ret__bindgen_ty_1 {
|
||||
fn default() -> Self {
|
||||
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
|
||||
unsafe {
|
||||
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
|
||||
s.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ::std::fmt::Debug for libafl_syshook_ret__bindgen_ty_1 {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
write!(f, "libafl_syshook_ret__bindgen_ty_1 {{ union }}")
|
||||
}
|
||||
}
|
||||
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
|
||||
const _: () = {
|
||||
["Size of libafl_syshook_ret"][::std::mem::size_of::<libafl_syshook_ret>() - 16usize];
|
||||
["Alignment of libafl_syshook_ret"][::std::mem::align_of::<libafl_syshook_ret>() - 8usize];
|
||||
["Offset of field: libafl_syshook_ret::tag"]
|
||||
[::std::mem::offset_of!(libafl_syshook_ret, tag) - 0usize];
|
||||
};
|
||||
impl Default for libafl_syshook_ret {
|
||||
fn default() -> Self {
|
||||
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
|
||||
unsafe {
|
||||
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
|
||||
s.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ::std::fmt::Debug for libafl_syshook_ret {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"libafl_syshook_ret {{ tag: {:?}, __bindgen_anon_1: {:?} }}",
|
||||
self.tag, self.__bindgen_anon_1
|
||||
)
|
||||
}
|
||||
}
|
||||
pub type libafl_pre_syscall_cb = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
data: u64,
|
||||
sys_num: ::std::os::raw::c_int,
|
||||
arg0: target_ulong,
|
||||
arg1: target_ulong,
|
||||
arg2: target_ulong,
|
||||
arg3: target_ulong,
|
||||
arg4: target_ulong,
|
||||
arg5: target_ulong,
|
||||
arg6: target_ulong,
|
||||
arg7: target_ulong,
|
||||
) -> libafl_syshook_ret,
|
||||
>;
|
||||
pub type libafl_post_syscall_cb = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
data: u64,
|
||||
ret: target_ulong,
|
||||
sys_num: ::std::os::raw::c_int,
|
||||
arg0: target_ulong,
|
||||
arg1: target_ulong,
|
||||
arg2: target_ulong,
|
||||
arg3: target_ulong,
|
||||
arg4: target_ulong,
|
||||
arg5: target_ulong,
|
||||
arg6: target_ulong,
|
||||
arg7: target_ulong,
|
||||
) -> target_ulong,
|
||||
>;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct libafl_pre_syscall_hook {
|
||||
pub callback: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
data: u64,
|
||||
sys_num: ::std::os::raw::c_int,
|
||||
arg0: target_ulong,
|
||||
arg1: target_ulong,
|
||||
arg2: target_ulong,
|
||||
arg3: target_ulong,
|
||||
arg4: target_ulong,
|
||||
arg5: target_ulong,
|
||||
arg6: target_ulong,
|
||||
arg7: target_ulong,
|
||||
) -> syshook_ret,
|
||||
>,
|
||||
pub callback: libafl_pre_syscall_cb,
|
||||
pub data: u64,
|
||||
pub num: usize,
|
||||
pub next: *mut libafl_pre_syscall_hook,
|
||||
@ -8748,21 +8842,7 @@ impl Default for libafl_pre_syscall_hook {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct libafl_post_syscall_hook {
|
||||
pub callback: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
data: u64,
|
||||
ret: target_ulong,
|
||||
sys_num: ::std::os::raw::c_int,
|
||||
arg0: target_ulong,
|
||||
arg1: target_ulong,
|
||||
arg2: target_ulong,
|
||||
arg3: target_ulong,
|
||||
arg4: target_ulong,
|
||||
arg5: target_ulong,
|
||||
arg6: target_ulong,
|
||||
arg7: target_ulong,
|
||||
) -> target_ulong,
|
||||
>,
|
||||
pub callback: libafl_post_syscall_cb,
|
||||
pub data: u64,
|
||||
pub num: usize,
|
||||
pub next: *mut libafl_post_syscall_hook,
|
||||
@ -8792,43 +8872,10 @@ impl Default for libafl_post_syscall_hook {
|
||||
}
|
||||
}
|
||||
unsafe extern "C" {
|
||||
pub fn libafl_add_pre_syscall_hook(
|
||||
callback: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
data: u64,
|
||||
sys_num: ::std::os::raw::c_int,
|
||||
arg0: target_ulong,
|
||||
arg1: target_ulong,
|
||||
arg2: target_ulong,
|
||||
arg3: target_ulong,
|
||||
arg4: target_ulong,
|
||||
arg5: target_ulong,
|
||||
arg6: target_ulong,
|
||||
arg7: target_ulong,
|
||||
) -> syshook_ret,
|
||||
>,
|
||||
data: u64,
|
||||
) -> usize;
|
||||
pub fn libafl_add_pre_syscall_hook(callback: libafl_pre_syscall_cb, data: u64) -> usize;
|
||||
}
|
||||
unsafe extern "C" {
|
||||
pub fn libafl_add_post_syscall_hook(
|
||||
callback: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
data: u64,
|
||||
ret: target_ulong,
|
||||
sys_num: ::std::os::raw::c_int,
|
||||
arg0: target_ulong,
|
||||
arg1: target_ulong,
|
||||
arg2: target_ulong,
|
||||
arg3: target_ulong,
|
||||
arg4: target_ulong,
|
||||
arg5: target_ulong,
|
||||
arg6: target_ulong,
|
||||
arg7: target_ulong,
|
||||
) -> target_ulong,
|
||||
>,
|
||||
data: u64,
|
||||
) -> usize;
|
||||
pub fn libafl_add_post_syscall_hook(callback: libafl_post_syscall_cb, data: u64) -> usize;
|
||||
}
|
||||
unsafe extern "C" {
|
||||
pub fn libafl_qemu_remove_pre_syscall_hook(num: usize) -> ::std::os::raw::c_int;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 1.87.0-nightly */
|
||||
/* qemu git hash: 2a676d9cd8c474b5c0db1d77d2769e56e2ed8524 */
|
||||
/* qemu git hash: 97bef506eed24ee8d0eda4a07c4419c55dae4acb */
|
||||
/* automatically generated by rust-bindgen 0.71.1 */
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 1.87.0-nightly */
|
||||
/* qemu git hash: 2a676d9cd8c474b5c0db1d77d2769e56e2ed8524 */
|
||||
/* qemu git hash: 97bef506eed24ee8d0eda4a07c4419c55dae4acb */
|
||||
/* automatically generated by rust-bindgen 0.71.1 */
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -98,7 +98,7 @@ pub fn python_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
#[cfg(feature = "usermode")]
|
||||
m.add_class::<GuestMaps>()?;
|
||||
|
||||
m.add_class::<SyscallHookResult>()?;
|
||||
m.add_class::<pybind::SyscallHookResult>()?;
|
||||
m.add_class::<pybind::Qemu>()?;
|
||||
|
||||
Ok(())
|
||||
|
@ -578,9 +578,9 @@ impl AsanGiovese {
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
SyscallHookResult::new(Some(r))
|
||||
SyscallHookResult::Skip(r)
|
||||
} else {
|
||||
SyscallHookResult::new(None)
|
||||
SyscallHookResult::Run
|
||||
}
|
||||
}
|
||||
|
||||
@ -1350,9 +1350,9 @@ where
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
SyscallHookResult::new(Some(0))
|
||||
SyscallHookResult::Skip(0)
|
||||
} else {
|
||||
SyscallHookResult::new(None)
|
||||
SyscallHookResult::Run
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,13 +400,13 @@ where
|
||||
|
||||
let first_parameter = unsafe {
|
||||
if (*c_array.offset(1)).is_null() {
|
||||
return SyscallHookResult::new(None);
|
||||
return SyscallHookResult::Run;
|
||||
}
|
||||
CStr::from_ptr(*c_array.offset(1)).to_string_lossy()
|
||||
};
|
||||
let second_parameter = unsafe {
|
||||
if (*c_array.offset(2)).is_null() {
|
||||
return SyscallHookResult::new(None);
|
||||
return SyscallHookResult::Run;
|
||||
}
|
||||
CStr::from_ptr(*c_array.offset(2)).to_string_lossy()
|
||||
};
|
||||
@ -419,9 +419,9 @@ where
|
||||
|
||||
//println!("PARAMETERS First {} Second {}", first_parameter, second_
|
||||
}
|
||||
SyscallHookResult::new(Some(0))
|
||||
SyscallHookResult::Skip(0)
|
||||
} else {
|
||||
SyscallHookResult::new(None)
|
||||
SyscallHookResult::Run
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ where
|
||||
{
|
||||
let h = emulator_modules.get_mut::<RedirectStdinModule>().unwrap();
|
||||
if h.input_addr.is_null() {
|
||||
return SyscallHookResult::new(None);
|
||||
return SyscallHookResult::Run;
|
||||
}
|
||||
if syscall == SYS_read as i32 && x0 == 0 {
|
||||
/*
|
||||
@ -143,7 +143,7 @@ where
|
||||
};
|
||||
// println!("copied {}", size);
|
||||
h.read += size as usize;
|
||||
return SyscallHookResult::new(Some(size));
|
||||
return SyscallHookResult::Skip(size);
|
||||
}
|
||||
SyscallHookResult::new(None)
|
||||
SyscallHookResult::Run
|
||||
}
|
||||
|
@ -888,11 +888,11 @@ where
|
||||
if i64::from(sys_num) == SYS_munmap {
|
||||
let h = emulator_modules.get_mut::<SnapshotModule>().unwrap();
|
||||
if !h.is_unmap_allowed(a0 as GuestAddr, a1 as usize) {
|
||||
return SyscallHookResult::new(Some(0));
|
||||
return SyscallHookResult::Skip(0);
|
||||
}
|
||||
}
|
||||
|
||||
SyscallHookResult::new(None)
|
||||
SyscallHookResult::Run
|
||||
}
|
||||
|
||||
#[expect(non_upper_case_globals, clippy::too_many_arguments)]
|
||||
|
@ -8,8 +8,6 @@ use core::{ffi::c_void, fmt::Debug, mem::transmute, ptr};
|
||||
|
||||
use libafl::executors::hooks::inprocess::inprocess_get_state;
|
||||
use libafl_qemu_sys::{CPUArchStatePtr, CPUStatePtr, FatPtr, GuestAddr, GuestUsize};
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::{FromPyObject, pyclass, pymethods};
|
||||
|
||||
use crate::{
|
||||
HookData, HookId,
|
||||
@ -85,12 +83,20 @@ pub enum Hook<F, C, R: Clone> {
|
||||
Empty,
|
||||
}
|
||||
|
||||
/// Syshook result representation
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This enum is shadowed by another enum in QEMU (`libafl_syshook_ret`). Any change made to this
|
||||
/// enum should be propagated to the C enum as well.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature = "python", pyclass)]
|
||||
#[cfg_attr(feature = "python", derive(FromPyObject))]
|
||||
pub struct SyscallHookResult {
|
||||
pub retval: GuestAddr,
|
||||
pub skip_syscall: bool,
|
||||
pub enum SyscallHookResult {
|
||||
/// Runs the syscall after the hook is executed. The return value will be the one of the
|
||||
/// syscall itself.
|
||||
/// If you need to change the return value of the syscall, please use a post-syscall hook.
|
||||
Run,
|
||||
/// Skip the syscall, and make the syscall return the value provided in the field in the target.
|
||||
Skip(GuestAddr),
|
||||
}
|
||||
|
||||
impl<F, C, R: Clone> Hook<F, C, R> {
|
||||
@ -1281,7 +1287,7 @@ impl QemuHooks {
|
||||
GuestAddr,
|
||||
GuestAddr,
|
||||
GuestAddr,
|
||||
) -> libafl_qemu_sys::syshook_ret = transmute(callback);
|
||||
) -> libafl_qemu_sys::libafl_syshook_ret = transmute(callback);
|
||||
let num = libafl_qemu_sys::libafl_add_pre_syscall_hook(Some(callback), data);
|
||||
PreSyscallHookId(num)
|
||||
}
|
||||
@ -1324,38 +1330,3 @@ impl QemuHooks {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
#[pymethods]
|
||||
impl SyscallHookResult {
|
||||
#[new]
|
||||
#[pyo3(signature = (
|
||||
value=None
|
||||
))]
|
||||
#[must_use]
|
||||
pub fn new(value: Option<GuestAddr>) -> Self {
|
||||
Self::new_internal(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl SyscallHookResult {
|
||||
#[cfg(not(feature = "python"))]
|
||||
#[must_use]
|
||||
pub fn new(value: Option<GuestAddr>) -> Self {
|
||||
Self::new_internal(value)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn new_internal(value: Option<GuestAddr>) -> Self {
|
||||
value.map_or(
|
||||
Self {
|
||||
retval: 0,
|
||||
skip_syscall: false,
|
||||
},
|
||||
|v| Self {
|
||||
retval: v,
|
||||
skip_syscall: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1238,6 +1238,8 @@ impl QemuMemoryChunk {
|
||||
pub mod pybind {
|
||||
use pyo3::{exceptions::PyValueError, prelude::*};
|
||||
|
||||
#[cfg(feature = "usermode")]
|
||||
pub use super::usermode::pybind::*;
|
||||
use super::{GuestAddr, GuestUsize};
|
||||
|
||||
static mut PY_GENERIC_HOOKS: Vec<(GuestAddr, PyObject)> = vec![];
|
||||
|
@ -467,17 +467,24 @@ impl Qemu {
|
||||
pub mod pybind {
|
||||
use libafl_qemu_sys::{GuestAddr, MmapPerms};
|
||||
use pyo3::{
|
||||
Bound, PyObject, PyResult, Python,
|
||||
conversion::FromPyObject,
|
||||
Bound, FromPyObject, PyObject, PyResult, Python,
|
||||
exceptions::PyValueError,
|
||||
pymethods,
|
||||
pyclass, pymethods,
|
||||
types::{PyAnyMethods, PyInt},
|
||||
};
|
||||
|
||||
use crate::{pybind::Qemu, qemu::hooks::SyscallHookResult};
|
||||
use crate::{pybind::Qemu, qemu::hooks};
|
||||
|
||||
static mut PY_SYSCALL_HOOK: Option<PyObject> = None;
|
||||
|
||||
#[pyclass]
|
||||
#[derive(FromPyObject)]
|
||||
pub struct SyscallHookResult {
|
||||
/// if None: run.
|
||||
/// else: skip with given value.
|
||||
skip: Option<GuestAddr>,
|
||||
}
|
||||
|
||||
extern "C" fn py_syscall_hook_wrapper(
|
||||
_data: u64,
|
||||
sys_num: i32,
|
||||
@ -489,25 +496,31 @@ pub mod pybind {
|
||||
a5: u64,
|
||||
a6: u64,
|
||||
a7: u64,
|
||||
) -> SyscallHookResult {
|
||||
) -> hooks::SyscallHookResult {
|
||||
unsafe { (&raw const PY_SYSCALL_HOOK).read() }.map_or_else(
|
||||
|| SyscallHookResult::new(None),
|
||||
|| hooks::SyscallHookResult::Run,
|
||||
|obj| {
|
||||
let args = (sys_num, a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
Python::with_gil(|py| {
|
||||
let ret = obj.call1(py, args).expect("Error in the syscall hook");
|
||||
let any = ret.bind(py);
|
||||
if any.is_none() {
|
||||
SyscallHookResult::new(None)
|
||||
hooks::SyscallHookResult::Run
|
||||
} else {
|
||||
let a: Result<&Bound<'_, PyInt>, _> = any.downcast_exact();
|
||||
if let Ok(i) = a {
|
||||
SyscallHookResult::new(Some(
|
||||
hooks::SyscallHookResult::Skip(
|
||||
i.extract().expect("Invalid syscall hook return value"),
|
||||
))
|
||||
)
|
||||
} else {
|
||||
SyscallHookResult::extract_bound(ret.bind(py))
|
||||
.expect("The syscall hook must return a SyscallHookResult")
|
||||
let syscall = SyscallHookResult::extract_bound(ret.bind(py))
|
||||
.expect("The syscall hook must return a SyscallHookResult");
|
||||
|
||||
if let Some(ret) = syscall.skip {
|
||||
hooks::SyscallHookResult::Skip(ret)
|
||||
} else {
|
||||
hooks::SyscallHookResult::Run
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user