JavaScript API
Getting started
To be more productive, we highly recommend using our TypeScript bindings. This means you get code completion, type checking, inline docs, refactoring tools, etc.
Here’s a short teaser video showing the editor experience:
Clone this repo to get started.
Table of contents
- Runtime information
- Process, Thread, Module and Memory
- Data Types, Function and Callback
- Network
- File and Stream
- Database
- Instrumentation
- CPU Instruction
- Other
Runtime information
Frida
-
Frida.version
: property containing the current Frida version, as a string. -
Frida.heapSize
: dynamic property containing the current size of Frida’s private heap, 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.
Script
-
Script.runtime
: string property containing the runtime being used. EitherQJS
orV8
. -
Script.pin()
: 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 bindWeak() when you need to schedule cleanup on another thread. -
Script.unpin()
: reverses a previous pin() so the current script may be unloaded. -
Script.bindWeak(value, fn)
: monitorsvalue
and calls thefn
callback as soon asvalue
has been garbage-collected, or the script is about to get unloaded. Returns an ID that you can pass toScript.unbindWeak()
for explicit cleanup.This API is useful if you’re building a language-binding, where you need to free native resources when a JS value is no longer needed.
-
Script.unbindWeak(id)
: stops monitoring the value passed toScript.bindWeak(value, fn)
, and call thefn
callback immediately. -
Script.setGlobalAccessHandler(handler | null)
: 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.The
handler
is an object containing two properties:enumerate()
: queries which additional globals exist. Must return an array of strings.get(property)
: retrieves the value for the given property.
Process, Thread, Module and Memory
Process
-
Process.id
: property containing the PID as a number -
Process.arch
: property containing the stringia32
,x64
,arm
orarm64
-
Process.platform
: property containing the stringwindows
,darwin
,linux
orqnx
-
Process.pageSize
: property containing the size of a virtual memory page (in bytes) as a number. This is used to make your scripts more portable. -
Process.pointerSize
: property containing the size of a pointer (in bytes) as a number. This is used to make your scripts more portable. -
Process.codeSigningPolicy
: property containing the stringoptional
orrequired
, where the latter means Frida will avoid modifying existing code in memory and will not try to run unsigned code. Currently this property will always be set tooptional
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. -
Process.mainModule
: property containing aModule
representing the main executable of the process -
Process.getCurrentDir()
: returns a string specifying the filesystem path to the current working directory -
Process.getHomeDir()
: returns a string specifying the filesystem path to the current user’s home directory -
Process.getTmpDir()
: returns a string specifying the filesystem path to the directory to use for temporary files -
Process.isDebuggerAttached()
: returns a boolean indicating whether a debugger is currently attached -
Process.getCurrentThreadId()
: get this thread’s OS-specific id as a number -
Process.enumerateThreads()
: enumerates all threads, returning an array of objects containing the following properties:id
: OS-specific idstate
: string specifying eitherrunning
,stopped
,waiting
,uninterruptible
orhalted
context
: object with the keyspc
andsp
, which are NativePointer objects specifying EIP/RIP/PC and ESP/RSP/SP, respectively, for ia32/x64/arm. Other processor-specific keys are also available, e.g.eax
,rax
,r0
,x0
, etc.
-
Process.findModuleByAddress(address)
,Process.getModuleByAddress(address)
,Process.findModuleByName(name)
,Process.getModuleByName(name)
: returns a Module whose address or name matches the one specified. In the event that no such module could be found, the find-prefixed functions return null whilst the get-prefixed functions throw an exception. -
Process.enumerateModules()
: enumerates modules loaded right now, returning an array of Module objects. -
Process.findRangeByAddress(address)
,getRangeByAddress(address)
: return an object with details about the range containing address. In the event that no such range could be found, findRangeByAddress() returns null whilst getRangeByAddress() throws an exception. SeeProcess.enumerateRanges()
for details about which fields are included. -
Process.enumerateRanges(protection|specifier)
: enumerates memory ranges satisfyingprotection
given as a string of the form:rwx
, whererw-
means “must be at least readable and writable”. Alternatively you may provide aspecifier
object with aprotection
key whose value is as aforementioned, and acoalesce
key set totrue
if you’d like neighboring ranges with the same protection to be coalesced (the default isfalse
; i.e. keeping the ranges separate). Returns an array of objects containing the following properties:base
: base address as aNativePointer
size
: size in bytesprotection
: protection string (see above)-
file
: (when available) file mapping details as an object containing:path
: full filesystem path as a stringoffset
: offset in the mapped file on disk, in bytessize
: size in the mapped file on disk, in bytes
-
Process.enumerateMallocRanges()
: just likeenumerateRanges()
, but for individual memory allocations known to the system heap. -
Process.setExceptionHandler(callback)
: install a process-wide exception handler callback that gets a chance to handle native exceptions before the hosting process itself does. Called with a single argument,details
, that is an object containing:type
: string specifying one of:- abort
- access-violation
- guard-page
- illegal-instruction
- stack-overflow
- arithmetic
- breakpoint
- single-step
- system
address
: address where the exception occurred, as a NativePointermemory
: if present, is an object containing:operation
: the kind of operation that triggered the exception, as a string specifying eitherread
,write
, orexecute
address
: address that was accessed when the exception occurred, as a NativePointer
context
: object with the keyspc
andsp
, which are NativePointer objects specifying EIP/RIP/PC and ESP/RSP/SP, respectively, for ia32/x64/arm. Other processor-specific keys are also available, e.g.eax
,rax
,r0
,x0
, etc. You may also update register values by assigning to these keys.nativeContext
: address of the OS and architecture-specific CPU context struct, as a NativePointer. This is only exposed as a last resort for edge-cases wherecontext
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.
It is up to your callback to decide what to do with the exception. It could log the issue, notify your application through a send() followed by a blocking recv() for acknowledgement of the sent data being received, or it can 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 returntrue
, Frida will forward the exception to the hosting process’ exception handler, if it has one, or let the OS terminate the process.
Thread
-
Thread.backtrace([context, backtracer])
: generate a backtrace for the current thread, returned as an array ofNativePointer
objects.If you call this from Interceptor’s
onEnter
oronLeave
callbacks you should providethis.context
for the optionalcontext
argument, as it will give you a more accurate backtrace. Omittingcontext
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 stack frames. The optionalbacktracer
argument specifies the kind of backtracer to use, and must be eitherBacktracer.FUZZY
orBacktracer.ACCURATE
, where the latter is the default if not specified. The accurate kind of backtracers rely on debugger-friendly binaries or presence of debug information to do a good job, whereas 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. The generated backtrace is currently limited to 16 frames and is not adjustable without recompiling Frida.
Thread.sleep(delay)
: suspend execution of the current thread fordelay
seconds specified as a number. For example 0.05 to sleep for 50 ms.
Module
Objects returned by e.g. Module.load()
and Process.enumerateModules()
.
-
name
: canonical module name as a string -
base
: base address as aNativePointer
-
size
: size in bytes -
path
: full filesystem path as a string -
enumerateImports()
: enumerates imports of module, returning an array of objects containing the following properties:type
: string specifying eitherfunction
orvariable
name
: import name as a stringmodule
: module name as a stringaddress
: absolute address as aNativePointer
slot
: memory location where the import is stored, as aNativePointer
Only the
name
field is guaranteed to be present for all imports. The platform-specific backend will do its best to resolve the other fields even beyond what the native metadata provides, but there is no guarantee that it will succeed. -
enumerateExports()
: enumerates exports of module, returning an array of objects containing the following properties:type
: string specifying eitherfunction
orvariable
name
: export name as a stringaddress
: absolute address as aNativePointer
-
enumerateSymbols()
: enumerates symbols of module, returning an array of objects containing the following properties:isGlobal
: boolean specifying whether symbol is globally visibletype
: string specifying one of:- unknown
- section
- undefined (Mach-O)
- absolute (Mach-O)
- prebound-undefined (Mach-O)
- indirect (Mach-O)
- object (ELF)
- function (ELF)
- file (ELF)
- common (ELF)
- tls (ELF)
section
: if present, is an object containing:id
: string containing section index, segment name (if applicable) and section name – same format as r2’s section IDsprotection
: protection like inProcess.enumerateRanges()
name
: symbol name as a stringaddress
: absolute address as aNativePointer
size
: if present, a number specifying the symbol’s size in bytes
enumerateSymbols() is only available on i/macOS and Linux-based OSes
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. You may also find the DebugSymbol API adequate, depending on your use-case.
-
enumerateRanges(protection)
: just likeProcess.enumerateRanges
, except it’s scoped to the module. -
enumerateSections()
: enumerates sections of module, returning an array of objects containing the following properties:id
: string containing section index, segment name (if applicable) and section name – same format as r2’s section IDsname
: section name as a stringaddress
: absolute address as aNativePointer
size
: size in bytes
-
enumerateDependencies()
: enumerates dependencies of module, returning an array of objects containing the following properties:name
: module name as a stringtype
: string specifying one of:- regular
- weak
- reexport
- upward
-
findExportByName(exportName)
,getExportByName(exportName)
: returns the absolute address of the export namedexportName
. In the event that no such export could be found, the find-prefixed function returns null whilst the get-prefixed function throws an exception. -
Module.load(path)
: loads the specified module from the filesystem path and returns aModule
object. Throws an exception if the specified module cannot be loaded. -
Module.ensureInitialized(name)
: ensures that initializers of the specified module 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 ObjC classes provided by a given module. -
Module.findBaseAddress(name)
,Module.getBaseAddress(name)
: returns the base address of thename
module. In the event that no such module could be found, the find-prefixed function returns null whilst the get-prefixed function throws an exception. -
Module.findExportByName(moduleName|null, exportName)
,Module.getExportByName(moduleName|null, exportName)
: returns the absolute address of the export namedexportName
inmoduleName
. If the module isn’t known you may passnull
instead of its name, but this can be a costly search and should be avoided. In the event that no such module or export could be found, the find-prefixed function returns null whilst the get-prefixed function throws an exception.
ModuleMap
-
new ModuleMap([filter])
: create 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 callingupdate()
. Thefilter
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. Thefilter
function is passed a Module object and must returntrue
for each module that should be kept in the map. It is called for each loaded module every time the map is updated. -
has(address)
: check ifaddress
belongs to any of the contained modules, and returns the result as a boolean -
find(address)
,get(address)
: returns a Module with details about the module thataddress
belongs to. In the event that no such module could be found,find()
returnsnull
whilstget()
throws an exception. -
findName(address)
,getName(address)
,findPath(address)
,getPath(address)
: just likefind()
andget()
, but only returns thename
orpath
field, which means less overhead when you don’t need the other details. -
update()
: update the map. You should call this after a module has been loaded or unloaded to avoid operating on stale data. -
values()
: returns an array with the Module objects currently in the map. The returned array is a deep copy and will not mutate after a call toupdate()
.
Memory
-
Memory.scan(address, size, pattern, callbacks)
: scan memory for occurrences ofpattern
in the memory range given byaddress
andsize
.-
pattern
must be of the form “13 37 ?? ff” to match 0x13 followed by 0x37 followed by any byte followed by 0xff. For more advanced matching it is also possible to specify an r2-style mask. The mask is bitwise AND-ed against both the needle and the haystack. To specify the mask append a:
character after the needle, followed by the mask using the same syntax. For example: “13 37 13 37 : 1f ff ff f1”. For convenience it is also possible to specify nibble-level wildcards, like “?3 37 13 ?7”, which gets translated into masks behind the scenes. -
callbacks
is an object with:-
onMatch(address, size)
: called withaddress
containing the address of the occurence as aNativePointer
andsize
specifying the size as a number.This function may return the string
stop
to cancel the memory scanning early. -
onError(reason)
: called withreason
when there was a memory access error while scanning -
onComplete()
: called when the memory range has been fully scanned
-
-
-
Memory.scanSync(address, size, pattern)
: synchronous version ofscan()
that returns an array of objects containing the following properties:address
: absolute address as aNativePointer
.size
: size in bytes
For example:
-
Memory.alloc(size[, options])
: allocatesize
bytes of memory on the heap, or, ifsize
is a multiple ofProcess.pageSize
, one or more raw memory pages managed by the OS. When using page granularity you may also specify anoptions
object if you need the memory allocated close to a given address, by specifying{ near: address, maxDistance: distanceInBytes }
. The returned value is aNativePointer
and the underlying memory will be released when all JavaScript handles to it are gone. This means you need to keep a reference to it while the pointer is being used by code outside the JavaScript runtime. -
Memory.copy(dst, src, n)
: just like memcpy(). Returns nothing.- dst: a
NativePointer
specifying the destination base address. - src: a
NativePointer
specifying the source base address. - n: size in bytes to be copied.
- dst: a
-
Memory.dup(address, size)
: short-hand forMemory.alloc()
followed byMemory.copy()
. Returns aNativePointer
containing the base address of the freshly allocated memory. SeeMemory.copy()
for details on the memory allocation’s lifetime. -
Memory.protect(address, size, protection)
: update protection on a region of memory, whereprotection
is a string of the same format asProcess.enumerateRanges()
.Returns a boolean indicating whether the operation completed successfully.
For example:
-
Memory.patchCode(address, size, apply)
: safely modifysize
bytes ataddress
, specified as a NativePointer. The supplied JavaScript functionapply
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 asaddress
, 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).For example:
Memory.allocUtf8String(str)
,Memory.allocUtf16String(str)
,Memory.allocAnsiString(str)
: allocate, encode and write outstr
as a UTF-8/UTF-16/ANSI string on the heap. The returned object is aNativePointer
. SeeMemory.alloc()
for details about its lifetime.
MemoryAccessMonitor
-
MemoryAccessMonitor.enable(ranges, callbacks)
: monitor one or more memory ranges for access, and notify on the first access of each contained memory page.ranges
is either a single range object or an array of such objects, each of which contains:base
: base address as aNativePointer
size
: size in bytes
callbacks
is an object specifying:onAccess(details)
: called synchronously withdetails
object containing:operation
: the kind of operation that triggered the access, as a string specifying eitherread
,write
, orexecute
from
: address of instruction performing the access as aNativePointer
address
: address being accessed as aNativePointer
rangeIndex
: index of the accessed range in the ranges provided toMemoryAccessMonitor.enable()
pageIndex
: index of the accessed memory page inside the specified rangepagesCompleted
: overall number of pages which have been accessed so far (and are no longer being monitored)pagesTotal
: overall number of pages that were initially monitored
-
MemoryAccessMonitor.disable()
: stop monitoring the remaining memory ranges passed toMemoryAccessMonitor.enable()
.
CModule
-
new CModule(code[, symbols, options])
: creates a new C module from the providedcode
, either a string containing the C source code to compile, or an ArrayBuffer containing a precompiled shared library. The C module gets mapped into memory and becomes fully accessible to JavaScript.Useful for implementing hot callbacks, e.g. for Interceptor and Stalker, but also useful when needing to start new threads in order to call functions in a tight loop, e.g. for fuzzing purposes.
Global functions are automatically exported as NativePointer properties named exactly like in the C source code. This means you can pass them to Interceptor and Stalker, or call them using NativePointer.
In addition to accessing a curated subset of Gum, GLib, and standard C APIs, the code being mapped in can also communicate with JavaScript through the
symbols
exposed to it. This is the optional second argument, an object specifying additional symbol names and their NativePointer values, each of which will be plugged in at creation. This may for example be one or more memory blocks allocated using Memory.alloc(), and/or NativeCallback values for receiving callbacks from the C module.To perform initialization and cleanup, you may define functions with the following names and signatures:
void init (void)
void finalize (void)
Note that all data is read-only, so writable globals should be declared extern, allocated using e.g. Memory.alloc(), and passed in as symbols through the constructor’s second argument.
The optional third argument,
options
, is an object that may be used to specify which toolchain to use, e.g.:{ toolchain: 'external' }
. Supported values are:internal
: use TinyCC, which is statically linked into the runtime. Never touches the filesystem and works even in sandboxed processes. The generated code is however not optimized, as TinyCC optimizes for small compiler footprint and short compilation times.external
: use toolchain provided by the target system, assuming it is accessible to the process we’re executing inside.any
: same asinternal
ifProcess.arch
is supported by TinyCC, andexternal
otherwise. This is the default behavior if left unspecified.
-
dispose()
: eagerly unmaps the module from memory. Useful for short-lived modules when waiting for a future garbage collection isn’t desirable. -
builtins
: an object specifying builtins present when constructing a CModule from C source code. This is typically used by a scaffolding tool such asfrida-create
in order to set up a build environment that matches what CModule uses. The exact contents depends on theProcess.arch
and Frida version, but may look something like the following:{ defines: { 'GLIB_SIZEOF_VOID_P': '8', 'G_GINT16_MODIFIER': '"h"', 'G_GINT32_MODIFIER': '""', 'G_GINT64_MODIFIER': '"ll"', 'G_GSIZE_MODIFIER': '"l"', 'G_GSSIZE_MODIFIER': '"l"', 'HAVE_I386': true }, headers: { 'gum/arch-x86/gumx86writer.h': '…', 'gum/gumdefs.h': '…', 'gum/guminterceptor.h': '…', 'gum/gummemory.h': '…', 'gum/gummetalarray.h': '…', 'gum/gummetalhash.h': '…', 'gum/gummodulemap.h': '…', 'gum/gumprocess.h': '…', 'gum/gumspinlock.h': '…', 'gum/gumstalker.h': '…', 'glib.h': '…', 'json-glib/json-glib.h': '…', 'capstone.h': '…' } }
Examples
Which you might load using Frida’s REPL:
(The REPL monitors the file on disk and reloads the script on change.)
You can then type hello()
in the REPL to call the C function.
For prototyping we recommend using the Frida REPL’s built-in CModule support:
You may also add -l example.js
to load some JavaScript next to it.
The JavaScript code may use the global variable named cm
to access
the CModule object, but only after rpc.exports.init()
has been
called, so perform any initialization depending on the CModule there. You may
also inject symbols by assigning to the global object named cs
, but this
must be done before rpc.exports.init()
gets called.
Here’s an example:
More details on CModule can be found in the Frida 12.7 release notes.
ApiResolver
-
new ApiResolver(type)
: create a new resolver of the giventype
, allowing you to quickly find APIs by name, with globs permitted. Precisely which resolvers are available depends on the current platform and runtimes loaded in the current process. As of the time of writing, the available resolvers are:module
: Resolves module exports, imports, and sections. Always available.swift
: Resolves Swift functions. Available in processes that have a Swift runtime loaded. UseSwift.available
to check at runtime, or wrap yournew ApiResolver('swift')
call in a try-catch.objc
: Resolves Objective-C methods. Available on macOS and iOS in processes that have the Objective-C runtime loaded. UseObjC.available
to check at runtime, or wrap yournew ApiResolver('objc')
call in a try-catch.
The resolver will load the minimum amount of data required on creation, and lazy-load the rest depending on the queries it receives. It is thus recommended to use the same instance for a batch of queries, but recreate it for future batches to avoid looking at stale data.
-
enumerateMatches(query)
: performs the resolver-specificquery
string, optionally suffixed with/i
to perform case-insensitive matching, returning an array of objects containing the following properties:name
: name of the API that was foundaddress
: address as aNativePointer
size
: if present, a number specifying the size in bytes
DebugSymbol
-
DebugSymbol.fromAddress(address)
,DebugSymbol.fromName(name)
: look up debug information foraddress
/name
and return it as an object containing:address
: Address that this symbol is for, as aNativePointer
.name
: Name of the symbol, as a string, or null if unknown.moduleName
: Module name owning this symbol, as a string, or null if unknown.fileName
: File name owning this symbol, as a string, or null if unknown.lineNumber
: Line number infileName
, as a number, or null if unknown.
You may also call
toString()
on it, which is very useful when combined withThread.backtrace()
:
-
DebugSymbol.getFunctionByName(name)
: resolves a function name and returns its address as aNativePointer
. Returns the first if more than one function is found. Throws an exception if the name cannot be resolved. -
DebugSymbol.findFunctionsNamed(name)
: resolves a function name and returns its addresses as an array ofNativePointer
objects. -
DebugSymbol.findFunctionsMatching(glob)
: resolves function names matchingglob
and returns their addresses as an array ofNativePointer
objects. -
DebugSymbol.load(path)
: loads debug symbols for a specific module.
Kernel
-
Kernel.available
: a boolean specifying whether the Kernel API is available. Do not invoke any otherKernel
properties or methods unless this is the case. -
Kernel.base
: base address of the kernel, as a UInt64. -
Kernel.pageSize
: size of a kernel page in bytes, as a number. -
Kernel.enumerateModules()
: enumerates kernel modules loaded right now, returning an array of objects containing the following properties:name
: canonical module name as a stringbase
: base address as aNativePointer
size
: size in bytes
-
Kernel.enumerateRanges(protection|specifier)
: enumerate kernel memory ranges satisfyingprotection
given as a string of the form:rwx
, whererw-
means “must be at least readable and writable”. Alternatively you may provide aspecifier
object with aprotection
key whose value is as aforementioned, and acoalesce
key set totrue
if you’d like neighboring ranges with the same protection to be coalesced (the default isfalse
; i.e. keeping the ranges separate). Returns an array of objects containing the following properties:base
: base address as aNativePointer
size
: size in bytesprotection
: protection string (see above)
-
Kernel.enumerateModuleRanges(name, protection)
: just likeKernel.enumerateRanges
, except it’s scoped to the specified modulename
– which may benull
for the module of the kernel itself. Each range also has aname
field containing a unique identifier as a string. -
Kernel.alloc(size)
: allocatesize
bytes of kernel memory, rounded up to a multiple of the kernel’s page size. The returned value is aUInt64
specifying the base address of the allocation. -
Kernel.protect(address, size, protection)
: update protection on a region of kernel memory, whereprotection
is a string of the same format asKernel.enumerateRanges()
.For example:
-
Kernel.readByteArray(address, length)
: just likeNativePointer#readByteArray
, but reading from kernel memory. -
Kernel.writeByteArray(address, bytes)
: just likeNativePointer#writeByteArray
, but writing to kernel memory. -
Kernel.scan(address, size, pattern, callbacks)
: just likeMemory.scan
, but scanning kernel memory. -
Kernel.scanSync(address, size, pattern)
: synchronous version ofscan()
that returns the matches in an array.
Data Types, Function and Callback
Int64
-
new Int64(v)
: create a new Int64 fromv
, which is either a number or a string containing a value in decimal, or hexadecimal if prefixed with “0x”. You may use theint64(v)
short-hand for brevity. -
add(rhs)
,sub(rhs)
,and(rhs)
,or(rhs)
,xor(rhs)
: make a new Int64 with this Int64 plus/minus/and/or/xorrhs
, which may either be a number or another Int64 -
shr(n)
,shl(n)
: make a new Int64 with this Int64 shifted right/left byn
bits -
compare(rhs)
: returns an integer comparison result just like String#localeCompare() -
toNumber()
: cast this Int64 to a number -
toString([radix = 10])
: convert to a string of optional radix (defaults to 10)
UInt64
-
new UInt64(v)
: create a new UInt64 fromv
, which is either a number or a string containing a value in decimal, or hexadecimal if prefixed with “0x”. You may use theuint64(v)
short-hand for brevity. -
add(rhs)
,sub(rhs)
,and(rhs)
,or(rhs)
,xor(rhs)
: make a new UInt64 with this UInt64 plus/minus/and/or/xorrhs
, which may either be a number or another UInt64 -
shr(n)
,shl(n)
: make a new UInt64 with this UInt64 shifted right/left byn
bits -
compare(rhs)
: returns an integer comparison result just like String#localeCompare() -
toNumber()
: cast this UInt64 to a number -
toString([radix = 10])
: convert to a string of optional radix (defaults to 10)
NativePointer
-
new NativePointer(s)
: creates a new NativePointer from the strings
containing a memory address in either decimal, or hexadecimal if prefixed with ‘0x’. You may use theptr(s)
short-hand for brevity. -
isNull()
: returns a boolean allowing you to conveniently check if a pointer is NULL -
add(rhs)
,sub(rhs)
,and(rhs)
,or(rhs)
,xor(rhs)
: makes a new NativePointer with this NativePointer plus/minus/and/or/xorrhs
, which may either be a number or another NativePointer -
shr(n)
,shl(n)
: makes a new NativePointer with this NativePointer shifted right/left byn
bits -
not()
: makes a new NativePointer with this NativePointer’s bits inverted -
sign([key, data])
: makes a new NativePointer by taking this NativePointer’s bits 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 NativePointer instead of a new value.Optionally,
key
may be specified as a string. Supported values are:- ia: The IA key, for signing code pointers. This is the default.
- ib: The IB key, for signing code pointers.
- da: The DA key, for signing data pointers.
- db: The DB key, for signing data pointers.
The
data
argument may also be specified as a NativePointer/number-like value to provide extra data used for the signing, and defaults to0
. -
strip([key])
: makes a new NativePointer by taking this NativePointer’s bits 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 NativePointer instead of a new value.Optionally,
key
may be passed to specify which key was used to sign the pointer being stripped. Defaults toia
. (Seesign()
for supported values.) -
blend(smallInteger)
: makes a new NativePointer by taking this NativePointer’s bits and blending them with a constant, which may in turn be passed tosign()
asdata
. -
equals(rhs)
: returns a boolean indicating whetherrhs
is equal to this one; i.e. it has the same pointer value -
compare(rhs)
: returns an integer comparison result just like String#localeCompare() -
toInt32()
: casts this NativePointer to a signed 32-bit integer -
toString([radix = 16])
: converts to a string of optional radix (defaults to 16) -
toMatchPattern()
: returns a string containing aMemory.scan()
-compatible match pattern for this pointer’s raw value -
readPointer()
: reads aNativePointer
from this memory location.A JavaScript exception will be thrown if the address isn’t readable.
-
writePointer(ptr)
: writesptr
to this memory location.A JavaScript exception will be thrown if the address isn’t writable.
-
readS8()
,readU8()
,readS16()
,readU16()
,readS32()
,readU32()
,readShort()
,readUShort()
,readInt()
,readUInt()
,readFloat()
,readDouble()
: reads a signed or unsigned 8/16/32/etc. or float/double value from this memory location and returns it as a number.A JavaScript exception will be thrown if the address isn’t readable.
-
writeS8(value)
,writeU8(value)
,writeS16(value)
,writeU16(value)
,writeS32(value)
,writeU32(value)
,writeShort(value)
,writeUShort(value)
,writeInt(value)
,writeUInt(value)
,writeFloat(value)
,writeDouble(value)
: writes a signed or unsigned 8/16/32/etc. or float/doublevalue
to this memory location.A JavaScript exception will be thrown if the address isn’t writable.
-
readS64()
,readU64()
,readLong()
,readULong()
: reads a signed or unsigned 64-bit, or long-sized, value from this memory location and returns it as an Int64/UInt64 value.A JavaScript exception will be thrown if the address isn’t readable.
-
writeS64(value)
,writeU64(value)
,writeLong(value)
,writeULong(value)
: writes the Int64/UInt64value
to this memory location.A JavaScript exception will be thrown if the address isn’t writable.
-
readByteArray(length)
: readslength
bytes from this memory location, and returns it as an ArrayBuffer. This buffer may be efficiently transferred to your Frida-based application by passing it as the second argument tosend()
.A JavaScript exception will be thrown if any of the
length
bytes read from the address isn’t readable. -
writeByteArray(bytes)
: writesbytes
to this memory location, wherebytes
is either an ArrayBuffer, typically returned fromreadByteArray()
, or an array of integers between 0 and 255. For example:[ 0x13, 0x37, 0x42 ]
.A JavaScript exception will be thrown if any of the bytes written to the address isn’t writable.
-
readCString([size = -1])
,readUtf8String([size = -1])
,readUtf16String([length = -1])
,readAnsiString([size = -1])
: reads the bytes at this memory location as an ASCII, UTF-8, UTF-16, or ANSI string. Supply the optionalsize
argument if you know the size of the string in bytes, or omit it or specify -1 if the string is NUL-terminated. Likewise you may supply the optionallength
argument if you know the length of the string in characters.A JavaScript exception will be thrown if any of the
size
/length
bytes read from the address isn’t readable.Note that
readAnsiString()
is only available (and relevant) on Windows. -
writeUtf8String(str)
,writeUtf16String(str)
,writeAnsiString(str)
: encodes and writes the JavaScript string to this memory location (with NUL-terminator).A JavaScript exception will be thrown if any of the bytes written to the address isn’t writable.
Note that
writeAnsiString()
is only available (and relevant) on Windows.
ArrayBuffer
-
wrap(address, size)
: creates an ArrayBuffer backed by an existing memory region, whereaddress
is aNativePointer
specifying the base address of the region, andsize
is a number specifying its size. Unlike theNativePointer
read/write APIs, no validation is performed on access, meaning a bad pointer will crash the process. -
unwrap()
: returns aNativePointer
specifying the base address of the ArrayBuffer’s backing store. It is the caller’s responsibility to keep the buffer alive while the backing store is still being used.
NativeFunction
-
new NativeFunction(address, returnType, argTypes[, abi])
: create a new NativeFunction to call the function ataddress
(specified with aNativePointer
), wherereturnType
specifies the return type, and theargTypes
array specifies the argument types. You may optionally also specifyabi
if not system default. For variadic functions, add a'...'
entry toargTypes
between the fixed arguments and the variadic ones.-
Structs & Classes by Value
As for structs or classes passed by value, instead of a string provide an array containing the struct’s field types following each other. You may nest these as deep as desired for representing structs inside structs. Note that the returned object is also a
NativePointer
, and can thus be passed toInterceptor#attach
.This must match the struct/class exactly, so if you have a struct with three ints, you must pass
['int', 'int', 'int']
.For a class that has virtual methods, the first field will be a pointer to the vtable.
For C++ scenarios involving a return value that is larger than
Process.pointerSize
, a typical ABI may expect that aNativePointer
to preallocated space must be passed in as the first parameter. (This scenario is common in WebKit, for example.) -
Supported Types
- void
- pointer
- int
- uint
- long
- ulong
- char
- uchar
- size_t
- ssize_t
- float
- double
- int8
- uint8
- int16
- uint16
- int32
- uint32
- int64
- uint64
- bool
-
Supported ABIs
- default
- Windows 32-bit:
- sysv
- stdcall
- thiscall
- fastcall
- mscdecl
- Windows 64-bit:
- win64
- UNIX x86:
- sysv
- unix64
- UNIX ARM:
- sysv
- vfp
-
-
new NativeFunction(address, returnType, argTypes[, options])
: just like the previous constructor, but where the fourth argument,options
, is an object that may contain one or more of the following keys:abi
: same enum as above.scheduling
: scheduling behavior as a string. Supported values are:- cooperative: Allow other threads to execute JavaScript code while calling the native function, i.e. let go of the lock before the call, and re-acquire it afterwards. This is the default behavior.
- exclusive: Do not allow other threads to execute JavaScript code while calling the native function, i.e. keep holding the JavaScript lock. This is faster but may result in deadlocks.
exceptions
: exception behavior as a string. Supported values are:- steal: If the called function generates a native exception, e.g. by dereferencing an invalid pointer, Frida will unwind the stack and steal the exception, turning it into a JavaScript exception that can be handled. This may leave the application in an undefined state, but is useful to avoid crashing the process while experimenting. This is the default behavior.
- propagate: Let the application deal with any native exceptions that
occur during the function call. (Or, the handler
installed through
Process.setExceptionHandler()
.)
traps
: code traps to be enabled, as a string. Supported values are:- default: Interceptor.attach() callbacks will be called if any hooks are triggered by a function call.
- all: In addition to Interceptor callbacks, Stalker
may also be temporarily reactivated for the duration of each function
call. This is useful for e.g. measuring code coverage while guiding a
fuzzer, implementing “step into” in a debugger, etc.
Note that this is also possible when using the Java
and ObjC APIs, as method wrappers also provide a
clone(options)
API to create a new method wrapper with custom NativeFunction options.
NativeCallback
new NativeCallback(func, returnType, argTypes[, abi])
: create a new NativeCallback implemented by the JavaScript functionfunc
, wherereturnType
specifies the return type, and theargTypes
array specifies the argument types. You may also specify the abi if not system default. SeeNativeFunction
for details about supported types and abis. Note that the returned object is also aNativePointer
, and can thus be passed toInterceptor#replace
. When using the resulting callback with Interceptor.replace(),func
will be invoked withthis
bound to an object with some useful properties, just like the one in Interceptor.attach().
SystemFunction
-
new SystemFunction(address, returnType, argTypes[, abi])
: just likeNativeFunction
, but also provides a snapshot of the thread’s last error status. The return value is an object wrapping the actual return value asvalue
, with one additional platform-specific field named eithererrno
(UNIX) orlastError
(Windows). -
new SystemFunction(address, returnType, argTypes[, options])
: same as above but accepting anoptions
object likeNativeFunction
’s corresponding constructor.
Network
Socket
-
Socket.listen([options])
: open a TCP or UNIX listening socket. Returns a Promise that receives a SocketListener.Defaults to listening on both IPv4 and IPv6, if supported, and binding on all interfaces on a randomly selected TCP port.
The optional
options
argument is an object that may contain some of the following keys:family
: address family as a string. Supported values are:- unix
- ipv4
- ipv6
Defaults to listening on both
ipv4
andipv6
if supported.
host
: (IP family) IP address as a string. Defaults to all interfaces.port
: (IP family) IP port as a number. Defaults to any available.type
: (UNIX family) UNIX socket type as a string. Supported types are:- anonymous
- path
- abstract
- abstract-padded
Defaults to
path
.
path
: (UNIX family) UNIX socket path as a string.backlog
: Listen backlog as a number. Defaults to10
.
-
Socket.connect(options)
: connect to a TCP or UNIX server. Returns a Promise that receives a SocketConnection.The
options
argument is an object that should contain some of the following keys:family
: address family as a string. Supported values are:- unix
- ipv4
- ipv6
Defaults to an IP family depending on the
host
specified.
host
: (IP family) IP address as a string. Defaults tolocalhost
.port
: (IP family) IP port as a number.type
: (UNIX family) UNIX socket type as a string. Supported types are:- anonymous
- path
- abstract
- abstract-padded
Defaults to
path
.
path
: (UNIX family) UNIX socket path as a string.
-
Socket.type(handle)
: inspect the OS sockethandle
and return its type as a string which is eithertcp
,udp
,tcp6
,udp6
,unix:stream
,unix:dgram
, ornull
if invalid or unknown. -
Socket.localAddress(handle)
,Socket.peerAddress(handle)
: inspect the OS sockethandle
and return its local or peer address, ornull
if invalid or unknown.The object returned has the fields:
ip
: (IP sockets) IP address as a string.port
: (IP sockets) IP port as a number.path
: (UNIX sockets) UNIX path as a string.
SocketListener
All methods are fully asynchronous and return Promise objects.
-
path
: (UNIX family) path being listened on. -
port
: (IP family) IP port being listened on. -
close()
: close the listener, releasing resources related to it. Once the listener is closed, all other operations will fail. Closing a listener multiple times is allowed and will not result in an error. -
accept()
: wait for the next client to connect. The returned Promise receives a SocketConnection.
SocketConnection
Inherits from IOStream.
All methods are fully asynchronous and return Promise objects.
setNoDelay(noDelay)
: disable the Nagle algorithm ifnoDelay
istrue
, otherwise enable it. The Nagle algorithm is enabled by default, so it is only necessary to call this method if you wish to optimize for low delay instead of high throughput.
File and Stream
File
-
File.readAllBytes(path)
: synchronously read all bytes from the file specified bypath
and return them as anArrayBuffer
. -
File.readAllText(path)
: synchronously read all text from the file specified bypath
and return it as a string. The file must be UTF-8 encoded, and an exception will be thrown if this is not the case. -
File.writeAllBytes(path, data)
: synchronously writedata
to the file specified bypath
, wheredata
is anArrayBuffer
. -
File.writeAllText(path, text)
: synchronously writetext
to the file specified bypath
, wheretext
is a string. The file will be UTF-8 encoded. -
new File(filePath, mode)
: open or create the file atfilePath
with themode
string specifying how it should be opened. For example"wb"
to open the file for writing in binary mode (this is the same format asfopen()
from the C standard library). -
tell()
: return the current position of the file pointer within the file. -
seek(offset[, whence])
: move the file pointer to a new location.offset
is the position to move to, andwhence
is the starting point for the offset (File.SEEK_SET
for the beginning of the file,File.SEEK_CUR
for the current file position, orFile.SEEK_END
for the end of the file). -
readBytes([size])
: read and returnsize
bytes from the file starting from the current file pointer position as anArrayBuffer
. Ifsize
is not specified, reads until the end of the file from the current position. -
readText([size])
: read and returnsize
characters from the file starting from the current file pointer position as a string. Ifsize
is not specified, reads text until the end of the file from the current position. The bytes being read must be UTF-8 encoded, and an exception will be thrown if this is not the case. -
readLine()
: read and return the next line as a string. Starts reading from the current file pointer position. The returned line does not include the newline character. -
write(data)
: synchronously writedata
to the file, wheredata
is either a string or a buffer as returned byNativePointer#readByteArray
-
flush()
: flush any buffered data to the underlying file. -
close()
: close the file. You should call this function when you’re done with the file unless you are fine with this happening when the object is garbage-collected or the script is unloaded.
IOStream
All methods are fully asynchronous and return Promise objects.
-
input
: the InputStream to read from. -
output
: the OutputStream to write to. -
close()
: close the stream, releasing resources related to it. This will also close the individual input and output streams. Once the stream is closed, all other operations will fail. Closing a stream multiple times is allowed and will not result in an error.
InputStream
All methods are fully asynchronous and return Promise objects.
-
close()
: close the stream, releasing resources related to it. Once the stream is closed, all other operations will fail. Closing a stream multiple times is allowed and will not result in an error. -
read(size)
: read up tosize
bytes from the stream. The returned Promise receives an ArrayBuffer up tosize
bytes long. End of stream is signalled through an empty buffer. -
readAll(size)
: keep reading from the stream until exactlysize
bytes have been consumed. The returned Promise receives an ArrayBuffer that is exactlysize
bytes long. Premature error or end of stream results in the Promise getting rejected with an error, where theError
object has apartialData
property containing the incomplete data.
OutputStream
All methods are fully asynchronous and return Promise objects.
-
close()
: close the stream, releasing resources related to it. Once the stream is closed, all other operations will fail. Closing a stream multiple times is allowed and will not result in an error. -
write(data)
: try to writedata
to the stream. Thedata
value is either an ArrayBuffer or an array of integers between 0 and 255. The returned Promise receives a Number specifying how many bytes ofdata
were written to the stream. -
writeAll(data)
: keep writing to the stream until all ofdata
has been written. Thedata
value is either an ArrayBuffer or an array of integers between 0 and 255. Premature error or end of stream results in an error, where theError
object has apartialSize
property specifying how many bytes ofdata
were written to the stream before the error occurred. -
writeMemoryRegion(address, size)
: try to writesize
bytes to the stream, reading them fromaddress
, which is aNativePointer
. The returned Promise receives a Number specifying how many bytes ofdata
were written to the stream.
UnixInputStream
(Only available on UNIX-like OSes.)
-
new UnixInputStream(fd[, options])
: create a new InputStream from the specified file descriptorfd
.You may also supply an
options
object withautoClose
set totrue
to make the stream close the underlying file descriptor when the stream is released, either throughclose()
or future garbage-collection.
UnixOutputStream
(Only available on UNIX-like OSes.)
-
new UnixOutputStream(fd[, options])
: create a new OutputStream from the specified file descriptorfd
.You may also supply an
options
object withautoClose
set totrue
to make the stream close the underlying file descriptor when the stream is released, either throughclose()
or future garbage-collection.
Win32InputStream
(Only available on Windows.)
-
new Win32InputStream(handle[, options])
: create a new InputStream from the specifiedhandle
, which is a Windows HANDLE value.You may also supply an
options
object withautoClose
set totrue
to make the stream close the underlying handle when the stream is released, either throughclose()
or future garbage-collection.
Win32OutputStream
(Only available on Windows.)
-
new Win32OutputStream(handle[, options])
: create a new OutputStream from the specifiedhandle
, which is a Windows HANDLE value.You may also supply an
options
object withautoClose
set totrue
to make the stream close the underlying handle when the stream is released, either throughclose()
or future garbage-collection.
Database
SqliteDatabase
-
SqliteDatabase.open(path[, options])
: opens the SQLite v3 database specified bypath
, a string containing the filesystem path to the database. By default the database will be opened read-write, but you may customize this behavior by providing anoptions
object with a property namedflags
, specifying an array of strings containing one or more of the following values:readonly
,readwrite
,create
. The returned SqliteDatabase object will allow you to perform queries on the database. -
SqliteDatabase.openInline(encodedContents)
: just likeopen()
but the contents of the database is provided as a string containing its data, Base64-encoded. We recommend gzipping the database before Base64-encoding it, but this is optional and detected by looking for a gzip magic marker. The database is opened read-write, but is 100% in-memory and never touches the filesystem. This is useful for agents that need to bundle a cache of precomputed data, e.g. static analysis data used to guide dynamic analysis. -
close()
: close the database. You should call this function when you’re done with the database, unless you are fine with this happening when the object is garbage-collected or the script is unloaded. -
exec(sql)
: execute a raw SQL query, wheresql
is a string containing the text-representation of the query. The query’s result is ignored, so this should only be used for queries for setting up the database, e.g. table creation. -
prepare(sql)
: compile the provided SQL into a SqliteStatement object, wheresql
is a string containing the text-representation of the query.For example:
dump()
: dump the database to a gzip-compressed blob encoded as Base64, where the result is returned as a string. This is useful for inlining a cache in your agent’s code, loaded by callingSqliteDatabase.openInline()
.
SqliteStatement
bindInteger(index, value)
: bind the integervalue
toindex
bindFloat(index, value)
: bind the floating pointvalue
toindex
bindText(index, value)
: bind the textvalue
toindex
bindBlob(index, bytes)
: bind the blobbytes
toindex
, wherebytes
is an ArrayBuffer, array of byte values, or a stringbindNull(index)
: bind a null value toindex
step()
: either start a new query and get the first result, or move to the next one. Returns an array containing the values in the order specified by the query, ornull
when the last result is reached. You should callreset()
at that point if you intend to use this object again.reset()
: reset internal state to allow subsequent queries
Instrumentation
Interceptor
-
Interceptor.attach(target, callbacks[, data])
: intercept calls to function attarget
. This is aNativePointer
specifying the address of the function you would like to intercept calls to. Note that on 32-bit ARM this address must have its least significant bit set to 0 for ARM functions, and 1 for Thumb functions. Frida takes care of this detail for you if you get the address from a Frida API (for exampleModule.getExportByName()
).The
callbacks
argument is an object containing one or more of:-
onEnter(args)
: callback function given one argumentargs
that can be used to read or write arguments as an array ofNativePointer
objects. {: #interceptor-onenter} -
onLeave(retval)
: callback function given one argumentretval
that is aNativePointer
-derived object containing the raw return value. You may callretval.replace(1337)
to replace the return value with the integer1337
, orretval.replace(ptr("0x1234"))
to replace with a pointer. Note that this object is recycled across onLeave calls, so do not store and use it outside your callback. Make a deep copy if you need to store the contained value, e.g.:ptr(retval.toString())
.
In case the hooked function is very hot,
onEnter
andonLeave
may beNativePointer
values pointing at native C functions compiled using CModule. Their signatures are:-
void onEnter (GumInvocationContext * ic)
-
void onLeave (GumInvocationContext * ic)
In such cases, the third optional argument
data
may be aNativePointer
accessible throughgum_invocation_context_get_listener_function_data()
.You may also intercept arbitrary instructions by passing a function instead of the
callbacks
object. This function has the same signature asonEnter
, but theargs
argument passed to it will only give you sensible values if the intercepted instruction is at the beginning of a function or at a point where registers/stack have not yet deviated from that point.Just like above, this function may also be implemented in C by specifying a
NativePointer
instead of a function.Returns a listener object that you can call
detach()
on.Note that these functions will be invoked with
this
bound to a per-invocation (thread-local) object where you can store arbitrary data, which is useful if you want to read an argument inonEnter
and act on it inonLeave
.For example:
-
-
Additionally, the object contains some useful properties:
-
returnAddress
: return address as a NativePointer -
context
: object with the keyspc
andsp
, which are NativePointer objects specifying EIP/RIP/PC and ESP/RSP/SP, respectively, for ia32/x64/arm. Other processor-specific keys are also available, e.g.eax
,rax
,r0
,x0
, etc. You may also update register values by assigning to these keys. -
errno
: (UNIX) current errno value (you may replace it) -
lastError
: (Windows) current OS error value (you may replace it) -
threadId
: OS thread ID -
depth
: call depth of relative to other invocations
For example:
-
Performance considerations
The callbacks provided have a significant impact on performance. If you only need to inspect arguments but do not care about the return value, or the other way around, make sure you omit the callback that you don't need; i.e. avoid putting your logic in onEnter and leaving onLeave in there as an empty callback.
On an iPhone 5S the base overhead when providing just onEnter might be something like 6 microseconds, and 11 microseconds with both onEnter and onLeave provided.
Also be careful about intercepting calls to functions that are called a bazillion times per second; while send() is asynchronous, the total overhead of sending a single message is not optimized for high frequencies, so that means Frida leaves it up to you to batch multiple values into a single send()-call, based on whether low delay or high throughput is desired.
However when hooking hot functions you may use Interceptor in conjunction with CModule to implement the callbacks in C.
-
Interceptor.detachAll()
: detach all previously attached callbacks. -
Interceptor.replace(target, replacement[, data])
: replace function attarget
with implementation atreplacement
. This is typically used if you want to fully or partially replace an existing function’s implementation.Use
NativeCallback
to implement areplacement
in JavaScript.In case the replaced function is very hot, you may implement
replacement
in C using CModule. You may then also specify the third optional argumentdata
, which is aNativePointer
accessible throughgum_invocation_context_get_listener_function_data()
. Usegum_interceptor_get_current_invocation()
to get hold of theGumInvocationContext *
.Note that
replacement
will be kept alive untilInterceptor#revert
is called.If you want to chain to the original implementation you can synchronously call
target
through aNativeFunction
inside your implementation, which will bypass and go directly to the original implementation.Here’s an example:
-
Interceptor.revert(target)
: revert function attarget
to the previous implementation. -
Interceptor.flush()
: ensure any pending changes have been committed to memory. This is should only be done in the few cases where this is necessary, e.g. if you just attach()ed to or replace()d a function that you are about to call using NativeFunction. Pending changes are flushed automatically whenever the current thread is about to leave the JavaScript runtime or calls send(). This includes any API built on top of send(), like when returning from an RPC method, and calling any method on the console API. -
Interceptor.breakpointKind
: a string specifying the kind of breakpoints to use for non-inline hooks. Only available in the Barebone backend.Defaults to ‘soft’, i.e. software breakpoints. Set it to ‘hard’ to use hardware breakpoints.
Stalker
-
Stalker.exclude(range)
: marks the specified memoryrange
as excluded, which is an object withbase
andsize
properties – like the properties in an object returned by e.g.Process.getModuleByName()
.This means Stalker will not follow execution when encountering a call to an instruction in such a range. You will thus be able to observe/modify the arguments going in, and the return value coming back, but won’t see the instructions that happened between.
Useful to improve performance and reduce noise.
-
Stalker.follow([threadId, options])
: start stalkingthreadId
(or the current thread if omitted), optionally withoptions
for enabling events.For example:
Performance considerations
The callbacks provided have a significant impact on performance. If you only need periodic call summaries but do not care about the raw events, or the other way around, make sure you omit the callback that you don't need; i.e. avoid putting your logic in onCallSummary and leaving onReceive in there as an empty callback.
Also note that Stalker may be used in conjunction with CModule, which means the callbacks may be implemented in C.
-
Stalker.unfollow([threadId])
: stop stalkingthreadId
(or the current thread if omitted). -
Stalker.parse(events[, options])
: parse GumEvent binary blob, optionally withoptions
for customizing the output.For example:
-
Stalker.flush()
: flush out any buffered events. Useful when you don’t want to wait until the nextStalker.queueDrainInterval
tick. -
Stalker.garbageCollect()
: free accumulated memory at a safe point afterStalker#unfollow
. This is needed to avoid race-conditions where the thread just unfollowed is executing its last instructions. -
Stalker.invalidate(address)
: invalidates the current thread’s translated code for a given basic block. Useful when providing a transform callback and wanting to dynamically adapt the instrumentation for a given basic block. This is much more efficient than unfollowing and re-following the thread, which would discard all cached translations and require all encountered basic blocks to be compiled from scratch. -
Stalker.invalidate(threadId, address)
: invalidates a specific thread’s translated code for a given basic block. Useful when providing a transform callback and wanting to dynamically adapt the instrumentation for a given basic block. This is much more efficient than unfollowing and re-following the thread, which would discard all cached translations and require all encountered basic blocks to be compiled from scratch. -
Stalker.addCallProbe(address, callback[, data])
: callcallback
(seeInterceptor#attach#onEnter
for signature) synchronously when a call is made toaddress
. Returns an id that can be passed toStalker#removeCallProbe
later.It is also possible to implement
callback
in C using CModule, by specifying aNativePointer
instead of a function. Signature:void onCall (GumCallSite * site, gpointer user_data)
In such cases, the third optional argument
data
may be aNativePointer
whose value is passed to the callback asuser_data
. -
Stalker.removeCallProbe
: remove a call probe added byStalker#addCallProbe
. -
Stalker.trustThreshold
: an integer specifying how many times a piece of code needs to be executed before it is assumed it can be trusted to not mutate. Specify -1 for no trust (slow), 0 to trust code from the get-go, and N to trust code after it has been executed N times. Defaults to 1. -
Stalker.queueCapacity
: an integer specifying the capacity of the event queue in number of events. Defaults to 16384 events. -
Stalker.queueDrainInterval
: an integer specifying the time in milliseconds between each time the event queue is drained. Defaults to 250 ms, which means that the event queue is drained four times per second. You may also set this property to zero to disable periodic draining, and instead callStalker.flush()
when you would like the queue to be drained.
ObjC
-
ObjC.available
: a boolean specifying whether the current process has an Objective-C runtime loaded. Do not invoke any otherObjC
properties or methods unless this is the case. -
ObjC.api
: an object mapping function names toNativeFunction
instances for direct access to a big portion of the Objective-C runtime API. -
ObjC.classes
: an object mapping class names toObjC.Object
JavaScript bindings for each of the currently registered classes. You can interact with objects by using dot notation and replacing colons with underscores, i.e.:[NSString stringWithString:@"Hello World"]
becomesconst { NSString } = ObjC.classes; NSString.stringWithString_("Hello World");
. Note the underscore after the method name. Refer to iOS Examples section for more details. -
ObjC.protocols
: an object mapping protocol names toObjC.Protocol
JavaScript bindings for each of the currently registered protocols. -
ObjC.mainQueue
: the GCD queue of the main thread -
ObjC.schedule(queue, work)
: schedule the JavaScript functionwork
on the GCD queue specified byqueue
. AnNSAutoreleasePool
is created just before callingwork
, and cleaned up on return.
new ObjC.Object(handle[, protocol])
: create a JavaScript binding given the existing object athandle
(a NativePointer). You may also specify theprotocol
argument if you’d like to treathandle
as an object implementing a certain protocol only.
This object has some special properties:
$kind
: string specifying eitherinstance
,class
ormeta-class
$super
: an ObjC.Object instance used for chaining up to super-class method implementations$superClass
: super-class as an ObjC.Object instance$class
: class of this object as an ObjC.Object instance$className
: string containing the class name of this object$moduleName
: string containing the module path of this object$protocols
: object mapping protocol name toObjC.Protocol
instance for each of the protocols that this object conforms to$methods
: array containing native method names exposed by this object’s class and parent classes$ownMethods
: array containing native method names exposed by this object’s class, not including parent classes$ivars
: object mapping each instance variable name to its current value, allowing you to read and write each through access and assignmentThere is also an
equals(other)
method for checking whether two instances refer to the same underlying object.Note that all method wrappers provide a
clone(options)
API to create a new method wrapper with custom NativeFunction options.
-
new ObjC.Protocol(handle)
: create a JavaScript binding given the existing protocol athandle
(a NativePointer). -
new ObjC.Block(target[, options])
: create a JavaScript binding given the existing block attarget
(a NativePointer), or, to define a new block,target
should be an object specifying the type signature and JavaScript function to call whenever the block is invoked. The function is specified with animplementation
key, and the signature is specified either through atypes
key, or through theretType
andargTypes
keys. SeeObjC.registerClass()
for details.Note that if an existing block lacks signature metadata, you may call
declare(signature)
, wheresignature
is an object with either atypes
key, orretType
andargTypes
keys, as described above.You may also provide an
options
object with the same options as supported by NativeFunction, e.g. to passtraps: 'all'
in order toStalker.follow()
the execution when calling the block.The most common use-case is hooking an existing block, which for a block expecting two arguments would look something like:
ObjC.implement(method, fn)
: create a JavaScript implementation compatible with the signature ofmethod
, where the JavaScript functionfn
is used as the implementation. Returns aNativeCallback
that you may assign to an ObjC method’simplementation
property.
As the
implementation
property is aNativeFunction
and thus also aNativePointer
, you may also useInterceptor
to hook functions:
-
ObjC.registerProxy(properties)
: create a new class designed to act as a proxy for a target object, whereproperties
is an object specifying:protocols
: (optional) Array of protocols this class conforms to.methods
: (optional) Object specifying methods to implement.events
: (optional) Object specifying callbacks for getting notified about events:dealloc()
: Called right after the object has been deallocated. This is where you might clean up any associated state.forward(name)
: Called withname
specifying the method name that we’re about to forward a call to. This might be where you’d start out with a temporary callback that just logs the names to help you decide which methods to override.
-
ObjC.registerClass(properties)
: create a new Objective-C class, whereproperties
is an object specifying:name
: (optional) String specifying the name of the class; omit this if you don’t care about the globally visible name and would like the runtime to auto-generate one for you.super
: (optional) Super-class, or null to create a new root class; omit to inherit from NSObject.protocols
: (optional) Array of protocols this class conforms to.methods
: (optional) Object specifying methods to implement.
-
ObjC.registerProtocol(properties)
: create a new Objective-C protocol, whereproperties
is an object specifying:name
: (optional) String specifying the name of the protocol; omit this if you don’t care about the globally visible name and would like the runtime to auto-generate one for you.protocols
: (optional) Array of protocols this protocol incorporates.methods
: (optional) Object specifying methods to declare.
-
ObjC.bind(obj, data)
: bind some JavaScript data to an Objective-C instance; seeObjC.registerClass()
for an example. -
ObjC.unbind(obj)
: unbind previous associated JavaScript data from an Objective-C instance; seeObjC.registerClass()
for an example. -
ObjC.getBoundData(obj)
: look up previously bound data from an Objective-C object. -
ObjC.enumerateLoadedClasses([options, ]callbacks)
: enumerate classes loaded right now, wherecallbacks
is an object specifying:-
onMatch(name, owner)
: called for each loaded class with thename
of the class as a string, andowner
specifying the path to the module where the class was loaded from. To obtain a JavaScript wrapper for a given class, do:ObjC.classes[name]
. -
onComplete()
: called when all classes have been enumerated.
For example:
-
The optional options
argument is an object where you may specify the
ownedBy
property to limit enumeration to modules in a given ModuleMap
.
For example:
-
ObjC.enumerateLoadedClassesSync([options])
: synchronous version ofenumerateLoadedClasses()
that returns an object mapping owner module to an array of class names.For example:
-
ObjC.choose(specifier, callbacks)
: enumerate live instances of classes matchingspecifier
by scanning the heap.specifier
is either a class selector or an object specifying a class selector and desired options. The class selector is an ObjC.Object of a class, e.g. ObjC.classes.UIButton. When passing an object as the specifier you should provide theclass
field with your class selector, and thesubclasses
field with a boolean indicating whether you’re also interested in subclasses matching the given class selector. The default is to also include subclasses. Thecallbacks
argument is an object specifying:-
onMatch(instance)
: called once for each live instance found with a ready-to-useinstance
just as if you would have callednew ObjC.Object(ptr("0x1234"))
knowing that this particular Objective-C instance lives at 0x1234.This function may return the string
stop
to cancel the enumeration early. -
onComplete()
: called when all instances have been enumerated
-
-
ObjC.chooseSync(specifier)
: synchronous version ofchoose()
that returns the instances in an array. -
ObjC.selector(name)
: convert the JavaScript stringname
to a selector -
ObjC.selectorAsString(sel)
: convert the selectorsel
to a JavaScript string
Java
-
Java.available
: a boolean specifying whether the current process has the a Java VM loaded, i.e. Dalvik or ART. Do not invoke any otherJava
properties or methods unless this is the case. -
Java.androidVersion
: a string specifying which version of Android we’re running on. -
Java.enumerateLoadedClasses(callbacks)
: enumerate classes loaded right now, wherecallbacks
is an object specifying:-
onMatch(name, handle)
: called for each loaded class withname
that may be passed touse()
to get a JavaScript wrapper. You may alsoJava.cast()
thehandle
tojava.lang.Class
. -
onComplete()
: called when all classes have been enumerated.
-
-
Java.enumerateLoadedClassesSync()
: synchronous version ofenumerateLoadedClasses()
that returns the class names in an array. -
Java.enumerateClassLoaders(callbacks)
: enumerate class loaders present in the Java VM, wherecallbacks
is an object specifying:-
onMatch(loader)
: called for each class loader withloader
, a wrapper for the specificjava.lang.ClassLoader
. -
onComplete()
: called when all class loaders have been enumerated.
You may pass such a loader to
Java.ClassFactory.get()
to be able to.use()
classes on the specified class loader. -
-
Java.enumerateClassLoadersSync()
: synchronous version ofenumerateClassLoaders()
that returns the class loaders in an array. -
Java.enumerateMethods(query)
: enumerate methods matchingquery
, specified as"class!method"
, with globs permitted. May also be suffixed with/
and one or more modifiers:i
: Case-insensitive matching.s
: Include method signatures, so e.g."putInt"
becomes"putInt(java.lang.String, int): void"
.u
: User-defined classes only, ignoring system classes.
-
Java.scheduleOnMainThread(fn)
: runfn
on the main thread of the VM. -
Java.perform(fn)
: ensure that the current thread is attached to the VM and callfn
. (This isn’t necessary in callbacks from Java.) Will defer callingfn
if the app’s class loader is not available yet. UseJava.performNow()
if access to the app’s classes is not needed.
-
Java.performNow(fn)
: ensure that the current thread is attached to the VM and callfn
. (This isn’t necessary in callbacks from Java.) -
Java.use(className)
: dynamically get a JavaScript wrapper forclassName
that you can instantiate objects from by calling$new()
on it to invoke a constructor. Call$dispose()
on an instance to clean it up explicitly (or wait for the JavaScript object to get garbage-collected, or script to get unloaded). Static and non-static methods are available, and you can even replace a method implementation and throw an exception from it:
Uses the app’s class loader by default, but you may customize this by assigning a different loader instance to
Java.classFactory.loader
.Note that all method wrappers provide a
clone(options)
API to create a new method wrapper with custom NativeFunction options.
-
Java.openClassFile(filePath)
: open the .dex file atfilePath
, returning an object with the following methods:-
load()
: load the contained classes into the VM. -
getClassNames()
: obtain an array of available class names.
-
-
Java.choose(className, callbacks)
: enumerate live instances of theclassName
class by scanning the Java heap, wherecallbacks
is an object specifying:-
onMatch(instance)
: called with each live instance found with a ready-to-useinstance
just as if you would have calledJava.cast()
with a raw handle to this particular instance.This function may return the string
stop
to cancel the enumeration early. -
onComplete()
: called when all instances have been enumerated
-
-
Java.retain(obj)
: duplicates the JavaScript wrapperobj
for later use outside replacement method.
Java.cast(handle, klass)
: create a JavaScript wrapper given the existing instance athandle
of given classklass
as returned fromJava.use()
. Such a wrapper also has aclass
property for getting a wrapper for its class, and a$className
property for getting a string representation of its class-name.
Java.array(type, elements)
: creates a Java array with elements of the specifiedtype
, from a JavaScript arrayelements
. The resulting Java array behaves like a JS array, but can be passed by reference to Java APIs in order to allow them to modify its contents.
-
Java.isMainThread()
: determine whether the caller is running on the main thread. -
Java.registerClass(spec)
: create a new Java class and return a wrapper for it, wherespec
is an object containing:name
: String specifying the name of the class.superClass
: (optional) Super-class. Omit to inherit fromjava.lang.Object
.implements
: (optional) Array of interfaces implemented by this class.fields
: (optional) Object specifying the name and type of each field to expose.methods
: (optional) Object specifying methods to implement.
-
Java.deoptimizeEverything()
: forces the VM to execute everything with its interpreter. Necessary to prevent optimizations from bypassing method hooks in some cases, and allows ART’s Instrumentation APIs to be used for tracing the runtime. -
Java.deoptimizeBootImage()
: similar to Java.deoptimizeEverything() but only deoptimizes boot image code. Use withdalvik.vm.dex2oat-flags --inline-max-code-units=0
for best results. -
Java.vm
: object with the following methods:-
perform(fn)
: ensures that the current thread is attached to the VM and callsfn
. (This isn’t necessary in callbacks from Java.) -
getEnv()
: gets a wrapper for the current thread’sJNIEnv
. Throws an exception if the current thread is not attached to the VM. -
tryGetEnv()
: tries to get a wrapper for the current thread’sJNIEnv
. Returnsnull
if the current thread is not attached to the VM.
-
-
Java.classFactory
: the default class factory used to implement e.g.Java.use()
. Uses the application’s main class loader. -
Java.ClassFactory
: class with the following properties:-
get(classLoader)
: Gets the class factory instance for a given class loader. The default class factory used behind the scenes only interacts with the application’s main class loader. Other class loaders can be discovered throughJava.enumerateClassLoaders()
and interacted with through this API. -
loader
: read-only property providing a wrapper for the class loader currently being used. For the default class factory this is updated by the first call toJava.perform()
. -
cacheDir
: string containing path to cache directory currently being used. For the default class factory this is updated by the first call toJava.perform()
. -
tempFileNaming
: object specifying naming convention to use for temporary files. Defaults to{ prefix: 'frida', suffix: 'dat' }
. -
use(className)
: likeJava.use()
but for a specific class loader. -
openClassFile(filePath)
: likeJava.openClassFile()
but for a specific class loader. -
choose(className, callbacks)
: likeJava.choose()
but for a specific class loader. -
retain(obj)
: likeJava.retain()
but for a specific class loader. -
cast(handle, klass)
: likeJava.cast()
but for a specific class loader. -
array(type, elements)
: likeJava.array()
but for a specific class loader. -
registerClass(spec)
: likeJava.registerClass()
but for a specific class loader.
-
CPU Instruction
Instruction
-
Instruction.parse(target)
: parse the instruction at thetarget
address in memory, represented by aNativePointer
. Note that on 32-bit ARM this address must have its least significant bit set to 0 for ARM functions, and 1 for Thumb functions. Frida takes care of this detail for you if you get the address from a Frida API (for exampleModule.getExportByName()
).The object returned has the fields:
address
: address (EIP) of this instruction, as aNativePointer
next
: pointer to the next instruction, so you canparse()
itsize
: size of this instructionmnemonic
: string representation of instruction mnemonicopStr
: string representation of instruction operandsoperands
: array of objects describing each operand, each specifying thetype
andvalue
, at a minimum, but potentially also additional properties depending on the architectureregsRead
: array of register names implicitly read by this instructionregsWritten
: array of register names implicitly written to by this instructiongroups
: array of group names that this instruction belongs totoString()
: convert to a human-readable string
For details about
operands
andgroups
, please consult the Capstone documentation for your architecture.
X86Writer
-
new X86Writer(codeAddress[, { pc: ptr('0x1234') }])
: create a new code writer for generating x86 machine code written directly to memory atcodeAddress
, specified as a NativePointer. The second argument is an optional options object where the initial program counter may be specified, which is useful when generating code to a scratch buffer. This is essential when usingMemory.patchCode()
on iOS, which may provide you with a temporary location that later gets mapped into memory at the intended memory location. -
reset(codeAddress[, { pc: ptr('0x1234') }])
: recycle instance -
dispose()
: eagerly clean up memory -
flush()
: resolve label references and write pending data to memory. You should always call this once you’ve finished generating code. It is usually also desirable to do this between pieces of unrelated code, e.g. when generating multiple functions in one go. -
base
: memory location of the first byte of output, as a NativePointer -
code
: memory location of the next byte of output, as a NativePointer -
pc
: program counter at the next byte of output, as a NativePointer -
offset
: current offset as a JavaScript Number -
putLabel(id)
: put a label at the current position, whereid
is a string that may be referenced in past and futureput*Label()
calls -
putCallAddressWithArguments(func, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putCallAddressWithAlignedArguments(func, args)
: like above, but also ensures that the argument list is aligned on a 16 byte boundary -
putCallRegWithArguments(reg, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putCallRegWithAlignedArguments(reg, args)
: like above, but also ensures that the argument list is aligned on a 16 byte boundary -
putCallRegOffsetPtrWithArguments(reg, offset, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putCallAddress(address)
: put a CALL instruction -
putCallReg(reg)
: put a CALL instruction -
putCallRegOffsetPtr(reg, offset)
: put a CALL instruction -
putCallIndirect(addr)
: put a CALL instruction -
putCallIndirectLabel(labelId)
: put a CALL instruction referencinglabelId
, defined by a past or futureputLabel()
-
putCallNearLabel(labelId)
: put a CALL instruction referencinglabelId
, defined by a past or futureputLabel()
-
putLeave()
: put a LEAVE instruction -
putRet()
: put a RET instruction -
putRetImm(immValue)
: put a RET instruction -
putJmpAddress(address)
: put a JMP instruction -
putJmpShortLabel(labelId)
: put a JMP instruction referencinglabelId
, defined by a past or futureputLabel()
-
putJmpNearLabel(labelId)
: put a JMP instruction referencinglabelId
, defined by a past or futureputLabel()
-
putJmpReg(reg)
: put a JMP instruction -
putJmpRegPtr(reg)
: put a JMP instruction -
putJmpRegOffsetPtr(reg, offset)
: put a JMP instruction -
putJmpNearPtr(address)
: put a JMP instruction -
putJccShort(instructionId, target, hint)
: put a JCC instruction -
putJccNear(instructionId, target, hint)
: put a JCC instruction -
putJccShortLabel(instructionId, labelId, hint)
: put a JCC instruction referencinglabelId
, defined by a past or futureputLabel()
-
putJccNearLabel(instructionId, labelId, hint)
: put a JCC instruction referencinglabelId
, defined by a past or futureputLabel()
-
putAddRegImm(reg, immValue)
: put an ADD instruction -
putAddRegReg(dstReg, srcReg)
: put an ADD instruction -
putAddRegNearPtr(dstReg, srcAddress)
: put an ADD instruction -
putSubRegImm(reg, immValue)
: put a SUB instruction -
putSubRegReg(dstReg, srcReg)
: put a SUB instruction -
putSubRegNearPtr(dstReg, srcAddress)
: put a SUB instruction -
putIncReg(reg)
: put an INC instruction -
putDecReg(reg)
: put a DEC instruction -
putIncRegPtr(target, reg)
: put an INC instruction -
putDecRegPtr(target, reg)
: put a DEC instruction -
putLockXaddRegPtrReg(dstReg, srcReg)
: put a LOCK XADD instruction -
putLockCmpxchgRegPtrReg(dstReg, srcReg)
: put a LOCK CMPXCHG instruction -
putLockIncImm32Ptr(target)
: put a LOCK INC IMM32 instruction -
putLockDecImm32Ptr(target)
: put a LOCK DEC IMM32 instruction -
putAndRegReg(dstReg, srcReg)
: put an AND instruction -
putAndRegU32(reg, immValue)
: put an AND instruction -
putShlRegU8(reg, immValue)
: put a SHL instruction -
putShrRegU8(reg, immValue)
: put a SHR instruction -
putXorRegReg(dstReg, srcReg)
: put an XOR instruction -
putMovRegReg(dstReg, srcReg)
: put a MOV instruction -
putMovRegU32(dstReg, immValue)
: put a MOV instruction -
putMovRegU64(dstReg, immValue)
: put a MOV instruction -
putMovRegAddress(dstReg, address)
: put a MOV instruction -
putMovRegPtrU32(dstReg, immValue)
: put a MOV instruction -
putMovRegOffsetPtrU32(dstReg, dstOffset, immValue)
: put a MOV instruction -
putMovRegPtrReg(dstReg, srcReg)
: put a MOV instruction -
putMovRegOffsetPtrReg(dstReg, dstOffset, srcReg)
: put a MOV instruction -
putMovRegRegPtr(dstReg, srcReg)
: put a MOV instruction -
putMovRegRegOffsetPtr(dstReg, srcReg, srcOffset)
: put a MOV instruction -
putMovRegBaseIndexScaleOffsetPtr(dstReg, baseReg, indexReg, scale, offset)
: put a MOV instruction -
putMovRegNearPtr(dstReg, srcAddress)
: put a MOV instruction -
putMovNearPtrReg(dstAddress, srcReg)
: put a MOV instruction -
putMovFsU32PtrReg(fsOffset, srcReg)
: put a MOV FS instruction -
putMovRegFsU32Ptr(dstReg, fsOffset)
: put a MOV FS instruction -
putMovFsRegPtrReg(fsOffset, srcReg)
: put a MOV FS instruction -
putMovRegFsRegPtr(dstReg, fsOffset)
: put a MOV FS instruction -
putMovGsU32PtrReg(fsOffset, srcReg)
: put a MOV GS instruction -
putMovRegGsU32Ptr(dstReg, fsOffset)
: put a MOV GS instruction -
putMovGsRegPtrReg(gsOffset, srcReg)
: put a MOV GS instruction -
putMovRegGsRegPtr(dstReg, gsOffset)
: put a MOV GS instruction -
putMovqXmm0EspOffsetPtr(offset)
: put a MOVQ XMM0 ESP instruction -
putMovqEaxOffsetPtrXmm0(offset)
: put a MOVQ EAX XMM0 instruction -
putMovdquXmm0EspOffsetPtr(offset)
: put a MOVDQU XMM0 ESP instruction -
putMovdquEaxOffsetPtrXmm0(offset)
: put a MOVDQU EAX XMM0 instruction -
putLeaRegRegOffset(dstReg, srcReg, srcOffset)
: put a LEA instruction -
putXchgRegRegPtr(leftReg, rightReg)
: put an XCHG instruction -
putPushU32(immValue)
: put a PUSH instruction -
putPushNearPtr(address)
: put a PUSH instruction -
putPushReg(reg)
: put a PUSH instruction -
putPopReg(reg)
: put a POP instruction -
putPushImmPtr(immPtr)
: put a PUSH instruction -
putPushax()
: put a PUSHAX instruction -
putPopax()
: put a POPAX instruction -
putPushfx()
: put a PUSHFX instruction -
putPopfx()
: put a POPFX instruction -
putSahf()
: put a SAHF instruction -
putLahf()
: put a LAHF instruction -
putTestRegReg(regA, regB)
: put a TEST instruction -
putTestRegU32(reg, immValue)
: put a TEST instruction -
putCmpRegI32(reg, immValue)
: put a CMP instruction -
putCmpRegOffsetPtrReg(regA, offset, regB)
: put a CMP instruction -
putCmpImmPtrImmU32(immPtr, immValue)
: put a CMP instruction -
putCmpRegReg(regA, regB)
: put a CMP instruction -
putClc()
: put a CLC instruction -
putStc()
: put a STC instruction -
putCld()
: put a CLD instruction -
putStd()
: put a STD instruction -
putCpuid()
: put a CPUID instruction -
putLfence()
: put an LFENCE instruction -
putRdtsc()
: put an RDTSC instruction -
putPause()
: put a PAUSE instruction -
putNop()
: put a NOP instruction -
putBreakpoint()
: put an OS/architecture-specific breakpoint instruction -
putPadding(n)
: putn
guard instruction -
putNopPadding(n)
: putn
NOP instructions -
putFxsaveRegPtr(reg)
: put a FXSAVE instruction -
putFxrstorRegPtr(reg)
: put a FXRSTOR instruction -
putU8(value)
: put a uint8 -
putS8(value)
: put an int8 -
putBytes(data)
: put raw data from the provided ArrayBuffer
X86Relocator
-
new X86Relocator(inputCode, output)
: create a new code relocator for copying x86 instructions from one memory location to another, taking care to adjust position-dependent instructions accordingly. The source address is specified byinputCode
, a NativePointer. The destination is given byoutput
, an X86Writer pointed at the desired target memory address. -
reset(inputCode, output)
: recycle instance -
dispose()
: eagerly clean up memory -
input
: latest Instruction read so far. Starts outnull
and changes on every call toreadOne()
. -
eob
: boolean indicating whether end-of-block has been reached, i.e. we’ve reached a branch of any kind, like CALL, JMP, BL, RET. -
eoi
: boolean indicating whether end-of-input has been reached, e.g. we’ve reached JMP/B/RET, an instruction after which there may or may not be valid code. -
readOne()
: read the next instruction into the relocator’s internal buffer and return the number of bytes read so far, including previous calls. You may keep calling this method to keep buffering, or immediately call eitherwriteOne()
orskipOne()
. Or, you can buffer up until the desired point and then callwriteAll()
. Returns zero when end-of-input is reached, which means theeoi
property is nowtrue
. -
peekNextWriteInsn()
: peek at the next Instruction to be written or skipped -
peekNextWriteSource()
: peek at the address of the next instruction to be written or skipped -
skipOne()
: skip the instruction that would have been written next -
skipOneNoLabel()
: skip the instruction that would have been written next, but without a label for internal use. This breaks relocation of branches to locations inside the relocated range, and is an optimization for use-cases where all branches are rewritten (e.g. Frida’s Stalker). -
writeOne()
: write the next buffered instruction -
writeOneNoLabel()
: write the next buffered instruction, but without a label for internal use. This breaks relocation of branches to locations inside the relocated range, and is an optimization for use-cases where all branches are rewritten (e.g. Frida’s Stalker). -
writeAll()
: write all buffered instructions
x86 enum types
- Register:
xax
xcx
xdx
xbx
xsp
xbp
xsi
xdi
eax
ecx
edx
ebx
esp
ebp
esi
edi
rax
rcx
rdx
rbx
rsp
rbp
rsi
rdi
r8
r9
r10
r11
r12
r13
r14
r15
r8d
r9d
r10d
r11d
r12d
r13d
r14d
r15d
xip
eip
rip
- InstructionId:
jo
jno
jb
jae
je
jne
jbe
ja
js
jns
jp
jnp
jl
jge
jle
jg
jcxz
jecxz
jrcxz
- BranchHint:
no-hint
likely
unlikely
- PointerTarget:
byte
dword
qword
ArmWriter
-
new ArmWriter(codeAddress[, { pc: ptr('0x1234') }])
: create a new code writer for generating ARM machine code written directly to memory atcodeAddress
, specified as a NativePointer. The second argument is an optional options object where the initial program counter may be specified, which is useful when generating code to a scratch buffer. This is essential when usingMemory.patchCode()
on iOS, which may provide you with a temporary location that later gets mapped into memory at the intended memory location. -
reset(codeAddress[, { pc: ptr('0x1234') }])
: recycle instance -
dispose()
: eagerly clean up memory -
flush()
: resolve label references and write pending data to memory. You should always call this once you’ve finished generating code. It is usually also desirable to do this between pieces of unrelated code, e.g. when generating multiple functions in one go. -
base
: memory location of the first byte of output, as a NativePointer -
code
: memory location of the next byte of output, as a NativePointer -
pc
: program counter at the next byte of output, as a NativePointer -
offset
: current offset as a JavaScript Number -
skip(nBytes)
: skipnBytes
-
putLabel(id)
: put a label at the current position, whereid
is a string that may be referenced in past and futureput*Label()
calls -
putCallAddressWithArguments(func, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putCallReg(reg)
: put a CALL instruction -
putCallRegWithArguments(reg, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putBranchAddress(address)
: put code needed for branching/jumping to the given address -
canBranchDirectlyBetween(from, to)
: determine whether a direct branch is possible between the two given memory locations -
putBImm(target)
: put a B instruction -
putBCondImm(cc, target)
: put a B COND instruction -
putBLabel(labelId)
: put a B instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBCondLabel(cc, labelId)
: put a B COND instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBlImm(target)
: put a BL instruction -
putBlxImm(target)
: put a BLX instruction -
putBlLabel(labelId)
: put a BL instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBxReg(reg)
: put a BX instruction -
putBlReg(reg)
: put a BL instruction -
putBlxReg(reg)
: put a BLX instruction -
putRet()
: put a RET instruction -
putVpushRange(firstReg, lastReg)
: put a VPUSH RANGE instruction -
putVpopRange(firstReg, lastReg)
: put a VPOP RANGE instruction -
putLdrRegAddress(reg, address)
: put an LDR instruction -
putLdrRegU32(reg, val)
: put an LDR instruction -
putLdrRegReg(dstReg, srcReg)
: put an LDR instruction -
putLdrRegRegOffset(dstReg, srcReg, srcOffset)
: put an LDR instruction -
putLdrCondRegRegOffset(cc, dstReg, srcReg, srcOffset)
: put an LDR COND instruction -
putLdmiaRegMask(reg, mask)
: put an LDMIA MASK instruction -
putLdmiaRegMaskWb(reg, mask)
: put an LDMIA MASK WB instruction -
putStrRegReg(srcReg, dstReg)
: put a STR instruction -
putStrRegRegOffset(srcReg, dstReg, dstOffset)
: put a STR instruction -
putStrCondRegRegOffset(cc, srcReg, dstReg, dstOffset)
: put a STR COND instruction -
putMovRegReg(dstReg, srcReg)
: put a MOV instruction -
putMovRegRegShift(dstReg, srcReg, shift, shiftValue)
: put a MOV SHIFT instruction -
putMovRegCpsr(reg)
: put a MOV CPSR instruction -
putMovCpsrReg(reg)
: put a MOV CPSR instruction -
putAddRegU16(dstReg, val)
: put an ADD U16 instruction -
putAddRegU32(dstReg, val)
: put an ADD instruction -
putAddRegRegImm(dstReg, srcReg, immVal)
: put an ADD instruction -
putAddRegRegReg(dstReg, srcReg1, srcReg2)
: put an ADD instruction -
putAddRegRegRegShift(dstReg, srcReg1, srcReg2, shift, shiftValue)
: put an ADD SHIFT instruction -
putSubRegU16(dstReg, val)
: put a SUB U16 instruction -
putSubRegU32(dstReg, val)
: put a SUB instruction -
putSubRegRegImm(dstReg, srcReg, immVal)
: put a SUB instruction -
putSubRegRegReg(dstReg, srcReg1, srcReg2)
: put a SUB instruction -
putRsbRegRegImm(dstReg, srcReg, immVal)
: put a RSB instruction -
putAndsRegRegImm(dstReg, srcReg, immVal)
: put an ANDS instruction -
putCmpRegImm(dstReg, immVal)
: put a CMP instruction -
putNop()
: put a NOP instruction -
putBreakpoint()
: put an OS/architecture-specific breakpoint instruction -
putBrkImm(imm)
: put a BRK instruction -
putInstruction(insn)
: put a raw instruction as a JavaScript Number -
putBytes(data)
: put raw data from the provided ArrayBuffer
ArmRelocator
-
new ArmRelocator(inputCode, output)
: create a new code relocator for copying ARM instructions from one memory location to another, taking care to adjust position-dependent instructions accordingly. The source address is specified byinputCode
, a NativePointer. The destination is given byoutput
, an ArmWriter pointed at the desired target memory address. -
reset(inputCode, output)
: recycle instance -
dispose()
: eagerly clean up memory -
input
: latest Instruction read so far. Starts outnull
and changes on every call toreadOne()
. -
eob
: boolean indicating whether end-of-block has been reached, i.e. we’ve reached a branch of any kind, like CALL, JMP, BL, RET. -
eoi
: boolean indicating whether end-of-input has been reached, e.g. we’ve reached JMP/B/RET, an instruction after which there may or may not be valid code. -
readOne()
: read the next instruction into the relocator’s internal buffer and return the number of bytes read so far, including previous calls. You may keep calling this method to keep buffering, or immediately call eitherwriteOne()
orskipOne()
. Or, you can buffer up until the desired point and then callwriteAll()
. Returns zero when end-of-input is reached, which means theeoi
property is nowtrue
. -
peekNextWriteInsn()
: peek at the next Instruction to be written or skipped -
peekNextWriteSource()
: peek at the address of the next instruction to be written or skipped -
skipOne()
: skip the instruction that would have been written next -
writeOne()
: write the next buffered instruction -
writeAll()
: write all buffered instructions
ThumbWriter
-
new ThumbWriter(codeAddress[, { pc: ptr('0x1234') }])
: create a new code writer for generating ARM machine code written directly to memory atcodeAddress
, specified as a NativePointer. The second argument is an optional options object where the initial program counter may be specified, which is useful when generating code to a scratch buffer. This is essential when usingMemory.patchCode()
on iOS, which may provide you with a temporary location that later gets mapped into memory at the intended memory location. -
reset(codeAddress[, { pc: ptr('0x1234') }])
: recycle instance -
dispose()
: eagerly clean up memory -
flush()
: resolve label references and write pending data to memory. You should always call this once you’ve finished generating code. It is usually also desirable to do this between pieces of unrelated code, e.g. when generating multiple functions in one go. -
base
: memory location of the first byte of output, as a NativePointer -
code
: memory location of the next byte of output, as a NativePointer -
pc
: program counter at the next byte of output, as a NativePointer -
offset
: current offset as a JavaScript Number -
skip(nBytes)
: skipnBytes
-
putLabel(id)
: put a label at the current position, whereid
is a string that may be referenced in past and futureput*Label()
calls -
commitLabel(id)
: commit the first pending reference to the given label, returningtrue
on success. Returnsfalse
if the given label hasn’t been defined yet, or there are no more pending references to it. -
putCallAddressWithArguments(func, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putCallRegWithArguments(reg, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putBranchAddress(address)
: put code needed for branching/jumping to the given address -
canBranchDirectlyBetween(from, to)
: determine whether a direct branch is possible between the two given memory locations -
putBImm(target)
: put a B instruction -
putBLabel(labelId)
: put a B instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBLabelWide(labelId)
: put a B WIDE instruction -
putBxReg(reg)
: put a BX instruction -
putBlImm(target)
: put a BL instruction -
putBlLabel(labelId)
: put a BL instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBlxImm(target)
: put a BLX instruction -
putBlxReg(reg)
: put a BLX instruction -
putCmpRegImm(reg, immValue)
: put a CMP instruction -
putBeqLabel(labelId)
: put a BEQ instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBneLabel(labelId)
: put a BNE instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBCondLabel(cc, labelId)
: put a B COND instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBCondLabelWide(cc, labelId)
: put a B COND WIDE instruction -
putCbzRegLabel(reg, labelId)
: put a CBZ instruction referencinglabelId
, defined by a past or futureputLabel()
-
putCbnzRegLabel(reg, labelId)
: put a CBNZ instruction referencinglabelId
, defined by a past or futureputLabel()
-
putPushRegs(regs)
: put a PUSH instruction with the specified registers, specified as a JavaScript array where each element is a string specifying the register name. -
putPopRegs(regs)
: put a POP instruction with the specified registers, specified as a JavaScript array where each element is a string specifying the register name. -
putVpushRange(firstReg, lastReg)
: put a VPUSH RANGE instruction -
putVpopRange(firstReg, lastReg)
: put a VPOP RANGE instruction -
putLdrRegAddress(reg, address)
: put an LDR instruction -
putLdrRegU32(reg, val)
: put an LDR instruction -
putLdrRegReg(dstReg, srcReg)
: put an LDR instruction -
putLdrRegRegOffset(dstReg, srcReg, srcOffset)
: put an LDR instruction -
putLdrbRegReg(dstReg, srcReg)
: put an LDRB instruction -
putVldrRegRegOffset(dstReg, srcReg, srcOffset)
: put a VLDR instruction -
putLdmiaRegMask(reg, mask)
: put an LDMIA MASK instruction -
putStrRegReg(srcReg, dstReg)
: put a STR instruction -
putStrRegRegOffset(srcReg, dstReg, dstOffset)
: put a STR instruction -
putMovRegReg(dstReg, srcReg)
: put a MOV instruction -
putMovRegU8(dstReg, immValue)
: put a MOV instruction -
putMovRegCpsr(reg)
: put a MOV CPSR instruction -
putMovCpsrReg(reg)
: put a MOV CPSR instruction -
putAddRegImm(dstReg, immValue)
: put an ADD instruction -
putAddRegReg(dstReg, srcReg)
: put an ADD instruction -
putAddRegRegReg(dstReg, leftReg, rightReg)
: put an ADD instruction -
putAddRegRegImm(dstReg, leftReg, rightValue)
: put an ADD instruction -
putSubRegImm(dstReg, immValue)
: put a SUB instruction -
putSubRegReg(dstReg, srcReg)
: put a SUB instruction -
putSubRegRegReg(dstReg, leftReg, rightReg)
: put a SUB instruction -
putSubRegRegImm(dstReg, leftReg, rightValue)
: put a SUB instruction -
putAndRegRegImm(dstReg, leftReg, rightValue)
: put an AND instruction -
putOrRegRegImm(dstReg, leftReg, rightValue)
: put an OR instruction -
putLslRegRegImm(dstReg, leftReg, rightValue)
: put a LSL instruction -
putLslsRegRegImm(dstReg, leftReg, rightValue)
: put a LSLS instruction -
putLsrsRegRegImm(dstReg, leftReg, rightValue)
: put a LSRS instruction -
putMrsRegReg(dstReg, srcReg)
: put a MRS instruction -
putMsrRegReg(dstReg, srcReg)
: put a MSR instruction -
putNop()
: put a NOP instruction -
putBkptImm(imm)
: put a BKPT instruction -
putBreakpoint()
: put an OS/architecture-specific breakpoint instruction -
putInstruction(insn)
: put a raw instruction as a JavaScript Number -
putInstructionWide(upper, lower)
: put a raw Thumb-2 instruction from two JavaScript Number values -
putBytes(data)
: put raw data from the provided ArrayBuffer
ThumbRelocator
-
new ThumbRelocator(inputCode, output)
: create a new code relocator for copying ARM instructions from one memory location to another, taking care to adjust position-dependent instructions accordingly. The source address is specified byinputCode
, a NativePointer. The destination is given byoutput
, a ThumbWriter pointed at the desired target memory address. -
reset(inputCode, output)
: recycle instance -
dispose()
: eagerly clean up memory -
input
: latest Instruction read so far. Starts outnull
and changes on every call toreadOne()
. -
eob
: boolean indicating whether end-of-block has been reached, i.e. we’ve reached a branch of any kind, like CALL, JMP, BL, RET. -
eoi
: boolean indicating whether end-of-input has been reached, e.g. we’ve reached JMP/B/RET, an instruction after which there may or may not be valid code. -
readOne()
: read the next instruction into the relocator’s internal buffer and return the number of bytes read so far, including previous calls. You may keep calling this method to keep buffering, or immediately call eitherwriteOne()
orskipOne()
. Or, you can buffer up until the desired point and then callwriteAll()
. Returns zero when end-of-input is reached, which means theeoi
property is nowtrue
. -
peekNextWriteInsn()
: peek at the next Instruction to be written or skipped -
peekNextWriteSource()
: peek at the address of the next instruction to be written or skipped -
skipOne()
: skip the instruction that would have been written next -
writeOne()
: write the next buffered instruction -
copyOne()
: copy out the next buffered instruction without advancing the output cursor, allowing the same instruction to be written out multiple times -
writeAll()
: write all buffered instructions
ARM enum types
- Register:
r0
r1
r2
r3
r4
r5
r6
r7
r8
r9
r10
r11
r12
r13
r14
r15
sp
lr
sb
sl
fp
ip
pc
s0
s1
s2
s3
s4
s5
s6
s7
s8
s9
s10
s11
s12
s13
s14
s15
s16
s17
s18
s19
s20
s21
s22
s23
s24
s25
s26
s27
s28
s29
s30
s31
d0
d1
d2
d3
d4
d5
d6
d7
d8
d9
d10
d11
d12
d13
d14
d15
d16
d17
d18
d19
d20
d21
d22
d23
d24
d25
d26
d27
d28
d29
d30
d31
q0
q1
q2
q3
q4
q5
q6
q7
q8
q9
q10
q11
q12
q13
q14
q15
- SystemRegister:
apsr-nzcvq
- ConditionCode:
eq
ne
hs
lo
mi
pl
vs
vc
hi
ls
ge
lt
gt
le
al
- Shifter:
asr
lsl
lsr
ror
rrx
asr-reg
lsl-reg
lsr-reg
ror-reg
rrx-reg
Arm64Writer
-
new Arm64Writer(codeAddress[, { pc: ptr('0x1234') }])
: create a new code writer for generating AArch64 machine code written directly to memory atcodeAddress
, specified as a NativePointer. The second argument is an optional options object where the initial program counter may be specified, which is useful when generating code to a scratch buffer. This is essential when usingMemory.patchCode()
on iOS, which may provide you with a temporary location that later gets mapped into memory at the intended memory location. -
reset(codeAddress[, { pc: ptr('0x1234') }])
: recycle instance -
dispose()
: eagerly clean up memory -
flush()
: resolve label references and write pending data to memory. You should always call this once you’ve finished generating code. It is usually also desirable to do this between pieces of unrelated code, e.g. when generating multiple functions in one go. -
base
: memory location of the first byte of output, as a NativePointer -
code
: memory location of the next byte of output, as a NativePointer -
pc
: program counter at the next byte of output, as a NativePointer -
offset
: current offset as a JavaScript Number -
skip(nBytes)
: skipnBytes
-
putLabel(id)
: put a label at the current position, whereid
is a string that may be referenced in past and futureput*Label()
calls -
putCallAddressWithArguments(func, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putCallRegWithArguments(reg, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putBranchAddress(address)
: put code needed for branching/jumping to the given address -
canBranchDirectlyBetween(from, to)
: determine whether a direct branch is possible between the two given memory locations -
putBImm(address)
: put a B instruction -
putBLabel(labelId)
: put a B instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBCondLabel(cc, labelId)
: put a B COND instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBlImm(address)
: put a BL instruction -
putBlLabel(labelId)
: put a BL instruction referencinglabelId
, defined by a past or futureputLabel()
-
putBrReg(reg)
: put a BR instruction -
putBrRegNoAuth(reg)
: put a BR instruction expecting a raw pointer without any authentication bits -
putBlrReg(reg)
: put a BLR instruction -
putBlrRegNoAuth(reg)
: put a BLR instruction expecting a raw pointer without any authentication bits -
putRet()
: put a RET instruction -
putRetReg(reg)
: put a RET instruction -
putCbzRegImm(reg, target)
: put a CBZ instruction -
putCbnzRegImm(reg, target)
: put a CBNZ instruction -
putCbzRegLabel(reg, labelId)
: put a CBZ instruction referencinglabelId
, defined by a past or futureputLabel()
-
putCbnzRegLabel(reg, labelId)
: put a CBNZ instruction referencinglabelId
, defined by a past or futureputLabel()
-
putTbzRegImmImm(reg, bit, target)
: put a TBZ instruction -
putTbnzRegImmImm(reg, bit, target)
: put a TBNZ instruction -
putTbzRegImmLabel(reg, bit, labelId)
: put a TBZ instruction referencinglabelId
, defined by a past or futureputLabel()
-
putTbnzRegImmLabel(reg, bit, labelId)
: put a TBNZ instruction referencinglabelId
, defined by a past or futureputLabel()
-
putPushRegReg(regA, regB)
: put a PUSH instruction -
putPopRegReg(regA, regB)
: put a POP instruction -
putPushAllXRegisters()
: put code needed for pushing all X registers on the stack -
putPopAllXRegisters()
: put code needed for popping all X registers off the stack -
putPushAllQRegisters()
: put code needed for pushing all Q registers on the stack -
putPopAllQRegisters()
: put code needed for popping all Q registers off the stack -
putLdrRegAddress(reg, address)
: put an LDR instruction -
putLdrRegU32(reg, val)
: put an LDR instruction -
putLdrRegU64(reg, val)
: put an LDR instruction -
putLdrRegU32Ptr(reg, srcAddress)
: put an LDR instruction -
putLdrRegU64Ptr(reg, srcAddress)
: put an LDR instruction -
putLdrRegRef(reg)
: put an LDR instruction with a dangling data reference, returning an opaque ref value that should be passed toputLdrRegValue()
at the desired location -
putLdrRegValue(ref, value)
: put the value and update the LDR instruction from a previousputLdrRegRef()
-
putLdrRegReg(dstReg, srcReg)
: put an LDR instruction -
putLdrRegRegOffset(dstReg, srcReg, srcOffset)
: put an LDR instruction -
putLdrRegRegOffsetMode(dstReg, srcReg, srcOffset, mode)
: put an LDR MODE instruction -
putLdrswRegRegOffset(dstReg, srcReg, srcOffset)
: put an LDRSW instruction -
putAdrpRegAddress(reg, address)
: put an ADRP instruction -
putStrRegReg(srcReg, dstReg)
: put a STR instruction -
putStrRegRegOffset(srcReg, dstReg, dstOffset)
: put a STR instruction -
putStrRegRegOffsetMode(srcReg, dstReg, dstOffset, mode)
: put a STR MODE instruction -
putLdpRegRegRegOffset(regA, regB, regSrc, srcOffset, mode)
: put an LDP instruction -
putStpRegRegRegOffset(regA, regB, regDst, dstOffset, mode)
: put a STP instruction -
putMovRegReg(dstReg, srcReg)
: put a MOV instruction -
putMovRegNzcv(reg)
: put a MOV NZCV instruction -
putMovNzcvReg(reg)
: put a MOV NZCV instruction -
putUxtwRegReg(dstReg, srcReg)
: put an UXTW instruction -
putAddRegRegImm(dstReg, leftReg, rightValue)
: put an ADD instruction -
putAddRegRegReg(dstReg, leftReg, rightReg)
: put an ADD instruction -
putSubRegRegImm(dstReg, leftReg, rightValue)
: put a SUB instruction -
putSubRegRegReg(dstReg, leftReg, rightReg)
: put a SUB instruction -
putAndRegRegImm(dstReg, leftReg, rightValue)
: put an AND instruction -
putEorRegRegReg(dstReg, leftReg, rightReg)
: put an EOR instruction -
putUbfm(dstReg, srcReg, imms, immr)
: put an UBFM instruction -
putLslRegImm(dstReg, srcReg, shift)
: put a LSL instruction -
putLsrRegImm(dstReg, srcReg, shift)
: put a LSR instruction -
putTstRegImm(reg, immValue)
: put a TST instruction -
putCmpRegReg(regA, regB)
: put a CMP instruction -
putXpaciReg(reg)
: put an XPACI instruction -
putNop()
: put a NOP instruction -
putBrkImm(imm)
: put a BRK instruction -
putMrs(dstReg, systemReg)
: put a MRS instruction -
putInstruction(insn)
: put a raw instruction as a JavaScript Number -
putBytes(data)
: put raw data from the provided ArrayBuffer -
sign(value)
: sign the given pointer value
Arm64Relocator
-
new Arm64Relocator(inputCode, output)
: create a new code relocator for copying AArch64 instructions from one memory location to another, taking care to adjust position-dependent instructions accordingly. The source address is specified byinputCode
, a NativePointer. The destination is given byoutput
, an Arm64Writer pointed at the desired target memory address. -
reset(inputCode, output)
: recycle instance -
dispose()
: eagerly clean up memory -
input
: latest Instruction read so far. Starts outnull
and changes on every call toreadOne()
. -
eob
: boolean indicating whether end-of-block has been reached, i.e. we’ve reached a branch of any kind, like CALL, JMP, BL, RET. -
eoi
: boolean indicating whether end-of-input has been reached, e.g. we’ve reached JMP/B/RET, an instruction after which there may or may not be valid code. -
readOne()
: read the next instruction into the relocator’s internal buffer and return the number of bytes read so far, including previous calls. You may keep calling this method to keep buffering, or immediately call eitherwriteOne()
orskipOne()
. Or, you can buffer up until the desired point and then callwriteAll()
. Returns zero when end-of-input is reached, which means theeoi
property is nowtrue
. -
peekNextWriteInsn()
: peek at the next Instruction to be written or skipped -
peekNextWriteSource()
: peek at the address of the next instruction to be written or skipped -
skipOne()
: skip the instruction that would have been written next -
writeOne()
: write the next buffered instruction -
writeAll()
: write all buffered instructions
AArch64 enum types
- Register:
x0
x1
x2
x3
x4
x5
x6
x7
x8
x9
x10
x11
x12
x13
x14
x15
x16
x17
x18
x19
x20
x21
x22
x23
x24
x25
x26
x27
x28
x29
x30
w0
w1
w2
w3
w4
w5
w6
w7
w8
w9
w10
w11
w12
w13
w14
w15
w16
w17
w18
w19
w20
w21
w22
w23
w24
w25
w26
w27
w28
w29
w30
sp
lr
fp
wsp
wzr
xzr
nzcv
ip0
ip1
s0
s1
s2
s3
s4
s5
s6
s7
s8
s9
s10
s11
s12
s13
s14
s15
s16
s17
s18
s19
s20
s21
s22
s23
s24
s25
s26
s27
s28
s29
s30
s31
d0
d1
d2
d3
d4
d5
d6
d7
d8
d9
d10
d11
d12
d13
d14
d15
d16
d17
d18
d19
d20
d21
d22
d23
d24
d25
d26
d27
d28
d29
d30
d31
q0
q1
q2
q3
q4
q5
q6
q7
q8
q9
q10
q11
q12
q13
q14
q15
q16
q17
q18
q19
q20
q21
q22
q23
q24
q25
q26
q27
q28
q29
q30
q31
- ConditionCode:
eq
ne
hs
lo
mi
pl
vs
vc
hi
ls
ge
lt
gt
le
al
nv
- IndexMode:
post-adjust
signed-offset
pre-adjust
MipsWriter
-
new MipsWriter(codeAddress[, { pc: ptr('0x1234') }])
: create a new code writer for generating MIPS machine code written directly to memory atcodeAddress
, specified as a NativePointer. The second argument is an optional options object where the initial program counter may be specified, which is useful when generating code to a scratch buffer. This is essential when usingMemory.patchCode()
on iOS, which may provide you with a temporary location that later gets mapped into memory at the intended memory location. -
reset(codeAddress[, { pc: ptr('0x1234') }])
: recycle instance -
dispose()
: eagerly clean up memory -
flush()
: resolve label references and write pending data to memory. You should always call this once you’ve finished generating code. It is usually also desirable to do this between pieces of unrelated code, e.g. when generating multiple functions in one go. -
base
: memory location of the first byte of output, as a NativePointer -
code
: memory location of the next byte of output, as a NativePointer -
pc
: program counter at the next byte of output, as a NativePointer -
offset
: current offset as a JavaScript Number -
skip(nBytes)
: skipnBytes
-
putLabel(id)
: put a label at the current position, whereid
is a string that may be referenced in past and futureput*Label()
calls -
putCallAddressWithArguments(func, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putCallRegWithArguments(reg, args)
: put code needed for calling a C function with the specifiedargs
, specified as a JavaScript array where each element is either a string specifying the register, or a Number or NativePointer specifying the immediate value. -
putJAddress(address)
: put a J instruction -
putJAddressWithoutNop(address)
: put a J WITHOUT NOP instruction -
putJLabel(labelId)
: put a J instruction referencinglabelId
, defined by a past or futureputLabel()
-
putJrReg(reg)
: put a JR instruction -
putJalAddress(address)
: put a JAL instruction -
putJalrReg(reg)
: put a JALR instruction -
putBOffset(offset)
: put a B instruction -
putBeqRegRegLabel(rightReg, leftReg, labelId)
: put a BEQ instruction referencinglabelId
, defined by a past or futureputLabel()
-
putRet()
: put a RET instruction -
putLaRegAddress(reg, address)
: put a LA instruction -
putLuiRegImm(reg, imm)
: put a LUI instruction -
putDsllRegReg(dstReg, srcReg, amount)
: put a DSLL instruction -
putOriRegRegImm(rt, rs, imm)
: put an ORI instruction -
putLdRegRegOffset(dstReg, srcReg, srcOffset)
: put an LD instruction -
putLwRegRegOffset(dstReg, srcReg, srcOffset)
: put a LW instruction -
putSwRegRegOffset(srcReg, dstReg, dstOffset)
: put a SW instruction -
putMoveRegReg(dstReg, srcReg)
: put a MOVE instruction -
putAdduRegRegReg(dstReg, leftReg, rightReg)
: put an ADDU instruction -
putAddiRegRegImm(dstReg, leftReg, imm)
: put an ADDI instruction -
putAddiRegImm(dstReg, imm)
: put an ADDI instruction -
putSubRegRegImm(dstReg, leftReg, imm)
: put a SUB instruction -
putPushReg(reg)
: put a PUSH instruction -
putPopReg(reg)
: put a POP instruction -
putMfhiReg(reg)
: put a MFHI instruction -
putMfloReg(reg)
: put a MFLO instruction -
putMthiReg(reg)
: put a MTHI instruction -
putMtloReg(reg)
: put a MTLO instruction -
putNop()
: put a NOP instruction -
putBreak()
: put a BREAK instruction -
putPrologueTrampoline(reg, address)
: put a minimal sized trampoline for vectoring to the given address -
putInstruction(insn)
: put a raw instruction as a JavaScript Number -
putBytes(data)
: put raw data from the provided ArrayBuffer
MipsRelocator
-
new MipsRelocator(inputCode, output)
: create a new code relocator for copying MIPS instructions from one memory location to another, taking care to adjust position-dependent instructions accordingly. The source address is specified byinputCode
, a NativePointer. The destination is given byoutput
, a MipsWriter pointed at the desired target memory address. -
reset(inputCode, output)
: recycle instance -
dispose()
: eagerly clean up memory -
input
: latest Instruction read so far. Starts outnull
and changes on every call toreadOne()
. -
eob
: boolean indicating whether end-of-block has been reached, i.e. we’ve reached a branch of any kind, like CALL, JMP, BL, RET. -
eoi
: boolean indicating whether end-of-input has been reached, e.g. we’ve reached JMP/B/RET, an instruction after which there may or may not be valid code. -
readOne()
: read the next instruction into the relocator’s internal buffer and return the number of bytes read so far, including previous calls. You may keep calling this method to keep buffering, or immediately call eitherwriteOne()
orskipOne()
. Or, you can buffer up until the desired point and then callwriteAll()
. Returns zero when end-of-input is reached, which means theeoi
property is nowtrue
. -
peekNextWriteInsn()
: peek at the next Instruction to be written or skipped -
peekNextWriteSource()
: peek at the address of the next instruction to be written or skipped -
skipOne()
: skip the instruction that would have been written next -
writeOne()
: write the next buffered instruction -
writeAll()
: write all buffered instructions
MIPS enum types
- Register:
v0
v1
a0
a1
a2
a3
t0
t1
t2
t3
t4
t5
t6
t7
s0
s1
s2
s3
s4
s5
s6
s7
t8
t9
k0
k1
gp
sp
fp
s8
ra
hi
lo
zero
at
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Others
Console
-
console.log(line)
,console.warn(line)
,console.error(line)
: writeline
to the console of your Frida-based application. The exact behavior depends on where frida-core is integrated. For example, this output goes to stdout or stderr when using Frida through frida-python, qDebug when using frida-qml, etc.Arguments that are ArrayBuffer objects will be substituted by the result of
hexdump()
with default options.
Hexdump
-
hexdump(target[, options])
: generate a hexdump from the provided ArrayBuffer or NativePointertarget
, optionally withoptions
for customizing the output.For example:
Shorthand
-
int64(v)
: short-hand fornew Int64(v)
-
uint64(v)
: short-hand fornew UInt64(v)
-
ptr(s)
: short-hand fornew NativePointer(s)
-
NULL
: short-hand forptr("0")
Communication between host and injected process
-
recv([type, ]callback)
: requestcallback
to be called on the next message received from your Frida-based application. Optionallytype
may be specified to only receive a message where thetype
field is set totype
.The message is passed in the first argument, and in case binary data was passed along with it, the second argument is an ArrayBuffer, otherwise null.
This will only give you one message, so you need to call
recv()
again to receive the next one. -
send(message[, data])
: send the JavaScript objectmessage
to your Frida-based application (it must be serializable to JSON). If you also have some raw binary data that you’d like to send along with it, e.g. you dumped some memory usingNativePointer#readByteArray
, then you may pass this through the optionaldata
argument. This requires it to either be an ArrayBuffer or an array of integers between 0 and 255.Performance considerations
While send() is asynchronous, the total overhead of sending a single message is not optimized for high frequencies, so that means Frida leaves it up to you to batch multiple values into a single send()-call, based on whether low delay or high throughput is desired.
-
rpc.exports
: 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.
For example:
From an application using the Node.js bindings this API would be consumed like this:
The Python version would be very similar:
In the example above we used script.on('message', on_message)
to monitor for
any messages from the injected process, JavaScript side. There are other
notifications that you can watch for as well on both the script
and session
.
If you want to be notified when the target process exits, use
session.on('detached', your_function)
.
Timing events
-
setTimeout(func, delay[, ...parameters])
: callfunc
afterdelay
milliseconds, optionally passing it one or moreparameters
. Returns an id that can be passed toclearTimeout
to cancel it. -
clearTimeout(id)
: cancel id returned by call tosetTimeout
. -
setInterval(func, delay[, ...parameters])
: callfunc
everydelay
milliseconds, optionally passing it one or moreparameters
. Returns an id that can be passed toclearInterval
to cancel it. -
clearInterval(id)
: cancel id returned by call tosetInterval
. -
setImmediate(func[, ...parameters])
: schedulesfunc
to be called on Frida’s JavaScript thread as soon as possible, optionally passing it one or moreparameters
. Returns an id that can be passed toclearImmediate
to cancel it. -
clearImmediate(id)
: cancel id returned by call tosetImmediate
.
Garbage collection
gc()
: force garbage collection. Useful for testing, especially logic involvingScript.bindWeak()
.
Worker
Worker script with its own JavaScript heap, lock, etc.
This is useful to move heavy processing to a background thread, allowing hooks to be handled in a timely manner.
-
new Worker(url[, options])
: creates a new worker, executing the script at the specifiedurl
.The URL is typically retrieved by having the module export its
import.meta.url
, and importing that from the module that creates the worker.If specified,
options
is an object that may contain one or more of the following keys: -
terminate()
: terminates the worker. -
post(message[, data])
: posts a message to the worker. Signature is identical to send(). Use recv() to receive it inside the worker. -
exports
: magic proxy object for calling rpc.exports defined by the worker. Each function returns a Promise, which you may await inside an async function.