From 80c6649d787c48a58aabd6bd405b3de80e497229 Mon Sep 17 00:00:00 2001 From: Victor Sheinmann Date: Wed, 22 Apr 2020 15:49:11 +0500 Subject: [PATCH] Version 2 update --- InjectLib/InjectDll.cpp | 314 ++++++++++++++++---------- InjectLib/InjectDll.h | 25 +- InjectLib/InjectDll.vcxproj | 53 +++-- InjectLib/InjectDll.vcxproj.filters | 3 + NOTES.txt | 88 +++++++- XDbgPlugin/LogoIcon.ico | Bin 0 -> 22486 bytes XDbgPlugin/Resources.rc | 12 +- XDbgPlugin/XDbgPlugin.cpp | 307 +++++++++++++++++-------- XDbgPlugin/XDbgPlugin.h | 34 ++- XDbgPlugin/XDbgPlugin.vcxproj | 38 ++-- XDbgPlugin/XDbgPlugin.vcxproj.filters | 6 + XDbgPlugin/pluginsdk/bridgemain.h | 2 +- 12 files changed, 603 insertions(+), 279 deletions(-) create mode 100644 XDbgPlugin/LogoIcon.ico diff --git a/InjectLib/InjectDll.cpp b/InjectLib/InjectDll.cpp index cfd2ed7..bca83f9 100644 --- a/InjectLib/InjectDll.cpp +++ b/InjectLib/InjectDll.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2018 Victor Sheinmann, Vicshann@gmail.com + Copyright (c) 2020 Victor Sheinmann, Vicshann@gmail.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, @@ -14,6 +14,13 @@ #include "InjectDll.h" +//#pragma comment(linker,"/MERGE:.rdata=.text") // .idata can be only there +//#pragma comment(linker,"/MERGE:.data=.text") +//#pragma comment(linker,"/MERGE:.idata=.text") +//#pragma comment(linker, "/SECTION:.text,EWR") // .text; .bss; .pdata; .idata; .reloc // GhostDbg can cut off after BSS (It does imports and relocs and PDATA is unused) +#pragma comment(linker,"/MERGE:.data=.rdata") // Now: .text; .bss; .rdata; .pdata; .reloc // rdata will not be writable - fixed manually for a separate DLL release +//#pragma comment(linker,"/MERGE:.text=.rdata") // Creates .xdata section +//#pragma comment(linker, "/SECTION:.rdata,WR") // Any attampt to make it writable will create .xdata section #pragma comment(linker,"/ENTRY:DLLMain") #pragma comment(linker,"/NODEFAULTLIB") @@ -23,6 +30,7 @@ UINT IPCSize = 0x100000; // 1Mb (Enough when Req-Rsp removed) //bool HideDllProxy = true; //bool HideDllProxyDsk = true; +bool SuspMainThAtLd = false; // Suspend main thread when loaded by GInjer bool RstDskHiddenProxy = true; bool AllowEjectOnDetach = false; //--------------------------------------- @@ -34,83 +42,119 @@ PHOOK(ProcNtUnmapViewOfSection) HookNtUnmapViewOfSection; PHOOK(ProcNtMapViewOfSection) HookNtMapViewOfSection; PHOOK(ProcNtGetContextThread) HookNtGetContextThread; PHOOK(ProcNtSetContextThread) HookNtSetContextThread; -PHOOK(ProcNtTerminateThread) HookNtTerminateThread; -//PHOOK(ProcNtTerminateProcess) HookNtTerminateProcess; +PHOOK(ProcNtTerminateThread) HookNtTerminateThread; +PHOOK(ProcNtTerminateProcess) HookNtTerminateProcess; PHOOK(ProcNtContinue) HookNtContinue; +SHookLdrpInitialize LdrpInitHook; SHookRtlDispatchException ExpDispHook; -bool ModInjected = false; +DWORD ModInjFlags = 0; // If 0 then the module is loaded normally(With loader) // -1 if the module is hidden or a proxy //BYTE ProxyEncKey = 0; //PBYTE ProxyDllCopy = NULL; //DWORD ProxyDllSize = 0; GhDbg::CDbgClient* Dbg = NULL; -HANDLE hIpcTh = NULL; -DWORD LastExcThID; // Helps to reduce overhead of NtContinue hook +HANDLE hIpcTh = NULL; +DWORD MainThId = 0; +DWORD LastThID = -1; +DWORD LastExcThID = 0;; // Helps to reduce overhead of NtContinue hook //LPSTR LibPathName = NULL; // TODO: Add an option to not use a detectable hooks ("No detectable hooks") PBYTE ThisLibBase = NULL; -SIZE_T ThisLibSize = 0; +//SIZE_T ThisLibSize = 0; PBYTE MainExeBase = NULL; -SIZE_T MainExeSize = 0; +//SIZE_T MainExeSize = 0; + +alignas(16) BYTE ArrDbgClient[sizeof(GhDbg::CDbgClient)]; wchar_t SysDirPath[MAX_PATH]; wchar_t StartUpDir[MAX_PATH]; wchar_t CfgFilePath[MAX_PATH]; wchar_t WorkFolder[MAX_PATH]; //=========================================================================== -BOOL APIENTRY DLLMain(HMODULE hModule, DWORD ReasonCall, LPVOID lpReserved) +/* + NOTE: Only a SystemService(sysenter/int2E) type of functions is allowed to be used + + Can be loaded by: XDbgPlugin, GInjer, A target process somehow + + Injector can load a DLL with LdrLoadDll or as '(HMODULE)Mod->ModuleBase, DLL_REFLECTIVE_LOAD, Mod' + Ginjer injects from a main thread +*/ +// Reflective load: +// hModule = Module Base +// ReasonCall = 15 +// lpReserved = SInjModDesc* (Can be used to find SBlkDescr*) +//=========================================================================== +BOOL APIENTRY DLLMain(HMODULE hModule, DWORD ReasonCall, LPVOID lpReserved) // ReasonCall and lpReserved is invalid for mfRunUAPC,mfRunRMTH,mfRunThHij { - wchar_t DllDirPath[MAX_PATH]; - bool RemTh = (DWORD)hModule & 0x0FFF; // Normal HMODULE would be aligned at 0x1000 - if(RemTh || (ReasonCall > 3)) - { - // - // TODO: Prevent multi-entering from different threads when APC injection method used - // - hModule = (HMODULE)InjLdr::PEImageInitialize(hModule); - ReasonCall = DLL_PROCESS_ATTACH; - ModInjected = true; - } + SModDesc* ModDesc = ModDescFromCurTh(); // NULL if loaded not by GInjer // NOTE: GInjer uses main thread + SBlkDesc* BlkDesc = AddrToBlkDesc(ModDesc); + SLdrDesc* LdrDesc = GetCurLdrDesc(BlkDesc); + UINT RemThFlags = (DWORD)hModule & InjLdr::RemThModMarker; // DLLMain has been passed to CreateRemoteThread/APC/ExistingThread (Where is only one argument available) // Normal HMODULE would be aligned at 0x1000 +#ifdef _DEBUG + if(ModDesc){LdrLogInit(ModDesc); LDRLOG("Hello from %08X: %ls", ModDesc->Flags, &ModDesc->ModulePath);} +#endif + if(RemThFlags || (ReasonCall >= DLL_REFLECTIVE_LOAD)) // NOTE: Variables get read in conditions even if these conditions is skipped // Either an own thread or APC callback of an existing thread // ReasonCall may be already outside of stack(Remote Thread)! + { + DWORD InjFlg = (RemThFlags?RemThFlags:(ReasonCall & InjLdr::RemThModMarker)) << 24; // ReasonCall = (Flags >> 24)|0x100 // mfRunUAPC,mfRunRMTH,mfRunThHij,mfRawRMTH + bool NotOwnThread = (InjFlg & (InjLdr::mfRunUAPC|InjLdr::mfRunThHij)); + bool NotReusableTh = ModDesc || NotOwnThread; + if(InjFlg & InjLdr::mfRunUAPC) // Cannot reuse these threads + { + // + // TODO: Prevent multi-entering from different threads when APC or Hijack injection method used + // + } + if(ModDesc)hModule = (HMODULE)InjLdr::ReflectiveRelocateSelf(hModule, (LdrDesc)?((PVOID)LdrDesc->NtDllBase):(NULL)); // Allocate to a new buffer // Loaded by GInjer + else hModule = (HMODULE)InjLdr::PEImageInitialize(hModule); // Relocate in current buffer (Must be large enough) // Loaded by a Debugger plugin + if(!NotReusableTh)hIpcTh = NtCurrentThread; // Can be changed later, before Start, if needed // A reusable injected remote thread // Assign globals after relocation + if(ModDesc && !NotOwnThread)MainThId = NtCurrentThreadId(); // Main thread by GInjer + ReasonCall = DLL_PROCESS_ATTACH; + ModInjFlags = InjFlg; // Injected with + } + else MainThId = NtCurrentThreadId(); // Injected from a Main Thread or loaded normally switch(ReasonCall) { case DLL_PROCESS_ATTACH: - { + { + wchar_t DllDirPath[MAX_PATH]; ThisLibBase = (PBYTE)hModule; - MainExeBase = (PBYTE)GetModuleHandleA(NULL); + MainExeBase = (PBYTE)NNTDLL::GetModuleBaseLdr(NULL); // GetModuleHandleA(NULL); // LibPathName = (LPSTR)&SysDirPath; - ThisLibSize = GetRealModuleSize(ThisLibBase); - MainExeSize = GetRealModuleSize(MainExeBase); - - GetModuleFileNameW((HMODULE)hModule,DllDirPath,countof(DllDirPath)); - GetSystemDirectoryW(SysDirPath,countof(SysDirPath)); +// ThisLibSize = GetRealModuleSize(ThisLibBase); +// MainExeSize = GetRealModuleSize(MainExeBase); + + NNTDLL::GetModuleNameLdr(hModule,DllDirPath,countof(DllDirPath)); // GetModuleFileNameW((HMODULE)hModule,DllDirPath,countof(DllDirPath)); +// GetSystemDirectoryW(SysDirPath,countof(SysDirPath)); // Get it from PEB? NSTR::StrCnat(SysDirPath, L"\\"); NSTR::StrCnat(SysDirPath,GetFileName(DllDirPath)); - GetModuleFileNameW((HMODULE)MainExeBase,StartUpDir,countof(StartUpDir)); + NNTDLL::GetModuleNameLdr(MainExeBase,StartUpDir,countof(StartUpDir)); // GetModuleFileNameW((HMODULE)MainExeBase,StartUpDir,countof(StartUpDir)); NSTR::StrCopy(WorkFolder, StartUpDir); TrimFilePath(WorkFolder); // NSTR::StrCnat((LPSTR)&WorkFolder,".LOGS\\"); - #ifndef NOLOG NSTR::StrCopy(LogFilePath, WorkFolder); NSTR::StrCnat(LogFilePath, GetFileName(StartUpDir)); - NSTR::StrCnat(LogFilePath, LOGFILE); + NSTR::StrCnat(LogFilePath, ctENCSA(LOGFILE)); #endif NSTR::StrCopy(CfgFilePath, WorkFolder); NSTR::StrCnat(CfgFilePath, GetFileName(StartUpDir)); - NSTR::StrCnat(CfgFilePath, CFGFILE); + NSTR::StrCnat(CfgFilePath, ctENCSA(CFGFILE)); - CreateDirectoryPath(WorkFolder); +// CreateDirectoryPath(WorkFolder); LoadConfiguration(); - if(LogMode & lmCons){AllocConsole();/*SetWinConsoleSizes(1000, 500, 1000, 500);*/} - LOGMSG("Time=%08X, ExeBase=%p, Owner='%ls'", (DWORD)GetTime64(),MainExeBase,&StartUpDir); -// LOGMSG("HookMod=%p, RealMod=%p", hModule, hRealMod); + DBGMSG("Starting up... (Time=%016X), Owner='%ls'", SysTimeToTime64(NNTDLL::GetSystemTime()), &StartUpDir); + DBGMSG("RemThFlags=%08X, hIpcTh=%p, ModDesc=%p, hModule=%p, lpReserved=%p, ModInjFlags=%08X, MainThId=%u", RemThFlags, hIpcTh, ModDesc, hModule, lpReserved, ModInjFlags, MainThId); TrimFilePath(StartUpDir); - LOGMSG("WorkFolder: %ls", &WorkFolder); - LOGMSG("StartUpDir: %ls", &StartUpDir); - LOGMSG("SysDirPath: %ls", &SysDirPath); + DBGMSG("WorkFolder: %ls", &WorkFolder); + DBGMSG("StartUpDir: %ls", &StartUpDir); + DBGMSG("SysDirPath: %ls", &SysDirPath); + +/* { + NTSTATUS stat = GhDbg::CDbgClient::CreateIpcThread(&hIpcTh, NULL, TRUE); // <<<<<<<<< TEST !!!!!!!!!!!! + } */ /* BOOL dres = true; if(!ModInjected && HideDllProxy) // NOTE: NO MORE DLL PROXY NEEDED { @@ -119,12 +163,12 @@ BOOL APIENTRY DLLMain(HMODULE hModule, DWORD ReasonCall, LPVOID lpReserved) hIpcTh = CreateThread(NULL,0,&GhDbg::CDbgClient::IPCQueueThread,NULL,CREATE_SUSPENDED,NULL); // Some anticheats prevent creation of threads outside of any module if(InjLdr::HideSelfProxyDll(hModule, GetModuleHandleA(ctENCSA("ntdll.dll")), (LPSTR)&SysDirPath, &NewBase, &EntryPT) > 0) // Are imports from our proxy DLL is already resolved by loader at this point? { - LOGMSG("Calling EP of a real DLL: Base=%p, EP=%p",hModule,EntryPT); + DBGMSG("Calling EP of a real DLL: Base=%p, EP=%p",hModule,EntryPT); dres = ((decltype(DLLMain)*)EntryPT)(hModule, ReasonCall, lpReserved); // Pass DLL_PROCESS_ATTACH notification hModule = (HMODULE)NewBase; if(HideDllProxyDsk && DllDirPath[0]) { - LOGMSG("Hiding from disk..."); + DBGMSG("Hiding from disk..."); if(RstDskHiddenProxy) { ProxyEncKey = (GetTickCount() >> 3) | 0x80; @@ -146,25 +190,24 @@ BOOL APIENTRY DLLMain(HMODULE hModule, DWORD ReasonCall, LPVOID lpReserved) } } DeleteFileA((LPSTR)&DllDirPath); // It is no longer mapped - LOGMSG("Done hiding from disk!"); + DBGMSG("Done hiding from disk!"); } } - LOGMSG("Done hiding!"); + DBGMSG("Done hiding!"); } */ if(!InitApplication())return false; - if(RemTh){LOGMSG("Terminating injected thread: %u", NtCurrentThreadId()); TerminateThread(GetCurrentThread(),0);} //Stack frame may be incorrect + if(ModInjFlags & InjLdr::mfRunRMTH){DBGMSG("Terminating injected thread(this): %u", NtCurrentThreadId()); NtTerminateThread(NtCurrentThread,0);} // Stack frame may be incorrect return true; //dres; } break; case DLL_THREAD_ATTACH: - LOGMSG("Hello DLL_THREAD_ATTACH"); if(Dbg && Dbg->IsActive())Dbg->TryAddCurrThread(); //Dbg->Report_CREATE_THREAD_DEBUG_EVENT(NtCurrentThreadId()); // For a simple testing break; case DLL_THREAD_DETACH: - if(Dbg && Dbg->IsActive())Dbg->Report_EXIT_THREAD_DEBUG_EVENT(NtCurrentThreadId(),0); // For a simple testing + if(Dbg && Dbg->IsActive())Dbg->Report_EXIT_THREAD_DEBUG_EVENT(NtCurrentTeb(),0); // For a simple testing break; case DLL_PROCESS_DETACH: - if(Dbg && Dbg->IsActive())Dbg->Report_EXIT_PROCESS_DEBUG_EVENT(0); // For a simple testing + if(Dbg && Dbg->IsActive())Dbg->Report_EXIT_PROCESS_DEBUG_EVENT(NtCurrentTeb(),0); // For a simple testing UnInitApplication(); break; @@ -173,21 +216,28 @@ BOOL APIENTRY DLLMain(HMODULE hModule, DWORD ReasonCall, LPVOID lpReserved) return true; } //==================================================================================== -void _stdcall LoadConfiguration(void) -{ - CJSonItem Root; +void _stdcall LoadConfiguration(void) // Avoid any specific file access here for now +{ +#ifdef _DEBUG + LogMode = lmFile; + // NSTR::StrCopy(LogFilePath, "C:\\TEST\\_LogMy.txt"); +#endif + +/* CJSonItem Root; CMiniStr str; str.FromFile(CfgFilePath); bool BinFmt = (str.Length())?(CJSonItem::IsBinaryEncrypted(str.c_data()) >= 0):(0); - LOGMSG("Loading config(Bin=%u): %ls", BinFmt, &CfgFilePath); + DBGMSG("Loading config(Bin=%u): %ls", BinFmt, &CfgFilePath); if(str.Length())Root.FromString(str); CJSonItem* Params = EnsureJsnParam(jsObject, "Parameters", &Root); LogMode = EnsureJsnParam((int)LogMode, "LogMode", Params)->GetValInt(); // lmCons;// - IPCSize = EnsureJsnParam(IPCSize, "IPCSize", Params)->GetValInt(); + IPCSize = EnsureJsnParam(IPCSize, "IPCSize", Params)->GetValInt(); + SuspMainThAtLd = EnsureJsnParam(SuspMainThAtLd, "SuspMainThAtLd", Params)->GetValBol(); //HideDllProxy = EnsureJsnParam(HideDllProxy, "HideDllProxy", Params)->GetValBol(); //HideDllProxyDsk = EnsureJsnParam(HideDllProxyDsk, "HideDllProxyDsk", Params)->GetValBol(); AllowEjectOnDetach = EnsureJsnParam(AllowEjectOnDetach, "AllowEjectOnDetach", Params)->GetValBol(); - // if(LogMode == lmCons)AllocConsole(); +// if(LogMode & lmCons){AllocConsole();} // SetWinConsoleSizes(1000, 500, 1000, 500); + CJSonItem* DbgParams = EnsureJsnParam(jsObject, "DbgClient", &Root); if(Dbg) { @@ -199,24 +249,25 @@ void _stdcall LoadConfiguration(void) Dbg->OnlyOwnTF = EnsureJsnParam(Dbg->OnlyOwnTF, "OnlyOwnTF", DbgParams)->GetValBol(); Dbg->SwBpVal = EnsureJsnParam((UINT)Dbg->SwBpVal, "SwBpVal", DbgParams)->GetValBol(); } - LOGMSG("Saving config(Bin=%u): %ls", BinFmt, &CfgFilePath); + DBGMSG("Saving config(Bin=%u): %ls", BinFmt, &CfgFilePath); str.Clear(); if(BinFmt)Root.ToBinary(str,true); Root.ToString(str,true); - str.ToFile(CfgFilePath); + str.ToFile(CfgFilePath); */ } //------------------------------------------------------------------------------------ void _stdcall SaveConfiguration(int BinFmt) { - CJSonItem Root; +/* CJSonItem Root; CMiniStr str; str.FromFile(CfgFilePath); bool VBinFmt = (str.Length() || (BinFmt < 0))?(CJSonItem::IsBinaryEncrypted(str.c_data()) >= 0):(BinFmt > 0); - LOGMSG("Loading config(Bin=%u): %ls", VBinFmt, &CfgFilePath); + DBGMSG("Loading config(Bin=%u): %ls", VBinFmt, &CfgFilePath); if(str.Length())Root.FromString(str); CJSonItem* Params = EnsureJsnParam(jsObject, "Parameters", &Root); LogMode = SetJsnParamValue((int)LogMode, "LogMode", Params)->GetValInt(); IPCSize = SetJsnParamValue(IPCSize, "IPCSize", Params)->GetValInt(); + SuspMainThAtLd = SetJsnParamValue(SuspMainThAtLd, "SuspMainThAtLd", Params)->GetValBol(); //HideDllProxy = SetJsnParamValue(HideDllProxy, "HideDllProxy", Params)->GetValBol(); //HideDllProxyDsk = SetJsnParamValue(HideDllProxyDsk, "HideDllProxyDsk", Params)->GetValBol(); AllowEjectOnDetach = SetJsnParamValue(AllowEjectOnDetach, "AllowEjectOnDetach", Params)->GetValBol(); @@ -232,66 +283,71 @@ void _stdcall SaveConfiguration(int BinFmt) SetJsnParamValue(Dbg->OnlyOwnTF, "OnlyOwnTF", DbgParams)->GetValBol(); SetJsnParamValue((UINT)Dbg->SwBpVal, "SwBpVal", DbgParams)->GetValBol(); } - LOGMSG("Saving config(Bin=%u): %ls", BinFmt, &CfgFilePath); + DBGMSG("Saving config(Bin=%u): %ls", BinFmt, &CfgFilePath); str.Clear(); if(VBinFmt)Root.ToBinary(str,true); Root.ToString(str,true); - str.ToFile(CfgFilePath); + str.ToFile(CfgFilePath); */ } //------------------------------------------------------------------------------------ bool _stdcall InitApplication(void) { - LOGMSG("Enter"); - if(GhDbg::CDbgClient::IsExistForID(GetCurrentProcessId())){LOGMSG("Already injected!"); return false;} + DBGMSG("Enter"); + if(GhDbg::CDbgClient::IsExistForID(NtCurrentProcessId())){DBGMSG("Already injected!"); return false;} /*#ifdef _AMD64_ - HookRtlRestoreContext.SetHook("RtlRestoreContext","ntdll.dll"); + HookRtlRestoreContext.SetHook("RtlRestoreContext","ntdll.dll"); // NtContinue #endif HookKiUserExceptionDispatcher.SetHook("KiUserExceptionDispatcher","ntdll.dll"); HookLdrInitializeThunk.SetHook("LdrInitializeThunk","ntdll.dll"); */ - Dbg = new GhDbg::CDbgClient; + Dbg = new ((void*)&ArrDbgClient) GhDbg::CDbgClient(ThisLibBase); Dbg->UsrReqCallback = &DbgUsrReqCallback; - LoadConfiguration(); - LOGMSG("IPC created: IPCSize=%u",IPCSize); - HookNtMapViewOfSection.SetHook("NtMapViewOfSection","ntdll.dll"); - HookNtUnmapViewOfSection.SetHook("NtUnmapViewOfSection","ntdll.dll"); - HookNtGetContextThread.SetHook("NtGetContextThread","ntdll.dll"); - HookNtSetContextThread.SetHook("NtSetContextThread","ntdll.dll"); - HookNtTerminateThread.SetHook("NtTerminateThread","ntdll.dll"); -// HookNtTerminateProcess.SetHook("NtTerminateProcess","ntdll.dll"); // Only for ProxyRestore to disk - HookNtContinue.SetHook("NtContinue","ntdll.dll"); - ExpDispHook.SetHook(ProcExpDispBefore, ProcExpDispAfter); - LOGMSG("Hooks set"); - Dbg->Start(IPCSize, hIpcTh); // Start it from DLL Main to avoid of similair DLL being loaded again - LOGMSG("IPC started"); +////////// LoadConfiguration(); + DBGMSG("IPC created: IPCSize=%u",IPCSize); + PVOID pNtDll = GetNtDllBaseFast(); + DBGMSG("NtDllBase: %p",pNtDll); + HookNtMapViewOfSection.SetHook(GetProcAddr(pNtDll, ctENCSA("NtMapViewOfSection"))); // For DLLs list + HookNtUnmapViewOfSection.SetHook(GetProcAddr(pNtDll, ctENCSA("NtUnmapViewOfSection"))); // For DLLs list + HookNtGetContextThread.SetHook(GetProcAddr(pNtDll, ctENCSA("NtGetContextThread"))); // For DRx hiding + HookNtSetContextThread.SetHook(GetProcAddr(pNtDll, ctENCSA("NtSetContextThread"))); // For DRx hiding + HookNtTerminateThread.SetHook(GetProcAddr(pNtDll, ctENCSA("NtTerminateThread"))); // For Thread list update + HookNtTerminateProcess.SetHook(GetProcAddr(pNtDll, ctENCSA("NtTerminateProcess"))); // Importand for latest Windows 10 bugs + HookNtContinue.SetHook(GetProcAddr(pNtDll, ctENCSA("NtContinue"))); // For Thread list update // TODO: Replace with LdrInitializeThunk hook + ExpDispHook.SetHook(ProcExpDispBefore, ProcExpDispAfter); // Debugger core function + LdrpInitHook.SetHook(ProcLdrpInitialize); // Optional: HookNtContinue can do the job but threads will be reported after initialization + DBGMSG("Hooks set: hIpcTh=%p, MainThId=%u",hIpcTh, MainThId); + Dbg->Start(IPCSize, hIpcTh, NULL, MainThId, (hIpcTh != NtCurrentThread)?NtCurrentThreadId():0); // Start it from DLL Main to avoid of similair DLL being loaded again // Exclude current temporary thread + DBGMSG("IPC started"); return true; } //------------------------------------------------------------------------------------ void _stdcall UnInitApplication(void) -{ +{ + DBGMSG("Enter"); + if(Dbg)Dbg->~CDbgClient(); // delete(Dbg); // Compiler will ALWAYS put an unused call to operator DELETE here if called 'Dbg->~CDbgClient()' in Release build if not specified '/MTd'(Multi-Threaded Debug) but it will define '_DEBUG to 1'! + DBGMSG("IPC destroyed"); HookNtContinue.Remove(); HookNtTerminateThread.Remove(); - //HookNtTerminateProcess.Remove(); + HookNtTerminateProcess.Remove(); HookNtUnmapViewOfSection.Remove(); HookNtMapViewOfSection.Remove(); HookNtSetContextThread.Remove(); HookNtGetContextThread.Remove(); + LdrpInitHook.Remove(); ExpDispHook.Remove(); - LOGMSG("Hooks removed"); - if(Dbg)delete(Dbg); - LOGMSG("IPC destroyed"); + DBGMSG("Hooks removed"); } //------------------------------------------------------------------------------------ -int _stdcall DbgUsrReqCallback(ShMem::CMessageIPC::SMsgHdr* Req, PVOID ArgA, UINT ArgB) +int _fastcall DbgUsrReqCallback(ShMem::CMessageIPC::SMsgHdr* Req, PVOID ArgA, UINT ArgB) { if(Req->MsgID == GhDbg::miDbgGetConfigs) { ShMem::CArgPack<>* apo = (ShMem::CArgPack<>*)ArgA; // apo->PushArgEx(HideDllProxy, "Hide Proxy DLL (After Restart)", GhDbg::CDbgClient::MakeCfgItemID(++ArgB,GhDbg::dtBool)); // apo->PushArgEx(HideDllProxyDsk, "Hide Proxy DLL on Disk (After Restart)", GhDbg::CDbgClient::MakeCfgItemID(++ArgB,GhDbg::dtBool)); - if(ModInjected)apo->PushArgEx(AllowEjectOnDetach, "Allow Eject On Detach", GhDbg::CDbgClient::MakeCfgItemID(++ArgB,GhDbg::dtBool)); - if(ModInjected){bool Nons = false; apo->PushArgEx(Nons, "Eject", GhDbg::CDbgClient::MakeCfgItemID(++ArgB,GhDbg::dtBool));} + if(!ModInjFlags)apo->PushArgEx(AllowEjectOnDetach, ctENCSA("Allow Eject On Detach"), GhDbg::CDbgClient::MakeCfgItemID(++ArgB,GhDbg::dtBool)); + if(!ModInjFlags){bool Nons = false; apo->PushArgEx(Nons, ctENCSA("Eject"), GhDbg::CDbgClient::MakeCfgItemID(++ArgB,GhDbg::dtBool));} return ArgB; } if(Req->MsgID == GhDbg::miDbgSetConfigs) @@ -312,12 +368,12 @@ int _stdcall DbgUsrReqCallback(ShMem::CMessageIPC::SMsgHdr* Req, PVOID ArgA, UIN AllowEjectOnDetach = *(bool*)ArgA; break; case 2: - if(ModInjected) + if(!ModInjFlags) { - LOGMSG("Ejecting by user!"); + DBGMSG("Ejecting by user!"); UnInitApplication(); - LOGMSG("Uninit done. Unmapping..."); - InjLdr::UnmapAndTerminateSelf(ThisLibBase); + DBGMSG("Uninit done. Unmapping..."); + NtTerminateThread(NtCurrentThread, 0); //// InjLdr::UnmapAndTerminateSelf(ThisLibBase); // TODO: Self unmap or deallocate } break; } @@ -327,12 +383,12 @@ int _stdcall DbgUsrReqCallback(ShMem::CMessageIPC::SMsgHdr* Req, PVOID ArgA, UIN } if(Req->MsgID == GhDbg::miDbgDetachNtfy) { - if(AllowEjectOnDetach && ModInjected) + if(AllowEjectOnDetach && !ModInjFlags) { - LOGMSG("Ejecting on Detach!"); + DBGMSG("Ejecting on Detach!"); UnInitApplication(); - LOGMSG("Uninit done. Unmapping..."); - InjLdr::UnmapAndTerminateSelf(ThisLibBase); + DBGMSG("Uninit done. Unmapping..."); + NtTerminateThread(NtCurrentThread, 0); //// InjLdr::UnmapAndTerminateSelf(ThisLibBase); // TODO: Self unmap or deallocate } } return 0; @@ -372,6 +428,12 @@ void NTAPI ProcLdrInitializeThunk(PVOID ArgA, PVOID ArgB, PVOID ArgC, PVOID ArgD HookLdrInitializeThunk.OrigProc(ArgA, ArgB, ArgC, ArgD); // Must be tail optimized - Requires optimization to be enabled (O1,O2,Ox) } */ //------------------------------------------------------------------------------------ +void _stdcall ProcLdrpInitialize(volatile PCONTEXT Ctx, volatile PVOID NtDllBase) +{ + DBGMSG("RetAddr=%p, Ctx=%p, NtDllBase=%p",_ReturnAddress(),Ctx,NtDllBase); +// if(Dbg && Dbg->IsActive()){LastThID = NtCurrentThreadId(); Dbg->TryAddCurrThread();} // LastThID prevents TryAddCurrThread from ProcNtContinue +} +//------------------------------------------------------------------------------------ /* x64 RSP+00 = RetAddr RSP+08 = RCX @@ -388,10 +450,10 @@ RSP+20 = R9 */ bool _cdecl ProcExpDispBefore(volatile PVOID ArgA, volatile PVOID ArgB, volatile PVOID ArgC, volatile PVOID ArgD, volatile PVOID RetVal) { - DBGMSG("Code=%08X, Addr=%p, FCtx=%08X",((PEXCEPTION_RECORD)ArgA)->ExceptionCode, ((PEXCEPTION_RECORD)ArgA)->ExceptionAddress, ((PCONTEXT)ArgB)->ContextFlags); +// DBGMSG("Code=%08X, Addr=%p, FCtx=%08X",((PEXCEPTION_RECORD)ArgA)->ExceptionCode, ((PEXCEPTION_RECORD)ArgA)->ExceptionAddress, ((PCONTEXT)ArgB)->ContextFlags); DWORD ThID = LastExcThID = NtCurrentThreadId(); if(!Dbg || !Dbg->IsActive() || Dbg->IsDbgThreadID(ThID))return true; - if(Dbg->HandleException(ThID, (PEXCEPTION_RECORD)ArgA, (PCONTEXT)ArgB)){RetVal = (PVOID)TRUE; DBGMSG("Handled!"); return false;} // Handled by a debugger + if(Dbg->HandleException(ThID, (PEXCEPTION_RECORD)ArgA, (PCONTEXT)ArgB)){RetVal = (PVOID)TRUE; /*DBGMSG("Handled!");*/ return false;} // Handled by a debugger if(!Dbg->HideDbgState)return true; // CONTEXT ForgedCtx; // No debugger context hiding for now :( // Can it be detected that this is a copy of original CONTEXT and have a different address on stack? @@ -403,8 +465,8 @@ bool _cdecl ProcExpDispBefore(volatile PVOID ArgA, volatile PVOID ArgB, volatile //------------------------------------------------------------------------------------ bool _cdecl ProcExpDispAfter(volatile PVOID ArgA, volatile PVOID ArgB, volatile PVOID ArgC, volatile PVOID ArgD, volatile PVOID RetVal) { - DBGMSG("Exiting!"); -// Dbg->DebugThreadSave(ThID, &ForgedCtx); // Save any modifications to DRx in a separate struct +// DBGMSG("Exiting!"); +// Dbg->DebugThreadSave(ThID, &ForgedCtx); // Save any modifications to DRx in a separate struct // NOTE: It is rare that a AntiDebug check will use an exception handlers to check DRx? // Dbg->DebugRstExcContext(ContextRecord, &ForgedCtx); return true; } @@ -416,50 +478,57 @@ bool _cdecl ProcExpDispAfter(volatile PVOID ArgA, volatile PVOID ArgB, volatile // Normal Dll map: AllocationType=00800000[MEM_ROTATE], Win32Protect=00000004[PAGE_READWRITE] // Win10 // // WinXPx32: ZwMapViewOfSection(v88, -1, (int)&v89, 0, 0, 0, (int)&v86, 1, 0, 4); -// Win7x64: ZwMapViewOfSection(v9, -1i64, v13, 0i64, 0i64, 0i64, v12, 1, v10, 4); +// Win7x64: ZwMapViewOfSection(v9, -1i64, v13, 0i64, 0i64, 0i64, v12, 1, v10, 4); // NTSTATUS NTAPI ProcNtMapViewOfSection(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Win32Protect) // NOTE: A detectable hook! { - NTSTATUS res = HookNtMapViewOfSection.OrigProc(SectionHandle,ProcessHandle,BaseAddress,ZeroBits,CommitSize,SectionOffset,ViewSize,InheritDisposition,AllocationType,Win32Protect); - if(!res && BaseAddress && *BaseAddress && ViewSize && *ViewSize && Dbg && Dbg->IsActive() && GhDbg::IsCurrentProcess(ProcessHandle) && IsValidPEHeaderBlk(*BaseAddress, Dbg->IsMemAvailable(*BaseAddress))) // Try to get the module`s name? + NTSTATUS res = HookNtMapViewOfSection.OrigProc(SectionHandle,ProcessHandle,BaseAddress,ZeroBits,CommitSize,SectionOffset,ViewSize,InheritDisposition,AllocationType,Win32Protect); // May return STATUS_IMAGE_NOT_AT_BASE + if((res >= 0) && BaseAddress && *BaseAddress && ViewSize && *ViewSize) // && Dbg && Dbg->IsActive() && GhDbg::IsCurrentProcess(ProcessHandle) && IsValidPEHeaderBlk(*BaseAddress, Dbg->IsMemAvailable(*BaseAddress))) // Try to get the module`s name? { - DBGMSG("Module: Status=%08X, SectionHandle=%p, BaseAddress=%p, ViewSize=%08X, AllocationType=%08X, Win32Protect=%08X",res,SectionHandle,*BaseAddress,*ViewSize,AllocationType,Win32Protect); - if(Dbg && Dbg->IsActive() && (Win32Protect == PAGE_READWRITE)) // <<< Duplicate mapping causes BPs to be set again and never removed if this module is already loaded(If this is not caused by LdrLoadDll)! + DBGMSG("Module: Status=%08X, SectionHandle=%p, BaseAddress=%p, ViewSize=%08X, AllocationType=%08X, Win32Protect=%08X",res,SectionHandle,*BaseAddress,*ViewSize,AllocationType,Win32Protect); + if(Dbg && Dbg->IsActive() && (Win32Protect == PAGE_READWRITE) && NNTDLL::IsCurrentProcess(ProcessHandle) && IsValidPEHeaderBlk(*BaseAddress, Dbg->IsMemAvailable(*BaseAddress))) // <<< Duplicate mapping causes BPs to be set again and never removed if this module is already loaded(If this is not caused by LdrLoadDll)! { - Dbg->Report_LOAD_DLL_DEBUG_INFO(*BaseAddress); // NOTE: This is done before PE configuration by LdrLoadDll // Events:TLS Callbacks must be disabled or xg4dbg will crash in 'cbLoadDll{ auto modInfo = ModInfoFromAddr(duint(base));}' (because it won`t check for NULL) if this mapping will be unmapped too soon + Dbg->Report_LOAD_DLL_DEBUG_INFO(NtCurrentTeb(), *BaseAddress); // NOTE: This is done before PE configuration by LdrLoadDll // Events:TLS Callbacks must be disabled or xg4dbg will crash in 'cbLoadDll{ auto modInfo = ModInfoFromAddr(duint(base));}' (because it won`t check for NULL) if this mapping will be unmapped too soon } } -// else {LOGMSG("Status=%08X, SectionHandle=%p, ViewSize=%08X, AllocationType=%08X, Win32Protect=%08X",res,SectionHandle,ViewSize,AllocationType,Win32Protect);} +// else {DBGMSG("Status=%08X, SectionHandle=%p, ViewSize=%08X, AllocationType=%08X, Win32Protect=%08X",res,SectionHandle,ViewSize,AllocationType,Win32Protect);} return res; } //------------------------------------------------------------------------------------ NTSTATUS NTAPI ProcNtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress) // NOTE: A detectable hook! { - if(GhDbg::IsCurrentProcess(ProcessHandle) && IsValidPEHeaderBlk(BaseAddress, Dbg->IsMemAvailable(BaseAddress))) + if(NNTDLL::IsCurrentProcess(ProcessHandle) && IsValidPEHeaderBlk(BaseAddress, Dbg->IsMemAvailable(BaseAddress))) { - DBGMSG("BaseAddress=%p",BaseAddress); - if(Dbg && Dbg->IsActive() && Dbg->IsOtherConnections())Dbg->Report_UNLOAD_DLL_DEBUG_EVENT(BaseAddress); + DBGMSG("BaseAddress=%p",BaseAddress); + if(Dbg && Dbg->IsActive() && Dbg->IsOtherConnections())Dbg->Report_UNLOAD_DLL_DEBUG_EVENT(NtCurrentTeb(), BaseAddress); } return HookNtUnmapViewOfSection.OrigProc(ProcessHandle,BaseAddress); } //------------------------------------------------------------------------------------ -// Called at start of a thread and at return from APC/Exception -// Protect CONTEXT here? Can be used separately from any kernel callback? +// Called at start of a thread(After initialization) and at return from APC/Exception +// Protect CONTEXT here? Can be used separately from any kernel callback? // Is someone using it for current thread`s CONTEXT modification(DRx corruption)? // On Win10 x64 it is called by RtlRestoreContext for normal exceptions but it is not used on Win7 x64 // On x32 it is called from LdrInitializeThunk when a new thread created (User mode thread`s entry point) +// LdrInitializeThunk exits with NtContinue // Hooking LdrInitializeThunk is hard // NTSTATUS NTAPI ProcNtContinue(PCONTEXT ContextRecord, BOOLEAN TestAlert) // NOTE: A detectable hook! // NOTE: Too much overhead of exception processing with this(Twice 'GetThread' on breakpoints) { - static DWORD LastThID = -1; DWORD CurrThID = NtCurrentThreadId(); - if(Dbg && (CurrThID != LastThID) && (CurrThID != LastExcThID) && Dbg->IsActive())Dbg->TryAddCurrThread(); // Report this thread if it is not in list yet + if(Dbg && (CurrThID != LastThID) && (CurrThID != LastExcThID) && Dbg->IsActive()){LastThID=CurrThID; Dbg->TryAddCurrThread();} // Report this thread if it is not in list yet return HookNtContinue.OrigProc(ContextRecord, TestAlert); // Will not return } //------------------------------------------------------------------------------------ -/*NTSTATUS NTAPI ProcNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus) // DISABLED: Just let IPC to timeout +// ProcessHandle is NULL then terminates all threads, except a current one +// RtlExitUserProcess: NtTerminateProcess(NULL), NtTerminateProcess(NtCurrentProcess) +// On Win 10 (2019) some suspended threads won`t be terminated! +// Some race condition with NtSuspendThread and NtTerminateProcess when called from different threads at almost same time? +// And they will be suspended when reporting i.e. DLL_UNLOAD, but GhostDbg thread already dead and can`t unfreeze these threads +// Could be a useful feature of NtSuspendProcess ;) +NTSTATUS NTAPI ProcNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus) { - if(RstDskHiddenProxy && ProxyDllCopy) // Restore the Proxy Dll on disk + DBGMSG("ProcessHandle=%p, ExitStatus=%08X",ProcessHandle,ExitStatus); +/* if(RstDskHiddenProxy && ProxyDllCopy) // Restore the Proxy Dll on disk { BYTE DllPath[MAX_PATH]; for(UINT ctr=0,total=ProxyDllSize+MAX_PATH;ctr < total;ctr++)ProxyDllCopy[ctr] = DecryptByteWithCtr(ProxyDllCopy[ctr], ProxyEncKey, ctr); @@ -472,38 +541,45 @@ NTSTATUS NTAPI ProcNtContinue(PCONTEXT ContextRecord, BOOLEAN TestAlert) // NO CloseHandle(hFile); VirtualFree(ProxyDllCopy,0,MEM_RELEASE); ProxyDllCopy = NULL; - LOGMSG("ProxyDll Restored: %s", (LPSTR)&DllPath); + DBGMSG("ProxyDll Restored: %s", (LPSTR)&DllPath); } + } */ + if(Dbg && Dbg->IsActive() && (!ProcessHandle || (ProcessHandle == NtCurrentProcess))) + { + if(!ProcessHandle)Dbg->Report_EXIT_PROCESS_DEBUG_EVENT(NtCurrentTeb(),0); // (ProcessHandle==NULL) will terminate all other threads, including GhostDbg + else UnInitApplication(); // Do not report EXIT_PROCESS_DEBUG_EVENT second time! } return HookNtTerminateProcess.OrigProc(ProcessHandle, ExitStatus); -} */ +} //------------------------------------------------------------------------------------ // Exit from a thread`s proc will also end up here // ThreadHandle is NULL for a current thread; NtCurrentThread is also works NTSTATUS NTAPI ProcNtTerminateThread(HANDLE ThreadHandle, NTSTATUS ExitStatus) // NOTE: A detectable hook! { - ULONG ThID; - if(Dbg && Dbg->IsActive() && (ThID=GhDbg::GetCurrProcessThreadID(ThreadHandle)))Dbg->Report_EXIT_THREAD_DEBUG_EVENT(ThID,ExitStatus); + PTEB teb = NULL; + DBGMSG("ThreadHandle=%p",ThreadHandle); + if(Dbg && Dbg->IsActive() && (teb=NNTDLL::GetCurrProcessTEB(ThreadHandle))){ Dbg->Report_EXIT_THREAD_DEBUG_EVENT(teb,ExitStatus); } + DBGMSG("Terminating: %p, %u",teb,(teb?(UINT)teb->ClientId.UniqueThread:0)); return HookNtTerminateThread.OrigProc(ThreadHandle, ExitStatus); // TODO: Just call our own NtTerminateThread } //------------------------------------------------------------------------------------ NTSTATUS NTAPI ProcNtGetContextThread(HANDLE ThreadHandle, PCONTEXT Context) // NOTE: A detectable hook! { ULONG ThID; - NTSTATUS res = HookNtGetContextThread.OrigProc(ThreadHandle, Context); // TODO: Just call our own NtGetContextThread - if(!res && Dbg && Dbg->IsActive() && Dbg->HideDbgState && (ThID=GhDbg::GetCurrProcessThreadID(ThreadHandle)))Dbg->DebugThreadLoad(ThID, Context); // Load into CONTEXT a previously saved DRx instead of currently read ones + NTSTATUS res = HookNtGetContextThread.OrigProc(ThreadHandle, Context); // TODO: Just call our own NtGetContextThread(What if it is hooked by someone)? + if(!res && Dbg && Dbg->IsActive() && Dbg->HideDbgState && (ThID=NNTDLL::GetCurrProcessThreadID(ThreadHandle)))Dbg->DebugThreadLoad(ThID, Context); // Load into CONTEXT a previously saved DRx instead of currently read ones return res; } //------------------------------------------------------------------------------------ NTSTATUS NTAPI ProcNtSetContextThread(HANDLE ThreadHandle, PCONTEXT Context) // NOTE: A detectable hook! // Do not let DRx to be changed by this { ULONG ThID; - if(!Dbg || !Dbg->IsActive() || !Dbg->HideDbgState || !(ThID=GhDbg::GetCurrProcessThreadID(ThreadHandle)))return HookNtSetContextThread.OrigProc(ThreadHandle, Context); // TODO: Just call our own NtSetContextThread + if(!Dbg || !Dbg->IsActive() || !Dbg->HideDbgState || !(ThID=NNTDLL::GetCurrProcessThreadID(ThreadHandle)))return HookNtSetContextThread.OrigProc(ThreadHandle, Context); // TODO: Just call our own NtSetContextThread CONTEXT FCtx; // Copy of CONTEXT where CONTEXT_DEBUG_REGISTERS is removed (CONTEXT_DEBUG_REGISTERS must be preserved in original Context in case it may be checked) Dbg->DebugThreadSave(ThID, Context); // Save any magic numbers which may be stored in debug registers to detect a debugger memcpy(&FCtx,Context,sizeof(CONTEXT)); FCtx.ContextFlags &= ~0x00000010; // CONTEXT_DEBUG_REGISTERS // TF is allowed to change? - return HookNtSetContextThread.OrigProc(ThreadHandle, &FCtx); // TODO: Just call our own NtSetContextThread + return HookNtSetContextThread.OrigProc(ThreadHandle, &FCtx); // TODO: Just call our own NtSetContextThread(What if it is hooked by someone)? } //------------------------------------------------------------------------------------ diff --git a/InjectLib/InjectDll.h b/InjectLib/InjectDll.h index e5721d1..8fcc6cc 100644 --- a/InjectLib/InjectDll.h +++ b/InjectLib/InjectDll.h @@ -1,15 +1,29 @@ #pragma once - +/* + Copyright (c) 2020 Victor Sheinmann, Vicshann@gmail.com + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + #include -#include +//#include #include "Utils.h" #include "UniHook.hpp" #include "json.h" -#include "FormatPE.h" +#include "NtDllEx.hpp" #include "CompileTime.hpp" #include "InjDllLdr.hpp" #include "GhostDbg.hpp" +#include "..\..\GlobalInjector\GInjer\LoaderCode.h" //==================================================================================== #define CFGFILE ".InjLib.jsn" @@ -20,15 +34,16 @@ void _stdcall LoadConfiguration(void); void _stdcall SaveConfiguration(int BinFmt=-1); void _stdcall UnInitApplication(void); bool _stdcall InitApplication(void); -int _stdcall DbgUsrReqCallback(ShMem::CMessageIPC::SMsgHdr* Req, PVOID ArgA, UINT ArgB); +int _fastcall DbgUsrReqCallback(ShMem::CMessageIPC::SMsgHdr* Req, PVOID ArgA, UINT ArgB); //------------------------------------------------------------------------------------ bool _cdecl ProcExpDispBefore(volatile PVOID ArgA, volatile PVOID ArgB, volatile PVOID ArgC, volatile PVOID ArgD, volatile PVOID RetVal); bool _cdecl ProcExpDispAfter(volatile PVOID ArgA, volatile PVOID ArgB, volatile PVOID ArgC, volatile PVOID ArgD, volatile PVOID RetVal); //__declspec(noreturn) VOID NTAPI ProcRtlRestoreContext(PCONTEXT ContextRecord, PEXCEPTION_RECORD ExceptionRecord); //__declspec(noreturn) void _fastcall ProcKiUserExceptionDispatcher(void); //__declspec(noreturn) void NTAPI ProcLdrInitializeThunk(PVOID ArgA, PVOID ArgB, PVOID ArgC, PVOID ArgD); +void _stdcall ProcLdrpInitialize(volatile PCONTEXT Ctx, volatile PVOID NtDllBase); NTSTATUS NTAPI ProcNtContinue(PCONTEXT ContextRecord, BOOLEAN TestAlert); -//NTSTATUS NTAPI ProcNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus); +NTSTATUS NTAPI ProcNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus); NTSTATUS NTAPI ProcNtTerminateThread(HANDLE ThreadHandle, NTSTATUS ExitStatus); NTSTATUS NTAPI ProcNtGetContextThread(HANDLE ThreadHandle, PCONTEXT Context); NTSTATUS NTAPI ProcNtSetContextThread(HANDLE ThreadHandle, PCONTEXT Context); diff --git a/InjectLib/InjectDll.vcxproj b/InjectLib/InjectDll.vcxproj index 5d7d67d..d3c91f4 100644 --- a/InjectLib/InjectDll.vcxproj +++ b/InjectLib/InjectDll.vcxproj @@ -112,30 +112,31 @@ - Disabled + Full Speed $(SolutionDir)COMMON\;$(SolutionDir)COMMON\ThirdParty\;$(SolutionDir)COMMON\ModuleTools\;$(SolutionDir)COMMON\ThirdParty\ntdll\;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;_NODESTR;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) false false Default MultiThreadedDebug - - + Default false - StreamingSIMDExtensions + StreamingSIMDExtensions2 false NotUsing Level3 false ProgramDatabase - StdCall + FastCall false true true true OnlyExplicitInline stdcpplatest + /Gs100000000 %(AdditionalOptions) + false LinkVerboseLib @@ -172,24 +173,23 @@ - Disabled + Full Speed $(SolutionDir)COMMON\;$(SolutionDir)COMMON\ThirdParty\;$(SolutionDir)COMMON\ModuleTools\;$(SolutionDir)COMMON\ThirdParty\ntdll\;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;_NODESTR;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) false false Default MultiThreadedDebug - - + Default false - StreamingSIMDExtensions + NotSet false NotUsing Level3 false ProgramDatabase - StdCall + FastCall false true true @@ -197,6 +197,8 @@ false OnlyExplicitInline stdcpplatest + /Gs100000000 %(AdditionalOptions) + false LinkVerboseLib @@ -235,24 +237,25 @@ true false $(SolutionDir)COMMON\;$(SolutionDir)COMMON\ThirdParty\;$(SolutionDir)COMMON\ModuleTools\;$(SolutionDir)COMMON\ThirdParty\ntdll\;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;_NODESTR;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true false MultiThreaded - - + Default false - StreamingSIMDExtensions + StreamingSIMDExtensions2 false NotUsing Level3 false - StdCall - CompileAsCpp + FastCall + Default true stdcpplatest + /Gs100000000 %(AdditionalOptions) + false LinkVerboseLib @@ -297,24 +300,25 @@ copy /Y "$(OutDir)$(TargetName)$(TargetExt)" "$(SolutionDir)BUILD\RELEASE\$(Solu true false $(SolutionDir)COMMON\;$(SolutionDir)COMMON\ThirdParty\;$(SolutionDir)COMMON\ModuleTools\;$(SolutionDir)COMMON\ThirdParty\ntdll\;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;_NODESTR;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true false MultiThreaded - - + Default false - StreamingSIMDExtensions + NotSet false NotUsing Level3 false - StdCall - CompileAsCpp + FastCall + Default true stdcpplatest + /Gs100000000 %(AdditionalOptions) + false LinkVerboseLib @@ -362,6 +366,7 @@ copy /Y "$(OutDir)$(TargetName)$(TargetExt)" "$(SolutionDir)BUILD\RELEASE\$(Solu + diff --git a/InjectLib/InjectDll.vcxproj.filters b/InjectLib/InjectDll.vcxproj.filters index 7f6358c..49aacea 100644 --- a/InjectLib/InjectDll.vcxproj.filters +++ b/InjectLib/InjectDll.vcxproj.filters @@ -65,5 +65,8 @@ Common + + Common + \ No newline at end of file diff --git a/NOTES.txt b/NOTES.txt index 7290ed1..3134a17 100644 --- a/NOTES.txt +++ b/NOTES.txt @@ -15,24 +15,98 @@ ETHREAD -> StartAddress ? https://www.codeproject.com/Articles/543542/Windows-x-system-service-hooks-and-advanced-debu + https://www.codeproject.com/Articles/543542/Windows-x64-system-service-hooks-and-advanced-debu TODO: - Unload inject DLL if it was loaded by a debugger and it is going to detach + Unload inject DLL if it was loaded by a debugger and it is going to detach? Intercept Any exception (Optional) - Start target as Explorer.exe + Start a target as Explorer.exe Hardware BP only for an active thread (Last for GetThreadContext?) Inject into child processes - Block constant Thread Suspend/Resume calls except for BP setting - Kernel exception dispatcer hook(No hook of KiUserExceptionDispatcher and NtContinue) - Use unly a low level WinAPI in GhostDbg.hpp + Block constant Thread Suspend/Resume calls by x64Dbg if it is already in DbgEvent handler? + Kernel exception dispatcher hook(No hook of KiUserExceptionDispatcher and NtContinue) (GhostDrv) + Make DebugBreak less intrusive (No CreateThread?) (APC?) + Alternate software BP support? + Single IPC buffer for all GhostDbg clients (Required for GhostDrv) + IPC SRW locks + Enable Config files + IDA compatibility + Fix NativeCreateThread on latest Windows 10 + Fix extreme slowness on Windows XP (Sync problem? Fix for GhostDrv) // https://communities.vmware.com/thread/466749 + GInjer compatibility (Especially WOW64 debugging) ISSUES: - Software breakpoints is very dangerous to set + Software breakpoints is very dangerous to set if not all threads are suspended on a Debug Event Because of SEH recursion a DBG context protection is not used(Find a way to mark a thread with RefCtr) + +//----------------------------------------------------------------------------------------------------------------- + MSVC compiler will always generate ExceptionDirectory for x64 builds. Need to use CLANG to make InjLib smaller: '/clang:-fno-unwind-tables' +//--------------------------- + +BOOL IsWow64Process2(HANDLE hProcess, USHORT *pProcessMachine, USHORT *pNativeMachine) --> NTSTATUS RtlWow64GetProcessMachines(HANDLE hProcess, USHORT *pProcessMachine, USHORT *pNativeMachine); + //----------------------------------------------------------------------------------------------------------------- How DebugActiveProcess works: 1) Suspends all process` threads 2) Creates a remote thread at ntdll.dll:DbgUiRemoteBreakin - 3) Suspends all other process` threads again (Including at DbgUiRemoteBreakin) // Suspend count 1,2,2,2,... + 3) Suspends all other process` threads again (Including at DbgUiRemoteBreakin) // Suspend count is 1,2,2,2,... + + + ------------------------------------------ + https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-resumethread + + Note that while reporting debug events, all threads within the reporting process are frozen. + Debuggers are expected to use the SuspendThread and ResumeThread functions to limit the set of threads that can execute within a process. + By suspending all threads in a process except for the one reporting a debug event, it is possible to "single step" a single thread. + The other threads are not released by a continue operation if they are suspended. + + ----------------------------------------------------------------------- + _chkstk Routine is a helper routine for the C compiler. For x86 compilers, _chkstk Routine is called when the local variables exceed 4K bytes; for x64 compilers it is 8K. + + ------------------------------------- + RtlDispatchException hooking: + 1) Find a call to RtlDispatchException in KiUserExceptionDispatcher + 2) Put a jump to a stub at beginning of RtlDispatchException (Save original instructions) + + ---------------------------------------------------------------------- + __int64 __fastcall Wow64NtCreateThread(_QWORD *a1, unsigned int a2, __int64 a3, __int64 aProcessHandle, __int64 a5, CONTEXT *a6, __int64 a7, char aSuspended) +{ + void *vProcessHandle; // rbp + struct _OBJECT_ATTRIBUTES *v9; // r15 + unsigned int v10; // er14 + void **v11; // rbx + __int64 result; // rax + NTSTATUS vStatus; // edi + __int16 vMachine; // [rsp+40h] [rbp-538h] + CONTEXT Dst; // [rsp+50h] [rbp-528h] + vProcessHandle = (void *)aProcessHandle; + v9 = (struct _OBJECT_ATTRIBUTES *)a3; + v10 = a2; + v11 = (void **)a1; + if ( !a1 || !a7 || !a6 )return 0xC000000Di64; + result = RtlWow64GetProcessMachines(aProcessHandle, &vMachine, 0i64); + if ( (int)result < 0 )return result; + if ( vMachine )return 0xC0000022i64; // ??????????????????????????????? // Not IMAGE_FILE_MACHINE_UNKNOWN // IsWow64Process is TRUE + memset_0(&Dst, 0, 1232u); + Dst.Rip = LODWORD(a6->R8); + Dst.Rcx = LODWORD(a6->Rdi); + Dst.Rdx = HIDWORD(a6->Rbp); + Dst.R8 = HIDWORD(a6->R9); + Dst.ContextFlags = 0x100003; + vStatus = NtCreateThread(v11, v10, v9, vProcessHandle, (PCLIENT_ID)a5, &Dst, (PINITIAL_TEB)a7, 1u); + if ( vStatus < 0 )return (unsigned int)vStatus; + if ( vMachine == 0x14C && (unsigned __int16)RtlWow64GetCurrentMachine() == 0x14C )Wow64pCpuInitializeStartupContext((__int64)vProcessHandle, (__int64)*v11, (__int64)a6); + if ( !aSuspended ) + { + vStatus = NtResumeThread(*v11, 0i64); + if ( vStatus < 0 ) + { + NtTerminateThread(*v11, 0); + return (unsigned int)vStatus; + } + } + return 0i64; +} + ---------------------------------------------------------------------- diff --git a/XDbgPlugin/LogoIcon.ico b/XDbgPlugin/LogoIcon.ico new file mode 100644 index 0000000000000000000000000000000000000000..398b368cccca7c5e46c224ddb7b18f1e4a524d65 GIT binary patch literal 22486 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 literal 0 HcmV?d00001 diff --git a/XDbgPlugin/Resources.rc b/XDbgPlugin/Resources.rc index 6198aa8..ef3c3c0 100644 --- a/XDbgPlugin/Resources.rc +++ b/XDbgPlugin/Resources.rc @@ -7,7 +7,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT #pragma code_page(1251) #endif //_WIN32 - +5 ICON "LogoIcon.ico" MAINICON RCDATA "MainIcon.png" // ICON InjLib RCDATA INJLIBPATH @@ -16,8 +16,8 @@ InjLib RCDATA INJLIBPATH // Version // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,0,0 - PRODUCTVERSION 1,1,0,0 + FILEVERSION 2,1,0,0 + PRODUCTVERSION 2,1,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -35,12 +35,12 @@ BEGIN VALUE "Comments", "https://github.com/Vicshann" // Github page VALUE "CompanyName", "Vicshann" VALUE "FileDescription", "x64Dbg plugin" - VALUE "FileVersion", "0, 8, 0, 0" + VALUE "FileVersion", "2, 0, 0, 0" VALUE "InternalName", "GhostDbg" - VALUE "LegalCopyright", "Copyright (c) 2018 Vicshann" + VALUE "LegalCopyright", "Copyright (c) 2020 Vicshann" VALUE "OriginalFilename", "GhostDbg.dll" VALUE "ProductName", "GhostDbg" - VALUE "ProductVersion", "0, 8, 0, 0" + VALUE "ProductVersion", "2, 0, 0, 0" END END BLOCK "VarFileInfo" diff --git a/XDbgPlugin/XDbgPlugin.cpp b/XDbgPlugin/XDbgPlugin.cpp index cc77d39..ce90046 100644 --- a/XDbgPlugin/XDbgPlugin.cpp +++ b/XDbgPlugin/XDbgPlugin.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2018 Victor Sheinmann, Vicshann@gmail.com + Copyright (c) 2020 Victor Sheinmann, Vicshann@gmail.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, @@ -15,7 +15,6 @@ #include "XDbgPlugin.h" #include "_plugins.h" - #pragma comment(linker,"/ENTRY:DLLMain") #pragma comment(linker,"/NODEFAULTLIB") @@ -24,11 +23,12 @@ typedef ShMem SHM; typedef GhDbg XNI; // ---------- SETTINGS ------------------ -bool PLogOnly = false; // Just log usage of Debug API -bool PEnabled = false; -bool AllowInject = false; // Allow to load inject DLL into target process. Else only processes with injected DLLs will be visible -bool AllowInjNew = false; -UINT InjFlags = InjLdr::mfInjMap|InjLdr::mfRunRMTH; +bool PLogOnly = false; // Just log usage of Debug API +bool PEnabled = false; // Enable the GhostDbg plugin +bool AllowInject = true; // Allow to load inject DLL into a target process(Attach). Else only processes with already injected GhostDbg DLLs will be visible +bool AllowInjNew = true; // Allow to load inject DLL into a target process(Create). +bool SuspendProc = true; // It is safer to keep a target process suspended while IPC and GhostDbg Client initializing but some timeouts may be detected +UINT InjFlags = InjLdr::mfInjMap|InjLdr::mfRunRMTH|InjLdr::mfRawRMTH; UINT WaitForInj = 3000; //--------------------------------------- @@ -44,6 +44,7 @@ PHOOK(ProcNtGetContextThread) HookNtGetContextThread; PHOOK(ProcNtSetContextThread) HookNtSetContextThread; PHOOK(ProcNtReadVirtualMemory) HookNtReadVirtualMemory; PHOOK(ProcNtWriteVirtualMemory) HookNtWriteVirtualMemory; +PHOOK(ProcNtTerminateProcess) HookNtTerminateProcess; PHOOK(ProcNtTerminateThread) HookNtTerminateThread; PHOOK(ProcNtSuspendThread) HookNtSuspendThread; PHOOK(ProcNtResumeThread) HookNtResumeThread; @@ -54,20 +55,26 @@ PHOOK(ProcDebugActiveProcessStop) HookDebugActiveProcessStop; PHOOK(ProcWaitForDebugEvent) HookWaitForDebugEvent; PHOOK(ProcContinueDebugEvent) HookContinueDebugEvent; PHOOK(ProcDebugBreakProcess) HookDebugBreakProcess; -PHOOK(ProcTerminateProcess) HookTerminateProcess; PHOOK(ProcCreateProcessA) HookCreateProcessA; PHOOK(ProcCreateProcessW) HookCreateProcessW; +PHOOK(ProcIsWow64Process) HookIsWow64Process; volatile bool BreakWrk = false; SHM::CMessageIPC* DbgIPC = NULL; XNI::CThreadList* ThList = NULL; +PVOID NtDllBase = NULL; +ULONG NtDllSize = 0; HMODULE hInst = NULL; -DWORD DbgProcID = 0; +HANDLE hSuspTh = NULL; +HANDLE hLstProc = NULL; +DWORD DbgProcID = 0; +DWORD LstProcID = 0; // After termination, to prevent reopen try and wait on unavailable IPC HWND hXDbgWnd = NULL; int PluginHandle = -1; int DbgCliMenu = -1; -bool HooksInstalled = false; +bool DoDisconnAtTerm = false; +bool HooksInstalled = false; bool DbgCliFlags[32]; // Because there is no function to request a menu item`s checked state in X64DBG :( @@ -105,7 +112,7 @@ BOOL APIENTRY DLLMain(HMODULE hModule, DWORD ReasonCall, LPVOID lpReserved) LoadConfiguration(); if(LogMode & lmCons){AllocConsole();/*SetWinConsoleSizes(1000, 500, 1000, 500);*/} - LOGMSG("Starting up... (Time=%08X), Owner='%ls'", (DWORD)GetTime64(),&StartUpDir); + LOGMSG("Starting up... (Time=%016llX), Owner='%ls'", SysTimeToTime64(NNTDLL::GetSystemTime()), &StartUpDir); TrimFilePath(StartUpDir); LOGMSG("WorkFolder: %ls", &WorkFolder); LOGMSG("StartUpDir: %ls", &StartUpDir); @@ -129,9 +136,16 @@ void _stdcall LoadConfiguration(void) PLogOnly = INIRefreshValueInt(CFGSECNAME, L"PLogOnly", PLogOnly, CfgFilePath); PEnabled = INIRefreshValueInt(CFGSECNAME, L"PEnabled", PEnabled, CfgFilePath); AllowInject = INIRefreshValueInt(CFGSECNAME, L"AllowInject", AllowInject, CfgFilePath); - AllowInjNew = INIRefreshValueInt(CFGSECNAME, L"AllowInjNew", AllowInjNew, CfgFilePath); + AllowInjNew = INIRefreshValueInt(CFGSECNAME, L"AllowInjNew", AllowInjNew, CfgFilePath); + SuspendProc = INIRefreshValueInt(CFGSECNAME, L"SuspendProc", SuspendProc, CfgFilePath); InjFlags = INIRefreshValueInt(CFGSECNAME, L"InjectFlags", InjFlags, CfgFilePath); WaitForInj = INIRefreshValueInt(CFGSECNAME, L"WaitForInj", WaitForInj, CfgFilePath); + + PVOID pNtDll = GetNtDllBaseFast(); + NtDllSize = GetRealModuleSize(pNtDll); + NtDllBase = VirtualAlloc(NULL,NtDllSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE); + memcpy(NtDllBase,pNtDll,NtDllSize); + LOGMSG("Clean copy of NtDll: %p", NtDllBase); } //------------------------------------------------------------------------------------ void _stdcall SaveConfiguration(void) @@ -139,8 +153,9 @@ void _stdcall SaveConfiguration(void) INISetValueInt(CFGSECNAME, L"LogMode", LogMode, CfgFilePath); INISetValueInt(CFGSECNAME, L"PLogOnly", PLogOnly, CfgFilePath); INISetValueInt(CFGSECNAME, L"PEnabled", PEnabled, CfgFilePath); - INISetValueInt(CFGSECNAME, L"AllowInject", AllowInject, CfgFilePath); + INISetValueInt(CFGSECNAME, L"AllowInject", AllowInject, CfgFilePath); INISetValueInt(CFGSECNAME, L"AllowInjNew", AllowInjNew, CfgFilePath); + INISetValueInt(CFGSECNAME, L"SuspendProc", SuspendProc, CfgFilePath); INISetValueInt(CFGSECNAME, L"InjectFlags", InjFlags, CfgFilePath); INISetValueInt(CFGSECNAME, L"WaitForInj", WaitForInj, CfgFilePath); } @@ -170,13 +185,32 @@ void _cdecl MenuHandler(CBTYPE Type, PLUG_CB_MENUENTRY *info) AllowInjNew = !AllowInjNew; SaveConfiguration(); break; + case MENU_ID_SUSPPROCESS: + SuspendProc = !SuspendProc; + SaveConfiguration(); + break; + case MENU_ID_USERAWTHREADS: + if(InjFlags & InjLdr::mfRawRMTH)InjFlags &= ~InjLdr::mfRawRMTH; + else InjFlags |= InjLdr::mfRawRMTH; + SaveConfiguration(); + break; case MENU_ID_ABOUT: { char Hdr[64]; // XDBGPLG_BUILD char About[128]; - wsprintfA(Hdr,"%s v%u.0",XDBGPLG_NAME,XDBGPLG_VER); + MSGBOXPARAMSA mpar; + wsprintfA(Hdr,"%s v%u.%u",XDBGPLG_NAME,XDBGPLG_VERH,XDBGPLG_VERL); wsprintfA(About,"Build: %s\nAuthor: Vicshann\nEmail: vicshann@gmail.com",XDBGPLG_BUILD); - MessageBoxA(hXDbgWnd, About, Hdr, MB_OK | MB_ICONINFORMATION); + memset(&mpar,0,sizeof(mpar)); + mpar.cbSize = sizeof(mpar); + mpar.hInstance = hInst; + mpar.hwndOwner = hXDbgWnd; + mpar.dwStyle = MB_OK | MB_USERICON; + mpar.dwLanguageId = MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL); + mpar.lpszIcon = MAKEINTRESOURCE(5); // Why can`t it accept the "LOGOICON" name? + mpar.lpszText = About; + mpar.lpszCaption = Hdr; + MessageBoxIndirectA(&mpar); } break; } @@ -191,7 +225,7 @@ extern "C" __declspec(dllexport) bool _cdecl pluginit(PLUG_INITSTRUCT* initStruc #else HMODULE pXDbgLib = GetModuleHandleA("x32dbg.dll"); #endif - + *(FARPROC*)&plugin_registercallback = GetProcAddress(pXDbgLib, "_plugin_registercallback"); *(FARPROC*)&plugin_menuentrysetchecked = GetProcAddress(pXDbgLib, "_plugin_menuentrysetchecked"); // *(FARPROC*)&plugin_menuentrysetname = GetProcAddress(pXDbgLib, "_plugin_menuentrysetname"); @@ -200,10 +234,10 @@ extern "C" __declspec(dllexport) bool _cdecl pluginit(PLUG_INITSTRUCT* initStruc *(FARPROC*)&plugin_menuseticon = GetProcAddress(pXDbgLib, "_plugin_menuseticon"); *(FARPROC*)&plugin_menuclear = GetProcAddress(pXDbgLib, "_plugin_menuclear"); *(FARPROC*)&plugin_menuadd = GetProcAddress(pXDbgLib, "_plugin_menuadd"); - *(FARPROC*)&plugin_logprintf = GetProcAddress(pXDbgLib, "_plugin_logprintf"); - + *(FARPROC*)&plugin_logprintf = GetProcAddress(pXDbgLib, "_plugin_logprintf"); + PluginHandle = initStruct->pluginHandle; - initStruct->pluginVersion = XDBGPLG_VER; + initStruct->pluginVersion = XDBGPLG_VERH; lstrcpyA(initStruct->pluginName, XDBGPLG_NAME); initStruct->sdkVersion = PLUG_SDKVERSION; plugin_registercallback(initStruct->pluginHandle, CB_MENUENTRY, (CBPLUGIN)MenuHandler); @@ -227,7 +261,10 @@ extern "C" __declspec(dllexport) void _cdecl plugsetup(PLUG_SETUPSTRUCT* setupSt plugin_menuaddentry(setupStruct->hMenu, MENU_ID_ENABLED, "Enabled"); plugin_menuaddentry(setupStruct->hMenu, MENU_ID_CHK_CANINJ, "Allow Injection"); // Open Process plugin_menuaddentry(setupStruct->hMenu, MENU_ID_CHK_CANINJNEW, "Allow Inject New"); // Create Process -// plugin_menuaddentry(setupStruct->hMenu, MENU_ID_CHK_CANINJ, "Allow Ejection"); // On Detach, if DLL ha been injected +// plugin_menuaddentry(setupStruct->hMenu, MENU_ID_CHK_CANEJ, "Allow Ejection"); // On Detach, if DLL has been injected + plugin_menuaddentry(setupStruct->hMenu, MENU_ID_SUSPPROCESS, "Suspend Process"); + plugin_menuaddentry(setupStruct->hMenu, MENU_ID_USERAWTHREADS, "Use Raw Threads"); + plugin_menuaddseparator(setupStruct->hMenu); DbgCliMenu = plugin_menuadd(setupStruct->hMenu, "Client Config"); plugin_menuaddseparator(setupStruct->hMenu); @@ -236,6 +273,8 @@ extern "C" __declspec(dllexport) void _cdecl plugsetup(PLUG_SETUPSTRUCT* setupSt plugin_menuentrysetchecked(PluginHandle,MENU_ID_ENABLED,PEnabled); plugin_menuentrysetchecked(PluginHandle,MENU_ID_CHK_CANINJ,AllowInject); plugin_menuentrysetchecked(PluginHandle,MENU_ID_CHK_CANINJNEW,AllowInjNew); + plugin_menuentrysetchecked(PluginHandle,MENU_ID_SUSPPROCESS,SuspendProc); + plugin_menuentrysetchecked(PluginHandle,MENU_ID_USERAWTHREADS,InjFlags & InjLdr::mfRawRMTH); ICONDATA ico; UINT ResSize = 0; @@ -252,7 +291,7 @@ int _stdcall EnablePlugin(void) DBGMSG("Enter"); BreakWrk = false; HooksInstalled = true; - + HookNtClose.SetHook("NtClose","ntdll.dll"); HookNtOpenThread.SetHook("NtOpenThread","ntdll.dll"); HookNtOpenProcess.SetHook("NtOpenProcess","ntdll.dll"); @@ -261,6 +300,8 @@ int _stdcall EnablePlugin(void) HookNtProtectVirtualMemory.SetHook("NtProtectVirtualMemory","ntdll.dll"); HookNtQueryInformationThread.SetHook("NtQueryInformationThread","ntdll.dll"); HookNtQueryInformationProcess.SetHook("NtQueryInformationProcess","ntdll.dll"); + + HookNtTerminateProcess.SetHook("NtTerminateProcess","ntdll.dll"); HookNtTerminateThread.SetHook("NtTerminateThread","ntdll.dll"); HookNtSuspendThread.SetHook("NtSuspendThread","ntdll.dll"); HookNtResumeThread.SetHook("NtResumeThread","ntdll.dll"); @@ -275,9 +316,9 @@ int _stdcall EnablePlugin(void) HookContinueDebugEvent.SetHook("ContinueDebugEvent","kernel32.dll"); HookWaitForDebugEvent.SetHook("WaitForDebugEvent","kernel32.dll"); HookDebugBreakProcess.SetHook("DebugBreakProcess","kernel32.dll"); - HookTerminateProcess.SetHook("TerminateProcess","kernel32.dll"); HookCreateProcessA.SetHook("CreateProcessA","kernel32.dll"); HookCreateProcessW.SetHook("CreateProcessW","kernel32.dll"); + HookIsWow64Process.SetHook("IsWow64Process","kernel32.dll"); ThList = new XNI::CThreadList; DbgIPC = new SHM::CMessageIPC; @@ -299,7 +340,8 @@ int _stdcall DisablePlugin(void) HookNtQueryVirtualMemory.Remove(); HookNtProtectVirtualMemory.Remove(); HookNtQueryInformationThread.Remove(); - HookNtQueryInformationProcess.Remove(); + HookNtQueryInformationProcess.Remove(); + HookNtTerminateProcess.Remove(); HookNtTerminateThread.Remove(); HookNtSuspendThread.Remove(); HookNtResumeThread.Remove(); @@ -314,7 +356,6 @@ int _stdcall DisablePlugin(void) HookContinueDebugEvent.Remove(); HookWaitForDebugEvent.Remove(); HookDebugBreakProcess.Remove(); - HookTerminateProcess.Remove(); HookCreateProcessA.Remove(); HookCreateProcessW.Remove(); @@ -336,7 +377,7 @@ int _stdcall LoadDbgClienConfig(void) SHM::CArgPack<> apo; DBGMSG("Enter"); plugin_menuclear(DbgCliMenu); - if(DbgIPC->ExchangeMsg(XNI::miDbgGetConfigs,XNI::mtUsrReq, &api, &apo) < 0)return -1; + if(DbgIPC->ExchangeMsg(XNI::miDbgGetConfigs,XNI::mtUsrReq, &api, &apo) < 0){DBGMSG("miDbgGetConfigs failed!"); return -1;} for(;;) { char Name[128]; @@ -354,6 +395,7 @@ int _stdcall LoadDbgClienConfig(void) } else if(Type & XNI::dtNull)plugin_menuaddseparator(DbgCliMenu); } + DBGMSG("Done"); return 0; } //------------------------------------------------------------------------------------ @@ -396,39 +438,77 @@ int _stdcall InjectProcess(HANDLE hProcess, DWORD ProcessID) else InjLib = GetResource(hInst, "InjLib", RT_RCDATA, &ResSize); if(!InjLib || !ResSize){DBGMSG("No InjLib found!"); return -1;} bool POpened = (hProcess == NULL); - if(POpened)hProcess = InjLdr::OpenRemoteProcess(ProcessID, Flags); - if(!hProcess)return -2; - int res = InjLdr::InjModuleIntoProcessAndExec(hProcess, InjLib, ResSize, Flags); - if(POpened)CloseHandle(hProcess); - if(res < 0)return -3; + if(POpened)hProcess = InjLdr::OpenRemoteProcess(ProcessID, Flags, SuspendProc); + if(!hProcess)return -2; + if(SuspendProc) + { + if(!POpened) + { + DuplicateHandle(NtCurrentProcess, hProcess, NtCurrentProcess, &hLstProc, 0, 0, DUPLICATE_SAME_ACCESS); + NTSTATUS stat = NtSuspendProcess(hLstProc); + DBGMSG("Entire process been suspended: Status=%08X, DupHandle=%p",stat,hLstProc); + } + else hLstProc = hProcess; + } + if(!POpened && NNTDLL::IsWinXPOrOlder())Flags &= ~InjLdr::mfRawRMTH; // On Windows XP this Csr unfriendly thread will catch a process initialization APC! // A DebugApi remote thread will also catch this APC and DebugApi threas is also not registered with Csr // On latest Win10 raw threads can`t be injected in notepad.exe (Access Denied) + int res = InjLdr::InjModuleIntoProcessAndExec(hProcess, InjLib, ResSize, Flags|InjLdr::mfResSyscall, 3, NULL, NULL, NtDllBase, 0x10000); // mfResSyscall is required to avoid self interception // Only .text(Data merged), .bss and .rdata + if(POpened && !SuspendProc)CloseHandle(hProcess); // Close after OpenRemoteProcess + if(res < 0){DBGMSG("InjModuleIntoProcessAndExec failed with %i",res); if(SuspendProc)NtResumeProcess(hProcess); return -3;} // Cannot terminate without a specific permission for(int ctr=WaitForInj;ctr > 0;ctr-=100) { Sleep(100); if(SHM::CMessageIPC::IsExistForID(ProcessID))break; } - if(!SHM::CMessageIPC::IsExistForID(ProcessID))return FALSE; + if(!SHM::CMessageIPC::IsExistForID(ProcessID))return -4; return 0; } //------------------------------------------------------------------------------------ +// Main threas is suspended, but some additional threads are not +// BOOL _stdcall ProcessCreateInjWrk(LPPROCESS_INFORMATION lpProcessInformation) -{ - int ires = InjectProcess(lpProcessInformation->hProcess, lpProcessInformation->dwProcessId); - CloseHandle(lpProcessInformation->hThread); - CloseHandle(lpProcessInformation->hProcess); - if(ires < 0){DBGMSG("Failed to inject a new process: %08X(%u)",lpProcessInformation->dwProcessId,lpProcessInformation->dwProcessId); return FALSE;} - if(lpProcessInformation->dwProcessId != DbgIPC->GetID())DbgIPC->Disconnect(); // Has been connected to some other process - if(DbgIPC->Connect((DWORD)lpProcessInformation->dwProcessId, 0, true) < 0){DBGMSG("Connect failed: %08X(%u)",lpProcessInformation->dwProcessId,lpProcessInformation->dwProcessId); return FALSE;} - DbgProcID = lpProcessInformation->dwProcessId; +{ + BOOL res = FALSE; + HANDLE hRealThrd = lpProcessInformation->hThread; + HANDLE hRealProc = lpProcessInformation->hProcess; + hSuspTh = NULL; lpProcessInformation->hProcess = XNI::CDbgClient::UintToFakeHandle(lpProcessInformation->dwProcessId); // All communication with a target process is only through IPC - lpProcessInformation->hThread = NULL; // TODO: Get it from target`s DbgClient - SHM::CArgPack<> api; - SHM::CArgPack<> apo; - api.PushArg(lpProcessInformation->dwProcessId); - if(DbgIPC->ExchangeMsg(XNI::miDebugActiveProcess,XNI::mtDbgReq, &api, &apo) < 0)return FALSE; - BOOL res = FALSE; - apo.PopArg(res); - LoadDbgClienConfig(); - plugin_logprintf("Main thread is in suspended state\n"); + lpProcessInformation->hThread = XNI::CDbgClient::UintToFakeHandle(0); // Any first thread in list! + int ires = InjectProcess(hRealProc, lpProcessInformation->dwProcessId); + if(ires >= 0) + { + if(lpProcessInformation->dwProcessId != DbgIPC->GetID())DbgIPC->Disconnect(); // Has been connected to some other process + if(DbgIPC->Connect((DWORD)lpProcessInformation->dwProcessId, 0, true) >= 0) + { + ThList->Clear(); + LstProcID = DbgProcID = lpProcessInformation->dwProcessId; // Required for ProcWaitForDebugEvent + DBGMSG("hProcess=%08X, hThread=%08X, ProcessId=%u, ThreadId=%u",lpProcessInformation->hProcess,lpProcessInformation->hThread,lpProcessInformation->dwProcessId,lpProcessInformation->dwThreadId); + SHM::CArgPack<> api; + SHM::CArgPack<> apo; + api.PushArg(lpProcessInformation->dwProcessId); + if(DbgIPC->ExchangeMsg(XNI::miDebugActiveProcess,XNI::mtDbgReq, &api, &apo) >= 0) // Do an usual attach but to a suspended process (Should have a single worker thread) + { + DWORD MainThID = 0; + HANDLE hPHandle = NULL; + HANDLE hTHandle = NULL; + PTEB MainThTeb = NULL; + apo.PopArg(res); + apo.PopArg(MainThID); + apo.PopArg(MainThTeb); + apo.PopArg(hTHandle); + apo.PopArg(hPHandle); + lpProcessInformation->hProcess = hPHandle; + lpProcessInformation->hThread = hTHandle; + ThList->AddThreadToList(MainThTeb, MainThID, hTHandle, false); // NOTE: Watch for CloseHandle for thread handles + LoadDbgClienConfig(); + if(res)hSuspTh = hRealThrd; +/////////////// plugin_logprintf("Main thread is in suspended state\n"); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + } + } + else {DBGMSG("Connect failed: %08X(%u)",lpProcessInformation->dwProcessId,lpProcessInformation->dwProcessId);} + } + else {DBGMSG("Failed to inject a new process: %08X(%u): %i",lpProcessInformation->dwProcessId,lpProcessInformation->dwProcessId,ires);} + if(!res){TerminateProcess(hRealProc,0); CloseHandle(hRealThrd);} + CloseHandle(hRealProc); return res; } //------------------------------------------------------------------------------------ @@ -443,6 +523,14 @@ BOOL _stdcall ProcessCreateInjWrk(LPPROCESS_INFORMATION lpProcessInformation) // NTSTATUS NTAPI ProcNtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId) { + DBGMSG("Opening: DbgProcID=%08X, LstProcID=%08X, ProcessID=%08X",DbgProcID,LstProcID,ClientId->UniqueProcess); + if(LstProcID == (ULONG)ClientId->UniqueProcess) // x64Dbg will try multiple times! + { + if(!DbgProcID){DBGMSG("Reopening prevented!"); return STATUS_ACCESS_DENIED;} + *ProcessHandle = XNI::CDbgClient::UintToFakeHandle((ULONG)ClientId->UniqueProcess); + DBGMSG("Reopening emulated!"); // "Reopening allowed!" + return STATUS_SUCCESS; // HookNtOpenProcess.OrigProc(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);; + } bool HaveMapping = SHM::CMessageIPC::IsExistForID((DWORD)ClientId->UniqueProcess); if(PLogOnly || !ClientId || !ProcessHandle || (!HaveMapping && AllowInject)) // Injection(optional) moved to DebugActiveProcess because opening a process is done after DebugActiveProcess { @@ -454,7 +542,8 @@ NTSTATUS NTAPI ProcNtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAcces if(!HaveMapping)return STATUS_UNSUCCESSFUL; // Debugger will try to open every process. Do not show processes without already injected DLLs if((DWORD)ClientId->UniqueProcess != DbgIPC->GetID())DbgIPC->Disconnect(); // Has been connected to some other process if(DbgIPC->Connect((DWORD)ClientId->UniqueProcess, 0, true) < 0){DBGMSG("Connect failed: %08X(%u)",ClientId->UniqueProcess,ClientId->UniqueProcess); return STATUS_UNSUCCESSFUL;} - DbgProcID = (DWORD)ClientId->UniqueProcess; + LstProcID = DbgProcID = (DWORD)ClientId->UniqueProcess; + ThList->Clear(); *ProcessHandle = XNI::CDbgClient::UintToFakeHandle((DWORD)ClientId->UniqueProcess); // All communication with a target process is only through IPC DBGMSG("FakeProcessHandle=%08X, DesiredAccess=%08X, UniqueProcess=%08X, UniqueThread=%08X",*ProcessHandle,DesiredAccess,ClientId->UniqueProcess,ClientId->UniqueThread); return STATUS_SUCCESS; @@ -463,11 +552,13 @@ NTSTATUS NTAPI ProcNtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAcces NTSTATUS NTAPI ProcNtOpenThread(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId) { HANDLE hTh = NULL; - if(PLogOnly || !DbgProcID || !ClientId || !ThreadHandle || !(hTh = ThList->GetHandleByIndex(ThList->FindThreadIdxInList(NULL, (DWORD)ClientId->UniqueThread, NULL)))) + DBGMSG("Opening: DbgProcID=%08X, ProcessID=%08X, ThreadID=%08X",DbgProcID,ClientId->UniqueProcess,ClientId->UniqueThread); + bool State = PLogOnly || !DbgProcID || !ClientId || !ThreadHandle; + if(State || !(hTh = ThList->GetHandleByIndex(ThList->FindThreadIdxInList(NULL, (DWORD)ClientId->UniqueThread, NULL)))) // TODO: Need a way to know main thread`s index(In GhostDbg list) of a new created process. It may be requested before CREATE_PROCESS_DEBUG_EVENT { + if(State && ClientId->UniqueThread && (ThList->FindThreadIdxInList(NULL, (DWORD)ClientId->UniqueThread, NULL) >= 0)){DBGMSG("Opening prevented!"); return STATUS_ACCESS_DENIED;} // x64Dbg will try multiple times! NTSTATUS Res = HookNtOpenThread.OrigProc(ThreadHandle, DesiredAccess, ObjectAttributes, ClientId); - HANDLE Hnd = (ThreadHandle)?(*ThreadHandle):(INVALID_HANDLE_VALUE); - DBGMSG("Status=%08X, ThreadHandle=%08X, DesiredAccess=%08X, UniqueProcess=%08X, UniqueThread=%08X",Res,Hnd,DesiredAccess,(ClientId)?(ClientId->UniqueProcess):(0),(ClientId)?(ClientId->UniqueThread):(0)); + DBGMSG("Status=%08X, ThreadHandle=%08X, DesiredAccess=%08X, UniqueProcess=%08X, UniqueThread=%08X",Res,((ThreadHandle)?(*ThreadHandle):(INVALID_HANDLE_VALUE)),DesiredAccess,(ClientId)?(ClientId->UniqueProcess):(0),(ClientId)?(ClientId->UniqueThread):(0)); return Res; } *ThreadHandle = hTh; @@ -498,33 +589,44 @@ NTSTATUS NTAPI ProcNtClose(HANDLE Handle) //------------------------------------------------------------------------------------ BOOL WINAPI ProcCreateProcessA(LPCSTR lpApplicationName,LPSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCSTR lpCurrentDirectory,LPSTARTUPINFOA lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation) { - DBGMSG("dwCreationFlags=%08X, lpApplicationName='%s',lpCommandLine='%s',",dwCreationFlags,lpApplicationName?lpApplicationName:"",lpCommandLine?lpCommandLine:""); + DBGMSG("dwCreationFlags=%08X, lpApplicationName='%s',lpCommandLine='%s'",dwCreationFlags,lpApplicationName?lpApplicationName:"",lpCommandLine?lpCommandLine:""); bool ForDebug = AllowInjNew && (dwCreationFlags & (DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS)); if(ForDebug) { dwCreationFlags &= ~(DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS); - dwCreationFlags |= CREATE_SUSPENDED; + dwCreationFlags |= CREATE_SUSPENDED; // Instead of DEBUG_PROCESS } BOOL res = HookCreateProcessA.OrigProc(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); + DBGMSG("ProcessId=%u, ThreadId=%u",lpProcessInformation->dwProcessId,lpProcessInformation->dwThreadId); if(res && ForDebug && lpProcessInformation)res = ProcessCreateInjWrk(lpProcessInformation); return res; } //------------------------------------------------------------------------------------ BOOL WINAPI ProcCreateProcessW(LPCWSTR lpApplicationName,LPWSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCWSTR lpCurrentDirectory,LPSTARTUPINFOW lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation) { - DBGMSG("dwCreationFlags=%08X, lpApplicationName='%ls',lpCommandLine='%ls',",dwCreationFlags,lpApplicationName?lpApplicationName:L"",lpCommandLine?lpCommandLine:L""); + DBGMSG("dwCreationFlags=%08X, lpApplicationName='%ls',lpCommandLine='%ls'",dwCreationFlags,lpApplicationName?lpApplicationName:L"",lpCommandLine?lpCommandLine:L""); bool ForDebug = AllowInjNew && (dwCreationFlags & (DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS)); if(ForDebug) { dwCreationFlags &= ~(DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS); - dwCreationFlags |= CREATE_SUSPENDED; + dwCreationFlags |= CREATE_SUSPENDED; // Instead of DEBUG_PROCESS } BOOL res = HookCreateProcessW.OrigProc(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); + DBGMSG("ProcessId=%u, ThreadId=%u",lpProcessInformation->dwProcessId,lpProcessInformation->dwThreadId); if(res && ForDebug && lpProcessInformation)res = ProcessCreateInjWrk(lpProcessInformation); return res; } //------------------------------------------------------------------------------------ - +BOOL WINAPI ProcIsWow64Process(HANDLE hProcess, PBOOL Wow64Process) // In Windows 10 (2019) it passes process` handle to NtQuerySystemInformationEx +{ + PVOID Value = NULL; + ULONG RetLen = 0; + NTSTATUS Status = NtQueryInformationProcess(hProcess, ProcessWow64Information, &Value, sizeof(Value), &RetLen); + if(Status < 0)RtlSetLastWin32Error(RtlNtStatusToDosError(Status)); + else if(Wow64Process)*Wow64Process = (bool)Value; + DBGMSG("Status=%08X, hProcess=%p, Value=%u",Status,hProcess,(UINT)Value); + return (Status >= 0); +} //==================================================================================== // @@ -538,6 +640,7 @@ BOOL WINAPI ProcWaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent, DWORD dwMillisecon DBGMSG("lpDebugEvent=%p, dwMilliseconds=%u",lpDebugEvent,dwMilliseconds); if(PLogOnly || !DbgProcID) { + DBGMSG("PLogOnly=%u, DbgProcID=%u",PLogOnly,DbgProcID); BOOL res = HookWaitForDebugEvent.OrigProc(lpDebugEvent, dwMilliseconds); if(res){DBGMSG("dwDebugEventCode=%08X, dwProcessId=%08X, dwThreadId=%08X, BASE: %p",lpDebugEvent->dwDebugEventCode,lpDebugEvent->dwProcessId,lpDebugEvent->dwThreadId,lpDebugEvent->u.LoadDll.lpBaseOfDll);} return res; @@ -554,7 +657,7 @@ BOOL WINAPI ProcWaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent, DWORD dwMillisecon { case EXCEPTION_DEBUG_EVENT: { - // Nothing to do for now + DBGMSG("EXCEPTION_DEBUG_EVENT: dwThreadId=%u, Code=%08X, Addr=%p",Evt->dwThreadId,Evt->u.Exception.ExceptionRecord.ExceptionCode, Evt->u.Exception.ExceptionRecord.ExceptionAddress); } break; case CREATE_THREAD_DEBUG_EVENT: @@ -567,6 +670,8 @@ BOOL WINAPI ProcWaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent, DWORD dwMillisecon { DBGMSG("CREATE_PROCESS_DEBUG_EVENT: hProcess=%08X, hThread=%08X, dwThreadId=%u",Evt->u.CreateProcessInfo.hProcess,Evt->u.CreateProcessInfo.hThread,Evt->dwThreadId); ThList->AddThreadToList((TEB*)Evt->u.CreateThread.lpThreadLocalBase, Evt->dwThreadId, Evt->u.CreateProcessInfo.hThread, false); // This fake handle is an encoded index in client`s thread list + if(hSuspTh){ResumeThread(hSuspTh); CloseHandle(hSuspTh); hSuspTh = NULL; DBGMSG("Main thread has been resumed");} // Was created as suspended // TODO: Optionally left main thread suspended if a new process started? + if(SuspendProc && hLstProc){NTSTATUS stat = NtResumeProcess(hLstProc); CloseHandle(hLstProc); DBGMSG("Entire process been resumed: Status=%08X, Handle=%p",stat,hLstProc); hLstProc=NULL;} // GhostDbg initialization is finished } break; case EXIT_THREAD_DEBUG_EVENT: @@ -578,8 +683,7 @@ BOOL WINAPI ProcWaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent, DWORD dwMillisecon case EXIT_PROCESS_DEBUG_EVENT: { DBGMSG("EXIT_PROCESS_DEBUG_EVENT: dwProcessId=%u, dwExitCode=%u",Evt->dwProcessId,Evt->u.ExitProcess.dwExitCode); - if(DbgProcID == Evt->dwProcessId)DbgProcID = 0; - if(DbgIPC)DbgIPC->Disconnect(); + if(DbgProcID == Evt->dwProcessId)DoDisconnAtTerm = true; } break; case LOAD_DLL_DEBUG_EVENT: @@ -606,9 +710,11 @@ BOOL WINAPI ProcWaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent, DWORD dwMillisecon default: {DBGMSG("Unknown DebugEventCode: %u",Evt->dwDebugEventCode);} } memcpy(lpDebugEvent,&Cmd->Data,sizeof(DEBUG_EVENT)); - DbgIPC->EndMsg(false); // Unlock shared buffer // Only single events can be removed because they read in order of arrival // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + DbgIPC->EndMsg(false); // Unlock shared buffer // Only single events can be removed because they read in order of arrival // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + DBGMSG("CONTINUE"); return TRUE; // Other events will wait untiiiil another call to WaitForDebugEvent } + DBGMSG("FINISH"); DbgProcID = 0; // No DebugActiveProcessStop is called when WaitForDebugEvent is failed DbgIPC->EndMsg(false); // Unlock shared buffer if it is still locked // <<<<<<<<<<<<<<<<<<< FALSE for now! DbgIPC->Disconnect(); @@ -625,18 +731,28 @@ BOOL WINAPI ProcDebugActiveProcess(DWORD dwProcessId) // Thes will make a de { if(AllowInject) { - if(InjectProcess(NULL, dwProcessId) < 0){DBGMSG("Failed to inject!"); return FALSE;} + if(int res = InjectProcess(NULL, dwProcessId); res < 0){DBGMSG("Failed to inject: %i", res); return FALSE;} } else return FALSE; } - if(DbgIPC->Connect(dwProcessId, 0, true) < 0){DBGMSG("Failed to connect!"); return FALSE;} - DbgProcID = dwProcessId; + if(int res = DbgIPC->Connect(dwProcessId, 0, true); res < 0){DBGMSG("Failed to connect: %i", res); return FALSE;} + LstProcID = DbgProcID = dwProcessId; + ThList->Clear(); SHM::CArgPack<> api; SHM::CArgPack<> apo; api.PushArg(dwProcessId); if(DbgIPC->ExchangeMsg(XNI::miDebugActiveProcess,XNI::mtDbgReq, &api, &apo) < 0){DBGMSG("Failed to communicate!"); return FALSE;} BOOL res = FALSE; + DWORD MainThID = 0; + HANDLE hPHandle = NULL; + HANDLE hTHandle = NULL; + PTEB MainThTeb = NULL; apo.PopArg(res); + apo.PopArg(MainThID); + apo.PopArg(MainThTeb); + apo.PopArg(hTHandle); + apo.PopArg(hPHandle); + ThList->AddThreadToList(MainThTeb, MainThID, hTHandle, false); // NOTE: Watch for CloseHandle for thread handles LoadDbgClienConfig(); return res; } @@ -645,7 +761,7 @@ BOOL WINAPI ProcDebugActiveProcessStop(DWORD dwProcessId) // Doesn`t called a { DBGMSG("dwProcessId=%08X",dwProcessId); if(PLogOnly || !DbgIPC || !DbgProcID)return HookDebugActiveProcessStop.OrigProc(dwProcessId); - if(DbgProcID == dwProcessId)DbgProcID = 0; + if(DbgProcID == dwProcessId)LstProcID = DbgProcID = 0; // Allow reopening of a target process SHM::CArgPack<> api; api.PushArg(dwProcessId); int res = DbgIPC->ExchangeMsg(XNI::miDebugActiveProcessStop,XNI::mtDbgReq, &api, NULL); @@ -656,16 +772,28 @@ BOOL WINAPI ProcDebugActiveProcessStop(DWORD dwProcessId) // Doesn`t called a //------------------------------------------------------------------------------------ BOOL WINAPI ProcContinueDebugEvent(DWORD dwProcessId, DWORD dwThreadId, DWORD dwContinueStatus) { - DBGMSG("dwProcessId=%08X, dwThreadId=%08X, dwContinueStatus=%08X",dwProcessId,dwThreadId,dwContinueStatus); - if(PLogOnly || !DbgIPC || !DbgProcID)return HookContinueDebugEvent.OrigProc(dwProcessId, dwThreadId, dwContinueStatus); + DBGMSG("dwProcessId=%08X, dwThreadId=%u, dwContinueStatus=%08X",dwProcessId,dwThreadId,dwContinueStatus); + if(PLogOnly || !DbgIPC || !DbgProcID)return HookContinueDebugEvent.OrigProc(dwProcessId, dwThreadId, dwContinueStatus); SHM::CArgPack<> api; SHM::CArgPack<> apo; api.PushArg(dwContinueStatus); api.PushArg(dwThreadId); api.PushArg(dwProcessId); + if(DoDisconnAtTerm) // Need to wait here to other threads which read Memory/ThreadInfo in a loop or termination will be slow + { + DBGMSG("Waiting for other threads to stop accessing the finished process..."); + Sleep(1000); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + DBGMSG("Continuing target process termination"); + } if(DbgIPC->ExchangeMsg(XNI::miContinueDebugEvent,XNI::mtDbgReq, &api, &apo) < 0)return FALSE; BOOL res = FALSE; apo.PopArg(res); + if(DoDisconnAtTerm && DbgIPC) + { + DoDisconnAtTerm = false; + DbgProcID = 0; + DbgIPC->Disconnect(); + } return res; } //------------------------------------------------------------------------------------ @@ -682,17 +810,19 @@ BOOL WINAPI ProcDebugBreakProcess(HANDLE hProcess) // Does ntdll.RtlpCreateU return res; } //------------------------------------------------------------------------------------ -BOOL WINAPI ProcTerminateProcess(HANDLE hProcess, UINT uExitCode) +NTSTATUS NTAPI ProcNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus) { - DBGMSG("hProcess=%p, uExitCode=%08X",hProcess,uExitCode); - if(PLogOnly || !DbgIPC || !XNI::CDbgClient::IsFakeHandle(hProcess))return HookTerminateProcess.OrigProc(hProcess, uExitCode); + DBGMSG("ProcessHandle=%p, ExitStatus=%08X",ProcessHandle,ExitStatus); + if(PLogOnly || !DbgIPC || !XNI::CDbgClient::IsFakeHandle(ProcessHandle))return HookNtTerminateProcess.OrigProc(ProcessHandle, ExitStatus); SHM::CArgPack<> api; SHM::CArgPack<> apo; - api.PushArg(uExitCode); - api.PushArg(hProcess); + api.PushArg(ExitStatus); + api.PushArg(ProcessHandle); if(DbgIPC->ExchangeMsg(XNI::miTerminateProcess,XNI::mtDbgReq, &api, &apo) < 0)return FALSE; - BOOL res = FALSE; + NTSTATUS res = STATUS_UNSUCCESSFUL; apo.PopArg(res); + if(!res)DbgIPC->Disconnect(); // x64Dbg is still owns the process handle and will try to request the process info with it! + DbgProcID = 0; // ???????????????????? return res; } //------------------------------------------------------------------------------------ @@ -702,20 +832,19 @@ NTSTATUS NTAPI ProcNtGetContextThread(HANDLE ThreadHandle, PCONTEXT Context) if(PLogOnly || !DbgIPC || !XNI::CDbgClient::IsFakeHandle(ThreadHandle) || !ThList->IsThreadInList(0,ThreadHandle))return HookNtGetContextThread.OrigProc(ThreadHandle, Context); NTSTATUS Status; SHM::CArgPack api; - SHM::CArgPack<> apo; + SHM::CArgPack apo; api.PushArg(*Context); // InOut api.PushArg(ThreadHandle); if(DbgIPC->ExchangeMsg(XNI::miGetThreadContext,XNI::mtDbgReq, &api, &apo) < 0)return STATUS_UNSUCCESSFUL; apo.PopArg(Status); apo.PopArg(*Context); - DBGMSG("RET: ThHndle=%p, Context=%p, DbgRegs=%u, DR7=%p, DR0=%p, DR1=%p, DR2=%p, DR3=%p",ThreadHandle,Context,bool(Context->ContextFlags & CONTEXT_DEBUG_REGISTERS), Context->Dr7,Context->Dr0,Context->Dr1,Context->Dr2,Context->Dr3); + DBGMSG("RET: ThHndle=%p, Context=%p, PC=%p, Trace=%u, DbgRegs=%u, DR7=%p, DR0=%p, DR1=%p, DR2=%p, DR3=%p",ThreadHandle,Context,XNI::CDbgClient::GetInstrPtr(Context),bool(Context->EFlags&0x0100),bool(Context->ContextFlags & CONTEXT_DEBUG_REGISTERS), Context->Dr7,Context->Dr0,Context->Dr1,Context->Dr2,Context->Dr3); return Status; } //------------------------------------------------------------------------------------ NTSTATUS NTAPI ProcNtSetContextThread(HANDLE ThreadHandle, PCONTEXT Context) { - DBGMSG("ThreadHandle=%p, Context=%p, DbgRegs=%u, DR7=%p, DR0=%p, DR1=%p, DR2=%p, DR3=%p",ThreadHandle,Context,bool(Context->ContextFlags & CONTEXT_DEBUG_REGISTERS), Context->Dr7,Context->Dr0,Context->Dr1,Context->Dr2,Context->Dr3); - // if(Context->Dr1)DebugBreak(); + DBGMSG("ThreadHandle=%p, Context=%p, PC=%p, Trace=%u, DbgRegs=%u, DR7=%p, DR0=%p, DR1=%p, DR2=%p, DR3=%p",ThreadHandle,Context,XNI::CDbgClient::GetInstrPtr(Context),bool(Context->EFlags&0x0100),bool(Context->ContextFlags & CONTEXT_DEBUG_REGISTERS), Context->Dr7,Context->Dr0,Context->Dr1,Context->Dr2,Context->Dr3); if(PLogOnly || !DbgIPC || !XNI::CDbgClient::IsFakeHandle(ThreadHandle) || !ThList->IsThreadInList(0,ThreadHandle))return HookNtSetContextThread.OrigProc(ThreadHandle, Context); NTSTATUS Status; SHM::CArgPack api; @@ -729,12 +858,12 @@ NTSTATUS NTAPI ProcNtSetContextThread(HANDLE ThreadHandle, PCONTEXT Context) //------------------------------------------------------------------------------------ NTSTATUS NTAPI ProcNtReadVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T BufferLength, PSIZE_T ReturnLength) { -//// DBGMSG("ProcessHandle=%p, BaseAddress=%p, Buffer=%p, BufferLength=%08X, ReturnLength=%p",ProcessHandle,BaseAddress,Buffer,BufferLength,ReturnLength); +// DBGMSG("ProcessHandle=%p, BaseAddress=%p, Buffer=%p, BufferLength=%08X, ReturnLength=%p",ProcessHandle,BaseAddress,Buffer,BufferLength,ReturnLength); if(PLogOnly || !DbgIPC || !XNI::CDbgClient::IsFakeHandle(ProcessHandle))return HookNtReadVirtualMemory.OrigProc(ProcessHandle, BaseAddress, Buffer, BufferLength, ReturnLength); SIZE_T RetLen = 0; NTSTATUS Status; SHM::CArgPack<> api; - SHM::CArgPack<> apo; + SHM::CArgPack<3072> apo; api.PushArg(BufferLength); api.PushArg(BaseAddress); api.PushArg(ProcessHandle); @@ -748,11 +877,11 @@ NTSTATUS NTAPI ProcNtReadVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, //------------------------------------------------------------------------------------ NTSTATUS NTAPI ProcNtWriteVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T BufferLength, PSIZE_T ReturnLength) { - DBGMSG("ProcessHandle=%p, BaseAddress=%p, Buffer=%p, BufferLength=%08X, ReturnLength=%p",ProcessHandle,BaseAddress,Buffer,BufferLength,ReturnLength); + DBGMSG("ProcessHandle=%p, BaseAddress=%p, Buffer=%p, BufferLength=%08X, BYTE=%02X, ReturnLength=%p",ProcessHandle,BaseAddress,Buffer,BufferLength,(Buffer)?(*(PBYTE)Buffer):0,ReturnLength); if(PLogOnly || !DbgIPC || !XNI::CDbgClient::IsFakeHandle(ProcessHandle))return HookNtWriteVirtualMemory.OrigProc(ProcessHandle, BaseAddress, Buffer, BufferLength, ReturnLength); SIZE_T RetLen = 0; NTSTATUS Status; - SHM::CArgPack<1024> api; + SHM::CArgPack<3072> api; SHM::CArgPack<> apo; api.PushBlk(BufferLength, Buffer); api.PushArg(BufferLength); @@ -817,6 +946,7 @@ NTSTATUS NTAPI ProcNtSuspendThread(HANDLE ThreadHandle, PULONG PreviousSuspendCo apo.PopArg(Status); apo.PopArg(SuspCtr); if(PreviousSuspendCount)*PreviousSuspendCount = SuspCtr; + DBGMSG("RET: ThreadHandle=%p, Status=%08X, SuspCtr=%u",ThreadHandle, Status, SuspCtr); return Status; } //------------------------------------------------------------------------------------ @@ -833,6 +963,7 @@ NTSTATUS NTAPI ProcNtResumeThread(HANDLE ThreadHandle, PULONG PreviousSuspendCou apo.PopArg(Status); apo.PopArg(SuspCtr); if(PreviousSuspendCount)*PreviousSuspendCount = SuspCtr; + DBGMSG("RET: ThreadHandle=%p, Status=%08X, SuspCtr=%u",ThreadHandle, Status, SuspCtr); return Status; } //------------------------------------------------------------------------------------ @@ -857,7 +988,7 @@ NTSTATUS NTAPI ProcNtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCL ULONG RetLen = 0; NTSTATUS Status; SHM::CArgPack<> api; - SHM::CArgPack<1024> apo; + SHM::CArgPack<3072> apo; api.PushArg(ProcessInformationLength); api.PushArg(ProcessInformationClass); api.PushArg(ProcessHandle); @@ -883,7 +1014,7 @@ NTSTATUS NTAPI ProcNtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCL default: DBGMSG("Untested information class: %u!",ProcessInformationClass); // DebugBreak(); - } + } return Status; } //------------------------------------------------------------------------------------ @@ -894,7 +1025,7 @@ NTSTATUS NTAPI ProcNtQueryInformationThread(HANDLE ThreadHandle, THREADINFOCLASS ULONG RetLen = 0; NTSTATUS Status; SHM::CArgPack<> api; - SHM::CArgPack<1024> apo; + SHM::CArgPack<3072> apo; api.PushArg(ThreadInformationLength); api.PushArg(ThreadInformationClass); api.PushArg(ThreadHandle); @@ -903,11 +1034,11 @@ NTSTATUS NTAPI ProcNtQueryInformationThread(HANDLE ThreadHandle, THREADINFOCLASS apo.PopArg(RetLen); apo.PopBlk(ThreadInformationLength,ThreadInformation); // Full buffer exchange if(ReturnLength)*ReturnLength = RetLen; - if(Status || !RetLen){DBGMSG("Failed with status: %08X!",Status); return Status;} + if(Status || !RetLen){DBGMSG("Failed %u with status: %08X!",ThreadInformationClass,Status); return Status;} switch(ThreadInformationClass) { case ThreadBasicInformation: - case ThreadSuspendCount: + case ThreadSuspendCount: // Since Windows 8.1 case ThreadCycleTime: case ThreadTimes: break; @@ -926,7 +1057,7 @@ NTSTATUS NTAPI ProcNtQueryVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, SIZE_T RetLen = 0; NTSTATUS Status; SHM::CArgPack<> api; - SHM::CArgPack<1024> apo; + SHM::CArgPack<3072> apo; api.PushArg(MemoryInformationLength); api.PushArg(MemoryInformationClass); api.PushArg(BaseAddress); @@ -936,7 +1067,7 @@ NTSTATUS NTAPI ProcNtQueryVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, apo.PopArg(RetLen); apo.PopBlk(MemoryInformationLength,MemoryInformation); // Full buffer exchange if(ReturnLength)*ReturnLength = RetLen; - if(Status || !RetLen){DBGMSG("Failed with status: %08X!",Status); return Status;} + if(Status || !RetLen){DBGMSG("Failed with status: %08X, %p, %u!",Status,BaseAddress,MemoryInformationClass); return Status;} switch(MemoryInformationClass) { case MemoryBasicInformation: diff --git a/XDbgPlugin/XDbgPlugin.h b/XDbgPlugin/XDbgPlugin.h index d739a4a..d657cf5 100644 --- a/XDbgPlugin/XDbgPlugin.h +++ b/XDbgPlugin/XDbgPlugin.h @@ -1,25 +1,40 @@ #pragma once - +/* + Copyright (c) 2020 Victor Sheinmann, Vicshann@gmail.com + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ #include #include "Utils.h" #include "UniHook.hpp" -#include "FormatPE.h" +#include "NtDllEx.hpp" #include "GhostDbg.hpp" #include "InjDllLdr.hpp" //==================================================================================== #define CFGSECNAME L"Parameters" -#define XDBGPLG_VER 1 +#define XDBGPLG_VERH 2 +#define XDBGPLG_VERL 0 #define XDBGPLG_NAME "GhostDbg" #define XDBGPLG_BUILD __DATE__ " - " __TIME__ -#define MENU_ID_ENABLED 1 -#define MENU_ID_ABOUT 2 -#define MENU_ID_CHK_CANINJ 3 +#define MENU_ID_ENABLED 1 +#define MENU_ID_ABOUT 2 +#define MENU_ID_CHK_CANINJ 3 #define MENU_ID_CHK_CANINJNEW 4 -#define MENU_ID_DBGCLIENT 16 +#define MENU_ID_SUSPPROCESS 5 +#define MENU_ID_USERAWTHREADS 6 +#define MENU_ID_DBGCLIENT 16 //==================================================================================== @@ -41,7 +56,7 @@ BOOL WINAPI ProcDebugActiveProcessStop(DWORD dwProcessId); BOOL WINAPI ProcWaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent, DWORD dwMilliseconds); BOOL WINAPI ProcContinueDebugEvent(DWORD dwProcessId, DWORD dwThreadId, DWORD dwContinueStatus); BOOL WINAPI ProcDebugBreakProcess(HANDLE Process); -BOOL WINAPI ProcTerminateProcess(HANDLE hProcess, UINT uExitCode); +BOOL WINAPI ProcIsWow64Process(HANDLE hProcess, PBOOL Wow64Process); BOOL WINAPI ProcCreateProcessA(LPCSTR lpApplicationName,LPSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCSTR lpCurrentDirectory,LPSTARTUPINFOA lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation); BOOL WINAPI ProcCreateProcessW(LPCWSTR lpApplicationName,LPWSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCWSTR lpCurrentDirectory,LPSTARTUPINFOW lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation); @@ -57,7 +72,8 @@ NTSTATUS NTAPI ProcNtGetContextThread(HANDLE ThreadHandle, PCONTEXT Context); NTSTATUS NTAPI ProcNtSetContextThread(HANDLE ThreadHandle, PCONTEXT Context); NTSTATUS NTAPI ProcNtReadVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T BufferLength, PSIZE_T ReturnLength); NTSTATUS NTAPI ProcNtWriteVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T BufferLength, PSIZE_T ReturnLength); -NTSTATUS NTAPI ProcNtTerminateThread(HANDLE ThreadHandle, NTSTATUS ExitStatus);; +NTSTATUS NTAPI ProcNtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus); +NTSTATUS NTAPI ProcNtTerminateThread(HANDLE ThreadHandle, NTSTATUS ExitStatus); NTSTATUS NTAPI ProcNtSuspendThread(HANDLE ThreadHandle, PULONG PreviousSuspendCount); NTSTATUS NTAPI ProcNtResumeThread(HANDLE ThreadHandle, PULONG PreviousSuspendCount); NTSTATUS NTAPI ProcNtClose(HANDLE Handle); diff --git a/XDbgPlugin/XDbgPlugin.vcxproj b/XDbgPlugin/XDbgPlugin.vcxproj index 22e03c1..a057d6f 100644 --- a/XDbgPlugin/XDbgPlugin.vcxproj +++ b/XDbgPlugin/XDbgPlugin.vcxproj @@ -124,16 +124,15 @@ false Default MultiThreadedDebug - - + Default false - StreamingSIMDExtensions + StreamingSIMDExtensions2 false NotUsing Level3 false ProgramDatabase - StdCall + FastCall false true false @@ -183,16 +182,15 @@ false Default MultiThreadedDebug - - + Default false - StreamingSIMDExtensions + NotSet false NotUsing Level3 false ProgramDatabase - StdCall + FastCall false true false @@ -229,8 +227,8 @@ - MinSpace - OnlyExplicitInline + MaxSpeed + AnySuitable false Speed false @@ -240,17 +238,16 @@ true false MultiThreaded - - + Default false - StreamingSIMDExtensions + StreamingSIMDExtensions2 false NotUsing Level3 false - StdCall + FastCall CompileAsCpp true stdcpplatest @@ -291,8 +288,8 @@ copy /Y "$(OutDir)$(TargetName)$(TargetExt)" "$(SolutionDir)BUILD\RELEASE\$(Solu - Disabled - OnlyExplicitInline + MaxSpeed + AnySuitable false Speed false @@ -302,17 +299,16 @@ copy /Y "$(OutDir)$(TargetName)$(TargetExt)" "$(SolutionDir)BUILD\RELEASE\$(Solu true false MultiThreaded - - + Default false - StreamingSIMDExtensions + NotSet false NotUsing Level3 false - StdCall + FastCall CompileAsCpp true stdcpplatest @@ -351,6 +347,7 @@ copy /Y "$(OutDir)$(TargetName)$(TargetExt)" "$(SolutionDir)BUILD\RELEASE\$(Solu + @@ -358,6 +355,7 @@ copy /Y "$(OutDir)$(TargetName)$(TargetExt)" "$(SolutionDir)BUILD\RELEASE\$(Solu + diff --git a/XDbgPlugin/XDbgPlugin.vcxproj.filters b/XDbgPlugin/XDbgPlugin.vcxproj.filters index 6624a0a..027f320 100644 --- a/XDbgPlugin/XDbgPlugin.vcxproj.filters +++ b/XDbgPlugin/XDbgPlugin.vcxproj.filters @@ -24,6 +24,9 @@ Common + + Common + @@ -53,6 +56,9 @@ Common + + Common + diff --git a/XDbgPlugin/pluginsdk/bridgemain.h b/XDbgPlugin/pluginsdk/bridgemain.h index e66fe1a..576cfa4 100644 --- a/XDbgPlugin/pluginsdk/bridgemain.h +++ b/XDbgPlugin/pluginsdk/bridgemain.h @@ -8,7 +8,7 @@ #endif //list structure (and C++ wrapper) -#include "bridgelist.h" +//#include "bridgelist.h" // Disabled because brings in C runtime (vector) //default structure alignments forced #ifdef _WIN64