Replace Capstone with Zydis
- While at it, added branch info logic to disassembler class - Thus reduce direct checks by mnemonic in GUI and analysis code - Replaced direct disassembler struct access with disassembler class calls where trivially possible - Removed workarounds for empty segment registers - Temp. disabled `cbInstrCapstone` command - Temp. disabled flag stuff in `QBeaEngine`
This commit is contained in:
parent
103866eafe
commit
5338a0a85b
|
@ -10,3 +10,6 @@
|
||||||
[submodule "deps"]
|
[submodule "deps"]
|
||||||
path = deps
|
path = deps
|
||||||
url = https://github.com/x64dbg/deps
|
url = https://github.com/x64dbg/deps
|
||||||
|
[submodule "src/zydis_wrapper"]
|
||||||
|
path = src/zydis_wrapper
|
||||||
|
url = https://athre0z@github.com/athre0z/zydis-x64dbg-module.git
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "TraceRecord.h"
|
#include "TraceRecord.h"
|
||||||
#include "capstone_wrapper.h"
|
#include "zydis_wrapper.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "threading.h"
|
#include "threading.h"
|
||||||
|
|
|
@ -355,9 +355,9 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, BRID
|
||||||
if(instr.arg[i].constant == instr.arg[i].value) //avoid: call <module.label> ; addr:label
|
if(instr.arg[i].constant == instr.arg[i].value) //avoid: call <module.label> ; addr:label
|
||||||
{
|
{
|
||||||
auto constant = instr.arg[i].constant;
|
auto constant = instr.arg[i].constant;
|
||||||
if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.InGroup(CS_GRP_CALL))
|
if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.IsCall())
|
||||||
temp_string.assign("call $0");
|
temp_string.assign("call $0");
|
||||||
else if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.InGroup(CS_GRP_JUMP))
|
else if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.IsJump())
|
||||||
temp_string.assign("jmp $0");
|
temp_string.assign("jmp $0");
|
||||||
else if(instr.type == instr_branch)
|
else if(instr.type == instr_branch)
|
||||||
continue;
|
continue;
|
||||||
|
@ -738,77 +738,77 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
|
||||||
Capstone cp;
|
Capstone cp;
|
||||||
if(!cp.Disassemble(addr, data))
|
if(!cp.Disassemble(addr, data))
|
||||||
return 0;
|
return 0;
|
||||||
if(cp.InGroup(CS_GRP_JUMP) || cp.InGroup(CS_GRP_CALL) || cp.IsLoop())
|
if(cp.IsBranchType(Capstone::BT_Jmp | Capstone::BT_Call | Capstone::BT_Loop))
|
||||||
{
|
{
|
||||||
auto opValue = cp.ResolveOpValue(0, [](x86_reg reg) -> size_t
|
auto opValue = cp.ResolveOpValue(0, [](ZydisRegister reg) -> size_t
|
||||||
{
|
{
|
||||||
switch(reg)
|
switch(reg)
|
||||||
{
|
{
|
||||||
#ifndef _WIN64 //x32
|
#ifndef _WIN64 //x32
|
||||||
case X86_REG_EAX:
|
case ZYDIS_REGISTER_EAX:
|
||||||
return titcontext.cax;
|
return titcontext.cax;
|
||||||
case X86_REG_EBX:
|
case ZYDIS_REGISTER_EBX:
|
||||||
return titcontext.cbx;
|
return titcontext.cbx;
|
||||||
case X86_REG_ECX:
|
case ZYDIS_REGISTER_ECX:
|
||||||
return titcontext.ccx;
|
return titcontext.ccx;
|
||||||
case X86_REG_EDX:
|
case ZYDIS_REGISTER_EDX:
|
||||||
return titcontext.cdx;
|
return titcontext.cdx;
|
||||||
case X86_REG_EBP:
|
case ZYDIS_REGISTER_EBP:
|
||||||
return titcontext.cbp;
|
return titcontext.cbp;
|
||||||
case X86_REG_ESP:
|
case ZYDIS_REGISTER_ESP:
|
||||||
return titcontext.csp;
|
return titcontext.csp;
|
||||||
case X86_REG_ESI:
|
case ZYDIS_REGISTER_ESI:
|
||||||
return titcontext.csi;
|
return titcontext.csi;
|
||||||
case X86_REG_EDI:
|
case ZYDIS_REGISTER_EDI:
|
||||||
return titcontext.cdi;
|
return titcontext.cdi;
|
||||||
case X86_REG_EIP:
|
case ZYDIS_REGISTER_EIP:
|
||||||
return titcontext.cip;
|
return titcontext.cip;
|
||||||
#else //x64
|
#else //x64
|
||||||
case X86_REG_RAX:
|
case ZYDIS_REGISTER_RAX:
|
||||||
return titcontext.cax;
|
return titcontext.cax;
|
||||||
case X86_REG_RBX:
|
case ZYDIS_REGISTER_RBX:
|
||||||
return titcontext.cbx;
|
return titcontext.cbx;
|
||||||
case X86_REG_RCX:
|
case ZYDIS_REGISTER_RCX:
|
||||||
return titcontext.ccx;
|
return titcontext.ccx;
|
||||||
case X86_REG_RDX:
|
case ZYDIS_REGISTER_RDX:
|
||||||
return titcontext.cdx;
|
return titcontext.cdx;
|
||||||
case X86_REG_RBP:
|
case ZYDIS_REGISTER_RBP:
|
||||||
return titcontext.cbp;
|
return titcontext.cbp;
|
||||||
case X86_REG_RSP:
|
case ZYDIS_REGISTER_RSP:
|
||||||
return titcontext.csp;
|
return titcontext.csp;
|
||||||
case X86_REG_RSI:
|
case ZYDIS_REGISTER_RSI:
|
||||||
return titcontext.csi;
|
return titcontext.csi;
|
||||||
case X86_REG_RDI:
|
case ZYDIS_REGISTER_RDI:
|
||||||
return titcontext.cdi;
|
return titcontext.cdi;
|
||||||
case X86_REG_RIP:
|
case ZYDIS_REGISTER_RIP:
|
||||||
return titcontext.cip;
|
return titcontext.cip;
|
||||||
case X86_REG_R8:
|
case ZYDIS_REGISTER_R8:
|
||||||
return titcontext.r8;
|
return titcontext.r8;
|
||||||
case X86_REG_R9:
|
case ZYDIS_REGISTER_R9:
|
||||||
return titcontext.r9;
|
return titcontext.r9;
|
||||||
case X86_REG_R10:
|
case ZYDIS_REGISTER_R10:
|
||||||
return titcontext.r10;
|
return titcontext.r10;
|
||||||
case X86_REG_R11:
|
case ZYDIS_REGISTER_R11:
|
||||||
return titcontext.r11;
|
return titcontext.r11;
|
||||||
case X86_REG_R12:
|
case ZYDIS_REGISTER_R12:
|
||||||
return titcontext.r12;
|
return titcontext.r12;
|
||||||
case X86_REG_R13:
|
case ZYDIS_REGISTER_R13:
|
||||||
return titcontext.r13;
|
return titcontext.r13;
|
||||||
case X86_REG_R14:
|
case ZYDIS_REGISTER_R14:
|
||||||
return titcontext.r14;
|
return titcontext.r14;
|
||||||
case X86_REG_R15:
|
case ZYDIS_REGISTER_R15:
|
||||||
return titcontext.r15;
|
return titcontext.r15;
|
||||||
#endif //_WIN64
|
#endif //_WIN64
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(cp[0].type == X86_OP_MEM)
|
if(cp[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
auto const tebseg = X86_REG_GS;
|
auto const tebseg = ZYDIS_REGISTER_GS;
|
||||||
#else
|
#else
|
||||||
auto const tebseg = X86_REG_FS;
|
auto const tebseg = ZYDIS_REGISTER_FS;
|
||||||
#endif //_WIN64
|
#endif //_WIN64
|
||||||
if(cp[0].mem.segment == tebseg)
|
if(cp[0].mem.segment == tebseg)
|
||||||
opValue += duint(GetTEBLocation(hActiveThread));
|
opValue += duint(GetTEBLocation(hActiveThread));
|
||||||
|
@ -818,7 +818,7 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
|
||||||
else
|
else
|
||||||
return opValue;
|
return opValue;
|
||||||
}
|
}
|
||||||
if(cp.InGroup(CS_GRP_RET))
|
if(cp.IsRet())
|
||||||
{
|
{
|
||||||
auto csp = titcontext.csp;
|
auto csp = titcontext.csp;
|
||||||
duint dest = 0;
|
duint dest = 0;
|
||||||
|
|
|
@ -31,16 +31,16 @@ bool CodeFollowPass::Analyse()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
duint CodeFollowPass::GetReferenceOperand(const cs_x86 & Context)
|
duint CodeFollowPass::GetReferenceOperand(const ZydisDecodedInstruction & Context)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < Context.op_count; i++)
|
for(int i = 0; i < Context.operandCount; i++)
|
||||||
{
|
{
|
||||||
auto operand = Context.operands[i];
|
auto operand = Context.operands[i];
|
||||||
|
|
||||||
// Looking for immediate references
|
// Looking for immediate references
|
||||||
if(operand.type == X86_OP_IMM)
|
if(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
duint dest = (duint)operand.imm;
|
duint dest = (duint)operand.imm.value.u;
|
||||||
|
|
||||||
if(ValidateAddress(dest))
|
if(ValidateAddress(dest))
|
||||||
return dest;
|
return dest;
|
||||||
|
@ -50,25 +50,25 @@ duint CodeFollowPass::GetReferenceOperand(const cs_x86 & Context)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
duint CodeFollowPass::GetMemoryOperand(Capstone & Disasm, const cs_x86 & Context, bool* Indirect)
|
duint CodeFollowPass::GetMemoryOperand(Capstone & Disasm, const ZydisDecodedInstruction & Context, bool* Indirect)
|
||||||
{
|
{
|
||||||
if(Context.op_count <= 0)
|
if(Context.operandCount <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Only the first operand matters
|
// Only the first operand matters
|
||||||
auto operand = Context.operands[0];
|
auto operand = Context.operands[0];
|
||||||
|
|
||||||
// Jumps and calls only
|
// Jumps and calls only
|
||||||
if(Disasm.InGroup(CS_GRP_CALL) || Disasm.InGroup(CS_GRP_JUMP))
|
if(Disasm.IsCall() || Disasm.IsJump())
|
||||||
{
|
{
|
||||||
// Looking for memory references
|
// Looking for memory references
|
||||||
if(operand.type == X86_OP_MEM)
|
if(operand.type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
{
|
{
|
||||||
// Notify if the operand was indirect
|
// Notify if the operand was indirect
|
||||||
if(Indirect)
|
if(Indirect)
|
||||||
{
|
{
|
||||||
if(operand.mem.base != X86_REG_INVALID ||
|
if(operand.mem.base != ZYDIS_REGISTER_NONE ||
|
||||||
operand.mem.index != X86_REG_INVALID ||
|
operand.mem.index != ZYDIS_REGISTER_NONE ||
|
||||||
operand.mem.scale != 0)
|
operand.mem.scale != 0)
|
||||||
{
|
{
|
||||||
*Indirect = true;
|
*Indirect = true;
|
||||||
|
@ -81,7 +81,7 @@ duint CodeFollowPass::GetMemoryOperand(Capstone & Disasm, const cs_x86 & Context
|
||||||
// TODO: Translate RIP-Relative
|
// TODO: Translate RIP-Relative
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
duint dest = (duint)operand.mem.disp;
|
duint dest = (duint)operand.mem.disp.value;
|
||||||
|
|
||||||
if(ValidateAddress(dest))
|
if(ValidateAddress(dest))
|
||||||
return dest;
|
return dest;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "AnalysisPass.h"
|
#include "AnalysisPass.h"
|
||||||
#include "BasicBlock.h"
|
#include "BasicBlock.h"
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
|
|
||||||
class CodeFollowPass : public AnalysisPass
|
class CodeFollowPass : public AnalysisPass
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,6 @@ public:
|
||||||
virtual bool Analyse() override;
|
virtual bool Analyse() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
duint GetReferenceOperand(const cs_x86 & Context);
|
duint GetReferenceOperand(const ZydisDecodedInstruction & Context);
|
||||||
duint GetMemoryOperand(Capstone & Disasm, const cs_x86 & Context, bool* Indirect);
|
duint GetMemoryOperand(Capstone & Disasm, const ZydisDecodedInstruction & Context, bool* Indirect);
|
||||||
};
|
};
|
|
@ -2,7 +2,7 @@
|
||||||
#include <ppl.h>
|
#include <ppl.h>
|
||||||
#include "AnalysisPass.h"
|
#include "AnalysisPass.h"
|
||||||
#include "LinearPass.h"
|
#include "LinearPass.h"
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
|
|
||||||
LinearPass::LinearPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
|
LinearPass::LinearPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
|
||||||
: AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
|
: AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
|
||||||
|
@ -167,10 +167,10 @@ void LinearPass::AnalysisWorker(duint Start, duint End, BBlockArray* Blocks)
|
||||||
insnCount++;
|
insnCount++;
|
||||||
|
|
||||||
// The basic block ends here if it is a branch
|
// The basic block ends here if it is a branch
|
||||||
bool call = disasm.InGroup(CS_GRP_CALL); // CALL
|
bool call = disasm.IsCall(); // CALL
|
||||||
bool jmp = disasm.InGroup(CS_GRP_JUMP); // JUMP
|
bool jmp = disasm.IsJump(); // JUMP
|
||||||
bool ret = disasm.InGroup(CS_GRP_RET); // RETURN
|
bool ret = disasm.IsRet(); // RETURN
|
||||||
bool padding = disasm.IsFilling(); // INSTRUCTION PADDING
|
bool padding = disasm.IsFilling(); // INSTRUCTION PADDING
|
||||||
|
|
||||||
if(padding)
|
if(padding)
|
||||||
{
|
{
|
||||||
|
@ -211,25 +211,25 @@ void LinearPass::AnalysisWorker(duint Start, duint End, BBlockArray* Blocks)
|
||||||
if(!padding)
|
if(!padding)
|
||||||
{
|
{
|
||||||
// Check if absolute jump, regardless of operand
|
// Check if absolute jump, regardless of operand
|
||||||
if(disasm.GetId() == X86_INS_JMP)
|
if(disasm.GetId() == ZYDIS_MNEMONIC_JMP)
|
||||||
block->SetFlag(BASIC_BLOCK_FLAG_ABSJMP);
|
block->SetFlag(BASIC_BLOCK_FLAG_ABSJMP);
|
||||||
|
|
||||||
// Figure out the operand type(s)
|
// Figure out the operand type(s)
|
||||||
const auto & operand = disasm.x86().operands[0];
|
const auto & operand = disasm[0];
|
||||||
|
|
||||||
if(operand.type == X86_OP_IMM)
|
if(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
// Branch target immediate
|
// Branch target immediate
|
||||||
block->Target = (duint)operand.imm;
|
block->Target = (duint)operand.imm.value.u;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Indirects (no operand, register, or memory)
|
// Indirects (no operand, register, or memory)
|
||||||
block->SetFlag(BASIC_BLOCK_FLAG_INDIRECT);
|
block->SetFlag(BASIC_BLOCK_FLAG_INDIRECT);
|
||||||
|
|
||||||
if(operand.type == X86_OP_MEM &&
|
if(operand.type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
||||||
operand.mem.base == X86_REG_RIP &&
|
operand.mem.base == ZYDIS_REGISTER_RIP &&
|
||||||
operand.mem.index == X86_REG_INVALID &&
|
operand.mem.index == ZYDIS_REGISTER_NONE &&
|
||||||
operand.mem.scale == 1)
|
operand.mem.scale == 1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -106,11 +106,11 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
||||||
for(int i = 1; i < mCp.Size(); i++)
|
for(int i = 1; i < mCp.Size(); i++)
|
||||||
mEncMap[node.end - mBase + i] = (byte)enc_middle;
|
mEncMap[node.end - mBase + i] = (byte)enc_middle;
|
||||||
}
|
}
|
||||||
if(mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop()) //jump
|
if(mCp.IsJump() || mCp.IsLoop()) //jump
|
||||||
{
|
{
|
||||||
//set the branch destinations
|
//set the branch destinations
|
||||||
node.brtrue = mCp.BranchDestination();
|
node.brtrue = mCp.BranchDestination();
|
||||||
if(mCp.GetId() != X86_INS_JMP) //unconditional jumps dont have a brfalse
|
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||||
node.brfalse = node.end + mCp.Size();
|
node.brfalse = node.end + mCp.Size();
|
||||||
|
|
||||||
//add node to the function graph
|
//add node to the function graph
|
||||||
|
@ -124,14 +124,14 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(mCp.InGroup(CS_GRP_CALL)) //call
|
if(mCp.IsCall()) //call
|
||||||
{
|
{
|
||||||
//TODO: handle no return
|
//TODO: handle no return
|
||||||
duint target = mCp.BranchDestination();
|
duint target = mCp.BranchDestination();
|
||||||
if(inRange(target) && mEntryPoints.find(target) == mEntryPoints.end())
|
if(inRange(target) && mEntryPoints.find(target) == mEntryPoints.end())
|
||||||
mCandidateEPs.insert(target);
|
mCandidateEPs.insert(target);
|
||||||
}
|
}
|
||||||
if(mCp.InGroup(CS_GRP_RET)) //return
|
if(mCp.IsRet()) //return
|
||||||
{
|
{
|
||||||
node.terminal = true;
|
node.terminal = true;
|
||||||
graph.AddNode(node);
|
graph.AddNode(node);
|
||||||
|
@ -164,7 +164,7 @@ void AdvancedAnalysis::linearXrefPass()
|
||||||
xref.from = mCp.Address();
|
xref.from = mCp.Address();
|
||||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||||
{
|
{
|
||||||
duint dest = mCp.ResolveOpValue(i, [](x86_reg)->size_t
|
duint dest = mCp.ResolveOpValue(i, [](ZydisRegister)->size_t
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
@ -176,9 +176,9 @@ void AdvancedAnalysis::linearXrefPass()
|
||||||
}
|
}
|
||||||
if(xref.addr)
|
if(xref.addr)
|
||||||
{
|
{
|
||||||
if(mCp.InGroup(CS_GRP_CALL))
|
if(mCp.IsCall())
|
||||||
xref.type = XREF_CALL;
|
xref.type = XREF_CALL;
|
||||||
else if(mCp.InGroup(CS_GRP_JUMP))
|
else if(mCp.IsJump())
|
||||||
xref.type = XREF_JMP;
|
xref.type = XREF_JMP;
|
||||||
else
|
else
|
||||||
xref.type = XREF_DATA;
|
xref.type = XREF_DATA;
|
||||||
|
@ -218,21 +218,21 @@ void AdvancedAnalysis::findInvalidXrefs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFloatInstruction(x86_insn opcode)
|
bool isFloatInstruction(ZydisMnemonic opcode)
|
||||||
{
|
{
|
||||||
switch(opcode)
|
switch(opcode)
|
||||||
{
|
{
|
||||||
case X86_INS_FLD:
|
case ZYDIS_MNEMONIC_FLD:
|
||||||
case X86_INS_FST:
|
case ZYDIS_MNEMONIC_FST:
|
||||||
case X86_INS_FSTP:
|
case ZYDIS_MNEMONIC_FSTP:
|
||||||
case X86_INS_FADD:
|
case ZYDIS_MNEMONIC_FADD:
|
||||||
case X86_INS_FSUB:
|
case ZYDIS_MNEMONIC_FSUB:
|
||||||
case X86_INS_FSUBR:
|
case ZYDIS_MNEMONIC_FSUBR:
|
||||||
case X86_INS_FMUL:
|
case ZYDIS_MNEMONIC_FMUL:
|
||||||
case X86_INS_FDIV:
|
case ZYDIS_MNEMONIC_FDIV:
|
||||||
case X86_INS_FDIVR:
|
case ZYDIS_MNEMONIC_FDIVR:
|
||||||
case X86_INS_FCOM:
|
case ZYDIS_MNEMONIC_FCOM:
|
||||||
case X86_INS_FCOMP:
|
case ZYDIS_MNEMONIC_FCOMP:
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
@ -261,7 +261,7 @@ void AdvancedAnalysis::writeDataXrefs()
|
||||||
ENCODETYPE type = enc_unknown;
|
ENCODETYPE type = enc_unknown;
|
||||||
|
|
||||||
//Todo: Analyze op type and set correct type
|
//Todo: Analyze op type and set correct type
|
||||||
if(op.type == X86_OP_MEM)
|
if(op.type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
{
|
{
|
||||||
duint datasize = op.size;
|
duint datasize = op.size;
|
||||||
duint size = datasize;
|
duint size = datasize;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define _ANALYSIS_H
|
#define _ANALYSIS_H
|
||||||
|
|
||||||
#include "_global.h"
|
#include "_global.h"
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
|
|
||||||
class Analysis
|
class Analysis
|
||||||
{
|
{
|
||||||
|
|
|
@ -150,15 +150,15 @@ void ControlFlowAnalysis::BasicBlockStarts()
|
||||||
mBlockStarts.insert(addr);
|
mBlockStarts.insert(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(mCp.InGroup(CS_GRP_RET)) //RET breaks control flow
|
else if(mCp.IsRet()) //RET breaks control flow
|
||||||
{
|
{
|
||||||
bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
|
bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
|
||||||
}
|
}
|
||||||
else if(mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop()) //branches
|
else if(mCp.IsJump() || mCp.IsLoop()) //branches
|
||||||
{
|
{
|
||||||
auto dest1 = getReferenceOperand();
|
auto dest1 = getReferenceOperand();
|
||||||
duint dest2 = 0;
|
duint dest2 = 0;
|
||||||
if(mCp.GetId() != X86_INS_JMP) //conditional jump
|
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //conditional jump
|
||||||
dest2 = addr + mCp.Size();
|
dest2 = addr + mCp.Size();
|
||||||
|
|
||||||
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
|
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
|
||||||
|
@ -168,7 +168,7 @@ void ControlFlowAnalysis::BasicBlockStarts()
|
||||||
if(dest2)
|
if(dest2)
|
||||||
mBlockStarts.insert(dest2);
|
mBlockStarts.insert(dest2);
|
||||||
}
|
}
|
||||||
else if(mCp.InGroup(CS_GRP_CALL))
|
else if(mCp.IsCall())
|
||||||
{
|
{
|
||||||
auto dest1 = getReferenceOperand();
|
auto dest1 = getReferenceOperand();
|
||||||
if(dest1)
|
if(dest1)
|
||||||
|
@ -206,15 +206,15 @@ void ControlFlowAnalysis::BasicBlocks()
|
||||||
prevaddr = addr;
|
prevaddr = addr;
|
||||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||||
{
|
{
|
||||||
if(mCp.InGroup(CS_GRP_RET))
|
if(mCp.IsRet())
|
||||||
{
|
{
|
||||||
insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
|
insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop())
|
else if(mCp.IsJump() || mCp.IsLoop())
|
||||||
{
|
{
|
||||||
auto dest1 = getReferenceOperand();
|
auto dest1 = getReferenceOperand();
|
||||||
auto dest2 = mCp.GetId() != X86_INS_JMP ? addr + mCp.Size() : 0;
|
auto dest2 = mCp.GetId() != ZYDIS_MNEMONIC_JMP ? addr + mCp.Size() : 0;
|
||||||
insertBlock(BasicBlock(start, addr, dest1, dest2));
|
insertBlock(BasicBlock(start, addr, dest1, dest2));
|
||||||
insertParent(dest1, start);
|
insertParent(dest1, start);
|
||||||
insertParent(dest2, start);
|
insertParent(dest2, start);
|
||||||
|
@ -415,17 +415,17 @@ duint ControlFlowAnalysis::getReferenceOperand() const
|
||||||
{
|
{
|
||||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||||
{
|
{
|
||||||
const auto & op = mCp.x86().operands[i];
|
const auto & op = mCp[i];
|
||||||
if(op.type == X86_OP_IMM)
|
if(op.type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
auto dest = duint(op.imm);
|
auto dest = duint(op.imm.value.u);
|
||||||
if(inRange(dest))
|
if(inRange(dest))
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
else if(op.type == X86_OP_MEM)
|
else if(op.type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
{
|
{
|
||||||
auto dest = duint(op.mem.disp);
|
auto dest = duint(op.mem.disp.value);
|
||||||
if(op.mem.base == X86_REG_RIP) //rip-relative
|
if(op.mem.base == ZYDIS_REGISTER_RIP) //rip-relative
|
||||||
dest += mCp.Address() + mCp.Size();
|
dest += mCp.Address() + mCp.Size();
|
||||||
if(inRange(dest))
|
if(inRange(dest))
|
||||||
return dest;
|
return dest;
|
||||||
|
|
|
@ -86,7 +86,7 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
||||||
if(mCp.Disassemble(start, translateAddr(start), MAX_DISASM_BUFFER))
|
if(mCp.Disassemble(start, translateAddr(start), MAX_DISASM_BUFFER))
|
||||||
{
|
{
|
||||||
//JMP [123456] ; import
|
//JMP [123456] ; import
|
||||||
if(mCp.InGroup(CS_GRP_JUMP) && mCp.x86().operands[0].type == X86_OP_MEM)
|
if(mCp.IsJump() && mCp[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,10 +100,10 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
||||||
if(addr + mCp.Size() > maxaddr) //we went past the maximum allowed address
|
if(addr + mCp.Size() > maxaddr) //we went past the maximum allowed address
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const auto & op = mCp.x86().operands[0];
|
const auto & op = mCp[0];
|
||||||
if((mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop()) && op.type == X86_OP_IMM) //jump
|
if((mCp.IsJump() || mCp.IsLoop()) && op.type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //jump
|
||||||
{
|
{
|
||||||
auto dest = duint(op.imm);
|
auto dest = duint(op.imm.value.u);
|
||||||
|
|
||||||
if(dest >= maxaddr) //jump across function boundaries
|
if(dest >= maxaddr) //jump across function boundaries
|
||||||
{
|
{
|
||||||
|
@ -113,12 +113,12 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
||||||
{
|
{
|
||||||
fardest = dest;
|
fardest = dest;
|
||||||
}
|
}
|
||||||
else if(end && dest < end && (mCp.GetId() == X86_INS_JMP || mCp.GetId() == X86_INS_LOOP)) //save the last JMP backwards
|
else if(end && dest < end && (mCp.GetId() == ZYDIS_MNEMONIC_JMP || mCp.GetId() == ZYDIS_MNEMONIC_LOOP)) //save the last JMP backwards
|
||||||
{
|
{
|
||||||
jumpback = addr;
|
jumpback = addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(mCp.InGroup(CS_GRP_RET)) //possible function end?
|
else if(mCp.IsRet()) //possible function end?
|
||||||
{
|
{
|
||||||
end = addr;
|
end = addr;
|
||||||
if(fardest < addr) //we stop if the farthest JXX destination forward is before this RET
|
if(fardest < addr) //we stop if the farthest JXX destination forward is before this RET
|
||||||
|
@ -137,12 +137,12 @@ duint LinearAnalysis::getReferenceOperand() const
|
||||||
{
|
{
|
||||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||||
{
|
{
|
||||||
const auto & op = mCp.x86().operands[i];
|
const auto & op = mCp[i];
|
||||||
if(mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop()) //skip jumps/loops
|
if(mCp.IsJump() || mCp.IsLoop()) //skip jumps/loops
|
||||||
continue;
|
continue;
|
||||||
if(op.type == X86_OP_IMM) //we are looking for immediate references
|
if(op.type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //we are looking for immediate references
|
||||||
{
|
{
|
||||||
auto dest = duint(op.imm);
|
auto dest = duint(op.imm.value.u);
|
||||||
if(inRange(dest))
|
if(inRange(dest))
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
||||||
xref.from = mCp.Address();
|
xref.from = mCp.Address();
|
||||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||||
{
|
{
|
||||||
duint dest = mCp.ResolveOpValue(i, [](x86_reg)->size_t
|
duint dest = mCp.ResolveOpValue(i, [](ZydisRegister)->size_t
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
@ -116,23 +116,23 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
||||||
if(xref.addr)
|
if(xref.addr)
|
||||||
mXrefs.push_back(xref);
|
mXrefs.push_back(xref);
|
||||||
|
|
||||||
if(!mCp.IsNop() && (mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop())) //non-nop jump
|
if(!mCp.IsNop() && (mCp.IsJump() || mCp.IsLoop())) //non-nop jump
|
||||||
{
|
{
|
||||||
//set the branch destinations
|
//set the branch destinations
|
||||||
node.brtrue = mCp.BranchDestination();
|
node.brtrue = mCp.BranchDestination();
|
||||||
if(mCp.GetId() != X86_INS_JMP && mCp.GetId() != X86_INS_LJMP) //unconditional jumps dont have a brfalse
|
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||||
node.brfalse = node.end + mCp.Size();
|
node.brfalse = node.end + mCp.Size();
|
||||||
|
|
||||||
//consider register/memory branches as terminal nodes
|
//consider register/memory branches as terminal nodes
|
||||||
if(mCp[0].type != X86_OP_IMM)
|
if(mCp[0].type != ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
//jmp ptr [index * sizeof(duint) + switchTable]
|
//jmp ptr [index * sizeof(duint) + switchTable]
|
||||||
if(mCp[0].type == X86_OP_MEM && mCp[0].mem.base == X86_OP_INVALID && mCp[0].mem.index != X86_OP_INVALID
|
if(mCp[0].type == ZYDIS_OPERAND_TYPE_MEMORY && mCp[0].mem.base == ZYDIS_REGISTER_NONE && mCp[0].mem.index != ZYDIS_REGISTER_NONE
|
||||||
&& mCp[0].mem.scale == sizeof(duint) && MemIsValidReadPtr(duint(mCp[0].mem.disp)))
|
&& mCp[0].mem.scale == sizeof(duint) && MemIsValidReadPtr(duint(mCp[0].mem.disp.value)))
|
||||||
{
|
{
|
||||||
Memory<duint*> switchTable(512 * sizeof(duint));
|
Memory<duint*> switchTable(512 * sizeof(duint));
|
||||||
duint actualSize, index;
|
duint actualSize, index;
|
||||||
MemRead(duint(mCp[0].mem.disp), switchTable(), 512 * sizeof(duint), &actualSize);
|
MemRead(duint(mCp[0].mem.disp.value), switchTable(), 512 * sizeof(duint), &actualSize);
|
||||||
actualSize /= sizeof(duint);
|
actualSize /= sizeof(duint);
|
||||||
for(index = 0; index < actualSize; index++)
|
for(index = 0; index < actualSize; index++)
|
||||||
if(MemIsCodePage(switchTable()[index], false) == false)
|
if(MemIsCodePage(switchTable()[index], false) == false)
|
||||||
|
@ -168,11 +168,11 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(mCp.InGroup(CS_GRP_CALL)) //call
|
if(mCp.IsCall())
|
||||||
{
|
{
|
||||||
//TODO: add this to a queue to be analyzed later
|
//TODO: add this to a queue to be analyzed later
|
||||||
}
|
}
|
||||||
if(mCp.InGroup(CS_GRP_RET)) //return
|
if(mCp.IsRet())
|
||||||
{
|
{
|
||||||
node.terminal = true;
|
node.terminal = true;
|
||||||
graph.AddNode(node);
|
graph.AddNode(node);
|
||||||
|
@ -224,17 +224,17 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
||||||
while(addr <= node.end) //disassemble all instructions
|
while(addr <= node.end) //disassemble all instructions
|
||||||
{
|
{
|
||||||
auto size = mCp.Disassemble(addr, translateAddr(addr)) ? mCp.Size() : 1;
|
auto size = mCp.Disassemble(addr, translateAddr(addr)) ? mCp.Size() : 1;
|
||||||
if(mCp.InGroup(CS_GRP_CALL) && mCp.OpCount()) //call reg / call [reg+X]
|
if(mCp.IsCall() && mCp.OpCount()) //call reg / call [reg+X]
|
||||||
{
|
{
|
||||||
auto & op = mCp[0];
|
auto & op = mCp[0];
|
||||||
switch(op.type)
|
switch(op.type)
|
||||||
{
|
{
|
||||||
case X86_OP_REG:
|
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||||
node.indirectcall = true;
|
node.indirectcall = true;
|
||||||
break;
|
break;
|
||||||
case X86_OP_MEM:
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
node.indirectcall |= op.mem.base != X86_REG_RIP &&
|
node.indirectcall |= op.mem.base != ZYDIS_REGISTER_RIP &&
|
||||||
(op.mem.base != X86_REG_INVALID || op.mem.index != X86_REG_INVALID);
|
(op.mem.base != ZYDIS_REGISTER_NONE || op.mem.index != ZYDIS_REGISTER_NONE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -21,7 +21,7 @@ void XrefsAnalysis::Analyse()
|
||||||
xref.from = mCp.Address();
|
xref.from = mCp.Address();
|
||||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||||
{
|
{
|
||||||
duint dest = mCp.ResolveOpValue(i, [](x86_reg)->size_t
|
duint dest = mCp.ResolveOpValue(i, [](ZydisRegister)->size_t
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
|
@ -570,8 +570,8 @@ static bool cbModCallFind(Capstone* disasm, BASIC_INSTRUCTION_INFO* basicinfo, R
|
||||||
}
|
}
|
||||||
switch(disasm->GetId())
|
switch(disasm->GetId())
|
||||||
{
|
{
|
||||||
case X86_INS_CALL: //call dword ptr: [&api]
|
case ZYDIS_MNEMONIC_CALL: //call dword ptr: [&api]
|
||||||
case X86_INS_MOV: //mov reg, dword ptr:[&api]
|
case ZYDIS_MNEMONIC_MOV: //mov reg, dword ptr:[&api]
|
||||||
if(!foundaddr && basicinfo->memory.value)
|
if(!foundaddr && basicinfo->memory.value)
|
||||||
{
|
{
|
||||||
duint memaddr;
|
duint memaddr;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
#include "capstone_wrapper.h"
|
#include "zydis_wrapper.h"
|
||||||
#include "mnemonichelp.h"
|
#include "mnemonichelp.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "symbolinfo.h"
|
#include "symbolinfo.h"
|
||||||
|
@ -209,6 +209,9 @@ bool cbInstrCopystr(int argc, char* argv[])
|
||||||
|
|
||||||
bool cbInstrCapstone(int argc, char* argv[])
|
bool cbInstrCapstone(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
if(IsArgumentsLessThan(argc, 2))
|
if(IsArgumentsLessThan(argc, 2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -237,10 +240,8 @@ bool cbInstrCapstone(int argc, char* argv[])
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cs_insn* instr = cp.GetInstr();
|
auto instr = cp.GetInstr();
|
||||||
const cs_detail* detail = instr->detail;
|
int argcount = instr->operandCount;
|
||||||
const cs_x86 & x86 = cp.x86();
|
|
||||||
int argcount = x86.op_count;
|
|
||||||
dprintf_untranslated("%s %s | %s\n", instr->mnemonic, instr->op_str, cp.InstructionText(true).c_str());
|
dprintf_untranslated("%s %s | %s\n", instr->mnemonic, instr->op_str, cp.InstructionText(true).c_str());
|
||||||
dprintf_untranslated("size: %d, id: %d, opcount: %d\n", cp.Size(), cp.GetId(), cp.OpCount());
|
dprintf_untranslated("size: %d, id: %d, opcount: %d\n", cp.Size(), cp.GetId(), cp.OpCount());
|
||||||
if(detail->regs_read_count)
|
if(detail->regs_read_count)
|
||||||
|
@ -301,6 +302,7 @@ bool cbInstrCapstone(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cbInstrVisualize(int argc, char* argv[])
|
bool cbInstrVisualize(int argc, char* argv[])
|
||||||
|
@ -357,10 +359,10 @@ bool cbInstrVisualize(int argc, char* argv[])
|
||||||
if(addr + _cp.Size() > maxaddr) //we went past the maximum allowed address
|
if(addr + _cp.Size() > maxaddr) //we went past the maximum allowed address
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const cs_x86_op & operand = _cp.x86().operands[0];
|
const auto & operand = _cp[0];
|
||||||
if((_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) && operand.type == X86_OP_IMM) //jump
|
if((_cp.IsJump() || _cp.IsLoop()) && operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //jump
|
||||||
{
|
{
|
||||||
duint dest = (duint)operand.imm;
|
duint dest = (duint)operand.imm.value.u;
|
||||||
|
|
||||||
if(dest >= maxaddr) //jump across function boundaries
|
if(dest >= maxaddr) //jump across function boundaries
|
||||||
{
|
{
|
||||||
|
@ -370,12 +372,12 @@ bool cbInstrVisualize(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
fardest = dest;
|
fardest = dest;
|
||||||
}
|
}
|
||||||
else if(end && dest < end && _cp.GetId() == X86_INS_JMP) //save the last JMP backwards
|
else if(end && dest < end && _cp.GetId() == ZYDIS_MNEMONIC_JMP) //save the last JMP backwards
|
||||||
{
|
{
|
||||||
jumpback = addr;
|
jumpback = addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(_cp.InGroup(CS_GRP_RET)) //possible function end?
|
else if(_cp.IsRet()) //possible function end?
|
||||||
{
|
{
|
||||||
end = addr;
|
end = addr;
|
||||||
if(fardest < addr) //we stop if the farthest JXX destination forward is before this RET
|
if(fardest < addr) //we stop if the farthest JXX destination forward is before this RET
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "encodemap.h"
|
#include "encodemap.h"
|
||||||
#include "stringutils.h"
|
#include "stringutils.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
std::unordered_map<ENCODETYPE, std::string> disasmMap;
|
std::unordered_map<ENCODETYPE, std::string> disasmMap;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "taskthread.h"
|
#include "taskthread.h"
|
||||||
#include "animate.h"
|
#include "animate.h"
|
||||||
#include "simplescript.h"
|
#include "simplescript.h"
|
||||||
#include "capstone_wrapper.h"
|
#include "zydis_wrapper.h"
|
||||||
#include "cmd-watch-control.h"
|
#include "cmd-watch-control.h"
|
||||||
#include "filemap.h"
|
#include "filemap.h"
|
||||||
#include "jit.h"
|
#include "jit.h"
|
||||||
|
@ -1164,7 +1164,7 @@ void cbRtrStep()
|
||||||
unsigned char data[MAX_DISASM_BUFFER];
|
unsigned char data[MAX_DISASM_BUFFER];
|
||||||
memset(data, 0, sizeof(data));
|
memset(data, 0, sizeof(data));
|
||||||
MemRead(cip, data, MAX_DISASM_BUFFER);
|
MemRead(cip, data, MAX_DISASM_BUFFER);
|
||||||
if(cp.Disassemble(cip, data) && cp.GetId() == X86_INS_RET)
|
if(cp.Disassemble(cip, data) && cp.IsRet())
|
||||||
cbRtrFinalStep(true);
|
cbRtrFinalStep(true);
|
||||||
else
|
else
|
||||||
StepOver((void*)cbRtrStep);
|
StepOver((void*)cbRtrStep);
|
||||||
|
|
|
@ -34,53 +34,53 @@ void fillbasicinfo(Capstone* cp, BASIC_INSTRUCTION_INFO* basicinfo, bool instrTe
|
||||||
//instruction size
|
//instruction size
|
||||||
basicinfo->size = cp->Size();
|
basicinfo->size = cp->Size();
|
||||||
//branch/call info
|
//branch/call info
|
||||||
if(cp->InGroup(CS_GRP_CALL))
|
if(cp->IsCall())
|
||||||
{
|
{
|
||||||
basicinfo->branch = true;
|
basicinfo->branch = true;
|
||||||
basicinfo->call = true;
|
basicinfo->call = true;
|
||||||
}
|
}
|
||||||
else if(cp->InGroup(CS_GRP_JUMP) || cp->IsLoop())
|
else if(cp->IsJump() || cp->IsLoop())
|
||||||
{
|
{
|
||||||
basicinfo->branch = true;
|
basicinfo->branch = true;
|
||||||
}
|
}
|
||||||
//handle operands
|
//handle operands
|
||||||
for(int i = 0; i < cp->x86().op_count; i++)
|
for(int i = 0; i < cp->OpCount(); i++)
|
||||||
{
|
{
|
||||||
const cs_x86_op & op = cp->x86().operands[i];
|
const auto & op = (*cp)[i];
|
||||||
switch(op.type)
|
switch(op.type)
|
||||||
{
|
{
|
||||||
case X86_OP_IMM:
|
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
||||||
{
|
{
|
||||||
if(basicinfo->branch)
|
if(basicinfo->branch)
|
||||||
{
|
{
|
||||||
basicinfo->type |= TYPE_ADDR;
|
basicinfo->type |= TYPE_ADDR;
|
||||||
basicinfo->addr = duint(op.imm);
|
basicinfo->addr = duint(op.imm.value.u);
|
||||||
basicinfo->value.value = duint(op.imm);
|
basicinfo->value.value = duint(op.imm.value.u);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
basicinfo->type |= TYPE_VALUE;
|
basicinfo->type |= TYPE_VALUE;
|
||||||
basicinfo->value.size = VALUE_SIZE(op.size);
|
basicinfo->value.size = VALUE_SIZE(op.size);
|
||||||
basicinfo->value.value = duint(op.imm);
|
basicinfo->value.value = duint(op.imm.value.u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case X86_OP_MEM:
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
{
|
{
|
||||||
const x86_op_mem & mem = op.mem;
|
const auto & mem = op.mem;
|
||||||
if(instrText)
|
if(instrText)
|
||||||
strcpy_s(basicinfo->memory.mnemonic, cp->OperandText(i).c_str());
|
strcpy_s(basicinfo->memory.mnemonic, cp->OperandText(i).c_str());
|
||||||
basicinfo->memory.size = MEMORY_SIZE(op.size);
|
basicinfo->memory.size = MEMORY_SIZE(op.size);
|
||||||
if(op.mem.base == X86_REG_RIP) //rip-relative
|
if(op.mem.base == ZYDIS_REGISTER_RIP) //rip-relative
|
||||||
{
|
{
|
||||||
basicinfo->memory.value = ULONG_PTR(cp->Address() + op.mem.disp + basicinfo->size);
|
basicinfo->memory.value = ULONG_PTR(cp->Address() + op.mem.disp.value + basicinfo->size);
|
||||||
basicinfo->type |= TYPE_MEMORY;
|
basicinfo->type |= TYPE_MEMORY;
|
||||||
}
|
}
|
||||||
else if(mem.disp)
|
else if(mem.disp.value)
|
||||||
{
|
{
|
||||||
basicinfo->type |= TYPE_MEMORY;
|
basicinfo->type |= TYPE_MEMORY;
|
||||||
basicinfo->memory.value = ULONG_PTR(mem.disp);
|
basicinfo->memory.value = ULONG_PTR(mem.disp.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define _DISASM_FAST_H
|
#define _DISASM_FAST_H
|
||||||
|
|
||||||
#include "_global.h"
|
#include "_global.h"
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
|
|
||||||
void fillbasicinfo(Capstone* disasm, BASIC_INSTRUCTION_INFO* basicinfo, bool instrText = true);
|
void fillbasicinfo(Capstone* disasm, BASIC_INSTRUCTION_INFO* basicinfo, bool instrText = true);
|
||||||
bool disasmfast(duint addr, BASIC_INSTRUCTION_INFO* basicinfo, bool cache = false);
|
bool disasmfast(duint addr, BASIC_INSTRUCTION_INFO* basicinfo, bool cache = false);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "encodemap.h"
|
#include "encodemap.h"
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
#include "datainst_helper.h"
|
#include "datainst_helper.h"
|
||||||
|
|
||||||
duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n)
|
duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n)
|
||||||
|
@ -113,7 +113,7 @@ duint disasmnext(unsigned char* data, duint base, duint size, duint ip, int n)
|
||||||
|
|
||||||
static void HandleCapstoneOperand(Capstone & cp, int opindex, DISASM_ARG* arg, bool getregs)
|
static void HandleCapstoneOperand(Capstone & cp, int opindex, DISASM_ARG* arg, bool getregs)
|
||||||
{
|
{
|
||||||
auto value = cp.ResolveOpValue(opindex, [&cp, getregs](x86_reg reg)
|
auto value = cp.ResolveOpValue(opindex, [&cp, getregs](ZydisRegister reg)
|
||||||
{
|
{
|
||||||
auto regName = getregs ? cp.RegName(reg) : nullptr;
|
auto regName = getregs ? cp.RegName(reg) : nullptr;
|
||||||
return regName ? getregister(nullptr, regName) : 0; //TODO: temporary needs enums + caching
|
return regName ? getregister(nullptr, regName) : 0; //TODO: temporary needs enums + caching
|
||||||
|
@ -123,34 +123,34 @@ static void HandleCapstoneOperand(Capstone & cp, int opindex, DISASM_ARG* arg, b
|
||||||
strcpy_s(arg->mnemonic, cp.OperandText(opindex).c_str());
|
strcpy_s(arg->mnemonic, cp.OperandText(opindex).c_str());
|
||||||
switch(op.type)
|
switch(op.type)
|
||||||
{
|
{
|
||||||
case X86_OP_REG:
|
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||||
{
|
{
|
||||||
arg->type = arg_normal;
|
arg->type = arg_normal;
|
||||||
arg->value = value;
|
arg->value = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case X86_OP_IMM:
|
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
||||||
{
|
{
|
||||||
arg->type = arg_normal;
|
arg->type = arg_normal;
|
||||||
arg->constant = arg->value = value;
|
arg->constant = arg->value = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case X86_OP_MEM:
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
{
|
{
|
||||||
arg->type = arg_memory;
|
arg->type = arg_memory;
|
||||||
const x86_op_mem & mem = op.mem;
|
const auto & mem = op.mem;
|
||||||
if(mem.base == X86_REG_RIP) //rip-relative
|
if(mem.base == ZYDIS_REGISTER_RIP) //rip-relative
|
||||||
arg->constant = cp.Address() + duint(mem.disp) + cp.Size();
|
arg->constant = cp.Address() + duint(mem.disp.value) + cp.Size();
|
||||||
else
|
else
|
||||||
arg->constant = duint(mem.disp);
|
arg->constant = duint(mem.disp.value);
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
if(mem.segment == X86_REG_GS)
|
if(mem.segment == ZYDIS_REGISTER_GS)
|
||||||
{
|
{
|
||||||
arg->segment = SEG_GS;
|
arg->segment = SEG_GS;
|
||||||
#else //x86
|
#else //x86
|
||||||
if(mem.segment == X86_REG_FS)
|
if(mem.segment == ZYDIS_REGISTER_FS)
|
||||||
{
|
{
|
||||||
arg->segment = SEG_FS;
|
arg->segment = SEG_FS;
|
||||||
#endif
|
#endif
|
||||||
|
@ -199,16 +199,16 @@ void disasmget(Capstone & cp, unsigned char* buffer, duint addr, DISASM_INSTR* i
|
||||||
instr->argcount = 0;
|
instr->argcount = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cs_insn* cpInstr = cp.GetInstr();
|
auto cpInstr = cp.GetInstr();
|
||||||
sprintf_s(instr->instruction, "%s %s", cpInstr->mnemonic, cpInstr->op_str);
|
strcpy_s(instr->instruction, cp.InstructionText().c_str());
|
||||||
instr->instr_size = cpInstr->size;
|
instr->instr_size = cpInstr->length;
|
||||||
if(cp.InGroup(CS_GRP_JUMP) || cp.IsLoop() || cp.InGroup(CS_GRP_RET) || cp.InGroup(CS_GRP_CALL))
|
if(cp.IsBranchType(Capstone::BT_Jmp | Capstone::BT_Loop | Capstone::BT_Ret | Capstone::BT_Call))
|
||||||
instr->type = instr_branch;
|
instr->type = instr_branch;
|
||||||
else if(strstr(cpInstr->op_str, "sp") || strstr(cpInstr->op_str, "bp"))
|
else if(strstr(instr->instruction, "sp") || strstr(instr->instruction, "bp"))
|
||||||
instr->type = instr_stack;
|
instr->type = instr_stack;
|
||||||
else
|
else
|
||||||
instr->type = instr_normal;
|
instr->type = instr_normal;
|
||||||
instr->argcount = cp.x86().op_count <= 3 ? cp.x86().op_count : 3;
|
instr->argcount = cp.OpCount() <= 3 ? cp.OpCount() : 3;
|
||||||
for(int i = 0; i < instr->argcount; i++)
|
for(int i = 0; i < instr->argcount; i++)
|
||||||
HandleCapstoneOperand(cp, i, &instr->arg[i], getregs);
|
HandleCapstoneOperand(cp, i, &instr->arg[i], getregs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define _DISASM_HELPER_H
|
#define _DISASM_HELPER_H
|
||||||
|
|
||||||
#include "_global.h"
|
#include "_global.h"
|
||||||
#include "capstone_wrapper.h"
|
#include "zydis_wrapper.h"
|
||||||
|
|
||||||
//functions
|
//functions
|
||||||
duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n);
|
duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "encodemap.h"
|
#include "encodemap.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "addrinfo.h"
|
#include "addrinfo.h"
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
|
|
||||||
struct ENCODEMAP : AddrInfo
|
struct ENCODEMAP : AddrInfo
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
#include "plugin_loader.h"
|
#include "plugin_loader.h"
|
||||||
#include "_dbgfunctions.h"
|
#include "_dbgfunctions.h"
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
#include "_scriptapi_gui.h"
|
#include "_scriptapi_gui.h"
|
||||||
#include "filehelper.h"
|
#include "filehelper.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
|
|
|
@ -389,13 +389,13 @@
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<OutDir>$(ProjectDir)..\..\bin\x64\</OutDir>
|
<OutDir>$(ProjectDir)..\..\bin\x64\</OutDir>
|
||||||
<TargetName>x64dbg</TargetName>
|
<TargetName>x64dbg</TargetName>
|
||||||
<IncludePath>$(ProjectDir)..\capstone_wrapper;$(ProjectDir);$(ProjectDir)analysis;$(ProjectDir)commands;$(IncludePath)</IncludePath>
|
<IncludePath>$(ProjectDir)..\zydis_wrapper;$(ProjectDir)..\capstone_wrapper;$(ProjectDir);$(ProjectDir)analysis;$(ProjectDir)commands;$(IncludePath)</IncludePath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<OutDir>$(ProjectDir)..\..\bin\x64d\</OutDir>
|
<OutDir>$(ProjectDir)..\..\bin\x64d\</OutDir>
|
||||||
<TargetName>x64dbg</TargetName>
|
<TargetName>x64dbg</TargetName>
|
||||||
<IncludePath>$(ProjectDir)..\capstone_wrapper;$(ProjectDir);$(ProjectDir)analysis;$(ProjectDir)commands;$(IncludePath)</IncludePath>
|
<IncludePath>$(ProjectDir)..\zydis_wrapper;$(ProjectDir)..\capstone_wrapper;$(ProjectDir);$(ProjectDir)analysis;$(ProjectDir)commands;$(IncludePath)</IncludePath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
|
@ -467,7 +467,7 @@
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>ntdll\ntdll_x64.lib;keystone\keystone_x64.lib;$(ProjectDir)..\capstone_wrapper\bin\x64\capstone_wrapper.lib;$(ProjectDir)..\capstone_wrapper\capstone\capstone_x64.lib;yara\yara_x64.lib;lz4\lz4_x64.lib;jansson\jansson_x64.lib;DeviceNameResolver\DeviceNameResolver_x64.lib;XEDParse\XEDParse_x64.lib;$(SolutionDir)bin\x64\x64bridge.lib;dbghelp\dbghelp_x64.lib;TitanEngine\TitanEngine_x64.lib;ws2_32.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(ProjectDir)..\zydis_wrapper\bin\x64\zydis_wrapper.lib;$(ProjectDir)..\zydis_wrapper\Zydis\Zydis_x64.lib;$(ProjectDir)..\capstone_wrapper\bin\x64\capstone_wrapper.lib;$(ProjectDir)..\capstone_wrapper\capstone\capstone_x64.lib;ntdll\ntdll_x64.lib;keystone\keystone_x64.lib;yara\yara_x64.lib;lz4\lz4_x64.lib;jansson\jansson_x64.lib;DeviceNameResolver\DeviceNameResolver_x64.lib;XEDParse\XEDParse_x64.lib;$(SolutionDir)bin\x64\x64bridge.lib;dbghelp\dbghelp_x64.lib;TitanEngine\TitanEngine_x64.lib;ws2_32.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
@ -491,7 +491,7 @@
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<EnableCOMDATFolding>false</EnableCOMDATFolding>
|
<EnableCOMDATFolding>false</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>false</OptimizeReferences>
|
<OptimizeReferences>false</OptimizeReferences>
|
||||||
<AdditionalDependencies>ntdll\ntdll_x64.lib;keystone\keystone_x64.lib;$(ProjectDir)..\capstone_wrapper\bin\x64d\capstone_wrapper.lib;$(ProjectDir)..\capstone_wrapper\capstone\capstone_x64.lib;yara\yara_x64.lib;lz4\lz4_x64.lib;jansson\jansson_x64.lib;DeviceNameResolver\DeviceNameResolver_x64.lib;XEDParse\XEDParse_x64.lib;$(SolutionDir)bin\x64d\x64bridge.lib;dbghelp\dbghelp_x64.lib;TitanEngine\TitanEngine_x64.lib;ws2_32.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(ProjectDir)..\zydis_wrapper\bin\x64d\zydis_wrapper.lib;$(ProjectDir)..\zydis_wrapper\Zydis\Zydis_x64.lib;$(ProjectDir)..\capstone_wrapper\bin\x64d\capstone_wrapper.lib;$(ProjectDir)..\capstone_wrapper\capstone\capstone_x64.lib;ntdll\ntdll_x64.lib;keystone\keystone_x64.lib;yara\yara_x64.lib;lz4\lz4_x64.lib;jansson\jansson_x64.lib;DeviceNameResolver\DeviceNameResolver_x64.lib;XEDParse\XEDParse_x64.lib;$(SolutionDir)bin\x64d\x64bridge.lib;dbghelp\dbghelp_x64.lib;TitanEngine\TitanEngine_x64.lib;ws2_32.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
|
|
@ -200,23 +200,15 @@ Instruction_t QBeaEngine::DisassembleAt(byte_t* data, duint size, duint origBase
|
||||||
|
|
||||||
auto branchType = Instruction_t::None;
|
auto branchType = Instruction_t::None;
|
||||||
Instruction_t wInst;
|
Instruction_t wInst;
|
||||||
if(success && (cp.InGroup(CS_GRP_JUMP) || cp.IsLoop() || cp.InGroup(CS_GRP_CALL) || cp.InGroup(CS_GRP_RET)))
|
if(success && (cp.IsBranchType(Capstone::BT_Jmp | Capstone::BT_Call | Capstone::BT_Ret | Capstone::BT_Loop)))
|
||||||
{
|
{
|
||||||
wInst.branchDestination = DbgGetBranchDestination(origBase + origInstRVA);
|
wInst.branchDestination = DbgGetBranchDestination(origBase + origInstRVA);
|
||||||
switch(cp.GetId())
|
if(cp.IsBranchType(Capstone::BT_UncondJmp))
|
||||||
{
|
|
||||||
case X86_INS_JMP:
|
|
||||||
case X86_INS_LJMP:
|
|
||||||
branchType = Instruction_t::Unconditional;
|
branchType = Instruction_t::Unconditional;
|
||||||
break;
|
else if(cp.IsBranchType(Capstone::BT_Call))
|
||||||
case X86_INS_CALL:
|
|
||||||
case X86_INS_LCALL:
|
|
||||||
branchType = Instruction_t::Call;
|
branchType = Instruction_t::Call;
|
||||||
break;
|
else if(cp.IsBranchType(Capstone::BT_CondJmp))
|
||||||
default:
|
branchType = Instruction_t::Conditional;
|
||||||
branchType = cp.InGroup(CS_GRP_RET) ? Instruction_t::None : Instruction_t::Conditional;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wInst.branchDestination = 0;
|
wInst.branchDestination = 0;
|
||||||
|
@ -233,8 +225,9 @@ Instruction_t QBeaEngine::DisassembleAt(byte_t* data, duint size, duint origBase
|
||||||
|
|
||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
|
/* TODO
|
||||||
|
auto instr = cp.GetInstr();
|
||||||
cp.RegInfo(reginfo);
|
cp.RegInfo(reginfo);
|
||||||
cp.FlagInfo(flaginfo);
|
|
||||||
|
|
||||||
auto flaginfo2reginfo = [](uint8_t info)
|
auto flaginfo2reginfo = [](uint8_t info)
|
||||||
{
|
{
|
||||||
|
@ -253,14 +246,15 @@ Instruction_t QBeaEngine::DisassembleAt(byte_t* data, duint size, duint origBase
|
||||||
for(uint8_t i = Capstone::FLAG_INVALID; i < Capstone::FLAG_ENDING; i++)
|
for(uint8_t i = Capstone::FLAG_INVALID; i < Capstone::FLAG_ENDING; i++)
|
||||||
if(flaginfo[i])
|
if(flaginfo[i])
|
||||||
{
|
{
|
||||||
reginfo[X86_REG_EFLAGS] = Capstone::None;
|
reginfo[ZYDIS_REGISTER_FLAGS] = Capstone::None;
|
||||||
wInst.regsReferenced.push_back({cp.FlagName(Capstone::Flag(i)), flaginfo2reginfo(flaginfo[i])});
|
wInst.regsReferenced.push_back({cp.FlagName(Capstone::Flag(i)), flaginfo2reginfo(flaginfo[i])});
|
||||||
}
|
}
|
||||||
|
|
||||||
reginfo[ArchValue(X86_REG_EIP, X86_REG_RIP)] = Capstone::None;
|
reginfo[ArchValue(ZYDIS_REGISTER_EIP, ZYDIS_REGISTER_RIP)] = Capstone::None;
|
||||||
for(uint8_t i = X86_REG_INVALID; i < X86_REG_ENDING; i++)
|
for(uint8_t i = ZYDIS_REGISTER_NONE; i < ZYDIS_REGISTER_ENUM_COUNT; i++)
|
||||||
if(reginfo[i])
|
if(reginfo[i])
|
||||||
wInst.regsReferenced.push_back({cp.RegName(x86_reg(i)), reginfo[i]});
|
wInst.regsReferenced.push_back({cp.RegName(x86_reg(i)), reginfo[i]});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return wInst;
|
return wInst;
|
||||||
|
|
|
@ -67,8 +67,8 @@ private:
|
||||||
bool _bLongDataInst;
|
bool _bLongDataInst;
|
||||||
EncodeMap* mEncodeMap;
|
EncodeMap* mEncodeMap;
|
||||||
CodeFoldingHelper* mCodeFoldingManager;
|
CodeFoldingHelper* mCodeFoldingManager;
|
||||||
uint8_t reginfo[X86_REG_ENDING];
|
uint8_t reginfo[ZYDIS_REGISTER_ENUM_COUNT];
|
||||||
uint8_t flaginfo[Capstone::FLAG_ENDING];
|
uint8_t flaginfo[ZYDIS_CPUFLAG_ENUM_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QBEAENGINE_H
|
#endif // QBEAENGINE_H
|
||||||
|
|
|
@ -362,21 +362,26 @@ bool CapstoneTokenizer::tokenizePrefix()
|
||||||
{
|
{
|
||||||
bool hasPrefix = true;
|
bool hasPrefix = true;
|
||||||
QString prefixText;
|
QString prefixText;
|
||||||
//TODO: look at multiple prefixes on one instruction (https://github.com/aquynh/capstone/blob/921904888d7c1547c558db3a24fa64bcf97dede4/arch/X86/X86DisassemblerDecoder.c#L540)
|
|
||||||
switch(_cp.x86().prefix[0])
|
//TODO: look at multiple prefixes on one instruction
|
||||||
{
|
auto attr = _cp.GetInstr()->attributes;
|
||||||
case X86_PREFIX_LOCK:
|
|
||||||
|
if(attr & ZYDIS_ATTRIB_HAS_LOCK)
|
||||||
prefixText = "lock";
|
prefixText = "lock";
|
||||||
break;
|
else if(attr & ZYDIS_ATTRIB_HAS_REP)
|
||||||
case X86_PREFIX_REP:
|
|
||||||
prefixText = "rep";
|
prefixText = "rep";
|
||||||
break;
|
else if(attr & ZYDIS_ATTRIB_HAS_REPNE)
|
||||||
case X86_PREFIX_REPNE:
|
prefixText = "repe";
|
||||||
|
else if(attr & ZYDIS_ATTRIB_HAS_REPNE)
|
||||||
prefixText = "repne";
|
prefixText = "repne";
|
||||||
break;
|
else if(attr & ZYDIS_ATTRIB_HAS_BOUND)
|
||||||
default:
|
prefixText = "bnd";
|
||||||
|
else if(attr & ZYDIS_ATTRIB_HAS_XACQUIRE)
|
||||||
|
prefixText = "xacquire";
|
||||||
|
else if(attr & ZYDIS_ATTRIB_HAS_XRELEASE)
|
||||||
|
prefixText = "xrelease";
|
||||||
|
else
|
||||||
hasPrefix = false;
|
hasPrefix = false;
|
||||||
}
|
|
||||||
|
|
||||||
if(hasPrefix)
|
if(hasPrefix)
|
||||||
{
|
{
|
||||||
|
@ -391,52 +396,25 @@ bool CapstoneTokenizer::tokenizeMnemonic()
|
||||||
{
|
{
|
||||||
QString mnemonic = QString(_cp.Mnemonic().c_str());
|
QString mnemonic = QString(_cp.Mnemonic().c_str());
|
||||||
_mnemonicType = TokenType::MnemonicNormal;
|
_mnemonicType = TokenType::MnemonicNormal;
|
||||||
|
|
||||||
auto id = _cp.GetId();
|
auto id = _cp.GetId();
|
||||||
if(isNop)
|
if(isNop)
|
||||||
_mnemonicType = TokenType::MnemonicNop;
|
_mnemonicType = TokenType::MnemonicNop;
|
||||||
else if(_cp.InGroup(CS_GRP_CALL))
|
else if(_cp.IsCall())
|
||||||
_mnemonicType = TokenType::MnemonicCall;
|
_mnemonicType = TokenType::MnemonicCall;
|
||||||
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())
|
else if(_cp.IsJump() || _cp.IsLoop())
|
||||||
{
|
{
|
||||||
switch(id)
|
_mnemonicType = (id == ZYDIS_MNEMONIC_JMP) ?
|
||||||
{
|
TokenType::MnemonicUncondJump : TokenType::MnemonicCondJump;
|
||||||
case X86_INS_JMP:
|
|
||||||
case X86_INS_LJMP:
|
|
||||||
_mnemonicType = TokenType::MnemonicUncondJump;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
_mnemonicType = TokenType::MnemonicCondJump;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(_cp.IsInt3())
|
else if(_cp.IsInt3())
|
||||||
_mnemonicType = TokenType::MnemonicInt3;
|
_mnemonicType = TokenType::MnemonicInt3;
|
||||||
else if(_cp.IsUnusual())
|
else if(_cp.IsUnusual())
|
||||||
_mnemonicType = TokenType::MnemonicUnusual;
|
_mnemonicType = TokenType::MnemonicUnusual;
|
||||||
else if(_cp.InGroup(CS_GRP_RET))
|
else if(_cp.IsRet())
|
||||||
_mnemonicType = TokenType::MnemonicRet;
|
_mnemonicType = TokenType::MnemonicRet;
|
||||||
else
|
else if(_cp.IsPushPop())
|
||||||
{
|
_mnemonicType = TokenType::MnemonicPushPop;
|
||||||
switch(id)
|
|
||||||
{
|
|
||||||
case X86_INS_PUSH:
|
|
||||||
case X86_INS_PUSHF:
|
|
||||||
case X86_INS_PUSHFD:
|
|
||||||
case X86_INS_PUSHFQ:
|
|
||||||
case X86_INS_PUSHAL:
|
|
||||||
case X86_INS_PUSHAW:
|
|
||||||
case X86_INS_POP:
|
|
||||||
case X86_INS_POPF:
|
|
||||||
case X86_INS_POPFD:
|
|
||||||
case X86_INS_POPFQ:
|
|
||||||
case X86_INS_POPAL:
|
|
||||||
case X86_INS_POPAW:
|
|
||||||
_mnemonicType = TokenType::MnemonicPushPop;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenizeMnemonic(_mnemonicType, mnemonic);
|
tokenizeMnemonic(_mnemonicType, mnemonic);
|
||||||
|
|
||||||
|
@ -459,57 +437,65 @@ bool CapstoneTokenizer::tokenizeMnemonic(TokenType type, const QString & mnemoni
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CapstoneTokenizer::tokenizeOperand(const cs_x86_op & op)
|
bool CapstoneTokenizer::tokenizeOperand(const ZydisDecodedOperand & op)
|
||||||
{
|
{
|
||||||
switch(op.type)
|
switch(op.type)
|
||||||
{
|
{
|
||||||
case X86_OP_REG:
|
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||||
return tokenizeRegOperand(op);
|
return tokenizeRegOperand(op);
|
||||||
case X86_OP_IMM:
|
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
||||||
return tokenizeImmOperand(op);
|
return tokenizeImmOperand(op);
|
||||||
case X86_OP_MEM:
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
return tokenizeMemOperand(op);
|
return tokenizeMemOperand(op);
|
||||||
case X86_OP_INVALID:
|
case ZYDIS_OPERAND_TYPE_UNUSED:
|
||||||
return tokenizeInvalidOperand(op);
|
return tokenizeInvalidOperand(op);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CapstoneTokenizer::tokenizeRegOperand(const cs_x86_op & op)
|
bool CapstoneTokenizer::tokenizeRegOperand(const ZydisDecodedOperand & op)
|
||||||
{
|
{
|
||||||
auto registerType = TokenType::GeneralRegister;
|
auto registerType = TokenType::GeneralRegister;
|
||||||
auto reg = op.reg;
|
auto reg = op.reg;
|
||||||
if(reg >= X86_REG_FP0 && reg <= X86_REG_FP7)
|
auto regClass = ZydisRegisterGetClass(reg);
|
||||||
registerType = TokenType::FpuRegister;
|
|
||||||
else if(reg >= X86_REG_ST0 && reg <= X86_REG_ST7)
|
switch(regClass)
|
||||||
registerType = TokenType::FpuRegister;
|
{
|
||||||
else if(reg >= X86_REG_MM0 && reg <= X86_REG_MM7)
|
case ZYDIS_REGCLASS_X87: registerType = TokenType::FpuRegister; break;
|
||||||
registerType = TokenType::MmxRegister;
|
case ZYDIS_REGCLASS_MMX: registerType = TokenType::MmxRegister; break;
|
||||||
else if(reg >= X86_REG_XMM0 && reg <= X86_REG_XMM31)
|
case ZYDIS_REGCLASS_XMM: registerType = TokenType::XmmRegister; break;
|
||||||
registerType = TokenType::XmmRegister;
|
case ZYDIS_REGCLASS_YMM: registerType = TokenType::YmmRegister; break;
|
||||||
else if(reg >= X86_REG_YMM0 && reg <= X86_REG_YMM31)
|
case ZYDIS_REGCLASS_ZMM: registerType = TokenType::ZmmRegister; break;
|
||||||
registerType = TokenType::YmmRegister;
|
}
|
||||||
else if(reg >= X86_REG_ZMM0 && reg <= X86_REG_ZMM31)
|
|
||||||
registerType = TokenType::ZmmRegister;
|
if(reg == ArchValue(ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS))
|
||||||
else if(reg == ArchValue(X86_REG_FS, X86_REG_GS))
|
|
||||||
registerType = TokenType::MnemonicUnusual;
|
registerType = TokenType::MnemonicUnusual;
|
||||||
|
|
||||||
addToken(registerType, _cp.RegName(reg));
|
addToken(registerType, _cp.RegName(reg));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CapstoneTokenizer::tokenizeImmOperand(const cs_x86_op & op)
|
bool CapstoneTokenizer::tokenizeImmOperand(const ZydisDecodedOperand & op)
|
||||||
{
|
{
|
||||||
auto value = duint(op.imm) & (duint(-1) >> (op.size ? 8 * (sizeof(duint) - op.size) : 0));
|
duint value;
|
||||||
auto valueType = TokenType::Value;
|
TokenType valueType;
|
||||||
if(_cp.InGroup(CS_GRP_JUMP) || _cp.InGroup(CS_GRP_CALL) || _cp.IsLoop())
|
if(_cp.IsBranchType(Capstone::BT_Jmp | Capstone::BT_Call | Capstone::BT_Loop))
|
||||||
|
{
|
||||||
|
value = _cp.BranchDestination();
|
||||||
valueType = TokenType::Address;
|
valueType = TokenType::Address;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = duint(op.imm.value.u) & (duint(-1) >> (op.size ? (8 * sizeof(duint) - op.size) : 0));
|
||||||
|
valueType = TokenType::Value;
|
||||||
|
}
|
||||||
auto tokenValue = TokenValue(op.size, value);
|
auto tokenValue = TokenValue(op.size, value);
|
||||||
addToken(valueType, printValue(tokenValue, true, _maxModuleLength), tokenValue);
|
addToken(valueType, printValue(tokenValue, true, _maxModuleLength), tokenValue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CapstoneTokenizer::tokenizeMemOperand(const cs_x86_op & op)
|
bool CapstoneTokenizer::tokenizeMemOperand(const ZydisDecodedOperand & op)
|
||||||
{
|
{
|
||||||
//memory size
|
//memory size
|
||||||
const char* sizeText = _cp.MemSizeName(op.size);
|
const char* sizeText = _cp.MemSizeName(op.size);
|
||||||
|
@ -520,37 +506,19 @@ bool CapstoneTokenizer::tokenizeMemOperand(const cs_x86_op & op)
|
||||||
|
|
||||||
//memory segment
|
//memory segment
|
||||||
const auto & mem = op.mem;
|
const auto & mem = op.mem;
|
||||||
const char* segmentText = _cp.RegName(mem.segment);
|
auto segmentType = op.reg == ArchValue(ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS)
|
||||||
if(mem.segment == X86_REG_INVALID) //segment not set
|
? TokenType::MnemonicUnusual : TokenType::MemorySegment;
|
||||||
{
|
addToken(segmentType, _cp.RegName(mem.segment));
|
||||||
switch(mem.base)
|
|
||||||
{
|
|
||||||
#ifdef _WIN64
|
|
||||||
case X86_REG_RSP:
|
|
||||||
case X86_REG_RBP:
|
|
||||||
#else //x86
|
|
||||||
case X86_REG_ESP:
|
|
||||||
case X86_REG_EBP:
|
|
||||||
#endif //_WIN64
|
|
||||||
segmentText = "ss";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
segmentText = "ds";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto segmentType = op.reg == ArchValue(X86_REG_FS, X86_REG_GS) ? TokenType::MnemonicUnusual : TokenType::MemorySegment;
|
|
||||||
addToken(segmentType, segmentText);
|
|
||||||
addToken(TokenType::Uncategorized, ":");
|
addToken(TokenType::Uncategorized, ":");
|
||||||
|
|
||||||
//memory opening bracket
|
//memory opening bracket
|
||||||
auto bracketsType = TokenType::MemoryBrackets;
|
auto bracketsType = TokenType::MemoryBrackets;
|
||||||
switch(mem.base)
|
switch(mem.base)
|
||||||
{
|
{
|
||||||
case X86_REG_ESP:
|
case ZYDIS_REGISTER_ESP:
|
||||||
case X86_REG_RSP:
|
case ZYDIS_REGISTER_RSP:
|
||||||
case X86_REG_EBP:
|
case ZYDIS_REGISTER_EBP:
|
||||||
case X86_REG_RBP:
|
case ZYDIS_REGISTER_RBP:
|
||||||
bracketsType = TokenType::MemoryStackBrackets;
|
bracketsType = TokenType::MemoryStackBrackets;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -558,9 +526,9 @@ bool CapstoneTokenizer::tokenizeMemOperand(const cs_x86_op & op)
|
||||||
addToken(bracketsType, "[");
|
addToken(bracketsType, "[");
|
||||||
|
|
||||||
//stuff inside the brackets
|
//stuff inside the brackets
|
||||||
if(mem.base == X86_REG_RIP) //rip-relative (#replacement)
|
if(mem.base == ZYDIS_REGISTER_RIP) //rip-relative (#replacement)
|
||||||
{
|
{
|
||||||
duint addr = _cp.Address() + duint(mem.disp) + _cp.Size();
|
duint addr = _cp.Address() + duint(mem.disp.value) + _cp.Size();
|
||||||
TokenValue value = TokenValue(op.size, addr);
|
TokenValue value = TokenValue(op.size, addr);
|
||||||
auto displacementType = DbgMemIsValidReadPtr(addr) ? TokenType::Address : TokenType::Value;
|
auto displacementType = DbgMemIsValidReadPtr(addr) ? TokenType::Address : TokenType::Value;
|
||||||
addToken(displacementType, printValue(value, false, _maxModuleLength), value);
|
addToken(displacementType, printValue(value, false, _maxModuleLength), value);
|
||||||
|
@ -568,12 +536,12 @@ bool CapstoneTokenizer::tokenizeMemOperand(const cs_x86_op & op)
|
||||||
else //#base + #index * #scale + #displacement
|
else //#base + #index * #scale + #displacement
|
||||||
{
|
{
|
||||||
bool prependPlus = false;
|
bool prependPlus = false;
|
||||||
if(mem.base != X86_REG_INVALID) //base register
|
if(mem.base != ZYDIS_REGISTER_NONE) //base register
|
||||||
{
|
{
|
||||||
addToken(TokenType::MemoryBaseRegister, _cp.RegName(mem.base));
|
addToken(TokenType::MemoryBaseRegister, _cp.RegName(mem.base));
|
||||||
prependPlus = true;
|
prependPlus = true;
|
||||||
}
|
}
|
||||||
if(mem.index != X86_REG_INVALID) //index register
|
if(mem.index != ZYDIS_REGISTER_NONE) //index register
|
||||||
{
|
{
|
||||||
if(prependPlus)
|
if(prependPlus)
|
||||||
addMemoryOperator('+');
|
addMemoryOperator('+');
|
||||||
|
@ -585,16 +553,16 @@ bool CapstoneTokenizer::tokenizeMemOperand(const cs_x86_op & op)
|
||||||
}
|
}
|
||||||
prependPlus = true;
|
prependPlus = true;
|
||||||
}
|
}
|
||||||
if(mem.disp)
|
if(mem.disp.value)
|
||||||
{
|
{
|
||||||
char operatorText = '+';
|
char operatorText = '+';
|
||||||
TokenValue value(op.size, duint(mem.disp));
|
TokenValue value(op.size, duint(mem.disp.value));
|
||||||
auto displacementType = DbgMemIsValidReadPtr(duint(mem.disp)) ? TokenType::Address : TokenType::Value;
|
auto displacementType = DbgMemIsValidReadPtr(duint(mem.disp.value)) ? TokenType::Address : TokenType::Value;
|
||||||
QString valueText;
|
QString valueText;
|
||||||
if(mem.disp < 0)
|
if(mem.disp.value < 0)
|
||||||
{
|
{
|
||||||
operatorText = '-';
|
operatorText = '-';
|
||||||
valueText = printValue(TokenValue(op.size, duint(mem.disp * -1)), false, _maxModuleLength);
|
valueText = printValue(TokenValue(op.size, duint(mem.disp.value * -1)), false, _maxModuleLength);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
valueText = printValue(value, false, _maxModuleLength);
|
valueText = printValue(value, false, _maxModuleLength);
|
||||||
|
@ -611,7 +579,7 @@ bool CapstoneTokenizer::tokenizeMemOperand(const cs_x86_op & op)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CapstoneTokenizer::tokenizeInvalidOperand(const cs_x86_op & op)
|
bool CapstoneTokenizer::tokenizeInvalidOperand(const ZydisDecodedOperand & op)
|
||||||
{
|
{
|
||||||
addToken(TokenType::MnemonicUnusual, "???");
|
addToken(TokenType::MnemonicUnusual, "???");
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef _CAPSTONE_GUI_H
|
#ifndef _CAPSTONE_GUI_H
|
||||||
#define _CAPSTONE_GUI_H
|
#define _CAPSTONE_GUI_H
|
||||||
|
|
||||||
#include <capstone_wrapper.h>
|
#include <zydis_wrapper.h>
|
||||||
#include "RichTextPainter.h"
|
#include "RichTextPainter.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -187,11 +187,11 @@ private:
|
||||||
bool tokenizePrefix();
|
bool tokenizePrefix();
|
||||||
bool tokenizeMnemonic();
|
bool tokenizeMnemonic();
|
||||||
bool tokenizeMnemonic(TokenType type, const QString & mnemonic);
|
bool tokenizeMnemonic(TokenType type, const QString & mnemonic);
|
||||||
bool tokenizeOperand(const cs_x86_op & op);
|
bool tokenizeOperand(const ZydisDecodedOperand & op);
|
||||||
bool tokenizeRegOperand(const cs_x86_op & op);
|
bool tokenizeRegOperand(const ZydisDecodedOperand & op);
|
||||||
bool tokenizeImmOperand(const cs_x86_op & op);
|
bool tokenizeImmOperand(const ZydisDecodedOperand & op);
|
||||||
bool tokenizeMemOperand(const cs_x86_op & op);
|
bool tokenizeMemOperand(const ZydisDecodedOperand & op);
|
||||||
bool tokenizeInvalidOperand(const cs_x86_op & op);
|
bool tokenizeInvalidOperand(const ZydisDecodedOperand & op);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_CAPSTONE_GUI_H
|
#endif //_CAPSTONE_GUI_H
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "LocalVarsView.h"
|
#include "LocalVarsView.h"
|
||||||
#include "capstone_wrapper.h"
|
#include "zydis_wrapper.h"
|
||||||
#include "CPUMultiDump.h"
|
#include "CPUMultiDump.h"
|
||||||
#include "MiscUtil.h"
|
#include "MiscUtil.h"
|
||||||
#include "WordEditDialog.h"
|
#include "WordEditDialog.h"
|
||||||
|
@ -210,18 +210,22 @@ void LocalVarsView::updateSlot()
|
||||||
}
|
}
|
||||||
for(int i = 0; i < dis.OpCount(); i++)
|
for(int i = 0; i < dis.OpCount(); i++)
|
||||||
{
|
{
|
||||||
if(dis[i].type != X86_OP_MEM)
|
if(dis[i].type != ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
continue;
|
continue;
|
||||||
if(dis[i].mem.base == X86_REG_INVALID) //mov eax, [10000000], global variable
|
if(dis[i].mem.base == ZYDIS_REGISTER_NONE) //mov eax, [10000000], global variable
|
||||||
continue;
|
continue;
|
||||||
if(dis[i].mem.index != X86_REG_INVALID) //mov eax, dword ptr ds:[ebp+ecx*4-10], indexed array
|
if(dis[i].mem.index != ZYDIS_REGISTER_NONE) //mov eax, dword ptr ds:[ebp+ecx*4-10], indexed array
|
||||||
continue;
|
continue;
|
||||||
const x86_reg registers[] =
|
const ZydisRegister registers[] =
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
X86_REG_RAX, X86_REG_RBX, X86_REG_RCX, X86_REG_RDX, X86_REG_RBP, X86_REG_RSP, X86_REG_RSI, X86_REG_RDI, X86_REG_R8, X86_REG_R9, X86_REG_R10, X86_REG_R11, X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15
|
ZYDIS_REGISTER_RAX, ZYDIS_REGISTER_RBX, ZYDIS_REGISTER_RCX, ZYDIS_REGISTER_RDX,
|
||||||
|
ZYDIS_REGISTER_RBP, ZYDIS_REGISTER_RSP, ZYDIS_REGISTER_RSI, ZYDIS_REGISTER_RDI,
|
||||||
|
ZYDIS_REGISTER_R8, ZYDIS_REGISTER_R9, ZYDIS_REGISTER_R10, ZYDIS_REGISTER_R11,
|
||||||
|
ZYDIS_REGISTER_R12, ZYDIS_REGISTER_R13, ZYDIS_REGISTER_R14, ZYDIS_REGISTER_R15
|
||||||
#else //x86
|
#else //x86
|
||||||
X86_REG_EAX, X86_REG_EBX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBP, X86_REG_ESP, X86_REG_ESI, X86_REG_EDI
|
ZYDIS_REGISTER_EAX, ZYDIS_REGISTER_EBX, ZYDIS_REGISTER_ECX, ZYDIS_REGISTER_EDX,
|
||||||
|
ZYDIS_REGISTER_EBP, ZYDIS_REGISTER_ESP, ZYDIS_REGISTER_ESI, ZYDIS_REGISTER_EDI
|
||||||
#endif //_WIN64
|
#endif //_WIN64
|
||||||
};
|
};
|
||||||
for(char j = 0; j < ArchValue(8, 16); j++)
|
for(char j = 0; j < ArchValue(8, 16); j++)
|
||||||
|
@ -229,7 +233,7 @@ void LocalVarsView::updateSlot()
|
||||||
if(!baseRegisters[j]->isChecked())
|
if(!baseRegisters[j]->isChecked())
|
||||||
continue;
|
continue;
|
||||||
if(dis[i].mem.base == registers[j])
|
if(dis[i].mem.base == registers[j])
|
||||||
usedOffsets[j].insert(dis[i].mem.disp);
|
usedOffsets[j].insert(dis[i].mem.disp.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
address += dis.Size();
|
address += dis.Size();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "capstone_wrapper.h"
|
#include "zydis_wrapper.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
|
|
@ -67,7 +67,8 @@ INCLUDEPATH += \
|
||||||
Src/Utils \
|
Src/Utils \
|
||||||
Src/ThirdPartyLibs/snowman \
|
Src/ThirdPartyLibs/snowman \
|
||||||
Src/ThirdPartyLibs/ldconvert \
|
Src/ThirdPartyLibs/ldconvert \
|
||||||
../capstone_wrapper
|
../capstone_wrapper \
|
||||||
|
../zydis_wrapper
|
||||||
|
|
||||||
# Resources, sources, headers, and forms
|
# Resources, sources, headers, and forms
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
|
@ -347,15 +348,15 @@ LIBS += -luser32 -ladvapi32 -lwinmm -lshell32
|
||||||
|
|
||||||
!contains(QMAKE_HOST.arch, x86_64) {
|
!contains(QMAKE_HOST.arch, x86_64) {
|
||||||
# Windows x86 (32bit) specific build
|
# Windows x86 (32bit) specific build
|
||||||
LIBS += -L"$$PWD/../capstone_wrapper/capstone" -lcapstone_x86
|
LIBS += -L"$$PWD/../zydis_wrapper/Zydis" -lZydis_x86
|
||||||
LIBS += -L"$$PWD/../capstone_wrapper/bin/x32$${DIR_SUFFIX}" -lcapstone_wrapper
|
LIBS += -L"$$PWD/../zydis_wrapper/bin/x32$${DIR_SUFFIX}" -lzydis_wrapper
|
||||||
LIBS += -L"$$PWD/Src/ThirdPartyLibs/snowman" -lsnowman_x86
|
LIBS += -L"$$PWD/Src/ThirdPartyLibs/snowman" -lsnowman_x86
|
||||||
LIBS += -L"$$PWD/Src/ThirdPartyLibs/ldconvert" -lldconvert_x86
|
LIBS += -L"$$PWD/Src/ThirdPartyLibs/ldconvert" -lldconvert_x86
|
||||||
LIBS += -L"$${X64_BIN_DIR}" -lx32bridge
|
LIBS += -L"$${X64_BIN_DIR}" -lx32bridge
|
||||||
} else {
|
} else {
|
||||||
# Windows x64 (64bit) specific build
|
# Windows x64 (64bit) specific build
|
||||||
LIBS += -L"$$PWD/../capstone_wrapper/capstone" -lcapstone_x64
|
LIBS += -L"$$PWD/../zydis_wrapper/Zydis" -lZydis_x64
|
||||||
LIBS += -L"$$PWD/../capstone_wrapper/bin/x64$${DIR_SUFFIX}" -lcapstone_wrapper
|
LIBS += -L"$$PWD/../zydis_wrapper/bin/x64$${DIR_SUFFIX}" -lzydis_wrapper
|
||||||
LIBS += -L"$$PWD/Src/ThirdPartyLibs/snowman" -lsnowman_x64
|
LIBS += -L"$$PWD/Src/ThirdPartyLibs/snowman" -lsnowman_x64
|
||||||
LIBS += -L"$$PWD/Src/ThirdPartyLibs/ldconvert" -lldconvert_x64
|
LIBS += -L"$$PWD/Src/ThirdPartyLibs/ldconvert" -lldconvert_x64
|
||||||
LIBS += -L"$${X64_BIN_DIR}" -lx64bridge
|
LIBS += -L"$${X64_BIN_DIR}" -lx64bridge
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 093fbde4acbe897ecd080ed157b3d4bfb95323f3
|
Loading…
Reference in New Issue