C API

Introduction

The C API offers bindings over the C++ API. The VM class’ methods are replaced by C functions that receive an object of type VMInstanceRef as a first parameter.

This API is compatible with QBDIPreload on Linux and macOS.

VM object

type VMInstanceRef

An abstract pointer to the VM object.

void qbdi_initVM(VMInstanceRef *instance, const char *cpu, const char **mattrs, Options opts)

Create and initialize a VM instance.

Parameters
  • [out] instance: VM instance created.

  • [in] cpu: A C string naming the CPU model to use. If NULL, the default architecture CPU model is used (see LLVM documentation for more details).

  • [in] mattrs: A NULL terminated array of C strings specifying the attributes of the cpu model. If NULL, no additional features are specified.

  • [in] opts: The options to enable in the VM

void qbdi_terminateVM(VMInstanceRef instance)

Destroy an instance of VM. This method mustn’t be called when the VM runs.

Parameters
  • [in] instance: VM instance.

Options

Options qbdi_getOptions(VMInstanceRef instance)

Get the current Options

Return

The current options of the VM

Parameters
  • [in] instance: VM instance.

void qbdi_setOptions(VMInstanceRef instance, Options options)

Set the Options This method mustn’t be called when the VM runs.

Parameters
  • [in] instance: VM instance.

  • [in] options: The new options of the VM.

State management

GPRState *qbdi_getGPRState(VMInstanceRef instance)

Obtain the current general purpose register state.

Return

A structure containing the General Purpose Registers state.

Parameters
  • [in] instance: VM instance.

FPRState *qbdi_getFPRState(VMInstanceRef instance)

Obtain the current floating point register state.

Return

A structure containing the Floating Point Registers state.

Parameters
  • [in] instance: VM instance.

void qbdi_setGPRState(VMInstanceRef instance, GPRState *gprState)

Set the GPR state

Parameters
  • [in] instance: VM instance.

  • [in] gprState: A structure containing the General Purpose Registers state.

void qbdi_setFPRState(VMInstanceRef instance, FPRState *fprState)

Set the FPR state

Parameters
  • [in] instance: VM instance.

  • [in] fprState: A structure containing the Floating Point Registers state.

Instrumentation range

Addition

void qbdi_addInstrumentedRange(VMInstanceRef instance, rword start, rword end)

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

Parameters
  • [in] instance: VM instance.

  • [in] start: Start address of the range (included).

  • [in] end: End address of the range (excluded).

bool qbdi_addInstrumentedModule(VMInstanceRef instance, const char *name)

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

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] name: The module’s name.

bool qbdi_addInstrumentedModuleFromAddr(VMInstanceRef instance, rword addr)

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

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] addr: An address contained by module’s range.

bool qbdi_instrumentAllExecutableMaps(VMInstanceRef instance)

Adds all the executable memory maps to the instrumented range set.

Return

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

Parameters
  • [in] instance: VM instance.

Removal

void qbdi_removeInstrumentedRange(VMInstanceRef instance, rword start, rword end)

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

Parameters
  • [in] instance: VM instance.

  • [in] start: Start address of the range (included).

  • [in] end: End address of the range (excluded).

bool qbdi_removeInstrumentedModule(VMInstanceRef instance, const char *name)

Remove the executable address ranges of a module from the set of instrumented address ranges.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] name: The module’s name.

bool qbdi_removeInstrumentedModuleFromAddr(VMInstanceRef instance, rword addr)

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

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] addr: An address contained by module’s range.

void qbdi_removeAllInstrumentedRanges(VMInstanceRef instance)

Remove all instrumented ranges.

Parameters
  • [in] instance: VM instance.

Callback management

InstCallback

uint32_t qbdi_addCodeCB(VMInstanceRef instance, InstPosition pos, InstCallback cbk, void *data)

Register a callback event for a specific instruction event.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] pos: Relative position of the event callback (QBDI_PREINST / QBDI_POSTINST).

  • [in] cbk: A function pointer to the callback.

  • [in] data: User defined data passed to the callback.

uint32_t qbdi_addCodeAddrCB(VMInstanceRef instance, rword address, InstPosition pos, InstCallback cbk, void *data)

Register a callback for when a specific address is executed.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] address: Code address which will trigger the callback.

  • [in] pos: Relative position of the callback (QBDI_PREINST / QBDI_POSTINST).

  • [in] cbk: A function pointer to the callback.

  • [in] data: User defined data passed to the callback.

uint32_t qbdi_addCodeRangeCB(VMInstanceRef instance, rword start, rword end, InstPosition pos, InstCallback cbk, void *data)

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

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] start: Start of the address range which will trigger the callback.

  • [in] end: End of the address range which will trigger the callback.

  • [in] pos: Relative position of the callback (QBDI_PREINST / QBDI_POSTINST).

  • [in] cbk: A function pointer to the callback.

  • [in] data: User defined data passed to the callback.

uint32_t qbdi_addMnemonicCB(VMInstanceRef instance, const char *mnemonic, InstPosition pos, InstCallback cbk, void *data)

Register a callback event if the instruction matches the mnemonic.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] mnemonic: Mnemonic to match.

  • [in] pos: Relative position of the event callback (QBDI_PREINST / QBDI_POSTINST).

  • [in] cbk: A function pointer to the callback.

  • [in] data: User defined data passed to the callback.

VMEvent

uint32_t qbdi_addVMEventCB(VMInstanceRef instance, VMEvent mask, VMCallback cbk, void *data)

Register a callback event for a specific VM event.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] mask: A mask of VM event type which will trigger the callback.

  • [in] cbk: A function pointer to the callback.

  • [in] data: User defined data passed to the callback.

MemoryAccess

uint32_t qbdi_addMemAccessCB(VMInstanceRef instance, MemoryAccessType type, InstCallback cbk, void *data)

Register a callback event for every memory access matching the type bitfield made by the instructions.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] type: A mode bitfield: either QBDI_MEMORY_READ, QBDI_MEMORY_WRITE or both (QBDI_MEMORY_READ_WRITE).

  • [in] cbk: A function pointer to the callback.

  • [in] data: User defined data passed to the callback.

uint32_t qbdi_addMemAddrCB(VMInstanceRef instance, rword address, MemoryAccessType type, InstCallback cbk, void *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.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] address: Code address which will trigger the callback.

  • [in] type: A mode bitfield: either QBDI_MEMORY_READ, QBDI_MEMORY_WRITE or both (QBDI_MEMORY_READ_WRITE).

  • [in] cbk: A function pointer to the callback.

  • [in] data: User defined data passed to the callback.

uint32_t qbdi_addMemRangeCB(VMInstanceRef instance, rword start, rword end, MemoryAccessType type, InstCallback cbk, void *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.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] start: Start of the address range which will trigger the callback.

  • [in] end: End of the address range which will trigger the callback.

  • [in] type: A mode bitfield: either QBDI_MEMORY_READ, QBDI_MEMORY_WRITE or both (QBDI_MEMORY_READ_WRITE).

  • [in] cbk: A function pointer to the callback.

  • [in] data: User defined data passed to the callback.

InstrRuleCallback

uint32_t qbdi_addInstrRule(VMInstanceRef instance, InstrRuleCallbackC cbk, AnalysisType type, void *data)

Add a custom instrumentation rule to the VM.

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] cbk: A function pointer to the callback

  • [in] type: Analyse type needed for this instruction function pointer to the callback

  • [in] data: User defined data passed to the callback.

uint32_t qbdi_addInstrRuleRange(VMInstanceRef instance, rword start, rword end, InstrRuleCallbackC cbk, AnalysisType type, void *data)

Add a custom instrumentation rule to the VM for a range of address

Return

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

Parameters
  • [in] instance: VM instance.

  • [in] start: Begin of the range of address where apply the rule

  • [in] end: End of the range of address where apply the rule

  • [in] cbk: A function pointer to the callback

  • [in] type: Analyse type needed for this instruction function pointer to the callback

  • [in] data: User defined data passed to the callback.

Removal

bool qbdi_deleteInstrumentation(VMInstanceRef instance, uint32_t id)

Remove an instrumentation.

Return

True if instrumentation has been removed.

Parameters
  • [in] instance: VM instance.

  • [in] id: The id of the instrumentation to remove.

void qbdi_deleteAllInstrumentations(VMInstanceRef instance)

Remove all the registered instrumentations.

Parameters
  • [in] instance: VM instance.

Run

bool qbdi_run(VMInstanceRef instance, rword start, rword stop)

Start the execution by the DBI from a given address (and stop when another is reached). This method mustn’t be called when the VM already runs.

Return

True if at least one block has been executed.

Parameters
  • [in] instance: VM instance.

  • [in] start: Address of the first instruction to execute.

  • [in] stop: Stop the execution when this instruction is reached.

bool qbdi_call(VMInstanceRef instance, rword *retval, rword function, uint32_t argNum, ...)

Call a function using the DBI (and its current state). This method mustn’t be called when the VM already runs.

Example:

// perform (with QBDI) a call similar to (*funcPtr)(42);
uint8_t *fakestack = NULL;
VMInstanceRef vm;
qbdi_initVM(&vm, NULL, NULL);
GPRState* gprState = qbdi_getGPRState(vm);
qbdi_allocateVirtualStack(gprState, 0x1000000, &fakestack);
qbdi_addInstrumentedModuleFromAddr(vm, funcPtr);
rword retVal;
qbdi_call(vm, &retVal, funcPtr, 1, 42);
Return

