optional hotpatch support
This commit is contained in:
parent
b49cd06876
commit
03100ee84b
12 changed files with 356 additions and 156 deletions
190
src/hook.c
Normal file
190
src/hook.c
Normal file
|
@ -0,0 +1,190 @@
|
|||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "main.h"
|
||||
#include "mouse.h"
|
||||
#include "hook.h"
|
||||
|
||||
BOOL Hook_Active;
|
||||
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;
|
||||
|
||||
void Hook_PatchIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction)
|
||||
{
|
||||
if (!hMod || hMod == INVALID_HANDLE_VALUE || !newFunction)
|
||||
return;
|
||||
|
||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMod;
|
||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return;
|
||||
|
||||
PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + (DWORD)pDosHeader->e_lfanew);
|
||||
if (pNTHeaders->Signature != IMAGE_NT_SIGNATURE)
|
||||
return;
|
||||
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDosHeader +
|
||||
(DWORD)(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
|
||||
|
||||
if (pImportDescriptor == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeaders)
|
||||
return;
|
||||
|
||||
while (pImportDescriptor->FirstThunk)
|
||||
{
|
||||
char *impModuleName = (char *)((DWORD)pDosHeader + (DWORD)(pImportDescriptor->Name));
|
||||
|
||||
if (_stricmp(impModuleName, moduleName) == 0)
|
||||
{
|
||||
PIMAGE_THUNK_DATA pFirstThunk =
|
||||
(PIMAGE_THUNK_DATA)((DWORD)pDosHeader + (DWORD)pImportDescriptor->FirstThunk);
|
||||
|
||||
PIMAGE_THUNK_DATA pOrigFirstThunk =
|
||||
(PIMAGE_THUNK_DATA)((DWORD)pDosHeader + (DWORD)pImportDescriptor->OriginalFirstThunk);
|
||||
|
||||
while (pFirstThunk->u1.Function && pOrigFirstThunk->u1.AddressOfData)
|
||||
{
|
||||
PIMAGE_IMPORT_BY_NAME pImport =
|
||||
(PIMAGE_IMPORT_BY_NAME)((DWORD)pDosHeader + pOrigFirstThunk->u1.AddressOfData);
|
||||
|
||||
if ((pOrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0 &&
|
||||
_stricmp((const char *)pImport->Name, functionName) == 0)
|
||||
{
|
||||
DWORD oldProtect;
|
||||
|
||||
if (VirtualProtect(&pFirstThunk->u1.Function, sizeof(DWORD), PAGE_READWRITE, &oldProtect))
|
||||
{
|
||||
pFirstThunk->u1.Function = (DWORD)newFunction;
|
||||
VirtualProtect(&pFirstThunk->u1.Function, sizeof(DWORD), oldProtect, &oldProtect);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
pFirstThunk++;
|
||||
pOrigFirstThunk++;
|
||||
}
|
||||
}
|
||||
|
||||
pImportDescriptor++;
|
||||
}
|
||||
}
|
||||
|
||||
PROC Hook_HotPatch(PROC function, PROC newFunction)
|
||||
{
|
||||
PROC result = function;
|
||||
|
||||
unsigned short *bytes = (unsigned short *)function;
|
||||
if (function && *bytes == 0xFF8B) // mov edi, edi
|
||||
{
|
||||
char *address = ((char *)function) - 5;
|
||||
DWORD oldProtect;
|
||||
|
||||
if (VirtualProtect(address, 7, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
{
|
||||
if (memcmp(address, (const char[]) { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, 5) == 0 ||
|
||||
memcmp(address, (const char[]) { 0x90, 0x90, 0x90, 0x90, 0x90 }, 5) == 0)
|
||||
{
|
||||
address[0] = 0xE9; // long jump
|
||||
*((DWORD *)(&address[1])) = ((char *)newFunction) - address - 5;
|
||||
*((WORD *)(&address[5])) = 0xF9EB; // short jump to our long jump
|
||||
|
||||
result = (PROC)(((char *)function) + 2);
|
||||
}
|
||||
|
||||
VirtualProtect(address, 7, oldProtect, &oldProtect);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Hook_TryHotPatch(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction, PROC *function)
|
||||
{
|
||||
PROC org = GetProcAddress(GetModuleHandle(moduleName), functionName);
|
||||
if (org)
|
||||
{
|
||||
*function = Hook_HotPatch(org, newFunction);
|
||||
|
||||
if (*function == org) // hotpatch failed...
|
||||
Hook_PatchIAT(hMod, moduleName, functionName, newFunction);
|
||||
}
|
||||
}
|
||||
|
||||
void Hook_Init()
|
||||
{
|
||||
if (!Hook_Active)
|
||||
{
|
||||
Hook_Active = TRUE;
|
||||
|
||||
if (ddraw->hotPatch)
|
||||
{
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
|
||||
Hook_TryHotPatch(
|
||||
GetModuleHandle(NULL), "user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
|
||||
}
|
||||
else
|
||||
{
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "ClipCursor", (PROC)fake_ClipCursor);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "ShowCursor", (PROC)fake_ShowCursor);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SetCursor", (PROC)fake_SetCursor);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetClientRect", (PROC)fake_GetClientRect);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "MoveWindow", (PROC)fake_MoveWindow);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SendMessageA", (PROC)fake_SendMessageA);
|
||||
Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue