Frida bindings

We propose bindings for Frida, the whole C/C++ API is available through them, but they are also backed up by helpers that fluidify script writing.

API bindings

Initialization

_QBDI

Create a new instrumentation virtual machine using “new QBDI()

Returns:QBDI virtual machine instance
Rtype:object

State Management

GPRState.prototype.getRegister(rid)

This function is used to get the value of a specific register.

Arguments:
  • rid – Register (register name or ID can be used e.g : “RAX”, “rax”, 0)
Returns:

GPR value (ex: 0x42)

Return type:

NativePointer

GPRState.prototype.setRegister(rid, value)

This function is used to set the value of a specific register.

Arguments:
  • rid – Register (register name or ID can be used e.g : “RAX”, “rax”, 0)
  • value – Register value (use strings for big integers)
GPRState.prototype.getRegisters()

This function is used to get values of all registers.

Returns:GPRs of current context (ex: {“RAX”:0x42, …})
Return type:{String:rword, …}
GPRState.prototype.setRegisters(gprs)

This function is used to set values of all registers.

Arguments:
  • gprs – Array of register values
GPRState.prototype.synchronizeRegister(FridaCtx, rid, direction)

This function is used to synchronise a specific register between Frida and QBDI.

Arguments:
  • FridaCtx – Frida context
  • rid – Register (register name or ID can be used e.g : “RAX”, “rax”, 0)
  • direction – Synchronization direction. (FRIDA_TO_QBDI or QBDI_TO_FRIDA)

Warning

Currently QBDI_TO_FRIDA is experimental. (E.G : RIP cannot be synchronized)

GPRState.prototype.synchronizeContext(FridaCtx, direction)

This function is used to synchronise context between Frida and QBDI.

Arguments:

Warning

Currently QBDI_TO_FRIDA is not implemented (due to Frida limitations).

GPRState.prototype.pp([color])

Pretty print QBDI context.

Arguments:
  • [color] – Will print a colored version of the context if set.
Returns:

dump of all GPRs in a pretty format

Return type:

String

GPRState.prototype.dump([color])

Pretty print and log QBDI context.

Arguments:
  • [color] – Will print a colored version of the context if set.
QBDI.prototype.getGPRState(state)

Obtain the current general register state.

Returns:An object containing the General Purpose Registers state.
Return type:object
QBDI.prototype.setGPRState(state)

Set the GPR state

Arguments:
  • state – Array of register values

State Initialization

QBDI.prototype.alignedAlloc(size, align)

Allocate a block of memory of a specified sized with an aligned base address.

Arguments:
  • size – Allocation size in bytes.
  • align – Base address alignement in bytes.
Returns:

Pointer to the allocated memory or NULL in case an error was encountered.

Return type:

rword

QBDI.prototype.allocateVirtualStack(gprs, stackSize)

Allocate a new stack and setup the GPRState accordingly. The allocated stack needs to be freed with alignedFree().

Arguments:
  • gprs – Array of register values
  • stackSize – Size of the stack to be allocated.
QBDI.prototype.setFPRState(state)

Set the FPR state

Arguments:
  • state – Array of register values
QBDI.prototype.setGPRState(state)

Set the GPR state

Arguments:
  • state – Array of register values
QBDI.prototype.simulateCall(state, retAddr[, args])

Simulate a call by modifying the stack and registers accordingly.

Arguments:
  • state – Array of register values
  • retAddr – Return address of the call to simulate.
  • args – A variadic list of arguments.

Execution

QBDI.prototype.addInstrumentedModule(name)

Add the executable address ranges of a module to the set of instrumented address ranges.

Arguments:
  • name – The module’s name.
Returns:

True if at least one range was added to the instrumented ranges.

Return type:

boolean

QBDI.prototype.addInstrumentedModuleFromAddr(addr)

Add the executable address ranges of a module to the set of instrumented address ranges. using an address belonging to the module.

Arguments:
  • addr – An address contained by module’s range.
Returns:

True if at least one range was removed from the instrumented ranges.

Return type:

boolean

QBDI.prototype.addInstrumentedRange(start, end)

Add an address range to the set of instrumented address ranges.

Arguments:
  • start – Start address of the range (included).
  • end – End address of the range (excluded).