True if at least one block has been executed.

Parameters
  • [in] instance: VM instance.

  • [in] [retval]: Pointer to the returned value (optional).

  • [in] function: Address of the function start instruction.

  • [in] argNum: The number of arguments in the variadic list.

  • [in] ...: A variadic list of arguments.

bool qbdi_callA(VMInstanceRef instance, rword *retval, rword function, uint32_t argNum, const rword *args)

Call a function using the DBI (and its current state). This method mustn’t be called when the VM already runs.

Return

True if at least one block has been executed.

Parameters
  • [in] instance: VM instance.

  • [in] [retval]: Pointer to the returned value (optional).

  • [in] function: Address of the function start instruction.

  • [in] argNum: The number of arguments in the variadic list.

  • [in] args: Arguments as an array of rword values.

bool qbdi_callV(VMInstanceRef instance, rword *retval, rword function, uint32_t argNum, va_list ap)

Call a function using the DBI (and its current state). This method mustn’t be called when the VM already runs.

Return

True if at least one block has been executed.

Parameters
  • [in] instance: VM instance.

  • [in] [retval]: Pointer to the returned value (optional).

  • [in] function: Address of the function start instruction.

  • [in] argNum: The number of arguments in the variadic list.

  • [in] ap: An stdarg va_list object.

InstAnalysis

const InstAnalysis *qbdi_getInstAnalysis(const VMInstanceRef instance, AnalysisType type)

Obtain the analysis of the current instruction. 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. This method must only be used in an InstCallback.

Return

A InstAnalysis structure containing the analysis result.

Parameters
  • [in] instance: VM instance.

  • [in] type: Properties to retrieve during analysis.

const InstAnalysis *qbdi_getCachedInstAnalysis(const VMInstanceRef instance, rword address, AnalysisType type)

Obtain the analysis of a cached instruction. Analysis results are cached in the VM. The validity of the returned pointer is only guaranteed until the end of the callback or a call to a noconst method of the VM instance.

Return

A InstAnalysis structure containing the analysis result. null if the instruction isn’t in the cache.

Parameters
  • [in] instance: VM instance.

  • [in] address: The address of the instruction to analyse.

  • [in] type: Properties to retrieve during analysis.

MemoryAccess

MemoryAccess *qbdi_getInstMemoryAccess(VMInstanceRef instance, size_t *size)

Obtain the memory accesses made by the last executed instruction. The method should be called in an InstCallback. Return NULL and a size of 0 if the instruction made no memory access.

Return

An array of memory accesses made by the instruction.

Parameters
  • [in] instance: VM instance.

  • [out] size: Will be set to the number of elements in the returned array.

MemoryAccess *qbdi_getBBMemoryAccess(VMInstanceRef instance, size_t *size)

Obtain the memory accesses made by the last executed basic block. The method should be called in a VMCallback with QBDI_SEQUENCE_EXIT. Return NULL and a size of 0 if the basic block made no memory access.

Return

An array of memory accesses made by the basic block.

Parameters
  • [in] instance: VM instance.

  • [out] size: Will be set to the number of elements in the returned array.

bool qbdi_recordMemoryAccess(VMInstanceRef instance, MemoryAccessType type)

Add instrumentation rules to log memory access using inline instrumentation and instruction shadows.

Return

True if inline memory logging is supported, False if not or in case of error.

Parameters
  • [in] instance: VM instance.

  • [in] type: Memory mode bitfield to activate the logging for: either QBDI_MEMORY_READ, QBDI_MEMORY_WRITE or both (QBDI_MEMORY_READ_WRITE).

Cache management

bool qbdi_precacheBasicBlock(VMInstanceRef instance, rword pc)

Pre-cache a known basic block This method mustn’t be called when the VM runs.

Return

True if basic block has been inserted in cache.

Parameters
  • [in] instance: VM instance.

  • [in] pc: Start address of a basic block

void qbdi_clearCache(VMInstanceRef instance, rword start, rword end)

Clear a specific address range from the translation cache.

Parameters
  • [in] instance: VM instance.

  • [in] start: Start of the address range to clear from the cache.

  • [in] end: End of the address range to clear from the cache.

void qbdi_clearAllCache(VMInstanceRef instance)

Clear the entire translation cache.

Parameters
  • [in] instance: VM instance.

Register state

type rword

An integer of the size of a register

  • uint32_t for X86

  • uint64_t for X86_64

struct GPRState

General Purpose Register context.

For X86 architecture:


typedef struct {
    rword eax;
    rword ebx;
    rword ecx;
    rword edx;
    rword esi;
    rword edi;
    rword ebp;
    rword esp;
    rword eip;
    rword eflags;
} GPRState;

