diff --git a/.gitignore b/.gitignore index f84323d..9da9612 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,4 @@ $RECYCLE.BIN/ *.cbTemp cov-* coverity* +*.user diff --git a/SDK/CPP/TitanEngine.h b/SDK/CPP/TitanEngine.h index f5fa595..12f0083 100644 --- a/SDK/CPP/TitanEngine.h +++ b/SDK/CPP/TitanEngine.h @@ -577,7 +577,7 @@ __declspec(dllimport) bool TITCALL DeleteLastSectionEx(char* szFileName, DWORD N __declspec(dllimport) bool TITCALL DeleteLastSectionExW(wchar_t* szFileName, DWORD NumberOfSections); __declspec(dllimport) ULONG_PTR TITCALL GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData); __declspec(dllimport) ULONG_PTR TITCALL GetPE32Data(char* szFileName, DWORD WhichSection, DWORD WhichData); -__declspec(dllimport) ULONG_PTR TITCALL GetPE32DataW(wchar_t* szFileName, DWORD WhichSection, DWORD WhichData); +__declspec(dllimport) ULONG_PTR TITCALL GetPE32DataW(const wchar_t* szFileName, DWORD WhichSection, DWORD WhichData); __declspec(dllimport) bool TITCALL GetPE32DataFromMappedFileEx(ULONG_PTR FileMapVA, LPVOID DataStorage); __declspec(dllimport) bool TITCALL GetPE32DataEx(char* szFileName, LPVOID DataStorage); __declspec(dllimport) bool TITCALL GetPE32DataExW(wchar_t* szFileName, LPVOID DataStorage); diff --git a/TitanEngine/Global.Engine.cpp b/TitanEngine/Global.Engine.cpp index eb62543..c2634d9 100644 --- a/TitanEngine/Global.Engine.cpp +++ b/TitanEngine/Global.Engine.cpp @@ -20,6 +20,7 @@ bool engineAutoHideFromDebugger = false; // hardcoded bool engineEnableDebugPrivilege = false; bool engineSafeAttach = false; bool engineMembpAlt = false; +bool engineDisableAslr = false; char engineFoundDLLName[512] = {0}; char engineFoundAPIName[512] = {0}; diff --git a/TitanEngine/Global.Engine.h b/TitanEngine/Global.Engine.h index a769fd3..0ab22e8 100644 --- a/TitanEngine/Global.Engine.h +++ b/TitanEngine/Global.Engine.h @@ -23,6 +23,7 @@ extern bool engineAutoHideFromDebugger; extern bool engineEnableDebugPrivilege; extern bool engineSafeAttach; extern bool engineMembpAlt; +extern bool engineDisableAslr; //Global.Engine.Functions void EngineInit(); diff --git a/TitanEngine/Global.Mapping.cpp b/TitanEngine/Global.Mapping.cpp index 689e134..188c2dc 100644 --- a/TitanEngine/Global.Mapping.cpp +++ b/TitanEngine/Global.Mapping.cpp @@ -4,7 +4,7 @@ #include "Global.Handle.h" // Global.Mapping.functions: -bool MapFileEx(char* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD FileSize, LPHANDLE FileMap, LPVOID FileMapVA, DWORD SizeModifier) +bool MapFileEx(const char* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD FileSize, LPHANDLE FileMap, LPVOID FileMapVA, DWORD SizeModifier) { DWORD FileAccess = 0; DWORD FileMapType = 0; @@ -65,7 +65,7 @@ bool MapFileEx(char* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD return false; } -bool MapFileExW(wchar_t* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD FileSize, LPHANDLE FileMap, LPVOID FileMapVA, DWORD SizeModifier) +bool MapFileExW(const wchar_t* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD FileSize, LPHANDLE FileMap, LPVOID FileMapVA, DWORD SizeModifier) { DWORD FileAccess = 0; DWORD FileMapType = 0; diff --git a/TitanEngine/Global.Mapping.h b/TitanEngine/Global.Mapping.h index 4298cc7..3108872 100644 --- a/TitanEngine/Global.Mapping.h +++ b/TitanEngine/Global.Mapping.h @@ -1,8 +1,8 @@ #ifndef _GLOBAL_MAPPING_H #define _GLOBAL_MAPPING_H -bool MapFileEx(char* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD FileSize, LPHANDLE FileMap, LPVOID FileMapVA, DWORD SizeModifier); -bool MapFileExW(wchar_t* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD FileSize, LPHANDLE FileMap, LPVOID FileMapVA, DWORD SizeModifier); +bool MapFileEx(const char* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD FileSize, LPHANDLE FileMap, LPVOID FileMapVA, DWORD SizeModifier); +bool MapFileExW(const wchar_t* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD FileSize, LPHANDLE FileMap, LPVOID FileMapVA, DWORD SizeModifier); void UnMapFileEx(HANDLE FileHandle, DWORD FileSize, HANDLE FileMap, ULONG_PTR FileMapVA); #endif //_GLOBAL_MAPPING_H \ No newline at end of file diff --git a/TitanEngine/TitanEngine.Debugger.DebugLoop.cpp b/TitanEngine/TitanEngine.Debugger.DebugLoop.cpp index a021ca6..8268ea4 100644 --- a/TitanEngine/TitanEngine.Debugger.DebugLoop.cpp +++ b/TitanEngine/TitanEngine.Debugger.DebugLoop.cpp @@ -153,6 +153,19 @@ __declspec(dllexport) void TITCALL DebugLoop() { case CREATE_PROCESS_DEBUG_EVENT: { + // HACK: when hollowing the process the debug event still delivers the original image base + if(engineDisableAslr && !DebugDebuggingDLL && DebugModuleImageBase != 0) + { + auto startAddress = ULONG_PTR(DBGEvent.u.CreateProcessInfo.lpStartAddress); + if(startAddress) + { + startAddress -= ULONG_PTR(DBGEvent.u.CreateProcessInfo.lpBaseOfImage); + startAddress += DebugModuleImageBase; + DBGEvent.u.CreateProcessInfo.lpStartAddress = LPTHREAD_START_ROUTINE(startAddress); + } + DBGEvent.u.CreateProcessInfo.lpBaseOfImage = LPVOID(DebugModuleImageBase); + } + bool attachBreakpoint = false; if(DBGFileHandle == NULL) //we didn't set the handle yet (initial process) { diff --git a/TitanEngine/TitanEngine.Debugger.cpp b/TitanEngine/TitanEngine.Debugger.cpp index db151cd..7986271 100644 --- a/TitanEngine/TitanEngine.Debugger.cpp +++ b/TitanEngine/TitanEngine.Debugger.cpp @@ -4,6 +4,7 @@ #include "Global.Engine.h" #include "Global.Handle.h" #include "Global.Threader.h" +#include "Global.Engine.Hider.h" static wchar_t szBackupDebuggedFileName[512]; @@ -41,17 +42,91 @@ __declspec(dllexport) void* TITCALL InitDebug(char* szFileName, char* szCommandL return NULL; } } + +static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMATION & pi) +{ + bool success = false; + auto hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); + if(hFile != INVALID_HANDLE_VALUE) + { + // Retrieve image base and entry point + DebugModuleImageBase = GetPE32DataW(szFileName, 0, UE_IMAGEBASE); + DebugModuleEntryPoint = GetPE32DataW(szFileName, 0, UE_OEP); + + auto hMapping = CreateFileMappingW(hFile, nullptr, SEC_IMAGE | PAGE_READONLY, 0, 0, nullptr); + if(hMapping) + { + CONTEXT ctx; + ctx.ContextFlags = CONTEXT_ALL; + if(GetThreadContext(pi.hThread, &ctx)) + { + PVOID imageBase; +#ifdef _WIN64 + auto & pebRegister = ctx.Rdx; + auto & entryPointRegister = ctx.Rcx; +#else + auto & pebRegister = ctx.Ebx; + auto & entryPointRegister = ctx.Eax; +#endif // _WIN64 + if(ReadProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr)) + { + auto status = NtUnmapViewOfSection(pi.hProcess, imageBase); + if(status == STATUS_SUCCESS) + { + SIZE_T viewSize = 0; + imageBase = PVOID(DebugModuleImageBase); + status = NtMapViewOfSection(hMapping, pi.hProcess, &imageBase, 0, 0, nullptr, &viewSize, ViewUnmap, 0, PAGE_READONLY); + if(!(status != 0 && status != STATUS_IMAGE_NOT_AT_BASE)) + { + if(WriteProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr)) + { + entryPointRegister = DebugModuleImageBase + DebugModuleEntryPoint; + if(SetThreadContext(pi.hThread, &ctx)) + { + success = true; +#ifndef _WIN64 + // For Wow64 processes, also adjust the 64-bit PEB + if(IsThisProcessWow64() && !WriteProcessMemory(pi.hProcess, (char*)pebRegister - 0x1000 + 0x10, &imageBase, sizeof(PVOID), nullptr)) + success = false; +#endif // _WIN64 + } + } + } + } + } + } + + CloseHandle(hMapping); + } + + CloseHandle(hFile); + } + + if(!success) + { + DebugModuleImageBase = 0; + DebugModuleEntryPoint = 0; + } + + return success; +} + __declspec(dllexport) void* TITCALL InitDebugW(wchar_t* szFileName, wchar_t* szCommandLine, wchar_t* szCurrentFolder) { - int DebugConsoleFlag = NULL; + int creationFlags = CREATE_NEW_CONSOLE | DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS; if(DebugDebuggingDLL) { - DebugConsoleFlag = CREATE_NO_WINDOW | CREATE_SUSPENDED; + creationFlags |= CREATE_NO_WINDOW; + creationFlags |= CREATE_SUSPENDED; } else if(engineRemoveConsoleForDebugee) { - DebugConsoleFlag = CREATE_NO_WINDOW; + creationFlags |= CREATE_NO_WINDOW; + } + else if(engineDisableAslr) + { + creationFlags = CREATE_NEW_CONSOLE | CREATE_SUSPENDED; } wchar_t* szFileNameCreateProcess; @@ -73,13 +148,20 @@ __declspec(dllexport) void* TITCALL InitDebugW(wchar_t* szFileName, wchar_t* szC szFileNameCreateProcess = 0; } // Temporarily disable the debug privilege so the child doesn't inherit it (this evades debugger detection) - if (engineEnableDebugPrivilege) + if(engineEnableDebugPrivilege) EngineSetDebugPrivilege(GetCurrentProcess(), false); - auto createProcessResult = CreateProcessW(szFileNameCreateProcess, szCommandLineCreateProcess, NULL, NULL, false, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | DebugConsoleFlag | CREATE_NEW_CONSOLE, NULL, szCurrentFolder, &dbgStartupInfo, &dbgProcessInformation); - if (engineEnableDebugPrivilege) + auto createProcessResult = CreateProcessW(szFileNameCreateProcess, szCommandLineCreateProcess, NULL, NULL, false, creationFlags, NULL, szCurrentFolder, &dbgStartupInfo, &dbgProcessInformation); + if(engineEnableDebugPrivilege) EngineSetDebugPrivilege(GetCurrentProcess(), true); if(createProcessResult) { + if(engineDisableAslr) + { + HollowProcessWithoutASLR(szFileName, dbgProcessInformation); + DebugActiveProcess_(dbgProcessInformation.dwProcessId); + DebugSetProcessKillOnExit(TRUE); + ResumeThread(dbgProcessInformation.hThread); + } DebugAttachedToProcess = false; DebugAttachedProcessCallBack = NULL; return &dbgProcessInformation; @@ -502,20 +584,13 @@ __declspec(dllexport) bool TITCALL StopDebug() __declspec(dllexport) bool TITCALL AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack) { - typedef void(WINAPI * fDebugSetProcessKillOnExit)(bool KillExitingDebugee); - fDebugSetProcessKillOnExit myDebugSetProcessKillOnExit; LPVOID funcDebugSetProcessKillOnExit = NULL; if(ProcessId != NULL && dbgProcessInformation.hProcess == NULL) { if(DebugActiveProcess_(ProcessId)) { - funcDebugSetProcessKillOnExit = GetProcAddress(GetModuleHandleA("kernel32.dll"), "DebugSetProcessKillOnExit"); - if(funcDebugSetProcessKillOnExit != NULL) - { - myDebugSetProcessKillOnExit = (fDebugSetProcessKillOnExit)(funcDebugSetProcessKillOnExit); - myDebugSetProcessKillOnExit(KillOnExit); - } + DebugSetProcessKillOnExit(KillOnExit); DebugDebuggingDLL = false; DebugAttachedToProcess = true; DebugAttachedProcessCallBack = (ULONG_PTR)CallBack; diff --git a/TitanEngine/TitanEngine.Engine.cpp b/TitanEngine/TitanEngine.Engine.cpp index 8180a84..fab5df0 100644 --- a/TitanEngine/TitanEngine.Engine.cpp +++ b/TitanEngine/TitanEngine.Engine.cpp @@ -52,6 +52,10 @@ __declspec(dllexport) void TITCALL SetEngineVariable(DWORD VariableId, bool Vari { engineMembpAlt = VariableSet; } + else if(VariableId == UE_ENGINE_DISABLE_ASLR) + { + engineDisableAslr = VariableSet; + } } __declspec(dllexport) bool TITCALL EngineCreateMissingDependencies(char* szFileName, char* szOutputFolder, bool LogCreatedFiles) diff --git a/TitanEngine/TitanEngine.PE.Data.cpp b/TitanEngine/TitanEngine.PE.Data.cpp index 762fd7e..e9e6845 100644 --- a/TitanEngine/TitanEngine.PE.Data.cpp +++ b/TitanEngine/TitanEngine.PE.Data.cpp @@ -368,7 +368,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetPE32Data(char* szFileName, DWORD Whic return(0); } } -__declspec(dllexport) ULONG_PTR TITCALL GetPE32DataW(wchar_t* szFileName, DWORD WhichSection, DWORD WhichData) +__declspec(dllexport) ULONG_PTR TITCALL GetPE32DataW(const wchar_t* szFileName, DWORD WhichSection, DWORD WhichData) { HANDLE FileHandle; diff --git a/TitanEngine/TitanEngine.vcxproj.user b/TitanEngine/TitanEngine.vcxproj.user deleted file mode 100644 index 695b5c7..0000000 --- a/TitanEngine/TitanEngine.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/TitanEngine/definitions.h b/TitanEngine/definitions.h index 73cd527..74a3144 100644 --- a/TitanEngine/definitions.h +++ b/TitanEngine/definitions.h @@ -58,7 +58,7 @@ __declspec(dllexport) bool TITCALL DeleteLastSectionEx(char* szFileName, DWORD N __declspec(dllexport) bool TITCALL DeleteLastSectionExW(wchar_t* szFileName, DWORD NumberOfSections); __declspec(dllexport) ULONG_PTR TITCALL GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData); __declspec(dllexport) ULONG_PTR TITCALL GetPE32Data(char* szFileName, DWORD WhichSection, DWORD WhichData); -__declspec(dllexport) ULONG_PTR TITCALL GetPE32DataW(wchar_t* szFileName, DWORD WhichSection, DWORD WhichData); +__declspec(dllexport) ULONG_PTR TITCALL GetPE32DataW(const wchar_t* szFileName, DWORD WhichSection, DWORD WhichData); __declspec(dllexport) bool TITCALL GetPE32DataFromMappedFileEx(ULONG_PTR FileMapVA, LPVOID DataStorage); __declspec(dllexport) bool TITCALL GetPE32DataEx(char* szFileName, LPVOID DataStorage); __declspec(dllexport) bool TITCALL GetPE32DataExW(wchar_t* szFileName, LPVOID DataStorage); diff --git a/TitanEngine/stdafx.h b/TitanEngine/stdafx.h index 50e18da..72073ec 100644 --- a/TitanEngine/stdafx.h +++ b/TitanEngine/stdafx.h @@ -472,6 +472,7 @@ typedef struct HOOK_ENTRY #define UE_ENGINE_SET_DEBUG_PRIVILEGE 9 #define UE_ENGINE_SAFE_ATTACH 10 #define UE_ENGINE_MEMBP_ALT 11 +#define UE_ENGINE_DISABLE_ASLR 12 #define UE_OPTION_REMOVEALL 1 #define UE_OPTION_DISABLEALL 2