From a0bf1ff544fb41fd5b82d007594a341de74ba0f5 Mon Sep 17 00:00:00 2001 From: xoffio <38369407+Xoffio@users.noreply.github.com> Date: Mon, 25 Nov 2024 23:26:11 -0500 Subject: [PATCH 1/6] adding process --- frida-gum/src/lib.rs | 3 + frida-gum/src/module.rs | 49 ++++++++----- frida-gum/src/process.rs | 130 +++++++++++++++++++++++++++++++++ frida-gum/src/range_details.rs | 2 +- 4 files changed, 166 insertions(+), 18 deletions(-) create mode 100644 frida-gum/src/process.rs diff --git a/frida-gum/src/lib.rs b/frida-gum/src/lib.rs index 6d30617..9041fd2 100644 --- a/frida-gum/src/lib.rs +++ b/frida-gum/src/lib.rs @@ -81,6 +81,9 @@ pub use module::*; mod module_map; pub use module_map::*; +mod process; +pub use process::*; + mod error; pub use error::Error; diff --git a/frida-gum/src/module.rs b/frida-gum/src/module.rs index 55ad145..bbd499a 100644 --- a/frida-gum/src/module.rs +++ b/frida-gum/src/module.rs @@ -53,6 +53,37 @@ impl fmt::Display for ExportType { } } +impl ModuleDetailsOwned { + pub unsafe fn from_module_details(details: *const GumModuleDetails) -> Self { + let name: String = NativePointer((*details).name as *mut _) + .try_into() + .unwrap_or_default(); + let path: String = NativePointer((*details).path as *mut _) + .try_into() + .unwrap_or_default(); + let range = (*details).range; + let base_address = (*range).base_address as usize; + let size = (*range).size as usize; + + ModuleDetailsOwned { + name, + path, + base_address, + size, + } + } +} + +impl fmt::Display for ModuleDetailsOwned { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + fmt, + "{{\n\tbase: 0x{:x}\n\tname: {}\n\tpath: {}\n\tsize: {}\n}}", + self.base_address, self.name, self.path, self.size + ) + } +} + /// Module symbol details returned by [`Module::enumerate_symbols`]. pub struct SymbolDetails { pub name: String, @@ -198,23 +229,7 @@ impl<'a> Module<'a> { 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 path: String = NativePointer((*details).path as *mut _) - .try_into() - .unwrap_or_default(); - let range = (*details).range; - let base_address = (*range).base_address as usize; - let size = (*range).size as usize; - let module_details = ModuleDetailsOwned { - name, - path, - base_address, - size, - }; - res.push(module_details); + res.push(ModuleDetailsOwned::from_module_details(details)); 1 } diff --git a/frida-gum/src/process.rs b/frida-gum/src/process.rs new file mode 100644 index 0000000..2bea715 --- /dev/null +++ b/frida-gum/src/process.rs @@ -0,0 +1,130 @@ +//! Module helpers. +//! + +#![cfg_attr( + any(target_arch = "x86_64", target_arch = "x86"), + allow(clippy::unnecessary_cast) +)] + +use crate::{FileMapping, NativePointer}; + +use { + crate::{module, Gum, PageProtection, RangeDetails}, + core::ffi::c_void, + frida_gum_sys as gum_sys, + frida_gum_sys::{gboolean, gpointer}, +}; + +use crate::alloc::borrow::ToOwned; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +#[derive(Clone, FromPrimitive, Debug)] +#[repr(u32)] +pub enum CodeSigningPolicy { + CodeSigningOptional = gum_sys::GumCodeSigningPolicy_GUM_CODE_SIGNING_OPTIONAL as u32, + CodeSigningRequired = gum_sys::GumCodeSigningPolicy_GUM_CODE_SIGNING_REQUIRED as u32, +} + +#[derive(Clone, FromPrimitive, Debug)] +#[repr(u32)] +pub enum Os { + OsWindows = gum_sys::_GumOS_GUM_OS_WINDOWS as u32, + OsMacos = gum_sys::_GumOS_GUM_OS_MACOS as u32, + OsLinux = gum_sys::_GumOS_GUM_OS_LINUX as u32, + OsIos = gum_sys::_GumOS_GUM_OS_IOS as u32, + OsWatchos = gum_sys::_GumOS_GUM_OS_WATCHOS as u32, + OsTvos = gum_sys::_GumOS_GUM_OS_TVOS as u32, + OsAndroid = gum_sys::_GumOS_GUM_OS_ANDROID as u32, + OsFreebsd = gum_sys::_GumOS_GUM_OS_FREEBSD as u32, + OsQnx = gum_sys::_GumOS_GUM_OS_QNX as u32, +} + +pub struct Range<'a> { + pub base: NativePointer, + pub size: usize, + pub protection: PageProtection, + pub file: Option>, +} + +pub struct Process<'a> { + // This is to verify that Gum is initialized before using any Module methods which requires + // intialization. + // Note that Gum is expected to be initialized via OnceCell which provides &Gum for every + // instance. + _gum: &'a Gum, + pub id: u32, + pub platform: Os, + pub code_signing_policy: CodeSigningPolicy, + pub main_module: module::ModuleDetailsOwned, +} + +impl<'a> Process<'a> { + pub fn obtain(gum: &'a Gum) -> Process<'a> { + let id = unsafe { gum_sys::gum_process_get_id() }; + let platform = + num::FromPrimitive::from_u32(unsafe { gum_sys::gum_process_get_native_os() }).unwrap(); + let code_signing_policy = + num::FromPrimitive::from_u32(unsafe { gum_sys::gum_process_get_code_signing_policy() }) + .unwrap(); + + let main_module = unsafe { + module::ModuleDetailsOwned::from_module_details(gum_sys::gum_process_get_main_module()) + }; + + Process { + _gum: gum, + id, + platform, + code_signing_policy, + main_module, + } + } + + pub fn enumerate_ranges(&self, protection: PageProtection) -> Vec> { + struct CallbackData<'a> { + ranges: Vec>, + protection: PageProtection, + } + + unsafe extern "C" fn enumerate_ranges_callback( + 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().to_owned(); + + res.ranges.push(Range { + base: m_range.base_address(), + size: m_range.size(), + protection: prot, + file: file_map, + }); + } + + 1 + } + + // Initialize the callback data + let callback_data = CallbackData { + ranges: Vec::new(), + protection: protection.clone(), + }; + + unsafe { + gum_sys::gum_process_enumerate_ranges( + protection as u32, + Some(enumerate_ranges_callback), + &callback_data as *const _ as *mut c_void, + ); + } + + callback_data.ranges + } +} diff --git a/frida-gum/src/range_details.rs b/frida-gum/src/range_details.rs index 6b19bc8..e29cb2b 100644 --- a/frida-gum/src/range_details.rs +++ b/frida-gum/src/range_details.rs @@ -25,7 +25,7 @@ use { use alloc::{boxed::Box, string::String}; /// The memory protection of an unassociated page. -#[derive(Clone, FromPrimitive, Debug)] +#[derive(Clone, FromPrimitive, Debug, PartialEq)] #[repr(u32)] pub enum PageProtection { NoAccess = gum_sys::_GumPageProtection_GUM_PAGE_NO_ACCESS as u32, From c19c3a3ceef68aa08da867226d9801629eb8c0eb Mon Sep 17 00:00:00 2001 From: xoffio <38369407+Xoffio@users.noreply.github.com> Date: Tue, 26 Nov 2024 00:04:28 -0500 Subject: [PATCH 2/6] fix CI check --- frida-gum/src/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frida-gum/src/process.rs b/frida-gum/src/process.rs index 2bea715..fd1b900 100644 --- a/frida-gum/src/process.rs +++ b/frida-gum/src/process.rs @@ -96,7 +96,7 @@ impl<'a> Process<'a> { let r_details = RangeDetails::from_raw(details); let prot = r_details.protection(); - if &res.protection == &prot { + if res.protection == prot { let m_range = r_details.memory_range(); let file_map = r_details.file_mapping().to_owned(); From fb17a15135f3764ac8bb42ed8a5802de706f9964 Mon Sep 17 00:00:00 2001 From: xoffio <38369407+Xoffio@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:34:50 -0500 Subject: [PATCH 3/6] fix CI issue --- frida-gum/src/process.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frida-gum/src/process.rs b/frida-gum/src/process.rs index fd1b900..9974e66 100644 --- a/frida-gum/src/process.rs +++ b/frida-gum/src/process.rs @@ -15,8 +15,6 @@ use { frida_gum_sys::{gboolean, gpointer}, }; -use crate::alloc::borrow::ToOwned; - #[cfg(not(feature = "std"))] use alloc::vec::Vec; @@ -98,7 +96,7 @@ impl<'a> Process<'a> { let prot = r_details.protection(); if res.protection == prot { let m_range = r_details.memory_range(); - let file_map = r_details.file_mapping().to_owned(); + let file_map = r_details.file_mapping(); res.ranges.push(Range { base: m_range.base_address(), From 8e645a79421b844cc2e1f3a42816e004768570e1 Mon Sep 17 00:00:00 2001 From: xoffio <38369407+Xoffio@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:52:40 -0500 Subject: [PATCH 4/6] Fix CI issue --- frida-gum/src/process.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frida-gum/src/process.rs b/frida-gum/src/process.rs index 9974e66..71fd30b 100644 --- a/frida-gum/src/process.rs +++ b/frida-gum/src/process.rs @@ -63,9 +63,10 @@ impl<'a> Process<'a> { let id = unsafe { gum_sys::gum_process_get_id() }; let platform = num::FromPrimitive::from_u32(unsafe { gum_sys::gum_process_get_native_os() }).unwrap(); - let code_signing_policy = - num::FromPrimitive::from_u32(unsafe { gum_sys::gum_process_get_code_signing_policy() }) - .unwrap(); + let code_signing_policy = num::FromPrimitive::from_u32(unsafe { + gum_sys::gum_process_get_code_signing_policy() as u32 + }) + .unwrap(); let main_module = unsafe { module::ModuleDetailsOwned::from_module_details(gum_sys::gum_process_get_main_module()) From 8a31461f34d2732c097e34f0105dc2ce3bc66aba Mon Sep 17 00:00:00 2001 From: xoffio <38369407+Xoffio@users.noreply.github.com> Date: Sat, 30 Nov 2024 16:35:06 -0500 Subject: [PATCH 5/6] documentaion updated --- frida-gum/src/process.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/frida-gum/src/process.rs b/frida-gum/src/process.rs index 71fd30b..fff714a 100644 --- a/frida-gum/src/process.rs +++ b/frida-gum/src/process.rs @@ -1,4 +1,4 @@ -//! Module helpers. +//! Process helpers. //! #![cfg_attr( @@ -40,9 +40,13 @@ pub enum Os { } pub struct Range<'a> { + /// Base address pub base: NativePointer, + /// Size in bytes pub size: usize, + /// Protection flag (e.g., Read, Write, Execute) pub protection: PageProtection, + /// When available, file mapping details. pub file: Option>, } @@ -52,13 +56,19 @@ pub struct Process<'a> { // Note that Gum is expected to be initialized via OnceCell which provides &Gum for every // instance. _gum: &'a Gum, + /// Property containing the PID as a number pub id: u32, + /// Properly specifying the current platform. pub platform: Os, + /// Property which can be `optional` or `required`, where the latter means Frida will avoid modifying + /// existing code in memory and will not try to run unsigned code. pub code_signing_policy: CodeSigningPolicy, + /// Contains a Module representing the main executable of the process. pub main_module: module::ModuleDetailsOwned, } impl<'a> Process<'a> { + /// Initialize a new process pub fn obtain(gum: &'a Gum) -> Process<'a> { let id = unsafe { gum_sys::gum_process_get_id() }; let platform = @@ -81,6 +91,7 @@ impl<'a> Process<'a> { } } + /// Enumerates memory ranges satisfying `protection` given pub fn enumerate_ranges(&self, protection: PageProtection) -> Vec> { struct CallbackData<'a> { ranges: Vec>, @@ -110,7 +121,6 @@ impl<'a> Process<'a> { 1 } - // Initialize the callback data let callback_data = CallbackData { ranges: Vec::new(), protection: protection.clone(), From a6c02b9c4f35a8dd5599c14e06f4828c4740bdf5 Mon Sep 17 00:00:00 2001 From: xoffio <38369407+Xoffio@users.noreply.github.com> Date: Sun, 1 Dec 2024 13:49:17 -0500 Subject: [PATCH 6/6] Fix CI issue Github CI is now using rustc 1.82.0 --- frida-gum/src/module.rs | 2 +- frida-gum/src/range_details.rs | 2 +- frida-gum/src/stalker/transformer.rs | 2 +- frida/src/device.rs | 2 +- frida/src/device_manager.rs | 8 ++++---- frida/src/injector.rs | 6 +++--- frida/src/process.rs | 8 ++++---- frida/src/script.rs | 6 +++--- frida/src/session.rs | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/frida-gum/src/module.rs b/frida-gum/src/module.rs index bbd499a..37bca9d 100644 --- a/frida-gum/src/module.rs +++ b/frida-gum/src/module.rs @@ -122,7 +122,7 @@ pub struct Module<'a> { _gum: &'a Gum, } -impl<'a> Module<'a> { +impl Module<'_> { pub fn obtain(gum: &Gum) -> Module { Module { _gum: gum } } diff --git a/frida-gum/src/range_details.rs b/frida-gum/src/range_details.rs index e29cb2b..092497a 100644 --- a/frida-gum/src/range_details.rs +++ b/frida-gum/src/range_details.rs @@ -64,7 +64,7 @@ pub struct FileMapping<'a> { phantom: PhantomData<&'a gum_sys::GumFileMapping>, } -impl<'a> FileMapping<'a> { +impl FileMapping<'_> { pub(crate) fn from_raw(file: *const gum_sys::GumFileMapping) -> Option { if file.is_null() { None diff --git a/frida-gum/src/stalker/transformer.rs b/frida-gum/src/stalker/transformer.rs index 48a29d6..ed8675f 100644 --- a/frida-gum/src/stalker/transformer.rs +++ b/frida-gum/src/stalker/transformer.rs @@ -204,7 +204,7 @@ impl<'a> Transformer<'a> { } } -impl<'a> Drop for Transformer<'a> { +impl Drop for Transformer<'_> { fn drop(&mut self) { unsafe { frida_gum_sys::g_object_unref(self.transformer as *mut c_void) } } diff --git a/frida/src/device.rs b/frida/src/device.rs index e7502a4..8f6933b 100644 --- a/frida/src/device.rs +++ b/frida/src/device.rs @@ -253,7 +253,7 @@ impl<'a> Device<'a> { } } -impl<'a> Drop for Device<'a> { +impl Drop for Device<'_> { fn drop(&mut self) { unsafe { frida_sys::frida_unref(self.device_ptr as _) } } diff --git a/frida/src/device_manager.rs b/frida/src/device_manager.rs index 3261b76..9325399 100644 --- a/frida/src/device_manager.rs +++ b/frida/src/device_manager.rs @@ -82,7 +82,7 @@ impl<'a> DeviceManager<'a> { return Err(Error::DeviceLookupFailed); } - return Ok(Device::from_raw(device_ptr)); + Ok(Device::from_raw(device_ptr)) } /// Returns the remote device with the specified host. @@ -104,7 +104,7 @@ impl<'a> DeviceManager<'a> { return Err(Error::DeviceLookupFailed); } - return Ok(Device::from_raw(device_ptr)); + Ok(Device::from_raw(device_ptr)) } /// Returns the local device. @@ -141,11 +141,11 @@ impl<'a> DeviceManager<'a> { return Err(Error::DeviceLookupFailed); } - return Ok(Device::from_raw(device_ptr)); + Ok(Device::from_raw(device_ptr)) } } -impl<'a> Drop for DeviceManager<'a> { +impl Drop for DeviceManager<'_> { fn drop(&mut self) { unsafe { frida_sys::frida_device_manager_close_sync( diff --git a/frida/src/injector.rs b/frida/src/injector.rs index 1fd7eb2..c37a864 100644 --- a/frida/src/injector.rs +++ b/frida/src/injector.rs @@ -44,7 +44,7 @@ impl<'a> Injector<'a> { } } -impl<'a> Default for Injector<'a> { +impl Default for Injector<'_> { fn default() -> Self { Self::new() } @@ -130,7 +130,7 @@ pub trait Inject { E: AsRef; } -impl<'a> Inject for Injector<'a> { +impl Inject for Injector<'_> { fn inject_library_file_sync( &mut self, pid: u32, @@ -228,7 +228,7 @@ impl<'a> Inject for Injector<'a> { } } -impl<'a> Inject for Device<'a> { +impl Inject for Device<'_> { fn inject_library_file_sync( &mut self, pid: u32, diff --git a/frida/src/process.rs b/frida/src/process.rs index 2b126ce..6333de2 100644 --- a/frida/src/process.rs +++ b/frida/src/process.rs @@ -36,7 +36,7 @@ impl<'a> Process<'a> { } } -impl<'a> Drop for Process<'a> { +impl Drop for Process<'_> { fn drop(&mut self) { unsafe { frida_sys::frida_unref(self.process_ptr as _) } } @@ -59,7 +59,7 @@ pub struct SpawnOptions<'a> { phantom: PhantomData<&'a FridaSpawnOptions>, } -impl<'a> SpawnOptions<'a> { +impl SpawnOptions<'_> { pub(crate) fn from_raw(options_ptr: *mut FridaSpawnOptions) -> Self { Self { options_ptr, @@ -159,13 +159,13 @@ impl<'a> SpawnOptions<'a> { } } -impl<'a> Default for SpawnOptions<'a> { +impl Default for SpawnOptions<'_> { fn default() -> Self { Self::new() } } -impl<'a> Drop for SpawnOptions<'a> { +impl Drop for SpawnOptions<'_> { fn drop(&mut self) { unsafe { frida_sys::frida_unref(self.options_ptr as _) } } diff --git a/frida/src/script.rs b/frida/src/script.rs index 412a9f0..8941d53 100644 --- a/frida/src/script.rs +++ b/frida/src/script.rs @@ -152,7 +152,7 @@ pub struct Exports<'a> { phantom: PhantomData<&'a _FridaScript>, } -impl<'a> Exports<'a> { +impl Exports<'_> { fn inc_id(&mut self) -> usize { let mut counter_borrow = self.rpc_id_counter.borrow_mut(); *counter_borrow += 1; @@ -306,7 +306,7 @@ impl<'a> Script<'a> { } } -impl<'a> Exports<'a> { +impl Exports<'_> { /// Run exported functions from a Frida script. pub fn call(&mut self, function_name: &str, args: Option) -> Result> { let json_req: String = { @@ -356,7 +356,7 @@ impl<'a> Exports<'a> { } } -impl<'a> Drop for Script<'a> { +impl Drop for Script<'_> { fn drop(&mut self) { unsafe { frida_sys::frida_unref(self.script_ptr as _) } } diff --git a/frida/src/session.rs b/frida/src/session.rs index d74bb3c..534be97 100644 --- a/frida/src/session.rs +++ b/frida/src/session.rs @@ -77,7 +77,7 @@ impl<'a> Session<'a> { } } -impl<'a> Drop for Session<'a> { +impl Drop for Session<'_> { fn drop(&mut self) { unsafe { frida_sys::frida_unref(self.session_ptr as _) } }