diff --git a/x64_dbg_dbg/_plugins.h b/x64_dbg_dbg/_plugins.h index 1c3e0f56..a0458cc5 100644 --- a/x64_dbg_dbg/_plugins.h +++ b/x64_dbg_dbg/_plugins.h @@ -40,24 +40,86 @@ struct PLUG_CB_CREATEPROCESS const char* DebugFileName; }; +struct PLUG_CB_EXITPROCESS +{ + EXIT_PROCESS_DEBUG_INFO* ExitProcess; +}; + +struct PLUG_CB_CREATETHREAD +{ + CREATE_THREAD_DEBUG_INFO* CreateThread; +}; + +struct PLUG_CB_EXITTHREAD +{ + EXIT_THREAD_DEBUG_INFO* ExitThread; +}; + +struct PLUG_CB_SYSTEMBREAKPOINT +{ + void* reserved; +}; + +struct PLUG_CB_LOADDLL +{ + LOAD_DLL_DEBUG_INFO* LoadDll; + IMAGEHLP_MODULE64* modInfo; + const char* modname; +}; + +struct PLUG_CB_UNLOADDLL +{ + UNLOAD_DLL_DEBUG_INFO* UnloadDll; +}; + +struct PLUG_CB_OUTPUTDEBUGSTRING +{ + OUTPUT_DEBUG_STRING_INFO* DebugString; +}; + +struct PLUG_CB_EXCEPTION +{ + EXCEPTION_DEBUG_INFO* Exception; +}; + +struct PLUG_CB_BREAKPOINT +{ + void* reserved; +}; + +struct PLUG_CB_PAUSEDEBUG +{ + void* reserved; +}; + +struct PLUG_CB_RESUMEDEBUG +{ + void* reserved; +}; + +struct PLUG_CB_STEPPED +{ + void* reserved; +}; + //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 + CB_EXITPROCESS, //PLUG_CB_EXITPROCESS + CB_CREATETHREAD, //PLUG_CB_CREATETHREAD + CB_EXITTHREAD, //PLUG_CB_EXITTHREAD + CB_SYSTEMBREAKPOINT, //PLUG_CB_SYSTEMBREAKPOINT + CB_LOADDLL, //PLUG_CB_LOADDLL + CB_UNLOADDLL, //PLUG_CB_UNLOADDLL + CB_OUTPUTDEBUGSTRING, //PLUG_CB_OUTPUTDEBUGSTRING + CB_EXCEPTION, //PLUG_CB_EXCEPTION + CB_BREAKPOINT, //PLUG_CB_BREAKPOINT + CB_PAUSEDEBUG, //PLUG_CB_PAUSEDEBUG + CB_RESUMEDEBUG, //PLUG_CB_RESUMEDEBUG + CB_STEPPED //PLUG_CB_STEPPED }; //typedefs diff --git a/x64_dbg_dbg/debugger.cpp b/x64_dbg_dbg/debugger.cpp index 54d01313..86f7e85b 100644 --- a/x64_dbg_dbg/debugger.cpp +++ b/x64_dbg_dbg/debugger.cpp @@ -18,6 +18,7 @@ uint pDebuggedDllBase=0; static bool isStepping=false; static bool isPausedByUser=false; static bool bScyllaLoaded=false; +static int ecount=0; //Superglobal variables char sqlitedb[deflen]=""; @@ -175,48 +176,6 @@ static void cbEntryBreakpoint() wait(WAITID_RUN); } -static int ecount=0; - -static void cbException(void* ExceptionData) -{ - EXCEPTION_DEBUG_INFO* edi=(EXCEPTION_DEBUG_INFO*)ExceptionData; - uint addr=(uint)edi->ExceptionRecord.ExceptionAddress; - if(edi->ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT) - { - if(isPausedByUser) - { - dputs("paused!"); - SetNextDbgContinueStatus(DBG_CONTINUE); - DebugUpdateGui(GetContextData(UE_CIP)); - GuiSetDebugState(paused); - //lock - lock(WAITID_RUN); - wait(WAITID_RUN); - return; - } - SetContextData(UE_CIP, (uint)edi->ExceptionRecord.ExceptionAddress); - } - - char msg[1024]=""; - if(edi->dwFirstChance) //first chance exception - { - sprintf(msg, "first chance exception on "fhex" (%.8X)!", addr, edi->ExceptionRecord.ExceptionCode); - SetNextDbgContinueStatus(DBG_EXCEPTION_NOT_HANDLED); - } - else //lock the exception - { - sprintf(msg, "last chance exception on "fhex" (%.8X)!", addr, edi->ExceptionRecord.ExceptionCode); - SetNextDbgContinueStatus(DBG_CONTINUE); - } - - dputs(msg); - DebugUpdateGui(GetContextData(UE_CIP)); - GuiSetDebugState(paused); - //lock - lock(WAITID_RUN); - wait(WAITID_RUN); -} - BOOL CALLBACK SymRegisterCallbackProc64( @@ -286,28 +245,6 @@ static bool cbSetModuleBreakpoints(const BREAKPOINT* bp) return true; } -static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll) -{ - void* base=LoadDll->lpBaseOfDll; - char DLLDebugFileName[deflen]=""; - if(!GetMappedFileNameA(fdProcessInfo->hProcess, base, DLLDebugFileName, deflen)) - strcpy(DLLDebugFileName, "??? (GetMappedFileName failed)"); - else - DevicePathToPath(DLLDebugFileName, DLLDebugFileName, deflen); - dprintf("DLL Loaded: "fhex" %s\n", base, DLLDebugFileName); - - SymLoadModuleEx(fdProcessInfo->hProcess, LoadDll->hFile, DLLDebugFileName, 0, (DWORD64)base, 0, 0, 0); - IMAGEHLP_MODULE64 modInfo; - memset(&modInfo, 0, sizeof(modInfo)); - modInfo.SizeOfStruct=sizeof(IMAGEHLP_MODULE64); - if(SymGetModuleInfo64(fdProcessInfo->hProcess, (DWORD64)base, &modInfo)) - modload((uint)base, modInfo.ImageSize, modInfo.ImageName); - bpenumall(0); - char modname[256]=""; - if(modnamefromaddr((uint)base, modname, true)) - bpenumall(cbSetModuleBreakpoints, modname); -} - static bool cbRemoveModuleBreakpoints(const BREAKPOINT* bp) { //TODO: more breakpoint types @@ -329,16 +266,44 @@ static bool cbRemoveModuleBreakpoints(const BREAKPOINT* bp) return true; } -static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll) +static void cbStep() { - void* base=UnloadDll->lpBaseOfDll; - char modname[256]="???"; - if(modnamefromaddr((uint)base, modname, true)) - bpenumall(cbRemoveModuleBreakpoints, modname); - SymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base); - dprintf("DLL Unloaded: "fhex" %s\n", base, modname); + isStepping=false; + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); } +static void cbRtrFinalStep() +{ + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + +static unsigned char getCIPch() +{ + unsigned char ch=0x90; + uint cip=GetContextData(UE_CIP); + memread(fdProcessInfo->hProcess, (void*)cip, &ch, 1, 0); + bpfixmemory(cip, &ch, 1); + return ch; +} + +static void cbRtrStep() +{ + unsigned int cipch=getCIPch(); + if(cipch==0xC3 or cipch==0xC2) + cbRtrFinalStep(); + else + StepOver((void*)cbRtrStep); +} + +///custom handlers static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo) { void* base=CreateProcessInfo->lpBaseOfImage; @@ -387,10 +352,33 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo) plugincbcall(CB_CREATEPROCESS, &callbackInfo); } +static void cbExitProcess(EXIT_PROCESS_DEBUG_INFO* ExitProcess) +{ + PLUG_CB_EXITPROCESS callbackInfo; + callbackInfo.ExitProcess=ExitProcess; + plugincbcall(CB_EXITPROCESS, &callbackInfo); +} + +static void cbCreateThread(CREATE_THREAD_DEBUG_INFO* CreateThread) +{ + PLUG_CB_CREATETHREAD callbackInfo; + callbackInfo.CreateThread=CreateThread; + plugincbcall(CB_CREATETHREAD, &callbackInfo); +} + +static void cbExitThread(EXIT_THREAD_DEBUG_INFO* ExitThread) +{ + PLUG_CB_EXITTHREAD callbackInfo; + callbackInfo.ExitThread=ExitThread; + plugincbcall(CB_EXITTHREAD, &callbackInfo); +} + static void cbSystemBreakpoint(void* ExceptionData) { + PLUG_CB_SYSTEMBREAKPOINT callbackInfo; + callbackInfo.reserved=0; + plugincbcall(CB_SYSTEMBREAKPOINT, &callbackInfo); //TODO: handle stuff (TLS, main entry, etc) - SetCustomHandler(UE_CH_SYSTEMBREAKPOINT, 0); //log message dputs("system breakpoint reached!"); //update GUI @@ -403,43 +391,103 @@ static void cbSystemBreakpoint(void* ExceptionData) wait(WAITID_RUN); } -static void cbStep() +static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll) { - isStepping=false; - DebugUpdateGui(GetContextData(UE_CIP)); - GuiSetDebugState(paused); - //lock - lock(WAITID_RUN); - wait(WAITID_RUN); -} - -static void cbRtrFinalStep() -{ - DebugUpdateGui(GetContextData(UE_CIP)); - GuiSetDebugState(paused); - //lock - lock(WAITID_RUN); - wait(WAITID_RUN); -} - -static unsigned char getCIPch() -{ - unsigned char ch=0x90; - uint cip=GetContextData(UE_CIP); - memread(fdProcessInfo->hProcess, (void*)cip, &ch, 1, 0); - bpfixmemory(cip, &ch, 1); - return ch; -} - -static void cbRtrStep() -{ - unsigned int cipch=getCIPch(); - if(cipch==0xC3 or cipch==0xC2) - cbRtrFinalStep(); + void* base=LoadDll->lpBaseOfDll; + char DLLDebugFileName[deflen]=""; + if(!GetMappedFileNameA(fdProcessInfo->hProcess, base, DLLDebugFileName, deflen)) + strcpy(DLLDebugFileName, "??? (GetMappedFileName failed)"); else - StepOver((void*)cbRtrStep); + DevicePathToPath(DLLDebugFileName, DLLDebugFileName, deflen); + dprintf("DLL Loaded: "fhex" %s\n", base, DLLDebugFileName); + + SymLoadModuleEx(fdProcessInfo->hProcess, LoadDll->hFile, DLLDebugFileName, 0, (DWORD64)base, 0, 0, 0); + IMAGEHLP_MODULE64 modInfo; + memset(&modInfo, 0, sizeof(modInfo)); + modInfo.SizeOfStruct=sizeof(IMAGEHLP_MODULE64); + if(SymGetModuleInfo64(fdProcessInfo->hProcess, (DWORD64)base, &modInfo)) + modload((uint)base, modInfo.ImageSize, modInfo.ImageName); + bpenumall(0); + char modname[256]=""; + if(modnamefromaddr((uint)base, modname, true)) + bpenumall(cbSetModuleBreakpoints, modname); + + //TODO: plugin callback + PLUG_CB_LOADDLL callbackInfo; + callbackInfo.LoadDll=LoadDll; + callbackInfo.modInfo=&modInfo; + callbackInfo.modname=modname; + plugincbcall(CB_LOADDLL, &callbackInfo); } +static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll) +{ + //TODO: plugin callback + PLUG_CB_UNLOADDLL callbackInfo; + callbackInfo.UnloadDll=UnloadDll; + plugincbcall(CB_UNLOADDLL, &callbackInfo); + + void* base=UnloadDll->lpBaseOfDll; + char modname[256]="???"; + if(modnamefromaddr((uint)base, modname, true)) + bpenumall(cbRemoveModuleBreakpoints, modname); + SymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base); + dprintf("DLL Unloaded: "fhex" %s\n", base, modname); +} + +static void cbOutputDebugString(OUTPUT_DEBUG_STRING_INFO* DebugString) +{ + //TODO: handle debug strings + PLUG_CB_OUTPUTDEBUGSTRING callbackInfo; + callbackInfo.DebugString=DebugString; + plugincbcall(CB_OUTPUTDEBUGSTRING, &callbackInfo); +} + +static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData) +{ + //TODO: plugin callback + PLUG_CB_EXCEPTION callbackInfo; + callbackInfo.Exception=ExceptionData; + plugincbcall(CB_EXCEPTION, &callbackInfo); + + uint addr=(uint)ExceptionData->ExceptionRecord.ExceptionAddress; + if(ExceptionData->ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT) + { + if(isPausedByUser) + { + dputs("paused!"); + SetNextDbgContinueStatus(DBG_CONTINUE); + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); + return; + } + SetContextData(UE_CIP, (uint)ExceptionData->ExceptionRecord.ExceptionAddress); + } + + char msg[1024]=""; + if(ExceptionData->dwFirstChance) //first chance exception + { + sprintf(msg, "first chance exception on "fhex" (%.8X)!", addr, ExceptionData->ExceptionRecord.ExceptionCode); + SetNextDbgContinueStatus(DBG_EXCEPTION_NOT_HANDLED); + } + else //lock the exception + { + sprintf(msg, "last chance exception on "fhex" (%.8X)!", addr, ExceptionData->ExceptionRecord.ExceptionCode); + SetNextDbgContinueStatus(DBG_CONTINUE); + } + + dputs(msg); + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + + static DWORD WINAPI threadDebugLoop(void* lpParameter) { //initialize @@ -465,10 +513,14 @@ static DWORD WINAPI threadDebugLoop(void* lpParameter) ecount=0; //NOTE: set custom handlers SetCustomHandler(UE_CH_CREATEPROCESS, (void*)cbCreateProcess); + SetCustomHandler(UE_CH_EXITPROCESS, (void*)cbExitProcess); + SetCustomHandler(UE_CH_CREATETHREAD, (void*)cbCreateThread); + SetCustomHandler(UE_CH_EXITTHREAD, (void*)cbExitThread); SetCustomHandler(UE_CH_SYSTEMBREAKPOINT, (void*)cbSystemBreakpoint); - SetCustomHandler(UE_CH_UNHANDLEDEXCEPTION, (void*)cbException); SetCustomHandler(UE_CH_LOADDLL, (void*)cbLoadDll); SetCustomHandler(UE_CH_UNLOADDLL, (void*)cbUnloadDll); + SetCustomHandler(UE_CH_OUTPUTDEBUGSTRING, (void*)cbOutputDebugString); + SetCustomHandler(UE_CH_UNHANDLEDEXCEPTION, (void*)cbException); //inform GUI start we started without problems GuiSetDebugState(initialized); //call plugin callback