Skip to content

Commit

Permalink
frida-gum: force frida-gum init to use Module (frida#98)
Browse files Browse the repository at this point in the history
In order to use the underlying C API global init should be called.

We hence force the creation of Gum to use Module::* functions.

We also use OnceLock instead of lazy_static! as discussed in the issue.
  • Loading branch information
elazarl committed Oct 28, 2024
1 parent 62a7e6b commit 147b799
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 34 deletions.
13 changes: 6 additions & 7 deletions examples/gum/debug_symbol/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use frida_gum::DebugSymbol;
use frida_gum::{Gum, Module};
use lazy_static::lazy_static;

lazy_static! {
static ref GUM: Gum = unsafe { Gum::obtain() };
}
use std::iter::Once;
use std::sync::OnceLock;

fn main() {
lazy_static::initialize(&GUM);
static CELL: OnceLock<Gum> = OnceLock::new();
let gum = CELL.get_or_init(|| Gum::obtain());

let symbol = Module::find_export_by_name(None, "mmap").unwrap();
let module = Module::from_gum(gum);
let symbol = module.find_export_by_name(None, "mmap").unwrap();
let symbol_details = DebugSymbol::from_address(symbol).unwrap();
println!(
"address={:#x?} module_name={:?} symbol_name={:?} file_name={:?} line_number={:?}",
Expand Down
1 change: 0 additions & 1 deletion examples/gum/hook_instruction/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ crate-type = ["cdylib"]

[dependencies]
frida-gum = { path = "../../../frida-gum", features = ["invocation-listener"] }
lazy_static = "1.4"
ctor = "0.2"
13 changes: 6 additions & 7 deletions examples/gum/hook_instruction/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ use frida_gum::{
interceptor::{Interceptor, InvocationContext, ProbeListener},
Gum, Module,
};
use lazy_static::lazy_static;

lazy_static! {
static ref GUM: Gum = unsafe { Gum::obtain() };
}
use std::sync::OnceLock;
#[derive(Default, Debug)]
struct OpenProbeListener;

Expand All @@ -19,8 +15,11 @@ impl ProbeListener for OpenProbeListener {

#[ctor]
fn init() {
let mut interceptor = Interceptor::obtain(&GUM);
let open = Module::find_export_by_name(None, "open").unwrap();
static CELL: OnceLock<Gum> = OnceLock::new();
let gum = CELL.get_or_init(|| Gum::obtain());
let mut interceptor = Interceptor::obtain(gum);
let module = Module::from_gum(gum);
let open = module.find_export_by_name(None, "open").unwrap();
let mut listener = OpenProbeListener;
interceptor.attach_instruction(open, &mut listener).unwrap();
}
9 changes: 6 additions & 3 deletions examples/gum/hook_open/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use lazy_static::lazy_static;
use libc::{c_char, c_int, c_void};
use std::cell::UnsafeCell;
use std::sync::Mutex;
use std::sync::OnceLock;

lazy_static! {
static ref GUM: Gum = unsafe { Gum::obtain() };
static ref ORIGINAL_OPEN: Mutex<UnsafeCell<Option<OpenFunc>>> =
Mutex::new(UnsafeCell::new(None));
}
Expand All @@ -29,8 +29,11 @@ unsafe extern "C" fn open_detour(name: *const c_char, flags: c_int) -> c_int {

#[ctor]
fn init() {
let mut interceptor = Interceptor::obtain(&GUM);
let open = Module::find_export_by_name(None, "open").unwrap();
static CELL: OnceLock<Gum> = OnceLock::new();
let gum = CELL.get_or_init(|| Gum::obtain());
let module = Module::from_gum(gum);
let mut interceptor = Interceptor::obtain(gum);
let open = module.find_export_by_name(None, "open").unwrap();
unsafe {
*ORIGINAL_OPEN.lock().unwrap().get_mut() = Some(std::mem::transmute::<
*mut libc::c_void,
Expand Down
1 change: 0 additions & 1 deletion examples/gum/open/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ crate-type = ["cdylib"]

[dependencies]
frida-gum = { path = "../../../frida-gum", features = ["invocation-listener"] }
lazy_static = "1.4"
16 changes: 8 additions & 8 deletions examples/gum/open/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@ use gum::{
interceptor::{Interceptor, InvocationContext, InvocationListener},
Gum, Module,
};
use lazy_static::lazy_static;
use std::os::raw::{c_int, c_void};

lazy_static! {
static ref GUM: Gum = unsafe { Gum::obtain() };
}
use std::sync::OnceLock;

struct OpenListener;

Expand All @@ -28,17 +24,21 @@ impl InvocationListener for OpenListener {
extern "C" fn example_agent_main(_user_data: *const c_void, resident: *mut c_int) {
unsafe { *resident = 1 };

let mut interceptor = Interceptor::obtain(&GUM);
static CELL: OnceLock<Gum> = OnceLock::new();
let gum = CELL.get_or_init(|| Gum::obtain());

let mut interceptor = Interceptor::obtain(gum);
let mut listener = OpenListener {};

let modules = Module::enumerate_modules();
let module = Module::from_gum(gum);
let modules = module.enumerate_modules();
for module in modules {
println!(
"{}@{:#x}/{:#x}",
module.name, module.base_address, module.size
);
}

let open = Module::find_export_by_name(None, "open").unwrap();
let open = module.find_export_by_name(None, "open").unwrap();
interceptor.attach(open, &mut listener).unwrap();
}
30 changes: 23 additions & 7 deletions frida-gum/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)]

use {
crate::{NativePointer, PageProtection, RangeDetails},
crate::{Gum, NativePointer, PageProtection, RangeDetails},
core::ffi::c_void,
cstr_core::CString,
frida_gum_sys as gum_sys,
Expand Down Expand Up @@ -56,12 +56,23 @@ pub struct ModuleDetailsOwned {
pub size: usize,
}

pub struct Module;
pub struct Module {
// 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: &'static Gum,
}

impl Module {
pub fn from_gum(gum: &'static Gum) -> Module {
Module { _gum: gum }
}

/// The absolute address of the export. In the event that no such export
/// could be found, returns NULL.
pub fn find_export_by_name(
self: &Self,
module_name: Option<&str>,
symbol_name: &str,
) -> Option<NativePointer> {
Expand Down Expand Up @@ -92,7 +103,11 @@ impl Module {

/// The absolute address of the symbol. In the event that no such symbol
/// could be found, returns NULL.
pub fn find_symbol_by_name(module_name: &str, symbol_name: &str) -> Option<NativePointer> {
pub fn find_symbol_by_name(
self: &Self,
module_name: &str,
symbol_name: &str,
) -> Option<NativePointer> {
let symbol_name = CString::new(symbol_name).unwrap();

let module_name = CString::new(module_name).unwrap();
Expand All @@ -112,7 +127,7 @@ impl Module {

/// Returns the base address of the specified module. In the event that no
/// such module could be found, returns NULL.
pub fn find_base_address(module_name: &str) -> NativePointer {
pub fn find_base_address(self: &Self, module_name: &str) -> NativePointer {
let module_name = CString::new(module_name).unwrap();

unsafe {
Expand All @@ -124,6 +139,7 @@ impl Module {

/// Enumerates memory ranges satisfying protection given.
pub fn enumerate_ranges(
self: &Self,
module_name: &str,
prot: PageProtection,
callout: impl FnMut(RangeDetails) -> bool,
Expand All @@ -147,7 +163,7 @@ impl Module {
}

/// Enumerates modules.
pub fn enumerate_modules() -> Vec<ModuleDetailsOwned> {
pub fn enumerate_modules(self: &Self) -> Vec<ModuleDetailsOwned> {
let result: Vec<ModuleDetailsOwned> = vec![];

unsafe extern "C" fn callback(
Expand Down Expand Up @@ -187,7 +203,7 @@ impl Module {
}

/// Enumerates exports in module.
pub fn enumerate_exports(module_name: &str) -> Vec<ExportDetails> {
pub fn enumerate_exports(self: &Self, module_name: &str) -> Vec<ExportDetails> {
let result: Vec<ExportDetails> = vec![];

unsafe extern "C" fn callback(
Expand Down Expand Up @@ -219,7 +235,7 @@ impl Module {
}

/// Enumerates symbols in module.
pub fn enumerate_symbols(module_name: &str) -> Vec<SymbolDetails> {
pub fn enumerate_symbols(self: &Self, module_name: &str) -> Vec<SymbolDetails> {
let result: Vec<SymbolDetails> = vec![];
unsafe extern "C" fn callback(
details: *const GumSymbolDetails,
Expand Down

0 comments on commit 147b799

Please sign in to comment.