From 6c3790cd24becc7fb5c3c5f63f1a01c8fa1bb8b4 Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Sun, 6 Aug 2023 09:09:38 +0200 Subject: [PATCH] replace hook=3 with GetProcAddress hook --- inc/hook.h | 4 +++- inc/winapi_hooks.h | 1 + src/config.c | 4 ++-- src/hook.c | 54 +++++++++++++++++++++------------------------- src/winapi_hooks.c | 39 +++++++++++++++++++++++++++++++-- 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/inc/hook.h b/inc/hook.h index e5025c6..008ca2f 100644 --- a/inc/hook.h +++ b/inc/hook.h @@ -6,7 +6,6 @@ #define SKIP_HOOK2 0x00000001l -#define SKIP_HOOK3 0x00000002l typedef struct HOOKLISTDATA { char function_name[32]; PROC new_function; PROC* function; DWORD flags; } HOOKLISTDATA; typedef struct HOOKLIST { char module_name[32]; HOOKLISTDATA data[30]; } HOOKLIST; @@ -54,6 +53,7 @@ typedef HMODULE(WINAPI* LOADLIBRARYAPROC)(LPCSTR); typedef HMODULE(WINAPI* LOADLIBRARYWPROC)(LPCWSTR); typedef HMODULE(WINAPI* LOADLIBRARYEXAPROC)(LPCSTR, HANDLE, DWORD); typedef HMODULE(WINAPI* LOADLIBRARYEXWPROC)(LPCWSTR, HANDLE, DWORD); +typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HMODULE, LPCSTR); typedef BOOL(WINAPI* GETDISKFREESPACEAPROC)(LPCSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD); typedef HRESULT(WINAPI* COCREATEINSTANCEPROC)(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*); typedef LPTOP_LEVEL_EXCEPTION_FILTER(WINAPI* SETUNHANDLEDEXCEPTIONFILTERPROC)(LPTOP_LEVEL_EXCEPTION_FILTER); @@ -94,12 +94,14 @@ extern LOADLIBRARYAPROC real_LoadLibraryA; extern LOADLIBRARYWPROC real_LoadLibraryW; extern LOADLIBRARYEXAPROC real_LoadLibraryExA; extern LOADLIBRARYEXWPROC real_LoadLibraryExW; +extern GETPROCADDRESSPROC real_GetProcAddress; extern GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA; extern COCREATEINSTANCEPROC real_CoCreateInstance; extern SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter; extern int g_hook_method; extern BOOL g_hook_active; +extern HOOKLIST g_hook_hooklist[]; void hook_init(BOOL initial_hook); void hook_exit(); diff --git a/inc/winapi_hooks.h b/inc/winapi_hooks.h index 009cac8..0983b9b 100644 --- a/inc/winapi_hooks.h +++ b/inc/winapi_hooks.h @@ -47,6 +47,7 @@ HMODULE WINAPI fake_LoadLibraryA(LPCSTR lpLibFileName); HMODULE WINAPI fake_LoadLibraryW(LPCWSTR lpLibFileName); HMODULE WINAPI fake_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); HMODULE WINAPI fake_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +FARPROC WINAPI fake_GetProcAddress(HMODULE hModule, LPCSTR lpProcName); BOOL WINAPI fake_GetDiskFreeSpaceA( LPCSTR lpRootPathName, diff --git a/src/config.c b/src/config.c index f7e53ba..59b8f43 100644 --- a/src/config.c +++ b/src/config.c @@ -312,9 +312,9 @@ static void cfg_create_ini() "; Note: Usually one of the following values will work: 60 / 30 / 25 / 20 / 15 (lower value = slower game speed)\n" "maxgameticks=0\n" "\n" - "; Windows API Hooking, Possible values: 0 = disabled, 1 = IAT Hooking, 2 = Microsoft Detours, 3 = IAT+Detours Hooking (All Modules), 4 = IAT Hooking (All Modules)\n" + "; Windows API Hooking, Possible values: 0 = disabled, 1 = IAT Hooking, 2 = Microsoft Detours, 3 = IAT+GetProcAddress hook (All Modules), 4 = IAT Hooking (All Modules)\n" "; Note: Change this value if windowed mode or upscaling isn't working properly\n" - "; Note: 'hook=2' will usually work for problematic games, but 'hook=2' should be combined with renderer=gdi\n" + "; Note: 'hook=3' will usually work for problematic games, if it doesn't then try 'hook=2' + 'renderer=gdi'\n" "hook=4\n" "\n" "; Force minimum FPS, possible values: 0 = disabled, -1 = use 'maxfps=' value, -2 = same as -1 but force full redraw, 1-1000 = custom FPS\n" diff --git a/src/hook.c b/src/hook.c index 5a0be42..5b18e25 100644 --- a/src/hook.c +++ b/src/hook.c @@ -53,11 +53,12 @@ LOADLIBRARYAPROC real_LoadLibraryA = LoadLibraryA; LOADLIBRARYWPROC real_LoadLibraryW = LoadLibraryW; LOADLIBRARYEXAPROC real_LoadLibraryExA = LoadLibraryExA; LOADLIBRARYEXWPROC real_LoadLibraryExW = LoadLibraryExW; +GETPROCADDRESSPROC real_GetProcAddress = GetProcAddress; GETDISKFREESPACEAPROC real_GetDiskFreeSpaceA = GetDiskFreeSpaceA; COCREATEINSTANCEPROC real_CoCreateInstance = CoCreateInstance; SETUNHANDLEDEXCEPTIONFILTERPROC real_SetUnhandledExceptionFilter = SetUnhandledExceptionFilter; -static HOOKLIST g_hooks[] = +HOOKLIST g_hook_hooklist[] = { { "user32.dll", @@ -66,8 +67,8 @@ static HOOKLIST g_hooks[] = { "ClipCursor", (PROC)fake_ClipCursor, (PROC*)&real_ClipCursor, 0 }, { "ShowCursor", (PROC)fake_ShowCursor, (PROC*)&real_ShowCursor, 0 }, { "SetCursor", (PROC)fake_SetCursor, (PROC*)&real_SetCursor, 0 }, - { "GetWindowRect", (PROC)fake_GetWindowRect, (PROC*)&real_GetWindowRect, SKIP_HOOK3 }, - { "GetClientRect", (PROC)fake_GetClientRect, (PROC*)&real_GetClientRect, SKIP_HOOK3 }, + { "GetWindowRect", (PROC)fake_GetWindowRect, (PROC*)&real_GetWindowRect, 0 }, + { "GetClientRect", (PROC)fake_GetClientRect, (PROC*)&real_GetClientRect, 0 }, { "ClientToScreen", (PROC)fake_ClientToScreen, (PROC*)&real_ClientToScreen, 0 }, { "ScreenToClient", (PROC)fake_ScreenToClient, (PROC*)&real_ScreenToClient, 0 }, { "SetCursorPos", (PROC)fake_SetCursorPos, (PROC*)&real_SetCursorPos, 0 }, @@ -96,44 +97,45 @@ static HOOKLIST g_hooks[] = { "ole32.dll", { - { "CoCreateInstance", (PROC)fake_CoCreateInstance, (PROC*)&real_CoCreateInstance, SKIP_HOOK2 | SKIP_HOOK3 }, + { "CoCreateInstance", (PROC)fake_CoCreateInstance, (PROC*)&real_CoCreateInstance, SKIP_HOOK2 }, { "", NULL, NULL, 0 } } }, { "dinput.dll", { - { "DirectInputCreateA", (PROC)fake_DirectInputCreateA, (PROC*)&real_DirectInputCreateA, SKIP_HOOK2 | SKIP_HOOK3 }, - { "DirectInputCreateW", (PROC)fake_DirectInputCreateW, (PROC*)&real_DirectInputCreateW, SKIP_HOOK2 | SKIP_HOOK3 }, - { "DirectInputCreateEx", (PROC)fake_DirectInputCreateEx, (PROC*)&real_DirectInputCreateEx, SKIP_HOOK2 | SKIP_HOOK3 }, + { "DirectInputCreateA", (PROC)fake_DirectInputCreateA, (PROC*)&real_DirectInputCreateA, SKIP_HOOK2 }, + { "DirectInputCreateW", (PROC)fake_DirectInputCreateW, (PROC*)&real_DirectInputCreateW, SKIP_HOOK2 }, + { "DirectInputCreateEx", (PROC)fake_DirectInputCreateEx, (PROC*)&real_DirectInputCreateEx, SKIP_HOOK2 }, { "", NULL, NULL, 0 } } }, { "dinput8.dll", { - { "DirectInput8Create", (PROC)fake_DirectInput8Create, (PROC*)&real_DirectInput8Create, SKIP_HOOK2 | SKIP_HOOK3 }, + { "DirectInput8Create", (PROC)fake_DirectInput8Create, (PROC*)&real_DirectInput8Create, SKIP_HOOK2 }, { "", NULL, NULL, 0 } } }, { "gdi32.dll", { - { "StretchBlt", (PROC)fake_StretchBlt, (PROC*)&real_StretchBlt, SKIP_HOOK2 | SKIP_HOOK3 }, - { "SetDIBitsToDevice", (PROC)fake_SetDIBitsToDevice, (PROC*)&real_SetDIBitsToDevice, SKIP_HOOK2 | SKIP_HOOK3 }, - { "StretchDIBits", (PROC)fake_StretchDIBits, (PROC*)&real_StretchDIBits, SKIP_HOOK2 | SKIP_HOOK3 }, - { "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps, SKIP_HOOK3 }, + { "StretchBlt", (PROC)fake_StretchBlt, (PROC*)&real_StretchBlt, SKIP_HOOK2 }, + { "SetDIBitsToDevice", (PROC)fake_SetDIBitsToDevice, (PROC*)&real_SetDIBitsToDevice, SKIP_HOOK2 }, + { "StretchDIBits", (PROC)fake_StretchDIBits, (PROC*)&real_StretchDIBits, SKIP_HOOK2 }, + { "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps, 0 }, { "", NULL, NULL, 0 } } }, { "kernel32.dll", { - { "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA, SKIP_HOOK2 | SKIP_HOOK3 }, - { "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW, SKIP_HOOK2 | SKIP_HOOK3 }, - { "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA, SKIP_HOOK2 | SKIP_HOOK3 }, - { "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW, SKIP_HOOK2 | SKIP_HOOK3 }, - { "GetDiskFreeSpaceA", (PROC)fake_GetDiskFreeSpaceA, (PROC*)&real_GetDiskFreeSpaceA, SKIP_HOOK2 | SKIP_HOOK3 }, + { "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA, SKIP_HOOK2 }, + { "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW, SKIP_HOOK2 }, + { "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA, SKIP_HOOK2 }, + { "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW, SKIP_HOOK2 }, + { "GetProcAddress", (PROC)fake_GetProcAddress, (PROC*)&real_GetProcAddress, SKIP_HOOK2 }, + { "GetDiskFreeSpaceA", (PROC)fake_GetDiskFreeSpaceA, (PROC*)&real_GetDiskFreeSpaceA, SKIP_HOOK2 }, { "", NULL, NULL, 0 } } }, @@ -365,16 +367,13 @@ void hook_patch_iat_list(HMODULE hmod, BOOL unhook, HOOKLIST* hooks) void hook_create(HOOKLIST* hooks, BOOL initial_hook) { #ifdef _MSC_VER - if ((g_hook_method == 2 || g_hook_method == 3) && initial_hook) + if ((g_hook_method == 2) && initial_hook) { for (int i = 0; hooks[i].module_name[0]; i++) { for (int x = 0; hooks[i].data[x].function_name[0]; x++) { - if (g_hook_method == 2 && (hooks[i].data[x].flags & SKIP_HOOK2)) - continue; - - if (g_hook_method == 3 && (hooks[i].data[x].flags & SKIP_HOOK3)) + if ((hooks[i].data[x].flags & SKIP_HOOK2)) continue; DetourTransactionBegin(); @@ -453,16 +452,13 @@ void hook_create(HOOKLIST* hooks, BOOL initial_hook) void hook_revert(HOOKLIST* hooks) { #ifdef _MSC_VER - if (g_hook_method == 2 || g_hook_method == 3) + if (g_hook_method == 2) { for (int i = 0; hooks[i].module_name[0]; i++) { for (int x = 0; hooks[i].data[x].function_name[0]; x++) { - if (g_hook_method == 2 && (hooks[i].data[x].flags & SKIP_HOOK2)) - continue; - - if (g_hook_method == 3 && (hooks[i].data[x].flags & SKIP_HOOK3)) + if ((hooks[i].data[x].flags & SKIP_HOOK2)) continue; DetourTransactionBegin(); @@ -546,7 +542,7 @@ void hook_init(BOOL initial_hook) hook_patch_iat(GetModuleHandle("AcGenral"), FALSE, "user32.dll", "SetWindowsHookExA", (PROC)fake_SetWindowsHookExA); } - hook_create((HOOKLIST*)&g_hooks, initial_hook); + hook_create((HOOKLIST*)&g_hook_hooklist, initial_hook); g_hook_active = TRUE; } @@ -558,7 +554,7 @@ void hook_exit() { g_hook_active = FALSE; - hook_revert((HOOKLIST*)&g_hooks); + hook_revert((HOOKLIST*)&g_hook_hooklist); #if defined(_DEBUG) && defined(_MSC_VER) DetourTransactionBegin(); diff --git a/src/winapi_hooks.c b/src/winapi_hooks.c index 6ec26c8..dcf2be2 100644 --- a/src/winapi_hooks.c +++ b/src/winapi_hooks.c @@ -14,6 +14,7 @@ #include "directinput.h" #include "ddsurface.h" #include "dllmain.h" +#include "hook.h" BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint) @@ -433,7 +434,7 @@ LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPar lParam = MAKELPARAM(x + g_ddraw->mouse.x_adjust, y + g_ddraw->mouse.y_adjust); } - if (g_ddraw->hwnd == hWnd && Msg == WM_SIZE && (g_hook_method != 2 && g_hook_method != 3)) + if (g_ddraw->hwnd == hWnd && Msg == WM_SIZE && g_hook_method != 2) { Msg = WM_SIZE_DDRAW; } @@ -536,7 +537,7 @@ BOOL WINAPI fake_ShowWindow(HWND hWnd, int nCmdShow) if (nCmdShow == SW_MAXIMIZE) nCmdShow = SW_NORMAL; - if (nCmdShow == SW_MINIMIZE && (g_hook_method != 2 && g_hook_method != 3)) + if (nCmdShow == SW_MINIMIZE && g_hook_method != 2) return TRUE; } @@ -999,6 +1000,40 @@ HMODULE WINAPI fake_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dw return hmod; } +FARPROC WINAPI fake_GetProcAddress(HMODULE hModule, LPCSTR lpProcName) +{ +#ifdef _DEBUG + char mod_path[MAX_PATH] = { 0 }; + if (hModule && GetModuleFileNameA(hModule, mod_path, MAX_PATH)) + { + TRACE("GetProcAddress %s (%s)\n", HIWORD(lpProcName) ? lpProcName : NULL, mod_path); + } +#endif + + FARPROC proc = real_GetProcAddress(hModule, lpProcName); + + if (g_hook_method != 3 || !hModule || !HIWORD(lpProcName)) + return proc; + + for (int i = 0; g_hook_hooklist[i].module_name[0]; i++) + { + HMODULE mod = GetModuleHandleA(g_hook_hooklist[i].module_name); + + if (hModule != mod) + continue; + + for (int x = 0; g_hook_hooklist[i].data[x].function_name[0]; x++) + { + if (strcmp(lpProcName, g_hook_hooklist[i].data[x].function_name) == 0) + { + return (FARPROC)g_hook_hooklist[i].data[x].new_function; + } + } + } + + return proc; +} + BOOL WINAPI fake_GetDiskFreeSpaceA( LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster,