Implement UE_ENGINE_DISABLE_ASLR

This commit is contained in:
Duncan Ogilvie 2022-09-10 00:04:42 +02:00
parent 39934ea3ae
commit b435ee57d3
12 changed files with 9562 additions and 14 deletions

View File

@ -138,6 +138,18 @@ namespace GleeBug
switch(mDebugEvent.dwDebugEventCode) switch(mDebugEvent.dwDebugEventCode)
{ {
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 (mDisableAslr && mDebugModuleImageBase != 0)
{
auto startAddress = ULONG_PTR(mDebugEvent.u.CreateProcessInfo.lpStartAddress);
if (startAddress)
{
startAddress -= ULONG_PTR(mDebugEvent.u.CreateProcessInfo.lpBaseOfImage);
startAddress += mDebugModuleImageBase;
mDebugEvent.u.CreateProcessInfo.lpStartAddress = LPTHREAD_START_ROUTINE(startAddress);
}
mDebugEvent.u.CreateProcessInfo.lpBaseOfImage = LPVOID(mDebugModuleImageBase);
}
createProcessEvent(mDebugEvent.u.CreateProcessInfo); createProcessEvent(mDebugEvent.u.CreateProcessInfo);
break; break;
case EXIT_PROCESS_DEBUG_EVENT: case EXIT_PROCESS_DEBUG_EVENT:

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "ntdll.h"
static DWORD BaseSetLastNTError(IN NTSTATUS Status) static DWORD BaseSetLastNTError(IN NTSTATUS Status)
{ {
DWORD dwErrCode; DWORD dwErrCode;

View File

@ -1,3 +1,4 @@
#include "Debugger.NativeAttach.h"
#include "Debugger.h" #include "Debugger.h"
#include "Debugger.Thread.Registers.h" #include "Debugger.Thread.Registers.h"
@ -37,29 +38,52 @@ namespace GleeBug
szFileNameCreateProcess = nullptr; szFileNameCreateProcess = nullptr;
} }
auto creationFlags = DEBUG_PROCESS;
creationFlags |= DEBUG_ONLY_THIS_PROCESS; // TODO: support child process debugging
if (newConsole)
creationFlags |= CREATE_NEW_CONSOLE;
if (startSuspended)
creationFlags |= CREATE_SUSPENDED;
if (mDisableAslr)
{
creationFlags |= CREATE_SUSPENDED;
// We will attach manually later
creationFlags &= ~(DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS);
}
bool result = !!CreateProcessW(szFileNameCreateProcess, bool result = !!CreateProcessW(szFileNameCreateProcess,
szCommandLineCreateProcess, szCommandLineCreateProcess,
nullptr, nullptr,
nullptr, nullptr,
FALSE, FALSE,
DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | (newConsole ? CREATE_NEW_CONSOLE : 0) | (startSuspended ? CREATE_SUSPENDED : 0), creationFlags,
nullptr, nullptr,
szCurrentDirectory, szCurrentDirectory,
&mMainStartupInfo, &mMainStartupInfo,
&mMainProcess); &mMainProcess);
if (result && mDisableAslr)
{
HollowProcessWithoutASLR(szFileNameCreateProcess, mMainProcess);
DebugActiveProcess_(mMainProcess.dwProcessId);
DebugSetProcessKillOnExit(TRUE);
if (!startSuspended)
ResumeThread(mMainProcess.hThread);
}
delete[] szCreateWithCmdLine; delete[] szCreateWithCmdLine;
mAttachedToProcess = false; mAttachedToProcess = false;
return result; return result;
} }
bool Debugger::Attach(DWORD processId, decltype(&DebugActiveProcess) debugActiveProcess) bool Debugger::Attach(DWORD processId)
{ {
//don't allow attaching when still debugging //don't allow attaching when still debugging
if(mIsDebugging) if(mIsDebugging)
return false; return false;
if(!debugActiveProcess(processId)) if(!DebugActiveProcess_(processId))
return false; return false;
mAttachedToProcess = true; mAttachedToProcess = true;
memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo)); memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo));
@ -102,4 +126,113 @@ namespace GleeBug
mDetachAndBreak = true; mDetachAndBreak = true;
mDetach = false; mDetach = false;
} }
static bool GetPeData(HANDLE hFile, ULONG_PTR& imageBase, ULONG_PTR& entryPoint)
{
IMAGE_DOS_HEADER idh;
DWORD read = 0;
if (!ReadFile(hFile, &idh, sizeof(idh), &read, nullptr))
return false;
if (idh.e_magic != IMAGE_DOS_SIGNATURE)
return false;
if (!SetFilePointer(hFile, idh.e_lfanew, nullptr, FILE_BEGIN))
return false;
IMAGE_NT_HEADERS64 inth;
if (!ReadFile(hFile, &inth, sizeof(inth), &read, nullptr))
return false;
if (inth.Signature != IMAGE_NT_SIGNATURE)
return false;
switch (inth.FileHeader.Machine)
{
case IMAGE_FILE_MACHINE_AMD64:
{
imageBase = inth.OptionalHeader.ImageBase;
entryPoint = inth.OptionalHeader.AddressOfEntryPoint;
}
break;
case IMAGE_FILE_MACHINE_I386:
{
auto nth32 = (IMAGE_NT_HEADERS32*)&inth;
imageBase = nth32->OptionalHeader.ImageBase;
entryPoint = nth32->OptionalHeader.AddressOfEntryPoint;
}
break;
default:
return false;
}
return true;
}
bool Debugger::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
ULONG_PTR debugModuleEntryPoint = 0;
if (GetPeData(hFile, mDebugModuleImageBase, debugModuleEntryPoint))
{
SetFilePointer(hFile, 0, nullptr, FILE_BEGIN);
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;
// TODO: support wow64 processes
#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(mDebugModuleImageBase);
status = NtMapViewOfSection(hMapping, pi.hProcess, &imageBase, 0, 0, nullptr, &viewSize, ViewUnmap, 0, PAGE_READONLY);
if (status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE)
{
if (WriteProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr))
{
entryPointRegister = mDebugModuleImageBase + 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)
{
mDebugModuleImageBase = 0;
}
return success;
}
}; };