For X86_64 architecture:


typedef struct {
    rword rax;
    rword rbx;
    rword rcx;
    rword rdx;
    rword rsi;
    rword rdi;
    rword r8;
    rword r9;
    rword r10;
    rword r11;
    rword r12;
    rword r13;
    rword r14;
    rword r15;
    rword rbp;
    rword rsp;
    rword rip;
    rword eflags;
} GPRState;
struct FPRState

Floating Point Register context.

For X86 architecture:


typedef struct {
    union {
        FPControl     fcw;      /* x87 FPU control word */
        uint16_t      rfcw;
    };
    union {
        FPStatus      fsw;      /* x87 FPU status word */
        uint16_t      rfsw;
    };
    uint8_t           ftw;          /* x87 FPU tag word */
    uint8_t           rsrv1;        /* reserved */
    uint16_t          fop;          /* x87 FPU Opcode */
    uint32_t          ip;           /* x87 FPU Instruction Pointer offset */
    uint16_t          cs;           /* x87 FPU Instruction Pointer Selector */
    uint16_t          rsrv2;        /* reserved */
    uint32_t          dp;           /* x87 FPU Instruction Operand(Data) Pointer offset */
    uint16_t          ds;           /* x87 FPU Instruction Operand(Data) Pointer Selector */
    uint16_t          rsrv3;        /* reserved */
    uint32_t          mxcsr;        /* MXCSR Register state */
    uint32_t          mxcsrmask;    /* MXCSR mask */
    MMSTReg           stmm0;        /* ST0/MM0   */
    MMSTReg           stmm1;        /* ST1/MM1  */
    MMSTReg           stmm2;        /* ST2/MM2  */
    MMSTReg           stmm3;        /* ST3/MM3  */
    MMSTReg           stmm4;        /* ST4/MM4  */
    MMSTReg           stmm5;        /* ST5/MM5  */
    MMSTReg           stmm6;        /* ST6/MM6  */
    MMSTReg           stmm7;        /* ST7/MM7  */
    char              xmm0[16];     /* XMM 0  */
    char              xmm1[16];     /* XMM 1  */
    char              xmm2[16];     /* XMM 2  */
    char              xmm3[16];     /* XMM 3  */
    char              xmm4[16];     /* XMM 4  */
    char              xmm5[16];     /* XMM 5  */
    char              xmm6[16];     /* XMM 6  */
    char              xmm7[16];     /* XMM 7  */
    char              reserved[14*16];
    char              ymm0[16];     /* YMM0[255:128] */
    char              ymm1[16];     /* YMM1[255:128] */
    char              ymm2[16];     /* YMM2[255:128] */
    char              ymm3[16];     /* YMM3[255:128] */
    char              ymm4[16];     /* YMM4[255:128] */
    char              ymm5[16];     /* YMM5[255:128] */
    char              ymm6[16];     /* YMM6[255:128] */
    char              ymm7[16];     /* YMM7[255:128] */
} FPRState;

For X86_64 architecture:


