diff --git a/src/utility.cpp b/src/utility.cpp index 481574bd..2b4492a1 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -423,176 +423,176 @@ BOOL IsModulePatched (HMODULE importmodule, moduleentry_t patchtable [], UINT ta // No patches listed in the patch table were found in the import module. return FALSE; -} - -#define MAX_PAGES_PROTECT 2 - -typedef struct PROTECT_INSTANCE_TAG -{ - DWORD old_protect[MAX_PAGES_PROTECT]; - LPVOID address; - SIZE_T size; -} PROTECT_INSTANCE; - -typedef struct PROTECT_INSTANCE_TAG* PROTECT_HANDLE; - -#ifdef _WIN64 -#define PAGE_MASK 0xFFFFFFFFFFFFF000 -#else -#define PAGE_MASK 0xFFFFF000 -#endif - -#define PAGE_SIZE 0x1000 - -static BOOL VLDVirtualProtect(PROTECT_HANDLE protect_handle, LPVOID address, SIZE_T size, DWORD protect) -{ - BOOL result = TRUE; - size_t page_count = 0; - - // save the address and size so that we can restore in the same way - protect_handle->address = address; - protect_handle->size = size; - - uintptr_t current_address = (uintptr_t)address; - - // walk all pages while we still have size > 0 - while ((size > 0) && (page_count < MAX_PAGES_PROTECT)) - { - uintptr_t page_address = current_address & PAGE_MASK; - SIZE_T size_in_page = page_address + PAGE_SIZE - current_address; - SIZE_T size_to_protect = (size_in_page < size) ? size_in_page : size; - - result = VirtualProtect((LPVOID)current_address, size_to_protect, protect, &protect_handle->old_protect[page_count]); - if (!result) - { - Report(L"%zu: !!! VirtualProtect FAILED when protecting for address=%p, size=%zu, with GetLastError()=%lu, protect_handle->address=%p, protect_handle->size=%zu", - __LINE__, current_address, size_to_protect, - GetLastError(), - protect_handle->address, protect_handle->size); - } - page_count++; - current_address += size_to_protect; - size -= size_to_protect; - } - - return result; -} - -static void VLDVirtualRestore(PROTECT_HANDLE protect_handle) -{ - size_t page_count = 0; - SIZE_T size = protect_handle->size; - uintptr_t current_address = (uintptr_t)protect_handle->address; - - // walk all pages while we still have size > 0 - while ((size > 0) && (page_count < MAX_PAGES_PROTECT)) - { - uintptr_t page_address = current_address & PAGE_MASK; - SIZE_T size_in_page = page_address + PAGE_SIZE - current_address; - SIZE_T size_to_protect = (size_in_page < size) ? size_in_page : size; - - DWORD dont_care; - if (!VirtualProtect((LPVOID)current_address, size_to_protect, protect_handle->old_protect[page_count], &dont_care)) - { - static volatile DWORD lastError = GetLastError(); - Report(L"%zu: !!! VirtualProtect FAILED when restoring for address=%p, size=%zu, with GetLastError()=%lu, protect_handle->old_protect[page_count]=%lu, protect_handle->address=%p, protect_handle->size=%zu", - __LINE__, current_address, size_to_protect, - GetLastError(), protect_handle->old_protect[page_count], - protect_handle->address, protect_handle->size); - abort(); - } - - page_count++; - current_address += size_to_protect; - size -= size_to_protect; - } - -} - +} + +#define MAX_PAGES_PROTECT 2 + +typedef struct PROTECT_INSTANCE_TAG +{ + DWORD old_protect[MAX_PAGES_PROTECT]; + LPVOID address; + SIZE_T size; +} PROTECT_INSTANCE; + +typedef struct PROTECT_INSTANCE_TAG* PROTECT_HANDLE; + +#ifdef _WIN64 +#define PAGE_MASK 0xFFFFFFFFFFFFF000 +#else +#define PAGE_MASK 0xFFFFF000 +#endif + +#define PAGE_SIZE 0x1000 + +static BOOL VLDVirtualProtect(PROTECT_HANDLE protect_handle, LPVOID address, SIZE_T size, DWORD protect) +{ + BOOL result = TRUE; + size_t page_count = 0; + + // save the address and size so that we can restore in the same way + protect_handle->address = address; + protect_handle->size = size; + + uintptr_t current_address = (uintptr_t)address; + + // walk all pages while we still have size > 0 + while ((size > 0) && (page_count < MAX_PAGES_PROTECT)) + { + uintptr_t page_address = current_address & PAGE_MASK; + SIZE_T size_in_page = page_address + PAGE_SIZE - current_address; + SIZE_T size_to_protect = (size_in_page < size) ? size_in_page : size; + + result = VirtualProtect((LPVOID)current_address, size_to_protect, protect, &protect_handle->old_protect[page_count]); + if (!result) + { + Report(L"%zu: !!! VirtualProtect FAILED when protecting for address=%p, size=%zu, with GetLastError()=%lu, protect_handle->address=%p, protect_handle->size=%zu\n", + __LINE__, current_address, size_to_protect, + GetLastError(), + protect_handle->address, protect_handle->size); + } + page_count++; + current_address += size_to_protect; + size -= size_to_protect; + } + + return result; +} + +static void VLDVirtualRestore(PROTECT_HANDLE protect_handle) +{ + size_t page_count = 0; + SIZE_T size = protect_handle->size; + uintptr_t current_address = (uintptr_t)protect_handle->address; + + // walk all pages while we still have size > 0 + while ((size > 0) && (page_count < MAX_PAGES_PROTECT)) + { + uintptr_t page_address = current_address & PAGE_MASK; + SIZE_T size_in_page = page_address + PAGE_SIZE - current_address; + SIZE_T size_to_protect = (size_in_page < size) ? size_in_page : size; + + DWORD dont_care; + if (!VirtualProtect((LPVOID)current_address, size_to_protect, protect_handle->old_protect[page_count], &dont_care)) + { + static volatile DWORD lastError = GetLastError(); + Report(L"%zu: !!! VirtualProtect FAILED when restoring for address=%p, size=%zu, with GetLastError()=%lu, protect_handle->old_protect[page_count]=%lu, protect_handle->address=%p, protect_handle->size=%zu\n", + __LINE__, current_address, size_to_protect, + GetLastError(), protect_handle->old_protect[page_count], + protect_handle->address, protect_handle->size); + abort(); + } + + page_count++; + current_address += size_to_protect; + size -= size_to_protect; + } + +} + LPVOID FindRealCode(LPVOID pCode) -{ - LPVOID result; +{ + LPVOID result; if (pCode != NULL) { - // we need to make sure we can read the first 7 ULONG_PTRs - PROTECT_INSTANCE protect_1; - - if (VLDVirtualProtect(&protect_1, pCode, sizeof(ULONG_PTR) * 7, PAGE_EXECUTE_READ)) - { + // we need to make sure we can read the first 7 ULONG_PTRs + PROTECT_INSTANCE protect_1; + + if (VLDVirtualProtect(&protect_1, pCode, sizeof(ULONG_PTR) * 7, PAGE_EXECUTE_READ)) + { if (*(WORD*)pCode == 0x25ff) // JMP r/m32 { #ifdef _WIN64 LONG offset = *((LONG*)((ULONG_PTR)pCode + 2)); // RIP relative addressing - PBYTE pNextInst = (PBYTE)((ULONG_PTR)pCode + 6); - - // now that we got the offset, make sure we can read the code at the offset - PROTECT_INSTANCE protect_2; - PBYTE addr = pNextInst + offset; - - if (VLDVirtualProtect(&protect_2, (LPVOID*)addr, sizeof(LPVOID), PAGE_EXECUTE_READ)) - { - pCode = *(LPVOID*)(addr); + PBYTE pNextInst = (PBYTE)((ULONG_PTR)pCode + 6); + + // now that we got the offset, make sure we can read the code at the offset + PROTECT_INSTANCE protect_2; + PBYTE addr = pNextInst + offset; + + if (VLDVirtualProtect(&protect_2, (LPVOID*)addr, sizeof(LPVOID), PAGE_EXECUTE_READ)) + { + pCode = *(LPVOID*)(addr); result = FindRealCode(pCode); - VLDVirtualRestore(&protect_2); - } - else - { - result = NULL; + VLDVirtualRestore(&protect_2); + } + else + { + result = NULL; } #else - DWORD addr = *((DWORD*)((ULONG_PTR)pCode + 2)); - // now that we got the address to read, make sure we can read the code at the offset - PROTECT_INSTANCE protect_2; - if (VLDVirtualProtect(&protect_2, (LPVOID)addr, sizeof(LPVOID), PAGE_EXECUTE_READ)) + DWORD addr = *((DWORD*)((ULONG_PTR)pCode + 2)); + // now that we got the address to read, make sure we can read the code at the offset + PROTECT_INSTANCE protect_2; + if (VLDVirtualProtect(&protect_2, (LPVOID)addr, sizeof(LPVOID), PAGE_EXECUTE_READ)) { - pCode = *(LPVOID*)(addr); - result = FindRealCode(pCode); - VLDVirtualRestore(&protect_2); - } - else - { - result = NULL; + pCode = *(LPVOID*)(addr); + result = FindRealCode(pCode); + VLDVirtualRestore(&protect_2); + } + else + { + result = NULL; } #endif } else if (*(BYTE*)pCode == 0xE9) // JMP rel32 { - // Relative next instruction + // Relative next instruction PROTECT_INSTANCE protect_2; PBYTE pNextInst = (PBYTE)((ULONG_PTR)pCode + 5); LONG offset = *((LONG*)((ULONG_PTR)pCode + 1)); - if (VLDVirtualProtect(&protect_2, pNextInst + offset, sizeof(LPVOID), PAGE_EXECUTE_READ)) + if (VLDVirtualProtect(&protect_2, pNextInst + offset, sizeof(LPVOID), PAGE_EXECUTE_READ)) { pCode = (LPVOID*)(pNextInst + offset); - result = FindRealCode(pCode); - VLDVirtualRestore(&protect_2); - } - else - { - result = NULL; + result = FindRealCode(pCode); + VLDVirtualRestore(&protect_2); + } + else + { + result = NULL; } - } - else - { - result = pCode; } - - // restore the page protection state - VLDVirtualRestore(&protect_1); - } - else - { - result = NULL; + else + { + result = pCode; + } + + // restore the page protection state + VLDVirtualRestore(&protect_1); + } + else + { + result = NULL; } - } - else - { - result = NULL; - } + } + else + { + result = NULL; + } return result; } - + #define MAX_PATCH_ENTRY_COUNT 128 // PatchImport - Patches all future calls to an imported function, or references @@ -654,16 +654,16 @@ BOOL PatchImport (HMODULE importmodule, moduleentry_t *patchModule) LPSTR pszBuffer = cwBuffer; DWORD dwMaxChars = _countof(cwBuffer); DWORD dwLength = ::GetModuleFileNameA(importmodule, pszBuffer, dwMaxChars); -#endif - - // have a stack local array of the addresses, don't want to use malloc for this - // The reason to precompute and cache these is because VirtualProtect is expensive - // Thus first we compute *only* once the real addresses for the export module - LPVOID realAddresses[MAX_PATCH_ENTRY_COUNT]; +#endif + + // have a stack local array of the addresses, don't want to use malloc for this + // The reason to precompute and cache these is because VirtualProtect is expensive + // Thus first we compute *only* once the real addresses for the export module + LPVOID realAddresses[MAX_PATCH_ENTRY_COUNT]; patchentry_t* patchEntry = patchModule->patchTable; - int i = 0; + int i = 0; while (patchEntry->importName) - { + { LPCSTR importname = patchEntry->importName; // Get the *real* address of the import. If we find this address in the IAT, @@ -672,27 +672,27 @@ BOOL PatchImport (HMODULE importmodule, moduleentry_t *patchModule) if (!import) import = GetProcAddress(exportmodule, importname); import = FindRealCode(import); - + realAddresses[i] = import; - patchEntry++; - i++; - - if (i >= MAX_PATCH_ENTRY_COUNT) - { - // we only process MAX_PATCH_ENTRY_COUNT, if we exceed it crash - // if this abort is ever hit, it means that MAX_PATCH_ENTRY_COUNT should be bumped up - Report(L"MAX_PATCH_ENTRY_COUNT is set to %zu, but has been exceeded, MAX_PATCH_ENTRY_COUNT needs to be increased.\n", MAX_PATCH_ENTRY_COUNT); - abort(); - break; - } + patchEntry++; + i++; + + if (i >= MAX_PATCH_ENTRY_COUNT) + { + // we only process MAX_PATCH_ENTRY_COUNT, if we exceed it crash + // if this abort is ever hit, it means that MAX_PATCH_ENTRY_COUNT should be bumped up + Report(L"MAX_PATCH_ENTRY_COUNT is set to %zu, but has been exceeded, MAX_PATCH_ENTRY_COUNT needs to be increased.\n", MAX_PATCH_ENTRY_COUNT); + abort(); + break; + } } int result = 0; while (idte->FirstThunk != 0x0) { PCHAR importdllname = (PCHAR)R2VA(importmodule, idte->Name); - UNREFERENCED_PARAMETER(importdllname); - HMODULE importdllbaseaddress = GetModuleHandleA(importdllname); + UNREFERENCED_PARAMETER(importdllname); + HMODULE importdllbaseaddress = GetModuleHandleA(importdllname); UNREFERENCED_PARAMETER(importdllbaseaddress); // Locate the import's IAT entry. @@ -700,15 +700,15 @@ BOOL PatchImport (HMODULE importmodule, moduleentry_t *patchModule) IMAGE_THUNK_DATA *origThunk = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->OriginalFirstThunk); for (; origThunk->u1.Function != NULL; origThunk++, thunk++) - { - LPVOID func = FindRealCode((LPVOID)thunk->u1.Function); - + { + LPVOID func = FindRealCode((LPVOID)thunk->u1.Function); + patchEntry = patchModule->patchTable; i = 0; while (patchEntry->importName) - { - LPVOID import = realAddresses[i]; - if (import != NULL) + { + LPVOID import = realAddresses[i]; + if (import != NULL) { LPCVOID replacement = patchEntry->replacement; @@ -776,9 +776,9 @@ BOOL PatchImport (HMODULE importmodule, moduleentry_t *patchModule) break; } } -#endif - } - +#endif + } + patchEntry++; i++; } } @@ -1281,16 +1281,16 @@ void GetFormattedMessage(DWORD last_error) // HMODULE GetCallingModule(UINT_PTR pCaller ) { - HMODULE hModule = NULL; - - /*MEMORY_BASIC_INFORMATION mbi; - if (VirtualQuery((LPCVOID)pCaller, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION)) - { - // the allocation base is the beginning of a PE file - hModule = (HMODULE)mbi.AllocationBase; - }*/ - - WIN32_MEMORY_REGION_INFORMATION memoryRegionInfo; + HMODULE hModule = NULL; + + /*MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery((LPCVOID)pCaller, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION)) + { + // the allocation base is the beginning of a PE file + hModule = (HMODULE)mbi.AllocationBase; + }*/ + + WIN32_MEMORY_REGION_INFORMATION memoryRegionInfo; if ( QueryVirtualMemoryInformation(GetCurrentProcess(), (LPCVOID)pCaller, MemoryRegionInfo, &memoryRegionInfo, sizeof(memoryRegionInfo), NULL) ) { // the allocation base is the beginning of a PE file diff --git a/src/vld.cpp b/src/vld.cpp index 0225c496..66e00507 100644 --- a/src/vld.cpp +++ b/src/vld.cpp @@ -401,7 +401,7 @@ VisualLeakDetector::VisualLeakDetector () // Initialize global variables. g_currentProcess = GetCurrentProcess(); g_currentThread = GetCurrentThread(); - g_processHeap = GetProcessHeap(); + g_processHeap = GetProcessHeap(); LoaderLock ll; @@ -457,7 +457,7 @@ VisualLeakDetector::VisualLeakDetector () // we got a valid TLS index. if (m_tlsIndex == TLS_OUT_OF_INDEXES) { Report(L"ERROR: Visual Leak Detector could not be installed because thread local" - L" storage could not be allocated."); + L" storage could not be allocated.\n"); return; } @@ -970,9 +970,9 @@ LPWSTR VisualLeakDetector::buildSymbolSearchPath () } delete [] env; } - -#if _MSC_VER > 2000 -#error Not supported VS + +#if _MSC_VER > 2000 +#error Not supported VS #endif // Append Visual Studio 2015/2013/2012/2010/2008 symbols cache directory. // NOTE: This does not seem to exist for VS 2019 on Windows 10, but leaving it as is for now, updated to 2019 (changed 14->16)