Compare commits
86 Commits
b7347f4506
...
a4be9f87f5
Author | SHA1 | Date |
---|---|---|
|
a4be9f87f5 | |
|
56ee888a0b | |
|
3e1b3d61bc | |
|
ffb6de5b56 | |
|
f6c3e4219a | |
|
c589bb57c8 | |
|
6e1a5000e8 | |
|
bba369d607 | |
|
437573276b | |
|
e3adaaac5d | |
|
5628094e17 | |
|
4ad555a509 | |
|
8820440f06 | |
|
51e697b726 | |
|
56c3249e75 | |
|
13bd1f3164 | |
|
335d94d2d9 | |
|
b74f6b5d5d | |
|
68112f51da | |
|
e2b658f0a3 | |
|
ce73e9cdf7 | |
|
ef925bcfa7 | |
|
df8bdfe1fb | |
|
7fcb626ba2 | |
|
517c82604f | |
|
c28653700a | |
|
0f5bc725f8 | |
|
c65c956f85 | |
|
3beec936ec | |
|
7f2566b6ed | |
|
7c00347a24 | |
|
fdc97fe6d1 | |
|
a349f9c05f | |
|
bdb38d6a97 | |
|
e2d1d79930 | |
|
7733012330 | |
|
663bfbbb06 | |
|
5797dae1c3 | |
|
812c91d361 | |
|
6fba4478fb | |
|
952c16aad7 | |
|
b22266b822 | |
|
3d56c4fd35 | |
|
7e9a89847e | |
|
6228bfe2bf | |
|
9fa8c8cea0 | |
|
11d96f1878 | |
|
dd91e4376a | |
|
2ce5a283f5 | |
|
02c762ff4a | |
|
cdee7fed64 | |
|
b6be841a48 | |
|
bc3d7574bc | |
|
7405acd42d | |
|
3616f2d33a | |
|
b28e317073 | |
|
323d318329 | |
|
d08773d3c7 | |
|
5659f7db2c | |
|
d68e1d44a8 | |
|
b3dc97c4a5 | |
|
48d81226ed | |
|
f557751365 | |
|
4a767ea507 | |
|
8c6f3089e9 | |
|
4e5c2bd9c4 | |
|
7d00017e69 | |
|
145053d8ae | |
|
e6b43cdc6c | |
|
4301af38a9 | |
|
78f37958eb | |
|
9f046b96e2 | |
|
414c9cb23e | |
|
a85f177567 | |
|
b477ffc490 | |
|
7bf53e72f1 | |
|
6b05405714 | |
|
f475f7d841 | |
|
479fdaf38d | |
|
b8c2aad3b3 | |
|
59b5d923cd | |
|
3151aa6280 | |
|
6a970e657d | |
|
791d6ba59c | |
|
d5901879a7 | |
|
6cd26dd3dd |
|
@ -1,13 +1,7 @@
|
|||
[submodule "src/gui/Translations"]
|
||||
path = src/gui/Translations
|
||||
url = ../Translations.git
|
||||
[submodule "src/dbg/btparser"]
|
||||
path = src/dbg/btparser
|
||||
url = ../btparser
|
||||
[submodule "deps"]
|
||||
path = deps
|
||||
url = ../deps
|
||||
shallow = true
|
||||
[submodule "src/zydis_wrapper/zydis"]
|
||||
path = src/zydis_wrapper/zydis
|
||||
url = ../zydis.git
|
||||
shallow = true
|
|
@ -21,7 +21,7 @@ An open-source binary debugger for Windows, aimed at malware analysis and revers
|
|||
|
||||
1. Download a snapshot from [GitHub](https://github.com/x64dbg/x64dbg/releases), [SourceForge](https://sourceforge.net/projects/x64dbg/files/snapshots) or [OSDN](https://osdn.net/projects/x64dbg) and extract it in a location your user has write access to.
|
||||
2. _Optionally_ use `x96dbg.exe` to register a shell extension and add shortcuts to your desktop.
|
||||
3. You can now run `x32\x32dbg.exe` if you want to debug a 32-bit executable or `x64\x64dbg.exe` to debug a 64-bit executable! If you are unsure you can always run `x96dbg.exe` and chose your architecture there.
|
||||
3. You can now run `x32\x32dbg.exe` if you want to debug a 32-bit executable or `x64\x64dbg.exe` to debug a 64-bit executable! If you are unsure you can always run `x96dbg.exe` and choose your architecture there.
|
||||
|
||||
You can also [compile](https://github.com/x64dbg/x64dbg/wiki/Compiling-the-whole-project) x64dbg yourself with a few easy steps!
|
||||
|
||||
|
@ -92,4 +92,4 @@ You can find an exhaustive list of GitHub contributors [here](https://github.com
|
|||
- [mrfearless](https://twitter.com/fearless0)
|
||||
- [JustMagic](https://github.com/JustasMasiulis)
|
||||
|
||||
Without the help of many people and other open-source projects, it would not have been possible to make x64dbg what is it today, thank you!
|
||||
Without the help of many people and other open-source projects, it would not have been possible to make x64dbg what it is today, thank you!
|
||||
|
|
|
@ -196,9 +196,9 @@ QMenuBar::item:disabled:selected {
|
|||
}
|
||||
|
||||
QMenu {
|
||||
border: 1px solid #212121;
|
||||
border: 1px solid #808080;
|
||||
color: #e0e0e0;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
QMenu::icon {
|
||||
|
@ -281,7 +281,7 @@ QMenu::right-arrow {
|
|||
}
|
||||
|
||||
QWidget:disabled {
|
||||
color: #454545;
|
||||
color: #646464;
|
||||
background-color: #212121;
|
||||
}
|
||||
|
||||
|
@ -313,6 +313,11 @@ QLineEdit {
|
|||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
/* e.g. "System breakpoint scripts" dialog */
|
||||
QLineEdit:disabled {
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
QAbstractItemView QLineEdit {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -501,7 +506,7 @@ QMainWindow::separator:hover {
|
|||
|
||||
QMenu::separator {
|
||||
height: 1px;
|
||||
background-color: #2a2b2f;
|
||||
background-color: #808080;
|
||||
color: white;
|
||||
padding-left: 4px;
|
||||
margin-left: 10px;
|
||||
|
@ -550,7 +555,7 @@ QPushButton {
|
|||
color: #e0e0e0;
|
||||
background-color: #212121;
|
||||
border-width: 1px;
|
||||
border-color: #2a2b2f;
|
||||
border-color: #808080;
|
||||
border-style: solid;
|
||||
padding: 5px;
|
||||
border-radius: 2px;
|
||||
|
@ -567,7 +572,7 @@ QPushButton:disabled {
|
|||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 2px;
|
||||
color: #454545;
|
||||
color: #646464;
|
||||
}
|
||||
|
||||
QPushButton:focus {
|
||||
|
@ -581,11 +586,11 @@ QPushButton:pressed {
|
|||
padding-bottom: -17px;
|
||||
}
|
||||
|
||||
QComboBox {
|
||||
QComboBox, QFontComboBox {
|
||||
selection-background-color: #89a2f6;
|
||||
selection-color: #000000;
|
||||
border-style: solid;
|
||||
border: 1px solid #212121;
|
||||
border: 1px solid #424242;
|
||||
border-radius: 2px;
|
||||
padding: 5px;
|
||||
min-width: 75px;
|
||||
|
@ -596,15 +601,19 @@ QPushButton:checked {
|
|||
border-color: #2a2b2f;
|
||||
}
|
||||
|
||||
QPushButton:hover {
|
||||
border: 1px solid #e0e0e0;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
QComboBox:hover,
|
||||
QPushButton:hover,
|
||||
QAbstractSpinBox:hover,
|
||||
QLineEdit:hover,
|
||||
QTextEdit:hover,
|
||||
QPlainTextEdit:hover,
|
||||
QAbstractView:hover,
|
||||
QTreeView:hover {
|
||||
border: 1px solid #414141;
|
||||
border: 1px solid #646464;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
|
@ -619,6 +628,7 @@ QComboBox QAbstractItemView {
|
|||
border-radius: 2px;
|
||||
border: 1px solid #212121;
|
||||
selection-background-color: #414141;
|
||||
selection-color: #ffffff; /* e.g. calling convention ComboBox */
|
||||
}
|
||||
|
||||
QComboBox::drop-down {
|
||||
|
@ -1096,4 +1106,13 @@ QTabWidget::pane {
|
|||
QTabBar::tear {
|
||||
width: 0px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* e.g. "Exception filters" list, "Patch file" modules list, "Set page memory rights" table, "Select font" list, etc */
|
||||
QTableView, QListView {
|
||||
selection-color: #c8c8c8;
|
||||
}
|
||||
|
||||
DisassemblyPopup {
|
||||
border: 1px solid #c0c0c0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[Colors]
|
||||
AbstractTableViewBackgroundColor=#212121
|
||||
AbstractTableViewHeaderTextColor=#E0E0E0
|
||||
AbstractTableViewHeaderBackgroundColor=#414141
|
||||
AbstractTableViewSelectionColor=#414141
|
||||
AbstractTableViewSeparatorColor=#717171
|
||||
AbstractTableViewTextColor=#E0E0E0
|
||||
|
@ -51,7 +52,7 @@ DisassemblyCommentColor=#E0E0E0
|
|||
DisassemblyConditionalJumpLineFalseColor=#808080
|
||||
DisassemblyConditionalJumpLineTrueColor=#AA0000
|
||||
DisassemblyFunctionColor=#F88478
|
||||
DisassemblyHardwareBreakpointBackgroundColor=#XXXXXX
|
||||
DisassemblyHardwareBreakpointBackgroundColor=#000000
|
||||
DisassemblyHardwareBreakpointColor=#E6E976
|
||||
DisassemblyLabelBackgroundColor=#XXXXXX
|
||||
DisassemblyLabelColor=#B794F6
|
||||
|
@ -105,10 +106,10 @@ HexDumpUnknownCodePointerHighlightColor=#0000FF
|
|||
HexDumpUnknownDataPointerHighlightColor=#89A2F6
|
||||
HexDumpUserModuleCodePointerHighlightColor=#00FF00
|
||||
HexDumpUserModuleDataPointerHighlightColor=#008000
|
||||
HexEditBackgroundColor=#212121
|
||||
HexEditSelectionColor=#414141
|
||||
HexEditBackgroundColor=#313131
|
||||
HexEditSelectionColor=#515151
|
||||
HexEditTextColor=#E0E0E0
|
||||
HexEditWildcardColor=#C60000
|
||||
HexEditWildcardColor=#FF0000
|
||||
InstructionAddressBackgroundColor=#XXXXXX
|
||||
InstructionAddressColor=#F88478
|
||||
InstructionCallBackgroundColor=#XXXXXX
|
||||
|
|
|
@ -2015,11 +2015,6 @@ BRIDGE_IMPEXP DWORD GuiGetMainThreadId()
|
|||
return (DWORD)(duint)_gui_sendmessage(GUI_GET_MAIN_THREAD_ID, nullptr, nullptr);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP bool GuiIsDebuggerFocused()
|
||||
{
|
||||
return !!(duint)_gui_sendmessage(GUI_IS_DEBUGGER_FOCUSED, nullptr, nullptr);
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
hInst = hinstDLL;
|
||||
|
|
|
@ -176,7 +176,10 @@ extern "C"
|
|||
#define MAX_SECTION_SIZE 10
|
||||
#define MAX_COMMAND_LINE_SIZE 256
|
||||
#define MAX_MNEMONIC_SIZE 64
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 0x1000
|
||||
#endif // PAGE_SIZE
|
||||
|
||||
//Debugger enums
|
||||
typedef enum
|
||||
|
@ -1126,7 +1129,6 @@ BRIDGE_IMPEXP void DbgGetSymbolInfo(const SYMBOLPTR* symbolptr, SYMBOLINFO* info
|
|||
BRIDGE_IMPEXP DEBUG_ENGINE DbgGetDebugEngine();
|
||||
BRIDGE_IMPEXP bool DbgGetSymbolInfoAt(duint addr, SYMBOLINFO* info);
|
||||
BRIDGE_IMPEXP duint DbgXrefAddMulti(const XREF_EDGE* edges, duint count);
|
||||
BRIDGE_IMPEXP bool GuiIsDebuggerFocused();
|
||||
|
||||
//Gui defines
|
||||
typedef enum
|
||||
|
@ -1275,7 +1277,7 @@ typedef enum
|
|||
GUI_GET_MAIN_THREAD_ID, // param1=unused, param2=unused
|
||||
GUI_ADD_MSG_TO_LOG_HTML, // param1=(const char*)msg, param2=unused
|
||||
GUI_IS_LOG_ENABLED, // param1=unused, param2=unused
|
||||
GUI_IS_DEBUGGER_FOCUSED, // param1=unused, param2=unused
|
||||
GUI_IS_DEBUGGER_FOCUSED_UNUSED, // This message is removed, could be used for future purposes
|
||||
GUI_SAVE_LOG, // param1=const char* file name,param2=unused
|
||||
GUI_REDIRECT_LOG, // param1=const char* file name,param2=unused
|
||||
GUI_STOP_REDIRECT_LOG, // param1=unused, param2=unused
|
||||
|
|
|
@ -73,7 +73,7 @@ bool TraceRecordManager::setTraceRecordType(duint pageAddress, TraceRecordType t
|
|||
newPage.moduleIndex = ~0;
|
||||
}
|
||||
|
||||
auto inserted = TraceRecord.insert(std::make_pair(ModHashFromAddr(pageAddress), newPage));
|
||||
auto inserted = TraceRecord.emplace(ModHashFromAddr(pageAddress), newPage);
|
||||
if(inserted.second == false) // we failed to insert new page into the map
|
||||
{
|
||||
efree(newPage.rawPtr);
|
||||
|
@ -205,14 +205,14 @@ void TraceRecordManager::TraceExecute(duint address, duint size)
|
|||
//See https://www.felixcloutier.com/x86/FXSAVE.html, max 512 bytes
|
||||
#define memoryContentSize 512
|
||||
|
||||
static void HandleZydisOperand(const Zydis & cp, int opindex, DISASM_ARGTYPE* argType, duint* value, unsigned char memoryContent[memoryContentSize], unsigned char* memorySize)
|
||||
static void HandleZydisOperand(const Zydis & zydis, int opindex, DISASM_ARGTYPE* argType, duint* value, unsigned char memoryContent[memoryContentSize], unsigned char* memorySize)
|
||||
{
|
||||
*value = cp.ResolveOpValue(opindex, [&cp](ZydisRegister reg)
|
||||
*value = (duint)zydis.ResolveOpValue(opindex, [&zydis](ZydisRegister reg) -> uint64_t
|
||||
{
|
||||
auto regName = cp.RegName(reg);
|
||||
auto regName = zydis.RegName(reg);
|
||||
return regName ? getregister(nullptr, regName) : 0; //TODO: temporary needs enums + caching
|
||||
});
|
||||
const auto & op = cp[opindex];
|
||||
const auto & op = zydis[opindex];
|
||||
switch(op.type)
|
||||
{
|
||||
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||
|
@ -269,7 +269,7 @@ void TraceRecordManager::TraceExecuteRecord(const Zydis & newInstruction)
|
|||
if(newInstruction.Success() && !newInstruction.IsNop() && newInstruction.GetId() != ZYDIS_MNEMONIC_LEA)
|
||||
{
|
||||
// This can happen when trace execute instruction is used, we need to fix that or something would go wrong with the GUI.
|
||||
newContext.registers.regcontext.cip = newInstruction.Address();
|
||||
newContext.registers.regcontext.cip = (duint)newInstruction.Address();
|
||||
DISASM_ARGTYPE argType;
|
||||
duint value;
|
||||
unsigned char memoryContent[memoryContentSize];
|
||||
|
@ -553,13 +553,13 @@ bool TraceRecordManager::enableTraceRecording(bool enabled, const char* fileName
|
|||
for(size_t i = 0; i < _countof(rtOldContextChanged); i++)
|
||||
rtOldContextChanged[i] = true;
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Started trace recording to file: %s\r\n"), fileName);
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
unsigned char instr[MAX_DISASM_BUFFER];
|
||||
auto cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(MemRead(cip, instr, MAX_DISASM_BUFFER))
|
||||
{
|
||||
cp.DisassembleSafe(cip, instr, MAX_DISASM_BUFFER);
|
||||
TraceExecuteRecord(cp);
|
||||
zydis.DisassembleSafe(cip, instr, MAX_DISASM_BUFFER);
|
||||
TraceExecuteRecord(zydis);
|
||||
}
|
||||
GuiOpenTraceFile(fileName);
|
||||
return true;
|
||||
|
@ -683,7 +683,7 @@ void TraceRecordManager::loadFromDb(JSON root)
|
|||
currentPage.moduleIndex = ~0;
|
||||
key = currentPage.rva;
|
||||
}
|
||||
TraceRecord.insert(std::make_pair(key, currentPage));
|
||||
TraceRecord.emplace(key, currentPage);
|
||||
}
|
||||
else
|
||||
efree(currentPage.rawPtr, "TraceRecordManager");
|
||||
|
|
|
@ -67,7 +67,10 @@ downslib_error downslib_download(const char* url,
|
|||
0);
|
||||
|
||||
if(!hInternet)
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
return downslib_error::inetopen;
|
||||
}
|
||||
|
||||
// Set a time-out value in milliseconds
|
||||
InternetSetOptionA(hInternet,
|
||||
|
|
|
@ -102,8 +102,8 @@ extern "C" DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr)
|
|||
unsigned char data[16];
|
||||
if(MemRead(addr, data, sizeof(data), nullptr, true))
|
||||
{
|
||||
Zydis cp;
|
||||
if(cp.Disassemble(addr, data))
|
||||
Zydis zydis;
|
||||
if(zydis.Disassemble(addr, data))
|
||||
{
|
||||
CONTEXT ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
|
@ -116,7 +116,7 @@ extern "C" DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr)
|
|||
auto cflags = ctx.EFlags;
|
||||
auto ccx = ctx.Ecx;
|
||||
#endif //_WIN64
|
||||
return cp.IsBranchGoingToExecute(cflags, ccx);
|
||||
return zydis.IsBranchGoingToExecute(cflags, ccx);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -329,11 +329,11 @@ static bool getAutoComment(duint addr, String & comment)
|
|||
BRIDGE_ADDRINFO newinfo;
|
||||
char string_text[MAX_STRING_SIZE] = "";
|
||||
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
auto getregs = !bOnlyCipAutoComments || addr == lastContext.cip;
|
||||
disasmget(cp, addr, &instr, getregs);
|
||||
disasmget(zydis, addr, &instr, getregs);
|
||||
// Some nop variants have 'operands' that should be ignored
|
||||
if(cp.Success() && !cp.IsNop())
|
||||
if(zydis.Success() && !zydis.IsNop())
|
||||
{
|
||||
//Ignore register values when not on CIP and OnlyCipAutoComments is enabled: https://github.com/x64dbg/x64dbg/issues/1383
|
||||
if(!getregs)
|
||||
|
@ -342,7 +342,7 @@ static bool getAutoComment(duint addr, String & comment)
|
|||
instr.arg[i].value = instr.arg[i].constant;
|
||||
}
|
||||
|
||||
if(addr == lastContext.cip && (cp.GetId() == ZYDIS_MNEMONIC_SYSCALL || (cp.GetId() == ZYDIS_MNEMONIC_INT && cp[0].imm.value.u == 0x2e)))
|
||||
if(addr == lastContext.cip && (zydis.GetId() == ZYDIS_MNEMONIC_SYSCALL || (zydis.GetId() == ZYDIS_MNEMONIC_INT && zydis[0].imm.value.u == 0x2e)))
|
||||
{
|
||||
auto syscallName = SyscallToName((unsigned int)lastContext.cax);
|
||||
if(!syscallName.empty())
|
||||
|
@ -367,9 +367,9 @@ static bool getAutoComment(duint addr, String & comment)
|
|||
if(instr.arg[i].constant == instr.arg[i].value) //avoid: call <module.label> ; addr:label
|
||||
{
|
||||
auto constant = instr.arg[i].constant;
|
||||
if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.IsCall())
|
||||
if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && zydis.IsCall())
|
||||
temp_string.assign("call $0");
|
||||
else if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.IsJump())
|
||||
else if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && zydis.IsJump())
|
||||
temp_string.assign("jmp $0");
|
||||
else if(instr.type == instr_branch)
|
||||
continue;
|
||||
|
@ -881,12 +881,12 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
|
|||
unsigned char data[MAX_DISASM_BUFFER];
|
||||
if(!MemIsValidReadPtr(addr, true) || !MemRead(addr, data, sizeof(data)))
|
||||
return 0;
|
||||
Zydis cp;
|
||||
if(!cp.Disassemble(addr, data))
|
||||
Zydis zydis;
|
||||
if(!zydis.Disassemble(addr, data))
|
||||
return 0;
|
||||
if(cp.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTLoop | Zydis::BTXbegin))
|
||||
if(zydis.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTLoop | Zydis::BTXbegin))
|
||||
{
|
||||
auto opValue = cp.ResolveOpValue(0, [](ZydisRegister reg) -> size_t
|
||||
auto opValue = (duint)zydis.ResolveOpValue(0, [](ZydisRegister reg) -> uint64_t
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
|
@ -949,10 +949,10 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
|
|||
return 0;
|
||||
}
|
||||
});
|
||||
if(cp.OpCount() && cp[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
if(zydis.OpCount() && zydis[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
{
|
||||
auto const tebseg = ArchValue(ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS);
|
||||
if(cp[0].mem.segment == tebseg)
|
||||
if(zydis[0].mem.segment == tebseg)
|
||||
opValue += duint(GetTEBLocation(hActiveThread));
|
||||
if(MemRead(opValue, &opValue, sizeof(opValue)))
|
||||
return opValue;
|
||||
|
@ -960,7 +960,7 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
|
|||
else
|
||||
return opValue;
|
||||
}
|
||||
if(cp.IsRet())
|
||||
if(zydis.IsRet())
|
||||
{
|
||||
auto csp = lastContext.csp;
|
||||
duint dest = 0;
|
||||
|
|
|
@ -31,9 +31,9 @@ bool CodeFollowPass::Analyse()
|
|||
return false;
|
||||
}
|
||||
|
||||
duint CodeFollowPass::GetReferenceOperand(const ZydisDecodedInstruction & Context)
|
||||
duint CodeFollowPass::GetReferenceOperand(const ZydisDisassembledInstruction & Context)
|
||||
{
|
||||
for(int i = 0; i < Context.operandCount; i++)
|
||||
for(int i = 0; i < Context.info.operand_count; i++)
|
||||
{
|
||||
auto operand = Context.operands[i];
|
||||
|
||||
|
@ -50,9 +50,9 @@ duint CodeFollowPass::GetReferenceOperand(const ZydisDecodedInstruction & Contex
|
|||
return 0;
|
||||
}
|
||||
|
||||
duint CodeFollowPass::GetMemoryOperand(Zydis & Disasm, const ZydisDecodedInstruction & Context, bool* Indirect)
|
||||
duint CodeFollowPass::GetMemoryOperand(Zydis & Disasm, const ZydisDisassembledInstruction & Context, bool* Indirect)
|
||||
{
|
||||
if(Context.operandCount <= 0)
|
||||
if(Context.info.operand_count <= 0)
|
||||
return 0;
|
||||
|
||||
// Only the first operand matters
|
||||
|
|
|
@ -14,6 +14,6 @@ public:
|
|||
virtual bool Analyse() override;
|
||||
|
||||
private:
|
||||
duint GetReferenceOperand(const ZydisDecodedInstruction & Context);
|
||||
duint GetMemoryOperand(Zydis & Disasm, const ZydisDecodedInstruction & Context, bool* Indirect);
|
||||
duint GetReferenceOperand(const ZydisDisassembledInstruction & Context);
|
||||
duint GetMemoryOperand(Zydis & Disasm, const ZydisDisassembledInstruction & Context, bool* Indirect);
|
||||
};
|
|
@ -79,6 +79,7 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
CFGraph graph(entryPoint);
|
||||
UintSet visited;
|
||||
std::queue<duint> queue;
|
||||
visited.reserve(queue.size());
|
||||
mEntryPoints.insert(entryPoint);
|
||||
queue.push(graph.entryPoint);
|
||||
while(!queue.empty())
|
||||
|
@ -93,7 +94,7 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
while(true)
|
||||
{
|
||||
node.icount++;
|
||||
if(!mCp.Disassemble(node.end, translateAddr(node.end)))
|
||||
if(!mZydis.Disassemble(node.end, translateAddr(node.end)))
|
||||
{
|
||||
if(writedata)
|
||||
mEncMap[node.end - mBase] = (byte)enc_byte;
|
||||
|
@ -108,7 +109,7 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
}
|
||||
// If the memory range doesn't fit the entire instruction
|
||||
// mark it as bytes and finish this node
|
||||
if(!inRange(node.end + mCp.Size() - 1))
|
||||
if(!inRange(node.end + mZydis.Size() - 1))
|
||||
{
|
||||
duint remainingSize = mBase + mSize - node.end;
|
||||
memset(&mEncMap[node.end - mBase], (byte)enc_byte, remainingSize);
|
||||
|
@ -118,15 +119,15 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
if(writedata)
|
||||
{
|
||||
mEncMap[node.end - mBase] = (byte)enc_code;
|
||||
for(int i = 1; i < mCp.Size(); i++)
|
||||
for(size_t i = 1; i < mZydis.Size(); i++)
|
||||
mEncMap[node.end - mBase + i] = (byte)enc_middle;
|
||||
}
|
||||
if(mCp.IsJump() || mCp.IsLoop()) //jump
|
||||
if(mZydis.IsJump() || mZydis.IsLoop()) //jump
|
||||
{
|
||||
//set the branch destinations
|
||||
node.brtrue = mCp.BranchDestination();
|
||||
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||
node.brfalse = node.end + mCp.Size();
|
||||
node.brtrue = (duint)mZydis.BranchDestination();
|
||||
if(mZydis.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||
node.brfalse = node.end + mZydis.Size();
|
||||
|
||||
//add node to the function graph
|
||||
graph.AddNode(node);
|
||||
|
@ -139,26 +140,26 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
|
||||
break;
|
||||
}
|
||||
if(mCp.IsCall()) //call
|
||||
if(mZydis.IsCall()) //call
|
||||
{
|
||||
//TODO: handle no return
|
||||
duint target = mCp.BranchDestination();
|
||||
auto target = (duint)mZydis.BranchDestination();
|
||||
if(inRange(target) && mEntryPoints.find(target) == mEntryPoints.end())
|
||||
mCandidateEPs.insert(target);
|
||||
}
|
||||
if(mCp.IsRet()) //return
|
||||
if(mZydis.IsRet()) //return
|
||||
{
|
||||
node.terminal = true;
|
||||
graph.AddNode(node);
|
||||
break;
|
||||
}
|
||||
// If this instruction finishes the memory range, end the loop for this entry point
|
||||
if(!inRange(node.end + mCp.Size()))
|
||||
if(!inRange(node.end + mZydis.Size()))
|
||||
{
|
||||
graph.AddNode(node);
|
||||
break;
|
||||
}
|
||||
node.end += mCp.Size();
|
||||
node.end += mZydis.Size();
|
||||
}
|
||||
}
|
||||
mFunctions.push_back(graph);
|
||||
|
@ -172,20 +173,20 @@ void AdvancedAnalysis::linearXrefPass()
|
|||
|
||||
for(auto addr = mBase; addr < mBase + mSize;)
|
||||
{
|
||||
if(!mCp.Disassemble(addr, translateAddr(addr)))
|
||||
if(!mZydis.Disassemble(addr, translateAddr(addr)))
|
||||
{
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
addr += mCp.Size();
|
||||
addr += mZydis.Size();
|
||||
|
||||
XREF xref;
|
||||
xref.valid = true;
|
||||
xref.addr = 0;
|
||||
xref.from = mCp.Address();
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
xref.from = (duint)mZydis.Address();
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
duint dest = mCp.ResolveOpValue(i, [](ZydisRegister)->size_t
|
||||
auto dest = (duint)mZydis.ResolveOpValue(i, [](ZydisRegister) -> uint64_t
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
|
@ -197,9 +198,9 @@ void AdvancedAnalysis::linearXrefPass()
|
|||
}
|
||||
if(xref.addr)
|
||||
{
|
||||
if(mCp.IsCall())
|
||||
if(mZydis.IsCall())
|
||||
xref.type = XREF_CALL;
|
||||
else if(mCp.IsJump())
|
||||
else if(mZydis.IsJump())
|
||||
xref.type = XREF_JMP;
|
||||
else
|
||||
xref.type = XREF_DATA;
|
||||
|
@ -269,16 +270,16 @@ void AdvancedAnalysis::writeDataXrefs()
|
|||
{
|
||||
if(xref.type == XREF_DATA && xref.valid)
|
||||
{
|
||||
if(!mCp.Disassemble(xref.from, translateAddr(xref.from)))
|
||||
if(!mZydis.Disassemble(xref.from, translateAddr(xref.from)))
|
||||
{
|
||||
xref.valid = false;
|
||||
continue;
|
||||
}
|
||||
auto opcode = mCp.GetId();
|
||||
auto opcode = mZydis.GetId();
|
||||
bool isfloat = isFloatInstruction(opcode);
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
auto & op = mCp[i];
|
||||
auto & op = mZydis[i];
|
||||
ENCODETYPE type = enc_unknown;
|
||||
|
||||
//Todo: Analyze op type and set correct type
|
||||
|
@ -344,6 +345,7 @@ void AdvancedAnalysis::writeDataXrefs()
|
|||
|
||||
void AdvancedAnalysis::findFuzzyEntryPoints()
|
||||
{
|
||||
mCandidateEPs.reserve(mFuzzyEPs.size());
|
||||
for(const auto & entryPoint : mFuzzyEPs)
|
||||
{
|
||||
mCandidateEPs.insert(entryPoint);
|
||||
|
@ -392,6 +394,7 @@ void AdvancedAnalysis::analyzeCandidateFunctions(bool writedata)
|
|||
pendingEPs.clear();
|
||||
if(mCandidateEPs.size() == 0)
|
||||
return;
|
||||
pendingEPs.reserve(mCandidateEPs.size());
|
||||
for(const auto & entryPoint : mCandidateEPs)
|
||||
{
|
||||
pendingEPs.insert(entryPoint);
|
||||
|
|
|
@ -17,7 +17,7 @@ protected:
|
|||
duint mBase;
|
||||
duint mSize;
|
||||
unsigned char* mData;
|
||||
Zydis mCp;
|
||||
Zydis mZydis;
|
||||
|
||||
bool inRange(duint addr) const
|
||||
{
|
||||
|
|
|
@ -140,26 +140,26 @@ void ControlFlowAnalysis::BasicBlockStarts()
|
|||
for(duint i = 0; i < mSize;)
|
||||
{
|
||||
auto addr = mBase + i;
|
||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(bSkipFilling) //handle filling skip mode
|
||||
{
|
||||
if(!mCp.IsFilling()) //do nothing until the filling stopped
|
||||
if(!mZydis.IsFilling()) //do nothing until the filling stopped
|
||||
{
|
||||
bSkipFilling = false;
|
||||
mBlockStarts.insert(addr);
|
||||
}
|
||||
}
|
||||
else if(mCp.IsRet()) //RET breaks control flow
|
||||
else if(mZydis.IsRet()) //RET breaks control flow
|
||||
{
|
||||
bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
|
||||
}
|
||||
else if(mCp.IsJump() || mCp.IsLoop()) //branches
|
||||
else if(mZydis.IsJump() || mZydis.IsLoop()) //branches
|
||||
{
|
||||
auto dest1 = getReferenceOperand();
|
||||
duint dest2 = 0;
|
||||
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //conditional jump
|
||||
dest2 = addr + mCp.Size();
|
||||
if(mZydis.GetId() != ZYDIS_MNEMONIC_JMP) //conditional jump
|
||||
dest2 = addr + mZydis.Size();
|
||||
|
||||
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
|
||||
bSkipFilling = true;
|
||||
|
@ -168,7 +168,7 @@ void ControlFlowAnalysis::BasicBlockStarts()
|
|||
if(dest2)
|
||||
mBlockStarts.insert(dest2);
|
||||
}
|
||||
else if(mCp.IsCall())
|
||||
else if(mZydis.IsCall())
|
||||
{
|
||||
auto dest1 = getReferenceOperand();
|
||||
if(dest1)
|
||||
|
@ -183,7 +183,7 @@ void ControlFlowAnalysis::BasicBlockStarts()
|
|||
if(dest1)
|
||||
mBlockStarts.insert(dest1);
|
||||
}
|
||||
i += mCp.Size();
|
||||
i += mZydis.Size();
|
||||
}
|
||||
else
|
||||
i++;
|
||||
|
@ -204,23 +204,23 @@ void ControlFlowAnalysis::BasicBlocks()
|
|||
for(duint addr = start, prevaddr; addr < mBase + mSize;)
|
||||
{
|
||||
prevaddr = addr;
|
||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(mCp.IsRet())
|
||||
if(mZydis.IsRet())
|
||||
{
|
||||
insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
|
||||
break;
|
||||
}
|
||||
else if(mCp.IsJump() || mCp.IsLoop())
|
||||
else if(mZydis.IsJump() || mZydis.IsLoop())
|
||||
{
|
||||
auto dest1 = getReferenceOperand();
|
||||
auto dest2 = mCp.GetId() != ZYDIS_MNEMONIC_JMP ? addr + mCp.Size() : 0;
|
||||
auto dest2 = mZydis.GetId() != ZYDIS_MNEMONIC_JMP ? addr + mZydis.Size() : 0;
|
||||
insertBlock(BasicBlock(start, addr, dest1, dest2));
|
||||
insertParent(dest1, start);
|
||||
insertParent(dest2, start);
|
||||
break;
|
||||
}
|
||||
addr += mCp.Size();
|
||||
addr += mZydis.Size();
|
||||
}
|
||||
else
|
||||
addr++;
|
||||
|
@ -275,7 +275,7 @@ void ControlFlowAnalysis::Functions()
|
|||
{
|
||||
auto function = findFunctionStart(block, parents);
|
||||
if(!function) //this happens with loops / unreferenced blocks sometimes
|
||||
delayedBlocks.push_back(DelayedBlock(block, parents));
|
||||
delayedBlocks.emplace_back(block, parents);
|
||||
else
|
||||
block->function = function;
|
||||
}
|
||||
|
@ -413,9 +413,9 @@ String ControlFlowAnalysis::blockToString(const BasicBlock* block)
|
|||
|
||||
duint ControlFlowAnalysis::getReferenceOperand() const
|
||||
{
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
const auto & op = mCp[i];
|
||||
const auto & op = mZydis[i];
|
||||
if(op.type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
{
|
||||
auto dest = duint(op.imm.value.u);
|
||||
|
@ -426,7 +426,7 @@ duint ControlFlowAnalysis::getReferenceOperand() const
|
|||
{
|
||||
auto dest = duint(op.mem.disp.value);
|
||||
if(op.mem.base == ZYDIS_REGISTER_RIP) //rip-relative
|
||||
dest += mCp.Address() + mCp.Size();
|
||||
dest += (duint)mZydis.Address() + mZydis.Size();
|
||||
if(inRange(dest))
|
||||
return dest;
|
||||
}
|
||||
|
|
|
@ -45,12 +45,12 @@ void LinearAnalysis::populateReferences()
|
|||
for(duint i = 0; i < mSize;)
|
||||
{
|
||||
auto addr = mBase + i;
|
||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
auto ref = getReferenceOperand();
|
||||
if(ref)
|
||||
mFunctions.push_back({ ref, 0 });
|
||||
i += mCp.Size();
|
||||
i += mZydis.Size();
|
||||
}
|
||||
else
|
||||
i++;
|
||||
|
@ -72,8 +72,8 @@ void LinearAnalysis::analyseFunctions()
|
|||
auto end = findFunctionEnd(function.start, maxaddr);
|
||||
if(end)
|
||||
{
|
||||
if(mCp.Disassemble(end, translateAddr(end), MAX_DISASM_BUFFER))
|
||||
function.end = end + mCp.Size() - 1;
|
||||
if(mZydis.Disassemble(end, translateAddr(end), MAX_DISASM_BUFFER))
|
||||
function.end = end + mZydis.Size() - 1;
|
||||
else
|
||||
function.end = end;
|
||||
}
|
||||
|
@ -83,10 +83,10 @@ void LinearAnalysis::analyseFunctions()
|
|||
duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
||||
{
|
||||
//disassemble first instruction for some heuristics
|
||||
if(mCp.Disassemble(start, translateAddr(start), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(start, translateAddr(start), MAX_DISASM_BUFFER))
|
||||
{
|
||||
//JMP [123456] ; import
|
||||
if(mCp.IsJump() && mCp.OpCount() && mCp[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
if(mZydis.IsJump() && mZydis.OpCount() && mZydis[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -95,14 +95,14 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
|||
duint jumpback = 0;
|
||||
for(duint addr = start, fardest = 0; addr < maxaddr;)
|
||||
{
|
||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(addr + mCp.Size() > maxaddr) //we went past the maximum allowed address
|
||||
if(addr + mZydis.Size() > maxaddr) //we went past the maximum allowed address
|
||||
break;
|
||||
|
||||
if((mCp.IsJump() || mCp.IsLoop()) && mCp.OpCount() && mCp[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //jump
|
||||
if((mZydis.IsJump() || mZydis.IsLoop()) && mZydis.OpCount() && mZydis[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //jump
|
||||
{
|
||||
auto dest = duint(mCp[0].imm.value.u);
|
||||
auto dest = duint(mZydis[0].imm.value.u);
|
||||
|
||||
if(dest >= maxaddr) //jump across function boundaries
|
||||
{
|
||||
|
@ -112,19 +112,19 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
|||
{
|
||||
fardest = dest;
|
||||
}
|
||||
else if(end && dest < end && (mCp.GetId() == ZYDIS_MNEMONIC_JMP || mCp.GetId() == ZYDIS_MNEMONIC_LOOP)) //save the last JMP backwards
|
||||
else if(end && dest < end && (mZydis.GetId() == ZYDIS_MNEMONIC_JMP || mZydis.GetId() == ZYDIS_MNEMONIC_LOOP)) //save the last JMP backwards
|
||||
{
|
||||
jumpback = addr;
|
||||
}
|
||||
}
|
||||
else if(mCp.IsRet()) //possible function end?
|
||||
else if(mZydis.IsRet()) //possible function end?
|
||||
{
|
||||
end = addr;
|
||||
if(fardest < addr) //we stop if the farthest JXX destination forward is before this RET
|
||||
break;
|
||||
}
|
||||
|
||||
addr += mCp.Size();
|
||||
addr += mZydis.Size();
|
||||
}
|
||||
else
|
||||
addr++;
|
||||
|
@ -134,10 +134,10 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
|||
|
||||
duint LinearAnalysis::getReferenceOperand() const
|
||||
{
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
const auto & op = mCp[i];
|
||||
if(mCp.IsJump() || mCp.IsLoop()) //skip jumps/loops
|
||||
const auto & op = mZydis[i];
|
||||
if(mZydis.IsJump() || mZydis.IsLoop()) //skip jumps/loops
|
||||
continue;
|
||||
if(op.type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //we are looking for immediate references
|
||||
{
|
||||
|
|
|
@ -59,11 +59,11 @@ void RecursiveAnalysis::SetMarkers()
|
|||
duint rangeStart = 0, rangeEnd = 0, rangeInstructionCount = 0;
|
||||
for(auto rangeItr = blockRanges.begin(); rangeItr != blockRanges.end(); ++rangeItr)
|
||||
{
|
||||
auto disasmLen = [this](duint addr)
|
||||
auto disasmLen = [this](duint addr) -> size_t
|
||||
{
|
||||
if(!mCp.Disassemble(addr, translateAddr(addr)))
|
||||
if(!mZydis.Disassemble(addr, translateAddr(addr)))
|
||||
return 1;
|
||||
return mCp.Size();
|
||||
return mZydis.Size();
|
||||
};
|
||||
const auto & node = *rangeItr->second;
|
||||
if(!rangeStart)
|
||||
|
@ -149,6 +149,7 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
CFGraph graph(entryPoint);
|
||||
UintSet visited;
|
||||
std::queue<duint> queue;
|
||||
visited.reserve(queue.size());
|
||||
queue.push(graph.entryPoint);
|
||||
while(!queue.empty())
|
||||
{
|
||||
|
@ -170,14 +171,14 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
{
|
||||
if(!inRange(node.end))
|
||||
{
|
||||
node.end = mCp.Address();
|
||||
node.end = (duint)mZydis.Address();
|
||||
node.terminal = true;
|
||||
graph.AddNode(node);
|
||||
break;
|
||||
}
|
||||
|
||||
node.icount++;
|
||||
if(!mCp.Disassemble(node.end, translateAddr(node.end)))
|
||||
if(!mZydis.Disassemble(node.end, translateAddr(node.end)))
|
||||
{
|
||||
node.end++;
|
||||
continue;
|
||||
|
@ -186,10 +187,10 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
//do xref analysis on the instruction
|
||||
XREF xref;
|
||||
xref.addr = 0;
|
||||
xref.from = mCp.Address();
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
xref.from = (duint)mZydis.Address();
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
duint dest = mCp.ResolveOpValue(i, [](ZydisRegister)->size_t
|
||||
auto dest = (duint)mZydis.ResolveOpValue(i, [](ZydisRegister) -> uint64_t
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
|
@ -202,23 +203,23 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
if(xref.addr)
|
||||
mXrefs.push_back(xref);
|
||||
|
||||
if(!mCp.IsNop() && (mCp.IsJump() || mCp.IsLoop())) //non-nop jump
|
||||
if(!mZydis.IsNop() && (mZydis.IsJump() || mZydis.IsLoop())) //non-nop jump
|
||||
{
|
||||
//set the branch destinations
|
||||
node.brtrue = mCp.BranchDestination();
|
||||
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||
node.brfalse = node.end + mCp.Size();
|
||||
node.brtrue = (duint)mZydis.BranchDestination();
|
||||
if(mZydis.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||
node.brfalse = node.end + mZydis.Size();
|
||||
|
||||
//consider register/memory branches as terminal nodes
|
||||
if(mCp.OpCount() && mCp[0].type != ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
if(mZydis.OpCount() && mZydis[0].type != ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
{
|
||||
//jmp ptr [index * sizeof(duint) + switchTable]
|
||||
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.value)))
|
||||
if(mZydis[0].type == ZYDIS_OPERAND_TYPE_MEMORY && mZydis[0 |