diff --git a/Cargo.toml b/Cargo.toml index 9c7b6ca3..e130b4e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ authors = [ "Keegan Saunders ", "Shmarya Rubenstein ", ] -edition = "2021" +edition = "2024" license = "wxWindows" repository = "https://github.com/frida/frida-rust" description = "Rust bindings for Frida" diff --git a/FRIDA_VERSION b/FRIDA_VERSION index 902d6768..b6e9aafb 100644 --- a/FRIDA_VERSION +++ b/FRIDA_VERSION @@ -1 +1 @@ -17.9.5 +17.15.3 diff --git a/frida-build/Cargo.toml b/frida-build/Cargo.toml index 1de2c6b7..78e3e2bd 100644 --- a/frida-build/Cargo.toml +++ b/frida-build/Cargo.toml @@ -11,9 +11,9 @@ description.workspace = true auto-download = [] [dependencies] -reqwest = { version = "0.12.24", default-features = false, features = [ +reqwest = { version = "0.13", default-features = false, features = [ "blocking", - "rustls-tls", + "rustls", ] } tar = "0.4.44" xz = "0.1.0" diff --git a/frida-build/src/lib.rs b/frida-build/src/lib.rs index b046a568..2c354787 100644 --- a/frida-build/src/lib.rs +++ b/frida-build/src/lib.rs @@ -7,7 +7,7 @@ use std::{ env, - fs::{remove_file, File}, + fs::{File, remove_file}, io::{self, Error}, path::Path, }; @@ -42,7 +42,7 @@ fn download_and_use_devkit_internal( let devkit_name = format!("frida-{kind}-devkit-{version}-{os}-{target_arch}",); let devkit_path = out_dir_path.join(&devkit_name); - let devkit_tar = out_dir_path.join(format!("{}.tar.xz", &devkit_name)); + let devkit_tar = out_dir_path.join(format!("{devkit_name}.tar.xz")); if force_download { drop(remove_file(&devkit_tar)); @@ -58,7 +58,7 @@ fn download_and_use_devkit_internal( println!( "cargo:warning=Frida {} devkit not found, downloading from {}...", - kind, &frida_url, + kind, frida_url, ); // Download devkit let mut resp = diff --git a/frida-gum-sys/FRIDA_VERSION b/frida-gum-sys/FRIDA_VERSION index 902d6768..b6e9aafb 100644 --- a/frida-gum-sys/FRIDA_VERSION +++ b/frida-gum-sys/FRIDA_VERSION @@ -1 +1 @@ -17.9.5 +17.15.3 diff --git a/frida-gum-sys/src/lib.rs b/frida-gum-sys/src/lib.rs index fa7c8110..d5a15305 100644 --- a/frida-gum-sys/src/lib.rs +++ b/frida-gum-sys/src/lib.rs @@ -42,8 +42,10 @@ impl Insn { /// /// The caller is fully responsible for the backing allocations lifetime, including freeing. pub unsafe fn from_raw(insn: *const cs_insn) -> Self { - Self { - insn: core::ptr::read(insn), + unsafe { + Self { + insn: core::ptr::read(insn), + } } } diff --git a/frida-gum/src/backtracer.rs b/frida-gum/src/backtracer.rs index 335e2a77..6df818e1 100644 --- a/frida-gum/src/backtracer.rs +++ b/frida-gum/src/backtracer.rs @@ -12,7 +12,7 @@ use {core::mem::MaybeUninit, frida_gum_sys as gum_sys}; // The following function is not exposed through the `frida-gum.h` header, so we don't have an // auto-generated binding for it. This may change in a future version. -extern "C" { +unsafe extern "C" { // On some platforms `ucontext` contains a u128 which does not have a defined ABI. In this case, // we disable the error as we assume the behaviour is correct (all other platforms are unaffected). #[cfg(target_os = "linux")] @@ -109,7 +109,7 @@ impl Backtracer { /// Generate a fuzzy backtrace as a list of return addresses for the supplied cpu /// context. pub fn fuzzy_with_context(context: &gum_sys::GumCpuContext) -> Vec { - Self::fuzzy_with_context_and_limit(&context, gum_sys::GUM_MAX_BACKTRACE_DEPTH) + Self::fuzzy_with_context_and_limit(context, gum_sys::GUM_MAX_BACKTRACE_DEPTH) } /// Generate a fuzzy backtrace as a list of return addresses for the supplied cpu diff --git a/frida-gum/src/debug_symbol.rs b/frida-gum/src/debug_symbol.rs index 4ab6f677..79b55460 100644 --- a/frida-gum/src/debug_symbol.rs +++ b/frida-gum/src/debug_symbol.rs @@ -3,7 +3,7 @@ use { core::{fmt, mem::MaybeUninit, str::Utf8Error}, cstr_core::{CStr, CString}, frida_gum_sys as gum_sys, - gum_sys::{gum_find_function, gum_symbol_details_from_address, GumDebugSymbolDetails}, + gum_sys::{GumDebugSymbolDetails, gum_find_function, gum_symbol_details_from_address}, }; pub struct Symbol { diff --git a/frida-gum/src/instruction_writer/aarch64/relocator.rs b/frida-gum/src/instruction_writer/aarch64/relocator.rs index 4e3d5dbd..a8f155f5 100644 --- a/frida-gum/src/instruction_writer/aarch64/relocator.rs +++ b/frida-gum/src/instruction_writer/aarch64/relocator.rs @@ -1,7 +1,7 @@ use { crate::instruction_writer::{Aarch64InstructionWriter, Relocator}, core::ffi::c_void, - frida_gum_sys::{cs_insn, Insn}, + frida_gum_sys::{Insn, cs_insn}, }; pub struct Aarch64Relocator { @@ -10,7 +10,7 @@ pub struct Aarch64Relocator { impl Relocator for Aarch64Relocator { fn new(input_code: u64, output: &mut Aarch64InstructionWriter) -> Self { - extern "C" { + unsafe extern "C" { fn gum_arm64_relocator_new( input_code: *const c_void, output: *mut c_void, @@ -24,7 +24,7 @@ impl Relocator for Aarch64Relocator { } fn read_one(&mut self) -> (u32, Insn) { - extern "C" { + unsafe extern "C" { fn gum_arm64_relocator_read_one( relocator: *mut c_void, instruction: *mut *const cs_insn, @@ -37,7 +37,7 @@ impl Relocator for Aarch64Relocator { } fn eoi(&mut self) -> bool { - extern "C" { + unsafe extern "C" { fn gum_arm64_relocator_eoi(relocator: *mut c_void) -> u32; } @@ -45,7 +45,7 @@ impl Relocator for Aarch64Relocator { } fn write_all(&mut self) { - extern "C" { + unsafe extern "C" { fn gum_arm64_relocator_write_all(relocator: *mut c_void); } @@ -53,7 +53,7 @@ impl Relocator for Aarch64Relocator { } fn write_one(&mut self) -> bool { - extern "C" { + unsafe extern "C" { fn gum_arm64_relocator_write_one(relocator: *mut c_void) -> i32; } @@ -61,7 +61,7 @@ impl Relocator for Aarch64Relocator { } fn skip_one(&mut self) -> bool { - extern "C" { + unsafe extern "C" { fn gum_arm64_relocator_skip_one(relocator: *mut c_void) -> i32; } @@ -71,7 +71,7 @@ impl Relocator for Aarch64Relocator { impl Drop for Aarch64Relocator { fn drop(&mut self) { - extern "C" { + unsafe extern "C" { fn gum_arm64_relocator_unref(relocator: *mut c_void); } diff --git a/frida-gum/src/instruction_writer/x86_64/relocator.rs b/frida-gum/src/instruction_writer/x86_64/relocator.rs index fa3f7d15..ab56bcdc 100644 --- a/frida-gum/src/instruction_writer/x86_64/relocator.rs +++ b/frida-gum/src/instruction_writer/x86_64/relocator.rs @@ -1,7 +1,7 @@ use { crate::instruction_writer::{Relocator, X86InstructionWriter}, core::ffi::c_void, - frida_gum_sys::{cs_insn, Insn}, + frida_gum_sys::{Insn, cs_insn}, }; pub struct X86Relocator { @@ -10,9 +10,9 @@ pub struct X86Relocator { impl Relocator for X86Relocator { fn new(input_code: u64, output: &mut X86InstructionWriter) -> Self { - extern "C" { + unsafe extern "C" { fn gum_x86_relocator_new(input_code: *const c_void, output: *mut c_void) - -> *mut c_void; + -> *mut c_void; } Self { inner: unsafe { @@ -22,7 +22,7 @@ impl Relocator for X86Relocator { } fn read_one(&mut self) -> (u32, Insn) { - extern "C" { + unsafe extern "C" { fn gum_x86_relocator_read_one( relocator: *mut c_void, instruction: *mut *const cs_insn, @@ -35,7 +35,7 @@ impl Relocator for X86Relocator { } fn eoi(&mut self) -> bool { - extern "C" { + unsafe extern "C" { fn gum_x86_relocator_eoi(relocator: *mut c_void) -> u32; } @@ -43,7 +43,7 @@ impl Relocator for X86Relocator { } fn write_all(&mut self) { - extern "C" { + unsafe extern "C" { fn gum_x86_relocator_write_all(relocator: *mut c_void); } @@ -51,7 +51,7 @@ impl Relocator for X86Relocator { } fn write_one(&mut self) -> bool { - extern "C" { + unsafe extern "C" { fn gum_x86_relocator_write_one(relocator: *mut c_void) -> i32; } @@ -59,7 +59,7 @@ impl Relocator for X86Relocator { } fn skip_one(&mut self) -> bool { - extern "C" { + unsafe extern "C" { fn gum_x86_relocator_skip_one(relocator: *mut c_void) -> i32; } @@ -69,7 +69,7 @@ impl Relocator for X86Relocator { impl Drop for X86Relocator { fn drop(&mut self) { - extern "C" { + unsafe extern "C" { fn gum_x86_relocator_unref(relocator: *mut c_void); } diff --git a/frida-gum/src/instruction_writer/x86_64/writer.rs b/frida-gum/src/instruction_writer/x86_64/writer.rs index 20b593a1..dcf90225 100644 --- a/frida-gum/src/instruction_writer/x86_64/writer.rs +++ b/frida-gum/src/instruction_writer/x86_64/writer.rs @@ -2,7 +2,7 @@ use { crate::instruction_writer::{Argument, InstructionWriter, X86BranchCondition, X86Register}, core::ffi::c_void, frida_gum_sys as gum_sys, - gum_sys::{gssize, GumArgument, GumBranchHint}, + gum_sys::{GumArgument, GumBranchHint, gssize}, }; #[cfg(not(any( diff --git a/frida-gum/src/interceptor.rs b/frida-gum/src/interceptor.rs index cdf97624..ee617b91 100644 --- a/frida-gum/src/interceptor.rs +++ b/frida-gum/src/interceptor.rs @@ -69,7 +69,7 @@ impl Interceptor { ) -> Result { let listener = invocation_listener_transform(listener); match unsafe { - gum_sys::gum_interceptor_attach(self.interceptor, f.0, listener, ptr::null_mut(), 0) + gum_sys::gum_interceptor_attach(self.interceptor, f.0, listener, ptr::null()) } { gum_sys::GumAttachReturn_GUM_ATTACH_OK => { Ok(Listener(NativePointer(listener as *mut c_void))) @@ -100,7 +100,7 @@ impl Interceptor { ) -> Result { let listener = probe_listener_transform(listener); match unsafe { - gum_sys::gum_interceptor_attach(self.interceptor, instr.0, listener, ptr::null_mut(), 0) + gum_sys::gum_interceptor_attach(self.interceptor, instr.0, listener, ptr::null()) } { gum_sys::GumAttachReturn_GUM_ATTACH_OK => { Ok(Listener(NativePointer(listener as *mut c_void))) @@ -145,7 +145,7 @@ impl Interceptor { &mut self, function: NativePointer, replacement: NativePointer, - replacement_data: NativePointer, + _replacement_data: NativePointer, ) -> Result { let mut original_function = NativePointer(ptr::null_mut()); unsafe { @@ -153,8 +153,8 @@ impl Interceptor { self.interceptor, function.0, replacement.0, - replacement_data.0, - &mut original_function.0, + ptr::addr_of_mut!(original_function.0), + ptr::null(), ) { gum_sys::GumReplaceReturn_GUM_REPLACE_OK => Ok(original_function), gum_sys::GumReplaceReturn_GUM_REPLACE_WRONG_SIGNATURE => { @@ -194,7 +194,8 @@ impl Interceptor { self.interceptor, function.0, replacement.0, - &mut original_function.0, + ptr::addr_of_mut!(original_function.0), + ptr::null(), ) { gum_sys::GumReplaceReturn_GUM_REPLACE_OK => Ok(original_function), gum_sys::GumReplaceReturn_GUM_REPLACE_WRONG_SIGNATURE => { diff --git a/frida-gum/src/interceptor/invocation_listener.rs b/frida-gum/src/interceptor/invocation_listener.rs index f29497b5..123cc4d3 100644 --- a/frida-gum/src/interceptor/invocation_listener.rs +++ b/frida-gum/src/interceptor/invocation_listener.rs @@ -27,16 +27,20 @@ unsafe extern "C" fn call_on_enter( user_data: *mut c_void, context: *mut gum_sys::GumInvocationContext, ) { - let listener: &mut I = &mut *(user_data as *mut I); - listener.on_enter(InvocationContext::from_raw(context)); + unsafe { + let listener: &mut I = &mut *(user_data as *mut I); + listener.on_enter(InvocationContext::from_raw(context)); + } } unsafe extern "C" fn call_on_leave( user_data: *mut c_void, context: *mut gum_sys::GumInvocationContext, ) { - let listener: &mut I = &mut *(user_data as *mut I); - listener.on_leave(InvocationContext::from_raw(context)); + unsafe { + let listener: &mut I = &mut *(user_data as *mut I); + listener.on_leave(InvocationContext::from_raw(context)); + } } pub(crate) fn invocation_listener_transform( @@ -59,8 +63,10 @@ unsafe extern "C" fn call_on_hit( user_data: *mut c_void, context: *mut gum_sys::GumInvocationContext, ) { - let listener: &mut I = &mut *(user_data as *mut I); - listener.on_hit(InvocationContext::from_raw(context)); + unsafe { + let listener: &mut I = &mut *(user_data as *mut I); + listener.on_hit(InvocationContext::from_raw(context)); + } } pub(crate) fn probe_listener_transform( diff --git a/frida-gum/src/lib.rs b/frida-gum/src/lib.rs index 8764d208..781c0379 100644 --- a/frida-gum/src/lib.rs +++ b/frida-gum/src/lib.rs @@ -59,7 +59,7 @@ extern crate num; extern crate num_derive; use core::{ - ffi::{c_char, c_void, CStr}, + ffi::{CStr, c_char, c_void}, fmt::{Debug, Display, Formatter, LowerHex, UpperHex}, }; diff --git a/frida-gum/src/memory_access_monitor.rs b/frida-gum/src/memory_access_monitor.rs index 10f96da9..cd09bb69 100644 --- a/frida-gum/src/memory_access_monitor.rs +++ b/frida-gum/src/memory_access_monitor.rs @@ -1,12 +1,12 @@ use super::{memory_range::MemoryRange, range_details::PageProtection}; -use crate::{error::GumResult, NativePointer}; +use crate::{NativePointer, error::GumResult}; use core::{ffi::c_void, ptr::null_mut}; use frida_gum_sys::{ _GumMemoryOperation_GUM_MEMOP_EXECUTE, _GumMemoryOperation_GUM_MEMOP_INVALID, _GumMemoryOperation_GUM_MEMOP_READ, _GumMemoryOperation_GUM_MEMOP_WRITE, _GumMemoryRange, - false_, gum_memory_access_monitor_disable, gum_memory_access_monitor_enable, - gum_memory_access_monitor_new, GError, GumMemoryAccessDetails, GumMemoryAccessMonitor, - GumPageProtection, + GError, GumMemoryAccessDetails, GumMemoryAccessMonitor, GumPageProtection, false_, + gum_memory_access_monitor_disable, gum_memory_access_monitor_enable, + gum_memory_access_monitor_new, }; pub trait CallbackFn: Fn(&mut MemoryAccessMonitor, &MemoryAccessDetails) {} diff --git a/frida-gum/src/module.rs b/frida-gum/src/module.rs index 2d0ce5f5..9dab9852 100644 --- a/frida-gum/src/module.rs +++ b/frida-gum/src/module.rs @@ -23,7 +23,7 @@ use { cstr_core::CString, frida_gum_sys as gum_sys, frida_gum_sys::{ - gboolean, gpointer, GumExportDetails, GumModule, GumSectionDetails, GumSymbolDetails, + GumExportDetails, GumModule, GumSectionDetails, GumSymbolDetails, gboolean, gpointer, }, }; @@ -215,16 +215,18 @@ impl Module { details: *const GumExportDetails, user_data: gpointer, ) -> gboolean { - let res = &mut *(user_data as *mut Vec); - let name: String = NativePointer((*details).name as *mut _) - .try_into() - .unwrap_or_default(); - - let address = (*details).address as usize; - let typ = num::FromPrimitive::from_u32((*details).type_ as u32).unwrap(); - let info = ExportDetails { typ, name, address }; - res.push(info); - 1 + unsafe { + let res = &mut *(user_data as *mut Vec); + let name: String = NativePointer((*details).name as *mut _) + .try_into() + .unwrap_or_default(); + + let address = (*details).address as usize; + let typ = num::FromPrimitive::from_u32((*details).type_ as u32).unwrap(); + let info = ExportDetails { typ, name, address }; + res.push(info); + 1 + } } unsafe { @@ -244,22 +246,24 @@ impl Module { details: *const GumSymbolDetails, user_data: gpointer, ) -> gboolean { - let res = &mut *(user_data as *mut Vec); - - let name: String = NativePointer((*details).name as *mut _) - .try_into() - .unwrap_or_default(); - let address = (*details).address as usize; - let size = (*details).size as usize; - - let info = SymbolDetails { - name, - address, - size, - }; - res.push(info); - - 1 + unsafe { + let res = &mut *(user_data as *mut Vec); + + let name: String = NativePointer((*details).name as *mut _) + .try_into() + .unwrap_or_default(); + let address = (*details).address as usize; + let size = (*details).size as usize; + + let info = SymbolDetails { + name, + address, + size, + }; + res.push(info); + + 1 + } } unsafe { @@ -280,26 +284,28 @@ impl Module { details: *const GumSectionDetails, user_data: gpointer, ) -> gboolean { - let res = &mut *(user_data as *mut Vec); - - let id: String = NativePointer((*details).id as *mut _) - .try_into() - .unwrap_or_default(); - let name: String = NativePointer((*details).name as *mut _) - .try_into() - .unwrap_or_default(); - let address = (*details).address as usize; - let size = (*details).size as usize; - - let info = SectionDetails { - id, - name, - address, - size, - }; - res.push(info); - - 1 + unsafe { + let res = &mut *(user_data as *mut Vec); + + let id: String = NativePointer((*details).id as *mut _) + .try_into() + .unwrap_or_default(); + let name: String = NativePointer((*details).name as *mut _) + .try_into() + .unwrap_or_default(); + let address = (*details).address as usize; + let size = (*details).size as usize; + + let info = SectionDetails { + id, + name, + address, + size, + }; + res.push(info); + + 1 + } } unsafe { diff --git a/frida-gum/src/module_map.rs b/frida-gum/src/module_map.rs index 14d2b8b6..bf428786 100644 --- a/frida-gum/src/module_map.rs +++ b/frida-gum/src/module_map.rs @@ -42,8 +42,10 @@ impl ModuleMap { details: *mut gum_sys::GumModule, callback: *mut c_void, ) -> i32 { - let callback = &mut *(callback as *mut Box<&mut dyn FnMut(Module) -> bool>); - i32::from((callback)(Module::from_raw(details))) + unsafe { + let callback = &mut *(callback as *mut Box<&mut dyn FnMut(Module) -> bool>); + i32::from((callback)(Module::from_raw(details))) + } } Self::from_raw(unsafe { gum_sys::gum_module_map_new_filtered( diff --git a/frida-gum/src/process.rs b/frida-gum/src/process.rs index 8bb1653d..11df0a07 100644 --- a/frida-gum/src/process.rs +++ b/frida-gum/src/process.rs @@ -10,7 +10,7 @@ use crate::{FileMapping, Module, NativePointer, Thread}; use { crate::{Gum, PageProtection, RangeDetails}, - core::ffi::{c_char, c_void, CStr}, + core::ffi::{CStr, c_char, c_void}, core::{fmt, fmt::Debug}, frida_gum_sys as gum_sys, frida_gum_sys::{gboolean, gpointer}, @@ -22,14 +22,14 @@ use cstr_core::CString; use frida_gum_sys::GumThreadFlags_GUM_THREAD_FLAGS_ALL; #[cfg(any(target_os = "linux", target_os = "freebsd"))] -extern "C" { +unsafe extern "C" { pub fn _frida_g_get_home_dir() -> *const c_char; pub fn _frida_g_get_current_dir() -> *const c_char; pub fn _frida_g_get_tmp_dir() -> *const c_char; } #[cfg(not(any(target_os = "linux", target_os = "freebsd")))] -extern "C" { +unsafe extern "C" { pub fn g_get_home_dir() -> *const c_char; pub fn g_get_current_dir() -> *const c_char; pub fn g_get_tmp_dir() -> *const c_char; @@ -185,23 +185,25 @@ impl<'a> Process<'a> { details: *const gum_sys::GumRangeDetails, user_data: gpointer, ) -> gboolean { - let res = &mut *(user_data as *mut CallbackData); - let r_details = RangeDetails::from_raw(details); - - let prot = r_details.protection(); - if res.protection == prot { - let m_range = r_details.memory_range(); - let file_map = r_details.file_mapping(); - - res.ranges.push(Range { - base: m_range.base_address(), - size: m_range.size(), - protection: prot, - file: file_map, - }); + unsafe { + let res = &mut *(user_data as *mut CallbackData); + let r_details = RangeDetails::from_raw(details); + + let prot = r_details.protection(); + if res.protection == prot { + let m_range = r_details.memory_range(); + let file_map = r_details.file_mapping(); + + res.ranges.push(Range { + base: m_range.base_address(), + size: m_range.size(), + protection: prot, + file: file_map, + }); + } + + 1 } - - 1 } let callback_data = CallbackData { @@ -230,10 +232,12 @@ impl<'a> Process<'a> { details: *mut gum_sys::GumModule, user_data: gpointer, ) -> gboolean { - let res = &mut *(user_data as *mut CallbackData); - res.modules.push(Module::from_raw(details)); + unsafe { + let res = &mut *(user_data as *mut CallbackData); + res.modules.push(Module::from_raw(details)); - 1 + 1 + } } let callback_data = CallbackData { @@ -256,12 +260,14 @@ impl<'a> Process<'a> { details: *const gum_sys::GumThreadDetails, user_data: gpointer, ) -> gboolean { - let res = &mut *(user_data as *mut Vec); - res.push(Thread::from_raw(details)); + unsafe { + let res = &mut *(user_data as *mut Vec); + res.push(Thread::from_raw(details)); - // if this value is zero, the iteration ends - // subprojects/frida-gum/gum/gumthreadregistry.c - 1 + // if this value is zero, the iteration ends + // subprojects/frida-gum/gum/gumthreadregistry.c + 1 + } } let callback_data = Vec::new(); diff --git a/frida-gum/src/range_details.rs b/frida-gum/src/range_details.rs index 9ffbf099..fe8b1d68 100644 --- a/frida-gum/src/range_details.rs +++ b/frida-gum/src/range_details.rs @@ -14,7 +14,7 @@ extern crate alloc; use { crate::MemoryRange, core::{ - ffi::{c_void, CStr}, + ffi::{CStr, c_void}, fmt, marker::PhantomData, }, @@ -105,28 +105,32 @@ unsafe extern "C" fn save_range_details_by_address( details: *const gum_sys::GumRangeDetails, context: *mut c_void, ) -> i32 { - let context = &mut *(context as *mut SaveRangeDetailsByAddressContext); - let range = (*details).range; - let start = (*range).base_address as u64; - let end = start + (*range).size as u64; - if start <= context.address && context.address < end { - context.details = Some(RangeDetails::from_raw(details)); - return 0; - } + unsafe { + let context = &mut *(context as *mut SaveRangeDetailsByAddressContext); + let range = (*details).range; + let start = (*range).base_address as u64; + let end = start + (*range).size as u64; + if start <= context.address && context.address < end { + context.details = Some(RangeDetails::from_raw(details)); + return 0; + } - 1 + 1 + } } unsafe extern "C" fn enumerate_ranges_stub( details: *const gum_sys::GumRangeDetails, context: *mut c_void, ) -> i32 { - if !(*(context as *mut Box<&mut dyn FnMut(&RangeDetails) -> bool>))(&RangeDetails::from_raw( - details, - )) { - return 0; + unsafe { + if !(*(context as *mut Box<&mut dyn FnMut(&RangeDetails) -> bool>))( + &RangeDetails::from_raw(details), + ) { + return 0; + } + 1 } - 1 } /// Details a range of virtual memory. diff --git a/frida-gum/src/script/backend.rs b/frida-gum/src/script/backend.rs index b7c38c28..17e57f51 100644 --- a/frida-gum/src/script/backend.rs +++ b/frida-gum/src/script/backend.rs @@ -1,13 +1,13 @@ use { crate::{ + Gum, error::GumResult, script::{Script, ScriptData}, - Gum, }, core::{ffi::c_void, pin::Pin, ptr::null_mut}, frida_gum_sys::{ - gum_script_backend_create, gum_script_backend_obtain_qjs, gum_script_backend_obtain_v8, - GBytes, GCancellable, GumScriptBackend, + GBytes, GCancellable, GumScriptBackend, gum_script_backend_create, + gum_script_backend_obtain_qjs, gum_script_backend_obtain_v8, }, }; diff --git a/frida-gum/src/script/data.rs b/frida-gum/src/script/data.rs index 5dbeb979..73cce601 100644 --- a/frida-gum/src/script/data.rs +++ b/frida-gum/src/script/data.rs @@ -1,14 +1,14 @@ use { crate::error::{Error, GumResult}, core::{ - ffi::{c_void, CStr}, + ffi::{CStr, c_void}, ptr::null_mut, slice::from_raw_parts, }, frida_gum_sys::{ - gchar, gpointer, gsize, gum_script_backend_create_finish, gum_script_load, - gum_script_load_finish, gum_script_set_message_handler, GAsyncResult, GBytes, GCancellable, - GError, GObject, GumScript, GumScriptBackend, + GAsyncResult, GBytes, GCancellable, GError, GObject, GumScript, GumScriptBackend, gchar, + gpointer, gsize, gum_script_backend_create_finish, gum_script_load, gum_script_load_finish, + gum_script_set_message_handler, }, }; @@ -47,24 +47,31 @@ where result: *mut GAsyncResult, user_data: gpointer, ) { - let data = &mut *(user_data as *mut ScriptData); - let mut error: *mut GError = null_mut(); + unsafe { + let data = &mut *(user_data as *mut ScriptData); + let mut error: *mut GError = null_mut(); - data.script = gum_script_backend_create_finish(data.backend, result, &mut error); - if data.script.is_null() || !error.is_null() { - data.result = Err(Error::FailedToCreateScript); - return; - } + data.script = gum_script_backend_create_finish(data.backend, result, &mut error); + if data.script.is_null() || !error.is_null() { + data.result = Err(Error::FailedToCreateScript); + return; + } - gum_script_set_message_handler(data.script, Some(ScriptData::::js_msg), user_data, None); + gum_script_set_message_handler( + data.script, + Some(ScriptData::::js_msg), + user_data, + None, + ); - let cancellable: *mut GCancellable = null_mut(); - gum_script_load( - data.script, - cancellable, - Some(ScriptData::::load_cb), - data as *mut ScriptData as *mut c_void, - ); + let cancellable: *mut GCancellable = null_mut(); + gum_script_load( + data.script, + cancellable, + Some(ScriptData::::load_cb), + data as *mut ScriptData as *mut c_void, + ); + } } fn get_bytes(gdata: &mut GBytes) -> GumResult<&[u8]> { @@ -84,15 +91,17 @@ where } unsafe extern "C" fn js_msg(gmessage: *const gchar, gbytes: *mut GBytes, user_data: gpointer) { - let data = &mut *(user_data as *mut ScriptData); - let message = CStr::from_ptr(gmessage).to_str().unwrap_or_default(); - let bytes = if gbytes.is_null() { - &[] - } else { - Self::get_bytes(&mut *gbytes).unwrap_or_default() - }; - if let Some(callback) = &mut data.callback { - callback(message, bytes); + unsafe { + let data = &mut *(user_data as *mut ScriptData); + let message = CStr::from_ptr(gmessage).to_str().unwrap_or_default(); + let bytes = if gbytes.is_null() { + &[] + } else { + Self::get_bytes(&mut *gbytes).unwrap_or_default() + }; + if let Some(callback) = &mut data.callback { + callback(message, bytes); + } } } @@ -101,9 +110,11 @@ where result: *mut GAsyncResult, user_data: gpointer, ) { - let data = &mut *(user_data as *mut ScriptData); - gum_script_load_finish(data.script, result); - data.result = Ok(()); + unsafe { + let data = &mut *(user_data as *mut ScriptData); + gum_script_load_finish(data.script, result); + data.result = Ok(()); + } } pub fn loaded(&self) -> GumResult<()> { diff --git a/frida-gum/src/script/scheduler.rs b/frida-gum/src/script/scheduler.rs index 6b3a48e0..cd399b85 100644 --- a/frida-gum/src/script/scheduler.rs +++ b/frida-gum/src/script/scheduler.rs @@ -1,8 +1,8 @@ use { crate::script::{backend::Backend, context::Context}, frida_gum_sys::{ - gum_script_backend_get_scheduler, gum_script_scheduler_disable_background_thread, - gum_script_scheduler_get_js_context, GumScriptScheduler, + GumScriptScheduler, gum_script_backend_get_scheduler, + gum_script_scheduler_disable_background_thread, gum_script_scheduler_get_js_context, }, }; diff --git a/frida-gum/src/stalker.rs b/frida-gum/src/stalker.rs index e48cb10e..3e94dbdd 100644 --- a/frida-gum/src/stalker.rs +++ b/frida-gum/src/stalker.rs @@ -295,11 +295,6 @@ impl Stalker { unsafe { gum_sys::gum_stalker_deactivate(self.stalker) } } - /// Enable (experimental) unwind hooking - pub fn enable_unwind_hooking(&mut self) { - unsafe { gum_sys::gum_stalker_activate_experimental_unwind_support() } - } - #[cfg(feature = "stalker-observer")] #[cfg_attr(docsrs, doc(cfg(feature = "stalker-observer")))] pub fn set_observer(&mut self, observer: &mut O) { diff --git a/frida-gum/src/stalker/event_sink.rs b/frida-gum/src/stalker/event_sink.rs index 1699bf5d..cda732d8 100644 --- a/frida-gum/src/stalker/event_sink.rs +++ b/frida-gum/src/stalker/event_sink.rs @@ -107,33 +107,43 @@ pub trait EventSink { } unsafe extern "C" fn call_start(user_data: *mut c_void) { - let event_sink: &mut S = &mut *(user_data as *mut S); - event_sink.start(); + unsafe { + let event_sink: &mut S = &mut *(user_data as *mut S); + event_sink.start(); + } } unsafe extern "C" fn call_process( user_data: *mut c_void, event: *const frida_gum_sys::GumEvent, ) { - let event_sink: &mut S = &mut *(user_data as *mut S); - event_sink.process(&(*event).into()); + unsafe { + let event_sink: &mut S = &mut *(user_data as *mut S); + event_sink.process(&(*event).into()); + } } unsafe extern "C" fn call_flush(user_data: *mut c_void) { - let event_sink: &mut S = &mut *(user_data as *mut S); - event_sink.flush(); + unsafe { + let event_sink: &mut S = &mut *(user_data as *mut S); + event_sink.flush(); + } } unsafe extern "C" fn call_stop(user_data: *mut c_void) { - let event_sink: &mut S = &mut *(user_data as *mut S); - event_sink.stop(); + unsafe { + let event_sink: &mut S = &mut *(user_data as *mut S); + event_sink.stop(); + } } unsafe extern "C" fn call_query_mask( user_data: *mut c_void, ) -> frida_gum_sys::GumEventType { - let event_sink: &mut S = &mut *(user_data as *mut S); - event_sink.query_mask() as u32 + unsafe { + let event_sink: &mut S = &mut *(user_data as *mut S); + event_sink.query_mask() as u32 + } } pub(crate) fn event_sink_transform( diff --git a/frida-gum/src/stalker/observer.rs b/frida-gum/src/stalker/observer.rs index ea9b383d..30396903 100644 --- a/frida-gum/src/stalker/observer.rs +++ b/frida-gum/src/stalker/observer.rs @@ -23,8 +23,10 @@ unsafe extern "C" fn notify_backpatch( backpatch: *const gum_sys::GumBackpatch, size: gum_sys::gsize, ) { - let stalker_observer: &mut S = &mut *(user_data as *mut S); - stalker_observer.notify_backpatch(backpatch, size); + unsafe { + let stalker_observer: &mut S = &mut *(user_data as *mut S); + stalker_observer.notify_backpatch(backpatch, size); + } } unsafe extern "C" fn switch_callback( @@ -34,8 +36,10 @@ unsafe extern "C" fn switch_callback( from_insn: gum_sys::gpointer, target: *mut gum_sys::gpointer, ) { - let stalker_observer: &mut S = &mut *(user_data as *mut S); - stalker_observer.switch_callback(from_address, start_address, from_insn, &mut *target); + unsafe { + let stalker_observer: &mut S = &mut *(user_data as *mut S); + stalker_observer.switch_callback(from_address, start_address, from_insn, &mut *target); + } } pub(crate) fn stalker_observer_transform( diff --git a/frida-gum/src/stalker/transformer.rs b/frida-gum/src/stalker/transformer.rs index cc6f3e9b..8353a03b 100644 --- a/frida-gum/src/stalker/transformer.rs +++ b/frida-gum/src/stalker/transformer.rs @@ -8,7 +8,7 @@ use crate::CpuContextAccess; use frida_gum_sys::Insn; use { - crate::{instruction_writer::TargetInstructionWriter, CpuContext, Gum}, + crate::{CpuContext, Gum, instruction_writer::TargetInstructionWriter}, core::{ffi::c_void, marker::PhantomData}, }; @@ -35,7 +35,9 @@ extern "C" fn put_callout_callback( } unsafe extern "C" fn put_callout_destroy(user_data: *mut c_void) { - let _ = Box::from_raw(user_data as *mut Box); + unsafe { + let _ = Box::from_raw(user_data as *mut Box); + } } impl<'a> StalkerIterator<'a> { @@ -176,7 +178,9 @@ extern "C" fn transformer_callback( } unsafe extern "C" fn transformer_destroy(user_data: *mut c_void) { - let _ = Box::from_raw(user_data as *mut Box); + unsafe { + let _ = Box::from_raw(user_data as *mut Box); + } } pub struct Transformer<'a> { diff --git a/frida-sys/FRIDA_VERSION b/frida-sys/FRIDA_VERSION index 902d6768..b6e9aafb 100644 --- a/frida-sys/FRIDA_VERSION +++ b/frida-sys/FRIDA_VERSION @@ -1 +1 @@ -17.9.5 +17.15.3 diff --git a/frida/src/device_manager.rs b/frida/src/device_manager.rs index 307f3baa..198d5a24 100644 --- a/frida/src/device_manager.rs +++ b/frida/src/device_manager.rs @@ -8,11 +8,11 @@ use frida_sys::_FridaDeviceManager; use std::ffi::CString; use std::marker::PhantomData; -use crate::device::{self, Device}; use crate::DeviceType; use crate::Error; use crate::Frida; use crate::Result; +use crate::device::{self, Device}; /// Platform-independent device manager abstraction access. pub struct DeviceManager<'a> { diff --git a/frida/src/lib.rs b/frida/src/lib.rs index ea851d00..cc6cd6f0 100644 --- a/frida/src/lib.rs +++ b/frida/src/lib.rs @@ -48,8 +48,10 @@ impl Frida { /// be called as many times as needed, and results in a no-op if the Frida runtime is /// already initialized. pub unsafe fn obtain() -> Frida { - frida_sys::frida_init(); - Frida {} + unsafe { + frida_sys::frida_init(); + Frida {} + } } /// Gets the current version of frida core @@ -67,17 +69,21 @@ impl Frida { unsafe extern "C" fn trampoline( func: frida_sys::gpointer, ) -> frida_sys::gboolean { - let func: &mut Option = &mut *(func as *mut Option); - let func = func - .take() - .expect("schedule_on_main closure called multiple times"); - func(); - frida_sys::G_SOURCE_REMOVE as frida_sys::gboolean + unsafe { + let func: &mut Option = &mut *(func as *mut Option); + let func = func + .take() + .expect("schedule_on_main closure called multiple times"); + func(); + frida_sys::G_SOURCE_REMOVE as frida_sys::gboolean + } } unsafe extern "C" fn destroy_closure( ptr: frida_sys::gpointer, ) { - let _ = Box::>::from_raw(ptr as *mut _); + unsafe { + let _ = Box::>::from_raw(ptr as *mut _); + } } let func = Box::into_raw(Box::new(Some(func))); diff --git a/frida/src/script.rs b/frida/src/script.rs index 4ef4167b..478fd7da 100644 --- a/frida/src/script.rs +++ b/frida/src/script.rs @@ -5,14 +5,14 @@ */ use frida_sys::{ - _FridaScript, _GBytes, g_bytes_get_data, g_bytes_new, g_bytes_unref, gsize, FridaScriptOptions, + _FridaScript, _GBytes, FridaScriptOptions, g_bytes_get_data, g_bytes_new, g_bytes_unref, gsize, }; use serde::Deserialize; use serde_json::Value; -use std::sync::mpsc::{channel, Receiver, Sender}; +use std::sync::mpsc::{Receiver, Sender, channel}; use std::{cell::RefCell, marker::PhantomData, rc::Rc}; use std::{ - ffi::{c_char, c_void, CStr, CString}, + ffi::{CStr, CString, c_char, c_void}, ptr::null_mut, }; @@ -94,55 +94,57 @@ unsafe extern "C" fn call_on_message( data: *const frida_sys::_GBytes, user_data: *mut c_void, ) { - let _ = std::marker::PhantomData::; - - let c_msg = CStr::from_ptr(message as *const c_char) - .to_str() - .unwrap_or_default(); - - let formatted_msg: Message = serde_json::from_str(c_msg).unwrap_or_else(|err| { - Message::Other(serde_json::json!({ - "error": err.to_string(), - "data": c_msg - })) - }); - - let callback_handler: *mut CallbackHandler = user_data as _; - let cb = match callback_handler.as_mut() { - Some(cb) => cb, - None => return, - }; - - match formatted_msg { - Message::Send(ref msg) - if msg.payload.get(0).and_then(|v| v.as_str()) == Some("frida:rpc") => - { - on_message(cb, formatted_msg); - } - _ => { - // Retrieve extra message data, if any. - let data_vec = if data.is_null() { - None - } else { - let mut raw_data_size: gsize = 0; - let raw_data: *const u8 = g_bytes_get_data( - // Cast to mut should be safe, as this function doesn't modify the data. - data as *mut _GBytes, - std::ptr::from_mut(&mut raw_data_size), - ) as *const u8; - if raw_data_size == 0 || raw_data.is_null() { + unsafe { + let _ = std::marker::PhantomData::; + + let c_msg = CStr::from_ptr(message as *const c_char) + .to_str() + .unwrap_or_default(); + + let formatted_msg: Message = serde_json::from_str(c_msg).unwrap_or_else(|err| { + Message::Other(serde_json::json!({ + "error": err.to_string(), + "data": c_msg + })) + }); + + let callback_handler: *mut CallbackHandler = user_data as _; + let cb = match callback_handler.as_mut() { + Some(cb) => cb, + None => return, + }; + + match formatted_msg { + Message::Send(ref msg) + if msg.payload.get(0).and_then(|v| v.as_str()) == Some("frida:rpc") => + { + on_message(cb, formatted_msg); + } + _ => { + // Retrieve extra message data, if any. + let data_vec = if data.is_null() { None } else { - // Copy to a vector to avoid potential lifetime issues. - Some( - std::slice::from_raw_parts(raw_data, raw_data_size.try_into().unwrap()) - .to_vec(), - ) - } - }; + let mut raw_data_size: gsize = 0; + let raw_data: *const u8 = g_bytes_get_data( + // Cast to mut should be safe, as this function doesn't modify the data. + data as *mut _GBytes, + std::ptr::from_mut(&mut raw_data_size), + ) as *const u8; + if raw_data_size == 0 || raw_data.is_null() { + None + } else { + // Copy to a vector to avoid potential lifetime issues. + Some( + std::slice::from_raw_parts(raw_data, raw_data_size.try_into().unwrap()) + .to_vec(), + ) + } + }; - if let Some(handler) = cb.script_handler.as_deref_mut() { - handler.on_message(formatted_msg, data_vec); + if let Some(handler) = cb.script_handler.as_deref_mut() { + handler.on_message(formatted_msg, data_vec); + } } } } diff --git a/frida/src/variant.rs b/frida/src/variant.rs index 8709c84f..5314f6ac 100644 --- a/frida/src/variant.rs +++ b/frida/src/variant.rs @@ -28,39 +28,41 @@ pub enum Variant { impl Variant { /// Construct a GVariant from a raw pointer pub(crate) unsafe fn from_ptr(variant: *mut frida_sys::GVariant) -> Self { - match variant_string(variant).as_str() { - "s" => { - let mut sz = 0; - let value = CStr::from_ptr(frida_sys::g_variant_get_string(variant, &mut sz)) - .to_string_lossy() - .to_string(); - Self::String(value) + unsafe { + match variant_string(variant).as_str() { + "s" => { + let mut sz = 0; + let value = CStr::from_ptr(frida_sys::g_variant_get_string(variant, &mut sz)) + .to_string_lossy() + .to_string(); + Self::String(value) + } + "b" => Self::Boolean( + frida_sys::g_variant_get_boolean(variant) != frida_sys::FALSE as i32, + ), + // Numeric variants get widened to i64. u64 above i64::MAX would + // wrap, but frida parameter values (ppid, started timestamps, + // process counters) sit well within signed-64 range. + "y" => Self::Int64(frida_sys::g_variant_get_byte(variant) as i64), + "n" => Self::Int64(frida_sys::g_variant_get_int16(variant) as i64), + "q" => Self::Int64(frida_sys::g_variant_get_uint16(variant) as i64), + "i" => Self::Int64(frida_sys::g_variant_get_int32(variant) as i64), + "u" => Self::Int64(frida_sys::g_variant_get_uint32(variant) as i64), + "x" => Self::Int64(frida_sys::g_variant_get_int64(variant)), + "t" => Self::Int64(frida_sys::g_variant_get_uint64(variant) as i64), + "a{sv}" => Self::Map(sv_array_to_map(variant)), + "aa{sv}" => Self::MapList(asv_array_to_maplist(variant)), + // Don't panic on unknown signatures; preserve the sig so callers + // can `Variant::Unsupported(sig)` and decide. Frida on Windows + // packs process icons as "ay" which we have no use for. + other => Self::Unsupported(other.to_string()), } - "b" => { - Self::Boolean(frida_sys::g_variant_get_boolean(variant) != frida_sys::FALSE as i32) - } - // Numeric variants get widened to i64. u64 above i64::MAX would - // wrap, but frida parameter values (ppid, started timestamps, - // process counters) sit well within signed-64 range. - "y" => Self::Int64(frida_sys::g_variant_get_byte(variant) as i64), - "n" => Self::Int64(frida_sys::g_variant_get_int16(variant) as i64), - "q" => Self::Int64(frida_sys::g_variant_get_uint16(variant) as i64), - "i" => Self::Int64(frida_sys::g_variant_get_int32(variant) as i64), - "u" => Self::Int64(frida_sys::g_variant_get_uint32(variant) as i64), - "x" => Self::Int64(frida_sys::g_variant_get_int64(variant)), - "t" => Self::Int64(frida_sys::g_variant_get_uint64(variant) as i64), - "a{sv}" => Self::Map(sv_array_to_map(variant)), - "aa{sv}" => Self::MapList(asv_array_to_maplist(variant)), - // Don't panic on unknown signatures; preserve the sig so callers - // can `Variant::Unsupported(sig)` and decide. Frida on Windows - // packs process icons as "ay" which we have no use for. - other => Self::Unsupported(other.to_string()), } } /// Get the string value of a variant, if any pub fn get_string(&self) -> Option<&str> { - let Self::String(ref s) = self else { + let Self::String(s) = self else { return None; }; Some(s) @@ -80,13 +82,13 @@ impl Variant { /// Get the mapping value of a variant, if any pub fn get_map(&self) -> Option<&HashMap> { - let Self::Map(ref m) = self else { return None }; + let Self::Map(m) = self else { return None }; Some(m) } /// Get the mapping list value of a variant, if any pub fn get_maplist(&self) -> Option<&[HashMap]> { - let Self::MapList(ref l) = self else { + let Self::MapList(l) = self else { return None; }; Some(l) @@ -107,47 +109,53 @@ impl std::fmt::Debug for Variant { } unsafe fn variant_string(variant: *mut frida_sys::GVariant) -> String { - CStr::from_ptr(frida_sys::g_variant_get_type_string(variant)) - .to_string_lossy() - .to_string() + unsafe { + CStr::from_ptr(frida_sys::g_variant_get_type_string(variant)) + .to_string_lossy() + .to_string() + } } unsafe fn sv_array_to_map(variant: *mut frida_sys::GVariant) -> HashMap { - let mut ret = HashMap::new(); - - let mut iter: frida_sys::GVariantIter = std::mem::MaybeUninit::zeroed().assume_init(); - let mut value: *mut frida_sys::GVariant = std::ptr::null_mut(); - let mut key: *const i8 = std::ptr::null_mut(); - - frida_sys::g_variant_iter_init(&mut iter, variant); - let sv = CString::new("{sv}").unwrap(); - while frida_sys::g_variant_iter_loop(&mut iter, sv.as_ptr(), &mut key, &mut value) != 0 { - let key = CStr::from_ptr(key.cast()).to_string_lossy().to_string(); - let value = Variant::from_ptr(value); - ret.insert(key, value); - } - ret -} + unsafe { + let mut ret = HashMap::new(); -unsafe fn asv_array_to_maplist(variant: *mut frida_sys::GVariant) -> Vec> { - let mut ret = Vec::new(); - let mut outer: frida_sys::GVariantIter = std::mem::MaybeUninit::zeroed().assume_init(); - let mut inner = std::ptr::null_mut(); - let mut key: *const i8 = std::ptr::null_mut(); - let mut value: *mut frida_sys::GVariant = std::ptr::null_mut(); - - frida_sys::g_variant_iter_init(&mut outer, variant); - let asv = CString::new("a{sv}").unwrap(); - let sv = CString::new("{sv}").unwrap(); - while frida_sys::g_variant_iter_loop(&mut outer, asv.as_ptr(), &mut inner) != 0 { - let mut map = HashMap::new(); - while frida_sys::g_variant_iter_loop(inner, sv.as_ptr(), &mut key, &mut value) != 0 { + let mut iter: frida_sys::GVariantIter = std::mem::MaybeUninit::zeroed().assume_init(); + let mut value: *mut frida_sys::GVariant = std::ptr::null_mut(); + let mut key: *const i8 = std::ptr::null_mut(); + + frida_sys::g_variant_iter_init(&mut iter, variant); + let sv = CString::new("{sv}").unwrap(); + while frida_sys::g_variant_iter_loop(&mut iter, sv.as_ptr(), &mut key, &mut value) != 0 { let key = CStr::from_ptr(key.cast()).to_string_lossy().to_string(); let value = Variant::from_ptr(value); - map.insert(key, value); + ret.insert(key, value); } - ret.push(map) + ret } +} + +unsafe fn asv_array_to_maplist(variant: *mut frida_sys::GVariant) -> Vec> { + unsafe { + let mut ret = Vec::new(); + let mut outer: frida_sys::GVariantIter = std::mem::MaybeUninit::zeroed().assume_init(); + let mut inner = std::ptr::null_mut(); + let mut key: *const i8 = std::ptr::null_mut(); + let mut value: *mut frida_sys::GVariant = std::ptr::null_mut(); + + frida_sys::g_variant_iter_init(&mut outer, variant); + let asv = CString::new("a{sv}").unwrap(); + let sv = CString::new("{sv}").unwrap(); + while frida_sys::g_variant_iter_loop(&mut outer, asv.as_ptr(), &mut inner) != 0 { + let mut map = HashMap::new(); + while frida_sys::g_variant_iter_loop(inner, sv.as_ptr(), &mut key, &mut value) != 0 { + let key = CStr::from_ptr(key.cast()).to_string_lossy().to_string(); + let value = Variant::from_ptr(value); + map.insert(key, value); + } + ret.push(map) + } - ret + ret + } }