From 24357c6a5a6bb9025a71050e50b38dbe9c02713a Mon Sep 17 00:00:00 2001 From: JohnMcPMS Date: Wed, 6 Jul 2022 16:36:20 -0700 Subject: [PATCH] Feature: Make section count configurable, fix RTC error, and expose DetourIsFunctionImported (#225) A few minor changes: - Expose detour_is_imported via a new public function DetourIsFunctionImported - Make certain runtime checks happy by masking pbTarget before casting to smaller type - Enable user to compile with a different number of supported section headers (leaves default at 32) --- src/detours.cpp | 9 ++++++++- src/detours.h | 14 ++++++++++---- tests/test_module_api.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/detours.cpp b/src/detours.cpp index 954050f7..c1138dca 100644 --- a/src/detours.cpp +++ b/src/detours.cpp @@ -1395,6 +1395,12 @@ PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget, return pbNewlyAllocated; } +BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode, + _In_ PBYTE pbAddress) +{ + return detour_is_imported(pbCode, pbAddress); +} + static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget) { // We have to place trampolines within +/- 2GB of target. @@ -1437,7 +1443,8 @@ static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget) // We need to allocate a new region. // Round pbTarget down to 64KB block. - pbTarget = pbTarget - (PtrToUlong(pbTarget) & 0xffff); + // /RTCc RuntimeChecks breaks PtrToUlong. + pbTarget = pbTarget - (ULONG)((ULONG_PTR)pbTarget & 0xffff); PVOID pbNewlyAllocated = detour_alloc_trampoline_allocate_new(pbTarget, pLo, pHi); diff --git a/src/detours.h b/src/detours.h index 38b3dc81..f3738af0 100644 --- a/src/detours.h +++ b/src/detours.h @@ -381,7 +381,11 @@ extern const GUID DETOUR_EXE_RESTORE_GUID; extern const GUID DETOUR_EXE_HELPER_GUID; #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! -typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; +typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; + +#ifndef DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS +#define DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS 32 +#endif // !DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS /////////////////////////////////////////////////////////// Binary Structures. // @@ -454,9 +458,9 @@ typedef struct _DETOUR_EXE_RESTORE #endif #ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this BYTE raw[sizeof(IMAGE_NT_HEADERS64) + - sizeof(IMAGE_SECTION_HEADER) * 32]; + sizeof(IMAGE_SECTION_HEADER) * DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS]; #else - BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * 32]; + BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS]; #endif }; DETOUR_CLR_HEADER clr; @@ -590,7 +594,9 @@ PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, _In_ BOOL fLimitReferencesToModule); PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget, - _Out_ PDWORD pcbAllocatedSize); + _Out_ PDWORD pcbAllocatedSize); +BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode, + _In_ PBYTE pbAddress); ///////////////////////////////////////////////////// Loaded Binary Functions. // diff --git a/tests/test_module_api.cpp b/tests/test_module_api.cpp index 706ea129..3e2928cd 100644 --- a/tests/test_module_api.cpp +++ b/tests/test_module_api.cpp @@ -728,4 +728,29 @@ TEST_CASE("DetourRestoreAfterWithEx", "[module]") // TODO: Needs to be written. } +// Define the import symbol so that we can get the address of the IAT entry for a static import +#ifdef _X86_ +#pragma warning(disable:4483) // disable warning/error about __identifier() +#define __imp_SetLastError __identifier("_imp__SetLastError@4") +#endif + +extern "C" extern void *__imp_SetLastError; + +TEST_CASE("DetourIsFunctionImported", "[module]") +{ + SECTION("Passing NULL code pointer, results in false") + { + REQUIRE(!DetourIsFunctionImported(NULL, reinterpret_cast(&__imp_SetLastError))); + } + + SECTION("Passing NULL target, results in false") + { + REQUIRE(!DetourIsFunctionImported(reinterpret_cast(&__ImageBase), NULL)); + } + + SECTION("Passing imported function, results in true") + { + REQUIRE(DetourIsFunctionImported(reinterpret_cast(&__ImageBase), reinterpret_cast(&__imp_SetLastError))); + } +}