From e0b92786f0e28c5c0d7d507ccfcb99e070fc677a Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Sat, 25 Apr 2020 22:12:57 +0200 Subject: [PATCH] DBG: move InitDLLDebugW out of TitanEngine --- src/dbg/commands/cmd-debug-control.cpp | 2 +- src/dbg/debugger.cpp | 75 ++++++++++-- src/dbg/debugger.h | 3 +- src/dbg/x64dbg.cpp | 4 + src/loaddll/loaddll.cpp | 23 ++++ src/loaddll/loaddll.vcxproj | 157 +++++++++++++++++++++++++ src/loaddll/loaddll.vcxproj.filters | 22 ++++ x64dbg.sln | 13 ++ 8 files changed, 286 insertions(+), 13 deletions(-) create mode 100644 src/loaddll/loaddll.cpp create mode 100644 src/loaddll/loaddll.vcxproj create mode 100644 src/loaddll/loaddll.vcxproj.filters diff --git a/src/dbg/commands/cmd-debug-control.cpp b/src/dbg/commands/cmd-debug-control.cpp index 35d177c7..a2ddec53 100644 --- a/src/dbg/commands/cmd-debug-control.cpp +++ b/src/dbg/commands/cmd-debug-control.cpp @@ -237,7 +237,7 @@ bool cbDebugAttach(int argc, char* argv[]) #endif // _WIN64 return false; } - if(!GetFileNameFromProcessHandle(hProcess, szFileName)) + if(!GetFileNameFromProcessHandle(hProcess, szDebuggeePath)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Could not get module filename %X!\n"), DWORD(pid)); return false; diff --git a/src/dbg/debugger.cpp b/src/dbg/debugger.cpp index 11519ecf..42b54eec 100644 --- a/src/dbg/debugger.cpp +++ b/src/dbg/debugger.cpp @@ -70,10 +70,11 @@ static WString gInitExe, gInitCmd, gInitDir, gDllLoader; static CookieQuery cookie; static duint exceptionDispatchAddr = 0; static bool bPausedOnException = false; +static HANDLE DebugDLLFileMapping = 0; char szProgramDir[MAX_PATH] = ""; -char szFileName[MAX_PATH] = ""; +char szDebuggeePath[MAX_PATH] = ""; +char szDllLoaderPath[MAX_PATH] = ""; char szSymbolCachePath[MAX_PATH] = ""; -char sqlitedb[deflen] = ""; std::vector> RunToUserCodeBreakpoints; PROCESS_INFORMATION* fdProcessInfo = &g_pi; HANDLE hActiveThread; @@ -1672,8 +1673,10 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll) char command[MAX_PATH * 2] = ""; bool bIsDebuggingThis = false; - if(bFileIsDll && !_stricmp(DLLDebugFileName, szFileName) && !bIsAttached) //Set entry breakpoint + if(bFileIsDll && !_stricmp(DLLDebugFileName, szDebuggeePath) && !bIsAttached) //Set entry breakpoint { + CloseHandle(DebugDLLFileMapping); + DebugDLLFileMapping = 0; bIsDebuggingThis = true; pDebuggedBase = (duint)base; DbCheckHash(ModContentHashFromAddr(pDebuggedBase)); //Check hash mismatch @@ -2553,6 +2556,45 @@ void dbgstartscriptthread(CBPLUGINSCRIPT cbScript) CloseHandle(CreateThread(0, 0, scriptThread, (LPVOID)cbScript, 0, 0)); } +static void* InitDLLDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder) +{ + WString loaderFilename = StringUtils::sprintf(L"\\DLLLoader" ArchValue(L"32", L"64") L"_%04X.exe", GetTickCount() & 0xFFFF); + WString debuggeeLoaderPath = szFileName; + { + auto backslashIdx = debuggeeLoaderPath.rfind('\\'); + if(backslashIdx != WString::npos) + debuggeeLoaderPath.resize(backslashIdx); + } + debuggeeLoaderPath += loaderFilename; + WString loaderPath = StringUtils::Utf8ToUtf16(szDllLoaderPath); + if(!CopyFileW(loaderPath.c_str(), debuggeeLoaderPath.c_str(), FALSE)) + { + debuggeeLoaderPath = StringUtils::Utf8ToUtf16(szProgramDir); + debuggeeLoaderPath += loaderFilename; + if(!CopyFileW(loaderPath.c_str(), debuggeeLoaderPath.c_str(), FALSE)) + { + dprintf(QT_TRANSLATE_NOOP("DBG", "Error debugging DLL (failed to copy loader)\n")); + return nullptr; + } + } + + PPROCESS_INFORMATION ReturnValue = (PPROCESS_INFORMATION)InitDebugW(debuggeeLoaderPath.c_str(), szCommandLine, szCurrentFolder); + WString mappingName = StringUtils::sprintf(L"Local\\szLibraryName%X", ReturnValue->dwProcessId); + const auto mappingSize = 512; + DebugDLLFileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, mappingSize * sizeof(wchar_t), mappingName.c_str()); + if(DebugDLLFileMapping) + { + wchar_t* szLibraryPathMapping = (wchar_t*)MapViewOfFile(DebugDLLFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, mappingSize * sizeof(wchar_t)); + if(szLibraryPathMapping) + { + wcscpy_s(szLibraryPathMapping, mappingSize, szFileName); + UnmapViewOfFile(szLibraryPathMapping); + } + } + + return ReturnValue; +} + static void debugLoopFunction(void* lpParameter, bool attach) { //initialize variables @@ -2565,7 +2607,7 @@ static void debugLoopFunction(void* lpParameter, bool attach) INIT_STRUCT* init; if(attach) { - gInitExe = StringUtils::Utf8ToUtf16(szFileName); + gInitExe = StringUtils::Utf8ToUtf16(szDebuggeePath); pid = DWORD(lpParameter); static PROCESS_INFORMATION pi_attached; memset(&pi_attached, 0, sizeof(pi_attached)); @@ -2575,14 +2617,19 @@ static void debugLoopFunction(void* lpParameter, bool attach) { init = (INIT_STRUCT*)lpParameter; gInitExe = StringUtils::Utf8ToUtf16(init->exe); - strcpy_s(szFileName, init->exe); + strcpy_s(szDebuggeePath, init->exe); } pDebuggedEntry = GetPE32DataW(gInitExe.c_str(), 0, UE_OEP); bEntryIsInMzHeader = pDebuggedEntry == 0 || pDebuggedEntry == 1; - bFileIsDll = IsFileDLLW(StringUtils::Utf8ToUtf16(szFileName).c_str(), 0); - DbSetPath(nullptr, szFileName); + bFileIsDll = IsFileDLLW(StringUtils::Utf8ToUtf16(szDebuggeePath).c_str(), 0); + if(bFileIsDll && !FileExists(szDllLoaderPath)) + { + dprintf(QT_TRANSLATE_NOOP("DBG", "Error debugging DLL (loaddll.exe not found)\n")); + return; + } + DbSetPath(nullptr, szDebuggeePath); if(!attach) { @@ -2602,7 +2649,7 @@ static void debugLoopFunction(void* lpParameter, bool attach) //start the process if(bFileIsDll) - fdProcessInfo = (PROCESS_INFORMATION*)InitDLLDebugW(gInitExe.c_str(), false, gInitCmd.c_str(), gInitDir.c_str(), 0); + fdProcessInfo = (PROCESS_INFORMATION*)InitDLLDebugW(gInitExe.c_str(), gInitCmd.c_str(), gInitDir.c_str()); else fdProcessInfo = (PROCESS_INFORMATION*)InitDebugW(gInitExe.c_str(), gInitCmd.c_str(), gInitDir.c_str()); if(!fdProcessInfo) @@ -2680,10 +2727,10 @@ static void debugLoopFunction(void* lpParameter, bool attach) //inform GUI we started without problems GuiSetDebugState(initialized); GuiFocusView(GUI_DISASSEMBLY); - GuiAddRecentFile(szFileName); + GuiAddRecentFile(szDebuggeePath); //set GUI title - strcpy_s(szBaseFileName, szFileName); + strcpy_s(szBaseFileName, szDebuggeePath); int len = (int)strlen(szBaseFileName); while(szBaseFileName[len] != '\\' && len) len--; @@ -2693,7 +2740,7 @@ static void debugLoopFunction(void* lpParameter, bool attach) //call plugin callback PLUG_CB_INITDEBUG initInfo; - initInfo.szFileName = szFileName; + initInfo.szFileName = szDebuggeePath; plugincbcall(CB_INITDEBUG, &initInfo); //call plugin callback (attach) @@ -2760,6 +2807,12 @@ static void debugLoopFunction(void* lpParameter, bool attach) hProcessToken = 0; } + if(DebugDLLFileMapping) + { + CloseHandle(DebugDLLFileMapping); + DebugDLLFileMapping = 0; + } + pDebuggedEntry = 0; pDebuggedBase = 0; pCreateProcessBase = 0; diff --git a/src/dbg/debugger.h b/src/dbg/debugger.h index d7ed139e..b608a6c8 100644 --- a/src/dbg/debugger.h +++ b/src/dbg/debugger.h @@ -114,7 +114,8 @@ extern PROCESS_INFORMATION* fdProcessInfo; extern HANDLE hActiveThread; extern HANDLE hProcessToken; extern char szProgramDir[MAX_PATH]; -extern char szFileName[MAX_PATH]; +extern char szDebuggeePath[MAX_PATH]; +extern char szDllLoaderPath[MAX_PATH]; extern char szSymbolCachePath[MAX_PATH]; extern bool bUndecorateSymbolNames; extern bool bEnableSourceDebugging; diff --git a/src/dbg/x64dbg.cpp b/src/dbg/x64dbg.cpp index e960e21b..4ba4921e 100644 --- a/src/dbg/x64dbg.cpp +++ b/src/dbg/x64dbg.cpp @@ -630,6 +630,10 @@ extern "C" DLL_EXPORT const char* _dbg_dbginit() while(szProgramDir[len] != '\\') len--; szProgramDir[len] = 0; + + strcpy_s(szDllLoaderPath, szProgramDir); + strcat_s(szDllLoaderPath, "\\loaddll.exe"); + #ifdef ENABLE_MEM_TRACE strcpy_s(alloctrace, szProgramDir); strcat_s(alloctrace, "\\alloctrace.txt"); diff --git a/src/loaddll/loaddll.cpp b/src/loaddll/loaddll.cpp new file mode 100644 index 00000000..e62c7db4 --- /dev/null +++ b/src/loaddll/loaddll.cpp @@ -0,0 +1,23 @@ +#include + +wchar_t szLibraryPath[512]; + +int main() +{ + wchar_t szName[256]; + wsprintfW(szName, L"Local\\szLibraryName%X", (unsigned int)GetCurrentProcessId()); + HANDLE hMapFile = OpenFileMappingW(FILE_MAP_READ, false, szName); + if(hMapFile) + { + const wchar_t* szLibraryPathMapping = (const wchar_t*)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, sizeof(szLibraryPath)); + if(szLibraryPathMapping) + { + lstrcpyW(szLibraryPath, szLibraryPathMapping); + UnmapViewOfFile(szLibraryPathMapping); + } + CloseHandle(hMapFile); + } + if(szLibraryPath[0]) + return (LoadLibraryW(szLibraryPath) != NULL); + return 0; +} diff --git a/src/loaddll/loaddll.vcxproj b/src/loaddll/loaddll.vcxproj new file mode 100644 index 00000000..bb9ccfdd --- /dev/null +++ b/src/loaddll/loaddll.vcxproj @@ -0,0 +1,157 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + {21AD9735-967B-41F7-8329-DB88D03743ED} + Win32Proj + + + + Application + false + v120_xp + + + Application + false + v120_xp + + + Application + false + v120_xp + + + Application + false + v120_xp + + + + + + + + + + + + + + + + + + + false + $(ProjectDir)..\..\bin\x32\ + false + $(Platform)\$(Configuration)\ + + + false + $(ProjectDir)..\..\bin\x32d\ + false + $(Platform)\$(Configuration)\ + + + false + $(ProjectDir)..\..\bin\x64\ + false + + + false + $(ProjectDir)..\..\bin\x64d\ + false + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + MultiThreaded + Level3 + ProgramDatabase + + + MachineX86 + true + Console + true + true + + + true + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Console + true + true + + + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + MultiThreaded + Level3 + ProgramDatabase + + + true + Console + true + true + + + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + + + true + Console + true + true + + + + + + + + \ No newline at end of file diff --git a/src/loaddll/loaddll.vcxproj.filters b/src/loaddll/loaddll.vcxproj.filters new file mode 100644 index 00000000..15005a8e --- /dev/null +++ b/src/loaddll/loaddll.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + \ No newline at end of file diff --git a/x64dbg.sln b/x64dbg.sln index e27a590c..43e49190 100644 --- a/x64dbg.sln +++ b/x64dbg.sln @@ -20,6 +20,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "x64dbg_launcher", "src\laun EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zydis_wrapper", "src\zydis_wrapper\zydis_wrapper.vcxproj", "{3B2C1EE1-FDEC-4D85-BE46-3C6A5EA69883}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loaddll", "src\loaddll\loaddll.vcxproj", "{21AD9735-967B-41F7-8329-DB88D03743ED}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -68,8 +70,19 @@ Global {3B2C1EE1-FDEC-4D85-BE46-3C6A5EA69883}.Release|Win32.Build.0 = Release|Win32 {3B2C1EE1-FDEC-4D85-BE46-3C6A5EA69883}.Release|x64.ActiveCfg = Release|x64 {3B2C1EE1-FDEC-4D85-BE46-3C6A5EA69883}.Release|x64.Build.0 = Release|x64 + {21AD9735-967B-41F7-8329-DB88D03743ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {21AD9735-967B-41F7-8329-DB88D03743ED}.Debug|Win32.Build.0 = Debug|Win32 + {21AD9735-967B-41F7-8329-DB88D03743ED}.Debug|x64.ActiveCfg = Debug|x64 + {21AD9735-967B-41F7-8329-DB88D03743ED}.Debug|x64.Build.0 = Debug|x64 + {21AD9735-967B-41F7-8329-DB88D03743ED}.Release|Win32.ActiveCfg = Release|Win32 + {21AD9735-967B-41F7-8329-DB88D03743ED}.Release|Win32.Build.0 = Release|Win32 + {21AD9735-967B-41F7-8329-DB88D03743ED}.Release|x64.ActiveCfg = Release|x64 + {21AD9735-967B-41F7-8329-DB88D03743ED}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CC6FA67F-9244-45AD-AC13-69C29283D226} + EndGlobalSection EndGlobal