From fe18bd2a684597dff6424cd7eb51850f497b04b7 Mon Sep 17 00:00:00 2001 From: Avin Date: Sat, 26 Mar 2016 02:24:55 +0530 Subject: [PATCH] Added SEH Viewer to GUI --- src/bridge/bridgemain.cpp | 7 ++- src/bridge/bridgemain.h | 2 + src/dbg/_dbgfunctions.cpp | 18 ++++++ src/dbg/_dbgfunctions.h | 14 +++++ src/dbg/debugger.cpp | 9 ++- src/dbg/exhandlerinfo.cpp | 11 +++- src/dbg/stackinfo.cpp | 20 ++++--- src/gui/Src/Bridge/Bridge.cpp | 4 ++ src/gui/Src/Bridge/Bridge.h | 1 + src/gui/Src/Gui/MainWindow.cpp | 12 ++++ src/gui/Src/Gui/MainWindow.h | 3 + src/gui/Src/Gui/MainWindow.ui | 11 ++++ src/gui/Src/Gui/SEHChainView.cpp | 99 +++++++++++++++++++++++++++++++ src/gui/Src/Gui/SEHChainView.h | 28 +++++++++ src/gui/images/seh-chain.png | Bin 0 -> 707 bytes src/gui/resource.qrc | 1 + src/gui/x64dbg.pro | 6 +- 17 files changed, 230 insertions(+), 16 deletions(-) create mode 100644 src/gui/Src/Gui/SEHChainView.cpp create mode 100644 src/gui/Src/Gui/SEHChainView.h create mode 100644 src/gui/images/seh-chain.png diff --git a/src/bridge/bridgemain.cpp b/src/bridge/bridgemain.cpp index 18eb165a..78c9215b 100644 --- a/src/bridge/bridgemain.cpp +++ b/src/bridge/bridgemain.cpp @@ -1200,6 +1200,11 @@ BRIDGE_IMPEXP void GuiUpdateCallStack() _gui_sendmessage(GUI_UPDATE_CALLSTACK, 0, 0); } +BRIDGE_IMPEXP void GuiUpdateSEHChain() +{ + _gui_sendmessage(GUI_UPDATE_SEHCHAIN, 0, 0); +} + BRIDGE_IMPEXP void GuiLoadSourceFile(const char* path, int line) { _gui_sendmessage(GUI_LOAD_SOURCE_FILE, (void*)path, (void*)line); @@ -1289,4 +1294,4 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { hInst = hinstDLL; return TRUE; -} \ No newline at end of file +} diff --git a/src/bridge/bridgemain.h b/src/bridge/bridgemain.h index 26508d5b..0f1ba7cd 100644 --- a/src/bridge/bridgemain.h +++ b/src/bridge/bridgemain.h @@ -787,6 +787,7 @@ typedef enum GUI_REPAINT_TABLE_VIEW, // param1=unused, param2=unused GUI_UPDATE_PATCHES, // param1=unused, param2=unused GUI_UPDATE_CALLSTACK, // param1=unused, param2=unused + GUI_UPDATE_SEHCHAIN, // param1=unused, param2=unused GUI_SYMBOL_REFRESH_CURRENT, // param1=unused, param2=unused GUI_UPDATE_MEMORY_VIEW, // param1=unused, param2=unused GUI_REF_INITIALIZE, // param1=const char* name, param2=unused @@ -902,6 +903,7 @@ BRIDGE_IMPEXP void GuiUpdateSideBar(); BRIDGE_IMPEXP void GuiRepaintTableView(); BRIDGE_IMPEXP void GuiUpdatePatches(); BRIDGE_IMPEXP void GuiUpdateCallStack(); +BRIDGE_IMPEXP void GuiUpdateSEHChain(); BRIDGE_IMPEXP void GuiLoadSourceFile(const char* path, int line); BRIDGE_IMPEXP void GuiMenuSetIcon(int hMenu, const ICONDATA* icon); BRIDGE_IMPEXP void GuiMenuSetEntryIcon(int hEntry, const ICONDATA* icon); diff --git a/src/dbg/_dbgfunctions.cpp b/src/dbg/_dbgfunctions.cpp index ec59d12d..ae9e1d66 100644 --- a/src/dbg/_dbgfunctions.cpp +++ b/src/dbg/_dbgfunctions.cpp @@ -15,6 +15,7 @@ #include "stackinfo.h" #include "symbolinfo.h" #include "module.h" +#include "exhandlerinfo.h" static DBGFUNCTIONS _dbgfunctions; @@ -90,6 +91,22 @@ static void _getcallstack(DBGCALLSTACK* callstack) stackgetcallstack(GetContextDataEx(hActiveThread, UE_CSP), (CALLSTACK*)callstack); } +static void _getsehchain(DBGSEHCHAIN* sehchain) +{ + std::vector SEHList; + ExHandlerGetSEH(SEHList); + sehchain->total = SEHList.size(); + if(sehchain->total > 0) + { + sehchain->records = (DBGSEHRECORD*)BridgeAlloc(sehchain->total * sizeof(DBGSEHRECORD)); + for(size_t i = 0; i < sehchain->total; i++) + { + sehchain->records[i].addr = SEHList[i]; + MemRead(SEHList[i] + 4, &sehchain->records[i].handler, sizeof(duint)); + } + } +} + static bool _getjitauto(bool* jit_auto) { return dbggetjitauto(jit_auto, notfound, NULL, NULL); @@ -207,6 +224,7 @@ void dbgfunctionsinit() _dbgfunctions.DisasmFast = disasmfast; _dbgfunctions.MemUpdateMap = _memupdatemap; _dbgfunctions.GetCallStack = _getcallstack; + _dbgfunctions.GetSEHChain = _getsehchain; _dbgfunctions.SymbolDownloadAllSymbols = SymDownloadAllSymbols; _dbgfunctions.GetJit = _getjit; _dbgfunctions.GetJitAuto = _getjitauto; diff --git a/src/dbg/_dbgfunctions.h b/src/dbg/_dbgfunctions.h index da8813db..60778f1d 100644 --- a/src/dbg/_dbgfunctions.h +++ b/src/dbg/_dbgfunctions.h @@ -27,6 +27,18 @@ typedef struct DBGCALLSTACKENTRY* entries; } DBGCALLSTACK; +typedef struct +{ + duint addr; + duint handler; +} DBGSEHRECORD; + +typedef struct +{ + size_t total; + DBGSEHRECORD* records; +} DBGSEHCHAIN; + typedef struct { DWORD dwProcessId; @@ -52,6 +64,7 @@ typedef int (*MODPATHFROMNAME)(const char* modname, char* path, int size); typedef bool (*DISASMFAST)(const unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* basicinfo); typedef void (*MEMUPDATEMAP)(); typedef void (*GETCALLSTACK)(DBGCALLSTACK* callstack); +typedef void (*GETSEHCHAIN)(DBGSEHCHAIN* sehchain); typedef void (*SYMBOLDOWNLOADALLSYMBOLS)(const char* szSymbolStore); typedef bool (*GETJIT)(char* jit, bool x64); typedef bool (*GETJITAUTO)(bool* jitauto); @@ -91,6 +104,7 @@ typedef struct DBGFUNCTIONS_ DISASMFAST DisasmFast; MEMUPDATEMAP MemUpdateMap; GETCALLSTACK GetCallStack; + GETSEHCHAIN GetSEHChain; SYMBOLDOWNLOADALLSYMBOLS SymbolDownloadAllSymbols; GETJITAUTO GetJitAuto; GETJIT GetJit; diff --git a/src/dbg/debugger.cpp b/src/dbg/debugger.cpp index 713e962e..9de1b2ef 100644 --- a/src/dbg/debugger.cpp +++ b/src/dbg/debugger.cpp @@ -213,6 +213,12 @@ DWORD WINAPI updateCallStackThread(void* ptr) return 0; } +DWORD WINAPI updateSEHChainThread(void* ptr) +{ + GuiUpdateSEHChain(); + return 0; +} + void DebugUpdateGui(duint disasm_addr, bool stack) { duint cip = GetContextDataEx(hActiveThread, UE_CIP); @@ -235,6 +241,7 @@ void DebugUpdateGui(duint disasm_addr, bool stack) { cacheCsp = csp; CloseHandle(CreateThread(0, 0, updateCallStackThread, 0, 0, 0)); + CloseHandle(CreateThread(0, 0, updateSEHChainThread, 0, 0, 0)); } char modname[MAX_MODULE_SIZE] = ""; char modtext[MAX_MODULE_SIZE * 2] = ""; @@ -1802,4 +1809,4 @@ DWORD WINAPI threadAttachLoop(void* lpParameter) { debugLoopFunction(lpParameter, true); return 0; -} \ No newline at end of file +} diff --git a/src/dbg/exhandlerinfo.cpp b/src/dbg/exhandlerinfo.cpp index 0d0ee1e1..f0af5354 100644 --- a/src/dbg/exhandlerinfo.cpp +++ b/src/dbg/exhandlerinfo.cpp @@ -54,18 +54,23 @@ bool ExHandlerGetInfo(EX_HANDLER_TYPE Type, EX_HANDLER_INFO* Info) bool ExHandlerGetSEH(std::vector & Entries) { - // TODO: 64-bit +#ifdef _WIN64 + return false; // TODO: 64-bit +#endif static duint nextSEH = 0; NT_TIB tib; if(ThreadGetTib((duint)GetTEBLocation(hActiveThread), &tib)) { EXCEPTION_REGISTRATION_RECORD sehr; duint addr_ExRegRecord = (duint)tib.ExceptionList; - while(addr_ExRegRecord != 0xFFFFFFFF) + int MAX_DEPTH = 1000; + while(addr_ExRegRecord != 0xFFFFFFFF && MAX_DEPTH) { Entries.push_back(addr_ExRegRecord); - MemRead(addr_ExRegRecord , &sehr, sizeof(EXCEPTION_REGISTRATION_RECORD)); + if(!MemRead(addr_ExRegRecord , &sehr, sizeof(EXCEPTION_REGISTRATION_RECORD))) + break; addr_ExRegRecord = (duint)sehr.Next; + MAX_DEPTH--; } } return true; diff --git a/src/dbg/stackinfo.cpp b/src/dbg/stackinfo.cpp index 85b4e26d..9aaaa676 100644 --- a/src/dbg/stackinfo.cpp +++ b/src/dbg/stackinfo.cpp @@ -16,16 +16,18 @@ bool stackcommentget(duint addr, STACK_COMMENT* comment) { std::vector SEHList; - ExHandlerGetSEH(SEHList); - std::vector::iterator iter = std::find(SEHList.begin(), SEHList.end(), addr); - if(iter != SEHList.end()) + if(ExHandlerGetSEH(SEHList)) { - if(iter + 1 != SEHList.end()) - sprintf_s(comment->comment, "Pointer to SEH_Record[%d]", iter - SEHList.begin() + 1); - else - sprintf_s(comment->comment, "End of SEH Chain"); - strcpy_s(comment->color, "#AE81FF"); - return true; + std::vector::iterator iter = std::find(SEHList.begin(), SEHList.end(), addr); + if(iter != SEHList.end()) + { + if(iter + 1 != SEHList.end()) + sprintf_s(comment->comment, "Pointer to SEH_Record[%d]", iter - SEHList.begin() + 1); + else + sprintf_s(comment->comment, "End of SEH Chain"); + strcpy_s(comment->color, "#AE81FF"); + return true; + } } duint data = 0; memset(comment, 0, sizeof(STACK_COMMENT)); diff --git a/src/gui/Src/Bridge/Bridge.cpp b/src/gui/Src/Bridge/Bridge.cpp index d2915c4d..f709228f 100644 --- a/src/gui/Src/Bridge/Bridge.cpp +++ b/src/gui/Src/Bridge/Bridge.cpp @@ -424,6 +424,10 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2) emit updateCallStack(); break; + case GUI_UPDATE_SEHCHAIN: + emit updateSEHChain(); + break; + case GUI_SYMBOL_REFRESH_CURRENT: emit symbolRefreshCurrent(); break; diff --git a/src/gui/Src/Bridge/Bridge.h b/src/gui/Src/Bridge/Bridge.h index 4f31ef85..71e72d08 100644 --- a/src/gui/Src/Bridge/Bridge.h +++ b/src/gui/Src/Bridge/Bridge.h @@ -100,6 +100,7 @@ signals: void repaintTableView(); void updatePatches(); void updateCallStack(); + void updateSEHChain(); void symbolRefreshCurrent(); void loadSourceFile(const QString path, int line, int selection); void setIconMenuEntry(int hEntry, QIcon icon); diff --git a/src/gui/Src/Gui/MainWindow.cpp b/src/gui/Src/Gui/MainWindow.cpp index 6c649c25..d33dbab5 100644 --- a/src/gui/Src/Gui/MainWindow.cpp +++ b/src/gui/Src/Gui/MainWindow.cpp @@ -110,6 +110,11 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi mCallStackView->setWindowIcon(QIcon(":/icons/images/callstack.png")); connect(mCallStackView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget())); + // SEH Chain view + mSEHChainView = new SEHChainView(); + mSEHChainView->setWindowTitle("SEH Chain"); + mSEHChainView->setWindowIcon(QIcon(":/icons/images/seh-chain.png")); + connect(mSEHChainView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget())); // Script view mScriptView = new ScriptView(); mScriptView->setWindowTitle("Script"); @@ -158,6 +163,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi mWidgetList.push_back(mBreakpointsView); mWidgetList.push_back(mMemMapView); mWidgetList.push_back(mCallStackView); + mWidgetList.push_back(mSEHChainView); mWidgetList.push_back(mScriptView); mWidgetList.push_back(mSymbolView); mWidgetList.push_back(mSourceViewManager); @@ -227,6 +233,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi connect(ui->actionFunctions, SIGNAL(triggered()), this, SLOT(displayFunctions())); connect(ui->actionCheckUpdates, SIGNAL(triggered()), this, SLOT(checkUpdates())); connect(ui->actionCallStack, SIGNAL(triggered()), this, SLOT(displayCallstack())); + connect(ui->actionSEHChain, SIGNAL(triggered()), this, SLOT(displaySEHChain())); connect(ui->actionDonate, SIGNAL(triggered()), this, SLOT(donate())); connect(ui->actionReportBug, SIGNAL(triggered()), this, SLOT(reportBug())); connect(ui->actionAttach, SIGNAL(triggered()), this, SLOT(displayAttach())); @@ -1073,6 +1080,11 @@ void MainWindow::displayCallstack() showQWidgetTab(mCallStackView); } +void MainWindow::displaySEHChain() +{ + showQWidgetTab(mSEHChainView); +} + void MainWindow::donate() { QMessageBox msg(QMessageBox::Information, "Donate", "All the money will go to x64dbg development."); diff --git a/src/gui/Src/Gui/MainWindow.h b/src/gui/Src/Gui/MainWindow.h index 4efad649..7a97b6b8 100644 --- a/src/gui/Src/Gui/MainWindow.h +++ b/src/gui/Src/Gui/MainWindow.h @@ -10,6 +10,7 @@ #include "CPUWidget.h" #include "MemoryMapView.h" #include "CallStackView.h" +#include "SEHChainView.h" #include "LogView.h" #include "SymbolView.h" #include "BreakpointsView.h" @@ -102,6 +103,7 @@ public slots: void displayFunctions(); void checkUpdates(); void displayCallstack(); + void displaySEHChain(); void setGlobalShortcut(QAction* action, const QKeySequence & key); void refreshShortcuts(); void openShortcuts(); @@ -129,6 +131,7 @@ private: CPUWidget* mCpuWidget; MemoryMapView* mMemMapView; CallStackView* mCallStackView; + SEHChainView* mSEHChainView; LogView* mLogView; SymbolView* mSymbolView; SourceViewerManager* mSourceViewManager; diff --git a/src/gui/Src/Gui/MainWindow.ui b/src/gui/Src/Gui/MainWindow.ui index d4632f08..0ad89568 100644 --- a/src/gui/Src/Gui/MainWindow.ui +++ b/src/gui/Src/Gui/MainWindow.ui @@ -56,6 +56,7 @@ + @@ -157,6 +158,7 @@ + @@ -697,6 +699,15 @@ FAQ + + + + :/icons/images/seh-chain.png:/icons/images/seh-chain.png + + + SEH Chain + + diff --git a/src/gui/Src/Gui/SEHChainView.cpp b/src/gui/Src/Gui/SEHChainView.cpp new file mode 100644 index 00000000..5b59e44f --- /dev/null +++ b/src/gui/Src/Gui/SEHChainView.cpp @@ -0,0 +1,99 @@ +#include "SEHChainView.h" +#include "Bridge.h" + +SEHChainView::SEHChainView(StdTable* parent) : StdTable(parent) +{ + int charWidth = getCharWidth(); + + addColumnAt(8 + charWidth * sizeof(dsint) * 2, "Address", true); //address in the stack + addColumnAt(8 + charWidth * 18, "Exception Handler", true); // Exception Handler + addColumnAt(8 + charWidth * 50, "Module/Label", false); + addColumnAt(charWidth * 10, "Comment", false); + connect(Bridge::getBridge(), SIGNAL(updateSEHChain()), this, SLOT(updateSEHChain())); + connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint))); + connect(this, SIGNAL(doubleClickedSignal()), this, SLOT(doubleClickedSlot())); + setupContextMenu(); +} + +void SEHChainView::setupContextMenu() +{ + mFollowAddress = new QAction("Follow &Address", this); + connect(mFollowAddress, SIGNAL(triggered()), this, SLOT(followAddress())); + mFollowHandler = new QAction("Follow Handler", this); + mFollowHandler->setShortcutContext(Qt::WidgetShortcut); + mFollowHandler->setShortcut(QKeySequence("enter")); + connect(mFollowHandler, SIGNAL(triggered()), this, SLOT(followHandler())); + connect(this, SIGNAL(enterPressedSignal()), this, SLOT(followHandler())); +} + +void SEHChainView::updateSEHChain() +{ + DBGSEHCHAIN sehchain; + memset(&sehchain, 0, sizeof(DBGSEHCHAIN)); + DbgFunctions()->GetSEHChain(&sehchain); + setRowCount(sehchain.total); + for(size_t i = 0; i < sehchain.total; i++) + { + QString cellText = QString("%1").arg(sehchain.records[i].addr, sizeof(duint) * 2, 16, QChar('0')).toUpper(); + setCellContent(i, 0, cellText); + cellText = QString("%1").arg(sehchain.records[i].handler, sizeof(duint) * 2, 16, QChar('0')).toUpper(); + setCellContent(i, 1, cellText); + + char label[MAX_LABEL_SIZE] = ""; + char module[MAX_MODULE_SIZE] = ""; + DbgGetModuleAt(sehchain.records[i].handler, module); + QString label_text; + if(DbgGetLabelAt(sehchain.records[i].handler, SEG_DEFAULT, label)) + label_text = "<" + QString(module) + "." + QString(label) + ">"; + else + label_text = QString(module); + setCellContent(i, 2, label_text); + char comment[MAX_COMMENT_SIZE] = ""; + if(DbgGetCommentAt(sehchain.records[i].handler, comment)) + { + if(comment[0] == '\1') //automatic comment + setCellContent(i, 3, QString(comment + 1)); + else + setCellContent(i, 3, comment); + } + } + if(sehchain.total) + BridgeFree(sehchain.records); + reloadData(); +} + +void SEHChainView::contextMenuSlot(const QPoint pos) +{ + if(!DbgIsDebugging()) + return; + QMenu* wMenu = new QMenu(this); //create context menu + wMenu->addAction(mFollowAddress); + wMenu->addAction(mFollowHandler); + QMenu wCopyMenu("&Copy", this); + setupCopyMenu(&wCopyMenu); + if(wCopyMenu.actions().length()) + { + wMenu->addSeparator(); + wMenu->addMenu(&wCopyMenu); + } + wMenu->exec(mapToGlobal(pos)); //execute context menu +} + +void SEHChainView::doubleClickedSlot() +{ + followHandler(); +} + +void SEHChainView::followAddress() +{ + QString addrText = getCellContent(getInitialSelection(), 0); + DbgCmdExecDirect(QString("sdump " + addrText).toUtf8().constData()); + emit showCpu(); +} + +void SEHChainView::followHandler() +{ + QString addrText = getCellContent(getInitialSelection(), 1); + DbgCmdExecDirect(QString("disasm " + addrText).toUtf8().constData()); + emit showCpu(); +} diff --git a/src/gui/Src/Gui/SEHChainView.h b/src/gui/Src/Gui/SEHChainView.h new file mode 100644 index 00000000..144c9806 --- /dev/null +++ b/src/gui/Src/Gui/SEHChainView.h @@ -0,0 +1,28 @@ +#ifndef SEHCHAINVIEW_H +#define SEHCHAINVIEW_H + +#include "StdTable.h" + +class SEHChainView : public StdTable +{ + Q_OBJECT +public: + explicit SEHChainView(StdTable* parent = 0); + void setupContextMenu(); + +signals: + void showCpu(); + +protected slots: + void updateSEHChain(); + void contextMenuSlot(const QPoint pos); + void doubleClickedSlot(); + void followAddress(); + void followHandler(); + +private: + QAction* mFollowAddress; + QAction* mFollowHandler; +}; + +#endif // SEHCHAINVIEW_H diff --git a/src/gui/images/seh-chain.png b/src/gui/images/seh-chain.png new file mode 100644 index 0000000000000000000000000000000000000000..330c408cf5de263108f82ade0f35b86fa9d88b01 GIT binary patch literal 707 zcmV;!0zCbRP)N97u9MfZ=lm#K0x@>({TdEI@{-h=_ihTa8ER^3y7~C{So897&77Q^#G9L2I$6Gc{mLsSC?o?kammMz9~*$q?Xt46 zWB|Gfh($rp2W$TDd@;kk?tgw-D(^dkbLM{x4i2dR>17rY5;8S3G}jRmlVHDa;jH-2 zpFjVKii$d2ym*n}`0?Wm$BrFixODLh12^M#1}EP-j?>5YD9USO3v+M^uz4fX&AgEbtJo*CYy5is zpzX=S2MmY5e*1d?q>vMc#ei4}8*VOUj5xi+;M~V2HJ~*A|M`uK|3^0|oogv(3m>8z38pect`}b1#-a~x`S((!e|9|~{`})?gHUIuGWU^q>+)>8J zpsUWn@aGSMC69oJ{(qLI!fby&GI;xRGu*vu%)r3PDExtgNB`@mFP0cd8R#?yO=YlV zhTp##k|d=0lsK85Gw`r}W%&BG5=`^3eqoT1=2rsAqqrc*oq<6?>OaHhFAzS^i9e1V pxO*4KybBR&N6kn~3_kz@3;;?x1odsYD_{Ts002ovPDHLkV1nyfUJ3vJ literal 0 HcmV?d00001 diff --git a/src/gui/resource.qrc b/src/gui/resource.qrc index 19fec6e8..7c587a84 100644 --- a/src/gui/resource.qrc +++ b/src/gui/resource.qrc @@ -74,5 +74,6 @@ images/processor32.png images/processor64.png images/processor-cpu.png + images/seh-chain.png diff --git a/src/gui/x64dbg.pro b/src/gui/x64dbg.pro index fce29db0..8fea46b7 100644 --- a/src/gui/x64dbg.pro +++ b/src/gui/x64dbg.pro @@ -142,7 +142,8 @@ SOURCES += \ Src/Gui/CPUMultiDump.cpp \ Src/Gui/AssembleDialog.cpp \ Src/ThirdPartyLibs/float128/float128.cpp \ - Src/Utils/StringUtil.cpp + Src/Utils/StringUtil.cpp \ + Src/Gui/SEHChainView.cpp HEADERS += \ @@ -225,7 +226,8 @@ HEADERS += \ Src/Utils/QActionLambda.h \ Src/Gui/CPUMultiDump.h \ Src/Gui/AssembleDialog.h \ - Src/ThirdPartyLibs/float128/float128.h + Src/ThirdPartyLibs/float128/float128.h \ + Src/Gui/SEHChainView.h FORMS += \ Src/Gui/MainWindow.ui \