1
0
Fork 0
x64dbg/x64_dbg_gui/Project/Src/Disassembler/QBeaEngine.cpp

189 lines
5.7 KiB
C++

#include "QBeaEngine.h"
QBeaEngine::QBeaEngine()
{
// Reset the Disasm structure
memset(&mDisasmStruct, 0, sizeof(DISASM));
BeaTokenizer::Init();
}
/**
* @brief Return the address of the nth instruction before the instruction pointed by ip. @n
* This function has been grabbed from OllyDbg ("Disassembleback" in asmserv.c)
*
* @param[in] data Address of the data to disassemble
* @param[in] base Original base address of the memory page (Required to disassemble destination addresses)
* @param[in] size Size of the data block pointed by data
* @param[in] ip RVA of the current instruction (Relative to data pointer)
* @param[in] n Number of instruction back
*
* @return Return the RVA (Relative to the data pointer) of the nth instruction before the instruction pointed by ip
*/
ulong QBeaEngine::DisassembleBack(byte_t* data, uint_t base, uint_t size, uint_t ip, int n)
{
const unsigned int max_instructions = 128;
Q_UNUSED(base);
int i;
uint_t abuf[131], addr, back, cmdsize;
byte_t* pdata;
int len;
// Reset Disasm Structure
memset(&mDisasmStruct, 0, sizeof(DISASM));
#ifdef _WIN64
mDisasmStruct.Archi = 64;
#endif
mDisasmStruct.Options = NoformatNumeral;
// Check if the pointer is not null
if(data == NULL)
return 0;
// Round the number of back instructions to 127
if(n < 0)
n = 0;
else if(n >= max_instructions)
n = max_instructions - 1;
// Check if the instruction pointer ip is not outside the memory range
if(ip >= size)
ip = size - 1;
// Obvious answer
if(n == 0)
return ip;
if(ip < (uint_t)n)
return ip;
back = 16 * (n + 3); // Instruction length limited to 16
if(ip < back)
back = ip;
addr = ip - back;
pdata = data + addr;
for(i = 0; addr < ip; i++)
{
abuf[i % max_instructions] = addr;
mDisasmStruct.EIP = (UIntPtr)pdata;
len = Disasm(&mDisasmStruct);
cmdsize = (len < 1) ? 1 : len ;
pdata += cmdsize;
addr += cmdsize;
back -= cmdsize;
}
if(i < n)
return abuf[0];
else
return abuf[(i - n + max_instructions) % max_instructions];
}
/**
* @brief Return the address of the nth instruction after the instruction pointed by ip. @n
* This function has been grabbed from OllyDbg ("Disassembleforward" in asmserv.c)
*
* @param[in] data Address of the data to disassemble
* @param[in] base Original base address of the memory page (Required to disassemble destination addresses)
* @param[in] size Size of the data block pointed by data
* @param[in] ip RVA of the current instruction (Relative to data pointer)
* @param[in] n Number of instruction next
*
* @return Return the RVA (Relative to the data pointer) of the nth instruction after the instruction pointed by ip
*/
ulong QBeaEngine::DisassembleNext(byte_t* data, uint_t base, uint_t size, uint_t ip, int n)
{
Q_UNUSED(base);
int i;
uint_t cmdsize;
byte_t* pdata;
int len;
// Reset Disasm Structure
memset(&mDisasmStruct, 0, sizeof(DISASM));
#ifdef _WIN64
mDisasmStruct.Archi = 64;
#endif
mDisasmStruct.Options = NoformatNumeral;
if(data == NULL)
return 0;
if(ip >= size)
ip = size - 1;
if(n <= 0)
return ip;
pdata = data + ip;
size -= ip;
for(i = 0; i < n && size > 0; i++)
{
mDisasmStruct.EIP = (UIntPtr)pdata;
mDisasmStruct.SecurityBlock = (UIntPtr)size;
len = Disasm(&mDisasmStruct);
cmdsize = (len < 1) ? 1 : len;
pdata += cmdsize;
ip += cmdsize;
size -= cmdsize;
}
return ip;
}
/**
* @brief Disassemble the instruction at the given ip RVA.
*
* @param[in] data Pointer to memory data (Can be either a buffer or the original data memory)
* @param[in] size Size of the memory pointed by data (Can be the memory page size if data points to the original memory page base address)
* @param[in] instIndex Offset to reach the instruction data from the data pointer
* @param[in] origBase Original base address of the memory page (Required to disassemble destination addresses)
* @param[in] origInstRVA Original Instruction RVA of the instruction to disassemble
*
* @return Return the disassembled instruction
*/
Instruction_t QBeaEngine::DisassembleAt(byte_t* data, uint_t size, uint_t instIndex, uint_t origBase, uint_t origInstRVA)
{
Instruction_t wInst;
int len;
// Reset Disasm Structure
memset(&mDisasmStruct, 0, sizeof(DISASM));
#ifdef _WIN64
mDisasmStruct.Archi = 64;
#endif
mDisasmStruct.Options = NoformatNumeral | ShowSegmentRegs;
mDisasmStruct.EIP = (UIntPtr)((uint_t)data + (uint_t)instIndex);
mDisasmStruct.VirtualAddr = origBase + origInstRVA;
mDisasmStruct.SecurityBlock = (UIntPtr)((uint_t)size - instIndex);
len = Disasm(&mDisasmStruct);
len = (len < 1) ? 1 : len ;
wInst.instStr = QString(mDisasmStruct.CompleteInstr);
int instrLen = wInst.instStr.length();
if(instrLen && wInst.instStr.at(instrLen - 1) == ' ')
wInst.instStr.chop(1);
wInst.dump = QByteArray((char*)mDisasmStruct.EIP, len);
wInst.rva = origInstRVA;
wInst.length = len;
wInst.disasm = mDisasmStruct;
//tokenize
BeaTokenizer::TokenizeInstruction(&wInst.tokens, &mDisasmStruct);
return wInst;
}