mirror of https://github.com/x64dbg/TitanEngine
Support disabling ASLR for WoW64 targets
This commit is contained in:
parent
89e251c54e
commit
69ed2e093c
|
|
@ -43,15 +43,12 @@ __declspec(dllexport) void* TITCALL InitDebug(char* szFileName, char* szCommandL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ProcessRelocations(char* imageCopy, ULONG_PTR imageSize, ULONG_PTR newImageBase, ULONG_PTR & oldImageBase)
|
template<typename NtHeaders>
|
||||||
|
static bool ProcessRelocationsForArchitecture(char* imageCopy, NtHeaders* pnth, ULONG_PTR newImageBase, ULONG_PTR & oldImageBase)
|
||||||
{
|
{
|
||||||
auto pnth = RtlImageNtHeader(imageCopy);
|
// Put the new base in the header using the image's pointer width.
|
||||||
if(pnth == nullptr)
|
oldImageBase = ULONG_PTR(pnth->OptionalHeader.ImageBase);
|
||||||
return false;
|
pnth->OptionalHeader.ImageBase = decltype(pnth->OptionalHeader.ImageBase)(newImageBase);
|
||||||
|
|
||||||
// Put the new base in the header
|
|
||||||
oldImageBase = pnth->OptionalHeader.ImageBase;
|
|
||||||
pnth->OptionalHeader.ImageBase = newImageBase;
|
|
||||||
|
|
||||||
// Nothing to do if relocations are stripped
|
// Nothing to do if relocations are stripped
|
||||||
if(pnth->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
|
if(pnth->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
|
||||||
|
|
@ -63,7 +60,7 @@ static bool ProcessRelocations(char* imageCopy, ULONG_PTR imageSize, ULONG_PTR n
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Process the relocations
|
// Process the relocations
|
||||||
auto delta = newImageBase - oldImageBase;
|
auto delta = LONG_PTR(newImageBase) - LONG_PTR(oldImageBase);
|
||||||
auto relocationItr = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)imageCopy + relocDir.VirtualAddress);
|
auto relocationItr = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)imageCopy + relocDir.VirtualAddress);
|
||||||
auto relocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)relocationItr + relocDir.Size);
|
auto relocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)relocationItr + relocDir.Size);
|
||||||
|
|
||||||
|
|
@ -80,6 +77,20 @@ static bool ProcessRelocations(char* imageCopy, ULONG_PTR imageSize, ULONG_PTR n
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ProcessRelocations(char* imageCopy, ULONG_PTR newImageBase, ULONG_PTR & oldImageBase)
|
||||||
|
{
|
||||||
|
auto pnth = RtlImageNtHeader(imageCopy);
|
||||||
|
if(pnth == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto magic = ((PIMAGE_NT_HEADERS32)pnth)->OptionalHeader.Magic;
|
||||||
|
if(magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||||
|
return ProcessRelocationsForArchitecture(imageCopy, (PIMAGE_NT_HEADERS32)pnth, newImageBase, oldImageBase);
|
||||||
|
if(magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||||
|
return ProcessRelocationsForArchitecture(imageCopy, (PIMAGE_NT_HEADERS64)pnth, newImageBase, oldImageBase);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool RelocateImage(HANDLE hProcess, PVOID imageBase, SIZE_T imageSize)
|
static bool RelocateImage(HANDLE hProcess, PVOID imageBase, SIZE_T imageSize)
|
||||||
{
|
{
|
||||||
constexpr auto pageSize = 0x1000;
|
constexpr auto pageSize = 0x1000;
|
||||||
|
|
@ -100,7 +111,7 @@ static bool RelocateImage(HANDLE hProcess, PVOID imageBase, SIZE_T imageSize)
|
||||||
|
|
||||||
// perform the actual relocations
|
// perform the actual relocations
|
||||||
ULONG_PTR oldImageBase = 0;
|
ULONG_PTR oldImageBase = 0;
|
||||||
auto success = ProcessRelocations(imageCopy, imageSize, (ULONG_PTR)imageBase, oldImageBase);
|
auto success = ProcessRelocations(imageCopy, (ULONG_PTR)imageBase, oldImageBase);
|
||||||
|
|
||||||
// write back the pages
|
// write back the pages
|
||||||
auto memWrite = [hProcess](PVOID ptr, LPCVOID data, SIZE_T size)
|
auto memWrite = [hProcess](PVOID ptr, LPCVOID data, SIZE_T size)
|
||||||
|
|
@ -165,28 +176,45 @@ static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMAT
|
||||||
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;
|
bool isWow64 = false;
|
||||||
// TODO: support wow64 processes
|
ULONG_PTR pebAddress = 0;
|
||||||
|
SIZE_T imageBaseOffset = 0;
|
||||||
|
SIZE_T imageBaseSize = 0;
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
auto & pebRegister = ctx.Rdx;
|
ULONG returnLength = 0;
|
||||||
auto & entryPointRegister = ctx.Rcx;
|
if(NT_SUCCESS(NtQueryInformationProcess(pi.hProcess, ProcessWow64Information, &pebAddress, sizeof(pebAddress), &returnLength)) && pebAddress != 0)
|
||||||
#else
|
|
||||||
auto & pebRegister = ctx.Ebx;
|
|
||||||
auto & entryPointRegister = ctx.Eax;
|
|
||||||
#endif // _WIN64
|
|
||||||
if(ReadProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr))
|
|
||||||
{
|
{
|
||||||
if(ULONG_PTR(imageBase) == DebugModuleImageBase)
|
isWow64 = true;
|
||||||
|
imageBaseOffset = offsetof(PEB32, ImageBaseAddress);
|
||||||
|
imageBaseSize = sizeof(DWORD);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pebAddress = ctx.Rdx;
|
||||||
|
imageBaseOffset = offsetof(PEB64, ImageBaseAddress);
|
||||||
|
imageBaseSize = sizeof(DWORD64);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
pebAddress = ctx.Ebx;
|
||||||
|
imageBaseOffset = offsetof(PEB32, ImageBaseAddress);
|
||||||
|
imageBaseSize = sizeof(DWORD);
|
||||||
|
#endif // _WIN64
|
||||||
|
|
||||||
|
ULONG_PTR imageBaseValue = 0;
|
||||||
|
if(ReadProcessMemory(pi.hProcess, (char*)pebAddress + imageBaseOffset, &imageBaseValue, imageBaseSize, nullptr))
|
||||||
|
{
|
||||||
|
if(imageBaseValue == DebugModuleImageBase)
|
||||||
{
|
{
|
||||||
// Already at the right base
|
// Already at the right base
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
auto imageBase = PVOID(imageBaseValue);
|
||||||
auto status = NtUnmapViewOfSection(pi.hProcess, imageBase);
|
auto status = NtUnmapViewOfSection(pi.hProcess, imageBase);
|
||||||
if(status == STATUS_SUCCESS)
|
if(status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
@ -201,23 +229,60 @@ static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMAT
|
||||||
}
|
}
|
||||||
if(status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE)
|
if(status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE)
|
||||||
{
|
{
|
||||||
auto pebOk = WriteProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr);
|
imageBaseValue = ULONG_PTR(imageBase);
|
||||||
|
auto pebOk = WriteProcessMemory(pi.hProcess, (char*)pebAddress + imageBaseOffset, &imageBaseValue, imageBaseSize, nullptr);
|
||||||
|
#ifdef _WIN64
|
||||||
|
if(pebOk && isWow64)
|
||||||
|
{
|
||||||
|
PROCESS_BASIC_INFORMATION processInfo = {};
|
||||||
|
if(NT_SUCCESS(NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &processInfo, sizeof(processInfo), &returnLength)))
|
||||||
|
{
|
||||||
|
DWORD64 imageBase64 = imageBaseValue;
|
||||||
|
pebOk = WriteProcessMemory(pi.hProcess, (char*)processInfo.PebBaseAddress + offsetof(PEB64, ImageBaseAddress), &imageBase64, sizeof(imageBase64), nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pebOk = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(pebOk && IsThisProcessWow64())
|
||||||
|
{
|
||||||
|
auto peb64 = GetPEBLocation64(pi.hProcess);
|
||||||
|
DWORD64 imageBase64 = imageBaseValue;
|
||||||
|
pebOk = peb64 != nullptr && WriteProcessMemory(pi.hProcess, (char*)peb64 + offsetof(PEB64, ImageBaseAddress), &imageBase64, sizeof(imageBase64), nullptr);
|
||||||
|
}
|
||||||
|
#endif // _WIN64
|
||||||
auto relocatedOk = RelocateImage(pi.hProcess, imageBase, viewSize);
|
auto relocatedOk = RelocateImage(pi.hProcess, imageBase, viewSize);
|
||||||
if(pebOk && relocatedOk)
|
if(pebOk && relocatedOk)
|
||||||
{
|
{
|
||||||
auto expectedBase = DebugModuleImageBase == ULONG_PTR(imageBase);
|
auto expectedBase = DebugModuleImageBase == imageBaseValue;
|
||||||
DebugModuleImageBase = ULONG_PTR(imageBase);
|
DebugModuleImageBase = imageBaseValue;
|
||||||
entryPointRegister = DebugModuleImageBase + DebugModuleEntryPoint;
|
auto entryPoint = DebugModuleImageBase + DebugModuleEntryPoint;
|
||||||
if(SetThreadContext(pi.hThread, &ctx))
|
bool contextOk = false;
|
||||||
|
#ifdef _WIN64
|
||||||
|
if(isWow64)
|
||||||
{
|
{
|
||||||
success = expectedBase;
|
WOW64_CONTEXT ctx32 = {};
|
||||||
#ifndef _WIN64
|
ctx32.ContextFlags = WOW64_CONTEXT_INTEGER;
|
||||||
// For Wow64 processes, also adjust the 64-bit PEB
|
if(Wow64GetThreadContext(pi.hThread, &ctx32))
|
||||||
if(IsThisProcessWow64() && !WriteProcessMemory(pi.hProcess, (char*)pebRegister - 0x1000 + 0x10, &imageBase, sizeof(PVOID), nullptr))
|
{
|
||||||
success = false;
|
ctx32.Eax = DWORD(entryPoint);
|
||||||
#endif // _WIN64
|
contextOk = Wow64SetThreadContext(pi.hThread, &ctx32) != FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx.Rcx = entryPoint;
|
||||||
|
contextOk = SetThreadContext(pi.hThread, &ctx) != FALSE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ctx.Eax = DWORD(entryPoint);
|
||||||
|
contextOk = SetThreadContext(pi.hThread, &ctx) != FALSE;
|
||||||
|
#endif // _WIN64
|
||||||
|
if(contextOk)
|
||||||
|
success = expectedBase;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue