Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions examples/gum/process_check/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "process-check"
version = "0.1.0"
authors = ["Xoffio / Ricardo J Marques Montilla"]
edition = "2018"
license = "MIT"
publish = false

[lib]
crate-type = ["cdylib"]

[dependencies]
frida-gum = { path = "../../../frida-gum", features = [
"invocation-listener",
# "std",
] }
ctor = "0.6.1"
7 changes: 7 additions & 0 deletions examples/gum/process_check/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Example to show all available `Process` functions.

```sh
cargo build --release

LD_PRELOAD=../../../target/release/libprocess_check.so cat /tmp/test.txt
```
85 changes: 85 additions & 0 deletions examples/gum/process_check/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use ctor::ctor;
use frida_gum::{
interceptor::{Interceptor, InvocationContext, ProbeListener},
Gum, Module,
};
use std::{sync::OnceLock, thread};

#[derive(Default, Debug)]
struct OpenProbeListener;

fn sleep_loop(secs: usize) {
for _ in 0..secs {
thread::sleep(std::time::Duration::from_millis(1000));
}
}

// I just made this function to test Process.enumerate_threads
impl ProbeListener for OpenProbeListener {
fn on_hit(&mut self, _context: InvocationContext<'_>) {
// println!("on_hit: open()");

let mut tasks = Vec::new();
for _ in 0..3 {
let task = thread::spawn(|| sleep_loop(3));
tasks.push(task);
}
}
}

#[ctor]
fn init() {
static CELL: OnceLock<Gum> = OnceLock::new();
let gum = CELL.get_or_init(|| Gum::obtain());

let handle = thread::spawn(move || {
let mut interceptor = Interceptor::obtain(gum);

// Load libc and find the export for open()
let module = Module::load(gum, "libc.so.6");
let open = module.find_export_by_name("open").unwrap();

let mut listener = OpenProbeListener;
interceptor.attach_instruction(open, &mut listener).unwrap();
});

let process = frida_gum::Process::obtain(&gum);

println!("Process Information");
println!("-------------------");
println!(" - ID: {}", process.id());
println!(" - Platform {:?}", process.platform());
println!(
" - Code signing policy: {:?}",
process.code_signing_policy()
);
println!(" - Main module: {:?}", process.main_module());
println!(" - Current directory: {}", process.current_dir());
println!(" - Home directory: {}", process.home_dir());
println!(" - Tmp directory: {}", process.tmp_dir());
println!(
" - Is debugger attached? {}",
process.is_debugger_attached()
);
println!(" - Current thread ID: {}", process.current_thread_id());

println!(" - Enumerate threads:");
let threads = process.enumerate_threads();
for thread in threads {
println!(" - {:?}", thread);
}

println!(" - Enumerate modules:");
let ranges = process.enumerate_modules();
for module in ranges {
println!(" - {:?}", module);
}

println!(" - Enumerate ranges (rwx):");
let ranges = process.enumerate_ranges(frida_gum::PageProtection::ReadWriteExecute);
for range in ranges {
println!(" - {:#?}", range);
}

handle.join();
}
19 changes: 15 additions & 4 deletions frida-gum/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::{ffi::CStr, string::ToString};

