Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

frida: clarify runtime lifetimes #160

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
72 changes: 24 additions & 48 deletions frida/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,35 @@
use frida_sys::_FridaDevice;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::marker::PhantomData;

use crate::process::Process;
use crate::session::Session;
use crate::variant::Variant;
use crate::{Error, Result, SpawnOptions};
use crate::{Error, Frida, GObject, Result, SpawnOptions};

/// Access to a Frida device.
pub struct Device<'a> {
pub(crate) device_ptr: *mut _FridaDevice,
phantom: PhantomData<&'a _FridaDevice>,
pub struct Device(GObject<_FridaDevice>);

impl Device {
pub(crate) fn ptr(&self) -> *mut _FridaDevice {
self.0.ptr()
}
}

impl<'a> Device<'a> {
pub(crate) fn from_raw(device_ptr: *mut _FridaDevice) -> Device<'a> {
Device {
device_ptr,
phantom: PhantomData,
}
impl Device {
pub(crate) fn from_raw(frida: Frida, ptr: *mut _FridaDevice) -> Self {
Self(GObject::new(ptr, frida))
}

/// Returns the device's name.
pub fn get_name(&self) -> &str {
let name =
unsafe { CStr::from_ptr(frida_sys::frida_device_get_name(self.device_ptr) as _) };
let name = unsafe { CStr::from_ptr(frida_sys::frida_device_get_name(self.0.ptr()) as _) };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not call the ptr() function above?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for the rest of the self.0.ptr() calls...

name.to_str().unwrap_or_default()
}

/// Returns the device's id.
pub fn get_id(&self) -> &str {
let id = unsafe { CStr::from_ptr(frida_sys::frida_device_get_id(self.device_ptr) as _) };
let id = unsafe { CStr::from_ptr(frida_sys::frida_device_get_id(self.0.ptr()) as _) };
id.to_str().unwrap_or_default()
}

Expand All @@ -52,7 +50,7 @@ impl<'a> Device<'a> {
/// assert_eq!(device.get_type(), DeviceType::Local);
/// ```
pub fn get_type(&self) -> DeviceType {
unsafe { frida_sys::frida_device_get_dtype(self.device_ptr).into() }
unsafe { frida_sys::frida_device_get_dtype(self.0.ptr()).into() }
}

/// Returns the device's system parameters
Expand All @@ -79,7 +77,7 @@ impl<'a> Device<'a> {

let ht = unsafe {
frida_sys::frida_device_query_system_parameters_sync(
self.device_ptr,
self.0.ptr(),
std::ptr::null_mut(),
&mut error,
)
Expand Down Expand Up @@ -115,20 +113,17 @@ impl<'a> Device<'a> {

/// Returns if the device is lost or not.
pub fn is_lost(&self) -> bool {
unsafe { frida_sys::frida_device_is_lost(self.device_ptr) == 1 }
unsafe { frida_sys::frida_device_is_lost(self.0.ptr()) == 1 }
}

/// Returns all processes.
pub fn enumerate_processes<'b>(&'a self) -> Vec<Process<'b>>
where
'a: 'b,
{
pub fn enumerate_processes(&self) -> Vec<Process> {
let mut processes = Vec::new();
let mut error: *mut frida_sys::GError = std::ptr::null_mut();

let processes_ptr = unsafe {
frida_sys::frida_device_enumerate_processes_sync(
self.device_ptr,
self.0.ptr(),
std::ptr::null_mut(),
std::ptr::null_mut(),
&mut error,
Expand All @@ -141,7 +136,7 @@ impl<'a> Device<'a> {

for i in 0..num_processes {
let process_ptr = unsafe { frida_sys::frida_process_list_get(processes_ptr, i) };
let process = Process::from_raw(process_ptr);
let process = Process::from_raw(self.0.runtime().clone(), process_ptr);
processes.push(process);
}
}
Expand All @@ -151,14 +146,11 @@ impl<'a> Device<'a> {
}

/// Creates [`Session`] and attaches the device to the current PID.
pub fn attach<'b>(&'a self, pid: u32) -> Result<Session<'b>>
where
'a: 'b,
{
pub fn attach(&self, pid: u32) -> Result<Session> {
let mut error: *mut frida_sys::GError = std::ptr::null_mut();
let session = unsafe {
frida_sys::frida_device_attach_sync(
self.device_ptr,
self.ptr(),
pid,
std::ptr::null_mut(),
std::ptr::null_mut(),
Expand All @@ -184,9 +176,9 @@ impl<'a> Device<'a> {

let pid = unsafe {
frida_sys::frida_device_spawn_sync(
self.device_ptr,
self.ptr(),
program.as_ptr(),
options.options_ptr,
options.ptr(),
std::ptr::null_mut(),
&mut error,
)
Expand All @@ -208,12 +200,7 @@ impl<'a> Device<'a> {
pub fn resume(&self, pid: u32) -> Result<()> {
let mut error: *mut frida_sys::GError = std::ptr::null_mut();
unsafe {
frida_sys::frida_device_resume_sync(
self.device_ptr,
pid,
std::ptr::null_mut(),
&mut error,
)
frida_sys::frida_device_resume_sync(self.ptr(), pid, std::ptr::null_mut(), &mut error)
};

if !error.is_null() {
Expand All @@ -232,12 +219,7 @@ impl<'a> Device<'a> {
pub fn kill(&mut self, pid: u32) -> Result<()> {
let mut error: *mut frida_sys::GError = std::ptr::null_mut();
unsafe {
frida_sys::frida_device_kill_sync(
self.device_ptr,
pid,
std::ptr::null_mut(),
&mut error,
)
frida_sys::frida_device_kill_sync(self.ptr(), pid, std::ptr::null_mut(), &mut error)
};

if !error.is_null() {
Expand All @@ -253,12 +235,6 @@ impl<'a> Device<'a> {
}
}

impl<'a> Drop for Device<'a> {
fn drop(&mut self) {
unsafe { frida_sys::frida_unref(self.device_ptr as _) }
}
}

#[repr(u32)]
#[non_exhaustive]
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
Expand Down
41 changes: 18 additions & 23 deletions frida/src/device_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use frida_sys::_FridaDeviceManager;
use std::ffi::CString;
use std::marker::PhantomData;

use crate::device::{self, Device};
use crate::DeviceType;
Expand All @@ -15,29 +14,24 @@ use crate::Frida;
use crate::Result;

/// Platform-independent device manager abstraction access.
pub struct DeviceManager<'a> {
#[derive(Clone)]
pub struct DeviceManager {
frida: Frida,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we call this frida here, but runtime() above... Let's choose one and stick with it.

manager_ptr: *mut _FridaDeviceManager,
phantom: PhantomData<&'a _FridaDeviceManager>,
}

impl<'a> DeviceManager<'a> {
impl DeviceManager {
/// Obtain an DeviceManager handle, ensuring that the runtime is properly initialized. This may be called as many
/// times as needed, and results in a no-op if the DeviceManager is already initialized.
pub fn obtain<'b>(_frida: &'b Frida) -> Self
where
'b: 'a,
{
pub fn obtain(frida: &Frida) -> Self {
DeviceManager {
manager_ptr: unsafe { frida_sys::frida_device_manager_new() },
phantom: PhantomData,
frida: frida.clone(),
}
}

/// Returns all devices.
pub fn enumerate_all_devices<'b>(&'a self) -> Vec<Device<'b>>
where
'a: 'b,
{
pub fn enumerate_all_devices(&self) -> Vec<Device> {
let mut devices = Vec::new();
let mut error: *mut frida_sys::GError = std::ptr::null_mut();

Expand All @@ -54,8 +48,9 @@ impl<'a> DeviceManager<'a> {
devices.reserve(num_devices as usize);

for i in 0..num_devices {
let device =
Device::from_raw(unsafe { frida_sys::frida_device_list_get(devices_ptr, i) });
let device = Device::from_raw(self.frida.clone(), unsafe {
frida_sys::frida_device_list_get(devices_ptr, i)
});
devices.push(device);
}
}
Expand All @@ -65,7 +60,7 @@ impl<'a> DeviceManager<'a> {
}

/// Returns the device of the specified type.
pub fn get_device_by_type(&'a self, r#type: DeviceType) -> Result<Device<'a>> {
pub fn get_device_by_type(&self, r#type: DeviceType) -> Result<Device> {
let mut error: *mut frida_sys::GError = std::ptr::null_mut();

let device_ptr = unsafe {
Expand All @@ -82,11 +77,11 @@ impl<'a> DeviceManager<'a> {
return Err(Error::DeviceLookupFailed);
}

return Ok(Device::from_raw(device_ptr));
return Ok(Device::from_raw(self.frida.clone(), device_ptr));
}

/// Returns the remote device with the specified host.
pub fn get_remote_device(&'a self, host: &str) -> Result<Device<'a>> {
pub fn get_remote_device(self, host: &str) -> Result<Device> {
let mut error: *mut frida_sys::GError = std::ptr::null_mut();
let host_cstring = CString::new(host).map_err(|_| Error::CStringFailed)?;

Expand All @@ -104,11 +99,11 @@ impl<'a> DeviceManager<'a> {
return Err(Error::DeviceLookupFailed);
}

return Ok(Device::from_raw(device_ptr));
return Ok(Device::from_raw(self.frida.clone(), device_ptr));
}

/// Returns the local device.
pub fn get_local_device(&'a self) -> Result<Device<'a>> {
pub fn get_local_device(&self) -> Result<Device> {
self.get_device_by_type(device::DeviceType::Local)
}

Expand All @@ -123,7 +118,7 @@ impl<'a> DeviceManager<'a> {
/// let device = device_manager.get_device_by_id(id).unwrap();
/// assert_eq!(device.get_id(), id);
///
pub fn get_device_by_id(&'a self, device_id: &str) -> Result<Device<'a>> {
pub fn get_device_by_id(&self, device_id: &str) -> Result<Device> {
let mut error: *mut frida_sys::GError = std::ptr::null_mut();
let cstring = CString::new(device_id).unwrap();

Expand All @@ -141,11 +136,11 @@ impl<'a> DeviceManager<'a> {
return Err(Error::DeviceLookupFailed);
}

return Ok(Device::from_raw(device_ptr));
return Ok(Device::from_raw(self.frida.clone(), device_ptr));
}
}

impl<'a> Drop for DeviceManager<'a> {
impl Drop for DeviceManager {
fn drop(&mut self) {
unsafe { frida_sys::frida_unref(self.manager_ptr as _) }
}
Expand Down
40 changes: 18 additions & 22 deletions frida/src/injector.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{Device, Error, Result};
use crate::{Device, Error, Frida, Result};
use std::ffi::CString;
use std::marker::PhantomData;
use std::path::Path;

#[cfg(unix)]
Expand All @@ -11,25 +10,27 @@
/// Local library injector
///
/// Implements [Inject] to allow library injection into a target process.
pub struct Injector<'a> {
pub struct Injector {
_frida: Frida,
injector_ptr: *mut _FridaInjector,
phantom: PhantomData<&'a _FridaInjector>,
}

impl<'a> Injector<'a> {
pub(crate) fn from_raw(injector_ptr: *mut _FridaInjector) -> Injector<'a> {
unsafe impl Send for Injector {}

impl Injector {
pub(crate) fn from_raw(frida: Frida, injector_ptr: *mut _FridaInjector) -> Injector {
Injector {
_frida: frida,
injector_ptr,
phantom: PhantomData,
}
}

/// Create a new Injector using a `frida-helper` process.
///
/// The `frida-helper` is a binary compiled into the Frida devkit, and is codesigned
/// to allow debugging. It is spawned and injection is delegated to the helper.
pub fn new() -> Self {
Self::from_raw(unsafe { frida_sys::frida_injector_new() })
pub fn new(frida: Frida) -> Self {
Self::from_raw(frida, unsafe { frida_sys::frida_injector_new() })
}

/// Create a new inprocess Injector
Expand All @@ -39,19 +40,14 @@
/// See [Injector::new] for details about the `frida-helper` process. Using an
/// in_process injector may require the debugger process to be codesigned on some
/// platforms.
pub fn in_process() -> Self {
Self::from_raw(unsafe { frida_sys::frida_injector_new_inprocess() })
}
}

impl<'a> Default for Injector<'a> {
fn default() -> Self {
Self::new()
pub fn in_process(frida: Frida) -> Self {
Self::from_raw(frida, unsafe { frida_sys::frida_injector_new_inprocess() })
}
}

impl Drop for Injector<'_> {
impl Drop for Injector {
fn drop(&mut self) {
eprintln!("dropping injector");
unsafe {
frida_sys::frida_injector_close_sync(
self.injector_ptr,
Expand Down Expand Up @@ -94,7 +90,7 @@
/// ```no_run
///# use crate::frida::{Injector, Inject};
/// let mut injector = Injector::new();
/// injector.inject_library_file_sync(1337, "/path/to/payload.so", "entrypoint", "hello world")

Check failure on line 93 in frida/src/injector.rs

View workflow job for this annotation

GitHub Actions / Check (x86_64)

this function takes 1 argument but 0 arguments were supplied
/// .expect("Could not inject library");
/// ```
pub trait Inject {
Expand Down Expand Up @@ -130,7 +126,7 @@
E: AsRef<str>;
}

impl<'a> Inject for Injector<'a> {
impl<'a> Inject for Injector {
fn inject_library_file_sync<D, E, P>(
&mut self,
pid: u32,
Expand Down Expand Up @@ -228,7 +224,7 @@
}
}

impl<'a> Inject for Device<'a> {
impl Inject for Device {
fn inject_library_file_sync<D, E, P>(
&mut self,
pid: u32,
Expand Down Expand Up @@ -261,7 +257,7 @@

let id = unsafe {
frida_sys::frida_device_inject_library_file_sync(
self.device_ptr,
self.ptr(),
pid as frida_sys::guint,
path.as_ptr() as *const frida_sys::gchar,
entrypoint.as_ptr() as *const frida_sys::gchar,
Expand Down Expand Up @@ -301,7 +297,7 @@
let id = unsafe {
let g_blob = g_bytes_new(blob.as_ptr() as _, blob.len() as _);
let id = frida_sys::frida_device_inject_library_blob_sync(
self.device_ptr,
self.ptr(),
pid,
g_blob,
entrypoint.as_ptr() as *const frida_sys::gchar,
Expand Down
Loading
Loading