QBDI.prototype.call(address[, args])

Call a function by its address (or through a Frida NativePointer).

Arguments:
  • address – function address (or Frida NativePointer).
  • [args] – optional list of arguments

Arguments can be provided, but their types need to be compatible with the .toRword() interface (like NativePointer or UInt64).

Example:
>>> var vm = new QBDI();
>>> var state = vm.getGPRState();
>>> vm.allocateVirtualStack(state, 0x1000000);
>>> var aFunction = Module.findExportByName(null, "Secret");
>>> vm.addInstrumentedModuleFromAddr(aFunction);
>>> vm.call(aFunction, [42]);
QBDI.prototype.getModuleNames()

Use QBDI engine to retrieve loaded modules.

Returns:list of module names (ex: [“ls”, “libc”, “libz”])
Return type:[String]
QBDI.prototype.removeInstrumentedRange(start, end)

Remove an address range from the set of instrumented address ranges.

Arguments:
  • start – Start address of the range (included).
  • end – End address of the range (excluded).
QBDI.prototype.run(start, stop)

Start the execution by the DBI from a given address (and stop when another is reached).

Arguments:
  • start – Address of the first instruction to execute.
  • stop – Stop the execution when this instruction is reached.
Returns:

True if at least one block has been executed.

Return type:

boolean

Instrumentation

QBDI.prototype.addCodeAddrCB(addr, pos, cbk, data)

Register a callback for when a specific address is executed.

Arguments:
  • addr – Code address which will trigger the callback.
  • pos – Relative position of the event callback (PreInst / PostInst).
  • cbk – A function pointer to the callback.
  • data – User defined data passed to the callback.
Returns:

The id of the registered instrumentation (or VMError.INVALID_EVENTID in case of failure).

Return type:

integer

QBDI.prototype.addCodeCB(pos, cbk, data)

Register a callback event for a specific instruction event.

Arguments:
  • pos – Relative position of the event callback (PreInst / PostInst).
  • cbk – A function pointer to the callback.
  • data – User defined data passed to the callback.
Returns:

The id of the registered instrumentation (or VMError.INVALID_EVENTID in case of failure).

Return type:

integer

QBDI.prototype.addCodeRangeCB(start, end, pos, cbk, data)

Register a callback for when a specific address range is executed.

Arguments:
  • start – Start of the address range which will trigger the callback.
  • end – End of the address range which will trigger the callback.
  • pos – Relative position of the event callback (PreInst / PostInst).
  • cbk – A function pointer to the callback.
  • data – User defined data passed to the callback.
Returns:

The id of the registered instrumentation (or VMError.INVALID_EVENTID in case of failure).

Return type:

integer

QBDI.prototype.addMnemonicCB(mnem, pos, cbk, data)

Register a callback event if the instruction matches the mnemonic.

Arguments:
  • mnem – Mnemonic to match.
  • pos – Relative position of the event callback (PreInst / PostInst).
  • cbk – A function pointer to the callback.
  • data – User defined data passed to the callback.
Returns:

The id of the registered instrumentation (or VMError.INVALID_EVENTID in case of failure).

Return type:

integer

QBDI.prototype.deleteAllInstrumentations()

Remove all the registered instrumentations.

QBDI.prototype.deleteInstrumentation(id)

Remove an instrumentation.

Arguments:
  • id – The id of the instrumentation to remove.
Returns:

True if instrumentation has been removed.

Return type:

boolean

Memory Callback

QBDI.prototype.addMemAccessCB(type, cbk, data)

Register a callback event for every memory access matching the type bitfield made by the instruction in the range codeStart to codeEnd.

Arguments:
  • type – A mode bitfield: either MEMORY_READ, MEMORY_WRITE or both (MEMORY_READ_WRITE).
  • cbk – A function pointer to the callback.
  • data – User defined data passed to the callback.
Returns:

The id of the registered instrumentation (or VMError.INVALID_EVENTID in case of failure).

Return type:

integer

QBDI.prototype.addMemAddrCB(addr, type, cbk, data)

Add a virtual callback which is triggered for any memory access at a specific address matching the access type. Virtual callbacks are called via callback forwarding by a gate callback triggered on every memory access. This incurs a high performance cost.

