From 7a32180ad41190f5bd79939e185d76e0f4452566 Mon Sep 17 00:00:00 2001 From: Leo <16115820+Leopard20@users.noreply.github.com> Date: Sat, 6 Jan 2024 21:17:05 +0330 Subject: [PATCH] Loader fixes and improvements (#291) * Use better and safer alternative to IsBadReadPtr; Fix loader for vc143; Fix hashmap poolAlloc * Fix Linux build --- src/host/loader/StateTypes.hpp | 3 ++- src/host/loader/loader.cpp | 19 ++++++++++++---- src/host/loader/ptraccess.h | 40 ++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/host/loader/StateTypes.hpp b/src/host/loader/StateTypes.hpp index 63efe92e..a952d4c8 100644 --- a/src/host/loader/StateTypes.hpp +++ b/src/host/loader/StateTypes.hpp @@ -11,8 +11,9 @@ namespace intercept { if (arr.size() != arr.capacity()) return false; - if (IsBadReadPtr(arr.data(), sizeof(void*))) + if (IsBadReadPtr(arr.data(), sizeof(void*) + 2 * sizeof(int))) return false; + return true; } diff --git a/src/host/loader/loader.cpp b/src/host/loader/loader.cpp index f2a287fa..9f33e584 100644 --- a/src/host/loader/loader.cpp +++ b/src/host/loader/loader.cpp @@ -176,7 +176,7 @@ namespace intercept { auto future_poolFuncAlloc = std::async([&]() { auto result = memorySections.findInMemoryPattern("\x40\x53\x48\x83\xEC\x20\xFF\x41\x60\x48\x8B\x41\x08\x48\x8B\xD9\x48\x3B\xC1\x74\x0B\x48\x85\xC0\x74\x06\x48\x83\xC0\xE0\x75\x2B\x48\x8D\x41\x18\x48\x8B\x49\x20\x48\x3B\xC8\x74\x0E\x48\x85\xC9\x74\x09\x48\x8D\x41\xE0\x48\x85\xC0\x75\x10\x48\x8B\xCB\xE8\x00\x00\x00\x00\x84\xC0\x0F\x84\x00\x00\x00\x00\x4C\x8B\x43\x08\x32\xC9\x45\x33\xD2\x4C\x3B\xC3\x74\x0B\x4D\x85\xC0\x74\x06\x49\x83\xC0\xE0\x75\x2A\x4C\x8B\x43\x20\x48\x8D\x43\x18\x4C\x3B\xC0", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx????xxxx????xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); if (!result) //vc143 - result = memorySections.findInMemoryPattern("\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x20\xFF\x41\x60\x33\xF6\x48\x8B\x41\x08\x48\x8B\xD9\x48\x3B\xC1\x74\x0F\x48\x85\xC0\x74\x0A\x48\x83\xC0\xE0\x0F\x85\x00\x00\x00\x00\x48\x8B\x41\x20\x48\x8D\x79\x18\x48\x3B\xC7\x74\x0F\x48\x85\xC0\x74\x0A\x48\x83\xC0\xE0\x0F\x85\x00\x00\x00\x00\x48\x63\x51\x58\x48\x8B\x0D\x00\x00\x00\x00\x4C\x8B\xC2\x48\x8B\x01\xFF\x50\x38\x48\x89\x70\x28\x48\x8B\xD0\x48\x89\x70\x20\x48\x8D\x48\x20\x48\x85\xC0\x0F\x84\x00\x00\x00\x00\x89\x30\x89\x70\x10\x48\x89\x58\x08\x48\x8B\x47\x08\x48\x89\x08\x48\x8B\x47\x08\x48\x89\x39\x48\x89\x42\x28\xFF\x47\x10\x48\x89\x4F\x08\x44\x8B\x4B\x5C", "xxxx?xxxx?xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxx????xxxxxxxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + result = memorySections.findInMemoryPattern("\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x20\xFF\x41\x60\x33\xF6\x48\x8B\x41\x08\x48\x8B\xD9\x48\x3B\xC1\x74\x0F\x48\x85\xC0\x74\x0A\x48\x83\xC0\xE0\x0F\x85\xB7\x00\x00\x00\x48\x8B\x41\x20\x48\x8D\x79\x18\x48\x3B\xC7\x74\x0F\x48\x85\xC0\x74\x0A\x48\x83\xC0\xE0\x0F\x85\x9B\x00\x00\x00\x48\x63\x51\x58\x48\x8B\x0D\xDA\x02\xD5\x00\x4C\x8B\xC2\x48\x8B\x01\xFF\x50\x38\x48\x89\x70\x28\x48\x8B\xD0\x48\x89\x70\x20\x4C\x8D\x40\x20\x48\x85\xC0\x0F\x84\x6F\x01\x00\x00\x89\x30\x89\x70\x10\x48\x89\x58\x08\x48\x8B\x4F\x08\x4C\x89\x01\x48\x8B\x47\x08\x49\x89\x38\x48\x89\x42\x28\xFF\x47\x10\x4C\x89\x47\x08\x44\x8B\x43\x5C", "xxxx?xxxx?xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxx????xxxxxxxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); return result; }); @@ -318,7 +318,7 @@ namespace intercept { const char* test = getRTTIName(allocatorVtablePtr); bool vc143Allocator = false; if (strlen(test) == 0) { - allocatorVtablePtr -= 0xA8; // vc143 build + allocatorVtablePtr -= 0xB0; // vc143 build test = getRTTIName(allocatorVtablePtr); vc143Allocator = true; } @@ -343,10 +343,21 @@ namespace intercept { if (!entry->_createFunction) continue; //Some types don't have create functions. Example: VECTOR. #if _WIN64 || __X86_64__ auto baseOffset = 0x7; - if (entry->_name == "CODE"sv) baseOffset += 2; if (vc143Allocator) - baseOffset = 0xC; + { + if (entry->_name == "HASHMAP"sv) + baseOffset = 0xAA; + else + baseOffset = 0xC; + } + else + { + if (entry->_name == "CODE"sv) + baseOffset += 2; + else if + (entry->_name == "HASHMAP"sv) baseOffset = 0xA5; + } const auto instructionPointer = reinterpret_cast(entry->_createFunction) + baseOffset + 0x4; const auto offset = *reinterpret_cast(reinterpret_cast(entry->_createFunction) + baseOffset); diff --git a/src/host/loader/ptraccess.h b/src/host/loader/ptraccess.h index fdb674e0..a0fdfcf4 100644 --- a/src/host/loader/ptraccess.h +++ b/src/host/loader/ptraccess.h @@ -2,6 +2,46 @@ #pragma once #if defined(_WIN32) || defined(_WIN64) #include +#ifdef __cplusplus +// From: https://stackoverflow.com/questions/496034/most-efficient-replacement-for-isbadreadptr +// Check memory address access +static const DWORD dwForbiddenArea = PAGE_GUARD | PAGE_NOACCESS; +static const DWORD dwReadRights = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; +static const DWORD dwWriteRights = PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; + +template +bool CheckAccess(const void* pAddress, size_t nSize) +{ + if (!pAddress || !nSize) + { + return false; + } + + MEMORY_BASIC_INFORMATION sMBI; + bool bRet = false; + + UINT_PTR pCurrentAddress = UINT_PTR(pAddress); + UINT_PTR pEndAdress = pCurrentAddress + (nSize - 1); + + do + { + ZeroMemory(&sMBI, sizeof(sMBI)); + VirtualQuery(LPCVOID(pCurrentAddress), &sMBI, sizeof(sMBI)); + + bRet = (sMBI.State & MEM_COMMIT) // memory allocated and + && !(sMBI.Protect & dwForbiddenArea) // access to page allowed and + && (sMBI.Protect & dwAccessRights); // the required rights + + pCurrentAddress = (UINT_PTR(sMBI.BaseAddress) + sMBI.RegionSize); + } while (bRet && pCurrentAddress <= pEndAdress); + + return bRet; +} + +#define IsBadWritePtr(p,n) (!CheckAccess(p,n)) +#define IsBadReadPtr(p,n) (!CheckAccess(p,n)) +#define IsBadStringPtrW(p,n) (!CheckAccess(p,n*2)) +#endif /* defined(__cplusplus) */ #else #define __CUSTOM_ISBADREADPTR #ifdef __cplusplus