1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-21 08:22:12 +01:00
cnc-ddraw/src/hook.c

391 lines
13 KiB
C
Raw Normal View History

2020-10-13 09:20:52 +02:00
#define WIN32_LEAN_AND_MEAN
2019-03-19 06:57:49 +01:00
#include <windows.h>
#include <stdio.h>
2020-10-13 09:20:52 +02:00
#include "dd.h"
#include "winapi_hooks.h"
2019-03-19 06:57:49 +01:00
#include "hook.h"
2020-10-13 09:20:52 +02:00
#include "dllmain.h"
2019-03-19 06:57:49 +01:00
2019-08-07 12:45:40 +02:00
#ifdef _MSC_VER
#include "detours.h"
#endif
2020-10-13 09:20:52 +02:00
BOOL g_hook_active;
int g_hook_method = 1;
2019-03-19 06:57:49 +01:00
GETCURSORPOSPROC real_GetCursorPos = GetCursorPos;
CLIPCURSORPROC real_ClipCursor = ClipCursor;
SHOWCURSORPROC real_ShowCursor = ShowCursor;
SETCURSORPROC real_SetCursor = SetCursor;
GETWINDOWRECTPROC real_GetWindowRect = GetWindowRect;
GETCLIENTRECTPROC real_GetClientRect = GetClientRect;
CLIENTTOSCREENPROC real_ClientToScreen = ClientToScreen;
SCREENTOCLIENTPROC real_ScreenToClient = ScreenToClient;
SETCURSORPOSPROC real_SetCursorPos = SetCursorPos;
WINDOWFROMPOINTPROC real_WindowFromPoint = WindowFromPoint;
GETCLIPCURSORPROC real_GetClipCursor = GetClipCursor;
GETCURSORINFOPROC real_GetCursorInfo = GetCursorInfo;
GETSYSTEMMETRICSPROC real_GetSystemMetrics = GetSystemMetrics;
SETWINDOWPOSPROC real_SetWindowPos = SetWindowPos;
MOVEWINDOWPROC real_MoveWindow = MoveWindow;
SENDMESSAGEAPROC real_SendMessageA = SendMessageA;
SETWINDOWLONGAPROC real_SetWindowLongA = SetWindowLongA;
2019-08-06 04:37:06 +02:00
ENABLEWINDOWPROC real_EnableWindow = EnableWindow;
CREATEWINDOWEXAPROC real_CreateWindowExA = CreateWindowExA;
DESTROYWINDOWPROC real_DestroyWindow = DestroyWindow;
GETDEVICECAPSPROC real_GetDeviceCaps = GetDeviceCaps;
LOADLIBRARYAPROC real_LoadLibraryA = LoadLibraryA;
LOADLIBRARYWPROC real_LoadLibraryW = LoadLibraryW;
LOADLIBRARYEXAPROC real_LoadLibraryExA = LoadLibraryExA;
2020-09-19 11:23:06 +02:00
LOADLIBRARYEXWPROC real_LoadLibraryExW = LoadLibraryExW;
2019-08-06 04:37:06 +02:00
2020-10-19 16:37:12 +02:00
static hook_list g_hooks[] =
{
{
"user32.dll",
TRUE,
{
{ "GetCursorPos", (PROC)fake_GetCursorPos, (PROC*)&real_GetCursorPos },
{ "ClipCursor", (PROC)fake_ClipCursor, (PROC*)&real_ClipCursor },
{ "ShowCursor", (PROC)fake_ShowCursor, (PROC*)&real_ShowCursor },
{ "SetCursor", (PROC)fake_SetCursor, (PROC*)&real_SetCursor },
{ "GetWindowRect", (PROC)fake_GetWindowRect, (PROC*)&real_GetWindowRect },
{ "GetClientRect", (PROC)fake_GetClientRect, (PROC*)&real_GetClientRect },
{ "ClientToScreen", (PROC)fake_ClientToScreen, (PROC*)&real_ClientToScreen },
{ "ScreenToClient", (PROC)fake_ScreenToClient, (PROC*)&real_ScreenToClient },
{ "SetCursorPos", (PROC)fake_SetCursorPos, (PROC*)&real_SetCursorPos },
{ "GetClipCursor", (PROC)fake_GetClipCursor, (PROC*)&real_GetClipCursor },
{ "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC*)&real_WindowFromPoint },
{ "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC*)&real_GetCursorInfo },
{ "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC*)&real_GetSystemMetrics },
{ "SetWindowPos", (PROC)fake_SetWindowPos, (PROC*)&real_SetWindowPos },
{ "MoveWindow", (PROC)fake_MoveWindow, (PROC*)&real_MoveWindow },
{ "SendMessageA", (PROC)fake_SendMessageA, (PROC*)&real_SendMessageA },
{ "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC*)&real_SetWindowLongA },
{ "EnableWindow", (PROC)fake_EnableWindow, (PROC*)&real_EnableWindow },
{ "CreateWindowExA", (PROC)fake_CreateWindowExA, (PROC*)&real_CreateWindowExA },
{ "DestroyWindow", (PROC)fake_DestroyWindow, (PROC*)&real_DestroyWindow },
{ "", NULL }
}
},
{
"gdi32.dll",
TRUE,
{
{ "GetDeviceCaps", (PROC)fake_GetDeviceCaps, (PROC*)&real_GetDeviceCaps },
{ "", NULL }
}
},
{
"kernel32.dll",
FALSE,
{
{ "LoadLibraryA", (PROC)fake_LoadLibraryA, (PROC*)&real_LoadLibraryA },
{ "LoadLibraryW", (PROC)fake_LoadLibraryW, (PROC*)&real_LoadLibraryW },
{ "LoadLibraryExA", (PROC)fake_LoadLibraryExA, (PROC*)&real_LoadLibraryExA },
{ "LoadLibraryExW", (PROC)fake_LoadLibraryExW, (PROC*)&real_LoadLibraryExW },
{ "", NULL }
}
},
{
"",
FALSE,
{
{ "", NULL }
}
}
};
2019-03-19 06:57:49 +01:00
2020-10-13 09:20:52 +02:00
void hook_patch_iat(HMODULE hmod, char *module_name, char *function_name, PROC new_function)
2019-03-19 06:57:49 +01:00
{
2020-10-13 09:20:52 +02:00
if (!hmod || hmod == INVALID_HANDLE_VALUE || !new_function)
2019-03-19 06:57:49 +01:00
return;
2020-09-22 14:04:49 +02:00
#ifdef _MSC_VER
__try
{
#endif
2020-10-13 09:20:52 +02:00
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)hmod;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
2020-09-22 14:04:49 +02:00
return;
2019-03-19 06:57:49 +01:00
2020-10-13 09:20:52 +02:00
PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((DWORD)dos_header + (DWORD)dos_header->e_lfanew);
if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
2020-09-22 14:04:49 +02:00
return;
2019-03-19 06:57:49 +01:00
2020-10-13 09:20:52 +02:00
PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos_header +
(DWORD)(nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
2019-03-19 06:57:49 +01:00
2020-10-13 09:20:52 +02:00
if (import_desc == (PIMAGE_IMPORT_DESCRIPTOR)nt_headers)
2020-09-22 14:04:49 +02:00
return;
2019-03-19 06:57:49 +01:00
2020-10-13 09:20:52 +02:00
while (import_desc->FirstThunk)
2019-03-19 06:57:49 +01:00
{
2020-10-13 09:20:52 +02:00
char* imp_module_name = (char*)((DWORD)dos_header + (DWORD)(import_desc->Name));
2019-03-19 06:57:49 +01:00
2020-10-13 09:20:52 +02:00
if (_stricmp(imp_module_name, module_name) == 0)
2019-03-19 06:57:49 +01:00
{
2020-10-13 09:20:52 +02:00
PIMAGE_THUNK_DATA first_thunk =
(PIMAGE_THUNK_DATA)((DWORD)dos_header + (DWORD)import_desc->FirstThunk);
2019-03-19 06:57:49 +01:00
2020-10-13 09:20:52 +02:00
PIMAGE_THUNK_DATA original_first_thunk =
(PIMAGE_THUNK_DATA)((DWORD)dos_header + (DWORD)import_desc->OriginalFirstThunk);
2020-09-22 14:04:49 +02:00
2020-10-13 09:20:52 +02:00
while (first_thunk->u1.Function && original_first_thunk->u1.AddressOfData)
2019-03-19 06:57:49 +01:00
{
2020-10-13 09:20:52 +02:00
PIMAGE_IMPORT_BY_NAME import =
(PIMAGE_IMPORT_BY_NAME)((DWORD)dos_header + original_first_thunk->u1.AddressOfData);
2019-03-19 06:57:49 +01:00
2020-10-13 09:20:52 +02:00
if ((original_first_thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0 &&
_stricmp((const char*)import->Name, function_name) == 0)
2019-03-19 06:57:49 +01:00
{
2020-10-13 09:20:52 +02:00
DWORD old_protect;
2020-09-22 14:04:49 +02:00
2020-10-13 09:20:52 +02:00
if (VirtualProtect(&first_thunk->u1.Function, sizeof(DWORD), PAGE_READWRITE, &old_protect))
2020-09-22 14:04:49 +02:00
{
2020-10-13 09:20:52 +02:00
first_thunk->u1.Function = (DWORD)new_function;
VirtualProtect(&first_thunk->u1.Function, sizeof(DWORD), old_protect, &old_protect);
2020-09-22 14:04:49 +02:00
}
break;
2019-03-19 06:57:49 +01:00
}
2020-10-13 09:20:52 +02:00
first_thunk++;
original_first_thunk++;
2019-03-19 06:57:49 +01:00
}
}
2020-10-13 09:20:52 +02:00
import_desc++;
2020-09-22 14:04:49 +02:00
}
#ifdef _MSC_VER
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
2019-03-19 06:57:49 +01:00
}
2020-09-22 14:04:49 +02:00
#endif
2019-03-19 06:57:49 +01:00
}
2020-10-19 16:37:12 +02:00
void hook_create(hook_list* hooks)
2019-03-19 06:57:49 +01:00
{
2019-08-07 12:45:40 +02:00
#ifdef _MSC_VER
2020-10-13 09:20:52 +02:00
if (g_hook_method == 2)
2019-03-20 05:07:28 +01:00
{
2020-10-19 16:37:12 +02:00
for (int i = 0; hooks[i].module_name[0]; i++)
{
if (!hooks[i].enabled)
continue;
for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((PVOID*)hooks[i].data[x].function, (PVOID)hooks[i].data[x].new_function);
DetourTransactionCommit();
}
}
2019-03-20 05:07:28 +01:00
}
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
if (g_hook_method == 3 || g_hook_method == 4)
2020-09-19 11:23:06 +02:00
{
2020-10-13 09:20:52 +02:00
WCHAR game_exe_path[MAX_PATH] = { 0 };
WCHAR game_dir[MAX_PATH] = { 0 };
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
if (GetModuleFileNameW(NULL, game_exe_path, MAX_PATH))
2020-09-19 11:23:06 +02:00
{
2020-10-13 09:20:52 +02:00
_wsplitpath(game_exe_path, NULL, game_dir, NULL, NULL);
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
WCHAR mod_path[MAX_PATH] = { 0 };
WCHAR mod_dir[MAX_PATH] = { 0 };
HMODULE hmod = NULL;
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
while (hmod = DetourEnumerateModules(hmod))
2020-09-19 11:23:06 +02:00
{
2020-10-13 09:20:52 +02:00
if (hmod == g_ddraw_module)
2020-09-19 11:23:06 +02:00
continue;
2020-10-13 09:20:52 +02:00
if (GetModuleFileNameW(hmod, mod_path, MAX_PATH))
2020-09-19 11:23:06 +02:00
{
2020-10-13 09:20:52 +02:00
_wsplitpath(mod_path, NULL, mod_dir, NULL, NULL);
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
if (_wcsnicmp(game_dir, mod_dir, wcslen(game_dir)) == 0)
2020-09-19 11:23:06 +02:00
{
2020-10-19 16:37:12 +02:00
for (int i = 0; hooks[i].module_name[0]; i++)
{
if (!hooks[i].enabled)
continue;
for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{
hook_patch_iat(
hmod,
hooks[i].module_name,
hooks[i].data[x].function_name,
hooks[i].data[x].new_function);
}
}
2020-09-19 11:23:06 +02:00
}
}
}
}
}
2019-08-07 12:45:40 +02:00
#endif
2019-03-20 05:07:28 +01:00
2020-10-13 09:20:52 +02:00
if (g_hook_method == 1)
2019-08-07 12:59:23 +02:00
{
2020-10-19 16:37:12 +02:00
for (int i = 0; hooks[i].module_name[0]; i++)
{
if (!hooks[i].enabled)
continue;
for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{
hook_patch_iat(
GetModuleHandle(NULL),
hooks[i].module_name,
hooks[i].data[x].function_name,
hooks[i].data[x].new_function);
}
}
2019-08-07 12:59:23 +02:00
}
2019-03-19 06:57:49 +01:00
}
2020-10-19 16:37:12 +02:00
void hook_revert(hook_list* hooks)
2019-03-19 06:57:49 +01:00
{
2019-08-07 12:45:40 +02:00
#ifdef _MSC_VER
2020-10-13 09:20:52 +02:00
if (g_hook_method == 2)
2019-03-19 06:57:49 +01:00
{
2020-10-19 16:37:12 +02:00
for (int i = 0; hooks[i].module_name[0]; i++)
{
if (!hooks[i].enabled)
continue;
for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach((PVOID*)hooks[i].data[x].function, (PVOID)hooks[i].data[x].new_function);
DetourTransactionCommit();
}
}
2019-03-19 09:43:47 +01:00
}
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
if (g_hook_method == 3 || g_hook_method == 4)
2020-09-19 11:23:06 +02:00
{
2020-10-13 09:20:52 +02:00
WCHAR game_exe_path[MAX_PATH] = { 0 };
WCHAR game_dir[MAX_PATH] = { 0 };
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
if (GetModuleFileNameW(NULL, game_exe_path, MAX_PATH))
2020-09-19 11:23:06 +02:00
{
2020-10-13 09:20:52 +02:00
_wsplitpath(game_exe_path, NULL, game_dir, NULL, NULL);
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
WCHAR mod_path[MAX_PATH] = { 0 };
WCHAR mod_dir[MAX_PATH] = { 0 };
HMODULE hmod = NULL;
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
while (hmod = DetourEnumerateModules(hmod))
2020-09-19 11:23:06 +02:00
{
2020-10-13 09:20:52 +02:00
if (hmod == g_ddraw_module)
2020-09-19 11:23:06 +02:00
continue;
2020-10-13 09:20:52 +02:00
if (GetModuleFileNameW(hmod, mod_path, MAX_PATH))
2020-09-19 11:23:06 +02:00
{
2020-10-13 09:20:52 +02:00
_wsplitpath(mod_path, NULL, mod_dir, NULL, NULL);
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
if (_wcsnicmp(game_dir, mod_dir, wcslen(game_dir)) == 0)
2020-09-19 11:23:06 +02:00
{
2020-10-19 16:37:12 +02:00
for (int i = 0; hooks[i].module_name[0]; i++)
{
if (!hooks[i].enabled)
continue;
for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{
hook_patch_iat(
hmod,
hooks[i].module_name,
hooks[i].data[x].function_name,
GetProcAddress(GetModuleHandle(hooks[i].module_name), hooks[i].data[x].function_name));
}
}
2020-09-19 11:23:06 +02:00
}
}
}
}
}
2019-08-07 12:45:40 +02:00
#endif
2019-08-06 04:37:06 +02:00
2020-10-13 09:20:52 +02:00
if (g_hook_method == 1)
2019-08-07 12:45:40 +02:00
{
2020-10-19 16:37:12 +02:00
for (int i = 0; hooks[i].module_name[0]; i++)
{
if (!hooks[i].enabled)
continue;
for (int x = 0; hooks[i].data[x].function_name[0]; x++)
{
hook_patch_iat(
GetModuleHandle(NULL),
hooks[i].module_name,
hooks[i].data[x].function_name,
GetProcAddress(GetModuleHandle(hooks[i].module_name), hooks[i].data[x].function_name));
}
}
2019-03-19 06:57:49 +01:00
}
}
2020-10-13 09:20:52 +02:00
void hook_init()
2019-03-19 06:57:49 +01:00
{
2020-10-13 09:20:52 +02:00
if (!g_hook_active || g_hook_method == 3 || g_hook_method == 4)
2019-03-19 06:57:49 +01:00
{
2020-09-22 14:04:49 +02:00
#ifdef _MSC_VER
2020-10-13 09:20:52 +02:00
if (!g_hook_active && g_hook_method == 3)
2020-09-19 11:23:06 +02:00
{
2020-09-19 12:05:49 +02:00
FARPROC proc = GetProcAddress(GetModuleHandle("kernelbase.dll"), "LoadLibraryExW");
if (proc)
2020-09-22 14:04:49 +02:00
real_LoadLibraryExW = (LOADLIBRARYEXWPROC)proc;
2020-09-19 12:05:49 +02:00
2020-09-19 11:23:06 +02:00
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((PVOID*)&real_LoadLibraryExW, (PVOID)fake_LoadLibraryExW);
DetourTransactionCommit();
}
2020-09-22 14:04:49 +02:00
#endif
2020-09-19 11:23:06 +02:00
2020-10-13 09:20:52 +02:00
g_hook_active = TRUE;
if (g_hook_method == 4)
{
2020-10-19 16:37:12 +02:00
for (int i = 0; g_hooks[i].module_name[0]; i++)
{
if (_stricmp(g_hooks[i].module_name, "kernel32.dll") == 0)
{
g_hooks[i].enabled = TRUE;
}
}
}
2020-10-19 16:37:12 +02:00
hook_create((hook_list*)&g_hooks);
2019-08-07 12:45:40 +02:00
}
}
2020-10-13 09:20:52 +02:00
void hook_exit()
2019-08-07 12:45:40 +02:00
{
2020-10-13 09:20:52 +02:00
if (g_hook_active)
2019-08-07 12:45:40 +02:00
{
2020-10-13 09:20:52 +02:00
g_hook_active = FALSE;
2019-08-07 12:45:40 +02:00
2020-09-22 14:04:49 +02:00
#ifdef _MSC_VER
2020-10-13 09:20:52 +02:00
if (g_hook_method == 3)
2020-09-19 11:23:06 +02:00
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach((PVOID*)&real_LoadLibraryExW, (PVOID)fake_LoadLibraryExW);
DetourTransactionCommit();
}
2020-09-22 14:04:49 +02:00
#endif
2020-09-19 11:23:06 +02:00
2020-10-19 16:37:12 +02:00
hook_revert((hook_list*)&g_hooks);
2019-03-19 06:57:49 +01:00
}
}