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
cov-*
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) 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);

View File

@ -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};

View File

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

View File

@ -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;

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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)

View File

@ -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;

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) 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);

View File

@ -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