@types/frida-gum
Version:
TypeScript definitions for frida-gum
1,805 lines (1,525 loc) • 204 kB
TypeScript
/**
* Returns a hexdump of the provided ArrayBuffer or NativePointerValue target.
*
* @param target The ArrayBuffer or NativePointerValue to dump.
* @param options Options customizing the output.
*/
declare function hexdump(target: ArrayBuffer | NativePointerValue, options?: HexdumpOptions): string;
interface HexdumpOptions {
/**
* Specifies base address of data being dumped. Defaults to the address of
* the `target` argument, if it has an address, and 0 otherwise.
*/
address?: NativePointer;
/**
* Specifies byte offset of where to start dumping. Defaults to 0.
*/
offset?: number | undefined;
/**
* Limits how many bytes to dump.
*/
length?: number | undefined;
/**
* Whether a header should be included. Defaults to true.
*/
header?: boolean | undefined;
/**
* Whether ANSI colors should be used. Defaults to false.
*/
ansi?: boolean | undefined;
}
/**
* Short-hand for `new Int64(value)`.
*/
declare function int64(value: string | number): Int64;
/**
* Short-hand for `new UInt64(value)`.
*/
declare function uint64(value: string | number): UInt64;
/**
* Short-hand for `new NativePointer(value)`.
*/
declare function ptr(value: string | number): NativePointer;
/**
* Short-hand for `ptr("0")`.
*/
declare const NULL: NativePointer;
/**
* Requests callback to be called on the next message received from your Frida-based application.
*
* This will only give you one message, so you need to call `recv()` again to receive the next one.
*/
declare function recv(callback: MessageCallback): MessageRecvOperation;
/**
* Requests callback to be called when the next message of the given `type` has been received from your
* Frida-based application.
*
* This will only give you one message, so you need to call `recv()` again to receive the next one.
*/
declare function recv(type: string, callback: MessageCallback): MessageRecvOperation;
interface MessageCallback {
(message: any, data: ArrayBuffer | null): void;
}
interface MessageRecvOperation {
/**
* Blocks until the message has been received and callback has returned.
*/
wait(): void;
}
/**
* Sends a JSON-serializable message to your Frida-based application,
* with (optionally) some raw binary data included. The latter is useful
* if you e.g. dumped some memory using `NativePointer#readByteArray()`.
*
* @param message Any JSON-serializable value.
* @param data Raw binary data.
*/
declare function send(message: any, data?: ArrayBuffer | number[] | null): void;
/**
* Calls `func` after `delay` milliseconds, or if omitted: as soon as Frida's
* JavaScript thread is idle. Any additional `params` are passed along.
*
* Returns an id that can be passed to `clearTimeout()` to cancel it.
*/
declare function setTimeout(func: ScheduledCallback, delay?: number, ...params: any[]): TimeoutId;
/**
* Cancels a previously scheduled `setTimeout()`.
*/
declare function clearTimeout(id: TimeoutId): void;
/**
* Opaque ID returned by `setTimeout()`. Pass it to `clearTimeout()` to cancel a pending `setTimeout()`.
*/
type TimeoutId = number;
/**
* Calls `func` every `delay` milliseconds, optionally passing it the provided params.
* Returns an id that can be passed to clearInterval() to cancel it.
*/
declare function setInterval(func: ScheduledCallback, delay: number, ...params: any[]): IntervalId;
/**
* Cancels a previously scheduled `setInterval()`.
*/
declare function clearInterval(id: IntervalId): void;
/**
* Opaque ID returned by `setInterval()`. Pass it to `clearInterval()` to cancel a pending `setInterval()`.
*/
type IntervalId = number;
/**
* Schedules `func` to be called on Frida's JavaScript thread, optionally passing it the provided params.
* Returns an id that can be passed to clearImmediate() to cancel it.
*/
declare function setImmediate(func: ScheduledCallback, ...params: any[]): ImmediateId;
/**
* Cancels a previously scheduled `clearImmediate()`.
*/
declare function clearImmediate(id: ImmediateId): void;
/**
* Opaque ID returned by `setImmediate()`. Pass it to `clearImmediate()` to cancel a pending `setImmediate()`.
*/
type ImmediateId = number;
type ScheduledCallback = (...params: any[]) => void;
declare namespace rpc {
/**
* Empty object that you can either replace or insert into to expose an RPC-style API to your application.
* The key specifies the method name and the value is your exported function. This function may either return
* a plain value for returning that to the caller immediately, or a Promise for returning asynchronously.
*/
let exports: RpcExports;
}
interface RpcExports {
[name: string]: AnyFunction;
}
type AnyFunction = (...args: any[]) => any;
declare namespace Frida {
/**
* The current Frida version.
*/
const version: string;
/**
* The current size – in bytes – of Frida’s private heap, which is shared by all scripts and Frida’s own runtime.
* This is useful for keeping an eye on how much memory your instrumentation is using out of the total consumed by
* the hosting process.
*/
const heapSize: number;
}
declare namespace Script {
/**
* Runtime being used.
*/
const runtime: ScriptRuntime;
/**
* Evaluates the given JavaScript `source` in the global scope. Useful for
* agents that want to support loading user-provided scripts inside their
* own script. The two benefits over simply using `eval()` is that the
* script filename can be provided, and source maps are supported — both
* inline and through `Script.registerSourceMap()`.
*
* @param name Name used in future stack traces, e.g. `/plugins/tty.js`.
* @param source JavaScript source code to be evaluated.
* @returns The resulting value of the evaluated code.
*/
function evaluate(name: string, source: string): any;
/**
* Compiles and evaluates the given JavaScript `source` as an ES module.
* Useful for agents that want to support loading user-provided scripts
* inside their own script. This API offers the same benefits over `eval()`
* as `Script.evaluate()`, in addition to encapsulating the user-provided
* code in its own ES module. This means values may be exported, and
* subsequently imported by other modules. The parent script may also export
* values that can be imported from the loaded child script. This requires
* that the parent uses the new ES module bundle format used by newer
* versions of frida-compile.
*
* @param name UNIX-style virtual filesystem name visible to other modules,
* e.g. `/plugins/screenshot.js`.
* @param source JavaScript source code.
* @returns The module's namespace object.
*/
function load(name: string, source: string): Promise<{ [name: string | symbol]: any }>;
/**
* Registers a source map for the specified script `name`. Should ideally
* be called before the given script gets loaded, so stack traces created
* during load can make use of the source map.
*
* @param name Name of the script that the source map is for, e.g.
* `/plugins/screenshot.js`.
* @param json Source map contents as JSON.
*/
function registerSourceMap(name: string, json: string): void;
/**
* Runs `func` on the next tick, i.e. when the current native thread exits
* the JavaScript runtime. Any additional `params` are passed to it.
*/
function nextTick(func: ScheduledCallback, ...params: any[]): void;
/**
* Temporarily prevents the current script from being unloaded.
* This is reference-counted, so there must be one matching `unpin()`
* happening at a later point.
*
* Typically used in the callback of `Script.bindWeak()` when you need to
* schedule cleanup on another thread.
*/
function pin(): void;
/**
* Reverses a previous `pin()` so the current script may be unloaded.
*/
function unpin(): void;
/**
* Starts monitoring the lifetime of `target`. Calls `callback` as soon as
* value has been garbage-collected, or the script is about to get
* unloaded.
*
* Useful when you're building a language-binding where you need to free
* native resources when a JS value is no longer needed.
*
* Be careful so `callback` is not a closure that accidentally captures
* `target` and keeps it alive beyond its intended lifetime.
*
* @param target Heap-allocated JavaScript value to monitor lifetime of.
* @param callback Function to call when `target` gets GCed.
*/
function bindWeak(target: any, callback: WeakRefCallback): WeakRefId;
/**
* Stops monitoring the value passed to `Script.bindWeak()` and calls the
* callback immediately.
*
* @param id ID returned by a previous call to `Script.bindWeak()`.
*/
function unbindWeak(id: WeakRefId): void;
/**
* Installs or uninstalls a handler that is used to resolve attempts to
* access non-existent global variables.
*
* Useful for implementing a REPL where unknown identifiers may be fetched
* lazily from a database.
*
* @param handler The handler to install, or `null` to uninstall a
* previously installed handler.
*/
function setGlobalAccessHandler(handler: GlobalAccessHandler | null): void;
}
type ScriptRuntime = "QJS" | "V8";
type WeakRefCallback = () => void;
/**
* Opaque ID returned by `Script.bindWeak()`. Pass it to `Script.unbindWeak()`
* to stop monitoring the target value.
*/
type WeakRefId = number;
interface GlobalAccessHandler {
/**
* Queries which additional globals exist.
*/
enumerate(): string[];
/**
* Called whenever an attempt to access a non-existent global variable is
* made. Return `undefined` to treat the variable as inexistent.
*
* @param property Name of non-existent global that is being accessed.
*/
get(property: string): any;
}
declare namespace Process {
/**
* PID of the current process.
*/
const id: number;
/**
* Architecture of the current process.
*/
const arch: Architecture;
/**
* Platform of the current process.
*/
const platform: Platform;
/**
* Size of a virtual memory page in bytes. This is used to make your scripts more portable.
*/
const pageSize: number;
/**
* Size of a pointer in bytes. This is used to make your scripts more portable.
*/
const pointerSize: number;
/**
* Whether Frida will avoid modifying existing code in memory and will not try to run unsigned code.
* Currently this property will always be set to Optional unless you are using Gadget and have configured
* it to assume that code-signing is required. This property allows you to determine whether the Interceptor
* API is off limits, and whether it is safe to modify code or run unsigned code.
*/
const codeSigningPolicy: CodeSigningPolicy;
/**
* The module representing the main executable of the process.
*/
const mainModule: Module;
/**
* Gets the filesystem path to the current working directory.
*/
function getCurrentDir(): string;
/**
* Gets the filesystem path to the current user's home directory.
*/
function getHomeDir(): string;
/**
* Gets the filesystem path to the directory to use for temporary files.
*/
function getTmpDir(): string;
/**
* Determines whether a debugger is currently attached.
*/
function isDebuggerAttached(): boolean;
/**
* Gets this thread’s OS-specific id.
*/
function getCurrentThreadId(): ThreadId;
/**
* Enumerates all threads.
*/
function enumerateThreads(): ThreadDetails[];
/**
* Starts observing threads, calling the provided callbacks as threads are
* added, removed, and renamed. Calls `onAdded` with all existing threads
* right away, so the initial state vs. updates can be managed easily
* without worrying about race conditions.
* All callbacks are optional, but at least one of them must be provided.
*/
function attachThreadObserver(callbacks: ThreadObserverCallbacks): ThreadObserver;
/**
* Runs the JavaScript function `callback` on the thread specified by `id`.
* Must be used with extreme caution due to the thread potentially being
* interrupted in non-reentrant code. For example, you could be interrupting
* it while it's in the middle of some delicate code, holding a specific
* non-recursive lock, which you then try to implicitly acquire again when
* you call some function.
*
* @param id ID of the thread to run on.
* @param callback Function to run.
* @returns A Promise that resolves to the value returned by `callback`.
*/
function runOnThread<T>(id: ThreadId, callback: () => T): Promise<T>;
/**
* Looks up a module by address. Returns null if not found.
*/
function findModuleByAddress(address: NativePointerValue): Module | null;
/**
* Looks up a module by address. Throws an exception if not found.
*/
function getModuleByAddress(address: NativePointerValue): Module;
/**
* Looks up a module by name. Returns null if not found.
*/
function findModuleByName(name: string): Module | null;
/**
* Looks up a module by name. Throws an exception if not found.
*/
function getModuleByName(name: string): Module;
/**
* Enumerates modules loaded right now.
*/
function enumerateModules(): Module[];
/**
* Starts observing modules, calling the provided callbacks as modules are
* added and removed. Calls `onAdded` with all existing modules right away,
* so the initial state vs. updates can be managed easily without worrying
* about race conditions.
* Both callbacks are optional, but at least one of them must be provided.
*/
function attachModuleObserver(callbacks: ModuleObserverCallbacks): ModuleObserver;
/**
* Looks up a memory range by address. Returns null if not found.
*/
function findRangeByAddress(address: NativePointerValue): RangeDetails | null;
/**
* Looks up a memory range by address. Throws an exception if not found.
*/
function getRangeByAddress(address: NativePointerValue): RangeDetails;
/**
* Enumerates memory ranges satisfying `specifier`.
*
* @param specifier The kind of ranges to include.
*/
function enumerateRanges(specifier: PageProtection | EnumerateRangesSpecifier): RangeDetails[];
/**
* Just like `enumerateRanges()`, but for individual memory allocations known to the system heap.
*/
function enumerateMallocRanges(): RangeDetails[];
/**
* Installs a process-wide exception handler callback that gets a chance to
* handle native exceptions before the hosting process itself does.
*
* It is up to your callback to decide what to do with the exception.
* It could for example:
* - Log the issue.
* - Notify your application through a `send()` followed by a blocking `recv()` for acknowledgement of the sent data
* being received.
* - Modify registers and memory to recover from the exception.
*
* You should return `true` if you did handle the exception, in which case
* Frida will resume the thread immediately. If you do not return `true`,
* Frida will forward the exception to the hosting process' exception
* handler, if it has one, or let the OS terminate the process.
*/
function setExceptionHandler(callback: ExceptionHandlerCallback): void;
}
declare class Module {
/**
* Canonical module name.
*/
name: string;
/**
* Module version, if available.
*/
version: string | null;
/**
* Base address.
*/
base: NativePointer;
/**
* Size in bytes.
*/
size: number;
/**
* Full filesystem path.
*/
path: string;
/**
* Ensures that the module initializers have been run. This is important
* during early instrumentation, i.e. code run early in the process
* lifetime, to be able to safely interact with APIs.
*
* One such use-case is interacting with Objective-C classes provided by
* a given module.
*/
ensureInitialized(): void;
/**
* Enumerates imports of module.
*/
enumerateImports(): ModuleImportDetails[];
/**
* Enumerates exports of module.
*/
enumerateExports(): ModuleExportDetails[];
/**
* Enumerates symbols of module.
*/
enumerateSymbols(): ModuleSymbolDetails[];
/**
* Enumerates memory ranges of module.
*
* @param protection Minimum protection of ranges to include.
*/
enumerateRanges(protection: PageProtection): RangeDetails[];
/**
* Enumerates sections of module.
*/
enumerateSections(): ModuleSectionDetails[];
/**
* Enumerates dependencies of module.
*/
enumerateDependencies(): ModuleDependencyDetails[];
/**
* Looks up the absolute address of the export named `name`.
*
* Returns null if the export doesn't exist.
*
* @param name Export name to find the address of.
*/
findExportByName(name: string): NativePointer | null;
/**
* Looks up the absolute address of the export named `name`.
*
* Throws an exception if the export doesn't exist.
*
* @param name Export name to find the address of.
*/
getExportByName(name: string): NativePointer;
/**
* Looks up the absolute address of the symbol named `name`.
*
* Returns null if the symbol doesn't exist.
*
* @param name Symbol name to find the address of.
*/
findSymbolByName(name: string): NativePointer | null;
/**
* Looks up the absolute address of the symbol named `name`.
*
* Throws an exception if the symbol doesn't exist.
*
* @param name Symbol name to find the address of.
*/
getSymbolByName(name: string): NativePointer;
/**
* Loads the specified module.
*/
static load(name: string): Module;
/**
* Looks up the absolute address of the global export named `name`.
* This can be a costly search and should be avoided.
*
* Returns null if the export doesn't exist.
*
* @param name Export name to find the address of.
*/
static findGlobalExportByName(name: string): NativePointer | null;
/**
* Looks up the absolute address of the global export named `name`.
* This can be a costly search and should be avoided.
*
* Throws an exception if the export doesn't exist.
*
* @param name Export name to find the address of.
*/
static getGlobalExportByName(name: string): NativePointer;
}
declare class ThreadObserver {
/**
* Detaches observer previously attached through `Process#attachThreadObserver()`.
*/
detach(): void;
}
interface ThreadObserverCallbacks {
/**
* Called synchronously when a Thread has been added.
*/
onAdded?(thread: StableThreadDetails): void;
/**
* Called synchronously when a Thread has been removed.
*/
onRemoved?(thread: StableThreadDetails): void;
/**
* Called synchronously when a Thread has been renamed.
*/
onRenamed?(thread: StableThreadDetails, previousName: string | null): void;
}
type StableThreadDetails = Omit<ThreadDetails, "state" | "context">;
declare class ModuleObserver {
/**
* Detaches observer previously attached through `Process#attachModuleObserver()`.
*/
detach(): void;
}
interface ModuleObserverCallbacks {
/**
* Called synchronously when a Module has been added.
*/
onAdded?(module: Module): void;
/**
* Called synchronously when a Module has been removed.
*/
onRemoved?(module: Module): void;
}
declare class ModuleMap {
/**
* Creates a new module map optimized for determining which module a given memory address belongs to, if any.
* Takes a snapshot of the currently loaded modules when created, which may be refreshed by calling `update()`.
*
* The `filter` argument is optional and allows you to pass a function used for filtering the list of modules.
* This is useful if you e.g. only care about modules owned by the application itself, and allows you to quickly
* check if an address belongs to one of its modules. The filter function is given the module's details and must
* return true for each module that should be kept in the map. It is called for each loaded module every time the
* map is updated.
*
* @param filter Filter function to decide which modules are kept in the map.
*/
constructor(filter?: ModuleMapFilter);
/**
* Determines if `address` belongs to any of the contained modules.
*
* @param address Address that might belong to a module in the map.
*/
has(address: NativePointerValue): boolean;
/**
* Looks up a module by address. Returns null if not found.
*
* @param address Address that might belong to a module in the map.
*/
find(address: NativePointerValue): Module | null;
/**
* Looks up a module by address. Throws an exception if not found.
*
* @param address Address that might belong to a module in the map.
*/
get(address: NativePointerValue): Module;
/**
* Just like `find()`, but only returns the `name` field, which means less overhead when you don’t need the
* other details. Returns null if not found.
*
* @param address Address that might belong to a module in the map.
*/
findName(address: NativePointerValue): string | null;
/**
* Just like `get()`, but only returns the `name` field, which means less overhead when you don’t need the
* other details. Throws an exception if not found.
*
* @param address Address that might belong to a module in the map.
*/
getName(address: NativePointerValue): string;
/**
* Just like `find()`, but only returns the `path` field, which means less overhead when you don’t need the
* other details. Returns null if not found.
*
* @param address Address that might belong to a module in the map.
*/
findPath(address: NativePointerValue): string | null;
/**
* Just like `get()`, but only returns the `path` field, which means less overhead when you don’t need the
* other details. Throws an exception if not found.
*
* @param address Address that might belong to a module in the map.
*/
getPath(address: NativePointerValue): string;
/**
* Updates the map.
*
* You should call this after a module has been loaded or unloaded to avoid operating on stale data.
*/
update(): void;
/**
* Gets the modules currently in the map. The returned array is a deep copy and will not mutate after a
* call to `update()`.
*/
values(): Module[];
}
type ModuleMapFilter = (m: Module) => boolean;
declare namespace Memory {
/**
* Scans memory for occurences of `pattern` in the memory range given by `address` and `size`.
*
* @param address Starting address to scan from.
* @param size Number of bytes to scan.
* @param pattern Match pattern, see `MatchPattern` for details.
* @param callbacks Object with callbacks.
*/
function scan(
address: NativePointerValue,
size: number | UInt64,
pattern: string | MatchPattern,
callbacks: MemoryScanCallbacks,
): Promise<void>;
/**
* Synchronous version of `scan()`.
*
* @param address Starting address to scan from.
* @param size Number of bytes to scan.
* @param pattern Match pattern, see `MatchPattern` for details.
*/
function scanSync(
address: NativePointerValue,
size: number | UInt64,
pattern: string | MatchPattern,
): MemoryScanMatch[];
/**
* Allocates `size` bytes of memory on Frida's private heap, or, if `size` is a multiple of Process#pageSize,
* one or more raw memory pages managed by the OS. The allocated memory will be released when the returned
* NativePointer value gets garbage collected. This means you need to keep a reference to it while the pointer
* is being used by code outside the JavaScript runtime.
*
* @param size Number of bytes to allocate.
* @param options Options to customize the memory allocation.
*/
function alloc(size: number | UInt64, options?: MemoryAllocOptions): NativePointer;
/**
* Allocates, encodes and writes out `str` as a UTF-8 string on Frida's private heap.
* See Memory#alloc() for details about its lifetime.
*
* @param str String to allocate.
*/
function allocUtf8String(str: string): NativePointer;
/**
* Allocates, encodes and writes out `str` as a UTF-16 string on Frida's private heap.
* See Memory#alloc() for details about its lifetime.
*
* @param str String to allocate.
*/
function allocUtf16String(str: string): NativePointer;
/**
* Allocates, encodes and writes out `str` as an ANSI string on Frida's private heap.
* See Memory#alloc() for details about its lifetime.
*
* @param str String to allocate.
*/
function allocAnsiString(str: string): NativePointer;
/**
* Just like memcpy.
*
* @param dst Destination address.
* @param src Sources address.
* @param n Number of bytes to copy.
*/
function copy(dst: NativePointerValue, src: NativePointerValue, n: number | UInt64): void;
/**
* Short-hand for Memory#alloc() followed by Memory#copy(). See Memory#alloc() for details about lifetime.
*
* @param address Address to copy from.
* @param size Number of bytes to copy.
*/
function dup(address: NativePointerValue, size: number | UInt64): NativePointer;
/**
* Changes the page protection of a region of memory.
*
* @param address Starting address.
* @param size Number of bytes. Must be a multiple of Process#pageSize.
* @param protection Desired page protection.
*/
function protect(address: NativePointerValue, size: number | UInt64, protection: PageProtection): boolean;
/**
* Determines the current protection of a page in memory.
*
* @param address Address inside page to determine the protection of.
* @returns The current page protection.
*/
function queryProtection(address: NativePointerValue): PageProtection;
/**
* Safely modifies `size` bytes at `address`. The supplied function `apply` gets called with a writable pointer
* where you must write the desired modifications before returning. Do not make any assumptions about this being
* the same location as address, as some systems require modifications to be written to a temporary location before
* being mapped into memory on top of the original memory page (e.g. on iOS, where directly modifying in-memory
* code may result in the process losing its CS_VALID status).
*
* @param address Starting address to modify.
* @param size Number of bytes to modify.
* @param apply Function that applies the desired changes.
*/
function patchCode(address: NativePointerValue, size: number | UInt64, apply: MemoryPatchApplyCallback): void;
}
interface MemoryRange {
/**
* Base address.
*/
base: NativePointer;
/**
* Size in bytes.
*/
size: number;
}
/**
* Monitors one or more memory ranges for access, and notifies on the first
* access of each contained memory page.
*
* Only available on Windows for now. We would love to support this on the other
* platforms too, so if you find this useful and would like to help out, please
* get in touch.
*/
declare namespace MemoryAccessMonitor {
/**
* Starts monitoring one or more memory ranges for access, and notifies on
* the first access of each contained memory page.
*
* @param ranges One or more ranges to monitor.
* @param callbacks Callbacks to be notified on access.
*/
function enable(ranges: MemoryAccessRange | MemoryAccessRange[], callbacks: MemoryAccessCallbacks): void;
/**
* Stops monitoring the remaining memory ranges passed to
* `MemoryAccessMonitor.enable()`.
*/
function disable(): void;
}
interface MemoryAccessRange {
/**
* Base address.
*/
base: NativePointer;
/**
* Size in bytes.
*/
size: number;
}
/**
* Callbacks to be notified synchronously on memory access.
*/
interface MemoryAccessCallbacks {
onAccess: (details: MemoryAccessDetails) => void;
}
interface MemoryAccessDetails {
/**
* The ID of the thread performing the access.
*/
threadId: ThreadId;
/**
* The kind of operation that triggered the access.
*/
operation: MemoryOperation;
/**
* Address of instruction performing the access.
*/
from: NativePointer;
/**
* Address being accessed.
*/
address: NativePointer;
/**
* Index of the accessed range in the ranges provided to
* `MemoryAccessMonitor.enable()`.
*/
rangeIndex: number;
/**
* Index of the accessed memory page inside the specified range.
*/
pageIndex: number;
/**
* Overall number of pages which have been accessed so far, and are thus
* no longer being monitored.
*/
pagesCompleted: number;
/**
* Overall number of pages that were initially monitored.
*/
pagesTotal: number;
/**
* CPU registers. You may also update register values by assigning to these keys.
*/
context: CpuContext;
}
declare namespace Thread {
/**
* Generates a backtrace for the given thread's `context`.
*
* If you call this from Interceptor's `onEnter` or `onLeave` callbacks
* you should provide `this.context` for the optional `context` argument,
* as it will give you a more accurate backtrace. Omitting `context` means
* the backtrace will be generated from the current stack location, which
* may not give you a very good backtrace due to the JavaScript VM's
* potentially JITed stack frames.
*
* @param context CPU context to use for generating the backtrace.
* @param backtracer The kind of backtracer to use. Must be either
* `Backtracer.FUZZY` or `Backtracer.ACCURATE`,
* where the latter is the default if not specified.
*/
function backtrace(context?: CpuContext, backtracer?: Backtracer): NativePointer[];
/**
* Suspends execution of the current thread for `delay` seconds.
*
* For example `0.05` to sleep for 50 ms.
*
* @param delay Delay in seconds.
*/
function sleep(delay: number): void;
}
// tslint:disable-next-line:no-unnecessary-class
declare class Backtracer {
/**
* The accurate kind of backtracers rely on debugger-friendly binaries or
* presence of debug information to do a good job, but avoid false
* positives.
*/
static ACCURATE: Backtracer;
/**
* The fuzzy backtracers perform forensics on the stack in order to guess
* the return addresses, which means you will get false positives, but it
* will work on any binary.
*/
static FUZZY: Backtracer;
}
type Architecture =
| "ia32"
| "x64"
| "arm"
| "arm64"
| "mips";
type Platform =
| "windows"
| "darwin"
| "linux"
| "freebsd"
| "qnx"
| "barebone";
type CodeSigningPolicy = "optional" | "required";
/**
* Given as a string of the form: rwx, where rw- means “readable and writable”.
*/
type PageProtection = string;
type ThreadId = number;
type ThreadState =
| "running"
| "stopped"
| "waiting"
| "uninterruptible"
| "halted";
type HardwareBreakpointId = number;
type HardwareWatchpointId = number;
type HardwareWatchpointConditions = "r" | "w" | "rw";
interface ThreadDetails {
/**
* OS-specific ID.
*/
id: ThreadId;
/**
* Name, if available.
*/
name?: string;
/**
* Snapshot of state.
*/
state: ThreadState;
/**
* Snapshot of CPU registers.
*/
context: CpuContext;
/**
* Where the thread started its execution, if applicable and available.
*/
entrypoint?: ThreadEntrypoint;
/**
* Set a hardware breakpoint.
*
* @param id ID of the breakpoint.
* @param address The address of the breakpoint.
*/
setHardwareBreakpoint(id: HardwareBreakpointId, address: NativePointerValue): void;
/**
* Unset a hardware breakpoint.
*
* @param id ID of the breakpoint.
*/
unsetHardwareBreakpoint(id: HardwareBreakpointId): void;
/**
* Set a harware watchpoint.
*
* @param id ID of the watchpoint.
* @param address The address of the region to be watched.
* @param size The size of the region to be watched.
* @param conditions The conditions to be watched for.
*/
setHardwareWatchpoint(
id: HardwareWatchpointId,
address: NativePointerValue,
size: number | UInt64,
conditions: HardwareWatchpointConditions,
): void;
/**
* Unset a hardware watchpoint.
*
* @param id ID of the watchpoint.
*/
unsetHardwareWatchpoint(id: HardwareWatchpointId): void;
}
interface ThreadEntrypoint {
/**
* The thread's start routine.
*/
routine: NativePointer;
/**
* Parameter passed to `routine`, if available.
*/
parameter?: NativePointer;
}
interface KernelModuleDetails {
/**
* Canonical module name.
*/
name: string;
/**
* Base address.
*/
base: UInt64;
/**
* Size in bytes.
*/
size: number;
}
interface ModuleImportDetails {
/**
* The kind of import, if available.
*/
type?: ModuleImportType | undefined;
/**
* Imported symbol name.
*/
name: string;
/**
* Module name, if available.
*/
module?: string | undefined;
/**
* Absolute address, if available.
*/
address?: NativePointer | undefined;
/**
* Memory location where the import is stored, if available.
*/
slot?: NativePointer | undefined;
}
interface ModuleExportDetails {
/**
* The kind of export.
*/
type: ModuleExportType;
/**
* Exported symbol name.
*/
name: string;
/**
* Absolute address.
*/
address: NativePointer;
}
interface ModuleSymbolDetails {
/**
* Whether symbol is globally visible.
*/
isGlobal: boolean;
/**
* The kind of symbol.
*/
type: ModuleSymbolType;
/**
* Which section this symbol resides in, if available.
*/
section?: ModuleSymbolSectionDetails | undefined;
/**
* Symbol name.
*/
name: string;
/**
* Absolute address.
*/
address: NativePointer;
/**
* Size in bytes, if available.
*/
size?: number | undefined;
}
interface ModuleSectionDetails {
/**
* Section index, segment name (if applicable) and section name – same
* format as r2’s section IDs.
*/
id: string;
/**
* Section name.
*/
name: string;
/**
* Absolute address.
*/
address: NativePointer;
/**
* Size in bytes.
*/
size: number;
}
interface ModuleDependencyDetails {
/**
* Module name.
*/
name: string;
/**
* Dependency type.
*/
type: ModuleDependencyType;
}
type ModuleImportType = "function" | "variable";
type ModuleExportType = "function" | "variable";
type ModuleSymbolType =
// Common
| "unknown"
| "section"
// Mach-O
| "undefined"
| "absolute"
| "prebound-undefined"
| "indirect"
// ELF
| "object"
| "function"
| "file"
| "common"
| "tls";
type ModuleDependencyType =
| "regular"
| "weak"
| "reexport"
| "upward";
interface ModuleSymbolSectionDetails {
/**
* Section index, segment name (if applicable) and section name – same
* format as r2’s section IDs.
*/
id: string;
/**
* Section's memory protection.
*/
protection: PageProtection;
}
interface RangeDetails {
/**
* Base address.
*/
base: NativePointer;
/**
* Size in bytes.
*/
size: number;
/**
* Protection.
*/
protection: PageProtection;
/**
* File mapping details, if available.
*/
file?: FileMapping | undefined;
}
interface KernelRangeDetails {
/**
* Base address.
*/
base: UInt64;
/**
* Size in bytes.
*/
size: number;
/**
* Protection.
*/
protection: PageProtection;
}
interface KernelModuleRangeDetails {
/**
* Name.
*/
name: string;
/**
* Base address.
*/
base: UInt64;
/**
* Size in bytes.
*/
size: number;
/**
* Protection.
*/
protection: PageProtection;
}
interface FileMapping {
/**
* Full filesystem path.
*/
path: string;
/**
* Offset in the mapped file on disk, in bytes.
*/
offset: number;
/**
* Size in the mapped file on disk, in bytes.
*/
size: number;
}
interface EnumerateRangesSpecifier {
/**
* Minimum protection required to be included in the result.
*/
protection: PageProtection;
/**
* Whether neighboring ranges with the same protection should be coalesced. The default is false.
*/
coalesce: boolean;
}
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
type ExceptionHandlerCallback = (exception: ExceptionDetails) => boolean | void;
interface ExceptionDetails {
/**
* The kind of exception that occurred.
*/
type: ExceptionType;
/**
* Address where the exception occurred.
*/
address: NativePointer;
/**
* Memory operation details, if relevant.
*/
memory?: ExceptionMemoryDetails | undefined;
/**
* CPU registers. You may also update register values by assigning to these keys.
*/
context: CpuContext;
/**
* Address of the OS and architecture-specific CPU context struct.
*
* This is only exposed as a last resort for edge-cases where `context` isn’t providing enough details.
* We would however discourage using this and rather submit a pull-request to add the missing bits needed
* for your use-case.
*/
nativeContext: NativePointer;
}
type ExceptionType =
| "abort"
| "access-violation"
| "guard-page"
| "illegal-instruction"
| "stack-overflow"
| "arithmetic"
| "breakpoint"
| "single-step"
| "system";
interface ExceptionMemoryDetails {
/**
* The kind of operation that triggered the exception.
*/
operation: MemoryOperation;
/**
* Address that was accessed when the exception occurred.
*/
address: NativePointer;
}
type MemoryOperation = "read" | "write" | "execute";
interface EnumerateCallbacks<T> {
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
onMatch: (item: T) => void | EnumerateAction;
onComplete: () => void;
}
type EnumerateAction = "stop";
interface MemoryScanCallbacks {
/**
* Called with each occurence that was found.
*
* @param address Memory address where a match was found.
* @param size Size of this match.
*/
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
onMatch: (address: NativePointer, size: number) => void | EnumerateAction;
/**
* Called when there was a memory access error while scanning.
*
* @param reason Why the memory access failed.
*/
onError?: ((reason: string) => void) | undefined;
/**
* Called when the memory range has been fully scanned.
*/
onComplete?: () => void;
}
interface MemoryScanMatch {
/**
* Memory address where a match was found.
*/
address: NativePointer;
/**
* Size of this match.
*/
size: number;
}
interface KernelMemoryScanCallbacks {
/**
* Called with each occurence that was found.
*
* @param address Memory address where a match was found.
* @param size Size of this match.
*/
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
onMatch: (address: UInt64, size: number) => void | EnumerateAction;
/**
* Called when there was a memory access error while scanning.
*
* @param reason Why the memory access failed.
*/
onError?: ((reason: string) => void) | undefined;
/**
* Called when the memory range has been fully scanned.
*/
onComplete?: () => void;
}
interface KernelMemoryScanMatch {
/**
* Memory address where a match was found.
*/
address: UInt64;
/**
* Size of this match.
*/
size: number;
}
type MemoryAllocOptions = Record<any, never> | MemoryAllocNearOptions;
interface MemoryAllocNearOptions {
/**
* Memory address to try allocating near.
*/
near: NativePointer;
/**
* Maximum distance to the given memory address, in bytes.
*/
maxDistance: number;
}
type MemoryPatchApplyCallback = (code: NativePointer) => void;
/**
* Represents a signed 64-bit value.
*/
declare class Int64 {
/**
* Creates a new Int64 from `v`, which is either a string containing the value in decimal, or hexadecimal
* if prefixed with “0x”, or a number. You may use the int64(v) short-hand for brevity.
*/
constructor(v: string | number | Int64);
/**
* Makes a new Int64 whose value is `this` + `v`.
*/
add(v: Int64 | number | string): Int64;
/**
* Makes a new Int64 whose value is `this` - `v`.
*/
sub(v: Int64 | number | string): Int64;
/**
* Makes a new Int64 whose value is `this` & `v`.
*/
and(v: Int64 | number | string): Int64;
/**
* Makes a new Int64 whose value is `this` | `v`.
*/
or(v: Int64 | number | string): Int64;
/**
* Makes a new Int64 whose value is `this` ^ `v`.
*/
xor(v: Int64 | number | string): Int64;
/**
* Makes a new Int64 whose value is `this` << `v`.
*/
shl(v: Int64 | number | string): Int64;
/**
* Makes a new Int64 whose value is `this` >> `v`.
*/
shr(v: Int64 | number | string): Int64;
/**
* Makes a new Int64 whose value is ~`this`.
*/
not(): Int64;
/**
* Returns an integer comparison result just like String#localeCompare().
*/
compare(v: Int64 | number | string): number;
/**
* Returns a boolean indicating whether `v` is equal to `this`.
*/
equals(v: Int64 | number | string): boolean;
/**
* Converts to a number.
*/
toNumber(): number;
/**
* Converts to a string, optionally with a custom `radix`.
*/
toString(radix?: number): string;
/**
* Converts to a JSON-serializable value. Same as `toString()`.
*/
toJSON(): string;
/**
* Converts to a number. Same as `toNumber()`.
*/
valueOf(): number;
}
/**
* Represents an unsigned 64-bit value.
*/
declare class UInt64 {
/**
* Creates a new UInt64 from `v`, which is either a string containing the value in decimal, or hexadecimal
* if prefixed with “0x”, or a number. You may use the uint64(v) short-hand for brevity.
*/
constructor(v: string | number | UInt64);
/**
* Makes a new UInt64 whose value is `this` + `v`.
*/
add(v: UInt64 | number | string): UInt64;
/**
* Makes a new UInt64 whose value is `this` - `v`.
*/
sub(v: UInt64 | number | string): UInt64;
/**
* Makes a new UInt64 whose value is `this` & `v`.
*/
and(v: UInt64 | number | string): UInt64;
/**
* Makes a new UInt64 whose value is `this` | `v`.
*/
or(v: UInt64 | number | string): UInt64;
/**
* Makes a new UInt64 whose value is `this` ^ `v`.
*/
xor(v: UInt64 | number | string): UInt64;
/**
* Makes a new UInt64 whose value is `this` >> `v`.
*/
shr(v: UInt64 | number | string): UInt64;
/**
* Makes a new UInt64 whose value is `this` << `v`.
*/
shl(v: UInt64 | number | string): UInt64;
/**
* Makes a new UInt64 whose value is ~`this`.
*/
not(): UInt64;
/**
* Returns an integer comparison result just like String#localeCompare().
*/
compare(v: UInt64 | number | string): number;
/**
* Returns a boolean indicating whether `v` is equal to `this`.
*/
equals(v: UInt64 | number | string): boolean;
/**
* Converts to a number.
*/
toNumber(): number;
/**
* Converts to a string, optionally with a custom `radix`.
*/
toString(radix?: number): string;
/**
* Converts to a JSON-serializable value. Same as `toString()`.
*/
toJSON(): string;
/**
* Converts to a number. Same as `toNumber()`.
*/
valueOf(): number;
}
/**
* Represents a native pointer value whose size depends on Process#pointerSize.
*/
declare class NativePointer {
/**
* Creates a new NativePointer from `v`, which is either a string containing the memory address in decimal,
* or hexadecimal if prefixed with “0x”, or a number. You may use the ptr(v) short-hand for brevity.
*/
constructor(v: string | number | UInt64 | Int64 | NativePointerValue);
/**
* Returns a boolean allowing you to conveniently check if a pointer is `NULL`.
*/
isNull(): boolean;
/**
* Makes a new NativePointer whose value is `this` + `v`.
*/
add(v: NativePointerValue | UInt64 | Int64 | number | string): NativePointer;
/**
* Makes a new NativePointer whose value is `this` - `v`.
*/
sub(v: NativePointerValue | UInt64 | Int64 | number | string): NativePointer;
/**
* Makes a new NativePointer whose value is `this` & `v`.
*/
and(v: NativePointerValue | UInt64 | Int64 | number | string): NativePointer;
/**
* Makes a new NativePointer whose value is `this` | `v`.
*/
or(v: NativePointerValue | UInt64 | Int64 | number | string): NativePointer;
/**
* Makes a new NativePointer whose value is `this` ^ `v`.
*/
xor(v: NativePointerValue | UInt64 | Int64 | number | string): NativePointer;
/**
* Makes a new NativePointer whose value is `this` << `v`.
*/
shr(v: NativePointerValue | UInt64 | Int64 | number | string): NativePointer;
/**
* Makes a new NativePointer whose value is `this` >> `v`.
*/
shl(v: NativePointerValue | UInt64 | Int64 | number | string): NativePointer;
/**
* Makes a new NativePointer whose value is ~`this`.
*/
not(): NativePointer;
/**
* Makes a new NativePointer by taking the bits of `this` and adding
* pointer authentication bits, creating a signed pointer. This is a
* no-op if the current process does not support pointer
* authentication, returning `this` instead of a new value.
*
* @param key The key to use. Defaults to `ia`.
* @param data The data to use. Defaults to `0`.
*/
sign(key?: PointerAuthenticationKey, data?: NativePointerValue | UInt64 | Int64 | number | string): NativePointer;
/**
* Makes a new NativePointer by taking the bits of `this` and
* removing its pointer authentication bits, creating a raw pointer.
* This is a no-op if the current process does not support pointer
* authentication, returning `this` instead of a new value.
*
* @param key The key that was used to sign `this`. Defaults to `ia`.
*/
strip(key?: PointerAuthenticationKey): NativePointer;
/**
* Makes a new NativePointer by taking `this` and blending it with
* a constant, which may in turn be passed to `sign()` as `data`.
*
* @param smallInteger Value to blend with.
*/
blend(smallInteger: number): NativePointer;
/**
* Returns a boolean indicating whether `v` is equal to `this`; i.e. it contains the same memory address.
*/
equals(v: NativePointerValue | UInt64 | Int64 | number | string): boolean;
/**
* Returns an integer comparison result just like String#localeCompare().
*/
compare(v: NativePointerValue | UInt64 | Int64 | number | string): number;
/**
* Converts to a signed 32-bit integer.
*/
toInt32(): number;
/**
* Converts to an unsigned 32-bit integer.
*/
toUInt32(): number;
/**
* Converts to a “0x”-prefixed hexadecimal string, unless a `radix`
* is specified.
*/
toString(radix?: number): string;
/**
* Converts to a JSON-serializable value. Same as `toString()`.
*/
toJSON(): string;
/**
* Returns a string containing a `Memory#scan()`-compatible match pattern for this pointer’s raw value.
*/
toMatchPattern(): string;
readPointer(): NativePointer;
readS8(): number;
readU8(): number;
readS16(): number;
readU16(): number;
readS32(): number;
readU32(): number;
readS64(): Int64;
readU64(): UInt