Skip to content

Commit

Permalink
Implement support for obtaining binary data added to messages (#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
casept authored Dec 17, 2024
1 parent c229b4f commit 6a8cd29
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 15 deletions.
2 changes: 1 addition & 1 deletion examples/core/console_log/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn main() {
struct Handler;

impl ScriptHandler for Handler {
fn on_message(&mut self, message: &frida::Message) {
fn on_message(&mut self, message: &frida::Message, _data: Option<Vec<u8>>) {
println!("{:?}", message);
}
}
2 changes: 1 addition & 1 deletion examples/core/list_exports/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn main() {
struct Handler;

impl frida::ScriptHandler for Handler {
fn on_message(&mut self, message: &Message) {
fn on_message(&mut self, message: &Message, _data: Option<Vec<u8>>) {
println!("- {:?}", message);
}
}
2 changes: 1 addition & 1 deletion examples/core/rpc_execute_function/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn main() {
struct Handler;

impl frida::ScriptHandler for Handler {
fn on_message(&mut self, message: &Message) {
fn on_message(&mut self, message: &Message, _data: Option<Vec<u8>>) {
println!("- {:?}", message);
}
}
4 changes: 2 additions & 2 deletions frida-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub use bindings::*;

#[cfg(not(any(target_vendor = "apple", target_os = "windows")))]
pub use crate::{
_frida_g_bytes_new as g_bytes_new, _frida_g_bytes_unref as g_bytes_unref,
_frida_g_clear_object as g_clear_object,
_frida_g_bytes_get_data as g_bytes_get_data, _frida_g_bytes_new as g_bytes_new,
_frida_g_bytes_unref as g_bytes_unref, _frida_g_clear_object as g_clear_object,
_frida_g_hash_table_iter_init as g_hash_table_iter_init,
_frida_g_hash_table_iter_next as g_hash_table_iter_next,
_frida_g_hash_table_size as g_hash_table_size, _frida_g_idle_source_new as g_idle_source_new,
Expand Down
47 changes: 37 additions & 10 deletions frida/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
* Licence: wxWindows Library Licence, Version 3.1
*/

use frida_sys::{FridaScriptOptions, _FridaScript, g_bytes_new, g_bytes_unref};
use frida_sys::{
FridaScriptOptions, _FridaScript, _GBytes, g_bytes_get_data, g_bytes_new, g_bytes_unref, gsize,
};
use serde::Deserialize;
use serde_json::Value;
use std::sync::mpsc::{channel, Receiver, Sender};
Expand Down Expand Up @@ -95,7 +97,7 @@ pub struct SendPayload {
unsafe extern "C" fn call_on_message<I: ScriptHandler>(
_script_ptr: *mut _FridaScript,
message: *const i8,
_data: &frida_sys::_GBytes,
data: *const frida_sys::_GBytes,
user_data: *mut c_void,
) {
let c_msg = CStr::from_ptr(message as *const c_char)
Expand All @@ -118,20 +120,42 @@ unsafe extern "C" fn call_on_message<I: ScriptHandler>(
}
_ => {
let handler: &mut I = &mut *(user_data as *mut I);
handler.on_message(&formatted_msg);

// Retrieve extra message data, if any.
if data.is_null() {
handler.on_message(&formatted_msg, None);
return;
}

let mut raw_data_size: gsize = 0;
let raw_data: *const u8 = g_bytes_get_data(
// Cast to mut should be safe, as this function doesn't modify the data.
data as *mut _GBytes,
std::ptr::from_mut(&mut raw_data_size),
) as *const u8;
let data_vec = if raw_data_size == 0 || raw_data.is_null() {
None
} else {
// Copy to a vector to avoid potential lifetime issues.
Some(
std::slice::from_raw_parts(raw_data, raw_data_size.try_into().unwrap())
.to_vec(),
)
};
handler.on_message(&formatted_msg, data_vec);
}
}
}

fn on_message(cb_handler: &mut CallbackHandler, message: Message) {
let (tx, _) = &cb_handler.channel;
let _ = tx.send(message);
let _ = tx.send((message, None));
}

/// Represents a script signal handler.
pub trait ScriptHandler {
/// Handler called when a message is shared from JavaScript to Rust.
fn on_message(&mut self, message: &Message);
fn on_message(&mut self, message: &Message, data: Option<Vec<u8>>);
}

/// Represents a Frida script.
Expand Down Expand Up @@ -212,8 +236,9 @@ impl<'a> Script<'a> {
/// struct Handler;
///
/// impl ScriptHandler for Handler {
/// fn on_message(&mut self, message: &frida::Message) {
/// println!("{:?}", message);
/// fn on_message(&mut self, message: &frida::Message, data: Option<Vec<u8>>) {
/// println!("Message: {:?}", message);
/// println!("Data: {:?}", data);
/// }
/// }
/// ```
Expand Down Expand Up @@ -284,7 +309,7 @@ impl<'a> Script<'a> {
self.post(&json_req, None).unwrap();
let borrowed_callback_handler = self.callback_handler.borrow();
let (_, rx) = &borrowed_callback_handler.channel;
let rpc_result = rx.recv().unwrap();
let (rpc_result, _) = rx.recv().unwrap();

let func_list: Vec<String> = match rpc_result {
Message::Send(r) => {
Expand Down Expand Up @@ -335,7 +360,7 @@ impl Exports<'_> {

let borrowed_callback_handler = self.callback_handler.borrow();
let (_, rx) = &borrowed_callback_handler.channel;
let rpc_result = rx.recv().unwrap();
let (rpc_result, _) = rx.recv().unwrap();

match rpc_result {
Message::Send(r) => {
Expand Down Expand Up @@ -433,8 +458,10 @@ impl Drop for ScriptOption {
}
}

type MsgSender = Sender<(Message, Option<Vec<u8>>)>;
type MsgReceiver = Receiver<(Message, Option<Vec<u8>>)>;
struct CallbackHandler {
channel: (Sender<Message>, Receiver<Message>),
channel: (MsgSender, MsgReceiver),
script_handler: Option<Box<dyn ScriptHandler>>,
}

Expand Down

0 comments on commit 6a8cd29

Please sign in to comment.