学一学 hook 专题,今天是 hotfix hook。

学习笔记

hotfix hook和 inline hook差不多,但是有利用条件,一是被hook的位置附近有空内存,那么可以直接把被 hook 函数的代码先短跳到附近内存,然后由这个内存跳转到我们自己的函数,这样的话就不需要频繁地装钩卸钩了。

也直接试试吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <stdio.h>
#include <Windows.h>

typedef int
(WINAPI
* fnMessageBoxA)(
_In_opt_ HWND hWnd,
_In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption,
_In_ UINT uType);

int
WINAPI
MyMessageBoxA(
_In_opt_ HWND hWnd,
_In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption,
_In_ UINT uType)
{
fnMessageBoxA NewFunc = (fnMessageBoxA)((DWORD)MessageBoxA + 2);
return NewFunc(hWnd, "xia0ji233", "hooked by xia0ji233", uType);
}

BOOL HOOK(const char* szModuleName, const char* szFuncName, PROC pfnFunc)
{
BYTE ShortJmp[2] = { 0xEB,0xF9 };
BYTE NewCodes[5] = { 0xE9,0, };
DWORD dwOldProtect = 0;
FARPROC pOldFuncAddr = (FARPROC)GetProcAddress(GetModuleHandleA(szModuleName), szFuncName);
VirtualProtect((LPVOID)((DWORD)pOldFuncAddr - 5), 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);
DWORD dwAddr = ((DWORD)pfnFunc - (DWORD)pOldFuncAddr);
*(DWORD*)(NewCodes + 1) = dwAddr;
memcpy((LPVOID)((DWORD)pOldFuncAddr - 5), NewCodes, 5);
memcpy(pOldFuncAddr, ShortJmp, 2);
VirtualProtect((LPVOID)((DWORD)pOldFuncAddr - 5), 7, dwOldProtect, &dwOldProtect);
return TRUE;
}

BOOL UnHook(const char* szModuleName, const char* szFuncName)
{
BYTE ShortJmp[2] = { 0x8B,0xFF };
BYTE NewCodes[5] = { 0x90,0x90,0x90,0x90,0x90 };
FARPROC pOldFuncAddr = (FARPROC)GetProcAddress(GetModuleHandleA(szModuleName), szFuncName);
DWORD dwOldProtect = 0;
VirtualProtect((LPVOID)((DWORD)pOldFuncAddr - 5), 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);
memcpy((LPVOID)((DWORD)pOldFuncAddr - 5), NewCodes, 5);
memcpy(pOldFuncAddr, ShortJmp, 2);
VirtualProtect((LPVOID)((DWORD)pOldFuncAddr - 5), 7, dwOldProtect, &dwOldProtect);
return TRUE;
}

BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
HOOK("user32.dll", "MessageBoxA", (PROC)MyMessageBoxA);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
UnHook("user32.dll", "MessageBoxA");
break;
}
return TRUE;
}

运行结果