1
0
Fork 0

DBG+GUI+PROJECT: removed BeaEngine and completely moved to capstone in the GUI.

This commit is contained in:
Mr. eXoDia 2015-10-28 04:02:23 +01:00
parent ec947144e0
commit 0cb27a182c
21 changed files with 146 additions and 1542 deletions

View File

@ -24,7 +24,6 @@ mkdir %RELEASEDIR%\bin_base\x64
copy bin\x32\x32_bridge.dll %RELEASEDIR%\bin_base\x32\x32_bridge.dll
copy bin\x32\x32_dbg.dll %RELEASEDIR%\bin_base\x32\x32_dbg.dll
copy bin\x32\BeaEngine.dll %RELEASEDIR%\bin_base\x32\BeaEngine.dll
copy bin\x32\capstone.dll %RELEASEDIR%\bin_base\x32\capstone.dll
copy bin\x32\dbghelp.dll %RELEASEDIR%\bin_base\x32\dbghelp.dll
copy bin\x32\symsrv.dll %RELEASEDIR%\bin_base\x32\symsrv.dll
@ -38,7 +37,6 @@ copy bin\x32\yara.dll %RELEASEDIR%\bin_base\x32\yara.dll
copy bin\x32\snowman.dll %RELEASEDIR%\bin_base\x32\snowman.dll
copy bin\x64\x64_bridge.dll %RELEASEDIR%\bin_base\x64\x64_bridge.dll
copy bin\x64\x64_dbg.dll %RELEASEDIR%\bin_base\x64\x64_dbg.dll
copy bin\x64\BeaEngine.dll %RELEASEDIR%\bin_base\x64\BeaEngine.dll
copy bin\x64\capstone.dll %RELEASEDIR%\bin_base\x64\capstone.dll
copy bin\x64\dbghelp.dll %RELEASEDIR%\bin_base\x64\dbghelp.dll
copy bin\x64\symsrv.dll %RELEASEDIR%\bin_base\x64\symsrv.dll

View File

@ -1998,15 +1998,9 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[])
}
Capstone cp;
if(cp.GetError()) //there was an error opening the handle
{
dprintf("cs_open() failed, error code %u\n", cp.GetError());
return STATUS_ERROR;
}
if(!cp.Disassemble(addr, data))
{
dprintf("failed to disassemble, error code %u!", cp.GetError());
dprintf("failed to disassemble!");
return STATUS_ERROR;
}

View File

@ -695,13 +695,13 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, int_t addr)
int_t selHeadRVA = mSelection.fromIndex;
int_t rva = addr;
Instruction_t instruction = DisassembleAt(selHeadRVA);
Int32 branchType = instruction.disasm.Instruction.BranchType;
auto branchType = instruction.branchType;
GraphicDump_t wPict = GD_Nothing;
if(branchType && branchType != RetType && branchType != CallType)
if(branchType != Instruction_t::None)
{
int_t destRVA = (int_t)DbgGetBranchDestination(rvaToVa(instruction.rva));
int_t destRVA = instruction.branchDestination;
int_t base = mMemPage->getBase();
if(destRVA >= base && destRVA < base + (int_t)mMemPage->getSize())
@ -731,7 +731,7 @@ int Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, int_t addr)
bool bIsExecute = DbgIsJumpGoingToExecute(rvaToVa(instruction.rva));
if(branchType == JmpType) //unconditional
if(branchType == Instruction_t::Unconditional) //unconditional
{
painter->setPen(ConfigColor("DisassemblyUnconditionalJumpLineColor"));
}

View File

@ -275,7 +275,6 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
return 0;
QBeaEngine disasm(-1);
Instruction_t instr = disasm.DisassembleAt(wBuffer, 16, 0, 0, parVA);
BeaTokenizer::TokenizeInstruction(&instr.tokens, &instr.disasm, -1);
QList<RichTextPainter::CustomRichText_t> richText;
BeaTokenizer::TokenToRichText(&instr.tokens, &richText, 0);
QString finalInstruction = "";

View File

