CPUDisassembly : Removed some code that was repeated from DisassembleAt function
Added a warning when user tries to assemble an instruction thats points to Non-executable memory and DEP is enabled
This commit is contained in:
parent
87fc0de91c
commit
9b8bcc70ec
|
@ -1250,6 +1250,11 @@ BRIDGE_IMPEXP void GuiDumpAtN(duint va, int index)
|
||||||
_gui_sendmessage(GUI_DUMP_AT_N, (void*)va, (void*)index);
|
_gui_sendmessage(GUI_DUMP_AT_N, (void*)va, (void*)index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BRIDGE_IMPEXP void GuiDisplayWarning(const char *title, const char *text)
|
||||||
|
{
|
||||||
|
_gui_sendmessage(GUI_DISPLAY_WARNING, (void*)title, (void*)text);
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
{
|
{
|
||||||
hInst = hinstDLL;
|
hInst = hinstDLL;
|
||||||
|
|
|
@ -787,6 +787,7 @@ typedef enum
|
||||||
GUI_SET_DEBUGGEE_NOTES, // param1=const char* text, param2=unused
|
GUI_SET_DEBUGGEE_NOTES, // param1=const char* text, param2=unused
|
||||||
GUI_GET_DEBUGGEE_NOTES, // param1=char** text, param2=unused
|
GUI_GET_DEBUGGEE_NOTES, // param1=char** text, param2=unused
|
||||||
GUI_DUMP_AT_N, // param1=int index, param2=duint va
|
GUI_DUMP_AT_N, // param1=int index, param2=duint va
|
||||||
|
GUI_DISPLAY_WARNING // param1=const char *text, param2=unused
|
||||||
} GUIMSG;
|
} GUIMSG;
|
||||||
|
|
||||||
//GUI Typedefs
|
//GUI Typedefs
|
||||||
|
@ -886,6 +887,7 @@ BRIDGE_IMPEXP void GuiGetGlobalNotes(char** text);
|
||||||
BRIDGE_IMPEXP void GuiSetDebuggeeNotes(const char* text);
|
BRIDGE_IMPEXP void GuiSetDebuggeeNotes(const char* text);
|
||||||
BRIDGE_IMPEXP void GuiGetDebuggeeNotes(char** text);
|
BRIDGE_IMPEXP void GuiGetDebuggeeNotes(char** text);
|
||||||
BRIDGE_IMPEXP void GuiDumpAtN(duint va, int index);
|
BRIDGE_IMPEXP void GuiDumpAtN(duint va, int index);
|
||||||
|
BRIDGE_IMPEXP void GuiDisplayWarning(const char *title, const char *text);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef _GLOBAL_H
|
#ifndef _GLOBAL_H
|
||||||
#define _GLOBAL_H
|
#define _GLOBAL_H
|
||||||
|
|
||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0601
|
||||||
#define WINVER 0x0501
|
#define WINVER 0x0501
|
||||||
#define _WIN32_IE 0x0500
|
#define _WIN32_IE 0x0500
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "XEDParse\XEDParse.h"
|
#include "XEDParse\XEDParse.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "disasm_helper.h"
|
#include "disasm_helper.h"
|
||||||
|
#include "debugger.h"
|
||||||
|
|
||||||
static bool cbUnknown(const char* text, ULONGLONG* value)
|
static bool cbUnknown(const char* text, ULONGLONG* value)
|
||||||
{
|
{
|
||||||
|
@ -67,6 +68,10 @@ bool assembleat(duint addr, const char* instruction, int* size, char* error, boo
|
||||||
if(size)
|
if(size)
|
||||||
*size = destSize;
|
*size = destSize;
|
||||||
|
|
||||||
|
// Check if the instruction doesn't set IP to non-executable memory
|
||||||
|
if (!isInstructionPointingToExMemory(addr, dest))
|
||||||
|
GuiDisplayWarning("Non-executable memory region", "Assembled instruction points to non-executable memory region !");
|
||||||
|
|
||||||
bool ret = MemPatch(addr, dest, destSize);
|
bool ret = MemPatch(addr, dest, destSize);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -91,3 +96,81 @@ bool assembleat(duint addr, const char* instruction, int* size, char* error, boo
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isInstructionPointingToExMemory(duint addr, const unsigned char* dest)
|
||||||
|
{
|
||||||
|
MEMMAP wMemMapStruct;
|
||||||
|
DISASM_ARG arg;
|
||||||
|
DISASM_INSTR wDisasInstrStruct;
|
||||||
|
MEMORY_BASIC_INFORMATION *wMbiStruct = NULL;
|
||||||
|
duint instrArgCount;
|
||||||
|
dsint instrMemValues[3] = {0};
|
||||||
|
duint instrMemValuesIndex = 0;
|
||||||
|
dsint mbiBaseAddr, mbiEndAddr;
|
||||||
|
|
||||||
|
disasmget((unsigned char*)dest, 0, &wDisasInstrStruct);
|
||||||
|
|
||||||
|
instrArgCount = wDisasInstrStruct.argcount;
|
||||||
|
if (instrArgCount)
|
||||||
|
{
|
||||||
|
// Loop through all arguements
|
||||||
|
for (int i = 0; i < wDisasInstrStruct.argcount; i++)
|
||||||
|
{
|
||||||
|
arg = wDisasInstrStruct.arg[i];
|
||||||
|
|
||||||
|
// Check if any of the arguments is a memory
|
||||||
|
if (arg.type == arg_memory)
|
||||||
|
{
|
||||||
|
instrMemValues[instrMemValuesIndex] = addr + arg.memvalue; // add current instruction VA for rip-relative addressing
|
||||||
|
instrMemValuesIndex++;
|
||||||
|
}
|
||||||
|
else if (wDisasInstrStruct.type == instr_branch)
|
||||||
|
{
|
||||||
|
instrMemValues[instrMemValuesIndex] = addr + arg.value;
|
||||||
|
instrMemValuesIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No memory pointer in the instruction, no need to go further
|
||||||
|
if (!instrMemValuesIndex)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get memory map to locate the sections to which the instr memory address belongs to
|
||||||
|
DbgMemMap(&wMemMapStruct);
|
||||||
|
|
||||||
|
// For each memPointerValue
|
||||||
|
for (auto & memValue : instrMemValues)
|
||||||
|
{
|
||||||
|
// Loop through the memMaps
|
||||||
|
for (int i = 0; i < wMemMapStruct.count; i++)
|
||||||
|
{
|
||||||
|
wMbiStruct = &(wMemMapStruct.page)[i].mbi;
|
||||||
|
mbiBaseAddr = (dsint)wMbiStruct->BaseAddress;
|
||||||
|
mbiEndAddr = (dsint)wMbiStruct->BaseAddress + (dsint)wMbiStruct->RegionSize;
|
||||||
|
if (memValue >= mbiBaseAddr && memValue < mbiEndAddr)
|
||||||
|
{
|
||||||
|
if (wMbiStruct->Protect == PAGE_EXECUTE ||
|
||||||
|
wMbiStruct->Protect == PAGE_EXECUTE_READ ||
|
||||||
|
wMbiStruct->Protect == PAGE_EXECUTE_READWRITE ||
|
||||||
|
wMbiStruct->Protect == PAGE_EXECUTE_WRITECOPY)
|
||||||
|
{
|
||||||
|
// Memory region is marked as executable
|
||||||
|
#ifndef _WIN64
|
||||||
|
DWORD lpFlagsDep;
|
||||||
|
BOOL bPermanentDep;
|
||||||
|
|
||||||
|
// DEP is disabled if lpFlagsDep == 0
|
||||||
|
if (GetProcessDEPPolicy(fdProcessInfo->hProcess, &lpFlagsDep, &bPermanentDep) && lpFlagsDep != 0)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
// DEP enabled on x64
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -5,5 +5,6 @@
|
||||||
|
|
||||||
bool assemble(duint addr, unsigned char* dest, int* size, const char* instruction, char* error);
|
bool assemble(duint addr, unsigned char* dest, int* size, const char* instruction, char* error);
|
||||||
bool assembleat(duint addr, const char* instruction, int* size, char* error, bool fillnop);
|
bool assembleat(duint addr, const char* instruction, int* size, char* error, bool fillnop);
|
||||||
|
bool isInstructionPointingToExMemory(duint addr, const unsigned char* dest);
|
||||||
|
|
||||||
#endif // _ASSEMBLE_H
|
#endif // _ASSEMBLE_H
|
||||||
|
|
|
@ -528,6 +528,14 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
||||||
emit dumpAtN((duint)param1, (int)param2);
|
emit dumpAtN((duint)param1, (int)param2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GUI_DISPLAY_WARNING:
|
||||||
|
{
|
||||||
|
QString title = QString((const char*)param1);
|
||||||
|
QString text = QString((const char*)param2);
|
||||||
|
emit displayWarning(title, text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ signals:
|
||||||
void setDebuggeeNotes(const QString text);
|
void setDebuggeeNotes(const QString text);
|
||||||
void getDebuggeeNotes(void* text);
|
void getDebuggeeNotes(void* text);
|
||||||
void dumpAtN(duint va, int index);
|
void dumpAtN(duint va, int index);
|
||||||
|
void displayWarning(QString title, QString text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMutex* mBridgeMutex;
|
QMutex* mBridgeMutex;
|
||||||
|
|
|
@ -24,6 +24,7 @@ CPUDisassembly::CPUDisassembly(CPUWidget* parent) : Disassembly(parent)
|
||||||
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(debugStateChangedSlot(DBGSTATE)));
|
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(debugStateChangedSlot(DBGSTATE)));
|
||||||
connect(Bridge::getBridge(), SIGNAL(selectionDisasmGet(SELECTIONDATA*)), this, SLOT(selectionGetSlot(SELECTIONDATA*)));
|
connect(Bridge::getBridge(), SIGNAL(selectionDisasmGet(SELECTIONDATA*)), this, SLOT(selectionGetSlot(SELECTIONDATA*)));
|
||||||
connect(Bridge::getBridge(), SIGNAL(selectionDisasmSet(const SELECTIONDATA*)), this, SLOT(selectionSetSlot(const SELECTIONDATA*)));
|
connect(Bridge::getBridge(), SIGNAL(selectionDisasmSet(const SELECTIONDATA*)), this, SLOT(selectionSetSlot(const SELECTIONDATA*)));
|
||||||
|
connect(Bridge::getBridge(), SIGNAL(displayWarning(QString, QString)), this, SLOT(displayWarningSlot(QString, QString)));
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
@ -704,24 +705,7 @@ void CPUDisassembly::assembleSlot()
|
||||||
duint wVA = rvaToVa(wRVA);
|
duint wVA = rvaToVa(wRVA);
|
||||||
QString addr_text = QString("%1").arg(wVA, sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
QString addr_text = QString("%1").arg(wVA, sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||||
|
|
||||||
QByteArray wBuffer;
|
Instruction_t instr = this->DisassembleAt(wRVA);
|
||||||
|
|
||||||
dsint wMaxByteCountToRead = 16 * 2;
|
|
||||||
|
|
||||||
//TODO: fix size problems
|
|
||||||
dsint size = getSize();
|
|
||||||
if(!size)
|
|
||||||
size = wRVA;
|
|
||||||
|
|
||||||
// Bounding
|
|
||||||
wMaxByteCountToRead = wMaxByteCountToRead > (size - wRVA) ? (size - wRVA) : wMaxByteCountToRead;
|
|
||||||
|
|
||||||
wBuffer.resize(wMaxByteCountToRead);
|
|
||||||
|
|
||||||
mMemPage->read(reinterpret_cast<byte_t*>(wBuffer.data()), wRVA, wMaxByteCountToRead);
|
|
||||||
|
|
||||||
QBeaEngine disasm(-1);
|
|
||||||
Instruction_t instr = disasm.DisassembleAt(reinterpret_cast<byte_t*>(wBuffer.data()), wMaxByteCountToRead, 0, 0, wVA);
|
|
||||||
|
|
||||||
QString actual_inst = instr.instStr;
|
QString actual_inst = instr.instStr;
|
||||||
|
|
||||||
|
@ -1250,6 +1234,11 @@ void CPUDisassembly::decompileFunctionSlot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPUDisassembly::displayWarningSlot(QString title, QString text)
|
||||||
|
{
|
||||||
|
QMessageBox::QMessageBox(QMessageBox::Information, title, text, QMessageBox::Ok).exec();
|
||||||
|
}
|
||||||
|
|
||||||
void CPUDisassembly::paintEvent(QPaintEvent* event)
|
void CPUDisassembly::paintEvent(QPaintEvent* event)
|
||||||
{
|
{
|
||||||
// Hook/hack to update the sidebar at the same time as this widget.
|
// Hook/hack to update the sidebar at the same time as this widget.
|
||||||
|
|
|
@ -83,6 +83,7 @@ public slots:
|
||||||
void openSourceSlot();
|
void openSourceSlot();
|
||||||
void decompileSelectionSlot();
|
void decompileSelectionSlot();
|
||||||
void decompileFunctionSlot();
|
void decompileFunctionSlot();
|
||||||
|
void displayWarningSlot(QString title, QString text);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent* event);
|
void paintEvent(QPaintEvent* event);
|
||||||
|
|
Loading…
Reference in New Issue