C++ API

Introduction

The C++ API is the primary API of QBDI. The API is compatible with QBDIPreload on Linux and macOS.

VM class

class QBDI::VM

Public Functions

VM(const std::string &cpu = "", const std::vector<std::string> &mattrs = {}, Options opts = Options::NO_OPT)

Construct a new VM for a given CPU with specific attributes

Parameters
  • cpu[in] The name of the CPU

  • mattrs[in] A list of additional attributes

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

VM(VM &&vm)

Move constructors. All the cache is keep. All registered callbacks will be called with the new pointer of the VM.

Parameters

vm[in] The VM to move

VM &operator=(VM &&vm)

Move assignment operator All the cache is keep. All registered callbacks will be called with the new pointer of the VM. This operator mustn’t be called when the target VM runs.

Parameters

vm[in] The VM to move

VM(const VM &vm)

Copy constructors The state and the configuration is copied. The cache isn’t duplicate. The assigned VM begin with an empty cache.

Parameters

vm[in] The VM to copy

VM &operator=(const VM &vm)

Copy assignment operator The state and the configuration is copied. The cache isn’t duplicate. The assigned VM begin with an empty cache. This operator mustn’t be called when the target VM runs.

Parameters

vm[in] The VM to copy

Options

Options QBDI::VM::getOptions() const

Get the current Options of the VM

void QBDI::VM::setOptions(Options options)

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

If the new options is different that the current ones, the cache will be clear.

Parameters

options[in] the new options of the VM

State management

GPRState *QBDI::VM::getGPRState() const

Obtain the current general purpose register state.

Returns

A structure containing the GPR state.

FPRState *QBDI::VM::getFPRState() const

Obtain the current floating point register state.

Returns

A structure containing the FPR state.

void QBDI::VM::setGPRState(const GPRState *gprState)

Set the GPR state

Parameters

gprState[in] A structure containing the GPR state.

void QBDI::VM::setFPRState(const FPRState *fprState)

Set the FPR state

Parameters

fprState[in] A structure containing the FPR state.

Instrumentation range

Addition

void QBDI::VM::addInstrumentedRange(rword start, rword end)

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

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

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

bool QBDI::VM::addInstrumentedModule(const std::string &name)

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

Parameters

name[in] The module’s name.

Returns

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

bool QBDI::VM::addInstrumentedModuleFromAddr(rword addr)

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

Parameters

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

Returns

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

bool QBDI::VM::instrumentAllExecutableMaps()

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

Returns

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

Removal

void QBDI::VM::removeInstrumentedRange(rword start, rword end)

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

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

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

bool QBDI::VM::removeInstrumentedModule(const std::string &name)

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

Parameters

name[in] The module’s name.

Returns

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

bool QBDI::VM::removeInstrumentedModuleFromAddr(rword addr)

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

Parameters

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

Returns

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

void QBDI::VM::removeAllInstrumentedRanges()

Remove all instrumented ranges.

Callback management

InstCallback

uint32_t QBDI::VM::addCodeCB(InstPosition pos, InstCallback cbk, void *data, int priority = PRIORITY_DEFAULT)

Register a callback event for every instruction executed.

Parameters
  • pos[in] Relative position of the event callback (PREINST / POSTINST).

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

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

  • priority[in] The priority of the callback.

Returns

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

uint32_t QBDI::VM::addCodeCB(InstPosition pos, InstCbLambda &&cbk, int priority = PRIORITY_DEFAULT)
uint32_t QBDI::VM::addCodeCB(InstPosition pos, const InstCbLambda &cbk, int priority = PRIORITY_DEFAULT)

Register a callback event for every instruction executed.

Parameters
  • pos[in] Relative position of the event callback (PREINST / POSTINST).

  • cbk[in] A lambda function to the callback

  • priority[in] The priority of the callback.

Returns

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

uint32_t QBDI::VM::addCodeAddrCB(rword address, InstPosition pos, InstCallback cbk, void *data, int priority = PRIORITY_DEFAULT)

Register a callback for when a specific address is executed.

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

  • pos[in] Relative position of the callback (PREINST / POSTINST).

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

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

  • priority[in] The priority of the callback.

Returns

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