use {
crate::{Gum, NativePointer, PageProtection, RangeDetails},
core::{ffi::c_void, fmt},
core::{ffi::c_void, fmt, fmt::Debug},
cstr_core::CString,
frida_gum_sys as gum_sys,
frida_gum_sys::{
Expand All @@ -28,7 +28,10 @@ use {
};

#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, string::String, vec, vec::Vec};
use {
alloc::{boxed::Box, string::String, string::ToString, vec, vec::Vec},
core::ffi::CStr,
};

extern "C" fn enumerate_ranges_callout(
range_details: *const gum_sys::_GumRangeDetails,
Expand Down Expand Up @@ -98,6 +101,7 @@ impl Module {
}
Self { inner: module }
}

/// Load a module by name
pub fn load(_gum: &Gum, module_name: &str) -> Self {
let module_name = CString::new(module_name).unwrap();
Expand All @@ -108,7 +112,6 @@ impl Module {
}
}

#[cfg(feature = "std")]
/// Get the name of this module
pub fn name(&self) -> String {
unsafe {
Expand All @@ -118,7 +121,6 @@ impl Module {
}
}

#[cfg(feature = "std")]
/// Get the path of this module
pub fn path(&self) -> String {
unsafe {
Expand Down Expand Up @@ -310,3 +312,12 @@ impl Module {
result
}
}

impl Debug for Module {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Module")
.field("name", &self.name())
.field("path", &self.path())
.finish_non_exhaustive()
}
}
76 changes: 44 additions & 32 deletions frida-gum/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{FileMapping, Module, NativePointer, Thread};
use {
crate::{Gum, PageProtection, RangeDetails},
core::ffi::{c_char, c_void, CStr},
core::{fmt, fmt::Debug},
frida_gum_sys as gum_sys,
frida_gum_sys::{gboolean, gpointer},
};
Expand Down Expand Up @@ -44,15 +45,15 @@ pub enum CodeSigningPolicy {
#[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,
Windows = gum_sys::_GumOS_GUM_OS_WINDOWS as u32,
Macos = gum_sys::_GumOS_GUM_OS_MACOS as u32,
Linux = gum_sys::_GumOS_GUM_OS_LINUX as u32,
Ios = gum_sys::_GumOS_GUM_OS_IOS as u32,
Watchos = gum_sys::_GumOS_GUM_OS_WATCHOS as u32,
Tvos = gum_sys::_GumOS_GUM_OS_TVOS as u32,
Android = gum_sys::_GumOS_GUM_OS_ANDROID as u32,
Freebsd = gum_sys::_GumOS_GUM_OS_FREEBSD as u32,
Qnx = gum_sys::_GumOS_GUM_OS_QNX as u32,
}

pub struct Range<'a> {
Expand All @@ -72,37 +73,36 @@ 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,
}

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 =
num::FromPrimitive::from_u32(unsafe { gum_sys::gum_process_get_native_os() }).unwrap();
let code_signing_policy = num::FromPrimitive::from_u32(unsafe {
Process { _gum: gum }
}

/// Property containing the PID as a number
pub fn id(&self) -> u32 {
unsafe { gum_sys::gum_process_get_id() }
}

/// Properly specifying the current platform.
pub fn platform(&self) -> Os {
num::FromPrimitive::from_u32(unsafe { gum_sys::gum_process_get_native_os() }).unwrap()
}

/// Returns 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 fn code_signing_policy(&self) -> CodeSigningPolicy {
num::FromPrimitive::from_u32(unsafe {
gum_sys::gum_process_get_code_signing_policy() as u32
})
.unwrap();

let main_module = unsafe { Module::from_raw(gum_sys::gum_process_get_main_module()) };
.unwrap()
}

Process {
_gum: gum,
id,
platform,
code_signing_policy,
main_module,
}
/// Returns a Module representing the main executable of the process.
pub fn main_module(&self) -> Module {
unsafe { Module::from_raw(gum_sys::gum_process_get_main_module()) }
}

pub fn find_module_by_name(&self, module_name: &str) -> Option<Module> {
Expand All @@ -127,6 +127,7 @@ impl<'a> Process<'a> {
}
}
}

/// Returns a string specifying the filesystem path to the current working directory
pub fn current_dir(&self) -> String {
unsafe {
Expand Down Expand Up @@ -276,3 +277,14 @@ impl<'a> Process<'a> {
callback_data
}
}

impl Debug for Range<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Range")
.field("base", &self.base)
.field("size", &self.size)
.field("protection", &self.protection)
.field("file", &self.file)
.finish()
}
}
2 changes: 1 addition & 1 deletion frida-gum/src/range_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl fmt::Display for PageProtection {
}

/// The file association to a page.
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct FileMapping<'a> {
path: String,
size: usize,
Expand Down
Loading