typedef struct {
    union {
        FPControl     fcw;      /* x87 FPU control word */
        uint16_t      rfcw;
    };
    union {
        FPStatus      fsw;      /* x87 FPU status word */
        uint16_t      rfsw;
    };
    uint8_t           ftw;          /* x87 FPU tag word */
    uint8_t           rsrv1;        /* reserved */
    uint16_t          fop;          /* x87 FPU Opcode */
    uint32_t          ip;           /* x87 FPU Instruction Pointer offset */
    uint16_t          cs;           /* x87 FPU Instruction Pointer Selector */
    uint16_t          rsrv2;        /* reserved */
    uint32_t          dp;           /* x87 FPU Instruction Operand(Data) Pointer offset */
    uint16_t          ds;           /* x87 FPU Instruction Operand(Data) Pointer Selector */
    uint16_t          rsrv3;        /* reserved */
    uint32_t          mxcsr;        /* MXCSR Register state */
    uint32_t          mxcsrmask;    /* MXCSR mask */
    MMSTReg           stmm0;        /* ST0/MM0   */
    MMSTReg           stmm1;        /* ST1/MM1  */
    MMSTReg           stmm2;        /* ST2/MM2  */
    MMSTReg           stmm3;        /* ST3/MM3  */
    MMSTReg           stmm4;        /* ST4/MM4  */
    MMSTReg           stmm5;        /* ST5/MM5  */
    MMSTReg           stmm6;        /* ST6/MM6  */
    MMSTReg           stmm7;        /* ST7/MM7  */
    char              xmm0[16];     /* XMM 0  */
    char              xmm1[16];     /* XMM 1  */
    char              xmm2[16];     /* XMM 2  */
    char              xmm3[16];     /* XMM 3  */
    char              xmm4[16];     /* XMM 4  */
    char              xmm5[16];     /* XMM 5  */
    char              xmm6[16];     /* XMM 6  */
    char              xmm7[16];     /* XMM 7  */
    char              xmm8[16];     /* XMM 8  */
    char              xmm9[16];     /* XMM 9  */
    char              xmm10[16];    /* XMM 10  */
    char              xmm11[16];    /* XMM 11  */
    char              xmm12[16];    /* XMM 12  */
    char              xmm13[16];    /* XMM 13  */
    char              xmm14[16];    /* XMM 14  */
    char              xmm15[16];    /* XMM 15  */
    char              reserved[6*16];
    char              ymm0[16];     /* YMM0[255:128] */
    char              ymm1[16];     /* YMM1[255:128] */
    char              ymm2[16];     /* YMM2[255:128] */
    char              ymm3[16];     /* YMM3[255:128] */
    char              ymm4[16];     /* YMM4[255:128] */
    char              ymm5[16];     /* YMM5[255:128] */
    char              ymm6[16];     /* YMM6[255:128] */
    char              ymm7[16];     /* YMM7[255:128] */
    char              ymm8[16];     /* YMM8[255:128] */
    char              ymm9[16];     /* YMM9[255:128] */
    char              ymm10[16];    /* YMM10[255:128] */
    char              ymm11[16];    /* YMM11[255:128] */
    char              ymm12[16];    /* YMM12[255:128] */
    char              ymm13[16];    /* YMM13[255:128] */
    char              ymm14[16];    /* YMM14[255:128] */
    char              ymm15[16];    /* YMM15[255:128] */
} FPRState;
struct MMSTReg

Public Members

char reg[10]
char rsrv[6]
struct FPControl

Public Members

uint16_t invalid
uint16_t denorm
uint16_t zdiv
uint16_t ovrfl
uint16_t undfl
uint16_t precis
uint16_t pc
uint16_t rc
struct FPStatus

Public Members

uint16_t invalid
uint16_t denorm
uint16_t zdiv
uint16_t ovrfl
uint16_t undfl
uint16_t precis
uint16_t stkflt
uint16_t errsumm
uint16_t c0
uint16_t c1
uint16_t c2
uint16_t tos
uint16_t c3
uint16_t busy
REG_RETURN
REG_BP
REG_SP
REG_PC
NUM_GPR

Callback

typedef VMAction (*InstCallback)(VMInstanceRef vm, GPRState *gprState, FPRState *fprState, void *data)

Instruction callback function type.

Return

The callback result used to signal subsequent actions the VM needs to take.

Parameters
  • [in] vm: VM instance of the callback.

  • [in] gprState: A structure containing the state of the General Purpose Registers. Modifying it affects the VM execution accordingly.

  • [in] fprState: A structure containing the state of the Floating Point Registers. Modifying it affects the VM execution accordingly.

  • [in] data: User defined data which can be defined when registering the callback.

typedef VMAction (*VMCallback)(VMInstanceRef vm, const VMState *vmState, GPRState *gprState, FPRState *fprState, void *data)

VM callback function type.

Return

The callback result used to signal subsequent actions the VM needs to take.

Parameters
  • [in] vm: VM instance of the callback.

  • [in] vmState: A structure containing the current state of the VM.

  • [in] gprState: A structure containing the state of the General Purpose Registers. Modifying it affects the VM execution accordingly.

  • [in] fprState: A structure containing the state of the Floating Point Registers. Modifying it affects the VM execution accordingly.

  • [in] data: User defined data which can be defined when registering the callback.

typedef void (*InstrRuleCallbackC)(VMInstanceRef vm, const InstAnalysis *inst, InstrRuleDataVec cbks, void *data)

Instrumentation rule callback function type for C API.

Parameters
  • [in] vm: VM instance of the callback.

  • [in] inst: AnalysisType of the current instrumented Instruction.

  • [in] cbks: An object to add the callback to apply for this instruction. InstCallback can be add with qbdi_addInstrRuleData

  • [in] data: User defined data which can be defined when registering the callback.

void qbdi_addInstrRuleData(InstrRuleDataVec cbks, InstPosition position, InstCallback cbk, void *data)

Add a callback for the current instruction

Parameters
  • [in] cbks: InstrRuleDataVec given in argument

  • [in] position: Relative position of the callback (QBDI_PREINST / QBDI_POSTINST).

  • [in] cbk: A function pointer to the callback

  • [in] data: User defined data passed to the callback.

type InstrRuleDataVec

An abstract type to append InstCallback for the current instruction

enum InstPosition

Position relative to an instruction.

Values:

enumerator QBDI_PREINST