uint32_t QBDI::VM::addCodeAddrCB(rword address, InstPosition pos, InstCbLambda &&cbk, int priority = PRIORITY_DEFAULT)
uint32_t QBDI::VM::addCodeAddrCB(rword address, InstPosition pos, const InstCbLambda &cbk, int priority = PRIORITY_DEFAULT)

Register a callback for when a specific address is executed.

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

  • pos[in] Relative position of the callback (PREINST / POSTINST).

  • cbk[in] A lambda function to the callback

  • priority[in] The priority of the callback.

Returns

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

uint32_t QBDI::VM::addCodeRangeCB(rword start, rword end, InstPosition pos, InstCallback cbk, void *data, int priority = PRIORITY_DEFAULT)

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

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

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

  • pos[in] Relative position of the callback (PREINST / POSTINST).

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

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

  • priority[in] The priority of the callback.

Returns

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

uint32_t QBDI::VM::addCodeRangeCB(rword start, rword end, InstPosition pos, InstCbLambda &&cbk, int priority = PRIORITY_DEFAULT)
uint32_t QBDI::VM::addCodeRangeCB(rword start, rword end, InstPosition pos, const InstCbLambda &cbk, int priority = PRIORITY_DEFAULT)

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

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

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

  • pos[in] Relative position of the callback (PREINST / POSTINST).

  • cbk[in] A lambda function to the callback

  • priority[in] The priority of the callback.

Returns

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

uint32_t QBDI::VM::addMnemonicCB(const char *mnemonic, InstPosition pos, InstCallback cbk, void *data, int priority = PRIORITY_DEFAULT)

Register a callback event if the instruction matches the mnemonic.

Parameters
  • mnemonic[in] Mnemonic to match.

  • pos[in] Relative position of the event callback (PREINST / POSTINST).

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

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

  • priority[in] The priority of the callback.

Returns

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

uint32_t QBDI::VM::addMnemonicCB(const char *mnemonic, InstPosition pos, InstCbLambda &&cbk, int priority = PRIORITY_DEFAULT)
uint32_t QBDI::VM::addMnemonicCB(const char *mnemonic, InstPosition pos, const InstCbLambda &cbk, int priority = PRIORITY_DEFAULT)

Register a callback event if the instruction matches the mnemonic.

Parameters
  • mnemonic[in] Mnemonic to match.

  • pos[in] Relative position of the event callback (PREINST / POSTINST).

  • cbk[in] A lambda function to the callback

  • priority[in] The priority of the callback.

Returns

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

VMEvent

uint32_t QBDI::VM::addVMEventCB(VMEvent mask, VMCallback cbk, void *data)

Register a callback event for a specific VM event.

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

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

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

Returns

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

uint32_t QBDI::VM::addVMEventCB(VMEvent mask, VMCbLambda &&cbk)
uint32_t QBDI::VM::addVMEventCB(VMEvent mask, const VMCbLambda &cbk)

Register a callback event for a specific VM event.

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

  • cbk[in] A lambda function to the callback.

Returns

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

MemoryAccess

uint32_t QBDI::VM::addMemAccessCB(MemoryAccessType type, InstCallback cbk, void *data, int priority = PRIORITY_DEFAULT)

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

Parameters
Returns

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

uint32_t QBDI::VM::addMemAccessCB(MemoryAccessType type, InstCbLambda &&cbk, int priority = PRIORITY_DEFAULT)
uint32_t QBDI::VM::addMemAccessCB(MemoryAccessType type, const InstCbLambda &cbk, int priority = PRIORITY_DEFAULT)

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

Parameters
Returns

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