Arguments:
  • addr – Code address which will trigger the callback.
  • type – A mode bitfield: either MEMORY_READ, MEMORY_WRITE or both (MEMORY_READ_WRITE).
  • cbk – A function pointer to the callback.
  • data – User defined data passed to the callback.
Returns:

The id of the registered instrumentation (or VMError.INVALID_EVENTID in case of failure).

Return type:

integer

QBDI.prototype.addMemRangeCB(start, end, type, cbk, data)

Add a virtual callback which is triggered for any memory access in a specific address range matching the access type. Virtual callbacks are called via callback forwarding by a gate callback triggered on every memory access. This incurs a high performance cost.

Arguments:
  • start – Start of the address range which will trigger the callback.
  • end – End of the address range which will trigger the callback.
  • type – A mode bitfield: either MEMORY_READ, MEMORY_WRITE or both (MEMORY_READ_WRITE).
  • cbk – A function pointer to the callback.
  • data – User defined data passed to the callback.
Returns:

The id of the registered instrumentation (or VMError.INVALID_EVENTID in case of failure).

Return type:

integer

QBDI.prototype.recordMemoryAccess(type)

Obtain the memory accesses made by the last executed instruction. Return NULL and a size of 0 if the instruction made no memory access.

Arguments:
  • type – Memory mode bitfield to activate the logging for: either MEMORY_READ, MEMORY_WRITE or both (MEMORY_READ_WRITE).

Analysis

QBDI.prototype.getBBMemoryAccess()
Obtain the memory accesses made by the last executed basic block. Return NULL and a size of 0 if the basic block made no memory access.
Returns:An array of memory accesses made by the basic block.
Return type:Array
QBDI.prototype.getInstAnalysis()

Obtain the analysis of an instruction metadata. Analysis results are cached in the VM. The validity of the returned pointer is only guaranteed until the end of the callback, else a deepcopy of the structure is required.

Arguments:
  • [type] – Properties to retrieve during analysis (default to ANALYSIS_INSTRUCTION | ANALYSIS_DISASSEMBLY).
Returns:

A InstAnalysis object containing the analysis result.

Return type:

Object

QBDI.prototype.getInstMemoryAccess()

Obtain the memory accesses made by the last executed instruction. Return NULL and a size of 0 if the instruction made no memory access.

Returns:An array of memory accesses made by the instruction.
Return type:Array

Cache management

QBDI.prototype.precacheBasicBlock(state)

Pre-cache a known basic block.

Arguments:
  • pc – Start address of a basic block
Returns:

True if basic block has been inserted in cache.

Return type:

bool

QBDI.prototype.precacheBasicBlock(state)

Clear a specific address range from the translation cache.

Arguments:
  • start – Start of the address range to clear from the cache.
  • end – End of the address range to clear from the cache.
QBDI.prototype.precacheBasicBlock(state)

Clear the entire translation cache.

VM Events

QBDI.prototype.addVMEventCB(mask, cbk, data)

Register a callback event for a specific VM event.

Arguments:
  • mask – A mask of VM event type which will trigger the callback.
  • cbk – A function pointer to the callback.
  • data – User defined data passed to the callback.
Returns:

The id of the registered instrumentation (or VMError.INVALID_EVENTID in case of failure).

Return type:

integer

VMError
static INVALID_EVENTID

Returned event is invalid.

Globals

QBDI_LIB_FULLPATH

Fullpath of the QBDI library

GPR_NAMES

An array holding register names.

REG_RETURN

A constant string representing the register carrying the return value of a function.

REG_PC

String of the instruction pointer register.

REG_SP

String of the stack pointer register.

SyncDirection
Synchronisation direction between Frida and QBDI GPR contexts
static QBDI_TO_FRIDA

Constant variable used to synchronize QBDI’s context to Frida’s.

Warning

This is currently not supported due to the lack of context updating in Frida.

static FRIDA_TO_QBDI

Constant variable used to synchronize Frida’s context to QBDI’s.

VMAction
The callback results.
static CONTINUE

The execution of the basic block continues.

static BREAK_TO_VM

