Skip to content

Commit

Permalink
Add support for stalker observer
Browse files Browse the repository at this point in the history
  • Loading branch information
WorksButNotTested authored Jan 9, 2023
1 parent c93bd23 commit 6d287d1
Show file tree
Hide file tree
Showing 20 changed files with 335 additions and 14 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ members = [
"frida",
"examples/gum/open",
"examples/gum/stalker",
"examples/gum/stalker_observer",
"examples/gum/hook_open",
"examples/gum/hook_instruction",
"examples/gum/debug_symbol",
Expand Down
4 changes: 2 additions & 2 deletions examples/gum/debug_symbol/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {
symbol_details.file_name(),
symbol_details.line_number()
);
println!("{:?}", symbol_details);
println!("{symbol_details:?}");

let symbol_details = DebugSymbol::from_name("open").unwrap();
println!(
Expand All @@ -30,5 +30,5 @@ fn main() {
symbol_details.file_name(),
symbol_details.line_number()
);
println!("{:?}", symbol_details);
println!("{symbol_details:?}");
}
1 change: 1 addition & 0 deletions examples/gum/stalker_observer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/
12 changes: 12 additions & 0 deletions examples/gum/stalker_observer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "stalker-observer"
version = "0.1.0"
authors = ["meme <meme@users.noreply.github.com>"]
edition = "2018"
license = "wxWindows"
publish = false

[dependencies]
frida-gum = { path = "../../../frida-gum", features = ["event-sink", "invocation-listener", "stalker-observer"] }
frida-gum-sys = { path = "../../../frida-gum-sys" }
lazy_static = "1.4"
73 changes: 73 additions & 0 deletions examples/gum/stalker_observer/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* This example is in the public domain */

use frida_gum as gum;
use frida_gum::stalker::{Event, EventMask, EventSink, Stalker, StalkerObserver, Transformer};
use frida_gum_sys as gum_sys;
use lazy_static::lazy_static;

lazy_static! {
static ref GUM: gum::Gum = unsafe { gum::Gum::obtain() };
}

struct SampleEventSink;

impl EventSink for SampleEventSink {
fn query_mask(&mut self) -> EventMask {
EventMask::Exec
}

fn start(&mut self) {
println!("start");
}

fn process(&mut self, _event: &Event) {
println!("process");
}

fn flush(&mut self) {
println!("flush");
}

fn stop(&mut self) {
println!("stop");
}
}

struct SampleStalkerObserver;

impl StalkerObserver for SampleStalkerObserver {
fn switch_callback(
&mut self,
from_address: gum_sys::gpointer,
start_address: gum_sys::gpointer,
from_insn: gum_sys::gpointer,
target: &mut gum_sys::gpointer,
) {
println!(
"from_address: {:p}, start_address: {:p}, from_insn: {:p}, target: {:p}",
from_address, start_address, from_insn, *target
);
}

fn notify_backpatch(
&mut self,
_backpatch: *const gum_sys::GumBackpatch,
_size: gum_sys::gsize,
) {
}
}

fn main() {
let mut stalker = Stalker::new(&GUM);
let transformer = Transformer::from_callback(&GUM, |basic_block, _output| {
for instr in basic_block {
instr.put_callout(|_cpu_context| {});
instr.keep();
}
});

let mut event_sink = SampleEventSink;
stalker.follow_me(&transformer, Some(&mut event_sink));
stalker.set_observer(&mut SampleStalkerObserver);
stalker.unfollow_me();
}
12 changes: 4 additions & 8 deletions frida-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn download_and_use_devkit_internal(

let os = env::var("CARGO_CFG_TARGET_OS").unwrap();

let devkit_name = format!("frida-{}-devkit-{}-{}-{}", kind, version, os, target_arch,);
let devkit_name = format!("frida-{kind}-devkit-{version}-{os}-{target_arch}",);

let devkit_path = out_dir_path.join(&devkit_name);
let devkit_tar = out_dir_path.join(format!("{}.tar.xz", &devkit_name));
Expand All @@ -45,8 +45,7 @@ fn download_and_use_devkit_internal(
if !devkit_path.is_dir() {
if !devkit_tar.is_file() {
let frida_url = format!(
"https://github.com/frida/frida/releases/download/{}/{}.tar.xz",
version, devkit_name,
"https://github.com/frida/frida/releases/download/{version}/{devkit_name}.tar.xz",
);

println!(
Expand All @@ -66,7 +65,7 @@ fn download_and_use_devkit_internal(
}

println!("cargo:rustc-link-search={}", out_dir.to_string_lossy());
println!("cargo:rustc-link-lib=static=frida-{}", kind);
println!("cargo:rustc-link-lib=static=frida-{kind}");

Ok(out_dir.to_string_lossy().to_string())
}
Expand All @@ -75,10 +74,7 @@ fn download_and_use_devkit_internal(
pub fn download_and_use_devkit(kind: &str, version: &str) -> String {
download_and_use_devkit_internal(kind, version, false)
.or_else(|e| {
println!(
"cargo:warning=Failed to unpack devkit: {}, retrying download...",
e
);
println!("cargo:warning=Failed to unpack devkit: {e}, retrying download...");
download_and_use_devkit_internal(kind, version, true)
})
.expect("cannot extract the devkit tar.gz")
Expand Down
1 change: 1 addition & 0 deletions frida-gum-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ description = "Rust generated bindings for Frida Gum"
auto-download = ["frida-build"]
event-sink = ["cc"]
invocation-listener = ["cc"]
stalker-observer = ["cc"]

[build-dependencies]
bindgen = "0.61.0"
Expand Down
32 changes: 30 additions & 2 deletions frida-gum-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ fn main() {
println!("cargo:rerun-if-changed=probe_listener.h");
}

#[cfg(feature = "stalker-observer")]
{
println!("cargo:rerun-if-changed=stalker_observer.c");
println!("cargo:rerun-if-changed=stalker_observer.h");
}

println!(
"cargo:rustc-link-search={}",
env::var("CARGO_MANIFEST_DIR").unwrap()
Expand All @@ -46,7 +52,7 @@ fn main() {
let bindings = bindgen::Builder::default();

#[cfg(feature = "auto-download")]
let bindings = bindings.clang_arg(format!("-I{}", include_dir));
let bindings = bindings.clang_arg(format!("-I{include_dir}"));

#[cfg(not(feature = "auto-download"))]
let bindings = if std::env::var("DOCS_RS").is_ok() {
Expand All @@ -60,6 +66,7 @@ fn main() {
.header("event_sink.h")
.header("invocation_listener.h")
.header("probe_listener.h")
.header("stalker_observer.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate_comments(false)
.layout_tests(false)
Expand Down Expand Up @@ -116,7 +123,7 @@ fn main() {

#[cfg(feature = "auto-download")]
#[allow(unused_mut)]
let mut builder = builder.include(include_dir);
let mut builder = builder.include(include_dir.clone());

#[cfg(not(feature = "auto-download"))]
let builder = if std::env::var("DOCS_RS").is_ok() {
Expand All @@ -130,6 +137,27 @@ fn main() {
.compile("probe_listener");
}

#[cfg(feature = "stalker-observer")]
{
let mut builder = cc::Build::new();

#[cfg(feature = "auto-download")]
#[allow(unused_mut)]
let mut builder = builder.include(include_dir);

#[cfg(not(feature = "auto-download"))]
let builder = if std::env::var("DOCS_RS").is_ok() {
builder.include("include")
} else {
&mut builder
};

builder
.file("stalker_observer.c")
.opt_level(3)
.compile("stalker_observer");
}

#[cfg(target_os = "windows")]
[
"dnsapi", "iphlpapi", "psapi", "winmm", "ws2_32", "advapi32", "crypt32", "gdi32",
Expand Down
78 changes: 78 additions & 0 deletions frida-gum-sys/stalker_observer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright © 2020-2021 Keegan Saunders
*
* Licence: wxWindows Library Licence, Version 3.1
*/

#include "stalker_observer.h"

static void gum_rust_stalker_observer_iface_init(gpointer g_iface, gpointer iface_data);

G_DEFINE_TYPE_EXTENDED(GumRustStalkerObserver,
gum_rust_stalker_observer,
G_TYPE_OBJECT,
0,
G_IMPLEMENT_INTERFACE(GUM_TYPE_STALKER_OBSERVER,
gum_rust_stalker_observer_iface_init))

static void
gum_rust_stalker_observer_finalize(GObject *obj)
{
G_OBJECT_CLASS(gum_rust_stalker_observer_parent_class)->finalize(obj);
}

static void
gum_rust_stalker_observer_class_init (GumRustStalkerObserverClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = gum_rust_stalker_observer_finalize;
}

static void
gum_rust_stalker_observer_notify_backpatch(GumStalkerObserver *sink,
const GumBackpatch * backpatch, gsize size)
{
GumRustStalkerObserver *self = GUM_RUST_STALKER_OBSERVER(sink);
return self->rust.notify_backpatch(self->rust.user_data, backpatch, size);
}

static void
gum_rust_stalker_observer_switch_callback(GumStalkerObserver *sink,
gpointer from_address, gpointer start_address, gpointer from_insn,
gpointer * target)
{
GumRustStalkerObserver *self = GUM_RUST_STALKER_OBSERVER(sink);
return self->rust.switch_callback(self->rust.user_data, from_address,
start_address, from_insn, target);
}

static void
gum_rust_stalker_observer_iface_init(gpointer g_iface, gpointer iface_data)
{
(void) iface_data;

GumStalkerObserverInterface *iface = g_iface;
iface->notify_backpatch = gum_rust_stalker_observer_notify_backpatch;
iface->switch_callback = gum_rust_stalker_observer_switch_callback;
}

static void
gum_rust_stalker_observer_init(GumRustStalkerObserver *self)
{
(void) self;
}

GumStalkerObserver*
gum_rust_stalker_observer_new (RustStalkerObserverVTable rust)
{
GumRustStalkerObserver *sink;
sink = g_object_new(GUM_TYPE_RUST_STALKER_OBSERVER, NULL);
memcpy(&sink->rust, &rust, sizeof(sink->rust));
return GUM_STALKER_OBSERVER(sink);
}

void
gum_rust_stalker_observer_reset(GumRustStalkerObserver *self)
{
(void) self;
}
34 changes: 34 additions & 0 deletions frida-gum-sys/stalker_observer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright © 2020-2021 Keegan Saunders
*
* Licence: wxWindows Library Licence, Version 3.1
*/

#pragma once

#include "frida-gum.h"

G_BEGIN_DECLS

#define GUM_TYPE_RUST_STALKER_OBSERVER (gum_rust_stalker_observer_get_type())
G_DECLARE_FINAL_TYPE(GumRustStalkerObserver, gum_rust_stalker_observer, GUM,
RUST_STALKER_OBSERVER, GObject)

typedef struct {
void *user_data;

void (*notify_backpatch)(void *user_data, const GumBackpatch * backpatch,
gsize size);
void (*switch_callback)(void *user_data, gpointer from_address,
gpointer start_address, gpointer from_insn, gpointer * target);
} RustStalkerObserverVTable;

struct _GumRustStalkerObserver {
GObject parent;
RustStalkerObserverVTable rust;
};

GumStalkerObserver *gum_rust_stalker_observer_new(RustStalkerObserverVTable rust);
void gum_rust_stalker_observer_reset(GumRustStalkerObserver *self);

G_END_DECLS
3 changes: 2 additions & 1 deletion frida-gum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ auto-download = ["frida-gum-sys/auto-download"]
backtrace = ["libc"]
event-sink = ["frida-gum-sys/event-sink"]
invocation-listener = ["frida-gum-sys/invocation-listener"]
stalker-observer = ["frida-gum-sys/stalker-observer"]

[dependencies]
frida-gum-sys = { path = "../frida-gum-sys", version = "0.6.0" }
Expand All @@ -31,5 +32,5 @@ lazy_static = "1"
maintenance = { status = "experimental" }

[package.metadata.docs.rs]
features = ["event-sink", "invocation-listener"]
features = ["event-sink", "invocation-listener", "stalker-observer"]
rustdoc-args = ["--cfg", "doc_cfg"]
5 changes: 5 additions & 0 deletions frida-gum/src/instruction_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
* Licence: wxWindows Library Licence, Version 3.1
*/

#![cfg_attr(
any(target_arch = "x86_64", target_arch = "x86"),
allow(clippy::unnecessary_cast)
)]

//! Instruction writer interface.
use frida_gum_sys as gum_sys;
use gum_sys::GumArgument;
Expand Down
5 changes: 5 additions & 0 deletions frida-gum/src/interceptor/invocation_listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
* Licence: wxWindows Library Licence, Version 3.1
*/

#![cfg_attr(
any(target_arch = "x86_64", target_arch = "x86"),
allow(clippy::unnecessary_cast)
)]

use crate::{CpuContext, NativePointer};
use frida_gum_sys as gum_sys;
use std::marker::PhantomData;
Expand Down
5 changes: 5 additions & 0 deletions frida-gum/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
//! Module helpers.
//!

#![cfg_attr(
any(target_arch = "x86_64", target_arch = "x86"),
allow(clippy::unnecessary_cast)
)]

use frida_gum_sys as gum_sys;
use std::convert::TryInto;
use std::ffi::CString;
Expand Down
Loading

0 comments on commit 6d287d1

Please sign in to comment.