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
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
@@ -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()
}

@@ -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
@@ -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,
)
@@ -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,
@@ -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);
}
}
@@ -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(),
@@ -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,
)
@@ -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() {
@@ -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() {
@@ -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)]
41 changes: 18 additions & 23 deletions frida/src/device_manager.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@

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

use crate::device::{self, Device};
use crate::DeviceType;
@@ -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();

@@ -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);
}
}
@@ -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 {
@@ -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)?;

@@ -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)
}

@@ -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();

@@ -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 _) }
}
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)]
@@ -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
@@ -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,
@@ -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

GitHub Actions / Check (x86_64)

this function takes 1 argument but 0 arguments were supplied
/// .expect("Could not inject library");
/// ```
pub trait Inject {
@@ -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,
@@ -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,
@@ -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,
@@ -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,
Loading