diff --git a/libafl_frida/src/alloc.rs b/libafl_frida/src/alloc.rs index adc18b9834..8fc13cc96e 100644 --- a/libafl_frida/src/alloc.rs +++ b/libafl_frida/src/alloc.rs @@ -556,12 +556,14 @@ impl Allocator { &mut |range: &RangeDetails| -> bool { let start = range.memory_range().base_address().0 as usize; let end = start + range.memory_range().size(); - - if !self.is_managed(start as *mut c_void) { + //the shadow region should be the highest valid userspace region, so don't continue after + if self.is_managed(start as *mut c_void) { + false + } else { + log::trace!("Unpoisoning: {:#x}-{:#x}", start, end); self.map_shadow_for_region(start, end, true); + true } - - true }, ); } @@ -587,6 +589,14 @@ impl Allocator { &mut |range: &RangeDetails| -> bool { let start = range.memory_range().base_address().0 as usize; let end = start + range.memory_range().size(); + log::trace!("New range: {:#x}-{:#x}", start, end); + + #[cfg(target_vendor = "apple")] + if start >= 0x600000000000 { + //this is the MALLOC_NANO region. There is no point in spending time tracking this region as we hook malloc + return false; + } + occupied_ranges.push((start, end)); // On x64, if end > 2**48, then that's in vsyscall or something. #[cfg(all(unix, target_arch = "x86_64"))] @@ -614,15 +624,17 @@ impl Allocator { #[cfg(windows)] let maxbit = 63; #[cfg(unix)] - for power in 1..64 { + for power in 44..64 { if 2_usize.pow(power) > userspace_max { maxbit = power; break; } } + log::trace!("max bit: {}", maxbit); + { - for try_shadow_bit in 44..maxbit { + for try_shadow_bit in 44..=maxbit { let addr: usize = 1 << try_shadow_bit; let shadow_start = addr; let shadow_end = addr + addr + addr; diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index 55300a7fd8..02a238874d 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -37,7 +37,10 @@ use yaxpeax_arch::Arch; #[cfg(target_arch = "aarch64")] use yaxpeax_arm::armv8::a64::{ARMv8, InstDecoder, Opcode, Operand, ShiftStyle, SizeCode}; #[cfg(target_arch = "x86_64")] -use yaxpeax_x86::amd64::{InstDecoder, Instruction, Opcode}; +use yaxpeax_x86::{ + amd64::{InstDecoder, Instruction, Opcode}, + long_mode::DisplayStyle, +}; #[cfg(target_arch = "x86_64")] use crate::utils::frida_to_cs; @@ -129,10 +132,9 @@ pub struct AsanRuntime { suppressed_addresses: Vec, skip_ranges: Vec, continue_on_error: bool, - pub(crate) hooks: HashMap, - pub(crate) hooks_enabled: bool, pc: Option, - + hooks: Vec, + pub(crate) hooks_enabled: bool, #[cfg(target_arch = "aarch64")] eh_frame: [u32; ASAN_EH_FRAME_DWORD_COUNT], } @@ -163,12 +165,6 @@ impl FridaRuntime for AsanRuntime { AsanErrors::get_mut_blocking().set_continue_on_error(self.continue_on_error); - self.register_hooks(gum); - - self.generate_instrumentation_blobs(); - - self.unpoison_all_existing_memory(); - self.module_map = Some(module_map.clone()); self.suppressed_addresses .extend(self.skip_ranges.iter().map(|skip| match skip { @@ -180,8 +176,17 @@ impl FridaRuntime for AsanRuntime { } })); + self.register_hooks(gum); + self.generate_instrumentation_blobs(); + self.unpoison_all_existing_memory(); + self.register_thread(); } + + fn deinit(&mut self, gum: &Gum) { + self.deregister_hooks(gum); + } + fn pre_exec( &mut self, input: &I, @@ -483,28 +488,33 @@ impl AsanRuntime { #[allow(clippy::too_many_lines)] pub fn register_hooks(&mut self, gum: &Gum) { let mut interceptor = Interceptor::obtain(gum); - macro_rules! hook_func { - ($lib:expr, $name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { + //No library case + ($name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { paste::paste! { log::trace!("Hooking {}", stringify!($name)); - let target_function = frida_gum::Module::find_export_by_name($lib, stringify!($name)).expect("Failed to find function"); - self.hooks.insert(stringify!($name).to_string(), target_function); + let target_function = frida_gum::Module::find_export_by_name(None, stringify!($name)).expect("Failed to find function"); + + static [<$name:snake:upper _PTR>]: std::sync::OnceLock $return_type> = std::sync::OnceLock::new(); + + let _ = [<$name:snake:upper _PTR>].set(unsafe {std::mem::transmute::<*const c_void, extern "C" fn($($param: $param_type),*) -> $return_type>(target_function.0)}).unwrap(); #[allow(non_snake_case)] unsafe extern "C" fn []($($param: $param_type),*) -> $return_type { let mut invocation = Interceptor::current_invocation(); let this = &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime); - // let real_address = this.real_address_for_stalked(invocation.return_addr()); + //is this necessary? The stalked return address will always be the real return address + // let real_address = this.real_address_for_stalked(invocation.return_addr()); + let original = [<$name:snake:upper _PTR>].get().unwrap(); if this.hooks_enabled { let previous_hook_state = this.hooks_enabled; this.hooks_enabled = false; - let ret = this.[]($($param),*); + let ret = this.[](*original, $($param),*); this.hooks_enabled = previous_hook_state; ret } else { - let original = std::mem::transmute::<*const c_void, extern "C" fn($($param: $param_type),*) -> $return_type>(this.hooks.get(&stringify!($name).to_string()).unwrap().0); + let previous_hook_state = this.hooks_enabled; this.hooks_enabled = false; let ret = (original)($($param),*); @@ -512,34 +522,43 @@ impl AsanRuntime { ret } } + + let self_ptr = core::ptr::from_ref(self) as usize; let _ = interceptor.replace( target_function, NativePointer([] as *mut c_void), - NativePointer(core::ptr::from_mut(self) as *mut c_void) + NativePointer(self_ptr as *mut c_void) ); - } - } - } - macro_rules! hook_func_with_check { - ($lib:expr, $name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { + self.hooks.push(target_function); + } + }; + //Library specific macro rule. lib and lib_ident are both needed because we need to generate a unique static variable and only name is insufficient. In addition, the lib name could contain invalid characters (i.e., lib.so is an invalid name) + ($lib:literal, $lib_ident:ident, $name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { paste::paste! { - log::trace!("Hooking {}", stringify!($name)); - let target_function = frida_gum::Module::find_export_by_name($lib, stringify!($name)).expect("Failed to find function"); - self.hooks.insert(stringify!($name).to_string(), target_function); + log::trace!("Hooking {}:{}", $lib, stringify!($name)); + + let target_function = frida_gum::Module::find_export_by_name(Some($lib), stringify!($name)).expect("Failed to find function"); + + static [<$lib_ident:snake:upper _ $name:snake:upper _PTR>]: std::sync::OnceLock $return_type> = std::sync::OnceLock::new(); + + let _ = [<$lib_ident:snake:upper _ $name:snake:upper _PTR>].set(unsafe {std::mem::transmute::<*const c_void, extern "C" fn($($param: $param_type),*) -> $return_type>(target_function.0)}).unwrap(); #[allow(non_snake_case)] unsafe extern "C" fn []($($param: $param_type),*) -> $return_type { let mut invocation = Interceptor::current_invocation(); let this = &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime); - if this.hooks_enabled && this.[]($($param),*) { + //is this necessary? The stalked return address will always be the real return address + // let real_address = this.real_address_for_stalked(invocation.return_addr()); + let original = [<$lib_ident:snake:upper _ $name:snake:upper _PTR>].get().unwrap(); + if this.hooks_enabled { let previous_hook_state = this.hooks_enabled; this.hooks_enabled = false; - let ret = this.[]($($param),*); + let ret = this.[](*original, $($param),*); this.hooks_enabled = previous_hook_state; ret } else { - let original = std::mem::transmute::<*const c_void, extern "C" fn($($param: $param_type),*) -> $return_type>(this.hooks.get(&stringify!($name).to_string()).unwrap().0); + let previous_hook_state = this.hooks_enabled; this.hooks_enabled = false; let ret = (original)($($param),*); @@ -547,35 +566,128 @@ impl AsanRuntime { ret } } + + let self_ptr = core::ptr::from_ref(self) as usize; let _ = interceptor.replace( target_function, NativePointer([] as *mut c_void), - NativePointer(core::ptr::from_mut(self) as *mut c_void) + NativePointer(self_ptr as *mut c_void) ); + + self.hooks.push(target_function); + } + }; + } + + #[allow(unused_macro_rules)] + macro_rules! hook_func_with_check { + //No library case + ($name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { + paste::paste! { + log::trace!("Hooking {}", stringify!($name)); + let target_function = frida_gum::Module::find_export_by_name(None, stringify!($name)).expect("Failed to find function"); + + static [<$name:snake:upper _PTR>]: std::sync::OnceLock $return_type> = std::sync::OnceLock::new(); + + + + let _ = [<$name:snake:upper _PTR>].set(unsafe {std::mem::transmute::<*const c_void, extern "C" fn($($param: $param_type),*) -> $return_type>(target_function.0)}).unwrap_or_else(|e| println!("{:?}", e)); + + #[allow(non_snake_case)] + unsafe extern "C" fn []($($param: $param_type),*) -> $return_type { + let mut invocation = Interceptor::current_invocation(); + let this = &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime); + let original = [<$name:snake:upper _PTR>].get().unwrap(); + + if this.hooks_enabled && this.[]($($param),*){ + let previous_hook_state = this.hooks_enabled; + this.hooks_enabled = false; + let ret = this.[](*original, $($param),*); + this.hooks_enabled = previous_hook_state; + ret + } else { + let previous_hook_state = this.hooks_enabled; + this.hooks_enabled = false; + let ret = (original)($($param),*); + this.hooks_enabled = previous_hook_state; + ret + } + + } + + let self_ptr = core::ptr::from_ref(self) as usize; + let _ = interceptor.replace( + target_function, + NativePointer([] as *mut c_void), + NativePointer(self_ptr as *mut c_void) + ); + self.hooks.push(target_function); + } + }; + //Library specific macro rule. lib and lib_ident are both needed because we need to generate a unique static variable and only name is insufficient. In addition, the lib name could contain invalid characters (i.e., lib.so is an invalid name) + ($lib:literal, $lib_ident:ident, $name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { + paste::paste! { + log::trace!("Hooking {}:{}", $lib, stringify!($name)); + let target_function = frida_gum::Module::find_export_by_name(Some($lib), stringify!($name)).expect("Failed to find function"); + + static [<$lib_ident:snake:upper _ $name:snake:upper _PTR>]: std::sync::OnceLock $return_type> = std::sync::OnceLock::new(); + + + + let _ = [<$lib_ident:snake:upper _ $name:snake:upper _PTR>].set(unsafe {std::mem::transmute::<*const c_void, extern "C" fn($($param: $param_type),*) -> $return_type>(target_function.0)}).unwrap_or_else(|e| println!("{:?}", e)); + + #[allow(non_snake_case)] + unsafe extern "C" fn []($($param: $param_type),*) -> $return_type { + let mut invocation = Interceptor::current_invocation(); + let this = &mut *(invocation.replacement_data().unwrap().0 as *mut AsanRuntime); + let original = [<$lib_ident:snake:upper _ $name:snake:upper _PTR>].get().unwrap(); + + if this.hooks_enabled && this.[]($($param),*){ + let previous_hook_state = this.hooks_enabled; + this.hooks_enabled = false; + let ret = this.[](*original, $($param),*); + this.hooks_enabled = previous_hook_state; + ret + } else { + let previous_hook_state = this.hooks_enabled; + this.hooks_enabled = false; + let ret = (original)($($param),*); + this.hooks_enabled = previous_hook_state; + ret + } + + } + + let self_ptr = core::ptr::from_ref(self) as usize; + let _ = interceptor.replace( + target_function, + NativePointer([] as *mut c_void), + NativePointer(self_ptr as *mut c_void) + ); + self.hooks.push(target_function); } } } // Hook the memory allocator functions #[cfg(not(windows))] - hook_func!(None, malloc, (size: usize), *mut c_void); + hook_func!(malloc, (size: usize), *mut c_void); #[cfg(not(windows))] - hook_func!(None, calloc, (nmemb: usize, size: usize), *mut c_void); + hook_func!(calloc, (nmemb: usize, size: usize), *mut c_void); #[cfg(not(windows))] - hook_func!(None, realloc, (ptr: *mut c_void, size: usize), *mut c_void); + hook_func!(realloc, (ptr: *mut c_void, size: usize), *mut c_void); #[cfg(not(windows))] - hook_func_with_check!(None, free, (ptr: *mut c_void), usize); + hook_func_with_check!(free, (ptr: *mut c_void), usize); #[cfg(not(any(target_vendor = "apple", windows)))] - hook_func!(None, memalign, (size: usize, alignment: usize), *mut c_void); + hook_func!(memalign, (size: usize, alignment: usize), *mut c_void); #[cfg(not(windows))] hook_func!( - None, posix_memalign, (pptr: *mut *mut c_void, size: usize, alignment: usize), i32 ); #[cfg(not(any(target_vendor = "apple", windows)))] - hook_func!(None, malloc_usable_size, (ptr: *mut c_void), usize); + hook_func!(malloc_usable_size, (ptr: *mut c_void), usize); // // #[cfg(windows)] // hook_priv_func!( // "c:\\windows\\system32\\ntdll.dll", @@ -604,56 +716,43 @@ impl AsanRuntime { // (file: usize, file_mapping_attributes: *const c_void, protect: i32, maximum_size_high: u32, maximum_size_low: u32, name: *const c_void), // usize // ); - #[cfg(windows)] - for libname in [ - "ntdll", - "win32u", - "ucrtbase", - "kernelbase", - "kernel32", - "msvcrt", - "api-ms-win-crt-private-l1-1-0", - "api-ms-win-crt-private-l1-1-0.dll", - "api-ms-win-core-heap-l1-1-0", - "api-ms-win-core-heap-l2-1-0", - "api-ms-win-core-heap-obsolete-l1-1-0", - // "vcruntime140", - ] { - log::info!("Hooking allocator functions in {}", libname); - for export in Module::enumerate_exports(libname) { + macro_rules! hook_heap_windows { + ($libname:literal, $lib_ident:ident) => { + log::info!("Hooking allocator functions in {}", $libname); + for export in Module::enumerate_exports($libname) { // log::trace!("- {}", export.name); match &export.name[..] { "NtGdiCreateCompatibleDC" => { - hook_func!(Some(libname), NtGdiCreateCompatibleDC, (hdc: *const c_void), *mut c_void); + hook_func!($libname, $lib_ident, NtGdiCreateCompatibleDC, (hdc: *const c_void), *mut c_void); } "RtlCreateHeap" => { - hook_func!(Some(libname), RtlCreateHeap, (flags: u32, heap_base: *const c_void, reserve_size: usize, commit_size: usize, lock: *const c_void, parameters: *const c_void), *mut c_void); + hook_func!($libname, $lib_ident, RtlCreateHeap, (flags: u32, heap_base: *const c_void, reserve_size: usize, commit_size: usize, lock: *const c_void, parameters: *const c_void), *mut c_void); } "RtlDestroyHeap" => { - hook_func!(Some(libname), RtlDestroyHeap, (handle: *const c_void), *mut c_void); + hook_func!($libname, $lib_ident, RtlDestroyHeap, (handle: *const c_void), *mut c_void); } "HeapAlloc" => { - hook_func!(Some(libname), HeapAlloc, (handle: *mut c_void, flags: u32, bytes: usize), *mut c_void); + hook_func!($libname, $lib_ident, HeapAlloc, (handle: *mut c_void, flags: u32, bytes: usize), *mut c_void); } "RtlAllocateHeap" => { - hook_func!(Some(libname), RtlAllocateHeap, (handle: *mut c_void, flags: u32, bytes: usize), *mut c_void); + hook_func!($libname, $lib_ident, RtlAllocateHeap, (handle: *mut c_void, flags: u32, bytes: usize), *mut c_void); } "HeapFree" => { - hook_func_with_check!(Some(libname), HeapFree, (handle: *mut c_void, flags: u32, mem: *mut c_void), bool); + hook_func_with_check!($libname, $lib_ident, HeapFree, (handle: *mut c_void, flags: u32, mem: *mut c_void), bool); } "RtlFreeHeap" => { - hook_func_with_check!(Some(libname), RtlFreeHeap, (handle: *mut c_void, flags: u32, mem: *mut c_void), usize); + hook_func_with_check!($libname, $lib_ident, RtlFreeHeap, (handle: *mut c_void, flags: u32, mem: *mut c_void), usize); } "HeapSize" => { - hook_func_with_check!(Some(libname), HeapSize, (handle: *mut c_void, flags: u32, mem: *mut c_void), usize); + hook_func_with_check!($libname, $lib_ident, HeapSize, (handle: *mut c_void, flags: u32, mem: *mut c_void), usize); } "RtlSizeHeap" => { - hook_func_with_check!(Some(libname), RtlSizeHeap , (handle: *mut c_void, flags: u32, mem: *mut c_void), usize); + hook_func_with_check!($libname, $lib_ident, RtlSizeHeap , (handle: *mut c_void, flags: u32, mem: *mut c_void), usize); } "RtlReAllocateHeap" => { hook_func!( - Some(libname), + $libname, $lib_ident, RtlReAllocateHeap, ( handle: *mut c_void, @@ -666,7 +765,7 @@ impl AsanRuntime { } "HeapReAlloc" => { hook_func!( - Some(libname), + $libname, $lib_ident, HeapReAlloc, ( handle: *mut c_void, @@ -678,56 +777,56 @@ impl AsanRuntime { ); } "LocalAlloc" => { - hook_func!(Some(libname), LocalAlloc, (flags: u32, size: usize), *mut c_void); + hook_func!($libname, $lib_ident, LocalAlloc, (flags: u32, size: usize), *mut c_void); } "LocalReAlloc" => { - hook_func!(Some(libname), LocalReAlloc, (mem: *mut c_void, size: usize, flags: u32), *mut c_void); + hook_func!($libname, $lib_ident, LocalReAlloc, (mem: *mut c_void, size: usize, flags: u32), *mut c_void); } "LocalHandle" => { - hook_func_with_check!(Some(libname), LocalHandle, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, LocalHandle, (mem: *mut c_void), *mut c_void); } "LocalLock" => { - hook_func_with_check!(Some(libname), LocalLock, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, LocalLock, (mem: *mut c_void), *mut c_void); } "LocalUnlock" => { - hook_func_with_check!(Some(libname), LocalUnlock, (mem: *mut c_void), bool); + hook_func_with_check!($libname, $lib_ident, LocalUnlock, (mem: *mut c_void), bool); } "LocalSize" => { - hook_func_with_check!(Some(libname), LocalSize, (mem: *mut c_void),usize); + hook_func_with_check!($libname, $lib_ident, LocalSize, (mem: *mut c_void),usize); } "LocalFree" => { - hook_func_with_check!(Some(libname), LocalFree, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, LocalFree, (mem: *mut c_void), *mut c_void); } "LocalFlags" => { - hook_func_with_check!(Some(libname), LocalFlags, (mem: *mut c_void),u32); + hook_func_with_check!($libname, $lib_ident, LocalFlags, (mem: *mut c_void),u32); } "GlobalAlloc" => { - hook_func!(Some(libname), GlobalAlloc, (flags: u32, size: usize), *mut c_void); + hook_func!($libname, $lib_ident, GlobalAlloc, (flags: u32, size: usize), *mut c_void); } "GlobalReAlloc" => { - hook_func!(Some(libname), GlobalReAlloc, (mem: *mut c_void, flags: u32, size: usize), *mut c_void); + hook_func!($libname, $lib_ident, GlobalReAlloc, (mem: *mut c_void, flags: u32, size: usize), *mut c_void); } "GlobalHandle" => { - hook_func_with_check!(Some(libname), GlobalHandle, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, GlobalHandle, (mem: *mut c_void), *mut c_void); } "GlobalLock" => { - hook_func_with_check!(Some(libname), GlobalLock, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, GlobalLock, (mem: *mut c_void), *mut c_void); } "GlobalUnlock" => { - hook_func_with_check!(Some(libname), GlobalUnlock, (mem: *mut c_void), bool); + hook_func_with_check!($libname, $lib_ident, GlobalUnlock, (mem: *mut c_void), bool); } "GlobalSize" => { - hook_func_with_check!(Some(libname), GlobalSize, (mem: *mut c_void),usize); + hook_func_with_check!($libname, $lib_ident, GlobalSize, (mem: *mut c_void),usize); } "GlobalFree" => { - hook_func_with_check!(Some(libname), GlobalFree, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, GlobalFree, (mem: *mut c_void), *mut c_void); } "GlobalFlags" => { - hook_func_with_check!(Some(libname), GlobalFlags, (mem: *mut c_void),u32); + hook_func_with_check!($libname, $lib_ident, GlobalFlags, (mem: *mut c_void),u32); } "memmove" => { hook_func!( - Some(libname), + $libname, $lib_ident, memmove, (dest: *mut c_void, src: *const c_void, n: usize), *mut c_void @@ -735,39 +834,39 @@ impl AsanRuntime { } "memcpy" => { hook_func!( - Some(libname), + $libname, $lib_ident, memcpy, (dest: *mut c_void, src: *const c_void, n: usize), *mut c_void ); } "malloc" => { - hook_func!(Some(libname), malloc, (size: usize), *mut c_void); + hook_func!($libname, $lib_ident, malloc, (size: usize), *mut c_void); } "_o_malloc" | "o_malloc" => { - hook_func!(Some(libname), _o_malloc, (size: usize), *mut c_void); + hook_func!($libname, $lib_ident, _o_malloc, (size: usize), *mut c_void); } "calloc" => { - hook_func!(Some(libname), calloc, (nmemb: usize, size: usize), *mut c_void); + hook_func!($libname, $lib_ident, calloc, (nmemb: usize, size: usize), *mut c_void); } "_o_calloc" | "o_calloc" => { - hook_func!(Some(libname), _o_calloc, (nmemb: usize, size: usize), *mut c_void); + hook_func!($libname, $lib_ident, _o_calloc, (nmemb: usize, size: usize), *mut c_void); } "realloc" => { - hook_func!(Some(libname), realloc, (ptr: *mut c_void, size: usize), *mut c_void); + hook_func!($libname, $lib_ident, realloc, (ptr: *mut c_void, size: usize), *mut c_void); } "_o_realloc" | "o_realloc" => { - hook_func!(Some(libname), _o_realloc, (ptr: *mut c_void, size: usize), *mut c_void); + hook_func!($libname, $lib_ident, _o_realloc, (ptr: *mut c_void, size: usize), *mut c_void); } "free" => { - hook_func_with_check!(Some(libname), free, (ptr: *mut c_void), usize); + hook_func_with_check!($libname, $lib_ident, free, (ptr: *mut c_void), usize); } "_o_free" | "o_free" => { - hook_func_with_check!(Some(libname), _o_free, (ptr: *mut c_void), usize); + hook_func_with_check!($libname, $lib_ident, _o_free, (ptr: *mut c_void), usize); } "_write" => { hook_func!( - Some(libname), + $libname, $lib_ident, _write, (fd: i32, buf: *const c_void, count: usize), usize @@ -775,7 +874,7 @@ impl AsanRuntime { } "_read" => { hook_func!( - Some(libname), + $libname, $lib_ident, _read, (fd: i32, buf: *mut c_void, count: usize), usize @@ -783,7 +882,7 @@ impl AsanRuntime { } "MapViewOfFile" => { hook_func!( - Some(libname), + $libname, $lib_ident, MapViewOfFile, (handle: *const c_void, desired_access: u32, file_offset_high: u32, file_offset_low: u32, size: usize), *const c_void @@ -791,7 +890,7 @@ impl AsanRuntime { } "LoadLibraryExW" => { hook_func!( - Some(libname), + $libname, $lib_ident, LoadLibraryExW, (path: *const c_void, file: usize, flags: i32), usize @@ -799,7 +898,7 @@ impl AsanRuntime { } "LdrLoadDll" => { hook_func!( - Some(libname), + $libname, $lib_ident, LdrLoadDll, (search_path: *const c_void, charecteristics: *const u32, dll_name: *const c_void, base_address: *mut *const c_void), usize @@ -808,8 +907,27 @@ impl AsanRuntime { _ => (), } } + } + } + #[cfg(windows)] + { + hook_heap_windows!("ntdll", ntdll); + hook_heap_windows!("win32u", win32u); + hook_heap_windows!("ucrtbase", ucrtbase); + hook_heap_windows!("kernelbase", kernelbase); + hook_heap_windows!("kernel32", kernel32); + hook_heap_windows!("msvcrt", msvcrt); + hook_heap_windows!("api-ms-win-crt-private-l1-1-0", api_ms_win1); + hook_heap_windows!("api-ms-win-crt-private-l1-1-0.dll", api_ms_win2); + hook_heap_windows!("api-ms-win-core-heap-l1-1-0", api_ms_heap1); + hook_heap_windows!("api-ms-win-core-heap-l2-1-0", api_ms_heap2); + hook_heap_windows!( + "api-ms-win-core-heap-obsolete-l1-1-0", + api_ms_heap2_obsolete + ); } + /* #[cfg(target_os = "linux")] let cpp_libs = [ "libc++.so", @@ -822,18 +940,19 @@ impl AsanRuntime { #[cfg(target_vendor = "apple")] let cpp_libs = ["libc++.1.dylib", "libc++abi.dylib", "libsystem_c.dylib"]; + */ - #[cfg(not(windows))] - for libname in cpp_libs { - log::info!("Hooking c++ functions in {}", libname); - for export in Module::enumerate_exports(libname) { + macro_rules! hook_cpp { + ($libname:literal, $lib_ident:ident) => { + log::info!("Hooking c++ functions in {}", $libname); + for export in Module::enumerate_exports($libname) { match &export.name[..] { "_Znam" => { - hook_func!(Some(libname), _Znam, (size: usize), *mut c_void); + hook_func!($libname, $lib_ident, _Znam, (size: usize), *mut c_void); } "_ZnamRKSt9nothrow_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZnamRKSt9nothrow_t, (size: usize, _nothrow: *const c_void), *mut c_void @@ -841,7 +960,7 @@ impl AsanRuntime { } "_ZnamSt11align_val_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZnamSt11align_val_t, (size: usize, alignment: usize), *mut c_void @@ -849,18 +968,18 @@ impl AsanRuntime { } "_ZnamSt11align_val_tRKSt9nothrow_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZnamSt11align_val_tRKSt9nothrow_t, (size: usize, alignment: usize, _nothrow: *const c_void), *mut c_void ); } "_Znwm" => { - hook_func!(Some(libname), _Znwm, (size: usize), *mut c_void); + hook_func!($libname, $lib_ident, _Znwm, (size: usize), *mut c_void); } "_ZnwmRKSt9nothrow_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZnwmRKSt9nothrow_t, (size: usize, _nothrow: *const c_void), *mut c_void @@ -868,7 +987,7 @@ impl AsanRuntime { } "_ZnwmSt11align_val_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZnwmSt11align_val_t, (size: usize, alignment: usize), *mut c_void @@ -876,21 +995,21 @@ impl AsanRuntime { } "_ZnwmSt11align_val_tRKSt9nothrow_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZnwmSt11align_val_tRKSt9nothrow_t, (size: usize, alignment: usize, _nothrow: *const c_void), *mut c_void ); } "_ZdaPv" => { - hook_func!(Some(libname), _ZdaPv, (ptr: *mut c_void), usize); + hook_func!($libname, $lib_ident, _ZdaPv, (ptr: *mut c_void), usize); } "_ZdaPvm" => { - hook_func!(Some(libname), _ZdaPvm, (ptr: *mut c_void, _ulong: u64), usize); + hook_func!($libname, $lib_ident, _ZdaPvm, (ptr: *mut c_void, _ulong: u64), usize); } "_ZdaPvmSt11align_val_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZdaPvmSt11align_val_t, (ptr: *mut c_void, _ulong: u64, _alignment: usize), usize @@ -898,7 +1017,7 @@ impl AsanRuntime { } "_ZdaPvRKSt9nothrow_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZdaPvRKSt9nothrow_t, (ptr: *mut c_void, _nothrow: *const c_void), usize @@ -906,7 +1025,7 @@ impl AsanRuntime { } "_ZdaPvSt11align_val_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZdaPvSt11align_val_t, (ptr: *mut c_void, _alignment: usize), usize @@ -914,21 +1033,21 @@ impl AsanRuntime { } "_ZdaPvSt11align_val_tRKSt9nothrow_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZdaPvSt11align_val_tRKSt9nothrow_t, (ptr: *mut c_void, _alignment: usize, _nothrow: *const c_void), usize ); } "_ZdlPv" => { - hook_func!(Some(libname), _ZdlPv, (ptr: *mut c_void), usize); + hook_func!($libname, $lib_ident, _ZdlPv, (ptr: *mut c_void), usize); } "_ZdlPvm" => { - hook_func!(Some(libname), _ZdlPvm, (ptr: *mut c_void, _ulong: u64), usize); + hook_func!($libname, $lib_ident, _ZdlPvm, (ptr: *mut c_void, _ulong: u64), usize); } "_ZdlPvmSt11align_val_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZdlPvmSt11align_val_t, (ptr: *mut c_void, _ulong: u64, _alignment: usize), usize @@ -936,7 +1055,7 @@ impl AsanRuntime { } "_ZdlPvRKSt9nothrow_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZdlPvRKSt9nothrow_t, (ptr: *mut c_void, _nothrow: *const c_void), usize @@ -944,7 +1063,7 @@ impl AsanRuntime { } "_ZdlPvSt11align_val_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZdlPvSt11align_val_t, (ptr: *mut c_void, _alignment: usize), usize @@ -952,7 +1071,7 @@ impl AsanRuntime { } "_ZdlPvSt11align_val_tRKSt9nothrow_t" => { hook_func!( - Some(libname), + $libname, $lib_ident, _ZdlPvSt11align_val_tRKSt9nothrow_t, (ptr: *mut c_void, _alignment: usize, _nothrow: *const c_void), usize @@ -961,10 +1080,28 @@ impl AsanRuntime { _ => {} } } + } } + #[cfg(target_os = "linux")] + { + hook_cpp!("libc++.so", libcpp); + hook_cpp!("libc++.so.1", libcpp1); + hook_cpp!("libc++.so.1", libcpp1); + hook_cpp!("libc++abi.so.1", libcppapi); + hook_cpp!("libc++_shared.so", libcppshared); + hook_cpp!("libstdc++.so", libstdcpp); + hook_cpp!("libstdc++.so.6", libstdcpp6); + } + + #[cfg(target_vendor = "apple")] + { + hook_cpp!("libc++.1.dylib", libcpp_darwin); + hook_cpp!("libc++abi.dylib", libcppabi_darwin); + hook_cpp!("libsystem_c.dylib", libsystem_c_darwin); + } + #[cfg(not(windows))] hook_func!( - None, mmap, ( addr: *const c_void, @@ -977,39 +1114,34 @@ impl AsanRuntime { *mut c_void ); #[cfg(not(windows))] - hook_func!(None, munmap, (addr: *const c_void, length: usize), i32); + hook_func!(munmap, (addr: *const c_void, length: usize), i32); // Hook libc functions which may access allocated memory #[cfg(not(windows))] hook_func!( - None, write, (fd: i32, buf: *const c_void, count: usize), usize ); #[cfg(not(windows))] - hook_func!(None, read, (fd: i32, buf: *mut c_void, count: usize), usize); + hook_func!(read, (fd: i32, buf: *mut c_void, count: usize), usize); hook_func!( - None, fgets, (s: *mut c_void, size: u32, stream: *mut c_void), *mut c_void ); hook_func!( - None, memcmp, (s1: *const c_void, s2: *const c_void, n: usize), i32 ); hook_func!( - None, memcpy, (dest: *mut c_void, src: *const c_void, n: usize), *mut c_void ); #[cfg(not(any(target_vendor = "apple", windows)))] hook_func!( - None, mempcpy, (dest: *mut c_void, src: *const c_void, n: usize), *mut c_void @@ -1022,27 +1154,23 @@ impl AsanRuntime { // *mut c_void // ); hook_func!( - None, memset, (s: *mut c_void, c: i32, n: usize), *mut c_void ); hook_func!( - None, memchr, (s: *mut c_void, c: i32, n: usize), *mut c_void ); #[cfg(not(any(target_vendor = "apple", windows)))] hook_func!( - None, memrchr, (s: *mut c_void, c: i32, n: usize), *mut c_void ); #[cfg(not(windows))] hook_func!( - None, memmem, ( haystack: *const c_void, @@ -1053,9 +1181,9 @@ impl AsanRuntime { *mut c_void ); #[cfg(not(any(target_os = "android", windows)))] - hook_func!(None, bzero, (s: *mut c_void, n: usize), usize); + hook_func!(bzero, (s: *mut c_void, n: usize), usize); #[cfg(not(any(target_os = "android", target_vendor = "apple", windows)))] - hook_func!(None, explicit_bzero, (s: *mut c_void, n: usize),usize); + hook_func!(explicit_bzero, (s: *mut c_void, n: usize),usize); // #[cfg(not(any(target_os = "android", windows)))] // hook_func!( // None, @@ -1063,112 +1191,114 @@ impl AsanRuntime { // (s1: *const c_void, s2: *const c_void, n: usize), // i32 // ); - hook_func!(None, strchr, (s: *mut c_char, c: i32), *mut c_char); - hook_func!(None, strrchr, (s: *mut c_char, c: i32), *mut c_char); + hook_func!(strchr, (s: *mut c_char, c: i32), *mut c_char); + hook_func!(strrchr, (s: *mut c_char, c: i32), *mut c_char); #[cfg(not(windows))] hook_func!( - None, strcasecmp, (s1: *const c_char, s2: *const c_char), i32 ); #[cfg(not(windows))] hook_func!( - None, strncasecmp, (s1: *const c_char, s2: *const c_char, n: usize), i32 ); hook_func!( - None, strcat, (dest: *mut c_char, src: *const c_char), *mut c_char ); - hook_func!(None, strcmp, (s1: *const c_char, s2: *const c_char), i32); + hook_func!(strcmp, (s1: *const c_char, s2: *const c_char), i32); hook_func!( - None, strncmp, (s1: *const c_char, s2: *const c_char, n: usize), i32 ); hook_func!( - None, strcpy, (dest: *mut c_char, src: *const c_char), *mut c_char ); hook_func!( - None, strncpy, (dest: *mut c_char, src: *const c_char, n: usize), *mut c_char ); #[cfg(not(windows))] hook_func!( - None, stpcpy, (dest: *mut c_char, src: *const c_char), *mut c_char ); #[cfg(not(windows))] - hook_func!(None, strdup, (s: *const c_char), *mut c_char); + hook_func!(strdup, (s: *const c_char), *mut c_char); #[cfg(windows)] - hook_func!(None, _strdup, (s: *const c_char), *mut c_char); - hook_func!(None, strlen, (s: *const c_char), usize); - hook_func!(None, strnlen, (s: *const c_char, n: usize), usize); + hook_func!(_strdup, (s: *const c_char), *mut c_char); + hook_func!(strlen, (s: *const c_char), usize); + hook_func!(strnlen, (s: *const c_char, n: usize), usize); hook_func!( - None, strstr, (haystack: *const c_char, needle: *const c_char), *mut c_char ); #[cfg(not(windows))] hook_func!( - None, strcasestr, (haystack: *const c_char, needle: *const c_char), *mut c_char ); - hook_func!(None, atoi, (nptr: *const c_char), i32); - hook_func!(None, atol, (nptr: *const c_char), i32); - hook_func!(None, atoll, (nptr: *const c_char), i64); - hook_func!(None, wcslen, (s: *const wchar_t), usize); + hook_func!(atoi, (nptr: *const c_char), i32); + hook_func!(atol, (nptr: *const c_char), i32); + hook_func!(atoll, (nptr: *const c_char), i64); + hook_func!(wcslen, (s: *const wchar_t), usize); hook_func!( - None, wcscpy, (dest: *mut wchar_t, src: *const wchar_t), *mut wchar_t ); - hook_func!(None, wcscmp, (s1: *const wchar_t, s2: *const wchar_t), i32); + hook_func!(wcscmp, (s1: *const wchar_t, s2: *const wchar_t), i32); #[cfg(target_vendor = "apple")] hook_func!( - None, memset_pattern4, (s: *mut c_void, c: *const c_void, n: usize), () ); #[cfg(target_vendor = "apple")] hook_func!( - None, memset_pattern8, (s: *mut c_void, c: *const c_void, n: usize), () ); #[cfg(target_vendor = "apple")] hook_func!( - None, memset_pattern16, (s: *mut c_void, c: *const c_void, n: usize), () ); } + /// Deregister all the hooks + fn deregister_hooks(&mut self, gum: &Gum) { + /*This is terrible code and should be replaced as soon as possible. + + This is basically a bandaid solution that happens to work because 2 different Interceptor::obtains will return the same interceptor. + + Ideally the interceptor should be stored in AsanRuntime, but because FridaRuntime has a 'static bound it becomes difficult to introduce that. + */ + let mut interceptor = Interceptor::obtain(gum); + for hook in &self.hooks { + interceptor.revert(*hook); + } + } + #[cfg(target_arch = "x86_64")] #[allow(clippy::cast_sign_loss)] #[allow(clippy::too_many_lines)] extern "system" fn handle_trap(&mut self) { - self.hooks_enabled = false; + self.disable_hooks(); + self.dump_registers(); let fault_address = self.regs[17]; @@ -1183,7 +1313,10 @@ impl AsanRuntime { ); let insn = instructions[0]; // This is the very instruction that has triggered fault - log::info!("{insn:#?}"); + log::info!( + "Fault Instruction: {}", + insn.display_with(DisplayStyle::Intel).to_string() + ); let operand_count = insn.operand_count(); let mut access_type: Option = None; @@ -1327,12 +1460,14 @@ impl AsanRuntime { // std::thread::sleep(std::time::Duration::from_secs(60)); // self.dump_registers(); + self.enable_hooks(); } #[cfg(target_arch = "aarch64")] #[allow(clippy::cast_sign_loss)] // for displacement #[allow(clippy::too_many_lines)] extern "system" fn handle_trap(&mut self) { + self.disable_hooks(); let mut actual_pc = self.regs[31]; actual_pc = match self.stalked_addresses.get(&actual_pc) { //get the pc associated with the trapped insn @@ -1449,6 +1584,7 @@ impl AsanRuntime { )) }; AsanErrors::get_mut_blocking().report_error(error); + self.enable_hooks(); } #[cfg(target_arch = "x86_64")] @@ -1615,7 +1751,7 @@ impl AsanRuntime { let mut ops = dynasmrt::VecAssembler::::new(0); shadow_check!(ops, bit); let ops_vec = ops.finalize().unwrap(); - ops_vec[..ops_vec.len() - 10].to_vec().into_boxed_slice() //subtract 10 because + ops_vec[..ops_vec.len() - 10].to_vec().into_boxed_slice() //subtract 10 because we don't need the last nop } #[cfg(target_arch = "aarch64")] @@ -2473,6 +2609,7 @@ impl AsanRuntime { .to_le_bytes(), ); //add x0, x0, w1, [shift] #[amount] } else if shift_encoding != -1 { + //https://developer.arm.com/documentation/ddi0602/2024-03/Base-Instructions/ADD--shifted-register---Add--shifted-register-- add shifted register #[allow(clippy::cast_sign_loss)] writer.put_bytes( &(0x8b010000 | ((shift_encoding as u32) << 22) | (shift_amount << 10)) @@ -2518,7 +2655,7 @@ impl AsanRuntime { Aarch64Register::X0, Aarch64Register::X0, u64::from(displacement_lo), - ); //sub x0, x0, #[displacement 496] + ); //sub x0, x0, #[displacement 4096] } } else if displacement > 0 { #[allow(clippy::cast_sign_loss)] @@ -2607,11 +2744,11 @@ impl Default for AsanRuntime { suppressed_addresses: Vec::new(), skip_ranges: Vec::new(), continue_on_error: false, - hooks: HashMap::new(), - hooks_enabled: false, #[cfg(target_arch = "aarch64")] eh_frame: [0; ASAN_EH_FRAME_DWORD_COUNT], pc: None, + hooks: Vec::new(), + hooks_enabled: false, } } } diff --git a/libafl_frida/src/asan/hook_funcs.rs b/libafl_frida/src/asan/hook_funcs.rs index d59dbfda44..6dccfe3df9 100644 --- a/libafl_frida/src/asan/hook_funcs.rs +++ b/libafl_frida/src/asan/hook_funcs.rs @@ -17,7 +17,11 @@ impl AsanRuntime { #[inline] #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_NtGdiCreateCompatibleDC(&mut self, _hdc: *const c_void) -> *mut c_void { + pub fn hook_NtGdiCreateCompatibleDC( + &mut self, + _original: extern "C" fn(_hdc: *const c_void) -> *mut c_void, + _hdc: *const c_void, + ) -> *mut c_void { unsafe { self.allocator_mut().alloc(8, 8) } } @@ -26,6 +30,14 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_CreateThread( &mut self, + original: extern "C" fn( + thread_attributes: *const c_void, + stack_size: usize, + start_address: *const c_void, + parameter: *const c_void, + creation_flags: i32, + thread_id: *mut i32, + ) -> usize, thread_attributes: *const c_void, stack_size: usize, start_address: *const c_void, @@ -33,32 +45,28 @@ impl AsanRuntime { creation_flags: i32, thread_id: *mut i32, ) -> usize { - extern "system" { - fn CreateThread( - thread_attributes: *const c_void, - stack_size: usize, - start_address: *const c_void, - parameter: *const c_void, - creation_flags: i32, - thread_id: *mut i32, - ) -> usize; - } - unsafe { - CreateThread( - thread_attributes, - stack_size, - start_address, - parameter, - creation_flags, - thread_id, - ) - } + original( + thread_attributes, + stack_size, + start_address, + parameter, + creation_flags, + thread_id, + ) } #[inline] #[allow(non_snake_case)] #[cfg(windows)] pub fn hook_CreateFileMappingW( &mut self, + original: extern "C" fn( + file: usize, + file_mapping_attributes: *const c_void, + protect: i32, + maximum_size_high: u32, + maximum_size_low: u32, + name: *const c_void, + ) -> usize, file: usize, file_mapping_attributes: *const c_void, protect: i32, @@ -66,49 +74,36 @@ impl AsanRuntime { maximum_size_low: u32, name: *const c_void, ) -> usize { - extern "system" { - fn CreateFileMappingW( - file: usize, - file_mapping_attributes: *const c_void, - protect: i32, - maximum_size_high: u32, - maximum_size_low: u32, - name: *const c_void, - ) -> usize; - } - winsafe::OutputDebugString("In CreateFileMapping\n"); - unsafe { - CreateFileMappingW( - file, - file_mapping_attributes, - protect, - maximum_size_high, - maximum_size_low, - name, - ) - } + // winsafe::OutputDebugString("In CreateFileMapping\n"); + original( + file, + file_mapping_attributes, + protect, + maximum_size_high, + maximum_size_low, + name, + ) } #[inline] #[allow(non_snake_case)] #[cfg(windows)] pub fn hook_LdrLoadDll( &mut self, + original: extern "C" fn( + search_path: *const c_void, + charecteristics: *const u32, + dll_name: *const c_void, + base_address: *mut *const c_void, + ) -> usize, search_path: *const c_void, charecteristics: *const u32, dll_name: *const c_void, base_address: *mut *const c_void, ) -> usize { - extern "system" { - fn LdrLoadDll( - search_path: *const c_void, - charecteristics: *const u32, - dll_name: *const c_void, - base_address: *mut *const c_void, - ) -> usize; - } - winsafe::OutputDebugString("LdrLoadDll"); + // winsafe::OutputDebugString("LdrLoadDll"); log::trace!("LdrLoadDll"); - let result = unsafe { LdrLoadDll(search_path, charecteristics, dll_name, base_address) }; + let result = original(search_path, charecteristics, dll_name, base_address); + self.allocator_mut().unpoison_all_existing_memory(); result } @@ -117,12 +112,18 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_LdrpCallInitRoutine( &mut self, + _original: extern "C" fn( + _base_address: *const c_void, + _reason: usize, + _base_address: *const c_void, + _entry_point: usize, + ) -> usize, _base_address: *const c_void, _reason: usize, _context: usize, _entry_point: usize, ) -> usize { - winsafe::OutputDebugString("LdrpCallInitRoutine"); + // winsafe::OutputDebugString("LdrpCallInitRoutine"); // let result = unsafe { LdrLoadDll(path, file, flags,x )}; // self.allocator_mut().unpoison_all_existing_memory(); // result @@ -131,12 +132,16 @@ impl AsanRuntime { #[inline] #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LoadLibraryExW(&mut self, path: *const c_void, file: usize, flags: i32) -> usize { + pub fn hook_LoadLibraryExW( + &mut self, + original: extern "C" fn(path: *const c_void, file: usize, flags: i32) -> usize, + path: *const c_void, + file: usize, + flags: i32, + ) -> usize { log::trace!("Loaded library!"); - extern "system" { - fn LoadLibraryExW(path: *const c_void, file: usize, flags: i32) -> usize; - } - let result = unsafe { LoadLibraryExW(path, file, flags) }; + + let result = original(path, file, flags); self.allocator_mut().unpoison_all_existing_memory(); result } @@ -146,6 +151,14 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_RtlCreateHeap( &mut self, + _original: extern "C" fn( + _flags: u32, + _heap_base: *const c_void, + _reserve_size: usize, + _commit_size: usize, + _lock: *const c_void, + _parameters: *const c_void, + ) -> *mut c_void, _flags: u32, _heap_base: *const c_void, _reserve_size: usize, @@ -158,14 +171,24 @@ impl AsanRuntime { #[inline] #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_RtlDestroyHeap(&mut self, _handle: *const c_void) -> *mut c_void { + pub fn hook_RtlDestroyHeap( + &mut self, + _original: extern "C" fn(_handle: *const c_void) -> *mut c_void, + _handle: *const c_void, + ) -> *mut c_void { std::ptr::null_mut() } #[inline] #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_HeapAlloc(&mut self, _handle: *mut c_void, flags: u32, size: usize) -> *mut c_void { + pub fn hook_HeapAlloc( + &mut self, + _original: extern "C" fn(_handle: *mut c_void, flags: u32, size: usize) -> *mut c_void, + _handle: *mut c_void, + flags: u32, + size: usize, + ) -> *mut c_void { let allocator = self.allocator_mut(); let ret = unsafe { allocator.alloc(size, 8) }; @@ -187,6 +210,7 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_RtlAllocateHeap( &mut self, + _original: extern "C" fn(_handle: *mut c_void, flags: u32, size: usize) -> *mut c_void, _handle: *mut c_void, flags: u32, size: usize, @@ -212,6 +236,12 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_HeapReAlloc( &mut self, + original: extern "C" fn( + handle: *mut c_void, + flags: u32, + ptr: *mut c_void, + size: usize, + ) -> *mut c_void, handle: *mut c_void, flags: u32, ptr: *mut c_void, @@ -219,15 +249,7 @@ impl AsanRuntime { ) -> *mut c_void { let allocator = self.allocator_mut(); if !allocator.is_managed(ptr) { - extern "system" { - fn HeapReAlloc( - handle: *mut c_void, - flags: u32, - ptr: *mut c_void, - size: usize, - ) -> *mut c_void; - } - return unsafe { HeapReAlloc(handle, flags, ptr, size) }; + return original(handle, flags, ptr, size); } let ret = unsafe { let ret = allocator.alloc(size, 8); @@ -260,6 +282,12 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_RtlReAllocateHeap( &mut self, + original: extern "C" fn( + handle: *mut c_void, + flags: u32, + ptr: *mut c_void, + size: usize, + ) -> *mut c_void, handle: *mut c_void, flags: u32, ptr: *mut c_void, @@ -268,15 +296,7 @@ impl AsanRuntime { let allocator = self.allocator_mut(); log::trace!("RtlReAllocateHeap({ptr:?}, {size:x})"); if !allocator.is_managed(ptr) { - extern "system" { - fn HeapReAlloc( - handle: *mut c_void, - flags: u32, - ptr: *mut c_void, - size: usize, - ) -> *mut c_void; - } - return unsafe { HeapReAlloc(handle, flags, ptr, size) }; + return original(handle, flags, ptr, size); } let ret = unsafe { let ret = allocator.alloc(size, 8); @@ -320,6 +340,7 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_RtlFreeHeap( &mut self, + _original: extern "C" fn(_handle: *mut c_void, _flags: u32, ptr: *mut c_void) -> usize, _handle: *mut c_void, _flags: u32, ptr: *mut c_void, @@ -341,7 +362,13 @@ impl AsanRuntime { #[inline] #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_HeapFree(&mut self, _handle: *mut c_void, _flags: u32, ptr: *mut c_void) -> bool { + pub fn hook_HeapFree( + &mut self, + _original: extern "C" fn(_handle: *mut c_void, _flags: u32, ptr: *mut c_void) -> bool, + _handle: *mut c_void, + _flags: u32, + ptr: *mut c_void, + ) -> bool { unsafe { self.allocator_mut().release(ptr) }; true } @@ -359,7 +386,13 @@ impl AsanRuntime { #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_HeapSize(&mut self, _handle: *mut c_void, _flags: u32, ptr: *mut c_void) -> usize { + pub fn hook_HeapSize( + &mut self, + _original: extern "C" fn(_handle: *mut c_void, _flags: u32, ptr: *mut c_void) -> usize, + _handle: *mut c_void, + _flags: u32, + ptr: *mut c_void, + ) -> usize { self.allocator().get_usable_size(ptr) } #[inline] @@ -378,6 +411,7 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_RtlSizeHeap( &mut self, + _original: extern "C" fn(_handle: *mut c_void, _flags: u32, ptr: *mut c_void) -> usize, _handle: *mut c_void, _flags: u32, ptr: *mut c_void, @@ -400,6 +434,7 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_RtlValidateHeap( &mut self, + _original: extern "C" fn(_handle: *mut c_void, _flags: u32, _ptr: *mut c_void) -> bool, _handle: *mut c_void, _flags: u32, _ptr: *mut c_void, @@ -409,7 +444,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LocalAlloc(&mut self, flags: u32, size: usize) -> *mut c_void { + pub fn hook_LocalAlloc( + &mut self, + _original: extern "C" fn(flags: u32, size: usize) -> *mut c_void, + flags: u32, + size: usize, + ) -> *mut c_void { let ret = unsafe { self.allocator_mut().alloc(size, 8) }; if flags & 0x40 == 0x40 { @@ -424,7 +464,13 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LocalReAlloc(&mut self, mem: *mut c_void, size: usize, _flags: u32) -> *mut c_void { + pub fn hook_LocalReAlloc( + &mut self, + _original: extern "C" fn(mem: *mut c_void, size: usize, _flags: u32) -> *mut c_void, + mem: *mut c_void, + size: usize, + _flags: u32, + ) -> *mut c_void { unsafe { let ret = self.allocator_mut().alloc(size, 0x8); if mem != std::ptr::null_mut() && ret != std::ptr::null_mut() { @@ -445,7 +491,11 @@ impl AsanRuntime { #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LocalFree(&mut self, mem: *mut c_void) -> *mut c_void { + pub fn hook_LocalFree( + &mut self, + _original: extern "C" fn(mem: *mut c_void) -> *mut c_void, + mem: *mut c_void, + ) -> *mut c_void { unsafe { self.allocator_mut().release(mem) }; mem } @@ -457,7 +507,11 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LocalHandle(&mut self, mem: *mut c_void) -> *mut c_void { + pub fn hook_LocalHandle( + &mut self, + _soriginal: extern "C" fn(mem: *mut c_void) -> *mut c_void, + mem: *mut c_void, + ) -> *mut c_void { mem } #[allow(non_snake_case)] @@ -468,7 +522,11 @@ impl AsanRuntime { #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LocalLock(&mut self, mem: *mut c_void) -> *mut c_void { + pub fn hook_LocalLock( + &mut self, + _original: extern "C" fn(mem: *mut c_void) -> *mut c_void, + mem: *mut c_void, + ) -> *mut c_void { mem } #[allow(non_snake_case)] @@ -478,7 +536,11 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LocalUnlock(&mut self, _mem: *mut c_void) -> bool { + pub fn hook_LocalUnlock( + &mut self, + _original: extern "C" fn(_mem: *mut c_void) -> bool, + _mem: *mut c_void, + ) -> bool { false } #[allow(non_snake_case)] @@ -488,7 +550,11 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LocalSize(&mut self, mem: *mut c_void) -> usize { + pub fn hook_LocalSize( + &mut self, + _original: extern "C" fn(mem: *mut c_void) -> usize, + mem: *mut c_void, + ) -> usize { self.allocator_mut().get_usable_size(mem) } #[allow(non_snake_case)] @@ -498,13 +564,22 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_LocalFlags(&mut self, _mem: *mut c_void) -> u32 { + pub fn hook_LocalFlags( + &mut self, + _original: extern "C" fn(_mem: *mut c_void) -> u32, + _mem: *mut c_void, + ) -> u32 { 0 } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_GlobalAlloc(&mut self, flags: u32, size: usize) -> *mut c_void { + pub fn hook_GlobalAlloc( + &mut self, + _original: extern "C" fn(flags: u32, size: usize) -> *mut c_void, + flags: u32, + size: usize, + ) -> *mut c_void { let ret = unsafe { self.allocator_mut().alloc(size, 8) }; if flags & 0x40 == 0x40 { @@ -521,6 +596,7 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_GlobalReAlloc( &mut self, + _original: extern "C" fn(mem: *mut c_void, _flags: u32, size: usize) -> *mut c_void, mem: *mut c_void, _flags: u32, size: usize, @@ -543,7 +619,11 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_GlobalFree(&mut self, mem: *mut c_void) -> *mut c_void { + pub fn hook_GlobalFree( + &mut self, + _original: extern "C" fn(mem: *mut c_void) -> *mut c_void, + mem: *mut c_void, + ) -> *mut c_void { unsafe { self.allocator_mut().release(mem) }; mem } @@ -555,7 +635,11 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_GlobalHandle(&mut self, mem: *mut c_void) -> *mut c_void { + pub fn hook_GlobalHandle( + &mut self, + _original: extern "C" fn(mem: *mut c_void) -> *mut c_void, + mem: *mut c_void, + ) -> *mut c_void { mem } #[allow(non_snake_case)] @@ -566,7 +650,11 @@ impl AsanRuntime { #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_GlobalLock(&mut self, mem: *mut c_void) -> *mut c_void { + pub fn hook_GlobalLock( + &mut self, + _original: extern "C" fn(mem: *mut c_void) -> *mut c_void, + mem: *mut c_void, + ) -> *mut c_void { mem } #[allow(non_snake_case)] @@ -576,7 +664,11 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_GlobalUnlock(&mut self, _mem: *mut c_void) -> bool { + pub fn hook_GlobalUnlock( + &mut self, + _original: extern "C" fn(_mem: *mut c_void) -> bool, + _mem: *mut c_void, + ) -> bool { false } #[allow(non_snake_case)] @@ -586,7 +678,11 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_GlobalSize(&mut self, mem: *mut c_void) -> usize { + pub fn hook_GlobalSize( + &mut self, + _original: extern "C" fn(mem: *mut c_void) -> usize, + mem: *mut c_void, + ) -> usize { self.allocator_mut().get_usable_size(mem) } #[allow(non_snake_case)] @@ -596,23 +692,39 @@ impl AsanRuntime { } #[allow(non_snake_case)] #[cfg(windows)] - pub fn hook_GlobalFlags(&mut self, _mem: *mut c_void) -> u32 { + pub fn hook_GlobalFlags( + &mut self, + _original: extern "C" fn(mem: *mut c_void) -> u32, + _mem: *mut c_void, + ) -> u32 { 0 } #[inline] - pub fn hook_malloc(&mut self, size: usize) -> *mut c_void { + pub fn hook_malloc( + &mut self, + _original: extern "C" fn(size: usize) -> *mut c_void, + size: usize, + ) -> *mut c_void { unsafe { self.allocator_mut().alloc(size, 8) } } #[inline] - pub fn hook_o_malloc(&mut self, size: usize) -> *mut c_void { + pub fn hook_o_malloc( + &mut self, + _original: extern "C" fn(size: usize) -> *mut c_void, + size: usize, + ) -> *mut c_void { unsafe { self.allocator_mut().alloc(size, 8) } } #[allow(non_snake_case)] #[inline] - pub fn hook__Znam(&mut self, size: usize) -> *mut c_void { + pub fn hook__Znam( + &mut self, + _original: extern "C" fn(size: usize) -> *mut c_void, + size: usize, + ) -> *mut c_void { unsafe { self.allocator_mut().alloc(size, 8) } } @@ -620,6 +732,7 @@ impl AsanRuntime { #[inline] pub fn hook__ZnamRKSt9nothrow_t( &mut self, + _original: extern "C" fn(size: usize, _nothrow: *const c_void) -> *mut c_void, size: usize, _nothrow: *const c_void, ) -> *mut c_void { @@ -628,7 +741,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[inline] - pub fn hook__ZnamSt11align_val_t(&mut self, size: usize, alignment: usize) -> *mut c_void { + pub fn hook__ZnamSt11align_val_t( + &mut self, + _original: extern "C" fn(size: usize, alignment: usize) -> *mut c_void, + size: usize, + alignment: usize, + ) -> *mut c_void { unsafe { self.allocator_mut().alloc(size, alignment) } } @@ -636,6 +754,11 @@ impl AsanRuntime { #[inline] pub fn hook__ZnamSt11align_val_tRKSt9nothrow_t( &mut self, + _original: extern "C" fn( + size: usize, + alignment: usize, + _nothrow: *const c_void, + ) -> *mut c_void, size: usize, alignment: usize, _nothrow: *const c_void, @@ -645,7 +768,11 @@ impl AsanRuntime { #[allow(non_snake_case)] #[inline] - pub fn hook__Znwm(&mut self, size: usize) -> *mut c_void { + pub fn hook__Znwm( + &mut self, + _original: extern "C" fn(size: usize) -> *mut c_void, + size: usize, + ) -> *mut c_void { let result = unsafe { self.allocator_mut().alloc(size, 8) }; if result.is_null() { extern "system" { @@ -665,6 +792,7 @@ impl AsanRuntime { #[inline] pub fn hook__ZnwmRKSt9nothrow_t( &mut self, + _original: extern "C" fn(size: usize, _nothrow: *const c_void) -> *mut c_void, size: usize, _nothrow: *const c_void, ) -> *mut c_void { @@ -673,7 +801,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[inline] - pub fn hook__ZnwmSt11align_val_t(&mut self, size: usize, alignment: usize) -> *mut c_void { + pub fn hook__ZnwmSt11align_val_t( + &mut self, + _original: extern "C" fn(size: usize, alignment: usize) -> *mut c_void, + size: usize, + alignment: usize, + ) -> *mut c_void { let result = unsafe { self.allocator_mut().alloc(size, alignment) }; if result.is_null() { extern "system" { @@ -691,6 +824,11 @@ impl AsanRuntime { #[inline] pub fn hook__ZnwmSt11align_val_tRKSt9nothrow_t( &mut self, + _original: extern "C" fn( + size: usize, + alignment: usize, + _nothrow: *const c_void, + ) -> *mut c_void, size: usize, alignment: usize, _nothrow: *const c_void, @@ -700,11 +838,20 @@ impl AsanRuntime { #[allow(non_snake_case)] #[inline] - pub fn hook__o_malloc(&mut self, size: usize) -> *mut c_void { + pub fn hook__o_malloc( + &mut self, + _original: extern "C" fn(size: usize) -> *mut c_void, + size: usize, + ) -> *mut c_void { unsafe { self.allocator_mut().alloc(size, 8) } } #[inline] - pub fn hook_calloc(&mut self, nmemb: usize, size: usize) -> *mut c_void { + pub fn hook_calloc( + &mut self, + _original: extern "C" fn(nmemb: usize, size: usize) -> *mut c_void, + nmemb: usize, + size: usize, + ) -> *mut c_void { extern "system" { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } @@ -717,7 +864,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[inline] - pub fn hook__o_calloc(&mut self, nmemb: usize, size: usize) -> *mut c_void { + pub fn hook__o_calloc( + &mut self, + _original: extern "C" fn(nmemb: usize, size: usize) -> *mut c_void, + nmemb: usize, + size: usize, + ) -> *mut c_void { extern "system" { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } @@ -731,7 +883,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[inline] #[allow(clippy::cmp_null)] - pub fn hook_realloc(&mut self, ptr: *mut c_void, size: usize) -> *mut c_void { + pub fn hook_realloc( + &mut self, + _original: extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void, + ptr: *mut c_void, + size: usize, + ) -> *mut c_void { unsafe { let ret = self.allocator_mut().alloc(size, 0x8); if ptr != std::ptr::null_mut() && ret != std::ptr::null_mut() { @@ -747,7 +904,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[inline] #[allow(clippy::cmp_null)] - pub fn hook__o_realloc(&mut self, ptr: *mut c_void, size: usize) -> *mut c_void { + pub fn hook__o_realloc( + &mut self, + _original: extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void, + ptr: *mut c_void, + size: usize, + ) -> *mut c_void { unsafe { let ret = self.allocator_mut().alloc(size, 0x8); if ptr != std::ptr::null_mut() && ret != std::ptr::null_mut() { @@ -769,7 +931,11 @@ impl AsanRuntime { #[allow(non_snake_case)] #[inline] #[allow(clippy::cmp_null)] - pub fn hook__o_free(&mut self, ptr: *mut c_void) -> usize { + pub fn hook__o_free( + &mut self, + _original: extern "C" fn(ptr: *mut c_void) -> usize, + ptr: *mut c_void, + ) -> usize { if ptr != std::ptr::null_mut() { unsafe { self.allocator_mut().release(ptr) } } @@ -782,7 +948,11 @@ impl AsanRuntime { #[inline] #[allow(clippy::cmp_null)] - pub fn hook_free(&mut self, ptr: *mut c_void) -> usize { + pub fn hook_free( + &mut self, + _original: extern "C" fn(ptr: *mut c_void) -> usize, + ptr: *mut c_void, + ) -> usize { if ptr != std::ptr::null_mut() { unsafe { self.allocator_mut().release(ptr) } } @@ -791,13 +961,19 @@ impl AsanRuntime { #[cfg(not(target_vendor = "apple"))] #[inline] - pub fn hook_memalign(&mut self, alignment: usize, size: usize) -> *mut c_void { + pub fn hook_memalign( + &mut self, + _original: extern "C" fn(alignment: usize, size: usize) -> *mut c_void, + alignment: usize, + size: usize, + ) -> *mut c_void { unsafe { self.allocator_mut().alloc(size, alignment) } } #[inline] pub fn hook_posix_memalign( &mut self, + _original: extern "C" fn(pptr: *mut *mut c_void, alignment: usize, size: usize) -> i32, pptr: *mut *mut c_void, alignment: usize, size: usize, @@ -810,7 +986,11 @@ impl AsanRuntime { #[inline] #[cfg(not(target_vendor = "apple"))] - pub fn hook_malloc_usable_size(&mut self, ptr: *mut c_void) -> usize { + pub fn hook_malloc_usable_size( + &mut self, + _original: extern "C" fn(ptr: *mut c_void) -> usize, + ptr: *mut c_void, + ) -> usize { self.allocator_mut().get_usable_size(ptr) } @@ -819,15 +999,20 @@ impl AsanRuntime { #[cfg(windows)] pub fn hook_MapViewOfFile( &mut self, + original: extern "C" fn( + handle: *const c_void, + desired_access: u32, + file_offset_high: u32, + file_offset_low: u32, + size: usize, + ) -> *const c_void, _handle: *const c_void, _desired_access: u32, _file_offset_high: u32, _file_offset_low: u32, size: usize, ) -> *const c_void { - let original: extern "C" fn(*const c_void, u32, u32, u32, usize) -> *const c_void = - unsafe { std::mem::transmute(self.hooks.get(&"MapViewOfFile".to_string()).unwrap().0) }; - let ret = (original)( + let ret = original( _handle, _desired_access, _file_offset_high, @@ -841,7 +1026,11 @@ impl AsanRuntime { #[allow(non_snake_case)] #[allow(clippy::cmp_null)] #[inline] - pub fn hook__ZdaPv(&mut self, ptr: *mut c_void) -> usize { + pub fn hook__ZdaPv( + &mut self, + _original: extern "C" fn(ptr: *mut c_void) -> usize, + ptr: *mut c_void, + ) -> usize { if ptr != std::ptr::null_mut() { unsafe { self.allocator_mut().release(ptr) } } @@ -851,7 +1040,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[allow(clippy::cmp_null)] #[inline] - pub fn hook__ZdaPvm(&mut self, ptr: *mut c_void, _ulong: u64) -> usize { + pub fn hook__ZdaPvm( + &mut self, + _original: extern "C" fn(ptr: *mut c_void, _ulong: u64) -> usize, + ptr: *mut c_void, + _ulong: u64, + ) -> usize { if ptr != std::ptr::null_mut() { unsafe { self.allocator_mut().release(ptr) } } @@ -863,6 +1057,7 @@ impl AsanRuntime { #[inline] pub fn hook__ZdaPvmSt11align_val_t( &mut self, + _original: extern "C" fn(ptr: *mut c_void, _ulong: u64, _alignment: usize) -> usize, ptr: *mut c_void, _ulong: u64, _alignment: usize, @@ -878,6 +1073,7 @@ impl AsanRuntime { #[inline] pub fn hook__ZdaPvRKSt9nothrow_t( &mut self, + _original: extern "C" fn(ptr: *mut c_void, _nothrow: *const c_void) -> usize, ptr: *mut c_void, _nothrow: *const c_void, ) -> usize { @@ -892,6 +1088,11 @@ impl AsanRuntime { #[inline] pub fn hook__ZdaPvSt11align_val_tRKSt9nothrow_t( &mut self, + _original: extern "C" fn( + ptr: *mut c_void, + _alignment: usize, + _nothrow: *const c_void, + ) -> usize, ptr: *mut c_void, _alignment: usize, _nothrow: *const c_void, @@ -905,7 +1106,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[allow(clippy::cmp_null)] #[inline] - pub fn hook__ZdaPvSt11align_val_t(&mut self, ptr: *mut c_void, _alignment: usize) -> usize { + pub fn hook__ZdaPvSt11align_val_t( + &mut self, + _original: extern "C" fn(ptr: *mut c_void, _alignment: usize) -> usize, + ptr: *mut c_void, + _alignment: usize, + ) -> usize { if ptr != std::ptr::null_mut() { unsafe { self.allocator_mut().release(ptr) } } @@ -915,7 +1121,11 @@ impl AsanRuntime { #[allow(non_snake_case)] #[allow(clippy::cmp_null)] #[inline] - pub fn hook__ZdlPv(&mut self, ptr: *mut c_void) -> usize { + pub fn hook__ZdlPv( + &mut self, + _original: extern "C" fn(ptr: *mut c_void) -> usize, + ptr: *mut c_void, + ) -> usize { if ptr != std::ptr::null_mut() { unsafe { self.allocator_mut().release(ptr) } } @@ -925,7 +1135,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[allow(clippy::cmp_null)] #[inline] - pub fn hook__ZdlPvm(&mut self, ptr: *mut c_void, _ulong: u64) -> usize { + pub fn hook__ZdlPvm( + &mut self, + _original: extern "C" fn(ptr: *mut c_void, _ulong: u64) -> usize, + ptr: *mut c_void, + _ulong: u64, + ) -> usize { if ptr != std::ptr::null_mut() { unsafe { self.allocator_mut().release(ptr) } } @@ -937,6 +1152,7 @@ impl AsanRuntime { #[inline] pub fn hook__ZdlPvmSt11align_val_t( &mut self, + _original: extern "C" fn(ptr: *mut c_void, _ulong: u64, _alignment: usize) -> usize, ptr: *mut c_void, _ulong: u64, _alignment: usize, @@ -952,6 +1168,7 @@ impl AsanRuntime { #[inline] pub fn hook__ZdlPvRKSt9nothrow_t( &mut self, + _original: extern "C" fn(ptr: *mut c_void, _nothrow: *const c_void) -> usize, ptr: *mut c_void, _nothrow: *const c_void, ) -> usize { @@ -966,6 +1183,11 @@ impl AsanRuntime { #[inline] pub fn hook__ZdlPvSt11align_val_tRKSt9nothrow_t( &mut self, + _original: extern "C" fn( + ptr: *mut c_void, + _alignment: usize, + _nothrow: *const c_void, + ) -> usize, ptr: *mut c_void, _alignment: usize, _nothrow: *const c_void, @@ -979,7 +1201,12 @@ impl AsanRuntime { #[allow(non_snake_case)] #[allow(clippy::cmp_null)] #[inline] - pub fn hook__ZdlPvSt11align_val_t(&mut self, ptr: *mut c_void, _alignment: usize) -> usize { + pub fn hook__ZdlPvSt11align_val_t( + &mut self, + _original: extern "C" fn(ptr: *mut c_void, _alignment: usize) -> usize, + ptr: *mut c_void, + _alignment: usize, + ) -> usize { if ptr != std::ptr::null_mut() { unsafe { self.allocator_mut().release(ptr) } } @@ -987,8 +1214,17 @@ impl AsanRuntime { } #[inline] + #[allow(clippy::too_many_arguments)] pub fn hook_mmap( &mut self, + original: extern "C" fn( + addr: *const c_void, + length: usize, + prot: i32, + flags: i32, + fd: i32, + offset: usize, + ) -> *mut c_void, addr: *const c_void, length: usize, prot: i32, @@ -996,17 +1232,7 @@ impl AsanRuntime { fd: i32, offset: usize, ) -> *mut c_void { - extern "system" { - fn mmap( - addr: *const c_void, - length: usize, - prot: i32, - flags: i32, - fd: i32, - offset: usize, - ) -> *mut c_void; - } - let res = unsafe { mmap(addr, length, prot, flags, fd, offset) }; + let res = original(addr, length, prot, flags, fd, offset); if res != (-1_isize as *mut c_void) { self.allocator_mut() .map_shadow_for_region(res as usize, res as usize + length, true); @@ -1015,11 +1241,13 @@ impl AsanRuntime { } #[inline] - pub fn hook_munmap(&mut self, addr: *const c_void, length: usize) -> i32 { - extern "system" { - fn munmap(addr: *const c_void, length: usize) -> i32; - } - let res = unsafe { munmap(addr, length) }; + pub fn hook_munmap( + &mut self, + original: extern "C" fn(addr: *const c_void, length: usize) -> i32, + addr: *const c_void, + length: usize, + ) -> i32 { + let res = original(addr, length); if res != -1 { Allocator::poison(self.allocator_mut().map_to_shadow(addr as usize), length); } @@ -1028,14 +1256,23 @@ impl AsanRuntime { #[inline] #[allow(non_snake_case)] - pub fn hook__write(&mut self, fd: i32, buf: *const c_void, count: usize) -> usize { - self.hook_write(fd, buf, count) + pub fn hook__write( + &mut self, + original: extern "C" fn(fd: i32, buf: *const c_void, count: usize) -> usize, + fd: i32, + buf: *const c_void, + count: usize, + ) -> usize { + self.hook_write(original, fd, buf, count) } #[inline] - pub fn hook_write(&mut self, fd: i32, buf: *const c_void, count: usize) -> usize { - extern "system" { - fn write(fd: i32, buf: *const c_void, count: usize) -> usize; - } + pub fn hook_write( + &mut self, + original: extern "C" fn(fd: i32, buf: *const c_void, count: usize) -> usize, + fd: i32, + buf: *const c_void, + count: usize, + ) -> usize { if !self.allocator_mut().check_shadow(buf, count) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "write".to_string(), @@ -1045,19 +1282,28 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { write(fd, buf, count) } + original(fd, buf, count) } #[inline] #[allow(non_snake_case)] - pub fn hook__read(&mut self, fd: i32, buf: *mut c_void, count: usize) -> usize { - self.hook_read(fd, buf, count) + pub fn hook__read( + &mut self, + original: extern "C" fn(fd: i32, buf: *mut c_void, count: usize) -> usize, + fd: i32, + buf: *mut c_void, + count: usize, + ) -> usize { + self.hook_read(original, fd, buf, count) } #[inline] - pub fn hook_read(&mut self, fd: i32, buf: *mut c_void, count: usize) -> usize { - extern "system" { - fn read(fd: i32, buf: *mut c_void, count: usize) -> usize; - } + pub fn hook_read( + &mut self, + original: extern "C" fn(fd: i32, buf: *mut c_void, count: usize) -> usize, + fd: i32, + buf: *mut c_void, + count: usize, + ) -> usize { if !self.allocator_mut().check_shadow(buf, count) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "read".to_string(), @@ -1067,14 +1313,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { read(fd, buf, count) } + original(fd, buf, count) } #[inline] - pub fn hook_fgets(&mut self, s: *mut c_void, size: u32, stream: *mut c_void) -> *mut c_void { - extern "system" { - fn fgets(s: *mut c_void, size: u32, stream: *mut c_void) -> *mut c_void; - } + pub fn hook_fgets( + &mut self, + original: extern "C" fn(s: *mut c_void, size: u32, stream: *mut c_void) -> *mut c_void, + s: *mut c_void, + size: u32, + stream: *mut c_void, + ) -> *mut c_void { if !self.allocator_mut().check_shadow(s, size as usize) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "fgets".to_string(), @@ -1084,14 +1333,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { fgets(s, size, stream) } + original(s, size, stream) } #[inline] - pub fn hook_memcmp(&mut self, s1: *const c_void, s2: *const c_void, n: usize) -> i32 { - extern "system" { - fn memcmp(s1: *const c_void, s2: *const c_void, n: usize) -> i32; - } + pub fn hook_memcmp( + &mut self, + original: extern "C" fn(s1: *const c_void, s2: *const c_void, n: usize) -> i32, + s1: *const c_void, + s2: *const c_void, + n: usize, + ) -> i32 { if !self.allocator_mut().check_shadow(s1, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcmp".to_string(), @@ -1110,14 +1362,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memcmp(s1, s2, n) } + original(s1, s2, n) } #[inline] - pub fn hook_memcpy(&mut self, dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void { - extern "system" { - fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void; - } + pub fn hook_memcpy( + &mut self, + original: extern "C" fn(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void, + dest: *mut c_void, + src: *const c_void, + n: usize, + ) -> *mut c_void { if !self.allocator_mut().check_shadow(dest, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memcpy".to_string(), @@ -1136,15 +1391,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memcpy(dest, src, n) } + original(dest, src, n) } #[inline] #[cfg(not(target_vendor = "apple"))] - pub fn hook_mempcpy(&mut self, dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void { - extern "system" { - fn mempcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void; - } + pub fn hook_mempcpy( + &mut self, + original: extern "C" fn(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void, + dest: *mut c_void, + src: *const c_void, + n: usize, + ) -> *mut c_void { if !self.allocator_mut().check_shadow(dest, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "mempcpy".to_string(), @@ -1163,14 +1421,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { mempcpy(dest, src, n) } + original(dest, src, n) } #[inline] - pub fn hook_memmove(&mut self, dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void { - extern "system" { - fn memmove(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void; - } + pub fn hook_memmove( + &mut self, + original: extern "C" fn(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void, + dest: *mut c_void, + src: *const c_void, + n: usize, + ) -> *mut c_void { if !self.allocator_mut().check_shadow(dest, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memmove".to_string(), @@ -1190,14 +1451,17 @@ impl AsanRuntime { ))); } - unsafe { memmove(dest, src, n) } + original(dest, src, n) } #[inline] - pub fn hook_memset(&mut self, dest: *mut c_void, c: i32, n: usize) -> *mut c_void { - extern "system" { - fn memset(dest: *mut c_void, c: i32, n: usize) -> *mut c_void; - } + pub fn hook_memset( + &mut self, + original: extern "C" fn(dest: *mut c_void, c: i32, n: usize) -> *mut c_void, + dest: *mut c_void, + c: i32, + n: usize, + ) -> *mut c_void { if !self.allocator_mut().check_shadow(dest, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset".to_string(), @@ -1207,14 +1471,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memset(dest, c, n) } + original(dest, c, n) } #[inline] - pub fn hook_memchr(&mut self, s: *mut c_void, c: i32, n: usize) -> *mut c_void { - extern "system" { - fn memchr(s: *mut c_void, c: i32, n: usize) -> *mut c_void; - } + pub fn hook_memchr( + &mut self, + original: extern "C" fn(s: *mut c_void, c: i32, n: usize) -> *mut c_void, + s: *mut c_void, + c: i32, + n: usize, + ) -> *mut c_void { if !self.allocator_mut().check_shadow(s, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memchr".to_string(), @@ -1224,15 +1491,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memchr(s, c, n) } + original(s, c, n) } #[inline] #[cfg(not(target_vendor = "apple"))] - pub fn hook_memrchr(&mut self, s: *mut c_void, c: i32, n: usize) -> *mut c_void { - extern "system" { - fn memrchr(s: *mut c_void, c: i32, n: usize) -> *mut c_void; - } + pub fn hook_memrchr( + &mut self, + original: extern "C" fn(s: *mut c_void, c: i32, n: usize) -> *mut c_void, + s: *mut c_void, + c: i32, + n: usize, + ) -> *mut c_void { if !self.allocator_mut().check_shadow(s, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memrchr".to_string(), @@ -1242,25 +1512,23 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memrchr(s, c, n) } + original(s, c, n) } #[inline] pub fn hook_memmem( &mut self, + original: extern "C" fn( + haystack: *const c_void, + haystacklen: usize, + needle: *const c_void, + needlelen: usize, + ) -> *mut c_void, haystack: *const c_void, haystacklen: usize, needle: *const c_void, needlelen: usize, ) -> *mut c_void { - extern "system" { - fn memmem( - haystack: *const c_void, - haystacklen: usize, - needle: *const c_void, - needlelen: usize, - ) -> *mut c_void; - } if !self.allocator_mut().check_shadow(haystack, haystacklen) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmem".to_string(), @@ -1279,15 +1547,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memmem(haystack, haystacklen, needle, needlelen) } + original(haystack, haystacklen, needle, needlelen) } #[cfg(not(target_os = "android"))] #[inline] - pub fn hook_bzero(&mut self, s: *mut c_void, n: usize) -> usize { - extern "system" { - fn bzero(s: *mut c_void, n: usize) -> usize; - } + pub fn hook_bzero( + &mut self, + original: extern "C" fn(s: *mut c_void, n: usize) -> usize, + s: *mut c_void, + n: usize, + ) -> usize { if !self.allocator_mut().check_shadow(s, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "bzero".to_string(), @@ -1297,15 +1567,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { bzero(s, n) } + original(s, n) } #[cfg(all(not(target_os = "android"), not(target_vendor = "apple")))] #[inline] - pub fn hook_explicit_bzero(&mut self, s: *mut c_void, n: usize) -> usize { - extern "system" { - fn explicit_bzero(s: *mut c_void, n: usize) -> usize; - } + pub fn hook_explicit_bzero( + &mut self, + original: extern "C" fn(s: *mut c_void, n: usize) -> usize, + s: *mut c_void, + n: usize, + ) -> usize { if !self.allocator_mut().check_shadow(s, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "explicit_bzero".to_string(), @@ -1315,15 +1587,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { explicit_bzero(s, n) } + original(s, n) } #[cfg(not(target_os = "android"))] #[inline] - pub fn hook_bcmp(&mut self, s1: *const c_void, s2: *const c_void, n: usize) -> i32 { - extern "system" { - fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> i32; - } + pub fn hook_bcmp( + &mut self, + original: extern "C" fn(s1: *const c_void, s2: *const c_void, n: usize) -> i32, + s1: *const c_void, + s2: *const c_void, + n: usize, + ) -> i32 { if !self.allocator_mut().check_shadow(s1, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "bcmp".to_string(), @@ -1342,13 +1617,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { bcmp(s1, s2, n) } + original(s1, s2, n) } #[inline] - pub fn hook_strchr(&mut self, s: *mut c_char, c: i32) -> *mut c_char { + pub fn hook_strchr( + &mut self, + original: extern "C" fn(s: *mut c_char, c: i32) -> *mut c_char, + s: *mut c_char, + c: i32, + ) -> *mut c_char { extern "system" { - fn strchr(s: *mut c_char, c: i32) -> *mut c_char; + fn strlen(s: *const c_char) -> usize; } if !self @@ -1363,13 +1643,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strchr(s, c) } + original(s, c) } #[inline] - pub fn hook_strrchr(&mut self, s: *mut c_char, c: i32) -> *mut c_char { + pub fn hook_strrchr( + &mut self, + original: extern "C" fn(s: *mut c_char, c: i32) -> *mut c_char, + s: *mut c_char, + c: i32, + ) -> *mut c_char { extern "system" { - fn strrchr(s: *mut c_char, c: i32) -> *mut c_char; fn strlen(s: *const c_char) -> usize; } if !self @@ -1384,13 +1668,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strrchr(s, c) } + original(s, c) } #[inline] - pub fn hook_strcasecmp(&mut self, s1: *const c_char, s2: *const c_char) -> i32 { + pub fn hook_strcasecmp( + &mut self, + original: extern "C" fn(s1: *const c_char, s2: *const c_char) -> i32, + s1: *const c_char, + s2: *const c_char, + ) -> i32 { extern "system" { - fn strcasecmp(s1: *const c_char, s2: *const c_char) -> i32; fn strlen(s: *const c_char) -> usize; } if !self @@ -1417,14 +1705,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strcasecmp(s1, s2) } + original(s1, s2) } #[inline] - pub fn hook_strncasecmp(&mut self, s1: *const c_char, s2: *const c_char, n: usize) -> i32 { - extern "system" { - fn strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> i32; - } + pub fn hook_strncasecmp( + &mut self, + original: extern "C" fn(s1: *const c_char, s2: *const c_char, n: usize) -> i32, + s1: *const c_char, + s2: *const c_char, + n: usize, + ) -> i32 { if !self.allocator_mut().check_shadow(s1 as *const c_void, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncasecmp".to_string(), @@ -1443,13 +1734,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strncasecmp(s1, s2, n) } + original(s1, s2, n) } #[inline] - pub fn hook_strcat(&mut self, s1: *mut c_char, s2: *const c_char) -> *mut c_char { + pub fn hook_strcat( + &mut self, + original: extern "C" fn(s1: *mut c_char, s2: *const c_char) -> *mut c_char, + s1: *mut c_char, + s2: *const c_char, + ) -> *mut c_char { extern "system" { - fn strcat(s1: *mut c_char, s2: *const c_char) -> *mut c_char; fn strlen(s: *const c_char) -> usize; } if !self @@ -1476,13 +1771,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strcat(s1, s2) } + original(s1, s2) } #[inline] - pub fn hook_strcmp(&mut self, s1: *const c_char, s2: *const c_char) -> i32 { + pub fn hook_strcmp( + &mut self, + original: extern "C" fn(s1: *const c_char, s2: *const c_char) -> i32, + s1: *const c_char, + s2: *const c_char, + ) -> i32 { extern "system" { - fn strcmp(s1: *const c_char, s2: *const c_char) -> i32; fn strlen(s: *const c_char) -> usize; } if !self @@ -1509,13 +1808,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strcmp(s1, s2) } + original(s1, s2) } #[inline] - pub fn hook_strncmp(&mut self, s1: *const c_char, s2: *const c_char, n: usize) -> i32 { + pub fn hook_strncmp( + &mut self, + original: extern "C" fn(s1: *const c_char, s2: *const c_char, n: usize) -> i32, + s1: *const c_char, + s2: *const c_char, + n: usize, + ) -> i32 { extern "system" { - fn strncmp(s1: *const c_char, s2: *const c_char, n: usize) -> i32; fn strnlen(s: *const c_char, n: usize) -> usize; } if !self @@ -1542,13 +1846,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strncmp(s1, s2, n) } + original(s1, s2, n) } #[inline] - pub fn hook_strcpy(&mut self, dest: *mut c_char, src: *const c_char) -> *mut c_char { + pub fn hook_strcpy( + &mut self, + original: extern "C" fn(dest: *mut c_char, src: *const c_char) -> *mut c_char, + dest: *mut c_char, + src: *const c_char, + ) -> *mut c_char { extern "system" { - fn strcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; fn strlen(s: *const c_char) -> usize; } if !self @@ -1575,14 +1883,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strcpy(dest, src) } + original(dest, src) } #[inline] - pub fn hook_strncpy(&mut self, dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char { - extern "system" { - fn strncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char; - } + pub fn hook_strncpy( + &mut self, + original: extern "C" fn(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char, + dest: *mut c_char, + src: *const c_char, + n: usize, + ) -> *mut c_char { if !self.allocator_mut().check_shadow(dest as *const c_void, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "strncpy".to_string(), @@ -1601,13 +1912,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strncpy(dest, src, n) } + original(dest, src, n) } #[inline] - pub fn hook_stpcpy(&mut self, dest: *mut c_char, src: *const c_char) -> *mut c_char { + pub fn hook_stpcpy( + &mut self, + original: extern "C" fn(dest: *mut c_char, src: *const c_char) -> *mut c_char, + dest: *mut c_char, + src: *const c_char, + ) -> *mut c_char { extern "system" { - fn stpcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; fn strlen(s: *const c_char) -> usize; } if !self @@ -1634,16 +1949,24 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { stpcpy(dest, src) } + original(dest, src) } #[inline] #[allow(non_snake_case)] - pub fn hook__strdup(&mut self, s: *const c_char) -> *mut c_char { - self.hook_strdup(s) + pub fn hook__strdup( + &mut self, + original: extern "C" fn(s: *const c_char) -> *mut c_char, + s: *const c_char, + ) -> *mut c_char { + self.hook_strdup(original, s) } #[inline] - pub fn hook_strdup(&mut self, s: *const c_char) -> *mut c_char { + pub fn hook_strdup( + &mut self, + _original: extern "C" fn(s: *const c_char) -> *mut c_char, + s: *const c_char, + ) -> *mut c_char { extern "system" { fn strlen(s: *const c_char) -> usize; fn strcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; @@ -1667,11 +1990,12 @@ impl AsanRuntime { } #[inline] - pub fn hook_strlen(&mut self, s: *const c_char) -> usize { - extern "system" { - fn strlen(s: *const c_char) -> usize; - } - let size = unsafe { strlen(s) }; + pub fn hook_strlen( + &mut self, + original: extern "C" fn(s: *const c_char) -> usize, + s: *const c_char, + ) -> usize { + let size = original(s); if !self.allocator_mut().check_shadow(s as *const c_void, size) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strlen".to_string(), @@ -1685,11 +2009,13 @@ impl AsanRuntime { } #[inline] - pub fn hook_strnlen(&mut self, s: *const c_char, n: usize) -> usize { - extern "system" { - fn strnlen(s: *const c_char, n: usize) -> usize; - } - let size = unsafe { strnlen(s, n) }; + pub fn hook_strnlen( + &mut self, + original: extern "C" fn(s: *const c_char, n: usize) -> usize, + s: *const c_char, + n: usize, + ) -> usize { + let size = original(s, n); if !self.allocator_mut().check_shadow(s as *const c_void, size) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strnlen".to_string(), @@ -1703,9 +2029,13 @@ impl AsanRuntime { } #[inline] - pub fn hook_strstr(&mut self, haystack: *const c_char, needle: *const c_char) -> *mut c_char { + pub fn hook_strstr( + &mut self, + original: extern "C" fn(haystack: *const c_char, needle: *const c_char) -> *mut c_char, + haystack: *const c_char, + needle: *const c_char, + ) -> *mut c_char { extern "system" { - fn strstr(haystack: *const c_char, needle: *const c_char) -> *mut c_char; fn strlen(s: *const c_char) -> usize; } if !self @@ -1732,17 +2062,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strstr(haystack, needle) } + original(haystack, needle) } #[inline] pub fn hook_strcasestr( &mut self, + original: extern "C" fn(haystack: *const c_char, needle: *const c_char) -> *mut c_char, haystack: *const c_char, needle: *const c_char, ) -> *mut c_char { extern "system" { - fn strcasestr(haystack: *const c_char, needle: *const c_char) -> *mut c_char; fn strlen(s: *const c_char) -> usize; } if !self @@ -1769,13 +2099,16 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { strcasestr(haystack, needle) } + original(haystack, needle) } #[inline] - pub fn hook_atoi(&mut self, s: *const c_char) -> i32 { + pub fn hook_atoi( + &mut self, + original: extern "C" fn(s: *const c_char) -> i32, + s: *const c_char, + ) -> i32 { extern "system" { - fn atoi(s: *const c_char) -> i32; fn strlen(s: *const c_char) -> usize; } if !self @@ -1790,14 +2123,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { atoi(s) } + original(s) } /// Hooks `atol` #[inline] - pub fn hook_atol(&mut self, s: *const c_char) -> i32 { + pub fn hook_atol( + &mut self, + original: extern "C" fn(s: *const c_char) -> i32, + s: *const c_char, + ) -> i32 { extern "system" { - fn atol(s: *const c_char) -> i32; fn strlen(s: *const c_char) -> usize; } if !self @@ -1812,14 +2148,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { atol(s) } + original(s) } /// Hooks `atoll` #[inline] - pub fn hook_atoll(&mut self, s: *const c_char) -> i64 { + pub fn hook_atoll( + &mut self, + original: extern "C" fn(s: *const c_char) -> i64, + s: *const c_char, + ) -> i64 { extern "system" { - fn atoll(s: *const c_char) -> i64; fn strlen(s: *const c_char) -> usize; } if !self @@ -1834,16 +2173,17 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { atoll(s) } + original(s) } /// Hooks `wcslen` #[inline] - pub fn hook_wcslen(&mut self, s: *const wchar_t) -> usize { - extern "system" { - fn wcslen(s: *const wchar_t) -> usize; - } - let size = unsafe { wcslen(s) }; + pub fn hook_wcslen( + &mut self, + original: extern "C" fn(s: *const wchar_t) -> usize, + s: *const wchar_t, + ) -> usize { + let size = original(s); if !self .allocator_mut() .check_shadow(s as *const c_void, (size + 1) * 2) @@ -1861,9 +2201,13 @@ impl AsanRuntime { /// Hooks `wcscpy` #[inline] - pub fn hook_wcscpy(&mut self, dest: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t { + pub fn hook_wcscpy( + &mut self, + original: extern "C" fn(dest: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t, + dest: *mut wchar_t, + src: *const wchar_t, + ) -> *mut wchar_t { extern "system" { - fn wcscpy(dest: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t; fn wcslen(s: *const wchar_t) -> usize; } if !self @@ -1890,14 +2234,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { wcscpy(dest, src) } + original(dest, src) } /// Hooks `wcscmp` #[inline] - pub fn hook_wcscmp(&mut self, s1: *const wchar_t, s2: *const wchar_t) -> i32 { + pub fn hook_wcscmp( + &mut self, + original: extern "C" fn(s1: *const wchar_t, s2: *const wchar_t) -> i32, + s1: *const wchar_t, + s2: *const wchar_t, + ) -> i32 { extern "system" { - fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> i32; fn wcslen(s: *const wchar_t) -> usize; } if !self @@ -1924,15 +2272,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { wcscmp(s1, s2) } + original(s1, s2) } #[cfg(target_vendor = "apple")] #[inline] - pub fn hook_memset_pattern4(&mut self, s: *mut c_void, p4: *const c_void, n: usize) { - extern "system" { - fn memset_pattern4(s: *mut c_void, p4: *const c_void, n: usize); - } + pub fn hook_memset_pattern4( + &mut self, + original: extern "C" fn(s: *mut c_void, p4: *const c_void, n: usize), + s: *mut c_void, + p4: *const c_void, + n: usize, + ) { if !self.allocator_mut().check_shadow(s, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern4".to_string(), @@ -1951,15 +2302,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memset_pattern4(s, p4, n) } + original(s, p4, n) } #[cfg(target_vendor = "apple")] #[inline] - pub fn hook_memset_pattern8(&mut self, s: *mut c_void, p8: *const c_void, n: usize) { - extern "system" { - fn memset_pattern8(s: *mut c_void, p8: *const c_void, n: usize); - } + pub fn hook_memset_pattern8( + &mut self, + original: extern "C" fn(s: *mut c_void, p8: *const c_void, n: usize), + s: *mut c_void, + p8: *const c_void, + n: usize, + ) { if !self.allocator_mut().check_shadow(s, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern8".to_string(), @@ -1978,15 +2332,18 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memset_pattern8(s, p8, n) } + original(s, p8, n) } #[cfg(target_vendor = "apple")] #[inline] - pub fn hook_memset_pattern16(&mut self, s: *mut c_void, p16: *const c_void, n: usize) { - extern "system" { - fn memset_pattern16(s: *mut c_void, p16: *const c_void, n: usize); - } + pub fn hook_memset_pattern16( + &mut self, + original: extern "C" fn(s: *mut c_void, p16: *const c_void, n: usize), + s: *mut c_void, + p16: *const c_void, + n: usize, + ) { if !self.allocator_mut().check_shadow(s, n) { AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern16".to_string(), @@ -2005,6 +2362,6 @@ impl AsanRuntime { Backtrace::new(), ))); } - unsafe { memset_pattern16(s, p16, n) } + original(s, p16, n) } } diff --git a/libafl_frida/src/cmplog_rt.rs b/libafl_frida/src/cmplog_rt.rs index 3970cb8afe..c6f1c2c283 100644 --- a/libafl_frida/src/cmplog_rt.rs +++ b/libafl_frida/src/cmplog_rt.rs @@ -128,6 +128,8 @@ impl FridaRuntime for CmpLogRuntime { self.generate_instrumentation_blobs(); } + fn deinit(&mut self, _gum: &frida_gum::Gum) {} + fn pre_exec(&mut self, _input: &I) -> Result<(), Error> { Ok(()) } diff --git a/libafl_frida/src/coverage_rt.rs b/libafl_frida/src/coverage_rt.rs index a4a5008a8c..971d2ee64d 100644 --- a/libafl_frida/src/coverage_rt.rs +++ b/libafl_frida/src/coverage_rt.rs @@ -42,6 +42,8 @@ impl FridaRuntime for CoverageRuntime { ) { } + fn deinit(&mut self, _gum: &frida_gum::Gum) {} + fn pre_exec( &mut self, _input: &I, diff --git a/libafl_frida/src/drcov_rt.rs b/libafl_frida/src/drcov_rt.rs index 6c76d31f26..4b250cc3c9 100644 --- a/libafl_frida/src/drcov_rt.rs +++ b/libafl_frida/src/drcov_rt.rs @@ -40,6 +40,8 @@ impl FridaRuntime for DrCovRuntime { .expect("failed to create directory for coverage files"); } + fn deinit(&mut self, _gum: &frida_gum::Gum) {} + /// Called before execution, does nothing fn pre_exec(&mut self, _input: &I) -> Result<(), Error> { Ok(()) diff --git a/libafl_frida/src/helper.rs b/libafl_frida/src/helper.rs index 7c73ec40cc..f32e85e487 100644 --- a/libafl_frida/src/helper.rs +++ b/libafl_frida/src/helper.rs @@ -45,6 +45,8 @@ pub trait FridaRuntime: 'static + Debug { ranges: &RangeMap, module_map: &Rc, ); + /// Deinitialization + fn deinit(&mut self, gum: &Gum); /// Method called before execution fn pre_exec(&mut self, input: &I) -> Result<(), Error>; @@ -63,6 +65,9 @@ pub trait FridaRuntimeTuple: MatchFirstType + Debug { module_map: &Rc, ); + /// Deinitialization + fn deinit_all(&mut self, gum: &Gum); + /// Method called before execution fn pre_exec_all(&mut self, input: &I) -> Result<(), Error>; @@ -78,6 +83,8 @@ impl FridaRuntimeTuple for () { _module_map: &Rc, ) { } + fn deinit_all(&mut self, _gum: &Gum) {} + fn pre_exec_all(&mut self, _input: &I) -> Result<(), Error> { Ok(()) } @@ -101,6 +108,11 @@ where self.1.init_all(gum, ranges, module_map); } + fn deinit_all(&mut self, gum: &Gum) { + self.0.deinit(gum); + self.1.deinit_all(gum); + } + fn pre_exec_all(&mut self, input: &I) -> Result<(), Error> { self.0.pre_exec(input)?; self.1.pre_exec_all(input) @@ -575,6 +587,11 @@ where } } + /// Clean up all runtimes + pub fn deinit(&mut self, gum: &Gum) { + (*self.runtimes).borrow_mut().deinit_all(gum); + } + /* /// Return the runtime pub fn runtime(&self) -> Option<&R> diff --git a/libafl_frida/src/lib.rs b/libafl_frida/src/lib.rs index 9685aad7b3..2236f4e55f 100644 --- a/libafl_frida/src/lib.rs +++ b/libafl_frida/src/lib.rs @@ -529,6 +529,8 @@ mod tests { } } } + + frida_helper.deinit(GUM.get().expect("Gum uninitialized")); } #[test]