View File

@ -47,7 +47,7 @@ namespace GleeBug
\param processId Process to attach to. \param processId Process to attach to.
\return true if the debuggee was attached to successfully, false otherwise. \return true if the debuggee was attached to successfully, false otherwise.
*/ */
bool Attach(DWORD processId, decltype(&DebugActiveProcess) = &DebugActiveProcess); bool Attach(DWORD processId);
/** /**
\brief Stops the debuggee (terminate the process) \brief Stops the debuggee (terminate the process)
@ -293,6 +293,7 @@ namespace GleeBug
bool mDetachAndBreak = false; bool mDetachAndBreak = false;
bool mAttachedToProcess = false; bool mAttachedToProcess = false;
bool mSafeStep = true; bool mSafeStep = true;
bool mDisableAslr = false;
/** /**
\brief The current process (can be null in some cases). \brief The current process (can be null in some cases).
@ -303,6 +304,10 @@ namespace GleeBug
\brief The current thread (can be null in some cases). Should be a copy of mProcess->thread. \brief The current thread (can be null in some cases). Should be a copy of mProcess->thread.
*/ */
Thread* mThread = nullptr; Thread* mThread = nullptr;
private:
bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMATION& pi);
ULONG_PTR mDebugModuleImageBase = 0;
}; };
}; };

View File

@ -188,6 +188,7 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="Debugger.Breakpoint.h" /> <ClInclude Include="Debugger.Breakpoint.h" />
<ClInclude Include="Debugger.Dll.h" /> <ClInclude Include="Debugger.Dll.h" />
<ClInclude Include="Debugger.NativeAttach.h" />
<ClInclude Include="Debugger.Process.h" /> <ClInclude Include="Debugger.Process.h" />
<ClInclude Include="Debugger.h" /> <ClInclude Include="Debugger.h" />
<ClInclude Include="Debugger.Thread.h" /> <ClInclude Include="Debugger.Thread.h" />
@ -196,6 +197,7 @@
<ClInclude Include="Debugger.Thread.Registers.h" /> <ClInclude Include="Debugger.Thread.Registers.h" />
<ClInclude Include="Debugger.Thread.Registers.Register.h" /> <ClInclude Include="Debugger.Thread.Registers.Register.h" />
<ClInclude Include="GleeBug.h" /> <ClInclude Include="GleeBug.h" />
<ClInclude Include="ntdll.h" />
<ClInclude Include="oprintf.h" /> <ClInclude Include="oprintf.h" />
<ClInclude Include="Static.BufferFile.h" /> <ClInclude Include="Static.BufferFile.h" />
<ClInclude Include="Static.File.h" /> <ClInclude Include="Static.File.h" />