Positioned before the instruction.

enumerator QBDI_POSTINST

Positioned after the instruction.

enum VMAction

The callback results.

Values:

enumerator QBDI_CONTINUE

The execution of the basic block continues.

enumerator QBDI_BREAK_TO_VM

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

enumerator QBDI_STOP

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

InstAnalysis

enum AnalysisType

Instruction analysis type

Values:

enumerator QBDI_ANALYSIS_INSTRUCTION

Instruction analysis (address, mnemonic, …)

enumerator QBDI_ANALYSIS_DISASSEMBLY

Instruction disassembly

enumerator QBDI_ANALYSIS_OPERANDS

Instruction operands analysis

enumerator QBDI_ANALYSIS_SYMBOL

Instruction symbol

struct InstAnalysis

Structure containing analysis results of an instruction provided by the VM.

Public Members

const char *mnemonic

LLVM mnemonic (warning: NULL if !ANALYSIS_INSTRUCTION)

rword address

Instruction address

uint32_t instSize

Instruction size (in bytes)

bool affectControlFlow

true if instruction affects control flow

bool isBranch

true if instruction acts like a ‘jump’

bool isCall

true if instruction acts like a ‘call’

bool isReturn

true if instruction acts like a ‘return’

bool isCompare

true if instruction is a comparison

bool isPredicable

true if instruction contains a predicate (~is conditional)

bool mayLoad

true if QBDI detects a load for this instruction

bool mayStore

true if QBDI detects a store for this instruction

uint32_t loadSize

size of the expected read access, may be 0 with mayLoad if the size isn’t determined

uint32_t storeSize

size of the expected write access, may be 0 with mayStore if the size isn’t determined

ConditionType condition

Condition associated with the instruction

char *disassembly

Instruction disassembly (warning: NULL if !ANALYSIS_DISASSEMBLY)

RegisterAccessType flagsAccess

Flag access type (noaccess, r, w, rw) (warning: REGISTER_UNUSED if !ANALYSIS_OPERANDS)

uint8_t numOperands

Number of operands used by the instruction

OperandAnalysis *operands

Structure containing analysis results of an operand provided by the VM. (warning: NULL if !ANALYSIS_OPERANDS)

const char *symbol

Instruction symbol (warning: NULL if !ANALYSIS_SYMBOL or not found)

uint32_t symbolOffset

Instruction symbol offset

const char *module

Instruction module name (warning: NULL if !ANALYSIS_SYMBOL or not found)

uint32_t analysisType

INTERNAL: Instruction analysis type (this should NOT be used)

enum ConditionType

Instruction Condition

Values:

enumerator QBDI_CONDITION_NONE

The instruction is unconditionnal

enumerator QBDI_CONDITION_ALWAYS

The instruction is always true

enumerator QBDI_CONDITION_NEVER

The instruction is always false

enumerator QBDI_CONDITION_EQUALS

Equals ( ‘==’ )

enumerator QBDI_CONDITION_NOT_EQUALS

Not Equals ( ‘!=’ )

enumerator QBDI_CONDITION_ABOVE

Above ( ‘>’ unsigned )

enumerator QBDI_CONDITION_BELOW_EQUALS

Below or Equals ( ‘<=’ unsigned )

enumerator QBDI_CONDITION_ABOVE_EQUALS

Above or Equals ( ‘>=’ unsigned )

enumerator QBDI_CONDITION_BELOW

Below ( ‘<’ unsigned )

enumerator QBDI_CONDITION_GREAT

Great ( ‘>’ signed )

enumerator QBDI_CONDITION_LESS_EQUALS

Less or Equals ( ‘<=’ signed )

enumerator QBDI_CONDITION_GREAT_EQUALS

Great or Equals ( ‘>=’ signed )

enumerator QBDI_CONDITION_LESS

Less ( ‘<’ signed )

enumerator QBDI_CONDITION_EVEN

Even

enumerator QBDI_CONDITION_ODD

Odd

enumerator QBDI_CONDITION_OVERFLOW

Overflow

enumerator QBDI_CONDITION_NOT_OVERFLOW

Not Overflow

enumerator QBDI_CONDITION_SIGN

Sign

enumerator QBDI_CONDITION_NOT_SIGN

Not Sign

struct OperandAnalysis

Structure containing analysis results of an operand provided by the VM.

Public Members

OperandType type

Operand type

OperandFlag flag

Operand flag

rword value

Operand value (if immediate), or register Id

uint8_t size

Operand size (in bytes)

uint8_t regOff

Sub-register offset in register (in bits)

int16_t regCtxIdx

Register index in VM state (< 0 if not know)

const char *regName

Register name

RegisterAccessType regAccess

Register access type (r, w, rw)

enum OperandType

Operand type

Values:

enumerator QBDI_OPERAND_INVALID

Invalid operand

enumerator QBDI_OPERAND_IMM

Immediate operand

enumerator QBDI_OPERAND_GPR

Register operand

enumerator QBDI_OPERAND_PRED

Predicate operand

enumerator QBDI_OPERAND_FPR

Float register operand

enumerator QBDI_OPERAND_SEG

Segment or unsupported register operand

enum OperandFlag

Values:

enumerator QBDI_OPERANDFLAG_NONE

No flag

enumerator QBDI_OPERANDFLAG_ADDR

The operand is used to compute an address

enumerator QBDI_OPERANDFLAG_PCREL

The value of the operand is PC relative

enumerator QBDI_OPERANDFLAG_UNDEFINED_EFFECT

The operand role isn’t fully defined

enumerator QBDI_OPERANDFLAG_IMPLICIT

The operand is implicit

enum RegisterAccessType

Access type (R/W/RW) of a register operand

Values:

enumerator QBDI_REGISTER_UNUSED

Unused register

enumerator QBDI_REGISTER_READ

Register read access

enumerator QBDI_REGISTER_WRITE

Register write access

enumerator QBDI_REGISTER_READ_WRITE

Register read/write access

MemoryAccess

struct MemoryAccess

Describe a memory access

Public Members

rword instAddress

Address of instruction making the access

rword accessAddress

Address of accessed memory

rword value

Value read from / written to memory

uint16_t size

Size of memory access (in bytes)

MemoryAccessType type

Memory access type (READ / WRITE)

MemoryAccessFlags flags

Memory access flags

enum MemoryAccessType

Memory access type (read / write / …)

Values:

enumerator QBDI_MEMORY_READ

Memory read access

enumerator QBDI_MEMORY_WRITE

Memory write access

enumerator QBDI_MEMORY_READ_WRITE

Memory read/write access

enum MemoryAccessFlags

Memory access flags

Values:

enumerator QBDI_MEMORY_NO_FLAGS
enumerator QBDI_MEMORY_UNKNOWN_SIZE

The size of the access isn’t known.

enumerator QBDI_MEMORY_MINIMUM_SIZE

The given size is a minimum size.

enumerator QBDI_MEMORY_UNKNOWN_VALUE

The value of the access is unknown or hasn’t been retrived.

VMEvent

enum VMEvent

Values:

enumerator QBDI_NO_EVENT
enumerator QBDI_SEQUENCE_ENTRY

Triggered when the execution enters a sequence.

enumerator QBDI_SEQUENCE_EXIT

Triggered when the execution exits from the current sequence.

enumerator QBDI_BASIC_BLOCK_ENTRY

Triggered when the execution enters a basic block.

enumerator QBDI_BASIC_BLOCK_EXIT

Triggered when the execution exits from the current basic block.

enumerator QBDI_BASIC_BLOCK_NEW

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

enumerator QBDI_EXEC_TRANSFER_CALL

Triggered when the ExecBroker executes an execution transfer.

enumerator QBDI_EXEC_TRANSFER_RETURN

Triggered when the ExecBroker returns from an execution transfer.

enumerator QBDI_SYSCALL_ENTRY

Not implemented.

enumerator QBDI_SYSCALL_EXIT

Not implemented.

enumerator QBDI_SIGNAL

Not implemented.

struct VMState

Structure describing the current VM state

Public Members

VMEvent event

The event(s) which triggered the callback (must be checked using a mask: event & BASIC_BLOCK_ENTRY).

rword basicBlockStart

The current basic block start address which can also be the execution transfer destination.

rword basicBlockEnd

The current basic block end address which can also be the execution transfer destination.

rword sequenceStart

The current sequence start address which can also be the execution transfer destination.

rword sequenceEnd

The current sequence end address which can also be the execution transfer destination.

rword lastSignal

Not implemented.

Memory management

Allocation

void *qbdi_alignedAlloc(size_t size, size_t align)

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

Return

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

Parameters
  • [in] size: Allocation size in bytes.

  • [in] align: Base address alignement in bytes.

bool qbdi_allocateVirtualStack(GPRState *ctx, uint32_t stackSize, uint8_t **stack)

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

Return

True if stack allocation was successfull.

Parameters
  • [in] ctx: GPRState which will be setup to use the new stack.

  • [in] stackSize: Size of the stack to be allocated.

  • [out] stack: The newly allocated stack pointer will be returned in the variable pointed by stack.

void qbdi_alignedFree(void *ptr)

Free a block of aligned memory allocated with alignedAlloc.

Parameters
  • [in] ptr: Pointer to the allocated memory.

void qbdi_simulateCall(GPRState *ctx, rword returnAddress, uint32_t argNum, ...)

