Skip to content
Merged
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
24 changes: 24 additions & 0 deletions types/frida-gum/frida-gum-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,38 @@ Interceptor.attach(puts, {
},
});

Interceptor.attach({
target: puts,
scratchRegister: "x15",
scenario: "online",
relocation: "checked",
}, {
onEnter(args) {
// $ExpectType InvocationArguments
args;
},
});

Interceptor.flush();

// $ExpectType void
Interceptor.replace(ptr("0x1234"), new NativeCallback(() => {}, "void", []));

// $ExpectType void
Interceptor.replace(
{ target: ptr("0x1234"), scratchRegister: "x15", relocation: "unchecked" },
new NativeCallback(() => {}, "void", []),
);

// $ExpectType NativePointer
Interceptor.replaceFast(ptr("0x1234"), new NativeCallback(() => {}, "void", []));

// $ExpectType NativePointer
Interceptor.replaceFast(
{ target: ptr("0x1234"), scenario: "offline", relocation: "forced" },
new NativeCallback(() => {}, "void", []),
);

const ccode = `
#include <gum/gumstalker.h>

Expand Down
91 changes: 85 additions & 6 deletions types/frida-gum/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3215,13 +3215,18 @@ declare namespace Interceptor {
* to specify a `InstructionProbeCallback` if `target` is not the first
* instruction of a function.
*
* @param target Address of function/instruction to intercept.
* The `target` may be specified either as a bare address, or as an object
* carrying the address alongside instrumentation options such as which
* scratch register to use.
*
* @param target Address of function/instruction to intercept, optionally
* wrapped together with instrumentation options.
* @param callbacksOrProbe Callbacks or instruction-level probe callback.
* @param data User data exposed to `NativeInvocationListenerCallbacks`
* through the `GumInvocationContext *`.
*/
function attach(
target: NativePointerValue,
target: NativePointerValue | InstrumentationTarget,
callbacksOrProbe: InvocationListenerCallbacks | InstructionProbeCallback,
data?: NativePointerValue,
): InvocationListener;
Expand All @@ -3240,13 +3245,22 @@ declare namespace Interceptor {
* your implementation. Interceptor uses thread-local state to determine
* that it should call the original in that case.
*
* @param target Address of function to replace.
* The `target` may be specified either as a bare address, or as an object
* carrying the address alongside instrumentation options such as which
* scratch register to use.
*
* @param target Address of function to replace, optionally wrapped together
* with instrumentation options.
* @param replacement Replacement implementation.
* @param data User data exposed to native replacement through the
* `GumInvocationContext *`, obtained using
* `gum_interceptor_get_current_invocation()`.
*/
function replace(target: NativePointerValue, replacement: NativePointerValue, data?: NativePointerValue): void;
function replace(
target: NativePointerValue | InstrumentationTarget,
replacement: NativePointerValue,
data?: NativePointerValue,
): void;

/**
* Replaces function at `target` with implementation at `replacement`.
Expand All @@ -3258,11 +3272,19 @@ declare namespace Interceptor {
* means that you need to use the returned pointer if you want to call the
* original implementation.
*
* @param target Address of function to replace.
* The `target` may be specified either as a bare address, or as an object
* carrying the address alongside instrumentation options such as which
* scratch register to use.
*
* @param target Address of function to replace, optionally wrapped together
* with instrumentation options.
* @param replacement Replacement implementation.
* @returns Address of trampoline that lets you call the original function.
*/
function replaceFast(target: NativePointerValue, replacement: NativePointerValue): NativePointer;
function replaceFast(
target: NativePointerValue | InstrumentationTarget,
replacement: NativePointerValue,
): NativePointer;

/**
* Reverts the previously replaced function at `target`.
Expand All @@ -3282,6 +3304,63 @@ declare namespace Interceptor {
let breakpointKind: "soft" | "hard";
}

/**
* Target to instrument, carrying the address alongside optional knobs that
* control how the inline hook is set up.
*/
interface InstrumentationTarget {
/**
* Address of function/instruction to instrument.
*/
target: NativePointerValue;

/**
* Register that Interceptor may clobber when building the trampoline.
*
* Only supported on architectures that expose scratch registers, i.e.
* arm64 and mips.
*/
scratchRegister?: Arm64Register | MipsRegister | undefined;

/**
* Whether another thread might be executing the target while it is being
* instrumented.
*
* Use `online` when calls may be in flight, i.e. a thread could have
* executed an instruction with call semantics (CALL/BL/etc.) but not yet
* returned. Use `offline` when that cannot happen — e.g. after `spawn()`
* but before `resume()`, or when no calls will occur until some external
* input you control. The `offline` scenario allows writing past the end of
* such an instruction, which would be unsafe online.
*
* Defaults to `online`.
*/
scenario?: InstrumentationScenario | undefined;

/**
* How to deal with relocation of the instructions overwritten by the hook.
*
* Defaults to `checked`.
*/
relocation?: RelocationPolicy | undefined;
}

type InstrumentationScenario = "online" | "offline";

/**
* How aggressively Interceptor may rewrite the function being instrumented.
*
* - `checked`: verify that the chosen scratch register (default or
* user-specified) is not used in the function's early prologue, that there
* are no branches back into the overwritten instruction(s), and similar
* constraints.
* - `unchecked`: skip those checks.
* - `forced`: like `unchecked`, but also allow overwriting past the end of the
* function — for cases where you know it is safe, e.g. because of alignment
* padding between this function and the next.
*/
type RelocationPolicy = "checked" | "unchecked" | "forced";

declare class InvocationListener {
/**
* Detaches listener previously attached through `Interceptor#attach()`.
Expand Down
2 changes: 1 addition & 1 deletion types/frida-gum/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@types/frida-gum",
"version": "19.1.9999",
"version": "19.2.9999",
"nonNpm": true,
"nonNpmDescription": "frida-gum",
"projects": [
Expand Down