Add UE_ENGINE_DISABLE_ASLR to remap the debuggee image without ASLR

This commit is contained in:
Duncan Ogilvie 2021-11-14 13:59:16 +01:00
parent 39fe35a09e
commit 0f81825ff0
13 changed files with 117 additions and 24 deletions

1
.gitignore vendored
View File

@ -160,3 +160,4 @@ $RECYCLE.BIN/
*.cbTemp *.cbTemp
cov-* cov-*
coverity* coverity*
*.user

View File

@ -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) 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 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 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 GetPE32DataFromMappedFileEx(ULONG_PTR FileMapVA, LPVOID DataStorage);
__declspec(dllimport) bool TITCALL GetPE32DataEx(char* szFileName, LPVOID DataStorage); __declspec(dllimport) bool TITCALL GetPE32DataEx(char* szFileName, LPVOID DataStorage);
__declspec(dllimport) bool TITCALL GetPE32DataExW(wchar_t* szFileName, LPVOID DataStorage); __declspec(dllimport) bool TITCALL GetPE32DataExW(wchar_t* szFileName, LPVOID DataStorage);

View File

@ -20,6 +20,7 @@ bool engineAutoHideFromDebugger = false; // hardcoded
bool engineEnableDebugPrivilege = false; bool engineEnableDebugPrivilege = false;
bool engineSafeAttach = false; bool engineSafeAttach = false;
bool engineMembpAlt = false; bool engineMembpAlt = false;
bool engineDisableAslr = false;
char engineFoundDLLName[512] = {0}; char engineFoundDLLName[512] = {0};
char engineFoundAPIName[512] = {0}; char engineFoundAPIName[512] = {0};

View File

@ -23,6 +23,7 @@ extern bool engineAutoHideFromDebugger;
extern bool engineEnableDebugPrivilege; extern bool engineEnableDebugPrivilege;
extern bool engineSafeAttach; extern bool engineSafeAttach;
extern bool engineMembpAlt; extern bool engineMembpAlt;
extern bool engineDisableAslr;
//Global.Engine.Functions //Global.Engine.Functions
void EngineInit(); void EngineInit();

View File

@ -4,7 +4,7 @@
#include "Global.Handle.h" #include "Global.Handle.h"
// Global.Mapping.functions: // 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 FileAccess = 0;
DWORD FileMapType = 0; DWORD FileMapType = 0;
@ -65,7 +65,7 @@ bool MapFileEx(char* szFileName, DWORD ReadOrWrite, LPHANDLE FileHandle, LPDWORD
return false; 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 FileAccess = 0;
DWORD FileMapType = 0; DWORD FileMapType = 0;

View File

@ -1,8 +1,8 @@
#ifndef _GLOBAL_MAPPING_H #ifndef _GLOBAL_MAPPING_H
#define _GLOBAL_MAPPING_H #define _GLOBAL_MAPPING_H
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);
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);
void UnMapFileEx(HANDLE FileHandle, DWORD FileSize, HANDLE FileMap, ULONG_PTR FileMapVA); void UnMapFileEx(HANDLE FileHandle, DWORD FileSize, HANDLE FileMap, ULONG_PTR FileMapVA);
#endif //_GLOBAL_MAPPING_H #endif //_GLOBAL_MAPPING_H

View File