uint32_t QBDI::VM::addMemAddrCB(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. The callback has the default priority.

Parameters
Returns

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

uint32_t QBDI::VM::addMemAddrCB(rword address, MemoryAccessType type, InstCbLambda &&cbk)
uint32_t QBDI::VM::addMemAddrCB(rword address, MemoryAccessType type, const InstCbLambda &cbk)

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. The callback has the default priority.

Parameters
Returns

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

uint32_t QBDI::VM::addMemRangeCB(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. The callback has the default priority.

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

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

  • type[in] A mode bitfield: either QBDI::MEMORY_READ, QBDI::MEMORY_WRITE or both (QBDI::MEMORY_READ_WRITE).

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

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

Returns

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

uint32_t QBDI::VM::addMemRangeCB(rword start, rword end, MemoryAccessType type, InstCbLambda &&cbk)
uint32_t QBDI::VM::addMemRangeCB(rword start, rword end, MemoryAccessType type, const InstCbLambda &cbk)

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. The callback has the default priority.

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

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

  • type[in] A mode bitfield: either QBDI::MEMORY_READ, QBDI::MEMORY_WRITE or both (QBDI::MEMORY_READ_WRITE).

  • cbk[in] A lambda function to the callback

Returns

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

InstrRuleCallback

uint32_t QBDI::VM::addInstrRule(InstrRuleCallback cbk, AnalysisType type, void *data)

Add a custom instrumentation rule to the VM.

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

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

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

Returns

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

uint32_t QBDI::VM::addInstrRule(InstrRuleCbLambda &&cbk, AnalysisType type)
uint32_t QBDI::VM::addInstrRule(const InstrRuleCbLambda &cbk, AnalysisType type)

Add a custom instrumentation rule to the VM.

Parameters
  • cbk[in] A lambda function to the callback

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

Returns

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

uint32_t QBDI::VM::addInstrRuleRange(rword start, rword end, InstrRuleCallback cbk, AnalysisType type, void *data)

Add a custom instrumentation rule to the VM on a specify range

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

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

  • cbk[in] A function pointer to the callback

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

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

Returns

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

uint32_t QBDI::VM::addInstrRuleRange(rword start, rword end, InstrRuleCbLambda &&cbk, AnalysisType type)
uint32_t QBDI::VM::addInstrRuleRange(rword start, rword end, const InstrRuleCbLambda &cbk, AnalysisType type)

Add a custom instrumentation rule to the VM on a specify range

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

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

  • cbk[in] A lambda function to the callback

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

Returns

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

uint32_t QBDI::VM::addInstrRuleRangeSet(RangeSet<rword> range, InstrRuleCallback cbk, AnalysisType type, void *data)

Add a custom instrumentation rule to the VM on a specify set of range

Parameters
  • range[in] Range of address where apply the rule

  • cbk[in] A function pointer to the callback

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

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

Returns

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

uint32_t QBDI::VM::addInstrRuleRangeSet(RangeSet<rword> range, InstrRuleCbLambda &&cbk, AnalysisType type)
uint32_t QBDI::VM::addInstrRuleRangeSet(RangeSet<rword> range, const InstrRuleCbLambda &cbk, AnalysisType type)

Add a custom instrumentation rule to the VM on a specify set of range

Parameters
  • range[in] Range of address where apply the rule

  • cbk[in] A lambda function to the callback

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

Returns

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

Removal

bool QBDI::VM::deleteInstrumentation(uint32_t id)

Remove an instrumentation.

Parameters

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

Returns

True if instrumentation has been removed.

void QBDI::VM::deleteAllInstrumentations()

Remove all the registered instrumentations.

Run

bool QBDI::VM::run(rword start, rword stop)

Start the execution by the DBI. This method mustn’t be called if the VM already runs.

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

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

Returns

True if at least one block has been executed.

bool QBDI::VM::call(rword *retval, rword function, const std::vector<rword> &args = {})

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

Example:

// perform (with QBDI) a call similar to (*funcPtr)(42);
uint8_t *fakestack = nullptr;
QBDI::VM *vm = new QBDI::VM();
QBDI::GPRState *state = vm->getGPRState();
QBDI::allocateVirtualStack(state, 0x1000000, &fakestack);
vm->addInstrumentedModuleFromAddr(funcPtr);
rword retVal;
vm->call(&retVal, funcPtr, {42});

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

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

  • args[in] A list of arguments.

Returns

True if at least one block has been executed.

bool QBDI::VM::callA(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 if the VM already runs.

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

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

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

  • args[in] An array of arguments.

Returns

True if at least one block has been executed.

bool QBDI::VM::callV(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 if the VM already runs.

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

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

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

  • ap[in] An stdarg va_list object.

Returns

True if at least one block has been executed.

InstAnalysis

const InstAnalysis *QBDI::VM::getInstAnalysis(AnalysisType type = ANALYSIS_INSTRUCTION | ANALYSIS_DISASSEMBLY) const

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.

Parameters

[type][in] Properties to retrieve during analysis. This argument is optional, defaulting to QBDI::ANALYSIS_INSTRUCTION | QBDI::ANALYSIS_DISASSEMBLY.

Returns

A InstAnalysis structure containing the analysis result.

const InstAnalysis *QBDI::VM::getCachedInstAnalysis(rword address, AnalysisType type = ANALYSIS_INSTRUCTION | ANALYSIS_DISASSEMBLY) const

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 object.

Parameters
Returns

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

MemoryAccess

std::vector<MemoryAccess> QBDI::VM::getInstMemoryAccess() const

Obtain the memory accesses made by the last executed instruction. The method should be called in an InstCallback.

Returns

List of memory access made by the instruction.

std::vector<MemoryAccess> QBDI::VM::getBBMemoryAccess() const

Obtain the memory accesses made by the last executed basic block. The method should be called in a VMCallback with VMEvent::SEQUENCE_EXIT.

Returns

List of memory access made by the instruction.

bool QBDI::VM::recordMemoryAccess(MemoryAccessType type)

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

Parameters

type[in] Memory mode bitfield to activate the logging for: either QBDI::MEMORY_READ, QBDI::MEMORY_WRITE or both (QBDI::MEMORY_READ_WRITE).

Returns

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

Cache management

bool QBDI::VM::precacheBasicBlock(rword pc)

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

Parameters

pc[in] Start address of a basic block

Returns

True if basic block has been inserted in cache.

void QBDI::VM::clearCache(rword start, rword end)

Clear a specific address range from the translation cache.

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

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

void QBDI::VM::clearAllCache()

Clear the entire translation cache.

Register state

type QBDI::rword

An integer of the size of a register

  • uint32_t for X86

  • uint64_t for X86_64

struct QBDI::GPRState

General Purpose Register context.

For X86 architecture:

typedef struct QBDI_ALIGNED(4) {
  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 QBDI_ALIGNED(8) {
  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;
  // Only backup and restore with OPT_ENABLE_FS_GS
  rword fs;
  rword gs;
} GPRState;
struct QBDI::FPRState

Floating Point Register context.

For X86 architecture:

typedef struct QBDI_ALIGNED(16) {
  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 QBDI_ALIGNED(16) {
  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 QBDI::MMSTReg

Public Members

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

Public Members

uint16_t invalid
uint16_t denorm
uint16_t zdiv
uint16_t ovrfl
uint16_t undfl
uint16_t precis
uint16_t __pad0__
uint16_t pc
uint16_t rc
uint16_t __pad1__
uint16_t __pad2__
struct QBDI::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
QBDI::REG_RETURN
QBDI::REG_BP
QBDI::REG_SP
QBDI::REG_PC
QBDI::NUM_GPR

Callback

using QBDI::VMInstanceRef = VM*
typedef VMAction (*QBDI::InstCallback)(VMInstanceRef vm, GPRState *gprState, FPRState *fprState, void *data)

Instruction callback function type.

Param vm

[in] VM instance of the callback.

Param gprState

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

Param fprState

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

Param data

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

Return

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

typedef std::function<VMAction(VMInstanceRef vm, GPRState *gprState, FPRState *fprState)> QBDI::InstCbLambda

Instruction callback lambda type.

Param vm

[in] VM instance of the callback.

Param gprState

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

Param fprState

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

Return

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

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

VM callback function type.

Param vm

[in] VM instance of the callback.

Param vmState

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

Param gprState

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

Param fprState

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

Param data

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

Return

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

typedef std::function<VMAction(VMInstanceRef vm, const VMState *vmState, GPRState *gprState, FPRState *fprState)> QBDI::VMCbLambda

VM callback lambda type.

Param vm

[in] VM instance of the callback.

Param vmState

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

Param gprState

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

Param fprState

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

Return

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

typedef std::vector<InstrRuleDataCBK> (*QBDI::InstrRuleCallback)(VMInstanceRef vm, const InstAnalysis *inst, void *data)

Instrumentation rule callback function type.

Param vm

[in] VM instance of the callback.

Param inst

[in] AnalysisType of the current instrumented Instruction.

Param data

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

Return

Return cbk to call when this instruction is run.

typedef std::function<std::vector<InstrRuleDataCBK>(VMInstanceRef vm, const InstAnalysis *inst)> QBDI::InstrRuleCbLambda

Instrumentation rule callback lambda type.

Param vm

[in] VM instance of the callback.

Param inst

[in] AnalysisType of the current instrumented Instruction.

Return

Return cbk to call when this instruction is run.

struct QBDI::InstrRuleDataCBK

Public Members

InstPosition position

Relative position of the event callback (PREINST / POSTINST).

InstCallback cbk

Address of the function to call when the instruction is executed.

void *data

User defined data which will be forward to cbk

InstCbLambda lambdaCbk

Lambda callback. Replace cbk and data if not nullptr

int priority

Priority of the callback

enum QBDI::InstPosition

Position relative to an instruction.

Values:

enumerator PREINST

Positioned before the instruction.

enumerator POSTINST

Positioned after the instruction.

enum QBDI::CallbackPriority

Priority of callback

A callback with an higher priority will be call before a callback with a lower priority.

ie:

  1. CBpre(p = 10)

  2. CBpre(p = 0)

  3. CBpre(p = -10)

  4. instrumented instruction

  5. CBpost(p = 10)

  6. CBpost(p = 0)

  7. CBpost(p = -10)

When the MemoryAccess API is used in a callback, the priority of the callback must not be greater than PRIORITY_MEMACCESS_LIMIT

Values:

enumerator PRIORITY_DEFAULT

Default priority for callback

enumerator PRIORITY_MEMACCESS_LIMIT

Maximum priority if getInstMemoryAccess is used in the callback

enum QBDI::VMAction

The callback results.

Values:

enumerator CONTINUE

The execution of the basic block continues.

enumerator SKIP_INST

Available only with PREINST InstCallback. The instruction and the remained PREINST callbacks are skip. The execution continue with the POSTINST instruction.

We recommand to used this result with a low priority PREINST callback in order to emulate the instruction without skipping the POSTINST callback.

enumerator SKIP_PATCH

Available only with InstCallback. The current instruction and the reminding callback (PRE and POST) are skip. The execution continues to the next instruction.

For instruction that change the instruction pointer (jump/call/ret), BREAK_TO_VM must be used insted of SKIP.

SKIP can break the record of MemoryAccess for the current instruction.

enumerator 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 STOP

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

InstAnalysis

enum QBDI::AnalysisType

Instruction analysis type

Values:

enumerator ANALYSIS_INSTRUCTION

Instruction analysis (address, mnemonic, …)

enumerator ANALYSIS_DISASSEMBLY

Instruction disassembly

enumerator ANALYSIS_OPERANDS

Instruction operands analysis

enumerator ANALYSIS_SYMBOL

Instruction symbol

struct QBDI::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)

CPUMode cpuMode

Instruction CPU mode

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 isMoveImm

true if this instruction is a move immediate (including conditional moves) instruction.

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 QBDI::ConditionType

Instruction Condition

Values:

enumerator CONDITION_NONE

The instruction is unconditionnal

enumerator CONDITION_ALWAYS

The instruction is always true

enumerator CONDITION_NEVER

The instruction is always false

enumerator CONDITION_EQUALS

Equals (‘==’)

enumerator CONDITION_NOT_EQUALS

Not Equals (‘!=’)

enumerator CONDITION_ABOVE

Above (‘>’ unsigned)

enumerator CONDITION_BELOW_EQUALS

Below or Equals (‘<=’ unsigned)

enumerator CONDITION_ABOVE_EQUALS

Above or Equals (‘>=’ unsigned)

enumerator CONDITION_BELOW

Below (‘<’ unsigned)

enumerator CONDITION_GREAT

Great (‘>’ signed)

enumerator CONDITION_LESS_EQUALS

Less or Equals (‘<=’ signed)

enumerator CONDITION_GREAT_EQUALS

Great or Equals (‘>=’ signed)

enumerator CONDITION_LESS

Less (‘<’ signed)

enumerator CONDITION_EVEN

Even

enumerator CONDITION_ODD

Odd

enumerator CONDITION_OVERFLOW

Overflow

enumerator CONDITION_NOT_OVERFLOW

Not Overflow

enumerator CONDITION_SIGN

Sign

enumerator CONDITION_NOT_SIGN

Not Sign

struct QBDI::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 QBDI::OperandType

Operand type

Values:

enumerator OPERAND_INVALID

Invalid operand

enumerator OPERAND_IMM

Immediate operand

enumerator OPERAND_GPR

Register operand

enumerator OPERAND_PRED

Predicate operand

enumerator OPERAND_FPR

Float register operand

enumerator OPERAND_SEG

Segment or unsupported register operand

enum QBDI::OperandFlag

Values:

enumerator OPERANDFLAG_NONE

No flag

enumerator OPERANDFLAG_ADDR

The operand is used to compute an address

enumerator OPERANDFLAG_PCREL

The value of the operand is PC relative

enumerator OPERANDFLAG_UNDEFINED_EFFECT

The operand role isn’t fully defined

enumerator OPERANDFLAG_IMPLICIT

The operand is implicit

enum QBDI::RegisterAccessType

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

Values:

enumerator REGISTER_UNUSED

Unused register

enumerator REGISTER_READ

Register read access

enumerator REGISTER_WRITE

Register write access

enumerator REGISTER_READ_WRITE

Register read/write access

MemoryAccess

struct QBDI::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 QBDI::MemoryAccessType

Memory access type (read / write / …)

Values:

enumerator MEMORY_READ

Memory read access

enumerator MEMORY_WRITE

Memory write access

enumerator MEMORY_READ_WRITE

Memory read/write access

enum QBDI::MemoryAccessFlags

Memory access flags

Values:

enumerator MEMORY_NO_FLAGS
enumerator MEMORY_UNKNOWN_SIZE

The size of the access isn’t known.

enumerator MEMORY_MINIMUM_SIZE

The given size is a minimum size.

enumerator MEMORY_UNKNOWN_VALUE

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

VMEvent

enum QBDI::VMEvent

Values:

enumerator NO_EVENT
enumerator SEQUENCE_ENTRY

Triggered when the execution enters a sequence.

enumerator SEQUENCE_EXIT

Triggered when the execution exits from the current sequence.

enumerator BASIC_BLOCK_ENTRY

Triggered when the execution enters a basic block.

enumerator BASIC_BLOCK_EXIT

Triggered when the execution exits from the current basic block.

enumerator BASIC_BLOCK_NEW

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

enumerator EXEC_TRANSFER_CALL

Triggered when the ExecBroker executes an execution transfer.

enumerator EXEC_TRANSFER_RETURN

Triggered when the ExecBroker returns from an execution transfer.

enumerator SYSCALL_ENTRY

Not implemented.

enumerator SYSCALL_EXIT

Not implemented.

enumerator SIGNAL

Not implemented.

struct QBDI::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.

Parameters
  • size[in] Allocation size in bytes.

  • align[in] Base address alignement in bytes.

Returns

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

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().

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

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

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

Returns

True if stack allocation was successfull.

void QBDI::alignedFree(void *ptr)

Free a block of aligned memory allocated with alignedAlloc.

Parameters

ptr[in] Pointer to the allocated memory.

void QBDI::simulateCall(GPRState *ctx, rword returnAddress, const std::vector<rword> &args = {})

Simulate a call by modifying the stack and registers accordingly (std::vector version).

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

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

  • args[in] A 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
  • ctx[in] GPRState where the simulated call will be setup. The state needs to point to a valid stack for example setup with allocateVirtualStack().

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

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

  • ap[in] 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
  • ctx[in] GPRState where the simulated call will be setup. The state needs to point to a valid stack for example setup with allocateVirtualStack().

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

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

  • args[in] An array or arguments.

Exploration

std::vector<std::string> QBDI::getModuleNames()

Get a list of all the module names loaded in the process memory.

Returns

A vector of string of module names.

std::vector<MemoryMap> QBDI::getCurrentProcessMaps(bool full_path = false)

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

Parameters

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

Returns

A vector of MemoryMap object.

std::vector<MemoryMap> QBDI::getRemoteProcessMaps(QBDI::rword pid, bool full_path = false)

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

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

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

Returns

A vector of MemoryMap object.

struct QBDI::MemoryMap

Map of a memory area (region).

Public Members

Range<rword> range

A range of memory (region), delimited between a start and an (excluded) end address.

Permission permission

Region access rights (PF_READ, PF_WRITE, PF_EXEC).

std::string name

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

enum QBDI::Permission

Memory access rights.

Values:

enumerator PF_NONE

No access

enumerator PF_READ

Read access

enumerator PF_WRITE

Write access

enumerator PF_EXEC

Execution access

Other globals

enum QBDI::Options

Values:

enumerator NO_OPT

Default value

enumerator OPT_DISABLE_FPR

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

enumerator OPT_DISABLE_OPTIONAL_FPR

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

enumerator OPT_ATT_SYNTAX

Used the AT&T syntax for instruction disassembly

enumerator OPT_ENABLE_FS_GS

Enable Backup/Restore of FS/GS segment. This option uses the instructions (RD|WR)(FS|GS)BASE that must be supported by the operating system

enum QBDI::VMError

QBDI Error values

Values:

enumerator INVALID_EVENTID

Mark a returned event id as invalid

Miscellaneous

Version

inline const char *QBDI::getVersion(uint32_t *version)

Return QBDI version.

Parameters

version[out] QBDI version encoded as an unsigned integer (0xMMmmpp).

Returns

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

Log

enum QBDI::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 DEBUG

Debug logs

enumerator INFO

Info logs (default)

enumerator WARNING

Warning logs

enumerator ERROR

Error logs

enumerator DISABLE

Disable logs message

void QBDI::setLogFile(const std::string &filename, bool truncate = false)

Redirect logs to a file.

Parameters
  • filename[in] the path of the file to append the log

  • truncate[in] Set to true to clear the file before append the log

inline void QBDI::setLogPriority(LogPriority priority = LogPriority::INFO)

Enable logs matching priority.

Parameters

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

inline void QBDI::setLogConsole()

Write log to the console (stderr)

inline void QBDI::setLogDefault()

Write log to the default location (stderr for linux, android_logger for android)

Range

template<typename T>
class QBDI::Range

Public Functions

inline T start() const
inline T end() const
inline void setStart(const T start)
inline void setEnd(const T end)
inline Range(const T start, const T end)

Construct a new range.

Parameters
  • start[in] Range start value.

  • end[in] Range end value (excluded).

inline T size() const

Return the total length of a range.

inline bool operator==(const Range &r) const

Return True if two ranges are equal (same boundaries).

Parameters

r[in] Range to check.

Returns

True if equal.

inline bool contains(const T t) const

Return True if an value is inside current range boundaries.

Parameters

t[in] Value to check.

Returns

True if contained.

inline bool contains(const Range<T> &r) const

Return True if a range is inside current range boundaries.

Parameters

r[in] Range to check.

Returns

True if contained.

inline bool overlaps(const Range<T> &r) const

Return True if a range is overlapping current range lower or/and upper boundary.

Parameters

r[in] Range to check.

Returns

True if overlapping.

inline void display(std::ostream &os) const

Pretty print a range

Parameters

os[in] An output stream.

inline Range<T> intersect(const Range<T> &r) const

Return the intersection of two ranges.

Parameters

r[in] Range to intersect with current range.

Returns

A new range.

template<typename T>
class QBDI::RangeSet

Public Functions

inline RangeSet()
inline const std::vector<Range<T>> &getRanges() const
inline T size() const
inline bool contains(const T t) const
inline bool contains(const Range<T> &t) const
inline bool overlaps(const Range<T> &t) const
inline void add(const Range<T> &t)
inline void add(const RangeSet<T> &t)
inline void remove(const Range<T> &t)
inline void remove(const RangeSet<T> &t)
inline void intersect(const RangeSet<T> &t)
inline void intersect(const Range<T> &t)
inline void clear()
inline void display(std::ostream &os) const
inline bool operator==(const RangeSet &r) const