@ -3,352 +3,6 @@
//variables
QMap<BeaTokenizer::BeaTokenType, BeaTokenizer::BeaTokenColor> BeaTokenizer::colorNamesMap;
QStringList BeaTokenizer::segmentNames;
QMap<int, QString> BeaTokenizer::memSizeNames;
QMap<int, QMap<ARGUMENTS_TYPE, QString>> BeaTokenizer::registerMap;
QSet<int> BeaTokenizer::repSet;
//functions
BeaTokenizer::BeaTokenizer()
{
}
void BeaTokenizer::AddToken(BeaInstructionToken* instr, const BeaTokenType type, const QString text, const BeaTokenValue* value)
{
BeaSingleToken token;
token.type = type;
if(type != TokenSpace && type != TokenArgumentSpace && type != TokenMemoryOperatorSpace)
token.text = text.trimmed(); //remove whitespaces from the start and end
else
token.text = text;
if(value)
token.value = *value;
else
{
if(ConfigBool("Disassembler", "Uppercase"))
token.text = token.text.toUpper();
token.value.size = 0;
token.value.value = 0;
}
instr->tokens.push_back(token);
}
void BeaTokenizer::Prefix(BeaInstructionToken* instr, const DISASM* disasm)
{
if(disasm->Prefix.LockPrefix)
{
AddToken(instr, TokenPrefix, "lock", 0);
AddToken(instr, TokenSpace, " ", 0);
}
if(disasm->Prefix.RepPrefix)
{
if(repSet.contains(disasm->Instruction.Opcode))
{
AddToken(instr, TokenPrefix, "rep", 0);
AddToken(instr, TokenSpace, " ", 0);
}
}
if(disasm->Prefix.RepnePrefix)
{
if(repSet.contains(disasm->Instruction.Opcode))
{
AddToken(instr, TokenPrefix, "repne", 0);
AddToken(instr, TokenSpace, " ", 0);
}
}
}
bool BeaTokenizer::IsNopInstruction(QString mnemonic, const DISASM* disasm)
{
Q_UNUSED(disasm);
//TODO: add instructions like "mov eax,eax" and "xchg ebx,ebx" and "lea eax,[eax]"
if(mnemonic == "nop")
return true;
return false;
}
void BeaTokenizer::StringInstructionMemory(BeaInstructionToken* instr, int size, QString segment, ARGUMENTS_TYPE reg)
{
if(memSizeNames.contains(size))
AddToken(instr, TokenMemorySize, memSizeNames.find(size).value() + " ptr", 0);
else
AddToken(instr, TokenMemorySize, "??? ptr", 0);
AddToken(instr, TokenSpace, " ", 0);
AddToken(instr, TokenMemorySegment, segment, 0);
AddToken(instr, TokenUncategorized, ":", 0);
AddToken(instr, TokenMemoryBrackets, "[", 0);
AddToken(instr, TokenMemoryBaseRegister, RegisterToString(sizeof(int_t) * 8, reg), 0); //EDI/RDI
AddToken(instr, TokenMemoryBrackets, "]", 0);
}
void BeaTokenizer::StringInstruction(QString mnemonic, BeaInstructionToken* instr, const DISASM* disasm)
{
AddToken(instr, TokenMnemonicNormal, mnemonic, 0);
AddToken(instr, TokenSpace, " ", 0);
if(mnemonic == "movs")
{
StringInstructionMemory(instr, disasm->Argument1.ArgSize, "es", REG7); //EDI/RDI
AddToken(instr, TokenComma, ",", 0);
AddToken(instr, TokenArgumentSpace, " ", 0);
StringInstructionMemory(instr, disasm->Argument1.ArgSize, "ds", REG6); //ESI/RSI
}
else if(mnemonic == "cmps")
{
StringInstructionMemory(instr, disasm->Argument1.ArgSize, "ds", REG6); //EDI/RDI
AddToken(instr, TokenComma, ",", 0);
AddToken(instr, TokenArgumentSpace, " ", 0);
StringInstructionMemory(instr, disasm->Argument1.ArgSize, "es", REG7); //ESI/RSI
}
else if(mnemonic == "scas" || mnemonic == "stos")
StringInstructionMemory(instr, disasm->Argument1.ArgSize, "es", REG7); //ESI/RSI
else if(mnemonic == "lods")
StringInstructionMemory(instr, disasm->Argument1.ArgSize, "ds", REG6); //ESI/RSI
else if(mnemonic == "outs")
{
AddToken(instr, TokenGeneralRegister, "dx", 0);
AddToken(instr, TokenComma, ",", 0);
AddToken(instr, TokenArgumentSpace, " ", 0);
StringInstructionMemory(instr, disasm->Argument2.ArgSize, "es", REG6); //EDI/RDI
}
}
void BeaTokenizer::Mnemonic(BeaInstructionToken* instr, const DISASM* disasm)
{
QString mnemonic = QString(disasm->Instruction.Mnemonic).trimmed().toLower();
bool farMnemonic = mnemonic.contains(" far");
if(farMnemonic)
mnemonic.truncate(mnemonic.indexOf(" far"));
QString completeInstr = QString(disasm->CompleteInstr).trimmed().toLower();
BeaTokenType type = TokenMnemonicNormal;
int brtype = disasm->Instruction.BranchType;
if(brtype) //jump/call
{
if(brtype == CallType)
type = TokenMnemonicCall;
else if(brtype == RetType)
type = TokenMnemonicRet;
else if(brtype == JmpType)
type = TokenMnemonicUncondJump;
else //cond jump
type = TokenMnemonicCondJump;
}
else if(mnemonic == "push" || mnemonic == "pop")
type = TokenMnemonicPushPop;
else if(IsNopInstruction(mnemonic, disasm)) //nop instructions
type = TokenMnemonicNop;
else if(mnemonic == "int3" || mnemonic == "int 3") //int3 instruction on request
type = TokenMnemonicInt3;
else if(completeInstr.contains("movs") || completeInstr.contains("cmps") || completeInstr.contains("scas") || completeInstr.contains("lods") || completeInstr.contains("stos") || completeInstr.contains("outs"))
{
completeInstr = completeInstr.replace("rep ", "").replace("repne ", "");
if(completeInstr.length() != 5)
{
AddToken(instr, type, mnemonic, 0);
return;
}
if(mnemonic[4] == 'b' || mnemonic[4] == 'w' || mnemonic[4] == 'd' || mnemonic[4] == 'q')
{
mnemonic.truncate(4);
StringInstruction(mnemonic, instr, disasm);
}
else
AddToken(instr, type, mnemonic, 0);
return;
}
AddToken(instr, type, mnemonic, 0);
if(farMnemonic)
{
AddToken(instr, TokenSpace, " ", 0);
AddToken(instr, TokenMnemonicFar, "far", 0);
}
if(ConfigBool("Disassembler", "TabbedMnemonic"))
{
int spaceCount = 7 - mnemonic.length();
if(spaceCount > 0)
{
for(int i = 0; i < spaceCount; i++)
AddToken(instr, TokenSpace, " ", 0);
}
}
}
QString BeaTokenizer::PrintValue(const BeaTokenValue* value, bool module, int maxModuleSize)
{
char labelText[MAX_LABEL_SIZE] = "";
char module_[MAX_MODULE_SIZE] = "";
QString moduleText;
int_t addr = value->value;
bool bHasLabel = DbgGetLabelAt(addr, SEG_DEFAULT, labelText);
bool bHasModule = (module && DbgGetModuleAt(addr, module_) && !QString(labelText).startsWith("JMP.&"));
moduleText = QString(module_);
if(maxModuleSize != -1)
moduleText.truncate(maxModuleSize);
if(moduleText.length())
moduleText += ".";
QString addrText;
addrText = QString("%1").arg(addr & (uint_t) - 1, 0, 16, QChar('0')).toUpper();
QString finalText;
if(bHasLabel && bHasModule) //<module.label>
finalText = QString("<%1%2>").arg(moduleText).arg(labelText);
else if(bHasModule) //module.addr
finalText = QString("%1%2").arg(moduleText).arg(addrText);
else if(bHasLabel) //<label>
finalText = QString("<%1>").arg(labelText);
else
finalText = addrText;
return finalText;
}
QString BeaTokenizer::RegisterToString(int size, int reg)
{
ARGUMENTS_TYPE regValue = (ARGUMENTS_TYPE)(reg & 0xFFFF);
if(!registerMap.contains(size)) //invalid size
return QString("UNKNOWN_REGISTER(size:%1)").arg(size);
QMap<ARGUMENTS_TYPE, QString>* currentMap = &registerMap.find(size).value();
if(!currentMap->contains(regValue))
return QString("UNKNOWN_REGISTER(reg:%1)").arg(reg);
return currentMap->find(regValue).value();
}
void BeaTokenizer::Argument(BeaInstructionToken* instr, const DISASM* disasm, const ARGTYPE* arg, bool* hadarg, int maxModuleSize)
{
if(arg->ArgType == NO_ARGUMENT || !arg->ArgMnemonic[0]) //empty/implicit argument
return;
if(*hadarg) //there already was an argument before this one
{
AddToken(instr, TokenComma, ",", 0);
AddToken(instr, TokenArgumentSpace, " ", 0);
}
else //no arg yet (only prefix/mnemonic)
AddToken(instr, TokenSpace, " ", 0);
//print argument
QString argMnemonic = QString(arg->ArgMnemonic).toLower().trimmed();
if((arg->ArgType & MEMORY_TYPE) == MEMORY_TYPE && QString(disasm->CompleteInstr).contains('[')) //memory argument
{
//#size ptr #segment:[#BaseRegister + #IndexRegister*#Scale +/- #Displacement]
if(memSizeNames.contains(arg->ArgSize))
AddToken(instr, TokenMemorySize, memSizeNames.find(arg->ArgSize).value() + " ptr", 0);
else
AddToken(instr, TokenMemorySize, QString().sprintf("???(%d) ptr", arg->ArgSize), 0);
AddToken(instr, TokenSpace, " ", 0);
AddToken(instr, TokenMemorySegment, segmentNames.at(arg->SegmentReg), 0);
AddToken(instr, TokenUncategorized, ":", 0);
BeaTokenType bracketsType = TokenMemoryBrackets;
if((arg->Memory.BaseRegister & REG4) == REG4 || (arg->Memory.BaseRegister & REG5) == REG5) //ESP/EBP
bracketsType = TokenMemoryStackBrackets;
AddToken(instr, bracketsType, "[", 0);
bool prependPlusMinus = false;
if(arg->Memory.BaseRegister) //base register
{
AddToken(instr, TokenMemoryBaseRegister, RegisterToString(sizeof(int_t) * 8, arg->Memory.BaseRegister), 0);
prependPlusMinus = true;
}
if(arg->Memory.IndexRegister) //index register + scale
{
if(prependPlusMinus)
{
AddToken(instr, TokenMemoryOperatorSpace, " ", 0);
AddToken(instr, TokenMemoryOperator, "+", 0);
AddToken(instr, TokenMemoryOperatorSpace, " ", 0);
}
AddToken(instr, TokenMemoryIndexRegister, RegisterToString(sizeof(int_t) * 8, arg->Memory.IndexRegister), 0);
int scale = arg->Memory.Scale;
if(scale > 1) //eax * 1 = eax
{
AddToken(instr, TokenMemoryOperatorSpace, " ", 0);
AddToken(instr, TokenMemoryOperator, "*", 0);
AddToken(instr, TokenMemoryOperatorSpace, " ", 0);
AddToken(instr, TokenMemoryScale, QString("%1").arg(arg->Memory.Scale), 0);
}
prependPlusMinus = true;
}
//displacement
BeaTokenValue displacement;
displacement.size = arg->ArgSize;
if((arg->ArgType & RELATIVE_) == RELATIVE_) //rip-relative displacement
displacement.value = disasm->Instruction.AddrValue;
else //direct displacement
displacement.value = arg->Memory.Displacement;
if(displacement.value || !prependPlusMinus) //support dword ptr fs:[0]
{
BeaTokenValue printDisplacement = displacement;
QString plusMinus = "+";
if(printDisplacement.value < 0) //negative -> '-(displacement*-1)'
{
printDisplacement.value *= -1;
printDisplacement.size = arg->ArgSize / 8;
plusMinus = "-";
}
if(prependPlusMinus)
{
AddToken(instr, TokenMemoryOperatorSpace, " ", 0);
AddToken(instr, TokenMemoryOperator, plusMinus, 0);
AddToken(instr, TokenMemoryOperatorSpace, " ", 0);
}
BeaTokenType type = TokenValue;
if(DbgMemIsValidReadPtr(displacement.value)) //pointer
type = TokenAddress;
AddToken(instr, type, PrintValue(&printDisplacement, false, maxModuleSize), &displacement);
}
AddToken(instr, bracketsType, "]", 0);
}
else if(disasm->Instruction.BranchType != 0 && disasm->Instruction.BranchType != RetType && (arg->ArgType & RELATIVE_) == RELATIVE_) //jump/call
{
BeaTokenValue value;
value.size = arg->ArgSize / 8;
value.value = disasm->Instruction.AddrValue;
AddToken(instr, TokenAddress, PrintValue(&value, true, maxModuleSize), &value);
}
else if((arg->ArgType & CONSTANT_TYPE) == CONSTANT_TYPE) //immediat
{
BeaTokenValue value;
value.size = arg->ArgSize / 8;
//nice little hack
LONGLONG val;
sscanf_s(arg->ArgMnemonic, "%llX", &val);
value.value = val;
/*
switch(value.size)
{
case 1:
value.value=(char)disasm->Instruction.Immediat;
break;
case 2:
value.value=(short)disasm->Instruction.Immediat;
break;
case 4:
value.value=(int)disasm->Instruction.Immediat;
break;
case 8:
value.value=(long long)disasm->Instruction.Immediat;
break;
}
*/
BeaTokenType type = TokenValue;
if(DbgMemIsValidReadPtr(value.value)) //pointer
type = TokenAddress;
AddToken(instr, type, PrintValue(&value, true, maxModuleSize), &value);
}
else if((arg->ArgType & REGISTER_TYPE) == REGISTER_TYPE) //registers
{
BeaTokenType type = TokenGeneralRegister; //general x86/unknown register
if((arg->ArgType & FPU_REG) == FPU_REG) //floating point register
type = TokenFpuRegister;
else if((arg->ArgType & MMX_REG) == MMX_REG) //MMX register
type = TokenMmxRegister;
else if((arg->ArgType & SSE_REG) == SSE_REG) //SSE register
type = TokenSseRegister;
AddToken(instr, type, argMnemonic, 0);
}
else //other
AddToken(instr, TokenUncategorized, argMnemonic, 0);
*hadarg = true; //we now added an argument
}
void BeaTokenizer::AddColorName(BeaTokenType type, QString color, QString backgroundColor)
{
@ -360,112 +14,6 @@ void BeaTokenizer::AddColorName(BeaTokenType type, QString color, QString backgr
void BeaTokenizer::Init()
{
registerMap.clear();
#ifdef _WIN64
QMap<ARGUMENTS_TYPE, QString> Registers8Bits64;
Registers8Bits64.insert(REG0, "al");
Registers8Bits64.insert(REG1, "cl");
Registers8Bits64.insert(REG2, "dl");
Registers8Bits64.insert(REG3, "bl");
Registers8Bits64.insert(REG4, "spl");
Registers8Bits64.insert(REG5, "bpl");
Registers8Bits64.insert(REG6, "sil");
Registers8Bits64.insert(REG7, "dil");
Registers8Bits64.insert(REG8, "r8b");
Registers8Bits64.insert(REG9, "r9b");
Registers8Bits64.insert(REG10, "r10b");
Registers8Bits64.insert(REG11, "r11b");
Registers8Bits64.insert(REG12, "r12b");
Registers8Bits64.insert(REG13, "r13b");
Registers8Bits64.insert(REG14, "r14b");
Registers8Bits64.insert(REG15, "r15b");
registerMap.insert(8, Registers8Bits64);
QMap<ARGUMENTS_TYPE, QString> Registers64Bits;
Registers64Bits.insert(REG0, "rax");
Registers64Bits.insert(REG1, "rcx");
Registers64Bits.insert(REG2, "rdx");
Registers64Bits.insert(REG3, "rbx");
Registers64Bits.insert(REG4, "rsp");
Registers64Bits.insert(REG5, "rbp");
Registers64Bits.insert(REG6, "rsi");
Registers64Bits.insert(REG7, "rdi");
Registers64Bits.insert(REG8, "r8");
Registers64Bits.insert(REG9, "r9");
Registers64Bits.insert(REG10, "r10");
Registers64Bits.insert(REG11, "r11");
Registers64Bits.insert(REG12, "r12");
Registers64Bits.insert(REG13, "r13");
Registers64Bits.insert(REG14, "r14");
Registers64Bits.insert(REG15, "r15");
registerMap.insert(64, Registers64Bits);
#else //x86
QMap<ARGUMENTS_TYPE, QString> Registers8Bits32;
Registers8Bits32.insert(REG0, "al");
Registers8Bits32.insert(REG1, "cl");
Registers8Bits32.insert(REG2, "dl");
Registers8Bits32.insert(REG3, "bl");
Registers8Bits32.insert(REG4, "ah");
Registers8Bits32.insert(REG5, "ch");
Registers8Bits32.insert(REG6, "dh");
Registers8Bits32.insert(REG7, "bh");
registerMap.insert(8, Registers8Bits32);
#endif //_WIN64
QMap<ARGUMENTS_TYPE, QString> Registers16Bits;
Registers16Bits.insert(REG0, "ax");
Registers16Bits.insert(REG1, "cx");
Registers16Bits.insert(REG2, "dx");
Registers16Bits.insert(REG3, "bx");
Registers16Bits.insert(REG4, "sp");
Registers16Bits.insert(REG5, "bp");
Registers16Bits.insert(REG6, "si");
Registers16Bits.insert(REG7, "di");
#ifdef _WIN64
Registers16Bits.insert(REG8, "r8w");
Registers16Bits.insert(REG9, "r9w");
Registers16Bits.insert(REG10, "r10w");
Registers16Bits.insert(REG11, "r11w");
Registers16Bits.insert(REG12, "r12w");
Registers16Bits.insert(REG13, "r13w");
Registers16Bits.insert(REG14, "r14w");
Registers16Bits.insert(REG15, "r15w");
#endif //_WIN64
registerMap.insert(16, Registers16Bits);
QMap<ARGUMENTS_TYPE, QString> Registers32Bits;
Registers32Bits.insert(REG0, "eax");
Registers32Bits.insert(REG1, "ecx");
Registers32Bits.insert(REG2, "edx");
Registers32Bits.insert(REG3, "ebx");
Registers32Bits.insert(REG4, "esp");
Registers32Bits.insert(REG5, "ebp");
Registers32Bits.insert(REG6, "esi");
Registers32Bits.insert(REG7, "edi");
#ifdef _WIN64
Registers32Bits.insert(REG8, "r8d");
Registers32Bits.insert(REG9, "r9d");
Registers32Bits.insert(REG10, "r10d");
Registers32Bits.insert(REG11, "r11d");
Registers32Bits.insert(REG12, "r12d");
Registers32Bits.insert(REG13, "r13d");
Registers32Bits.insert(REG14, "r14d");
Registers32Bits.insert(REG15, "r15d");
#endif //_WIN64
registerMap.insert(32, Registers32Bits);
//memory parser
memSizeNames.clear();
memSizeNames.insert(8, "byte");
memSizeNames.insert(16, "word");
memSizeNames.insert(32, "dword");
memSizeNames.insert(48, "fword");
memSizeNames.insert(64, "qword");
memSizeNames.insert(80, "tword");
memSizeNames.insert(128, "dqword");
memSizeNames.insert(256, "yword");
memSizeNames.insert(512, "zword");
segmentNames.clear();
segmentNames << "??" << "es" << "ds" << "fs" << "gs" << "cs" << "ss";
//color names map
colorNamesMap.clear();
//filling
@ -502,82 +50,6 @@ void BeaTokenizer::Init()
AddColorName(TokenFpuRegister, "InstructionFpuRegisterColor", "InstructionFpuRegisterBackgroundColor");
AddColorName(TokenMmxRegister, "InstructionMmxRegisterColor", "InstructionMmxRegisterBackgroundColor");
AddColorName(TokenSseRegister, "InstructionSseRegisterColor", "InstructionSseRegisterBackgroundColor");
//valid instructions with the REP prefix
repSet.clear();
repSet.insert(0x6C);
repSet.insert(0x6D);
repSet.insert(0x6E);
repSet.insert(0x6F);
repSet.insert(0xA4);
repSet.insert(0xA5);
repSet.insert(0xA6);
repSet.insert(0xA7);
repSet.insert(0xAA);
repSet.insert(0xAB);
repSet.insert(0xAC);
repSet.insert(0xAD);
repSet.insert(0xAE);
repSet.insert(0xAF);
}
//djb2 (http://www.cse.yorku.ca/~oz/hash.html)
unsigned long BeaTokenizer::HashInstruction(const DISASM* disasm)
{
const char* str = disasm->CompleteInstr;
unsigned long hash = 5381;
int c;
while(c = *str++)
hash = ((hash << 5) + hash) + c; /*hash*33+c*/
return hash;
}
void BeaTokenizer::TokenizeInstruction(BeaInstructionToken* instr, const DISASM* disasm, int maxModuleSize)
{
//initialization
instr->hash = HashInstruction(disasm); //hash instruction
instr->tokens.clear(); //clear token list
//base instruction
Prefix(instr, disasm);
Mnemonic(instr, disasm);
//arguments
QString mnemonic = QString(disasm->Instruction.Mnemonic).trimmed();
if(mnemonic.contains("far") && !QString(disasm->CompleteInstr).contains("[")) //far jumps / calls (not the memory ones)
{
unsigned int segment = 0;
unsigned int address = 0;
sscanf_s(disasm->Argument1.ArgMnemonic, "%X : %X", &segment, &address);
AddToken(instr, TokenSpace, QString(" "), 0);
BeaTokenValue val;
val.size = 2;
val.value = segment;
AddToken(instr, TokenValue, PrintValue(&val, true, maxModuleSize), &val);
AddToken(instr, TokenUncategorized, ":", 0);
val.size = 4;
val.value = address;
AddToken(instr, TokenAddress, PrintValue(&val, true, maxModuleSize), &val);
}
else
{
bool hadarg = false;
Argument(instr, disasm, &disasm->Argument1, &hadarg, maxModuleSize);
Argument(instr, disasm, &disasm->Argument2, &hadarg, maxModuleSize);
Argument(instr, disasm, &disasm->Argument3, &hadarg, maxModuleSize);
}
//remove spaces when needed
bool bArgumentSpaces = ConfigBool("Disassembler", "ArgumentSpaces");
bool bMemorySpaces = ConfigBool("Disassembler", "MemorySpaces");
for(int i = instr->tokens.size() - 1; i > -1; i--)
{
if(!bArgumentSpaces && instr->tokens.at(i).type == TokenArgumentSpace)
instr->tokens.erase(instr->tokens.begin() + i);
if(!bMemorySpaces && instr->tokens.at(i).type == TokenMemoryOperatorSpace)
instr->tokens.erase(instr->tokens.begin() + i);
}
}
void BeaTokenizer::TokenToRichText(const BeaInstructionToken* instr, QList<RichTextPainter::CustomRichText_t>* richTextList, const BeaSingleToken* highlightToken)

View File

@ -4,14 +4,11 @@
#include <QMap>
#include <QSet>
#include "RichTextPainter.h"
#include "BeaEngine.h"
#include "NewTypes.h"
class BeaTokenizer : RichTextPainter
{
public:
BeaTokenizer();
enum BeaTokenType
{
//filling
@ -77,8 +74,6 @@ public:
};
static void Init();
static unsigned long HashInstruction(const DISASM* disasm);
static void TokenizeInstruction(BeaInstructionToken* instr, const DISASM* disasm, int maxModuleSize);
static void TokenToRichText(const BeaInstructionToken* instr, QList<RichTextPainter::CustomRichText_t>* richTextList, const BeaSingleToken* highlightToken);
static bool TokenFromX(const BeaInstructionToken* instr, BeaSingleToken* token, int x, int charwidth);
static bool IsHighlightableToken(const BeaSingleToken* token);
@ -87,21 +82,6 @@ public:
private:
//variables
static QMap<BeaTokenType, BeaTokenColor> colorNamesMap;
static QStringList segmentNames;
static QMap<int, QString> memSizeNames;
static QMap<int, QMap<ARGUMENTS_TYPE, QString>> registerMap;
static QSet<int> repSet;
//functions
static void AddToken(BeaInstructionToken* instr, const BeaTokenType type, const QString text, const BeaTokenValue* value);
static void Prefix(BeaInstructionToken* instr, const DISASM* disasm);
static bool IsNopInstruction(QString mnemonic, const DISASM* disasm);
static void StringInstructionMemory(BeaInstructionToken* instr, int size, QString segment, ARGUMENTS_TYPE reg);
static void StringInstruction(QString mnemonic, BeaInstructionToken* instr, const DISASM* disasm);
static void Mnemonic(BeaInstructionToken* instr, const DISASM* disasm);
static QString PrintValue(const BeaTokenValue* value, bool module, int maxModuleSize);
static QString RegisterToString(int size, int reg);
static void Argument(BeaInstructionToken* instr, const DISASM* disasm, const ARGTYPE* arg, bool* hadarg, int maxModuleSize);
static void AddColorName(BeaTokenType type, QString color, QString backgroundColor);
};

View File

@ -4,8 +4,6 @@ QBeaEngine::QBeaEngine(int maxModuleSize)
: _tokenizer(maxModuleSize)
{
mMaxModuleSize = maxModuleSize;
// Reset the Disasm structure
memset(&mDisasmStruct, 0, sizeof(DISASM));
BeaTokenizer::Init();
}
@ -23,21 +21,13 @@ QBeaEngine::QBeaEngine(int maxModuleSize)
*/
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);
Q_UNUSED(base)
int i;
uint_t abuf[131], addr, back, cmdsize;
byte_t* pdata;
int len;
uint abuf[131], addr, back, cmdsize;
unsigned char* pdata;
// Reset Disasm Structure
memset(&mDisasmStruct, 0, sizeof(DISASM));
#ifdef _WIN64
mDisasmStruct.Archi = 64;
#endif
mDisasmStruct.Options = NoformatNumeral;
Capstone cp;
// Check if the pointer is not null
if(data == NULL)
@ -46,8 +36,8 @@ ulong QBeaEngine::DisassembleBack(byte_t* data, uint_t base, uint_t size, uint_t
// Round the number of back instructions to 127
if(n < 0)
n = 0;
else if(n >= max_instructions)
n = max_instructions - 1;
else if(n > 127)
n = 127;
// Check if the instruction pointer ip is not outside the memory range
if(ip >= size)
@ -57,10 +47,10 @@ ulong QBeaEngine::DisassembleBack(byte_t* data, uint_t base, uint_t size, uint_t
if(n == 0)
return ip;
if(ip < (uint_t)n)
if(ip < (uint)n)
return ip;
back = 16 * (n + 3); // Instruction length limited to 16
back = MAX_DISASM_BUFFER * (n + 3); // Instruction length limited to 16
if(ip < back)
back = ip;
@ -71,21 +61,24 @@ ulong QBeaEngine::DisassembleBack(byte_t* data, uint_t base, uint_t size, uint_t
for(i = 0; addr < ip; i++)
{
abuf[i % max_instructions] = addr;
abuf[i % 128] = addr;
mDisasmStruct.EIP = (UIntPtr)pdata;
len = Disasm(&mDisasmStruct);
cmdsize = (len < 1) ? 1 : len ;
if(!cp.Disassemble(0, pdata, (int)size))
cmdsize = 1;
else
cmdsize = cp.Size();
pdata += cmdsize;
addr += cmdsize;
back -= cmdsize;
size -= cmdsize;
}
if(i < n)
return abuf[0];
else
return abuf[(i - n + max_instructions) % max_instructions];
return abuf[(i - n + 128) % 128];
}
/**
@ -102,19 +95,13 @@ ulong QBeaEngine::DisassembleBack(byte_t* data, uint_t base, uint_t size, uint_t
*/
ulong QBeaEngine::DisassembleNext(byte_t* data, uint_t base, uint_t size, uint_t ip, int n)
{
Q_UNUSED(base);
Q_UNUSED(base)
int i;
uint_t cmdsize;
byte_t* pdata;
int len;
uint cmdsize;
unsigned char* pdata;
// Reset Disasm Structure
memset(&mDisasmStruct, 0, sizeof(DISASM));
#ifdef _WIN64
mDisasmStruct.Archi = 64;
#endif
mDisasmStruct.Options = NoformatNumeral;
Capstone cp;
if(data == NULL)
return 0;
@ -130,10 +117,10 @@ ulong QBeaEngine::DisassembleNext(byte_t* data, uint_t base, uint_t size, uint_t
for(i = 0; i < n && size > 0; i++)
{
mDisasmStruct.EIP = (UIntPtr)pdata;
mDisasmStruct.SecurityBlock = (UIntPtr)size;
len = Disasm(&mDisasmStruct);
cmdsize = (len < 1) ? 1 : len;
if(!cp.Disassemble(0, pdata, (int)size))
cmdsize = 1;
else
cmdsize = cp.Size();
pdata += cmdsize;
ip += cmdsize;
@ -157,36 +144,38 @@ ulong QBeaEngine::DisassembleNext(byte_t* data, uint_t base, uint_t size, uint_t
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
CapstoneTokenizer::InstructionToken cap;
_tokenizer.Tokenize(mDisasmStruct.VirtualAddr, data, size, cap);
_tokenizer.Tokenize(origBase + origInstRVA, data, size, cap);
int len = _tokenizer.Size();
const auto & cp = _tokenizer.GetCapstone();
bool success = cp.Success();
auto branchType = Instruction_t::None;
if(success && (cp.InGroup(CS_GRP_JUMP) || cp.IsLoop()))
{
switch(cp.GetId())
{
case X86_INS_JMP:
case X86_INS_LOOP:
branchType = Instruction_t::Unconditional;
break;
default:
branchType = Instruction_t::Conditional;
break;
}
}
Instruction_t wInst;
wInst.instStr = QString(cp.InstructionText().c_str());
wInst.dump = QByteArray((const char*)data, len);
wInst.rva = origInstRVA;
wInst.length = len;
wInst.branchType = branchType;
wInst.branchDestination = cp.BranchDestination();
//add tokens to struct
for(const auto & token : cap.tokens)
wInst.tokens.tokens.push_back(_tokenizer.Convert(token));

View File

@ -6,16 +6,32 @@
#include "BeaTokenizer.h"
#include "capstone_gui.h"
typedef struct _Instruction_t
struct Instruction_t
{
enum BranchType
{
None,
Conditional,
Unconditional
};
Instruction_t()
: rva(0),
length(0),
branchDestination(0),
branchType(None)
{
}
QString instStr;
QByteArray dump;
uint_t rva;
int length;
DISASM disasm;
//DISASM disasm;
uint_t branchDestination;
BranchType branchType;
BeaTokenizer::BeaInstructionToken tokens;
} Instruction_t;
};
class QBeaEngine
{
@ -27,7 +43,6 @@ public:
void UpdateConfig();
private:
DISASM mDisasmStruct;
int mMaxModuleSize;
CapstoneTokenizer _tokenizer;
};

View File

@ -1,4 +1,5 @@
#include "capstone_wrapper.h"
#include <windows.h>
csh Capstone::mHandle = 0;
@ -21,7 +22,7 @@ void Capstone::GlobalFinalize()
Capstone::Capstone()
{
mInstr = nullptr;
mError = CS_ERR_OK;
mSuccess = false;
}
Capstone::~Capstone()
@ -30,12 +31,12 @@ Capstone::~Capstone()
cs_free(mInstr, 1);
}
bool Capstone::Disassemble(duint addr, const unsigned char data[MAX_DISASM_BUFFER])
bool Capstone::Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER])
{
return Disassemble(addr, data, MAX_DISASM_BUFFER);
}
bool Capstone::Disassemble(duint addr, const unsigned char* data, int size)
bool Capstone::Disassemble(size_t addr, const unsigned char* data, int size)
{
if(!data)
return false;
@ -44,17 +45,19 @@ bool Capstone::Disassemble(duint addr, const unsigned char* data, int size)
cs_free(mInstr, 1);
mInstr = nullptr;
}
return !!cs_disasm(mHandle, data, size, addr, 1, &mInstr);
return mSuccess = !!cs_disasm(mHandle, data, size, addr, 1, &mInstr);
}
const cs_insn* Capstone::GetInstr() const
{
if(!Success())
return nullptr;
return mInstr;
}
cs_err Capstone::GetError() const
bool Capstone::Success() const
{
return mError;
return mSuccess;
}
const char* Capstone::RegName(x86_reg reg) const
@ -64,11 +67,15 @@ const char* Capstone::RegName(x86_reg reg) const
bool Capstone::InGroup(cs_group_type group) const
{
if(!Success())
return false;
return cs_insn_group(mHandle, mInstr, group);
}
std::string Capstone::OperandText(int opindex) const
{
if(!Success())
return false;
if(opindex >= mInstr->detail->x86.op_count)
return "";
const auto & op = mInstr->detail->x86.operands[opindex];
@ -143,21 +150,29 @@ std::string Capstone::OperandText(int opindex) const
int Capstone::Size() const
{
if(!Success())
return 1;
return GetInstr()->size;
}
duint Capstone::Address() const
size_t Capstone::Address() const
{
return duint (GetInstr()->address);
if(!Success())
return 0;
return size_t(GetInstr()->address);
}
const cs_x86 & Capstone::x86() const
{
if(!Success())
DebugBreak();
return GetInstr()->detail->x86;
}
bool Capstone::IsFilling() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_NOP:
@ -170,6 +185,8 @@ bool Capstone::IsFilling() const
bool Capstone::IsLoop() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_LOOP:
@ -183,25 +200,34 @@ bool Capstone::IsLoop() const
x86_insn Capstone::GetId() const
{
if(!Success())
DebugBreak();
return x86_insn(mInstr->id);
}
std::string Capstone::InstructionText() const
{
if(!Success())
return "???";
std::string result = Mnemonic();
result += " ";
result += mInstr->op_str;
if(OpCount())
{
result += " ";
result += mInstr->op_str;
}
return result;
}
int Capstone::OpCount() const
{
if(!Success())
return 0;
return x86().op_count;
}
cs_x86_op Capstone::operator[](int index) const
{
if(index >= OpCount())
if(!Success() || index >= OpCount())
DebugBreak();
return x86().operands[index];
}
@ -213,6 +239,8 @@ bool Capstone::IsNop() const
bool Capstone::IsInt3() const
{
if(!Success())
return false;
switch(GetId())
{
case X86_INS_INT3:
@ -229,6 +257,8 @@ bool Capstone::IsInt3() const
std::string Capstone::Mnemonic() const
{
if(!Success())
return "???";
return mInstr->mnemonic;
}
@ -258,3 +288,16 @@ const char* Capstone::MemSizeName(int size) const
return nullptr;
}
}
size_t Capstone::BranchDestination() const
{
if(!Success())
return 0;
if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
{
const auto & op = x86().operands[0];
if(op.type == CS_OP_IMM)
return size_t(op.imm);
}
return 0;
}

View File

@ -3,9 +3,9 @@
#include "..\..\..\x64_dbg_dbg\capstone\capstone.h"
#include "Imports.h"
#include <string>
#define MAX_DISASM_BUFFER 16
#define INVALID_TITAN_REG 0
class Capstone
{
@ -14,15 +14,15 @@ public:
static void GlobalFinalize();
Capstone();
~Capstone();
bool Disassemble(duint addr, const unsigned char data[MAX_DISASM_BUFFER]);
bool Disassemble(duint addr, const unsigned char* data, int size);
bool Disassemble(size_t addr, const unsigned char data[MAX_DISASM_BUFFER]);
bool Disassemble(size_t addr, const unsigned char* data, int size);
const cs_insn* GetInstr() const;
cs_err GetError() const;
bool Success() const;
const char* RegName(x86_reg reg) const;
bool InGroup(cs_group_type group) const;
std::string OperandText(int opindex) const;
int Size() const;
duint Address() const;
size_t Address() const;
const cs_x86 & x86() const;
bool IsFilling() const;
bool IsLoop() const;
@ -34,11 +34,12 @@ public:
bool IsInt3() const;
std::string Mnemonic() const;
const char* MemSizeName(int size) const;
size_t BranchDestination() const;
private:
static csh mHandle;
cs_insn* mInstr;
cs_err mError;
bool mSuccess;
};
#endif //_CAPSTONE_WRAPPER_H

View File

@ -70,12 +70,13 @@ void CPUSideBar::setSelection(int_t selVA)
bool CPUSideBar::isJump(int i) const
{
int BranchType = InstrBuffer->at(i).disasm.Instruction.BranchType;
if(BranchType && BranchType != RetType && BranchType != CallType)
const auto & instr = InstrBuffer->at(i);
auto branchType = instr.branchType;
if(branchType != Instruction_t::None)
{
uint_t start = CodePtr->getBase();
uint_t end = start + CodePtr->getSize();
uint_t addr = DbgGetBranchDestination(CodePtr->rvaToVa(InstrBuffer->at(i).rva));
uint_t addr = instr.branchDestination;
return addr >= start && addr < end; //do not draw jumps that go out of the section
}
return false;
@ -120,12 +121,9 @@ void CPUSideBar::paintEvent(QPaintEvent* event)
jumpoffset++;
int_t destVA = (int_t)DbgGetBranchDestination(CodePtr->rvaToVa(instr.rva));
int_t destVA = instr.branchDestination;
if(instr.disasm.Instruction.Opcode == 0xFF)
continue;
bool isConditional = !((instr.disasm.Instruction.Opcode == 0xEB) || instr.disasm.Instruction.Opcode == 0xE9);
bool isConditional = instr.branchType == Instruction_t::Conditional;
if(destVA == instrVA) //do not try to draw EBFE
continue;

View File

@ -1,392 +0,0 @@
#ifndef _BEA_ENGINE_
#define _BEA_ENGINE_
#if defined(__cplusplus) && defined(__BORLANDC__)
namespace BeaEngine
{
#endif
#include "macros.h"
#include "export.h"
#include "basic_types.h"
#if !defined(BEA_ENGINE_STATIC)
#if defined(BUILD_BEA_ENGINE_DLL)
#define BEA_API bea__api_export__
#else
#define BEA_API bea__api_import__
#endif
#else
#define BEA_API
#endif
#define INSTRUCT_LENGTH 64
#pragma pack(1)
typedef struct
{
UInt8 W_;
UInt8 R_;
UInt8 X_;
UInt8 B_;
UInt8 state;
} REX_Struct ;
#pragma pack()
#pragma pack(1)
typedef struct
{
int Number;
int NbUndefined;
UInt8 LockPrefix;
UInt8 OperandSize;
UInt8 AddressSize;
UInt8 RepnePrefix;
UInt8 RepPrefix;
UInt8 FSPrefix;
UInt8 SSPrefix;
UInt8 GSPrefix;
UInt8 ESPrefix;
UInt8 CSPrefix;
UInt8 DSPrefix;
UInt8 BranchTaken;
UInt8 BranchNotTaken;
REX_Struct REX;
char alignment[2];
} PREFIXINFO ;
#pragma pack()
#pragma pack(1)
typedef struct
{
UInt8 OF_;
UInt8 SF_;
UInt8 ZF_;
UInt8 AF_;
UInt8 PF_;
UInt8 CF_;
UInt8 TF_;
UInt8 IF_;
UInt8 DF_;
UInt8 NT_;
UInt8 RF_;
UInt8 alignment;
} EFLStruct ;
#pragma pack()
#pragma pack(4)
typedef struct
{
Int32 BaseRegister;
Int32 IndexRegister;
Int32 Scale;
Int64 Displacement;
} MEMORYTYPE ;
#pragma pack()
#pragma pack(1)
typedef struct
{
Int32 Category; //INSTRUCTION_TYPE
Int32 Opcode;
char Mnemonic[16];
Int32 BranchType; //BRANCH_TYPE
EFLStruct Flags;
UInt64 AddrValue;
Int64 Immediat;
UInt32 ImplicitModifiedRegs;
} INSTRTYPE;
#pragma pack()
#pragma pack(1)
typedef struct
{
char ArgMnemonic[64];
Int32 ArgType; //ARGUMENTS_TYPE
Int32 ArgSize;
Int32 ArgPosition;
UInt32 AccessMode;
MEMORYTYPE Memory;
UInt32 SegmentReg;
} ARGTYPE;
#pragma pack()
/* reserved structure used for thread-safety */
/* unusable by customer */
#pragma pack(1)
typedef struct
{
UIntPtr EIP_;
UInt64 EIP_VA;
UIntPtr EIP_REAL;
Int32 OriginalOperandSize;
Int32 OperandSize;
Int32 MemDecoration;
Int32 AddressSize;
Int32 MOD_;
Int32 RM_;
Int32 INDEX_;
Int32 SCALE_;
Int32 BASE_;
Int32 MMX_;
Int32 SSE_;
Int32 CR_;
Int32 DR_;
Int32 SEG_;
Int32 REGOPCODE;
UInt32 DECALAGE_EIP;
Int32 FORMATNUMBER;
Int32 SYNTAX_;
UInt64 EndOfBlock;
Int32 RelativeAddress;
UInt32 Architecture;
Int32 ImmediatSize;
Int32 NB_PREFIX;
Int32 PrefRepe;
Int32 PrefRepne;
UInt32 SEGMENTREGS;
UInt32 SEGMENTFS;
Int32 third_arg;
Int32 TAB_;
Int32 ERROR_OPCODE;
REX_Struct REX;
Int32 OutOfBlock;
} InternalDatas;
#pragma pack()
/* ************** main structure ************ */
#pragma pack(1)
typedef struct _Disasm