From 86b6c81ef810ec16b3b5d71ca018df6c0b0c5de1 Mon Sep 17 00:00:00 2001 From: s1341 Date: Tue, 14 Jan 2025 16:51:48 +0200 Subject: [PATCH 01/17] Frida updates and FASAN fixes --- fuzzers/binary_only/frida_libpng/Cargo.toml | 9 +- .../binary_only/frida_libpng/src/fuzzer.rs | 327 +++++----- libafl_frida/Cargo.toml | 6 +- libafl_frida/build.rs | 1 + libafl_frida/src/alloc.rs | 45 +- libafl_frida/src/asan/asan_rt.rs | 310 +++++----- libafl_frida/src/asan/errors.rs | 32 +- libafl_frida/src/asan/hook_funcs.rs | 569 ++++++++++++++---- libafl_frida/src/executor.rs | 10 +- libafl_frida/src/helper.rs | 19 +- 10 files changed, 841 insertions(+), 487 deletions(-) diff --git a/fuzzers/binary_only/frida_libpng/Cargo.toml b/fuzzers/binary_only/frida_libpng/Cargo.toml index 59d011ef1c..6d080d85a6 100644 --- a/fuzzers/binary_only/frida_libpng/Cargo.toml +++ b/fuzzers/binary_only/frida_libpng/Cargo.toml @@ -16,6 +16,7 @@ lto = true codegen-units = 1 opt-level = 3 debug = true +panic = 'abort' [dependencies] libafl = { path = "../../../libafl", features = [ @@ -26,7 +27,7 @@ libafl = { path = "../../../libafl", features = [ "errors_backtrace", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.15.1", features = [ +frida-gum = { version = "0.16.2", features = [ "auto-download", "event-sink", "invocation-listener", @@ -37,7 +38,7 @@ libafl_targets = { path = "../../../libafl_targets", features = [ "sancov_cmplog", ] } libloading = "0.8.5" -log = { version = "0.4.22", features = ["release_max_level_info"] } -mimalloc = { version = "0.1.43", default-features = false } -color-backtrace = "0.6.1" +log = { version = "0.4.22", features = ["release_max_level_trace"] } +mimalloc = { version = "0.1.43", default-features = true, features = ["local_dynamic_tls"] } +color-backtrace = { version= "0.6.1", features = ["resolve-modules"] } env_logger = "0.11.5" diff --git a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs index 9a94d2459a..0a6c87abe8 100644 --- a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs @@ -25,8 +25,6 @@ use libafl::{ state::{HasCorpus, StdState}, Error, HasMetadata, }; -#[cfg(unix)] -use libafl::{feedback_and_fast, feedbacks::ConstFeedback}; use libafl_bolts::{ cli::{parse_args, FuzzerOptions}, rands::StdRand, @@ -56,19 +54,16 @@ pub fn main() { color_backtrace::install(); let options = parse_args(); - unsafe { - match fuzz(&options) { - Ok(()) | Err(Error::ShuttingDown) => println!("\nFinished fuzzing. Good bye."), - Err(e) => panic!("Error during fuzzing: {e:?}"), - } + log::info!("Frida fuzzer starting up."); + match fuzz(&options) { + Ok(()) | Err(Error::ShuttingDown) => println!("\nFinished fuzzing. Good bye."), + Err(e) => panic!("Error during fuzzing: {e:?}"), } } /// The actual fuzzer #[expect(clippy::too_many_lines)] -unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { - log::info!("Frida fuzzer starting up."); - +fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { // 'While the stats are state, they are usually used in the broker - which is likely never restarted let monitor = MultiMonitor::new(|s| println!("{s}")); @@ -81,180 +76,182 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { }; let mut run_client = |state: Option<_>, - mgr: LlmpRestartingEventManager<_, _, _>, + mut mgr: LlmpRestartingEventManager<_, _, _>, client_description: ClientDescription| { // The restarting state will spawn the same process again as child, then restarted it each time it crashes. // println!("{:?}", mgr.mgr_id()); - let lib = libloading::Library::new(options.clone().harness.unwrap()).unwrap(); + let lib = unsafe { libloading::Library::new(options.clone().harness.unwrap()).unwrap() }; + let init_func: libloading::Symbol< + unsafe extern "C" fn(argc: *const usize, argv: *const *const *const u8), + > = unsafe { lib.get("LLVMFuzzerInitialize".as_bytes()).unwrap() }; let target_func: libloading::Symbol< unsafe extern "C" fn(data: *const u8, size: usize) -> i32, - > = lib.get(options.harness_function.as_bytes()).unwrap(); + > = unsafe { lib.get(options.harness_function.as_bytes()).unwrap() }; + + unsafe { + init_func(std::ptr::null(), std::ptr::null()); + } let mut frida_harness = |input: &BytesInput| { let target = input.target_bytes(); let buf = target.as_slice(); - (target_func)(buf.as_ptr(), buf.len()); + unsafe { (target_func)(buf.as_ptr(), buf.len()) }; ExitKind::Ok }; - // if options.asan && options.asan_cores.contains(client_description.core_id()) { - (|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _>, _client_description| { - let gum = Gum::obtain(); - - let coverage = CoverageRuntime::new(); - let asan = AsanRuntime::new(options); - let cmplog = CmpLogRuntime::new(); - - let client_description_clone = client_description.clone(); - let options_clone = options.clone(); - let client_description_clone2 = client_description.clone(); - let options_clone2 = options.clone(); - let mut frida_helper = FridaInstrumentationHelper::new( - &gum, - options, - tuple_list!( - IfElseRuntime::new( - move || Ok(is_asan(&options_clone, &client_description_clone)), - tuple_list!(asan), - tuple_list!() - ), - IfElseRuntime::new( - move || Ok(is_cmplog(&options_clone2, &client_description_clone2)), - tuple_list!(cmplog), - tuple_list!() - ), - coverage + let gum = Gum::obtain(); + + let coverage = CoverageRuntime::new(); + let asan = AsanRuntime::new(options); + let cmplog = CmpLogRuntime::new(); + + let client_description_clone = client_description.clone(); + let options_clone = options.clone(); + let client_description_clone2 = client_description.clone(); + let options_clone2 = options.clone(); + let mut frida_helper = FridaInstrumentationHelper::new( + &gum, + options, + tuple_list!( + IfElseRuntime::new( + move || Ok(is_asan(&options_clone, &client_description_clone)), + tuple_list!(asan), + tuple_list!() ), - ); - - // Create an observation channel using the coverage map - let edges_observer = HitcountsMapObserver::new(StdMapObserver::from_mut_ptr( - "edges", - frida_helper.map_mut_ptr().unwrap(), - MAP_SIZE, - )) - .track_indices(); - - // Create an observation channel to keep track of the execution time - let time_observer = TimeObserver::new("time"); - let asan_observer = AsanErrorsObserver::from_static_asan_errors(); - - // Feedback to rate the interestingness of an input - // This one is composed by two Feedbacks in OR - let mut feedback = feedback_or!( - // New maximization map feedback linked to the edges observer and the feedback state - MaxMapFeedback::new(&edges_observer), - // Time feedback, this one does not need a feedback state - TimeFeedback::new(&time_observer) - ); - - // Feedbacks to recognize an input as solution - #[cfg(unix)] - let mut objective = feedback_or_fast!( - CrashFeedback::new(), - TimeoutFeedback::new(), - // true enables the AsanErrorFeedback - feedback_and_fast!( - ConstFeedback::from(true), - AsanErrorsFeedback::new(&asan_observer) - ) - ); - #[cfg(windows)] - let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new()); - - // If not restarting, create a State from scratch - let mut state = state.unwrap_or_else(|| { - StdState::new( - // RNG - StdRand::new(), - // Corpus that will be evolved, we keep it in memory for performance - CachedOnDiskCorpus::no_meta(PathBuf::from("./corpus_discovered"), 64).unwrap(), - // Corpus in which we store solutions (crashes in this example), - // on disk so the user can get them after stopping the fuzzer - OnDiskCorpus::new(options.output.clone()).unwrap(), - &mut feedback, - &mut objective, - ) - .unwrap() - }); - - println!("We're a client, let's fuzz :)"); - - // Create a PNG dictionary if not existing - if state.metadata_map().get::().is_none() { - state.add_metadata(Tokens::from([ - vec![137, 80, 78, 71, 13, 10, 26, 10], // PNG header - b"IHDR".to_vec(), - b"IDAT".to_vec(), - b"PLTE".to_vec(), - b"IEND".to_vec(), - ])); - } - - // Setup a basic mutator with a mutational stage - let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); - - // A minimization+queue policy to get testcasess from the corpus - let scheduler = - IndexesLenTimeMinimizerScheduler::new(&edges_observer, QueueScheduler::new()); - - // A fuzzer with feedbacks and a corpus scheduler - let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); - - #[cfg(unix)] - let observers = tuple_list!(edges_observer, time_observer, asan_observer); - #[cfg(windows)] - let observers = tuple_list!(edges_observer, time_observer); - - // Create the executor for an in-process function with just one observer for edge coverage - let mut executor = FridaInProcessExecutor::new( - &gum, - InProcessExecutor::new( - &mut frida_harness, - observers, - &mut fuzzer, - &mut state, - &mut mgr, - )?, - &mut frida_helper, - ); - // Create an observation channel using cmplog map - let cmplog_observer = CmpLogObserver::new("cmplog", true); - - let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); - - let tracing = ShadowTracingStage::new(&mut executor); - - // Setup a randomic Input2State stage - let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( - I2SRandReplace::new() - ))); - - // In case the corpus is empty (on first run), reset - if state.must_load_initial_inputs() { - state - .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &options.input) - .unwrap_or_else(|_| { - panic!("Failed to load initial corpus at {:?}", &options.input) - }); - println!("We imported {} inputs from disk.", state.corpus().count()); - } - - let mut stages = tuple_list!( - IfElseStage::new( - |_, _, _, _| Ok(is_cmplog(&options, &client_description)), - tuple_list!(tracing, i2s), + IfElseRuntime::new( + move || Ok(is_cmplog(&options_clone2, &client_description_clone2)), + tuple_list!(cmplog), tuple_list!() ), - StdMutationalStage::new(mutator) - ); + coverage + ), + ); + + // Create an observation channel using the coverage map + let edges_observer = HitcountsMapObserver::new(unsafe { + StdMapObserver::from_mut_ptr("edges", frida_helper.map_mut_ptr().unwrap(), MAP_SIZE) + }) + .track_indices(); + + // Create an observation channel to keep track of the execution time + let time_observer = TimeObserver::new("time"); + let asan_observer = AsanErrorsObserver::from_static_asan_errors(); + + // Feedback to rate the interestingness of an input + // This one is composed by two Feedbacks in OR + let mut feedback = feedback_or!( + // New maximization map feedback linked to the edges observer and the feedback state + MaxMapFeedback::new(&edges_observer), + // Time feedback, this one does not need a feedback state + TimeFeedback::new(&time_observer) + ); + + // Feedbacks to recognize an input as solution + let mut objective = feedback_or_fast!( + CrashFeedback::new(), + AsanErrorsFeedback::new(&asan_observer), + TimeoutFeedback::new(), + ); + + // If not restarting, create a State from scratch + let mut state = state.unwrap_or_else(|| { + StdState::new( + // RNG + StdRand::new(), + // Corpus that will be evolved, we keep it in memory for performance + CachedOnDiskCorpus::no_meta(PathBuf::from("./corpus_discovered"), 64).unwrap(), + // Corpus in which we store solutions (crashes in this example), + // on disk so the user can get them after stopping the fuzzer + OnDiskCorpus::new(options.output.clone()).unwrap(), + &mut feedback, + &mut objective, + ) + .unwrap() + }); + + println!("We're a client, let's fuzz :)"); + + // Create a PNG dictionary if not existing + if state.metadata_map().get::().is_none() { + state.add_metadata(Tokens::from([ + vec![137, 80, 78, 71, 13, 10, 26, 10], // PNG header + b"IHDR".to_vec(), + b"IDAT".to_vec(), + b"PLTE".to_vec(), + b"IEND".to_vec(), + ])); + } + + // Setup a basic mutator with a mutational stage + let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); + + // A minimization+queue policy to get testcasess from the corpus + let scheduler = + IndexesLenTimeMinimizerScheduler::new(&edges_observer, QueueScheduler::new()); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); + + #[cfg(unix)] + let observers = tuple_list!(edges_observer, time_observer, asan_observer); + #[cfg(windows)] + let observers = tuple_list!(edges_observer, time_observer); + + // Create the executor for an in-process function with just one observer for edge coverage + let executor = FridaInProcessExecutor::new( + &gum, + InProcessExecutor::with_timeout( + &mut frida_harness, + observers, + &mut fuzzer, + &mut state, + &mut mgr, + options.timeout, + )?, + &mut frida_helper, + ); + // Create an observation channel using cmplog map + let cmplog_observer = CmpLogObserver::new("cmplog", true); + + let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); + + let tracing = ShadowTracingStage::new(&mut executor); + + // Setup a randomic Input2State stage + let i2s = + StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); + + // In case the corpus is empty (on first run), reset + if state.must_load_initial_inputs() { + state + .load_initial_inputs_multicore( + &mut fuzzer, + &mut executor, + &mut mgr, + &options.input, + &client_description.core_id(), + &options.cores, + ) + .unwrap_or_else(|_| { + panic!("Failed to load initial corpus at {:?}", &options.input) + }); + println!("We imported {} inputs from disk.", state.corpus().count()); + } + + let mut stages = tuple_list!( + IfElseStage::new( + |_, _, _, _| Ok(is_cmplog(&options, &client_description)), + tuple_list!(tracing, i2s), + tuple_list!() + ), + StdMutationalStage::new(mutator) + ); - fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?; + fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?; - Ok(()) - })(state, mgr, client_description.clone()) + Ok(()) }; Launcher::builder() diff --git a/libafl_frida/Cargo.toml b/libafl_frida/Cargo.toml index 8e7e0e2832..169b390238 100644 --- a/libafl_frida/Cargo.toml +++ b/libafl_frida/Cargo.toml @@ -58,15 +58,16 @@ nix = { workspace = true, default-features = true, features = ["mman"] } libc = { workspace = true } hashbrown = { workspace = true, default-features = true } rangemap = { workspace = true } -frida-gum-sys = { version = "0.15.1", features = [ +frida-gum-sys = { version = "0.16.2", features = [ "event-sink", "invocation-listener", ] } -frida-gum = { version = "0.15.1", features = [ +frida-gum = { version = "0.16.2", features = [ "event-sink", "invocation-listener", "module-names", "script", + "backtrace", ] } dynasmrt = "3.0.1" @@ -94,7 +95,6 @@ serial_test = { workspace = true, default-features = false, features = [ clap = { workspace = true, features = ["derive"] } libloading = "0.8.5" mimalloc = { workspace = true, default-features = false } -dlmalloc = { version = "0.2.6", features = ["global"] } [lints] workspace = true diff --git a/libafl_frida/build.rs b/libafl_frida/build.rs index 7d0656cc4c..ca0a08657f 100644 --- a/libafl_frida/build.rs +++ b/libafl_frida/build.rs @@ -14,6 +14,7 @@ fn main() { let target_family = std::env::var("CARGO_CFG_TARGET_FAMILY").unwrap(); // Force linking against libc++ + #[cfg(not(target_vendor = "apple"))] if target_family == "unix" { println!("cargo:rustc-link-lib=dylib=c++"); } diff --git a/libafl_frida/src/alloc.rs b/libafl_frida/src/alloc.rs index 97114765dd..9a5074b347 100644 --- a/libafl_frida/src/alloc.rs +++ b/libafl_frida/src/alloc.rs @@ -11,7 +11,6 @@ use std::{collections::BTreeMap, ffi::c_void}; use backtrace::Backtrace; use frida_gum::{PageProtection, RangeDetails}; -use hashbrown::HashMap; use libafl_bolts::cli::FuzzerOptions; #[cfg(target_vendor = "apple")] use mach_sys::{ @@ -59,9 +58,9 @@ pub struct Allocator { /// Whether we've pre allocated a shadow mapping: using_pre_allocated_shadow_mapping: bool, /// All tracked allocations - allocations: HashMap, + allocations: BTreeMap, /// All mappings - mappings: HashMap, + mappings: BTreeMap, /// The shadow memory pages shadow_pages: RangeSet, /// A list of allocations @@ -171,7 +170,6 @@ impl Allocator { #[must_use] #[expect(clippy::missing_safety_doc)] pub unsafe fn alloc(&mut self, size: usize, _alignment: usize) -> *mut c_void { - log::trace!("alloc"); let mut is_malloc_zero = false; let size = if size == 0 { is_malloc_zero = true; @@ -249,7 +247,7 @@ impl Allocator { let address = (metadata.address + self.page_size) as *mut c_void; self.allocations.insert(address as usize, metadata); - log::trace!( + log::info!( "serving address: {:#x}, size: {:#x}", address as usize, size @@ -260,21 +258,26 @@ impl Allocator { /// Releases the allocation at the given address. #[expect(clippy::missing_safety_doc)] pub unsafe fn release(&mut self, ptr: *mut c_void) { - log::trace!("release {:?}", ptr); + log::info!("release {:?}", ptr); let Some(metadata) = self.allocations.get_mut(&(ptr as usize)) else { if !ptr.is_null() { - AsanErrors::get_mut_blocking() - .report_error(AsanError::UnallocatedFree((ptr as usize, Backtrace::new()))); + if AsanErrors::get_mut_blocking() + .report_error(AsanError::UnallocatedFree((ptr as usize, Backtrace::new()))) + { + panic!("ASAN: Crashing target!"); + } } return; }; if metadata.freed { - AsanErrors::get_mut_blocking().report_error(AsanError::DoubleFree(( + if AsanErrors::get_mut_blocking().report_error(AsanError::DoubleFree(( ptr as usize, metadata.clone(), Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + } } let shadow_mapping_start = map_to_shadow!(self, ptr as usize); @@ -316,7 +319,7 @@ impl Allocator { /// Resets the allocator contents pub fn reset(&mut self) { let mut tmp_allocations = Vec::new(); - for (address, mut allocation) in self.allocations.drain() { + while let Some((address, mut allocation)) = self.allocations.pop_first() { if !allocation.freed { tmp_allocations.push(allocation); continue; @@ -580,8 +583,20 @@ impl Allocator { pub fn check_for_leaks(&self) { for metadata in self.allocations.values() { if !metadata.freed { - AsanErrors::get_mut_blocking() - .report_error(AsanError::Leak((metadata.address, metadata.clone()))); + if AsanErrors::get_mut_blocking() + .report_error(AsanError::Leak((metadata.address, metadata.clone()))) + { + unsafe { + println!( + "{:x?}", + std::slice::from_raw_parts( + metadata.address as *const u8, + metadata.size + ) + ); + }; + panic!("ASAN: Crashing target!"); + }; } } } @@ -818,10 +833,10 @@ impl Default for Allocator { page_size, pre_allocated_shadow_mappings: Vec::new(), using_pre_allocated_shadow_mapping: false, - mappings: HashMap::new(), + mappings: BTreeMap::new(), shadow_offset: 0, shadow_bit: 0, - allocations: HashMap::new(), + allocations: BTreeMap::new(), shadow_pages: RangeSet::new(), allocation_queue: BTreeMap::new(), largest_allocation: 0, diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index 727b248249..c66ca635a7 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -23,7 +23,7 @@ use frida_gum::instruction_writer::X86Register; use frida_gum::instruction_writer::{Aarch64Register, IndexMode}; use frida_gum::{ instruction_writer::InstructionWriter, interceptor::Interceptor, stalker::StalkerOutput, Gum, - Module, ModuleDetails, ModuleMap, NativePointer, PageProtection, RangeDetails, + Module, ModuleMap, NativePointer, PageProtection, Process, RangeDetails, }; use frida_gum_sys::Insn; use hashbrown::HashMap; @@ -96,6 +96,25 @@ thread_local! { static ASAN_IN_HOOK: Cell = const { Cell::new(false) }; } +#[inline] +#[cfg(target_arch = "aarch64")] +unsafe fn thread_local_initted() -> bool { + let mut tid: u64; + std::arch::asm!( + "mrs {tid}, TPIDRRO_EL0", + tid = out(reg) tid, + ); + tid = tid & 0xffff_ffff_ffff_fff8; + let tlsptr = tid as *const u64; + tlsptr.add(0x102).read() != 0u64 +} + +#[inline] +#[cfg(not(target_arch = "aarch64"))] +unsafe fn thread_local_initted() -> bool { + true +} + /// The count of registers that need to be saved by the asan runtime #[cfg(target_arch = "aarch64")] pub const ASAN_SAVE_REGISTER_COUNT: usize = 32; @@ -174,8 +193,8 @@ impl FridaRuntime for AsanRuntime { .extend(self.skip_ranges.iter().map(|skip| match skip { SkipRange::Absolute(range) => range.start, SkipRange::ModuleRelative { name, range } => { - let module_details = ModuleDetails::with_name(name.clone()).unwrap(); - let lib_start = module_details.range().base_address().0 as usize; + let module = Module::load(gum, name); + let lib_start = module.range().base_address().0 as usize; lib_start + range.start } })); @@ -456,54 +475,14 @@ impl AsanRuntime { #[expect(clippy::too_many_lines)] pub fn register_hooks(&mut self, gum: &Gum) { let mut interceptor = Interceptor::obtain(gum); - let module = Module::obtain(gum); + let process = Process::obtain(gum); macro_rules! hook_func { - //No library case - ($name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { - paste::paste! { - log::trace!("Hooking {}", stringify!($name)); - - let target_function = 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)] // depends on the values the macro is invoked with - 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); - //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 !ASAN_IN_HOOK.get() && this.hooks_enabled { - ASAN_IN_HOOK.set(true); - let ret = this.[](*original, $($param),*); - ASAN_IN_HOOK.set(false); - ret - } else { - let ret = (original)($($param),*); - 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 = module.find_export_by_name(Some($lib), stringify!($name)).expect("Failed to find function"); + let target_function = process.find_module_by_name($lib).expect("Failed to find module").find_export_by_name(stringify!($name)).expect("Failed to find function"); + log::warn!("Hooking {}:{} = {:?}", $lib, stringify!($name), target_function.0); static [<$lib_ident:snake:upper _ $name:snake:upper _PTR>]: std::sync::OnceLock $return_type> = std::sync::OnceLock::new(); @@ -516,14 +495,21 @@ impl AsanRuntime { //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 !ASAN_IN_HOOK.get() && this.hooks_enabled { - ASAN_IN_HOOK.set(true); - let ret = this.[](*original, $($param),*); - ASAN_IN_HOOK.set(false); - ret + if this.hooks_enabled { + if thread_local_initted() { + if !ASAN_IN_HOOK.get() { + ASAN_IN_HOOK.set(true); + let ret = this.[](*original, $($param),*); + ASAN_IN_HOOK.set(false); + ret + } else { + (original)($($param),*) + } + } else { + (original)($($param),*) + } } else { - let ret = (original)($($param),*); - ret + (original)($($param),*) } } @@ -539,54 +525,13 @@ impl AsanRuntime { }; } - #[expect(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 = 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)] // depends on the values the macro is invoked with - 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(); - //don't check if hooks are enabled as there are certain cases where we want to run the hook even if we are out of the program - //For example, sometimes libafl will allocate certain things during the run and free them after the run. This results in a bug where a buffer will come from libafl-frida alloc and be freed in the normal allocator. - if !ASAN_IN_HOOK.get() && this.[]($($param),*){ - ASAN_IN_HOOK.set(true); - let ret = this.[](*original, $($param),*); - ASAN_IN_HOOK.set(false); - ret - } else { - let ret = (original)($($param),*); - 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) => { + ($lib:literal, $lib_ident:ident, $name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty, $always_enabled:expr) => { paste::paste! { - log::trace!("Hooking {}:{}", $lib, stringify!($name)); - let target_function = module.find_export_by_name(Some($lib), stringify!($name)).expect("Failed to find function"); + let target_function = process.find_module_by_name($lib).expect("Failed to find module").find_export_by_name(stringify!($name)).expect("Failed to find function"); + log::warn!("Hooking {}:{} = {:?}", $lib, stringify!($name), target_function.0); static [<$lib_ident:snake:upper _ $name:snake:upper _PTR>]: std::sync::OnceLock $return_type> = std::sync::OnceLock::new(); @@ -600,14 +545,30 @@ impl AsanRuntime { let original = [<$lib_ident:snake:upper _ $name:snake:upper _PTR>].get().unwrap(); //don't check if hooks are enabled as there are certain cases where we want to run the hook even if we are out of the program //For example, sometimes libafl will allocate certain things during the run and free them after the run. This results in a bug where a buffer will come from libafl-frida alloc and be freed in the normal allocator. - if !ASAN_IN_HOOK.get() && this.[]($($param),*){ - ASAN_IN_HOOK.set(true); - let ret = this.[](*original, $($param),*); - ASAN_IN_HOOK.set(false); - ret + if $always_enabled || this.hooks_enabled { + if thread_local_initted() { + if !ASAN_IN_HOOK.get() { + ASAN_IN_HOOK.set(true); + let ret = if this.[]($($param),*) { + this.[](*original, $($param),*) + } else { + (original)($($param),*) + }; + ASAN_IN_HOOK.set(false); + ret + } else { + (original)($($param),*) + } + } else { + let ret = if $always_enabled && this.[]($($param),*) { + this.[](*original, $($param),*) + } else { + (original)($($param),*) + }; + ret + } } else { - let ret = (original)($($param),*); - ret + (original)($($param),*) } } @@ -625,23 +586,43 @@ impl AsanRuntime { // Hook the memory allocator functions #[cfg(not(windows))] - hook_func!(malloc, (size: usize), *mut c_void); + hook_func!("libc", libc, malloc, (size: usize), *mut c_void); #[cfg(not(windows))] - hook_func!(calloc, (nmemb: usize, size: usize), *mut c_void); + hook_func!("libc", libc, calloc, (nmemb: usize, size: usize), *mut c_void); #[cfg(not(windows))] - hook_func!(realloc, (ptr: *mut c_void, size: usize), *mut c_void); + hook_func_with_check!("libc", libc, realloc, (ptr: *mut c_void, size: usize), *mut c_void, false); #[cfg(not(windows))] - hook_func_with_check!(free, (ptr: *mut c_void), usize); + hook_func_with_check!("libc", libc, free, (ptr: *mut c_void), usize, true); #[cfg(not(any(target_vendor = "apple", windows)))] - hook_func!(memalign, (size: usize, alignment: usize), *mut c_void); + hook_func!("libc", libc, memalign, (size: usize, alignment: usize), *mut c_void); #[cfg(not(windows))] hook_func!( - posix_memalign, + "libc", libc, posix_memalign, (pptr: *mut *mut c_void, size: usize, alignment: usize), i32 ); #[cfg(not(any(target_vendor = "apple", windows)))] - hook_func!(malloc_usable_size, (ptr: *mut c_void), usize); + hook_func!("libc", libc, malloc_usable_size, (ptr: *mut c_void), usize); + #[cfg(target_vendor = "apple")] + hook_func!("libc", libc, valloc, (size: usize), *mut c_void); + #[cfg(target_vendor = "apple")] + hook_func_with_check!("libc", libc, reallocf, (ptr: *mut c_void, size: usize), *mut c_void, false); + #[cfg(target_vendor = "apple")] + hook_func_with_check!("libc", libc, malloc_size, (ptr: *mut c_void), usize, false); + #[cfg(target_vendor = "apple")] + hook_func_with_check!("libc", libc, malloc_good_size, (ptr: *mut c_void), usize, false); + #[cfg(target_vendor = "apple")] + hook_func!("libSystem.B.dylib", libSystemB, os_log_type_enabled, (oslog: *mut c_void, r#type: u8), bool); + #[cfg(target_vendor = "apple")] + hook_func!("libSystem.B.dylib", libSystemB, _os_log_impl, (dso: *const c_void, log: *mut c_void, r#type: u8, format: *const c_char, buf: *const u8, size: u32), ()); + #[cfg(target_vendor = "apple")] + hook_func!("libSystem.B.dylib", libSystemB, _os_log_fault_impl, (dso: *const c_void, log: *mut c_void, r#type: u8, format: *const c_char, buf: *const u8, size: u32), ()); + #[cfg(target_vendor = "apple")] + hook_func!("libSystem.B.dylib", libSystemB, _os_log_error_impl, (dso: *const c_void, log: *mut c_void, r#type: u8, format: *const c_char, buf: *const u8, size: u32), ()); + #[cfg(target_vendor = "apple")] + hook_func!("libSystem.B.dylib", libSystemB, _os_log_debug_impl, (dso: *const c_void, log: *mut c_void, r#type: u8, format: *const c_char, buf: *const u8, size: u32), ()); + hook_func!("libc++.1.dylib", libcpp, __cxa_allocate_exception, (size: usize), *const c_void); + hook_func!("libc++.1.dylib", libcpp, __cxa_free_exception, (ptr: *mut c_void), usize); // // #[cfg(windows)] // hook_priv_func!( // "c:\\windows\\system32\\ntdll.dll", @@ -674,7 +655,7 @@ impl AsanRuntime { macro_rules! hook_heap_windows { ($libname:literal, $lib_ident:ident) => { log::info!("Hooking allocator functions in {}", $libname); - for export in module.enumerate_exports($libname) { + for export in process.find_module_by_name($libname).enumerate_exports() { // log::trace!("- {}", export.name); match &export.name[..] { "NtGdiCreateCompatibleDC" => { @@ -693,16 +674,16 @@ impl AsanRuntime { hook_func!($libname, $lib_ident, RtlAllocateHeap, (handle: *mut c_void, flags: u32, bytes: usize), *mut c_void); } "HeapFree" => { - hook_func_with_check!($libname, $lib_ident, 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, true); } "RtlFreeHeap" => { - hook_func_with_check!($libname, $lib_ident, 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, true); } "HeapSize" => { - hook_func_with_check!($libname, $lib_ident, 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, false); } "RtlSizeHeap" => { - hook_func_with_check!($libname, $lib_ident, 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, false); } "RtlReAllocateHeap" => { hook_func!( @@ -737,22 +718,22 @@ impl AsanRuntime { hook_func!($libname, $lib_ident, LocalReAlloc, (mem: *mut c_void, size: usize, flags: u32), *mut c_void); } "LocalHandle" => { - hook_func_with_check!($libname, $lib_ident, LocalHandle, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, LocalHandle, (mem: *mut c_void), *mut c_void, false); } "LocalLock" => { - hook_func_with_check!($libname, $lib_ident, LocalLock, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, LocalLock, (mem: *mut c_void), *mut c_void, false); } "LocalUnlock" => { - hook_func_with_check!($libname, $lib_ident, LocalUnlock, (mem: *mut c_void), bool); + hook_func_with_check!($libname, $lib_ident, LocalUnlock, (mem: *mut c_void), bool, false); } "LocalSize" => { - hook_func_with_check!($libname, $lib_ident, LocalSize, (mem: *mut c_void),usize); + hook_func_with_check!($libname, $lib_ident, LocalSize, (mem: *mut c_void),usize, false); } "LocalFree" => { - hook_func_with_check!($libname, $lib_ident, LocalFree, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, LocalFree, (mem: *mut c_void), *mut c_void, true); } "LocalFlags" => { - hook_func_with_check!($libname, $lib_ident, LocalFlags, (mem: *mut c_void),u32); + hook_func_with_check!($libname, $lib_ident, LocalFlags, (mem: *mut c_void),u32, false); } "GlobalAlloc" => { hook_func!($libname, $lib_ident, GlobalAlloc, (flags: u32, size: usize), *mut c_void); @@ -761,22 +742,22 @@ impl AsanRuntime { hook_func!($libname, $lib_ident, GlobalReAlloc, (mem: *mut c_void, flags: u32, size: usize), *mut c_void); } "GlobalHandle" => { - hook_func_with_check!($libname, $lib_ident, GlobalHandle, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, GlobalHandle, (mem: *mut c_void), *mut c_void, false); } "GlobalLock" => { - hook_func_with_check!($libname, $lib_ident, GlobalLock, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, GlobalLock, (mem: *mut c_void), *mut c_void, false); } "GlobalUnlock" => { - hook_func_with_check!($libname, $lib_ident, GlobalUnlock, (mem: *mut c_void), bool); + hook_func_with_check!($libname, $lib_ident, GlobalUnlock, (mem: *mut c_void), bool, false); } "GlobalSize" => { - hook_func_with_check!($libname, $lib_ident, GlobalSize, (mem: *mut c_void),usize); + hook_func_with_check!($libname, $lib_ident, GlobalSize, (mem: *mut c_void),usize, false); } "GlobalFree" => { - hook_func_with_check!($libname, $lib_ident, GlobalFree, (mem: *mut c_void), *mut c_void); + hook_func_with_check!($libname, $lib_ident, GlobalFree, (mem: *mut c_void), *mut c_void, true); } "GlobalFlags" => { - hook_func_with_check!($libname, $lib_ident, GlobalFlags, (mem: *mut c_void),u32); + hook_func_with_check!($libname, $lib_ident, GlobalFlags, (mem: *mut c_void),u32, false); } "memmove" => { hook_func!( @@ -813,10 +794,10 @@ impl AsanRuntime { hook_func!($libname, $lib_ident, _o_realloc, (ptr: *mut c_void, size: usize), *mut c_void); } "free" => { - hook_func_with_check!($libname, $lib_ident, free, (ptr: *mut c_void), usize); + hook_func_with_check!($libname, $lib_ident, free, (ptr: *mut c_void), usize, true); } "_o_free" | "o_free" => { - hook_func_with_check!($libname, $lib_ident, _o_free, (ptr: *mut c_void), usize); + hook_func_with_check!($libname, $lib_ident, _o_free, (ptr: *mut c_void), usize, true); } "_write" => { hook_func!( @@ -900,7 +881,7 @@ impl AsanRuntime { macro_rules! hook_cpp { ($libname:literal, $lib_ident:ident) => { log::info!("Hooking c++ functions in {}", $libname); - for export in module.enumerate_exports($libname) { + for export in process.find_module_by_name($libname).expect("Failed to find module").enumerate_exports() { match &export.name[..] { "_Znam" => { hook_func!($libname, $lib_ident, _Znam, (size: usize), *mut c_void); @@ -1057,6 +1038,7 @@ impl AsanRuntime { #[cfg(not(windows))] hook_func!( + "libc", libc, mmap, ( addr: *const c_void, @@ -1069,34 +1051,39 @@ impl AsanRuntime { *mut c_void ); #[cfg(not(windows))] - hook_func!(munmap, (addr: *const c_void, length: usize), i32); + hook_func!("libc", libc, munmap, (addr: *const c_void, length: usize), i32); // Hook libc functions which may access allocated memory #[cfg(not(windows))] hook_func!( + "libc", libc, write, (fd: i32, buf: *const c_void, count: usize), usize ); #[cfg(not(windows))] - hook_func!(read, (fd: i32, buf: *mut c_void, count: usize), usize); + hook_func!("libc", libc, read, (fd: i32, buf: *mut c_void, count: usize), usize); hook_func!( + "libc", libc, fgets, (s: *mut c_void, size: u32, stream: *mut c_void), *mut c_void ); hook_func!( + "libc", libc, memcmp, (s1: *const c_void, s2: *const c_void, n: usize), i32 ); hook_func!( + "libc", libc, memcpy, (dest: *mut c_void, src: *const c_void, n: usize), *mut c_void ); #[cfg(not(any(target_vendor = "apple", windows)))] hook_func!( + "libc", libc, mempcpy, (dest: *mut c_void, src: *const c_void, n: usize), *mut c_void @@ -1109,23 +1096,27 @@ impl AsanRuntime { // *mut c_void // ); hook_func!( + "libc", libc, memset, (s: *mut c_void, c: i32, n: usize), *mut c_void ); hook_func!( + "libc", libc, memchr, (s: *mut c_void, c: i32, n: usize), *mut c_void ); #[cfg(not(any(target_vendor = "apple", windows)))] hook_func!( + "libc", libc, memrchr, (s: *mut c_void, c: i32, n: usize), *mut c_void ); #[cfg(not(windows))] hook_func!( + "libc", libc, memmem, ( haystack: *const c_void, @@ -1136,9 +1127,9 @@ impl AsanRuntime { *mut c_void ); #[cfg(not(any(target_os = "android", windows)))] - hook_func!(bzero, (s: *mut c_void, n: usize), usize); + hook_func!("libc", libc, bzero, (s: *mut c_void, n: usize), usize); #[cfg(not(any(target_os = "android", target_vendor = "apple", windows)))] - hook_func!(explicit_bzero, (s: *mut c_void, n: usize),usize); + hook_func!("libc", libc, explicit_bzero, (s: *mut c_void, n: usize),usize); // #[cfg(not(any(target_os = "android", windows)))] // hook_func!( // None, @@ -1146,88 +1137,101 @@ impl AsanRuntime { // (s1: *const c_void, s2: *const c_void, n: usize), // i32 // ); - hook_func!(strchr, (s: *mut c_char, c: i32), *mut c_char); - hook_func!(strrchr, (s: *mut c_char, c: i32), *mut c_char); + hook_func!("libc", libc, strchr, (s: *mut c_char, c: i32), *mut c_char); + hook_func!("libc", libc, strrchr, (s: *mut c_char, c: i32), *mut c_char); #[cfg(not(windows))] hook_func!( + "libc", libc, strcasecmp, (s1: *const c_char, s2: *const c_char), i32 ); #[cfg(not(windows))] hook_func!( + "libc", libc, strncasecmp, (s1: *const c_char, s2: *const c_char, n: usize), i32 ); hook_func!( + "libc", libc, strcat, (dest: *mut c_char, src: *const c_char), *mut c_char ); - hook_func!(strcmp, (s1: *const c_char, s2: *const c_char), i32); + hook_func!("libc", libc, strcmp, (s1: *const c_char, s2: *const c_char), i32); hook_func!( + "libc", libc, strncmp, (s1: *const c_char, s2: *const c_char, n: usize), i32 ); hook_func!( + "libc", libc, strcpy, (dest: *mut c_char, src: *const c_char), *mut c_char ); hook_func!( + "libc", libc, strncpy, (dest: *mut c_char, src: *const c_char, n: usize), *mut c_char ); #[cfg(not(windows))] hook_func!( + "libc", libc, stpcpy, (dest: *mut c_char, src: *const c_char), *mut c_char ); #[cfg(not(windows))] - hook_func!(strdup, (s: *const c_char), *mut c_char); + hook_func!("libc", libc, strdup, (s: *const c_char), *mut c_char); #[cfg(windows)] 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!("libc", libc, strlen, (s: *const c_char), usize); + hook_func!("libc", libc, strnlen, (s: *const c_char, n: usize), usize); hook_func!( + "libc", libc, strstr, (haystack: *const c_char, needle: *const c_char), *mut c_char ); #[cfg(not(windows))] hook_func!( + "libc", libc, strcasestr, (haystack: *const c_char, needle: *const c_char), *mut c_char ); - 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!("libc", libc, atoi, (nptr: *const c_char), i32); + hook_func!("libc", libc, atol, (nptr: *const c_char), i32); + hook_func!("libc", libc, atoll, (nptr: *const c_char), i64); + hook_func!("libc", libc, wcslen, (s: *const wchar_t), usize); hook_func!( + "libc", libc, wcscpy, (dest: *mut wchar_t, src: *const wchar_t), *mut wchar_t ); - hook_func!(wcscmp, (s1: *const wchar_t, s2: *const wchar_t), i32); + hook_func!("libc", libc, wcscmp, (s1: *const wchar_t, s2: *const wchar_t), i32); #[cfg(target_vendor = "apple")] hook_func!( + "libc", libc, memset_pattern4, (s: *mut c_void, c: *const c_void, n: usize), () ); #[cfg(target_vendor = "apple")] hook_func!( + "libc", libc, memset_pattern8, (s: *mut c_void, c: *const c_void, n: usize), () ); #[cfg(target_vendor = "apple")] hook_func!( + "libc", libc, memset_pattern16, (s: *mut c_void, c: *const c_void, n: usize), () @@ -1397,16 +1401,20 @@ impl AsanRuntime { backtrace, )) }; - AsanErrors::get_mut_blocking().report_error(error); + if AsanErrors::get_mut_blocking().report_error(error) { + panic!("ASAN: Crashing target!"); + } // This is not even a mem instruction?? } else { - AsanErrors::get_mut_blocking().report_error(AsanError::Unknown(( + if AsanErrors::get_mut_blocking().report_error(AsanError::Unknown(( self.regs, actual_pc, (None, None, 0, fault_address), backtrace, - ))); + ))) { + panic!("ASAN: Crashing target!"); + } } // log::info!("ASAN Error, attach the debugger!"); @@ -1536,7 +1544,9 @@ impl AsanRuntime { backtrace, )) }; - AsanErrors::get_mut_blocking().report_error(error); + if AsanErrors::get_mut_blocking().report_error(self._gum.unwrap(), error) { + panic!("ASAN: Crashing target!"); + } self.enable_hooks(); } diff --git a/libafl_frida/src/asan/errors.rs b/libafl_frida/src/asan/errors.rs index bdd062d262..0b14df3e09 100644 --- a/libafl_frida/src/asan/errors.rs +++ b/libafl_frida/src/asan/errors.rs @@ -11,7 +11,7 @@ use backtrace::Backtrace; use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity}; #[cfg(target_arch = "aarch64")] use frida_gum::interceptor::Interceptor; -use frida_gum::ModuleDetails; +use frida_gum::{Gum, Process}; use libafl::{ corpus::Testcase, executors::ExitKind, @@ -25,6 +25,7 @@ use libafl_bolts::{ tuples::{Handle, Handled, MatchNameRef}, Named, SerdeAny, }; +use mmap_rs::MmapOptions; use serde::{Deserialize, Serialize}; use termcolor::{Color, ColorSpec, WriteColor}; #[cfg(target_arch = "aarch64")] @@ -152,9 +153,9 @@ impl AsanErrors { self.continue_on_error = continue_on_error; } - /// Report an error + /// Report an error, returns true if the caller should panic #[expect(clippy::too_many_lines)] - pub(crate) fn report_error(&mut self, error: AsanError) { + pub(crate) fn report_error(&mut self, error: AsanError) -> bool { let mut out_stream = default_output_stream(); let output = out_stream.as_mut(); @@ -181,7 +182,9 @@ impl AsanErrors { | AsanError::WriteAfterFree(error) => { let (basereg, indexreg, _displacement, fault_address) = error.fault; - if let Some(module_details) = ModuleDetails::with_address(error.pc as u64) { + if let Some(module_details) = + Process::obtain(&Gum::obtain()).find_module_by_address(error.pc) + { writeln!( output, " at 0x{:x} ({}@0x{:04x}), faulting address 0x{:x}", @@ -295,7 +298,8 @@ impl AsanErrors { writeln!(output, "{:━^100}", " ALLOCATION INFO ").unwrap(); let fault_address: i64 = fault_address.try_into().unwrap(); let metadata_address: i64 = error.metadata.address.try_into().unwrap(); - let offset: i64 = fault_address - (metadata_address + 0x1000); + let offset: i64 = + fault_address - (metadata_address + MmapOptions::page_size() as i64); let direction = if offset > 0 { "right" } else { "left" }; writeln!( output, @@ -303,7 +307,7 @@ impl AsanErrors { offset, direction, error.metadata.size, - error.metadata.address + 0x1000 + error.metadata.address + MmapOptions::page_size() ) .unwrap(); @@ -344,7 +348,9 @@ impl AsanErrors { { let invocation = Interceptor::current_invocation(); let cpu_context = invocation.cpu_context(); - if let Some(module_details) = ModuleDetails::with_address(*_pc as u64) { + if let Some(module_details) = + Process::obtain(&Gum::obtain()).find_module_by_address(*_pc as u64) + { writeln!( output, " at 0x{:x} ({}@0x{:04x})", @@ -389,7 +395,7 @@ impl AsanErrors { writeln!( output, "allocation at 0x{:x}, with size 0x{:x}", - metadata.address + 0x1000, + metadata.address + MmapOptions::page_size(), metadata.size ) .unwrap(); @@ -427,7 +433,7 @@ impl AsanErrors { writeln!( output, "allocation at 0x{:x}, with size 0x{:x}", - metadata.address + 0x1000, + metadata.address + MmapOptions::page_size(), metadata.size ) .unwrap(); @@ -448,7 +454,9 @@ impl AsanErrors { | AsanError::StackOobWrite((registers, pc, fault, backtrace)) => { let (basereg, indexreg, _displacement, fault_address) = fault; - if let Some(module_details) = ModuleDetails::with_address(*pc as u64) { + if let Some(module_details) = + Process::obtain(&Gum::obtain()).find_module_by_address(*pc) + { writeln!( output, " at 0x{:x} ({}:0x{:04x}), faulting address 0x{:x}", @@ -558,9 +566,7 @@ impl AsanErrors { self.errors.push(error); #[expect(clippy::manual_assert)] - if !self.continue_on_error { - panic!("ASAN: Crashing target!"); - } + !self.continue_on_error } } diff --git a/libafl_frida/src/asan/hook_funcs.rs b/libafl_frida/src/asan/hook_funcs.rs index d7e391c5b5..edcc9857f1 100644 --- a/libafl_frida/src/asan/hook_funcs.rs +++ b/libafl_frida/src/asan/hook_funcs.rs @@ -695,6 +695,16 @@ impl AsanRuntime { 0 } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook_valloc( + &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_malloc( &mut self, @@ -855,6 +865,11 @@ impl AsanRuntime { fn memset(s: *mut c_void, c: i32, n: usize) -> *mut c_void; } let ret = unsafe { self.allocator_mut().alloc(size * nmemb, 8) }; + // if size * nmemb == 0x10 { + // log::error!("backtrace: {:0x?}", frida_gum::Backtracer::accurate()); + // let x:usize = 0x12345; + // unsafe { (x as *const usize).read(); } + // } unsafe { memset(ret, 0, size * nmemb); } @@ -879,6 +894,12 @@ impl AsanRuntime { ret } + #[inline] + #[expect(clippy::cmp_null)] + pub fn hook_check_realloc(&mut self, ptr: *mut c_void, _size: usize) -> bool { + self.allocator_mut().is_managed(ptr) + } + #[inline] #[expect(clippy::cmp_null)] pub fn hook_realloc( @@ -888,6 +909,45 @@ impl AsanRuntime { size: usize, ) -> *mut c_void { unsafe { + if size == 0 { + self.allocator_mut().release(ptr); + #[cfg(not(target_vendor = "apple"))] + return std::ptr::null_mut(); + #[cfg(target_vendor = "apple")] + return self.allocator_mut().alloc(0, 0x8); + } + let ret = self.allocator_mut().alloc(size, 0x8); + if ptr != std::ptr::null_mut() && ret != std::ptr::null_mut() { + let old_size = self.allocator_mut().get_usable_size(ptr); + let copy_size = if size < old_size { size } else { old_size }; + (ptr as *mut u8).copy_to(ret as *mut u8, copy_size); + self.allocator_mut().release(ptr); + } + ret + } + } + + #[inline] + #[expect(clippy::cmp_null)] + #[cfg(target_vendor = "apple")] + pub fn hook_check_reallocf(&mut self, ptr: *mut c_void, size: usize) -> bool { + self.allocator_mut().is_managed(ptr) + } + + #[inline] + #[expect(clippy::cmp_null)] + #[cfg(target_vendor = "apple")] + pub fn hook_reallocf( + &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 { + if size == 0 { + self.allocator_mut().release(ptr); + return self.allocator_mut().alloc(0, 0x8); + } let ret = self.allocator_mut().alloc(size, 0x8); if ptr != std::ptr::null_mut() && ret != std::ptr::null_mut() { let old_size = self.allocator_mut().get_usable_size(ptr); @@ -991,7 +1051,150 @@ impl AsanRuntime { ) -> usize { self.allocator_mut().get_usable_size(ptr) } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook_check_malloc_size(&mut self, ptr: *mut c_void) -> bool { + self.allocator_mut().is_managed(ptr) + } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook_malloc_size( + &mut self, + _original: extern "C" fn(ptr: *mut c_void) -> usize, + ptr: *mut c_void, + ) -> usize { + self.allocator_mut().get_usable_size(ptr) + } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook_check_malloc_good_size(&mut self, ptr: *mut c_void) -> bool { + self.allocator_mut().is_managed(ptr) + } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook_malloc_good_size( + &mut self, + _original: extern "C" fn(ptr: *mut c_void) -> usize, + ptr: *mut c_void, + ) -> usize { + self.allocator_mut().get_usable_size(ptr) + } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook_os_log_type_enabled( + &mut self, + _original: extern "C" fn(oslog: *mut c_void, r#type: u8) -> bool, + _oslog: *mut c_void, + r#_type: u8, + ) -> bool { + false + } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook__os_log_impl( + &mut self, + _original: extern "C" fn( + dso: *const c_void, + log: *mut c_void, + r#type: u8, + format: *const c_char, + buf: *const u8, + size: u32, + ), + _dso: *const c_void, + _log: *mut c_void, + r#_type: u8, + _format: *const c_char, + _buf: *const u8, + _size: u32, + ) { + } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook__os_log_fault_impl( + &mut self, + _original: extern "C" fn( + dso: *const c_void, + log: *mut c_void, + r#type: u8, + format: *const c_char, + buf: *const u8, + size: u32, + ), + _dso: *const c_void, + _log: *mut c_void, + r#_type: u8, + _format: *const c_char, + _buf: *const u8, + _size: u32, + ) { + } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook__os_log_error_impl( + &mut self, + _original: extern "C" fn( + dso: *const c_void, + log: *mut c_void, + r#type: u8, + format: *const c_char, + buf: *const u8, + size: u32, + ), + _dso: *const c_void, + _log: *mut c_void, + r#_type: u8, + _format: *const c_char, + _buf: *const u8, + _size: u32, + ) { + } + #[inline] + #[cfg(target_vendor = "apple")] + pub fn hook__os_log_debug_impl( + &mut self, + _original: extern "C" fn( + dso: *const c_void, + log: *mut c_void, + r#type: u8, + format: *const c_char, + buf: *const u8, + size: u32, + ), + _dso: *const c_void, + _log: *mut c_void, + r#_type: u8, + _format: *const c_char, + _buf: *const u8, + _size: u32, + ) { + } + #[inline] + #[expect(non_snake_case)] + pub fn hook___cxa_allocate_exception( + &mut self, + _original: extern "C" fn(size: usize) -> *const c_void, + size: usize, + ) -> *const c_void { + unsafe { + self.allocator_mut() + .alloc((size + 0x8f) & 0xfffffffffffffff0, 8) + .add(0x80) + } + } + #[inline] + #[expect(non_snake_case)] + pub fn hook___cxa_free_exception( + &mut self, + _original: extern "C" fn(ptr: *mut c_void) -> usize, + ptr: *mut c_void, + ) -> usize { + unsafe { + self.allocator_mut().release(ptr.sub(0x80)); + } + 0 + } #[inline] #[expect(non_snake_case)] #[cfg(windows)] @@ -1274,13 +1477,15 @@ impl AsanRuntime { count: usize, ) -> usize { if !self.allocator_mut().check_shadow(buf, count) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "write".to_string(), self.real_address_for_stalked(self.pc()), buf as usize, count, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + } } original(fd, buf, count) } @@ -1305,13 +1510,15 @@ impl AsanRuntime { count: usize, ) -> usize { if !self.allocator_mut().check_shadow(buf, count) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "read".to_string(), self.real_address_for_stalked(self.pc()), buf as usize, count, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + } } original(fd, buf, count) } @@ -1325,13 +1532,15 @@ impl AsanRuntime { 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(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "fgets".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size as usize, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + } } original(s, size, stream) } @@ -1345,22 +1554,26 @@ impl AsanRuntime { n: usize, ) -> i32 { if !self.allocator_mut().check_shadow(s1, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + } } if !self.allocator_mut().check_shadow(s2, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s1, s2, n) } @@ -1374,22 +1587,26 @@ impl AsanRuntime { n: usize, ) -> *mut c_void { if !self.allocator_mut().check_shadow(dest, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(src, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(dest, src, n) } @@ -1404,22 +1621,26 @@ impl AsanRuntime { n: usize, ) -> *mut c_void { if !self.allocator_mut().check_shadow(dest, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "mempcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(src, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "mempcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(dest, src, n) } @@ -1433,22 +1654,26 @@ impl AsanRuntime { n: usize, ) -> *mut c_void { if !self.allocator_mut().check_shadow(dest, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memmove".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(src, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmove".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(dest, src, n) @@ -1463,13 +1688,15 @@ impl AsanRuntime { n: usize, ) -> *mut c_void { if !self.allocator_mut().check_shadow(dest, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(dest, c, n) } @@ -1483,13 +1710,15 @@ impl AsanRuntime { n: usize, ) -> *mut c_void { if !self.allocator_mut().check_shadow(s, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, c, n) } @@ -1504,13 +1733,15 @@ impl AsanRuntime { n: usize, ) -> *mut c_void { if !self.allocator_mut().check_shadow(s, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memrchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, c, n) } @@ -1530,22 +1761,26 @@ impl AsanRuntime { needlelen: usize, ) -> *mut c_void { if !self.allocator_mut().check_shadow(haystack, haystacklen) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmem".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, haystacklen, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(needle, needlelen) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmem".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, needlelen, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(haystack, haystacklen, needle, needlelen) } @@ -1559,13 +1794,15 @@ impl AsanRuntime { n: usize, ) -> usize { if !self.allocator_mut().check_shadow(s, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "bzero".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, n) } @@ -1579,13 +1816,15 @@ impl AsanRuntime { n: usize, ) -> usize { if !self.allocator_mut().check_shadow(s, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "explicit_bzero".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, n) } @@ -1600,22 +1839,26 @@ impl AsanRuntime { n: usize, ) -> i32 { if !self.allocator_mut().check_shadow(s1, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "bcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(s2, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "bcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s1, s2, n) } @@ -1635,13 +1878,15 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s as *const c_void, unsafe { strlen(s) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, c) } @@ -1660,13 +1905,15 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s as *const c_void, unsafe { strlen(s) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strrchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, c) } @@ -1685,25 +1932,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasecmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasecmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s1, s2) } @@ -1717,22 +1968,26 @@ impl AsanRuntime { n: usize, ) -> i32 { if !self.allocator_mut().check_shadow(s1 as *const c_void, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncasecmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(s2 as *const c_void, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncasecmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s1, s2, n) } @@ -1751,25 +2006,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcat".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcat".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s1, s2) } @@ -1788,25 +2047,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s1, s2) } @@ -1826,25 +2089,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s1 as *const c_void, unsafe { strnlen(s1, n) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(s2 as *const c_void, unsafe { strnlen(s2, n) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s1, s2, n) } @@ -1863,25 +2130,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(dest as *const c_void, unsafe { strlen(src) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "strcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, unsafe { strlen(src) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(src as *const c_void, unsafe { strlen(src) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, unsafe { strlen(src) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(dest, src) } @@ -1894,23 +2165,31 @@ impl AsanRuntime { src: *const c_char, n: usize, ) -> *mut c_char { + extern "system" { + fn strlen(s: *const c_char) -> usize; + } if !self.allocator_mut().check_shadow(dest as *const c_void, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "strncpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } - if !self.allocator_mut().check_shadow(src as *const c_void, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + let mn = std::cmp::min(n, unsafe { strlen(src) } + 1); + if !self.allocator_mut().check_shadow(src as *const c_void, mn) { + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, - n, + mn, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(dest, src, n) } @@ -1929,25 +2208,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(dest as *const c_void, unsafe { strlen(src) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "stpcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, unsafe { strlen(src) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(src as *const c_void, unsafe { strlen(src) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "stpcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, unsafe { strlen(src) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(dest, src) } @@ -1971,15 +2254,17 @@ impl AsanRuntime { fn strlen(s: *const c_char) -> usize; fn strcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; } - let size = unsafe { strlen(s) }; + let size = unsafe { strlen(s) + 1 }; if !self.allocator_mut().check_shadow(s as *const c_void, size) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strdup".to_string(), self.real_address_for_stalked(self.pc()), s as usize, - unsafe { strlen(s) }, + unsafe { strlen(s) + 1 }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } unsafe { @@ -1997,13 +2282,15 @@ impl AsanRuntime { ) -> 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(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strlen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } size } @@ -2017,13 +2304,15 @@ impl AsanRuntime { ) -> 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(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strnlen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } size } @@ -2042,25 +2331,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strstr".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, unsafe { strlen(haystack) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strstr".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, unsafe { strlen(needle) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(haystack, needle) } @@ -2079,25 +2372,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasestr".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, unsafe { strlen(haystack) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasestr".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, unsafe { strlen(needle) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(haystack, needle) } @@ -2115,13 +2412,15 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s as *const c_void, unsafe { strlen(s) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atoi".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s) } @@ -2140,13 +2439,15 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s as *const c_void, unsafe { strlen(s) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atol".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s) } @@ -2165,13 +2466,15 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s as *const c_void, unsafe { strlen(s) }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atoll".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s) } @@ -2188,13 +2491,15 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s as *const c_void, (size + 1) * 2) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcslen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, (size + 1) * 2, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } size } @@ -2214,25 +2519,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(dest as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "wcscpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, (unsafe { wcslen(src) } + 1) * 2, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(src as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, (unsafe { wcslen(src) } + 1) * 2, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(dest, src) } @@ -2252,25 +2561,29 @@ impl AsanRuntime { .allocator_mut() .check_shadow(s1 as *const c_void, unsafe { (wcslen(s1) + 1) * 2 }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, (unsafe { wcslen(s1) } + 1) * 2, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self .allocator_mut() .check_shadow(s2 as *const c_void, unsafe { (wcslen(s2) + 1) * 2 }) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, (unsafe { wcslen(s2) } + 1) * 2, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s1, s2) } @@ -2285,22 +2598,26 @@ impl AsanRuntime { n: usize, ) { if !self.allocator_mut().check_shadow(s, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern4".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(p4, n / 4) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern4".to_string(), self.real_address_for_stalked(self.pc()), p4 as usize, n / 4, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, p4, n); } @@ -2315,22 +2632,26 @@ impl AsanRuntime { n: usize, ) { if !self.allocator_mut().check_shadow(s, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern8".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(p8, n / 8) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern8".to_string(), self.real_address_for_stalked(self.pc()), p8 as usize, n / 8, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, p8, n); } @@ -2345,22 +2666,26 @@ impl AsanRuntime { n: usize, ) { if !self.allocator_mut().check_shadow(s, n) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern16".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } if !self.allocator_mut().check_shadow(p16, n / 16) { - AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern16".to_string(), self.real_address_for_stalked(self.pc()), p16 as usize, n / 16, Backtrace::new(), - ))); + ))) { + panic!("ASAN: Crashing target!"); + }; } original(s, p16, n); } diff --git a/libafl_frida/src/executor.rs b/libafl_frida/src/executor.rs index d16a71446b..9af6f5f022 100644 --- a/libafl_frida/src/executor.rs +++ b/libafl_frida/src/executor.rs @@ -180,13 +180,15 @@ where // Include the current module (the fuzzer) in stalked ranges. We clone the ranges so that // we don't add it to the INSTRUMENTED ranges. let mut ranges = helper.ranges().clone(); - for module in frida_gum::Module::obtain(gum).enumerate_modules() { - if module.base_address < Self::with_target_bytes_converter as usize + for module in frida_gum::Process::obtain(gum).enumerate_modules() { + let range = module.range(); + if (range.base_address().0 as usize) < Self::with_target_bytes_converter as usize && (Self::with_target_bytes_converter as usize as u64) - < module.base_address as u64 + module.size as u64 + < range.base_address().0 as u64 + range.size() as u64 { ranges.insert( - module.base_address as u64..(module.base_address as u64 + module.size as u64), + range.base_address().0 as u64 + ..(range.base_address().0 as u64 + range.size() as u64), (0xffff, "fuzzer".to_string()), ); break; diff --git a/libafl_frida/src/helper.rs b/libafl_frida/src/helper.rs index d6dca76dc5..d8851e657f 100644 --- a/libafl_frida/src/helper.rs +++ b/libafl_frida/src/helper.rs @@ -11,7 +11,7 @@ use std::{ use frida_gum::{ instruction_writer::InstructionWriter, stalker::{StalkerIterator, StalkerOutput, Transformer}, - Backend, Gum, ModuleDetails, ModuleMap, Script, + Backend, Gum, Module, ModuleMap, Script, }; use frida_gum_sys::gchar; use libafl::Error; @@ -276,8 +276,8 @@ pub struct FridaInstrumentationHelperBuilder { stalker_enabled: bool, disable_excludes: bool, #[expect(clippy::type_complexity)] - instrument_module_predicate: Option bool>>, - skip_module_predicate: Box bool>, + instrument_module_predicate: Option bool>>, + skip_module_predicate: Box bool>, skip_ranges: Vec, } @@ -353,7 +353,7 @@ impl FridaInstrumentationHelperBuilder { /// .instrument_module_if(|module| module.path().starts_with("/usr/lib")); /// ``` #[must_use] - pub fn instrument_module_if bool + 'static>( + pub fn instrument_module_if bool + 'static>( mut self, mut predicate: F, ) -> Self { @@ -382,10 +382,7 @@ impl FridaInstrumentationHelperBuilder { /// .skip_module_if(|module| module.name() == "libfoo.so"); /// ``` #[must_use] - pub fn skip_module_if bool + 'static>( - mut self, - mut predicate: F, - ) -> Self { + pub fn skip_module_if bool + 'static>(mut self, mut predicate: F) -> Self { let new = move |module: &_| (self.skip_module_predicate)(module) || predicate(module); Self { skip_module_predicate: Box::new(new), @@ -430,7 +427,7 @@ impl FridaInstrumentationHelperBuilder { !skip_module_predicate(&module) } }); - let module_map = Rc::new(ModuleMap::new_with_filter(gum, &mut module_filter)); + let module_map = Rc::new(ModuleMap::new_with_filter(&mut module_filter)); let ranges = RangeMap::new(); // Wrap ranges and runtimes in reference-counted refcells in order to move @@ -461,7 +458,7 @@ impl FridaInstrumentationHelperBuilder { .borrow_mut() .remove(range.start as u64..range.end as u64), SkipRange::ModuleRelative { name, range } => { - let module_details = ModuleDetails::with_name(name).unwrap(); + let module_details = Module::load(gum, &name); let lib_start = module_details.range().base_address().0 as u64; ranges.borrow_mut().remove( (lib_start + range.start as u64)..(lib_start + range.end as u64), @@ -550,7 +547,7 @@ pub unsafe extern "C" fn test_function(message: *const gchar) { } } -fn pathlist_contains_module(list: I, module: &ModuleDetails) -> bool +fn pathlist_contains_module(list: I, module: &Module) -> bool where I: IntoIterator, P: AsRef, From 57bd086bf91009e2c6642d0227803a771e2646fb Mon Sep 17 00:00:00 2001 From: s1341 Date: Tue, 14 Jan 2025 16:54:26 +0200 Subject: [PATCH 02/17] fmt --- fuzzers/binary_only/frida_libpng/Cargo.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fuzzers/binary_only/frida_libpng/Cargo.toml b/fuzzers/binary_only/frida_libpng/Cargo.toml index 6d080d85a6..7b477c220e 100644 --- a/fuzzers/binary_only/frida_libpng/Cargo.toml +++ b/fuzzers/binary_only/frida_libpng/Cargo.toml @@ -39,6 +39,8 @@ libafl_targets = { path = "../../../libafl_targets", features = [ ] } libloading = "0.8.5" log = { version = "0.4.22", features = ["release_max_level_trace"] } -mimalloc = { version = "0.1.43", default-features = true, features = ["local_dynamic_tls"] } -color-backtrace = { version= "0.6.1", features = ["resolve-modules"] } +mimalloc = { version = "0.1.43", default-features = true, features = [ + "local_dynamic_tls", +] } +color-backtrace = { version = "0.6.1", features = ["resolve-modules"] } env_logger = "0.11.5" From cd0d947366c052d4e59a19cce47e6ee7ca447425 Mon Sep 17 00:00:00 2001 From: s1341 Date: Tue, 14 Jan 2025 16:55:46 +0200 Subject: [PATCH 03/17] Fixes --- libafl_frida/src/asan/asan_rt.rs | 2 +- libafl_frida/src/asan/errors.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index c66ca635a7..2f03e528b6 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -1544,7 +1544,7 @@ impl AsanRuntime { backtrace, )) }; - if AsanErrors::get_mut_blocking().report_error(self._gum.unwrap(), error) { + if AsanErrors::get_mut_blocking().report_error(error) { panic!("ASAN: Crashing target!"); } self.enable_hooks(); diff --git a/libafl_frida/src/asan/errors.rs b/libafl_frida/src/asan/errors.rs index 0b14df3e09..12bc152640 100644 --- a/libafl_frida/src/asan/errors.rs +++ b/libafl_frida/src/asan/errors.rs @@ -349,7 +349,7 @@ impl AsanErrors { let invocation = Interceptor::current_invocation(); let cpu_context = invocation.cpu_context(); if let Some(module_details) = - Process::obtain(&Gum::obtain()).find_module_by_address(*_pc as u64) + Process::obtain(&Gum::obtain()).find_module_by_address(*_pc) { writeln!( output, From 2613758803e08fb7abaa18416bc93bb79df8d3d6 Mon Sep 17 00:00:00 2001 From: s1341 Date: Tue, 14 Jan 2025 17:19:28 +0200 Subject: [PATCH 04/17] clippy --- libafl_frida/src/alloc.rs | 40 ++-- libafl_frida/src/asan/asan_rt.rs | 17 +- libafl_frida/src/asan/hook_funcs.rs | 346 +++++++++------------------- 3 files changed, 131 insertions(+), 272 deletions(-) diff --git a/libafl_frida/src/alloc.rs b/libafl_frida/src/alloc.rs index 9a5074b347..406356f051 100644 --- a/libafl_frida/src/alloc.rs +++ b/libafl_frida/src/alloc.rs @@ -260,24 +260,19 @@ impl Allocator { pub unsafe fn release(&mut self, ptr: *mut c_void) { log::info!("release {:?}", ptr); let Some(metadata) = self.allocations.get_mut(&(ptr as usize)) else { - if !ptr.is_null() { - if AsanErrors::get_mut_blocking() - .report_error(AsanError::UnallocatedFree((ptr as usize, Backtrace::new()))) - { - panic!("ASAN: Crashing target!"); - } + if !ptr.is_null() && AsanErrors::get_mut_blocking() + .report_error(AsanError::UnallocatedFree((ptr as usize, Backtrace::new()))) { + panic!("ASAN: Crashing target!"); } return; }; - if metadata.freed { - if AsanErrors::get_mut_blocking().report_error(AsanError::DoubleFree(( + if metadata.freed && AsanErrors::get_mut_blocking().report_error(AsanError::DoubleFree(( ptr as usize, metadata.clone(), Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - } + panic!("ASAN: Crashing target!"); } let shadow_mapping_start = map_to_shadow!(self, ptr as usize); @@ -582,21 +577,18 @@ impl Allocator { /// Checks if any of the allocations has not been freed pub fn check_for_leaks(&self) { for metadata in self.allocations.values() { - if !metadata.freed { - if AsanErrors::get_mut_blocking() - .report_error(AsanError::Leak((metadata.address, metadata.clone()))) - { - unsafe { - println!( - "{:x?}", - std::slice::from_raw_parts( - metadata.address as *const u8, - metadata.size - ) - ); - }; - panic!("ASAN: Crashing target!"); + if !metadata.freed && AsanErrors::get_mut_blocking() + .report_error(AsanError::Leak((metadata.address, metadata.clone()))) { + unsafe { + println!( + "{:x?}", + std::slice::from_raw_parts( + metadata.address as *const u8, + metadata.size + ) + ); }; + panic!("ASAN: Crashing target!"); } } } diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index 2f03e528b6..7e7ce1e65e 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -1401,20 +1401,19 @@ impl AsanRuntime { backtrace, )) }; + #[allow(clippy::manual_assert)] if AsanErrors::get_mut_blocking().report_error(error) { panic!("ASAN: Crashing target!"); } // This is not even a mem instruction?? - } else { - if AsanErrors::get_mut_blocking().report_error(AsanError::Unknown(( - self.regs, - actual_pc, - (None, None, 0, fault_address), - backtrace, - ))) { - panic!("ASAN: Crashing target!"); - } + } else if AsanErrors::get_mut_blocking().report_error(AsanError::Unknown(( + self.regs, + actual_pc, + (None, None, 0, fault_address), + backtrace, + ))) { + panic!("ASAN: Crashing target!"); } // log::info!("ASAN Error, attach the debugger!"); diff --git a/libafl_frida/src/asan/hook_funcs.rs b/libafl_frida/src/asan/hook_funcs.rs index edcc9857f1..401022753a 100644 --- a/libafl_frida/src/asan/hook_funcs.rs +++ b/libafl_frida/src/asan/hook_funcs.rs @@ -930,7 +930,7 @@ impl AsanRuntime { #[inline] #[expect(clippy::cmp_null)] #[cfg(target_vendor = "apple")] - pub fn hook_check_reallocf(&mut self, ptr: *mut c_void, size: usize) -> bool { + pub fn hook_check_reallocf(&mut self, ptr: *mut c_void, _size: usize) -> bool { self.allocator_mut().is_managed(ptr) } @@ -1476,16 +1476,14 @@ impl AsanRuntime { buf: *const c_void, count: usize, ) -> usize { - if !self.allocator_mut().check_shadow(buf, count) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(buf, count) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "write".to_string(), self.real_address_for_stalked(self.pc()), buf as usize, count, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - } + panic!("ASAN: Crashing target!"); } original(fd, buf, count) } @@ -1509,16 +1507,14 @@ impl AsanRuntime { buf: *mut c_void, count: usize, ) -> usize { - if !self.allocator_mut().check_shadow(buf, count) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(buf, count) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "read".to_string(), self.real_address_for_stalked(self.pc()), buf as usize, count, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - } + panic!("ASAN: Crashing target!"); } original(fd, buf, count) } @@ -1531,16 +1527,14 @@ impl AsanRuntime { size: u32, stream: *mut c_void, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(s, size as usize) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s, size as usize) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "fgets".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size as usize, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - } + panic!("ASAN: Crashing target!"); } original(s, size, stream) } @@ -1553,27 +1547,23 @@ impl AsanRuntime { s2: *const c_void, n: usize, ) -> i32 { - if !self.allocator_mut().check_shadow(s1, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s1, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - } + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(s2, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s2, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s1, s2, n) } @@ -1586,27 +1576,23 @@ impl AsanRuntime { src: *const c_void, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(dest, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(dest, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(src, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(src, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(dest, src, n) } @@ -1620,27 +1606,23 @@ impl AsanRuntime { src: *const c_void, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(dest, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(dest, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "mempcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(src, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(src, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "mempcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(dest, src, n) } @@ -1653,27 +1635,23 @@ impl AsanRuntime { src: *const c_void, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(dest, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(dest, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memmove".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(src, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(src, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmove".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(dest, src, n) @@ -1687,16 +1665,14 @@ impl AsanRuntime { c: i32, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(dest, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(dest, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(dest, c, n) } @@ -1709,16 +1685,14 @@ impl AsanRuntime { c: i32, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(s, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s, c, n) } @@ -1732,16 +1706,14 @@ impl AsanRuntime { c: i32, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(s, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memrchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s, c, n) } @@ -1760,27 +1732,23 @@ impl AsanRuntime { needle: *const c_void, needlelen: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(haystack, haystacklen) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(haystack, haystacklen) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmem".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, haystacklen, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(needle, needlelen) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(needle, needlelen) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmem".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, needlelen, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(haystack, haystacklen, needle, needlelen) } @@ -1793,16 +1761,14 @@ impl AsanRuntime { s: *mut c_void, n: usize, ) -> usize { - if !self.allocator_mut().check_shadow(s, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(s, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "bzero".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s, n) } @@ -1815,16 +1781,14 @@ impl AsanRuntime { s: *mut c_void, n: usize, ) -> usize { - if !self.allocator_mut().check_shadow(s, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(s, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "explicit_bzero".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s, n) } @@ -1838,27 +1802,23 @@ impl AsanRuntime { s2: *const c_void, n: usize, ) -> i32 { - if !self.allocator_mut().check_shadow(s1, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s1, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "bcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(s2, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s2, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "bcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s1, s2, n) } @@ -1876,17 +1836,14 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s, c) } @@ -1903,17 +1860,14 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strrchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s, c) } @@ -1930,31 +1884,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasecmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasecmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s1, s2) } @@ -1967,27 +1915,23 @@ impl AsanRuntime { s2: *const c_char, n: usize, ) -> i32 { - if !self.allocator_mut().check_shadow(s1 as *const c_void, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s1 as *const c_void, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncasecmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(s2 as *const c_void, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s2 as *const c_void, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncasecmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s1, s2, n) } @@ -2004,31 +1948,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcat".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcat".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s1, s2) } @@ -2045,31 +1983,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s1, s2) } @@ -2087,31 +2019,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { strnlen(s1, n) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { strnlen(s1, n) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { strnlen(s2, n) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { strnlen(s2, n) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s1, s2, n) } @@ -2128,31 +2054,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(dest as *const c_void, unsafe { strlen(src) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + .check_shadow(dest as *const c_void, unsafe { strlen(src) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "strcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, unsafe { strlen(src) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(src as *const c_void, unsafe { strlen(src) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(src as *const c_void, unsafe { strlen(src) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, unsafe { strlen(src) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(dest, src) } @@ -2168,28 +2088,24 @@ impl AsanRuntime { extern "system" { fn strlen(s: *const c_char) -> usize; } - if !self.allocator_mut().check_shadow(dest as *const c_void, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(dest as *const c_void, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "strncpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } let mn = std::cmp::min(n, unsafe { strlen(src) } + 1); - if !self.allocator_mut().check_shadow(src as *const c_void, mn) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(src as *const c_void, mn) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, mn, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(dest, src, n) } @@ -2206,31 +2122,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(dest as *const c_void, unsafe { strlen(src) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + .check_shadow(dest as *const c_void, unsafe { strlen(src) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "stpcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, unsafe { strlen(src) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(src as *const c_void, unsafe { strlen(src) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(src as *const c_void, unsafe { strlen(src) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "stpcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, unsafe { strlen(src) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(dest, src) } @@ -2255,16 +2165,14 @@ impl AsanRuntime { fn strcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; } let size = unsafe { strlen(s) + 1 }; - if !self.allocator_mut().check_shadow(s as *const c_void, size) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s as *const c_void, size) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strdup".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) + 1 }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } unsafe { @@ -2281,16 +2189,14 @@ impl AsanRuntime { s: *const c_char, ) -> usize { let size = original(s); - if !self.allocator_mut().check_shadow(s as *const c_void, size) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s as *const c_void, size) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strlen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } size } @@ -2303,16 +2209,14 @@ impl AsanRuntime { n: usize, ) -> usize { let size = original(s, n); - if !self.allocator_mut().check_shadow(s as *const c_void, size) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s as *const c_void, size) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strnlen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } size } @@ -2329,31 +2233,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strstr".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, unsafe { strlen(haystack) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strstr".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, unsafe { strlen(needle) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(haystack, needle) } @@ -2370,31 +2268,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasestr".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, unsafe { strlen(haystack) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasestr".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, unsafe { strlen(needle) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(haystack, needle) } @@ -2410,17 +2302,14 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atoi".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s) } @@ -2437,17 +2326,14 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atol".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s) } @@ -2464,17 +2350,14 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atoll".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s) } @@ -2489,17 +2372,14 @@ impl AsanRuntime { let size = original(s); if !self .allocator_mut() - .check_shadow(s as *const c_void, (size + 1) * 2) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, (size + 1) * 2) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcslen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, (size + 1) * 2, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } size } @@ -2517,31 +2397,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(dest as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + .check_shadow(dest as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "wcscpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, (unsafe { wcslen(src) } + 1) * 2, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(src as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(src as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, (unsafe { wcslen(src) } + 1) * 2, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(dest, src) } @@ -2559,31 +2433,25 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { (wcslen(s1) + 1) * 2 }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { (wcslen(s1) + 1) * 2 }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, (unsafe { wcslen(s1) } + 1) * 2, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { (wcslen(s2) + 1) * 2 }) - { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { (wcslen(s2) + 1) * 2 }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, (unsafe { wcslen(s2) } + 1) * 2, Backtrace::new(), ))) { - panic!("ASAN: Crashing target!"); - }; + panic!("ASAN: Crashing target!"); } original(s1, s2) } From 8e5e6a43e901808d46b8a9789974a104c8b8a27b Mon Sep 17 00:00:00 2001 From: s1341 Date: Tue, 14 Jan 2025 17:24:39 +0200 Subject: [PATCH 05/17] fmt --- libafl_frida/src/alloc.rs | 23 +- libafl_frida/src/asan/hook_funcs.rs | 318 ++++++++++++++++++---------- 2 files changed, 225 insertions(+), 116 deletions(-) diff --git a/libafl_frida/src/alloc.rs b/libafl_frida/src/alloc.rs index 406356f051..ece38bea1f 100644 --- a/libafl_frida/src/alloc.rs +++ b/libafl_frida/src/alloc.rs @@ -260,18 +260,22 @@ impl Allocator { pub unsafe fn release(&mut self, ptr: *mut c_void) { log::info!("release {:?}", ptr); let Some(metadata) = self.allocations.get_mut(&(ptr as usize)) else { - if !ptr.is_null() && AsanErrors::get_mut_blocking() - .report_error(AsanError::UnallocatedFree((ptr as usize, Backtrace::new()))) { + if !ptr.is_null() + && AsanErrors::get_mut_blocking() + .report_error(AsanError::UnallocatedFree((ptr as usize, Backtrace::new()))) + { panic!("ASAN: Crashing target!"); } return; }; - if metadata.freed && AsanErrors::get_mut_blocking().report_error(AsanError::DoubleFree(( + if metadata.freed + && AsanErrors::get_mut_blocking().report_error(AsanError::DoubleFree(( ptr as usize, metadata.clone(), Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } let shadow_mapping_start = map_to_shadow!(self, ptr as usize); @@ -577,15 +581,14 @@ impl Allocator { /// Checks if any of the allocations has not been freed pub fn check_for_leaks(&self) { for metadata in self.allocations.values() { - if !metadata.freed && AsanErrors::get_mut_blocking() - .report_error(AsanError::Leak((metadata.address, metadata.clone()))) { + if !metadata.freed + && AsanErrors::get_mut_blocking() + .report_error(AsanError::Leak((metadata.address, metadata.clone()))) + { unsafe { println!( "{:x?}", - std::slice::from_raw_parts( - metadata.address as *const u8, - metadata.size - ) + std::slice::from_raw_parts(metadata.address as *const u8, metadata.size) ); }; panic!("ASAN: Crashing target!"); diff --git a/libafl_frida/src/asan/hook_funcs.rs b/libafl_frida/src/asan/hook_funcs.rs index 401022753a..82a787f1cd 100644 --- a/libafl_frida/src/asan/hook_funcs.rs +++ b/libafl_frida/src/asan/hook_funcs.rs @@ -1476,13 +1476,15 @@ impl AsanRuntime { buf: *const c_void, count: usize, ) -> usize { - if !self.allocator_mut().check_shadow(buf, count) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(buf, count) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "write".to_string(), self.real_address_for_stalked(self.pc()), buf as usize, count, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(fd, buf, count) @@ -1507,13 +1509,15 @@ impl AsanRuntime { buf: *mut c_void, count: usize, ) -> usize { - if !self.allocator_mut().check_shadow(buf, count) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(buf, count) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "read".to_string(), self.real_address_for_stalked(self.pc()), buf as usize, count, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(fd, buf, count) @@ -1527,13 +1531,15 @@ impl AsanRuntime { 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(( + if !self.allocator_mut().check_shadow(s, size as usize) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "fgets".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size as usize, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s, size, stream) @@ -1547,22 +1553,26 @@ impl AsanRuntime { s2: *const c_void, n: usize, ) -> i32 { - if !self.allocator_mut().check_shadow(s1, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s1, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(s2, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s2, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s1, s2, n) @@ -1576,22 +1586,26 @@ impl AsanRuntime { 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(( + if !self.allocator_mut().check_shadow(dest, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(src, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(src, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(dest, src, n) @@ -1606,22 +1620,26 @@ impl AsanRuntime { 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(( + if !self.allocator_mut().check_shadow(dest, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "mempcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(src, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(src, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "mempcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(dest, src, n) @@ -1635,22 +1653,26 @@ impl AsanRuntime { 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(( + if !self.allocator_mut().check_shadow(dest, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memmove".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(src, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(src, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmove".to_string(), self.real_address_for_stalked(self.pc()), src as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } @@ -1665,13 +1687,15 @@ impl AsanRuntime { c: i32, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(dest, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(dest, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(dest, c, n) @@ -1685,13 +1709,15 @@ impl AsanRuntime { c: i32, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(s, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s, c, n) @@ -1706,13 +1732,15 @@ impl AsanRuntime { c: i32, n: usize, ) -> *mut c_void { - if !self.allocator_mut().check_shadow(s, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memrchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s, c, n) @@ -1732,22 +1760,26 @@ impl AsanRuntime { 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(( + if !self.allocator_mut().check_shadow(haystack, haystacklen) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmem".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, haystacklen, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(needle, needlelen) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(needle, needlelen) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "memmem".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, needlelen, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(haystack, haystacklen, needle, needlelen) @@ -1761,13 +1793,15 @@ impl AsanRuntime { s: *mut c_void, n: usize, ) -> usize { - if !self.allocator_mut().check_shadow(s, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(s, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "bzero".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s, n) @@ -1781,13 +1815,15 @@ impl AsanRuntime { s: *mut c_void, n: usize, ) -> usize { - if !self.allocator_mut().check_shadow(s, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(s, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "explicit_bzero".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s, n) @@ -1802,22 +1838,26 @@ impl AsanRuntime { s2: *const c_void, n: usize, ) -> i32 { - if !self.allocator_mut().check_shadow(s1, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s1, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "bcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(s2, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s2, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "bcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s1, s2, n) @@ -1836,13 +1876,15 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s, c) @@ -1860,13 +1902,15 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strrchr".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s, c) @@ -1884,24 +1928,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasecmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasecmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s1, s2) @@ -1915,22 +1963,26 @@ impl AsanRuntime { 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(( + if !self.allocator_mut().check_shadow(s1 as *const c_void, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncasecmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(s2 as *const c_void, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s2 as *const c_void, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncasecmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s1, s2, n) @@ -1948,24 +2000,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcat".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcat".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s1, s2) @@ -1983,24 +2039,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { strlen(s1) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, unsafe { strlen(s1) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { strlen(s2) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, unsafe { strlen(s2) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s1, s2) @@ -2019,24 +2079,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { strnlen(s1, n) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { strnlen(s1, n) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { strnlen(s2, n) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { strnlen(s2, n) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s1, s2, n) @@ -2054,24 +2118,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(dest as *const c_void, unsafe { strlen(src) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + .check_shadow(dest as *const c_void, unsafe { strlen(src) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "strcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, unsafe { strlen(src) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(src as *const c_void, unsafe { strlen(src) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(src as *const c_void, unsafe { strlen(src) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, unsafe { strlen(src) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(dest, src) @@ -2088,23 +2156,27 @@ impl AsanRuntime { extern "system" { fn strlen(s: *const c_char) -> usize; } - if !self.allocator_mut().check_shadow(dest as *const c_void, n) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(dest as *const c_void, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "strncpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, n, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } let mn = std::cmp::min(n, unsafe { strlen(src) } + 1); - if !self.allocator_mut().check_shadow(src as *const c_void, mn) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(src as *const c_void, mn) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strncpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, mn, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(dest, src, n) @@ -2122,24 +2194,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(dest as *const c_void, unsafe { strlen(src) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + .check_shadow(dest as *const c_void, unsafe { strlen(src) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "stpcpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, unsafe { strlen(src) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(src as *const c_void, unsafe { strlen(src) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(src as *const c_void, unsafe { strlen(src) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "stpcpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, unsafe { strlen(src) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(dest, src) @@ -2165,13 +2241,15 @@ impl AsanRuntime { fn strcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; } let size = unsafe { strlen(s) + 1 }; - if !self.allocator_mut().check_shadow(s as *const c_void, size) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + if !self.allocator_mut().check_shadow(s as *const c_void, size) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strdup".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) + 1 }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } @@ -2189,13 +2267,15 @@ impl AsanRuntime { 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(( + if !self.allocator_mut().check_shadow(s as *const c_void, size) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strlen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } size @@ -2209,13 +2289,15 @@ impl AsanRuntime { 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(( + if !self.allocator_mut().check_shadow(s as *const c_void, size) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strnlen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, size, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } size @@ -2233,24 +2315,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strstr".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, unsafe { strlen(haystack) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strstr".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, unsafe { strlen(needle) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(haystack, needle) @@ -2268,24 +2354,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(haystack as *const c_void, unsafe { strlen(haystack) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasestr".to_string(), self.real_address_for_stalked(self.pc()), haystack as usize, unsafe { strlen(haystack) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(needle as *const c_void, unsafe { strlen(needle) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "strcasestr".to_string(), self.real_address_for_stalked(self.pc()), needle as usize, unsafe { strlen(needle) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(haystack, needle) @@ -2302,13 +2392,15 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atoi".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s) @@ -2326,13 +2418,15 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atol".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s) @@ -2350,13 +2444,15 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s as *const c_void, unsafe { strlen(s) }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, unsafe { strlen(s) }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "atoll".to_string(), self.real_address_for_stalked(self.pc()), s as usize, unsafe { strlen(s) }, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s) @@ -2372,13 +2468,15 @@ impl AsanRuntime { let size = original(s); if !self .allocator_mut() - .check_shadow(s as *const c_void, (size + 1) * 2) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s as *const c_void, (size + 1) * 2) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcslen".to_string(), self.real_address_for_stalked(self.pc()), s as usize, (size + 1) * 2, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } size @@ -2397,24 +2495,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(dest as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + .check_shadow(dest as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "wcscpy".to_string(), self.real_address_for_stalked(self.pc()), dest as usize, (unsafe { wcslen(src) } + 1) * 2, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(src as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(src as *const c_void, unsafe { (wcslen(src) + 1) * 2 }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscpy".to_string(), self.real_address_for_stalked(self.pc()), src as usize, (unsafe { wcslen(src) } + 1) * 2, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(dest, src) @@ -2433,24 +2535,28 @@ impl AsanRuntime { } if !self .allocator_mut() - .check_shadow(s1 as *const c_void, unsafe { (wcslen(s1) + 1) * 2 }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s1 as *const c_void, unsafe { (wcslen(s1) + 1) * 2 }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscmp".to_string(), self.real_address_for_stalked(self.pc()), s1 as usize, (unsafe { wcslen(s1) } + 1) * 2, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } if !self .allocator_mut() - .check_shadow(s2 as *const c_void, unsafe { (wcslen(s2) + 1) * 2 }) && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( + .check_shadow(s2 as *const c_void, unsafe { (wcslen(s2) + 1) * 2 }) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgRead(( "wcscmp".to_string(), self.real_address_for_stalked(self.pc()), s2 as usize, (unsafe { wcslen(s2) } + 1) * 2, Backtrace::new(), - ))) { + ))) + { panic!("ASAN: Crashing target!"); } original(s1, s2) From 3c91d04fbc2741830d0bc5f3e67be35ad581656a Mon Sep 17 00:00:00 2001 From: s1341 Date: Tue, 14 Jan 2025 17:39:42 +0200 Subject: [PATCH 06/17] Clippy --- libafl_frida/src/asan/asan_rt.rs | 3 +- libafl_frida/src/asan/errors.rs | 2 +- libafl_frida/src/asan/hook_funcs.rs | 70 ++++++++++++++++------------- 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index 7e7ce1e65e..1b5b35c94f 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -104,7 +104,7 @@ unsafe fn thread_local_initted() -> bool { "mrs {tid}, TPIDRRO_EL0", tid = out(reg) tid, ); - tid = tid & 0xffff_ffff_ffff_fff8; + tid &= 0xffff_ffff_ffff_fff8; let tlsptr = tid as *const u64; tlsptr.add(0x102).read() != 0u64 } @@ -1543,6 +1543,7 @@ impl AsanRuntime { backtrace, )) }; + #[allow(clippy::manual_assert)] if AsanErrors::get_mut_blocking().report_error(error) { panic!("ASAN: Crashing target!"); } diff --git a/libafl_frida/src/asan/errors.rs b/libafl_frida/src/asan/errors.rs index 12bc152640..79c16ae7b2 100644 --- a/libafl_frida/src/asan/errors.rs +++ b/libafl_frida/src/asan/errors.rs @@ -298,6 +298,7 @@ impl AsanErrors { writeln!(output, "{:━^100}", " ALLOCATION INFO ").unwrap(); let fault_address: i64 = fault_address.try_into().unwrap(); let metadata_address: i64 = error.metadata.address.try_into().unwrap(); + #[allow(clippy::cast_possible_wrap)] let offset: i64 = fault_address - (metadata_address + MmapOptions::page_size() as i64); let direction = if offset > 0 { "right" } else { "left" }; @@ -565,7 +566,6 @@ impl AsanErrors { self.errors.push(error); - #[expect(clippy::manual_assert)] !self.continue_on_error } } diff --git a/libafl_frida/src/asan/hook_funcs.rs b/libafl_frida/src/asan/hook_funcs.rs index 82a787f1cd..f5ba2d1945 100644 --- a/libafl_frida/src/asan/hook_funcs.rs +++ b/libafl_frida/src/asan/hook_funcs.rs @@ -895,7 +895,6 @@ impl AsanRuntime { } #[inline] - #[expect(clippy::cmp_null)] pub fn hook_check_realloc(&mut self, ptr: *mut c_void, _size: usize) -> bool { self.allocator_mut().is_managed(ptr) } @@ -928,7 +927,6 @@ impl AsanRuntime { } #[inline] - #[expect(clippy::cmp_null)] #[cfg(target_vendor = "apple")] pub fn hook_check_reallocf(&mut self, ptr: *mut c_void, _size: usize) -> bool { self.allocator_mut().is_managed(ptr) @@ -1091,6 +1089,8 @@ impl AsanRuntime { } #[inline] #[cfg(target_vendor = "apple")] + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] pub fn hook__os_log_impl( &mut self, _original: extern "C" fn( @@ -1111,6 +1111,8 @@ impl AsanRuntime { } #[inline] #[cfg(target_vendor = "apple")] + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] pub fn hook__os_log_fault_impl( &mut self, _original: extern "C" fn( @@ -1131,6 +1133,8 @@ impl AsanRuntime { } #[inline] #[cfg(target_vendor = "apple")] + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] pub fn hook__os_log_error_impl( &mut self, _original: extern "C" fn( @@ -1151,6 +1155,8 @@ impl AsanRuntime { } #[inline] #[cfg(target_vendor = "apple")] + #[allow(clippy::too_many_arguments)] + #[allow(non_snake_case)] pub fn hook__os_log_debug_impl( &mut self, _original: extern "C" fn( @@ -2571,27 +2577,27 @@ impl AsanRuntime { p4: *const c_void, n: usize, ) { - if !self.allocator_mut().check_shadow(s, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(s, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern4".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))) { - panic!("ASAN: Crashing target!"); - }; + ))) + { + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(p4, n / 4) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(p4, n / 4) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern4".to_string(), self.real_address_for_stalked(self.pc()), p4 as usize, n / 4, Backtrace::new(), - ))) { - panic!("ASAN: Crashing target!"); - }; + ))) + { + panic!("ASAN: Crashing target!"); } original(s, p4, n); } @@ -2605,27 +2611,27 @@ impl AsanRuntime { p8: *const c_void, n: usize, ) { - if !self.allocator_mut().check_shadow(s, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(s, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern8".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))) { - panic!("ASAN: Crashing target!"); - }; + ))) + { + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(p8, n / 8) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(p8, n / 8) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern8".to_string(), self.real_address_for_stalked(self.pc()), p8 as usize, n / 8, Backtrace::new(), - ))) { - panic!("ASAN: Crashing target!"); - }; + ))) + { + panic!("ASAN: Crashing target!"); } original(s, p8, n); } @@ -2639,27 +2645,27 @@ impl AsanRuntime { p16: *const c_void, n: usize, ) { - if !self.allocator_mut().check_shadow(s, n) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(s, n) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern16".to_string(), self.real_address_for_stalked(self.pc()), s as usize, n, Backtrace::new(), - ))) { - panic!("ASAN: Crashing target!"); - }; + ))) + { + panic!("ASAN: Crashing target!"); } - if !self.allocator_mut().check_shadow(p16, n / 16) { - if AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( + if !self.allocator_mut().check_shadow(p16, n / 16) + && AsanErrors::get_mut_blocking().report_error(AsanError::BadFuncArgWrite(( "memset_pattern16".to_string(), self.real_address_for_stalked(self.pc()), p16 as usize, n / 16, Backtrace::new(), - ))) { - panic!("ASAN: Crashing target!"); - }; + ))) + { + panic!("ASAN: Crashing target!"); } original(s, p16, n); } From 05c88d20c698601d45d9080a52d1e786d7b9f490 Mon Sep 17 00:00:00 2001 From: s1341 Date: Tue, 14 Jan 2025 17:45:41 +0200 Subject: [PATCH 07/17] Update to frida 0.16.2 --- fuzzers/binary_only/frida_executable_libpng/Cargo.toml | 2 +- fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fuzzers/binary_only/frida_executable_libpng/Cargo.toml b/fuzzers/binary_only/frida_executable_libpng/Cargo.toml index 2be49193a2..7ca933659b 100644 --- a/fuzzers/binary_only/frida_executable_libpng/Cargo.toml +++ b/fuzzers/binary_only/frida_executable_libpng/Cargo.toml @@ -25,7 +25,7 @@ libafl = { path = "../../../libafl", features = [ "frida_cli", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.15.1", features = [ +frida-gum = { version = "0.16.2", features = [ "auto-download", "event-sink", "invocation-listener", diff --git a/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml b/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml index 92ae48c01e..8e0d095356 100644 --- a/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml +++ b/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml @@ -23,7 +23,7 @@ libafl = { path = "../../../libafl", features = [ "errors_backtrace", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.15.1", features = [ +frida-gum = { version = "0.16.2", features = [ "auto-download", "event-sink", "invocation-listener", From 0b8bcae44e52c2f1fd533be64359ed9cdfd20bac Mon Sep 17 00:00:00 2001 From: s1341 Date: Tue, 14 Jan 2025 18:14:26 +0200 Subject: [PATCH 08/17] fix windows hooks --- libafl_frida/src/windows_hooks.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libafl_frida/src/windows_hooks.rs b/libafl_frida/src/windows_hooks.rs index f02e2f2f12..1a3d14ad6f 100644 --- a/libafl_frida/src/windows_hooks.rs +++ b/libafl_frida/src/windows_hooks.rs @@ -1,7 +1,7 @@ // Based on the example of setting hooks: Https://github.com/frida/frida-rust/blob/main/examples/gum/hook_open/src/lib.rs use std::ffi::c_void; -use frida_gum::{interceptor::Interceptor, Gum, Module, NativePointer}; +use frida_gum::{interceptor::Interceptor, Gum, Process, NativePointer}; use libafl_bolts::os::windows_exceptions::{ handle_exception, IsProcessorFeaturePresent, UnhandledExceptionFilter, EXCEPTION_POINTERS, PROCESSOR_FEATURE_ID, @@ -21,16 +21,16 @@ unsafe extern "C" fn unhandled_exception_filter_detour( } /// Initialize the hooks pub fn initialize(gum: &Gum) { - let module = Module::obtain(gum); + let module = Process::obtain(gum).find_module_by_name("kernel32.dll").unwrap(); let is_processor_feature_present = - module.find_export_by_name(Some("kernel32.dll"), "IsProcessorFeaturePresent"); + module.find_export_by_name("IsProcessorFeaturePresent"); let is_processor_feature_present = is_processor_feature_present.unwrap(); assert!( !is_processor_feature_present.is_null(), "IsProcessorFeaturePresent not found" ); let unhandled_exception_filter = - module.find_export_by_name(Some("kernel32.dll"), "UnhandledExceptionFilter"); + module.find_export_by_name("UnhandledExceptionFilter"); let unhandled_exception_filter = unhandled_exception_filter.unwrap(); assert!( !unhandled_exception_filter.is_null(), From ea359e9a64fbd8e54a9880e24ccd3dd7964a0093 Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 08:11:18 +0200 Subject: [PATCH 09/17] Fix --- libafl_frida/src/asan/asan_rt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index 1b5b35c94f..932ca451bf 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -655,7 +655,7 @@ impl AsanRuntime { macro_rules! hook_heap_windows { ($libname:literal, $lib_ident:ident) => { log::info!("Hooking allocator functions in {}", $libname); - for export in process.find_module_by_name($libname).enumerate_exports() { + for export in process.find_module_by_name($libname).expect("Failed to find module").enumerate_exports() { // log::trace!("- {}", export.name); match &export.name[..] { "NtGdiCreateCompatibleDC" => { From 175ea6f9414630607956b0b1a4a2ea207afdb911 Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 08:11:36 +0200 Subject: [PATCH 10/17] Fmt --- libafl_frida/src/windows_hooks.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libafl_frida/src/windows_hooks.rs b/libafl_frida/src/windows_hooks.rs index 1a3d14ad6f..772ef469d5 100644 --- a/libafl_frida/src/windows_hooks.rs +++ b/libafl_frida/src/windows_hooks.rs @@ -1,7 +1,7 @@ // Based on the example of setting hooks: Https://github.com/frida/frida-rust/blob/main/examples/gum/hook_open/src/lib.rs use std::ffi::c_void; -use frida_gum::{interceptor::Interceptor, Gum, Process, NativePointer}; +use frida_gum::{interceptor::Interceptor, Gum, NativePointer, Process}; use libafl_bolts::os::windows_exceptions::{ handle_exception, IsProcessorFeaturePresent, UnhandledExceptionFilter, EXCEPTION_POINTERS, PROCESSOR_FEATURE_ID, @@ -21,16 +21,16 @@ unsafe extern "C" fn unhandled_exception_filter_detour( } /// Initialize the hooks pub fn initialize(gum: &Gum) { - let module = Process::obtain(gum).find_module_by_name("kernel32.dll").unwrap(); - let is_processor_feature_present = - module.find_export_by_name("IsProcessorFeaturePresent"); + let module = Process::obtain(gum) + .find_module_by_name("kernel32.dll") + .unwrap(); + let is_processor_feature_present = module.find_export_by_name("IsProcessorFeaturePresent"); let is_processor_feature_present = is_processor_feature_present.unwrap(); assert!( !is_processor_feature_present.is_null(), "IsProcessorFeaturePresent not found" ); - let unhandled_exception_filter = - module.find_export_by_name("UnhandledExceptionFilter"); + let unhandled_exception_filter = module.find_export_by_name("UnhandledExceptionFilter"); let unhandled_exception_filter = unhandled_exception_filter.unwrap(); assert!( !unhandled_exception_filter.is_null(), From ba81634cc3938294491790660717f0e3aaa910de Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 08:27:25 +0200 Subject: [PATCH 11/17] windows fix --- libafl_frida/src/asan/asan_rt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index 932ca451bf..5eb23ddf8c 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -1188,7 +1188,7 @@ impl AsanRuntime { #[cfg(not(windows))] hook_func!("libc", libc, strdup, (s: *const c_char), *mut c_char); #[cfg(windows)] - hook_func!(_strdup, (s: *const c_char), *mut c_char); + hook_func!("libc", libc, _strdup, (s: *const c_char), *mut c_char); hook_func!("libc", libc, strlen, (s: *const c_char), usize); hook_func!("libc", libc, strnlen, (s: *const c_char, n: usize), usize); hook_func!( From 4b41c3a80cb1e094457b6aa563f293782928b1a4 Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 08:30:13 +0200 Subject: [PATCH 12/17] Bump frida version to 0.16.3 --- fuzzers/binary_only/frida_executable_libpng/Cargo.toml | 2 +- fuzzers/binary_only/frida_libpng/Cargo.toml | 2 +- fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml | 2 +- libafl_frida/Cargo.toml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fuzzers/binary_only/frida_executable_libpng/Cargo.toml b/fuzzers/binary_only/frida_executable_libpng/Cargo.toml index 7ca933659b..7cb2591e83 100644 --- a/fuzzers/binary_only/frida_executable_libpng/Cargo.toml +++ b/fuzzers/binary_only/frida_executable_libpng/Cargo.toml @@ -25,7 +25,7 @@ libafl = { path = "../../../libafl", features = [ "frida_cli", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.16.2", features = [ +frida-gum = { version = "0.16.3", features = [ "auto-download", "event-sink", "invocation-listener", diff --git a/fuzzers/binary_only/frida_libpng/Cargo.toml b/fuzzers/binary_only/frida_libpng/Cargo.toml index 7b477c220e..7332bd38cb 100644 --- a/fuzzers/binary_only/frida_libpng/Cargo.toml +++ b/fuzzers/binary_only/frida_libpng/Cargo.toml @@ -27,7 +27,7 @@ libafl = { path = "../../../libafl", features = [ "errors_backtrace", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.16.2", features = [ +frida-gum = { version = "0.16.3", features = [ "auto-download", "event-sink", "invocation-listener", diff --git a/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml b/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml index 8e0d095356..fb00bd0d10 100644 --- a/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml +++ b/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml @@ -23,7 +23,7 @@ libafl = { path = "../../../libafl", features = [ "errors_backtrace", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.16.2", features = [ +frida-gum = { version = "0.16.3", features = [ "auto-download", "event-sink", "invocation-listener", diff --git a/libafl_frida/Cargo.toml b/libafl_frida/Cargo.toml index ce152f821e..f71866e401 100644 --- a/libafl_frida/Cargo.toml +++ b/libafl_frida/Cargo.toml @@ -62,11 +62,11 @@ nix = { workspace = true, default-features = true, features = ["mman"] } libc = { workspace = true } hashbrown = { workspace = true, default-features = true } rangemap = { workspace = true } -frida-gum-sys = { version = "0.16.2", features = [ +frida-gum-sys = { version = "0.16.3", features = [ "event-sink", "invocation-listener", ] } -frida-gum = { version = "0.16.2", features = [ +frida-gum = { version = "0.16.3", features = [ "event-sink", "invocation-listener", "module-names", From c21161eebc41b08a3fea285cc837c79ce7f4fe14 Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 09:36:02 +0200 Subject: [PATCH 13/17] Get rid of call to LLVMFuzzerInitialize --- fuzzers/binary_only/frida_libpng/src/fuzzer.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs index 0a6c87abe8..2d89401695 100644 --- a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs @@ -83,17 +83,10 @@ fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { // println!("{:?}", mgr.mgr_id()); let lib = unsafe { libloading::Library::new(options.clone().harness.unwrap()).unwrap() }; - let init_func: libloading::Symbol< - unsafe extern "C" fn(argc: *const usize, argv: *const *const *const u8), - > = unsafe { lib.get("LLVMFuzzerInitialize".as_bytes()).unwrap() }; let target_func: libloading::Symbol< unsafe extern "C" fn(data: *const u8, size: usize) -> i32, > = unsafe { lib.get(options.harness_function.as_bytes()).unwrap() }; - unsafe { - init_func(std::ptr::null(), std::ptr::null()); - } - let mut frida_harness = |input: &BytesInput| { let target = input.target_bytes(); let buf = target.as_slice(); @@ -261,7 +254,7 @@ fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { .run_client(&mut run_client) .cores(&options.cores) .broker_port(options.broker_port) - // .stdout_file(Some(&options.stdout)) + .stdout_file(Some(&options.stdout)) .remote_broker_addr(options.remote_broker_addr) .build() .launch() From 165b13b6612eea4316de0547fc6a45aba85ff62e Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 10:20:25 +0200 Subject: [PATCH 14/17] bump version 0.16.5; use find_global_export_by_name --- .../frida_executable_libpng/Cargo.toml | 2 +- fuzzers/binary_only/frida_libpng/Cargo.toml | 2 +- .../frida_windows_gdiplus/Cargo.toml | 2 +- libafl_frida/Cargo.toml | 4 +- libafl_frida/src/asan/asan_rt.rs | 211 +++++++++++++----- 5 files changed, 162 insertions(+), 59 deletions(-) diff --git a/fuzzers/binary_only/frida_executable_libpng/Cargo.toml b/fuzzers/binary_only/frida_executable_libpng/Cargo.toml index 7cb2591e83..afea67e201 100644 --- a/fuzzers/binary_only/frida_executable_libpng/Cargo.toml +++ b/fuzzers/binary_only/frida_executable_libpng/Cargo.toml @@ -25,7 +25,7 @@ libafl = { path = "../../../libafl", features = [ "frida_cli", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.16.3", features = [ +frida-gum = { version = "0.16.5", features = [ "auto-download", "event-sink", "invocation-listener", diff --git a/fuzzers/binary_only/frida_libpng/Cargo.toml b/fuzzers/binary_only/frida_libpng/Cargo.toml index 7332bd38cb..f1c9a9bcaf 100644 --- a/fuzzers/binary_only/frida_libpng/Cargo.toml +++ b/fuzzers/binary_only/frida_libpng/Cargo.toml @@ -27,7 +27,7 @@ libafl = { path = "../../../libafl", features = [ "errors_backtrace", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.16.3", features = [ +frida-gum = { version = "0.16.5", features = [ "auto-download", "event-sink", "invocation-listener", diff --git a/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml b/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml index fb00bd0d10..87f623f20f 100644 --- a/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml +++ b/fuzzers/binary_only/frida_windows_gdiplus/Cargo.toml @@ -23,7 +23,7 @@ libafl = { path = "../../../libafl", features = [ "errors_backtrace", ] } #, "llmp_small_maps", "llmp_debug"]} libafl_bolts = { path = "../../../libafl_bolts" } -frida-gum = { version = "0.16.3", features = [ +frida-gum = { version = "0.16.5", features = [ "auto-download", "event-sink", "invocation-listener", diff --git a/libafl_frida/Cargo.toml b/libafl_frida/Cargo.toml index f71866e401..f8c4e80c34 100644 --- a/libafl_frida/Cargo.toml +++ b/libafl_frida/Cargo.toml @@ -62,11 +62,11 @@ nix = { workspace = true, default-features = true, features = ["mman"] } libc = { workspace = true } hashbrown = { workspace = true, default-features = true } rangemap = { workspace = true } -frida-gum-sys = { version = "0.16.3", features = [ +frida-gum-sys = { version = "0.16.5", features = [ "event-sink", "invocation-listener", ] } -frida-gum = { version = "0.16.3", features = [ +frida-gum = { version = "0.16.5", features = [ "event-sink", "invocation-listener", "module-names", diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index 5eb23ddf8c..edafd25cc5 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -477,10 +477,56 @@ impl AsanRuntime { let mut interceptor = Interceptor::obtain(gum); let process = Process::obtain(gum); macro_rules! hook_func { + ($name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty) => { + paste::paste! { + + let target_function = Module::find_global_export_by_name(stringify!($name)).expect("Failed to find function"); + log::warn!("Hooking {} = {:?}", stringify!($name), target_function.0); + + 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); + //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 { + if thread_local_initted() { + if !ASAN_IN_HOOK.get() { + ASAN_IN_HOOK.set(true); + let ret = this.[](*original, $($param),*); + ASAN_IN_HOOK.set(false); + ret + } else { + (original)($($param),*) + } + } else { + (original)($($param),*) + } + } else { + (original)($($param),*) + } + } + + 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::warn!("Hooking {}:{}", $lib, stringify!($name)); let target_function = process.find_module_by_name($lib).expect("Failed to find module").find_export_by_name(stringify!($name)).expect("Failed to find function"); log::warn!("Hooking {}:{} = {:?}", $lib, stringify!($name), target_function.0); @@ -526,6 +572,59 @@ impl AsanRuntime { } macro_rules! hook_func_with_check { + ($name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty, $always_enabled:expr) => { + paste::paste! { + let target_function = Module::find_global_export_by_name(stringify!($name)).expect("Failed to find function"); + + log::warn!("Hooking {} = {:?}", stringify!($name), target_function.0); + 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(); + //don't check if hooks are enabled as there are certain cases where we want to run the hook even if we are out of the program + //For example, sometimes libafl will allocate certain things during the run and free them after the run. This results in a bug where a buffer will come from libafl-frida alloc and be freed in the normal allocator. + if $always_enabled || this.hooks_enabled { + if thread_local_initted() { + if !ASAN_IN_HOOK.get() { + ASAN_IN_HOOK.set(true); + let ret = if this.[]($($param),*) { + this.[](*original, $($param),*) + } else { + (original)($($param),*) + }; + ASAN_IN_HOOK.set(false); + ret + } else { + (original)($($param),*) + } + } else { + let ret = if $always_enabled && this.[]($($param),*) { + this.[](*original, $($param),*) + } else { + (original)($($param),*) + }; + ret + } + } else { + (original)($($param),*) + } + + } + + 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, $always_enabled:expr) => { paste::paste! { @@ -586,31 +685,31 @@ impl AsanRuntime { // Hook the memory allocator functions #[cfg(not(windows))] - hook_func!("libc", libc, malloc, (size: usize), *mut c_void); + hook_func!(malloc, (size: usize), *mut c_void); #[cfg(not(windows))] - hook_func!("libc", libc, calloc, (nmemb: usize, size: usize), *mut c_void); + hook_func!(calloc, (nmemb: usize, size: usize), *mut c_void); #[cfg(not(windows))] - hook_func_with_check!("libc", libc, realloc, (ptr: *mut c_void, size: usize), *mut c_void, false); + hook_func_with_check!(realloc, (ptr: *mut c_void, size: usize), *mut c_void, false); #[cfg(not(windows))] - hook_func_with_check!("libc", libc, free, (ptr: *mut c_void), usize, true); + hook_func_with_check!(free, (ptr: *mut c_void), usize, true); #[cfg(not(any(target_vendor = "apple", windows)))] - hook_func!("libc", libc, memalign, (size: usize, alignment: usize), *mut c_void); + hook_func!(memalign, (size: usize, alignment: usize), *mut c_void); #[cfg(not(windows))] hook_func!( - "libc", libc, posix_memalign, + posix_memalign, (pptr: *mut *mut c_void, size: usize, alignment: usize), i32 ); #[cfg(not(any(target_vendor = "apple", windows)))] - hook_func!("libc", libc, malloc_usable_size, (ptr: *mut c_void), usize); + hook_func!(malloc_usable_size, (ptr: *mut c_void), usize); #[cfg(target_vendor = "apple")] - hook_func!("libc", libc, valloc, (size: usize), *mut c_void); + hook_func!(valloc, (size: usize), *mut c_void); #[cfg(target_vendor = "apple")] - hook_func_with_check!("libc", libc, reallocf, (ptr: *mut c_void, size: usize), *mut c_void, false); + hook_func_with_check!(reallocf, (ptr: *mut c_void, size: usize), *mut c_void, false); #[cfg(target_vendor = "apple")] - hook_func_with_check!("libc", libc, malloc_size, (ptr: *mut c_void), usize, false); + hook_func_with_check!(malloc_size, (ptr: *mut c_void), usize, false); #[cfg(target_vendor = "apple")] - hook_func_with_check!("libc", libc, malloc_good_size, (ptr: *mut c_void), usize, false); + hook_func_with_check!(malloc_good_size, (ptr: *mut c_void), usize, false); #[cfg(target_vendor = "apple")] hook_func!("libSystem.B.dylib", libSystemB, os_log_type_enabled, (oslog: *mut c_void, r#type: u8), bool); #[cfg(target_vendor = "apple")] @@ -621,7 +720,9 @@ impl AsanRuntime { hook_func!("libSystem.B.dylib", libSystemB, _os_log_error_impl, (dso: *const c_void, log: *mut c_void, r#type: u8, format: *const c_char, buf: *const u8, size: u32), ()); #[cfg(target_vendor = "apple")] hook_func!("libSystem.B.dylib", libSystemB, _os_log_debug_impl, (dso: *const c_void, log: *mut c_void, r#type: u8, format: *const c_char, buf: *const u8, size: u32), ()); + #[cfg(target_vendor = "apple")] hook_func!("libc++.1.dylib", libcpp, __cxa_allocate_exception, (size: usize), *const c_void); + #[cfg(target_vendor = "apple")] hook_func!("libc++.1.dylib", libcpp, __cxa_free_exception, (ptr: *mut c_void), usize); // // #[cfg(windows)] // hook_priv_func!( @@ -655,7 +756,8 @@ impl AsanRuntime { macro_rules! hook_heap_windows { ($libname:literal, $lib_ident:ident) => { log::info!("Hooking allocator functions in {}", $libname); - for export in process.find_module_by_name($libname).expect("Failed to find module").enumerate_exports() { + if let Some(module) = process.find_module_by_name($libname) { + for export in module.enumerate_exports() { // log::trace!("- {}", export.name); match &export.name[..] { "NtGdiCreateCompatibleDC" => { @@ -841,7 +943,7 @@ impl AsanRuntime { } _ => (), } - } + }} } } #[cfg(windows)] @@ -881,7 +983,8 @@ impl AsanRuntime { macro_rules! hook_cpp { ($libname:literal, $lib_ident:ident) => { log::info!("Hooking c++ functions in {}", $libname); - for export in process.find_module_by_name($libname).expect("Failed to find module").enumerate_exports() { + if let Some(module) = process.find_module_by_name($libname) { + for export in module.enumerate_exports() { match &export.name[..] { "_Znam" => { hook_func!($libname, $lib_ident, _Znam, (size: usize), *mut c_void); @@ -1015,7 +1118,7 @@ impl AsanRuntime { } _ => {} } - } + }} } } #[cfg(target_os = "linux")] @@ -1038,7 +1141,7 @@ impl AsanRuntime { #[cfg(not(windows))] hook_func!( - "libc", libc, + mmap, ( addr: *const c_void, @@ -1051,39 +1154,39 @@ impl AsanRuntime { *mut c_void ); #[cfg(not(windows))] - hook_func!("libc", libc, 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!( - "libc", libc, + write, (fd: i32, buf: *const c_void, count: usize), usize ); #[cfg(not(windows))] - hook_func!("libc", libc, read, (fd: i32, buf: *mut c_void, count: usize), usize); + hook_func!(read, (fd: i32, buf: *mut c_void, count: usize), usize); hook_func!( - "libc", libc, + fgets, (s: *mut c_void, size: u32, stream: *mut c_void), *mut c_void ); hook_func!( - "libc", libc, + memcmp, (s1: *const c_void, s2: *const c_void, n: usize), i32 ); hook_func!( - "libc", libc, + memcpy, (dest: *mut c_void, src: *const c_void, n: usize), *mut c_void ); #[cfg(not(any(target_vendor = "apple", windows)))] hook_func!( - "libc", libc, + mempcpy, (dest: *mut c_void, src: *const c_void, n: usize), *mut c_void @@ -1096,27 +1199,27 @@ impl AsanRuntime { // *mut c_void // ); hook_func!( - "libc", libc, + memset, (s: *mut c_void, c: i32, n: usize), *mut c_void ); hook_func!( - "libc", libc, + memchr, (s: *mut c_void, c: i32, n: usize), *mut c_void ); #[cfg(not(any(target_vendor = "apple", windows)))] hook_func!( - "libc", libc, + memrchr, (s: *mut c_void, c: i32, n: usize), *mut c_void ); #[cfg(not(windows))] hook_func!( - "libc", libc, + memmem, ( haystack: *const c_void, @@ -1127,9 +1230,9 @@ impl AsanRuntime { *mut c_void ); #[cfg(not(any(target_os = "android", windows)))] - hook_func!("libc", libc, 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!("libc", libc, 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, @@ -1137,101 +1240,101 @@ impl AsanRuntime { // (s1: *const c_void, s2: *const c_void, n: usize), // i32 // ); - hook_func!("libc", libc, strchr, (s: *mut c_char, c: i32), *mut c_char); - hook_func!("libc", libc, 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!( - "libc", libc, + strcasecmp, (s1: *const c_char, s2: *const c_char), i32 ); #[cfg(not(windows))] hook_func!( - "libc", libc, + strncasecmp, (s1: *const c_char, s2: *const c_char, n: usize), i32 ); hook_func!( - "libc", libc, + strcat, (dest: *mut c_char, src: *const c_char), *mut c_char ); - hook_func!("libc", libc, strcmp, (s1: *const c_char, s2: *const c_char), i32); + hook_func!(strcmp, (s1: *const c_char, s2: *const c_char), i32); hook_func!( - "libc", libc, + strncmp, (s1: *const c_char, s2: *const c_char, n: usize), i32 ); hook_func!( - "libc", libc, + strcpy, (dest: *mut c_char, src: *const c_char), *mut c_char ); hook_func!( - "libc", libc, + strncpy, (dest: *mut c_char, src: *const c_char, n: usize), *mut c_char ); #[cfg(not(windows))] hook_func!( - "libc", libc, + stpcpy, (dest: *mut c_char, src: *const c_char), *mut c_char ); #[cfg(not(windows))] - hook_func!("libc", libc, strdup, (s: *const c_char), *mut c_char); + hook_func!(strdup, (s: *const c_char), *mut c_char); #[cfg(windows)] - hook_func!("libc", libc, _strdup, (s: *const c_char), *mut c_char); - hook_func!("libc", libc, strlen, (s: *const c_char), usize); - hook_func!("libc", libc, 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!( - "libc", libc, + strstr, (haystack: *const c_char, needle: *const c_char), *mut c_char ); #[cfg(not(windows))] hook_func!( - "libc", libc, + strcasestr, (haystack: *const c_char, needle: *const c_char), *mut c_char ); - hook_func!("libc", libc, atoi, (nptr: *const c_char), i32); - hook_func!("libc", libc, atol, (nptr: *const c_char), i32); - hook_func!("libc", libc, atoll, (nptr: *const c_char), i64); - hook_func!("libc", libc, 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!( - "libc", libc, + wcscpy, (dest: *mut wchar_t, src: *const wchar_t), *mut wchar_t ); - hook_func!("libc", libc, 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!( - "libc", libc, + memset_pattern4, (s: *mut c_void, c: *const c_void, n: usize), () ); #[cfg(target_vendor = "apple")] hook_func!( - "libc", libc, + memset_pattern8, (s: *mut c_void, c: *const c_void, n: usize), () ); #[cfg(target_vendor = "apple")] hook_func!( - "libc", libc, + memset_pattern16, (s: *mut c_void, c: *const c_void, n: usize), () From 84b2aab37346ca1f02bd1acb98ffba68b1dbd46a Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 10:30:03 +0200 Subject: [PATCH 15/17] allow unused_macro_rules --- libafl_frida/src/asan/asan_rt.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index edafd25cc5..f9bd3f6826 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -571,6 +571,7 @@ impl AsanRuntime { }; } + #[allow(unused_macro_rules)] macro_rules! hook_func_with_check { ($name:ident, ($($param:ident : $param_type:ty),*), $return_type:ty, $always_enabled:expr) => { paste::paste! { From c9de51721f60ae6a317ce3c7cf032bc2cda83618 Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 10:41:54 +0200 Subject: [PATCH 16/17] Don't do stdout_file on windows --- fuzzers/binary_only/frida_libpng/src/fuzzer.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs index 2d89401695..ab950eda9f 100644 --- a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs @@ -247,15 +247,18 @@ fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { Ok(()) }; - Launcher::builder() + let builder = Launcher::builder() .configuration(EventConfig::AlwaysUnique) .shmem_provider(shmem_provider) .monitor(monitor) .run_client(&mut run_client) .cores(&options.cores) .broker_port(options.broker_port) - .stdout_file(Some(&options.stdout)) - .remote_broker_addr(options.remote_broker_addr) - .build() + .remote_broker_addr(options.remote_broker_addr); + + #[cfg(not(windows))] + let builder = builder.stdout_file(Some(&options.stdout)); + + builder.build() .launch() } From b0441a488527b3f0897e7ae49581b35c9f60c46e Mon Sep 17 00:00:00 2001 From: s1341 Date: Wed, 15 Jan 2025 10:45:21 +0200 Subject: [PATCH 17/17] fmt --- fuzzers/binary_only/frida_libpng/src/fuzzer.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs index ab950eda9f..2d00661ba4 100644 --- a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs @@ -256,9 +256,8 @@ fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { .broker_port(options.broker_port) .remote_broker_addr(options.remote_broker_addr); - #[cfg(not(windows))] - let builder = builder.stdout_file(Some(&options.stdout)); + #[cfg(not(windows))] + let builder = builder.stdout_file(Some(&options.stdout)); - builder.build() - .launch() + builder.build().launch() }