View File

@ -199,6 +199,12 @@
<ClInclude Include="stringutils.h"> <ClInclude Include="stringutils.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Debugger.NativeAttach.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ntdll.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="zyan-disassembler-engine\include\Zydis\Internal\GeneratedTypes.inc"> <None Include="zyan-disassembler-engine\include\Zydis\Internal\GeneratedTypes.inc">

9394
GleeBug/ntdll.h Normal file

File diff suppressed because it is too large Load Diff

BIN
GleeBug/ntdll_x64.lib Normal file

Binary file not shown.

BIN
GleeBug/ntdll_x86.lib Normal file

Binary file not shown.

View File

@ -6,7 +6,6 @@
#include "TitanEngine.h" #include "TitanEngine.h"
#include "FileMap.h" #include "FileMap.h"
#include "PEB.h" #include "PEB.h"
#include "NativeAttach.h"
#include "Global.Engine.Context.h" #include "Global.Engine.Context.h"
#include "Hider.h" #include "Hider.h"
@ -68,7 +67,7 @@ public:
bool AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack) bool AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack)
{ {
if(!Attach(ProcessId, DebugActiveProcess_)) if(!Attach(ProcessId))
return false; return false;
mCbATTACHBREAKPOINT = STEPCALLBACK(CallBack); mCbATTACHBREAKPOINT = STEPCALLBACK(CallBack);
mAttachProcessInfo = (PROCESS_INFORMATION*)DebugInfo; mAttachProcessInfo = (PROCESS_INFORMATION*)DebugInfo;
@ -188,12 +187,12 @@ public:
case UE_ENGINE_SET_DEBUG_PRIVILEGE: case UE_ENGINE_SET_DEBUG_PRIVILEGE:
mSetDebugPrivilege = VariableSet; mSetDebugPrivilege = VariableSet;
break; break;
case UE_ENGINE_SAFE_ATTACH:
mSafeAttach = VariableSet;
break;
case UE_ENGINE_SAFE_STEP: case UE_ENGINE_SAFE_STEP:
mSafeStep = VariableSet; mSafeStep = VariableSet;
break; break;
case UE_ENGINE_DISABLE_ASLR:
mDisableAslr = VariableSet;
break;
} }
} }
@ -1301,7 +1300,6 @@ private: //functions
private: //variables private: //variables
bool mSetDebugPrivilege = false; bool mSetDebugPrivilege = false;
bool mSafeAttach = false;
typedef void(*CUSTOMHANDLER)(const void*); typedef void(*CUSTOMHANDLER)(const void*);
typedef void(*STEPCALLBACK)(); typedef void(*STEPCALLBACK)();
typedef STEPCALLBACK BPCALLBACK; typedef STEPCALLBACK BPCALLBACK;

View File

@ -154,7 +154,6 @@
<ClInclude Include="FileMap.h" /> <ClInclude Include="FileMap.h" />
<ClInclude Include="Global.Engine.Context.h" /> <ClInclude Include="Global.Engine.Context.h" />
<ClInclude Include="Hider.h" /> <ClInclude Include="Hider.h" />
<ClInclude Include="NativeAttach.h" />
<ClInclude Include="ntdll.h" /> <ClInclude Include="ntdll.h" />
<ClInclude Include="PEB.h" /> <ClInclude Include="PEB.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />

View File

@ -43,9 +43,6 @@
<ClInclude Include="resource.h"> <ClInclude Include="resource.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="NativeAttach.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ntdll.h"> <ClInclude Include="ntdll.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>