The execution breaks and returns to the VM causing a complete reevaluation of the execution state. A VMAction.BREAK_TO_VM is needed to ensure that modifications of the Program Counter or the program code are taken into account.

static STOP

Stops the execution of the program. This causes the run function to return early.

InstPosition
Position relative to an instruction.
static PREINST

Positioned before the instruction..

static POSTINST

Positioned after the instruction..

VMEvent
Events triggered by the virtual machine.
static SEQUENCE_ENTRY

Triggered when the execution enters a sequence.

static SEQUENCE_EXIT

Triggered when the execution exits from the current sequence.

static BASIC_BLOCK_ENTRY

Triggered when the execution enters a basic block.

static BASIC_BLOCK_EXIT

Triggered when the execution exits from the current basic block.

static BASIC_BLOCK_NEW

Triggered when the execution enters a new (~unknown) basic block.

static EXEC_TRANSFER_CALL

Triggered when the ExecBroker executes an execution transfer.

static EXEC_TRANSFER_RETURN

Triggered when the ExecBroker returns from an execution transfer.

static SYSCALL_ENTRY

Not implemented.

static SYSCALL_EXIT

Not implemented.

static SIGNAL

Not implemented.

MemoryAccessType
Memory access type (read / write / …)
static MEMORY_READ

Memory read access.

static MEMORY_WRITE

Memory write access.

static MEMORY_READ_WRITE

Memory read/write access.

AnalysisType
Properties to retrieve during an instruction analysis.
static ANALYSIS_INSTRUCTION

Instruction analysis (address, mnemonic, …).

static ANALYSIS_DISASSEMBLY

Instruction disassembly.

static ANALYSIS_OPERANDS

Instruction operands analysis.

static ANALYSIS_SYMBOL

Instruction nearest symbol (and offset).

Register values

The size of a general register depends of the architecture. QBDI uses a custom type (rword) to represent a register value.

This binding provides a common interface (.toRword()) to cast values into JS types compatible with the C rword type.

rword

An alias to Frida uint type with the size of general registers (uint64 or uint32)

NativePointer.prototype.toRword()

Convert a NativePointer into a type with the size of a register (Number or UInt64).

Number.prototype.toRword()

Convert a number into a type with the size of a register (Number or UInt64). Can’t be used for numbers > 32 bits, would cause weird results due to IEEE-754.

UInt64.prototype.toRword()

An identity function (returning the same UInt64 object). It exists only to provide a unified toRword interface.

Helpers

Some functions helpful to interact with Frida interface and write scripts.

hexPointer(ptr)

This function is used to pretty print a pointer, padded with 0 to the size of a register.

Arguments:
  • ptr – Pointer you want to pad
Returns:

pointer value as padded string (ex: “0x00004242”)

Return type:

String

QBDI.prototype.getModuleNames()

Use QBDI engine to retrieve loaded modules.

Returns:list of module names (ex: [“ls”, “libc”, “libz”])
Return type:[String]
QBDI.prototype.newInstCallback(cbk)

Create a native Instruction callback from a JS function.

Arguments:
  • cbk – an instruction callback (ex: function(vm, gpr, fpr, data) {};)
Returns:

an instruction callback

Return type:

NativeCallback

Example:
>>> var icbk = vm.newInstCallback(function(vm, gpr, fpr, data) {
>>>   inst = vm.getInstAnalysis();
>>>   console.log("0x" + inst.address.toString(16) + " " + inst.disassembly);
>>>   return VMAction.CONTINUE;
>>> });
QBDI.prototype.newVMCallback(cbk)

Create a native VM callback from a JS function.

Arguments:
  • cbk – a VM callback (ex: function(vm, state, gpr, fpr, data) {};)
Returns:

a VM callback

Return type:

NativeCallback

Example:
>>> var vcbk = vm.newVMCallback(function(vm, evt, gpr, fpr, data) {
>>>   if (evt.event & VMEvent.EXEC_TRANSFER_CALL) {
>>>     console.warn("[!] External call to 0x" + evt.basicBlockStart.toString(16));
>>>   }
>>>   return VMAction.CONTINUE;
>>> });
QBDI.version

QBDI version (major, minor, patch).

{string:String,integer:Number,major:Number,minor:Number,patch:Number}