@ -153,6 +153,19 @@ __declspec(dllexport) void TITCALL DebugLoop()
{ {
case CREATE_PROCESS_DEBUG_EVENT: 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; bool attachBreakpoint = false;
if(DBGFileHandle == NULL) //we didn't set the handle yet (initial process) if(DBGFileHandle == NULL) //we didn't set the handle yet (initial process)
{ {

View File

@ -4,6 +4,7 @@
#include "Global.Engine.h" #include "Global.Engine.h"
#include "Global.Handle.h" #include "Global.Handle.h"
#include "Global.Threader.h" #include "Global.Threader.h"
#include "Global.Engine.Hider.h"
static wchar_t szBackupDebuggedFileName[512]; static wchar_t szBackupDebuggedFileName[512];
@ -41,17 +42,91 @@ __declspec(dllexport) void* TITCALL InitDebug(char* szFileName, char* szCommandL
return NULL; 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) __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) if(DebugDebuggingDLL)
{ {
DebugConsoleFlag = CREATE_NO_WINDOW | CREATE_SUSPENDED; creationFlags |= CREATE_NO_WINDOW;
creationFlags |= CREATE_SUSPENDED;
} }
else if(engineRemoveConsoleForDebugee) else if(engineRemoveConsoleForDebugee)
{ {
DebugConsoleFlag = CREATE_NO_WINDOW; creationFlags |= CREATE_NO_WINDOW;
}
else if(engineDisableAslr)
{
creationFlags = CREATE_NEW_CONSOLE | CREATE_SUSPENDED;
} }
wchar_t* szFileNameCreateProcess; wchar_t* szFileNameCreateProcess;
@ -73,13 +148,20 @@ __declspec(dllexport) void* TITCALL InitDebugW(wchar_t* szFileName, wchar_t* szC
szFileNameCreateProcess = 0; szFileNameCreateProcess = 0;
} }
// Temporarily disable the debug privilege so the child doesn't inherit it (this evades debugger detection) // Temporarily disable the debug privilege so the child doesn't inherit it (this evades debugger detection)
if (engineEnableDebugPrivilege) if(engineEnableDebugPrivilege)
EngineSetDebugPrivilege(GetCurrentProcess(), false); 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); auto createProcessResult = CreateProcessW(szFileNameCreateProcess, szCommandLineCreateProcess, NULL, NULL, false, creationFlags, NULL, szCurrentFolder, &dbgStartupInfo, &dbgProcessInformation);
if (engineEnableDebugPrivilege) if(engineEnableDebugPrivilege)
EngineSetDebugPrivilege(GetCurrentProcess(), true); EngineSetDebugPrivilege(GetCurrentProcess(), true);
if(createProcessResult) if(createProcessResult)
{ {
if(engineDisableAslr)
{
HollowProcessWithoutASLR(szFileName, dbgProcessInformation);
DebugActiveProcess_(dbgProcessInformation.dwProcessId);
DebugSetProcessKillOnExit(TRUE);
ResumeThread(dbgProcessInformation.hThread);
}
DebugAttachedToProcess = false; DebugAttachedToProcess = false;
DebugAttachedProcessCallBack = NULL; DebugAttachedProcessCallBack = NULL;
return &dbgProcessInformation; return &dbgProcessInformation;
@ -502,20 +584,13 @@ __declspec(dllexport) bool TITCALL StopDebug()
__declspec(dllexport) bool TITCALL AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack) __declspec(dllexport) bool TITCALL AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack)
{ {
typedef void(WINAPI * fDebugSetProcessKillOnExit)(bool KillExitingDebugee);
fDebugSetProcessKillOnExit myDebugSetProcessKillOnExit;
LPVOID funcDebugSetProcessKillOnExit = NULL; LPVOID funcDebugSetProcessKillOnExit = NULL;
if(ProcessId != NULL && dbgProcessInformation.hProcess == NULL) if(ProcessId != NULL && dbgProcessInformation.hProcess == NULL)
{ {
if(DebugActiveProcess_(ProcessId)) if(DebugActiveProcess_(ProcessId))
{ {
funcDebugSetProcessKillOnExit = GetProcAddress(GetModuleHandleA("kernel32.dll"), "DebugSetProcessKillOnExit"); DebugSetProcessKillOnExit(KillOnExit);
if(funcDebugSetProcessKillOnExit != NULL)
{
myDebugSetProcessKillOnExit = (fDebugSetProcessKillOnExit)(funcDebugSetProcessKillOnExit);
myDebugSetProcessKillOnExit(KillOnExit);
}
DebugDebuggingDLL = false; DebugDebuggingDLL = false;
DebugAttachedToProcess = true; DebugAttachedToProcess = true;
DebugAttachedProcessCallBack = (ULONG_PTR)CallBack; DebugAttachedProcessCallBack = (ULONG_PTR)CallBack;

View File

@ -52,6 +52,10 @@ __declspec(dllexport) void TITCALL SetEngineVariable(DWORD VariableId, bool Vari
{ {
engineMembpAlt = VariableSet; engineMembpAlt = VariableSet;
} }
else if(VariableId == UE_ENGINE_DISABLE_ASLR)
{
engineDisableAslr = VariableSet;
}
} }
__declspec(dllexport) bool TITCALL EngineCreateMissingDependencies(char* szFileName, char* szOutputFolder, bool LogCreatedFiles) __declspec(dllexport) bool TITCALL EngineCreateMissingDependencies(char* szFileName, char* szOutputFolder, bool LogCreatedFiles)

View File

@ -368,7 +368,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetPE32Data(char* szFileName, DWORD Whic
return(0); 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; HANDLE FileHandle;

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>

View File

@ -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) 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 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 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 GetPE32DataFromMappedFileEx(ULONG_PTR FileMapVA, LPVOID DataStorage);
__declspec(dllexport) bool TITCALL GetPE32DataEx(char* szFileName, LPVOID DataStorage); __declspec(dllexport) bool TITCALL GetPE32DataEx(char* szFileName, LPVOID DataStorage);
__declspec(dllexport) bool TITCALL GetPE32DataExW(wchar_t* szFileName, LPVOID DataStorage); __declspec(dllexport) bool TITCALL GetPE32DataExW(wchar_t* szFileName, LPVOID DataStorage);

View File

@ -472,6 +472,7 @@ typedef struct HOOK_ENTRY
#define UE_ENGINE_SET_DEBUG_PRIVILEGE 9 #define UE_ENGINE_SET_DEBUG_PRIVILEGE 9
#define UE_ENGINE_SAFE_ATTACH 10 #define UE_ENGINE_SAFE_ATTACH 10
#define UE_ENGINE_MEMBP_ALT 11 #define UE_ENGINE_MEMBP_ALT 11
#define UE_ENGINE_DISABLE_ASLR 12
#define UE_OPTION_REMOVEALL 1 #define UE_OPTION_REMOVEALL 1
#define UE_OPTION_DISABLEALL 2 #define UE_OPTION_DISABLEALL 2