Simulate a call by modifying the stack and registers accordingly.

Parameters
  • [in] ctx: GPRState where the simulated call will be setup. The state needs to point to a valid stack for example setup with allocateVirtualStack().

  • [in] returnAddress: Return address of the call to simulate.

  • [in] argNum: The number of arguments in the variadic list.

  • [in] ...: A variadic list of arguments.

void qbdi_simulateCallV(GPRState *ctx, rword returnAddress, uint32_t argNum, va_list ap)

Simulate a call by modifying the stack and registers accordingly (stdarg version).

Parameters
  • [in] ctx: GPRState where the simulated call will be setup. The state needs to point to a valid stack for example setup with allocateVirtualStack().

  • [in] returnAddress: Return address of the call to simulate.

  • [in] argNum: The number of arguments in the va_list object.

  • [in] ap: An stdarg va_list object.

void qbdi_simulateCallA(GPRState *ctx, rword returnAddress, uint32_t argNum, const rword *args)

Simulate a call by modifying the stack and registers accordingly (C array version).

Parameters
  • [in] ctx: GPRState where the simulated call will be setup. The state needs to point to a valid stack for example setup with allocateVirtualStack().

  • [in] returnAddress: Return address of the call to simulate.

  • [in] argNum: The number of arguments in the array args.

  • [in] args: An array or arguments.

Exploration

char **qbdi_getModuleNames(size_t *size)

Get a list of all the module names loaded in the process memory. If no modules are found, size is set to 0 and this function returns NULL.

Return

An array of C strings, each one containing the name of a loaded module. This array needs to be free’d by the caller by repetively calling free() on each of its element then finally on the array itself.

Parameters
  • [out] size: Will be set to the number of strings in the returned array.

qbdi_MemoryMap *qbdi_getCurrentProcessMaps(bool full_path, size_t *size)

Get a list of all the memory maps (regions) of the current process.

Return

An array of MemoryMap object.

Parameters
  • [in] full_path: Return the full path of the module in name field

  • [out] size: Will be set to the number of strings in the returned array.

qbdi_MemoryMap *qbdi_getRemoteProcessMaps(rword pid, bool full_path, size_t *size)

Get a list of all the memory maps (regions) of a process.

Return

An array of MemoryMap object.

Parameters
  • [in] pid: The identifier of the process.

  • [in] full_path: Return the full path of the module in name field

  • [out] size: Will be set to the number of strings in the returned array.

void qbdi_freeMemoryMapArray(qbdi_MemoryMap *arr, size_t size)

Free an array of memory maps objects.

Parameters
  • [in] arr: An array of MemoryMap object.

  • [in] size: Number of elements in the array.

struct qbdi_MemoryMap

Map of a memory area (region).

Public Members

qbdi_Permission permission

Region access rights (PF_READ, PF_WRITE, PF_EXEC).

char *name

Region name or path (useful when a region is mapping a module).

enum qbdi_Permission

Memory access rights.

Values:

enumerator QBDI_PF_NONE

No access

enumerator QBDI_PF_READ

Read access

enumerator QBDI_PF_WRITE

Write access

enumerator QBDI_PF_EXEC

Execution access

Other globals

enum Options

Values:

enumerator QBDI_NO_OPT

Default value

enumerator QBDI_OPT_DISABLE_FPR

Disable all operation on FPU (SSE, AVX, SIMD). May break the execution if the target use the FPU

enumerator QBDI_OPT_DISABLE_OPTIONAL_FPR

Disable context switch optimisation when the target execblock doesn’t used FPR

enumerator QBDI_OPT_ATT_SYNTAX

Used the AT&T syntax for instruction disassembly

enum VMError

QBDI Error values

Values:

enumerator QBDI_INVALID_EVENTID

Mark a returned event id as invalid

Miscellaneous

Version

const char *qbdi_getVersion(uint32_t *version)

Return QBDI version.

Return

QBDI version as a string (major.minor.patch).

Parameters
  • [out] version: QBDI version encoded as an unsigned integer (0xMmp).

Log

enum LogPriority

Each log has a priority (or level) which can be used to control verbosity. In production builds, only Warning and Error logs are kept.

Values:

enumerator QBDI_DEBUG

Debug logs

enumerator QBDI_WARNING

Warning logs

enumerator QBDI_ERROR

Error logs

void qbdi_setLogOutput(FILE *output)

Redirect logs to an opened file.

Parameters
  • [in] output: Pointer to an opened file where logs will be append.

void qbdi_addLogFilter(const char *tag, LogPriority priority)

Enable logs matching tag and priority.

Parameters
  • [in] tag: Logs are identified using a tag (ex: Engine::patch). “*” will log everything matching priority.

  • [in] priority: Filter logs with greater or equal priority.