From 6588b90ecdb79595ee0358513240d4f41c3fdae3 Mon Sep 17 00:00:00 2001 From: "mr.exodia" Date: Fri, 22 Nov 2013 22:12:56 +0100 Subject: [PATCH] DBG: added basic plugin support (load plugins + register & call callbacks) --- x64_dbg_dbg/_plugin_types.h | 32 ++++++++++ x64_dbg_dbg/_plugins.cpp | 13 ++++ x64_dbg_dbg/_plugins.h | 79 +++++++++++++++++++++++ x64_dbg_dbg/debugger.cpp | 18 +++++- x64_dbg_dbg/plugin_loader.cpp | 117 ++++++++++++++++++++++++++++++++++ x64_dbg_dbg/plugin_loader.h | 34 ++++++++++ x64_dbg_dbg/x64_dbg.cpp | 7 +- x64_dbg_dbg/x64_dbg_dbg.cbp | 10 +++ 8 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 x64_dbg_dbg/_plugin_types.h create mode 100644 x64_dbg_dbg/_plugins.cpp create mode 100644 x64_dbg_dbg/_plugins.h create mode 100644 x64_dbg_dbg/plugin_loader.cpp create mode 100644 x64_dbg_dbg/plugin_loader.h diff --git a/x64_dbg_dbg/_plugin_types.h b/x64_dbg_dbg/_plugin_types.h new file mode 100644 index 00000000..c0075225 --- /dev/null +++ b/x64_dbg_dbg/_plugin_types.h @@ -0,0 +1,32 @@ +#ifndef _PLUGIN_DATA_H +#define _PLUGIN_DATA_H + +#ifdef BUILD_DBG + +#include "_global.h" + +#else + +#ifdef __GNUC__ +#include "dbghelp\dbghelp.h" +#else +#include +#endif //__GNUC__ + +#define deflen 1024 + +#ifdef _WIN64 //defined by default +#define fhex "%.16llX" +#define fext "ll" +typedef unsigned long long duint; +typedef long long dsint; +#else +#define fhex "%.8X" +#define fext "" +typedef unsigned long duint; +typedef long dsint; +#endif // _WIN64 + +#endif //BUILD_DBG + +#endif // _PLUGIN_DATA_H diff --git a/x64_dbg_dbg/_plugins.cpp b/x64_dbg_dbg/_plugins.cpp new file mode 100644 index 00000000..67b852f3 --- /dev/null +++ b/x64_dbg_dbg/_plugins.cpp @@ -0,0 +1,13 @@ +#include "_plugins.h" +#include "plugin_loader.h" + +///debugger plugin exports (wrappers) +PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin) +{ + pluginregistercallback(pluginHandle, cbType, cbPlugin); +} + +PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType) +{ + return pluginunregistercallback(pluginHandle, cbType); +} diff --git a/x64_dbg_dbg/_plugins.h b/x64_dbg_dbg/_plugins.h new file mode 100644 index 00000000..1c3e0f56 --- /dev/null +++ b/x64_dbg_dbg/_plugins.h @@ -0,0 +1,79 @@ +#ifndef _PLUGINS_H +#define _PLUGINS_H + +#ifndef PLUG_IMPEXP +#ifdef BUILD_DBG +#define PLUG_IMPEXP __declspec(dllexport) +#else +#define PLUG_IMPEXP __declspec(dllimport) +#endif //BUILD_DBG +#endif //PLUG_IMPEXP + +#include "_plugin_types.h" + +//structures +struct PLUG_INITSTRUCT +{ + //provided by the debugger + int pluginHandle; + //provided by the pluginit function + int sdkVersion; + int pluginVersion; + char pluginName[256]; +}; + +//callback structures +struct PLUG_CB_INITDEBUG +{ + const char* szFileName; +}; + +struct PLUG_CB_STOPDEBUG +{ + void* reserved; +}; + +struct PLUG_CB_CREATEPROCESS +{ + CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo; + IMAGEHLP_MODULE64* modInfo; + const char* DebugFileName; +}; + +//enums +enum CBTYPE +{ + CB_INITDEBUG, //PLUG_CB_INITDEBUG + CB_STOPDEBUG, //PLUG_CB_STOPDEBUG + CB_CREATEPROCESS, //PLUG_CB_CREATEPROCESS + CB_EXITPROCESS, + CB_CREATETHREAD, + CB_EXITTHREAD, + CB_SYSTEMBREAKPOINT, + CB_LOADDLL, + CB_UNLOADDLL, + CB_OUTPUTDEBUGSTRING, + CB_EXCEPTION, + CB_BREAKPOINT, + CB_PAUSEDEBUG, + CB_RESUMEDEBUG, + CB_STEPPED +}; + +//typedefs +typedef void (*CBPLUGIN)(CBTYPE cbType, void* callbackInfo); + +//exports +#ifdef __cplusplus +extern "C" +{ +#endif + +PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin); +PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType); + +#ifdef __cplusplus +} +#endif + +#endif // _PLUGINS_H diff --git a/x64_dbg_dbg/debugger.cpp b/x64_dbg_dbg/debugger.cpp index cb066c59..54d01313 100644 --- a/x64_dbg_dbg/debugger.cpp +++ b/x64_dbg_dbg/debugger.cpp @@ -8,6 +8,7 @@ #include "memory.h" #include "_exports.h" #include "addrinfo.h" +#include "plugin_loader.h" static PROCESS_INFORMATION g_pi= {0,0,0,0}; PROCESS_INFORMATION* fdProcessInfo=&g_pi; @@ -377,6 +378,13 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo) char modname[256]=""; if(modnamefromaddr((uint)base, modname, true)) bpenumall(cbSetModuleBreakpoints, modname); + + //call plugin callback + PLUG_CB_CREATEPROCESS callbackInfo; + callbackInfo.CreateProcessInfo=CreateProcessInfo; + callbackInfo.modInfo=&modInfo; + callbackInfo.DebugFileName=DebugFileName; + plugincbcall(CB_CREATEPROCESS, &callbackInfo); } static void cbSystemBreakpoint(void* ExceptionData) @@ -463,10 +471,18 @@ static DWORD WINAPI threadDebugLoop(void* lpParameter) SetCustomHandler(UE_CH_UNLOADDLL, (void*)cbUnloadDll); //inform GUI start we started without problems GuiSetDebugState(initialized); + //call plugin callback + PLUG_CB_INITDEBUG initInfo; + initInfo.szFileName=szFileName; + plugincbcall(CB_INITDEBUG, &initInfo); //run debug loop (returns when process debugging is stopped) DebugLoop(); - DeleteFileA("DLLLoader.exe"); + //call plugin callback + PLUG_CB_STOPDEBUG stopInfo; + stopInfo.reserved=0; + plugincbcall(CB_STOPDEBUG, &stopInfo); //message the user/do final stuff + DeleteFileA("DLLLoader.exe"); SymCleanup(fdProcessInfo->hProcess); dbclose(); modclear(); diff --git a/x64_dbg_dbg/plugin_loader.cpp b/x64_dbg_dbg/plugin_loader.cpp new file mode 100644 index 00000000..646b01b3 --- /dev/null +++ b/x64_dbg_dbg/plugin_loader.cpp @@ -0,0 +1,117 @@ +#include "plugin_loader.h" +#include "console.h" + +static std::vector pluginList; +static int curPluginHandle=0; +static std::vector pluginCallbackList; + +///internal plugin functions +void pluginload(const char* pluginDir) +{ + char currentDir[deflen]=""; + GetCurrentDirectoryA(deflen, currentDir); + SetCurrentDirectoryA(pluginDir); + char searchName[deflen]=""; +#ifdef _WIN64 + sprintf(searchName, "%s\\*.dp64", pluginDir); +#else + sprintf(searchName, "%s\\*.dp32", pluginDir); +#endif // _WIN64 + WIN32_FIND_DATA foundData; + HANDLE hSearch=FindFirstFileA(searchName, &foundData); + if(hSearch==INVALID_HANDLE_VALUE) + { + SetCurrentDirectoryA(currentDir); + return; + } + PLUG_DATA pluginData; + char errorMsg[deflen]=""; + do + { + memset(&pluginData, 0, sizeof(PLUG_DATA)); + pluginData.initStruct.pluginHandle=curPluginHandle; + pluginData.hPlugin=LoadLibraryA(foundData.cFileName); //load the plugin library + if(!pluginData.hPlugin) + { + sprintf(errorMsg, "Failed to load plugin: %s", foundData.cFileName); + MessageBoxA(0, errorMsg, "Plugin Error!", MB_ICONERROR|MB_SYSTEMMODAL); + continue; + } + pluginData.pluginit=(PLUGINIT)GetProcAddress(pluginData.hPlugin, "pluginit"); + if(!pluginData.pluginit) + { + sprintf(errorMsg, "Export \"pluginit\" not found in plugin: %s", foundData.cFileName); + MessageBoxA(0, errorMsg, "Plugin Error!", MB_ICONERROR|MB_SYSTEMMODAL); + FreeLibrary(pluginData.hPlugin); + continue; + } + pluginData.plugstop=(PLUGSTOP)GetProcAddress(pluginData.hPlugin, "plugstop"); + if(!pluginData.plugstop) + { + sprintf(errorMsg, "Export \"plugstop\" not found in plugin: %s", foundData.cFileName); + MessageBoxA(0, errorMsg, "Plugin Error!", MB_ICONERROR|MB_SYSTEMMODAL); + FreeLibrary(pluginData.hPlugin); + continue; + } + //TODO: handle exceptions + if(!pluginData.pluginit(&pluginData.initStruct)) + { + sprintf(errorMsg, "pluginit failed for plugin: %s", foundData.cFileName); + MessageBoxA(0, errorMsg, "Plugin Error!", MB_ICONERROR|MB_SYSTEMMODAL); + FreeLibrary(pluginData.hPlugin); + continue; + } + pluginList.push_back(pluginData); + curPluginHandle++; + } + while(FindNextFileA(hSearch, &foundData)); + SetCurrentDirectoryA(currentDir); +} + +void pluginunload() +{ + int pluginCount=pluginList.size(); + for(int i=0; i