Improve no ASLR by retrying

This commit is contained in:
Duncan Ogilvie 2022-09-10 01:13:09 +02:00
parent d0b7e5addd
commit 259f1e88e3
1 changed files with 55 additions and 26 deletions

View File

@ -47,46 +47,62 @@ static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMAT
{ {
bool success = false; bool success = false;
auto hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); auto hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if(hFile != INVALID_HANDLE_VALUE) if (hFile != INVALID_HANDLE_VALUE)
{ {
// Retrieve image base and entry point // Retrieve image base and entry point
DebugModuleImageBase = GetPE32DataW(szFileName, 0, UE_IMAGEBASE); DebugModuleImageBase = GetPE32DataW(szFileName, 0, UE_IMAGEBASE);
DebugModuleEntryPoint = GetPE32DataW(szFileName, 0, UE_OEP); DebugModuleEntryPoint = GetPE32DataW(szFileName, 0, UE_OEP);
auto hMapping = CreateFileMappingW(hFile, nullptr, SEC_IMAGE | PAGE_READONLY, 0, 0, nullptr); auto hMapping = CreateFileMappingW(hFile, nullptr, SEC_IMAGE | PAGE_READONLY, 0, 0, nullptr);
if(hMapping) if (hMapping)
{ {
CONTEXT ctx; CONTEXT ctx;
ctx.ContextFlags = CONTEXT_ALL; ctx.ContextFlags = CONTEXT_ALL;
if(GetThreadContext(pi.hThread, &ctx)) if (GetThreadContext(pi.hThread, &ctx))
{ {
PVOID imageBase; PVOID imageBase;
// TODO: support wow64 processes
#ifdef _WIN64 #ifdef _WIN64
auto & pebRegister = ctx.Rdx; auto& pebRegister = ctx.Rdx;
auto & entryPointRegister = ctx.Rcx; auto& entryPointRegister = ctx.Rcx;
#else #else
auto & pebRegister = ctx.Ebx; auto& pebRegister = ctx.Ebx;
auto & entryPointRegister = ctx.Eax; auto& entryPointRegister = ctx.Eax;
#endif // _WIN64 #endif // _WIN64
if(ReadProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr)) if (ReadProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr))
{
if (ULONG_PTR(imageBase) == DebugModuleImageBase)
{
// Already at the right base
success = true;
}
else
{ {
auto status = NtUnmapViewOfSection(pi.hProcess, imageBase); auto status = NtUnmapViewOfSection(pi.hProcess, imageBase);
if(status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
{ {
SIZE_T viewSize = 0; SIZE_T viewSize = 0;
imageBase = PVOID(DebugModuleImageBase); imageBase = PVOID(DebugModuleImageBase);
status = NtMapViewOfSection(hMapping, pi.hProcess, &imageBase, 0, 0, nullptr, &viewSize, ViewUnmap, 0, PAGE_READONLY); status = NtMapViewOfSection(hMapping, pi.hProcess, &imageBase, 0, 0, nullptr, &viewSize, ViewUnmap, 0, PAGE_READONLY);
if(!(status != 0 && status != STATUS_IMAGE_NOT_AT_BASE)) if (status == STATUS_CONFLICTING_ADDRESSES)
{ {
if(WriteProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr)) // Remap in a random location (otherwise the process will crash)
imageBase = 0;
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))
{
auto expectedBase = DebugModuleImageBase == ULONG_PTR(imageBase);
DebugModuleImageBase = ULONG_PTR(imageBase);
entryPointRegister = DebugModuleImageBase + DebugModuleEntryPoint; entryPointRegister = DebugModuleImageBase + DebugModuleEntryPoint;
if(SetThreadContext(pi.hThread, &ctx)) if (SetThreadContext(pi.hThread, &ctx))
{ {
success = true; success = expectedBase;
#ifndef _WIN64 #ifndef _WIN64
// For Wow64 processes, also adjust the 64-bit PEB // For Wow64 processes, also adjust the 64-bit PEB
if(IsThisProcessWow64() && !WriteProcessMemory(pi.hProcess, (char*)pebRegister - 0x1000 + 0x10, &imageBase, sizeof(PVOID), nullptr)) if (IsThisProcessWow64() && !WriteProcessMemory(pi.hProcess, (char*)pebRegister - 0x1000 + 0x10, &imageBase, sizeof(PVOID), nullptr))
success = false; success = false;
#endif // _WIN64 #endif // _WIN64
} }
@ -95,6 +111,7 @@ static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMAT
} }
} }
} }
}
CloseHandle(hMapping); CloseHandle(hMapping);
} }
@ -105,7 +122,6 @@ static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMAT
if(!success) if(!success)
{ {
DebugModuleImageBase = 0; DebugModuleImageBase = 0;
DebugModuleEntryPoint = 0;
} }
return success; return success;
@ -147,6 +163,8 @@ __declspec(dllexport) void* TITCALL InitDebugW(wchar_t* szFileName, wchar_t* szC
szCommandLineCreateProcess = (wchar_t*)createWithCmdLine.c_str(); szCommandLineCreateProcess = (wchar_t*)createWithCmdLine.c_str();
szFileNameCreateProcess = 0; szFileNameCreateProcess = 0;
} }
int retries = 0;
retry_no_aslr:
// 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);
@ -157,11 +175,22 @@ __declspec(dllexport) void* TITCALL InitDebugW(wchar_t* szFileName, wchar_t* szC
{ {
if(engineDisableAslr) if(engineDisableAslr)
{ {
HollowProcessWithoutASLR(szFileName, dbgProcessInformation); if (!HollowProcessWithoutASLR(szFileName, dbgProcessInformation))
{
TerminateThread(dbgProcessInformation.hThread, STATUS_CONFLICTING_ADDRESSES);
TerminateProcess(dbgProcessInformation.hProcess, STATUS_CONFLICTING_ADDRESSES);
if (retries++ < 10)
goto retry_no_aslr;
memset(&dbgProcessInformation, 0, sizeof(PROCESS_INFORMATION));
return nullptr;
}
else
{
DebugActiveProcess_(dbgProcessInformation.dwProcessId); DebugActiveProcess_(dbgProcessInformation.dwProcessId);
DebugSetProcessKillOnExit(TRUE); DebugSetProcessKillOnExit(TRUE);
ResumeThread(dbgProcessInformation.hThread); ResumeThread(dbgProcessInformation.hThread);
} }
}
DebugAttachedToProcess = false; DebugAttachedToProcess = false;
DebugAttachedProcessCallBack = NULL; DebugAttachedProcessCallBack = NULL;
return &dbgProcessInformation; return &dbgProcessInformation;