Ring3 Api Hook (2) Hot patching inline hook
1
#pragma once
2 #include < stdio.h >
3 // module: InlineHook.h
4 // author: cntrump
5 // create: 2011-05-11
6
7 #if defined(DEBUG)||defined(_DEBUG)
8 #define HOOKTRACE Trace
9 #else
10 #define HOOKTRACE
11 #endif
12
13 static inline void Trace(LPCWSTR fmt, )
14 {
15 WCHAR wzOut[MAX_PATH];
16 ZeroMemory(wzOut, sizeof (wzOut));
17 va_list arg_list;
18 va_start(arg_list, fmt);
19 _vswprintf_p(wzOut, _countof(wzOut), fmt, arg_list);
20 va_end(arg_list);
21
22 OutputDebugStringW(wzOut);
23 }
24
25 class CHotPatchInlineHook
26 {
27 public :
28 CHotPatchInlineHook(HANDLE hProcess, LPVOID pRealFuncAddress, LPVOID pFakeFuncAddress)
29 :m_hProcess(hProcess)
30 ,m_pRealFuncAddress(pRealFuncAddress)
31 {
32 if ( ! WriteLongJmp(pRealFuncAddress, pFakeFuncAddress))
33 HOOKTRACE(L " WriteLongJmp error " );
34
35 if ( ! WriteShortJmp(pRealFuncAddress))
36 HOOKTRACE(L " WriteShortJmp error " );
37 }
38
39 ~ CHotPatchInlineHook()
40 {
41 UnHook();
42 }
43
44 VOID UnHook()
45 {
46 UnloadShortJmp();
47 UnloadLongJmp();
48 }
49 protected :
50 BOOL WriteShortJmp(LPVOID pRealFuncAddress)
51 {
52 DWORD dwOldProtect;
53 BOOL bRet;
54 bRet = VirtualProtectEx(m_hProcess, pRealFuncAddress, sizeof (ShortJmp), PAGE_EXECUTE_READWRITE, & dwOldProtect);
55
56 if ( ! bRet)
57 return FALSE;
58
59 HOOKTRACE(L " Org Address: %X " , (DWORD)pRealFuncAddress);
60
61 CopyMemory( & m_orgShortJmp, pRealFuncAddress, sizeof (ShortJmp));
62 CopyMemory( & m_shortJmp, pRealFuncAddress, sizeof (ShortJmp));
63 // 构造 jmp $-5
64 m_shortJmp.op = 0xEB ;
65 m_shortJmp.offset = 0xF9 ;
66 DWORD dwNumberOfByteWritten;
67 bRet = WriteProcessMemory(m_hProcess, pRealFuncAddress, & m_shortJmp, sizeof (ShortJmp), & dwNumberOfByteWritten);
68 VirtualProtectEx(m_hProcess, pRealFuncAddress, sizeof (ShortJmp), dwOldProtect, & dwOldProtect);
69
70 return bRet;
71 }
72
73 BOOL WriteLongJmp(LPVOID pRealFuncAddress, LPVOID pFakeFuncAddress)
74 {
75 DWORD dwRealFuncAddress = GetRealFuncAddress(pFakeFuncAddress);
76 // 构造 call xxxxxxxx
77 m_longJmp.op = 0xE8 ;
78 m_longJmp.offset = GetFuncOffset((LPBYTE)pRealFuncAddress - 5 , (LPVOID)dwRealFuncAddress, 5 );
79 DWORD dwOldProtect;
80 VirtualProtectEx(m_hProcess, (LPBYTE)pRealFuncAddress - 5 , sizeof (LongJmp), PAGE_EXECUTE_READWRITE, & dwOldProtect);
81 CopyMemory( & m_orgLongJmp, (LPBYTE)pRealFuncAddress - 5 , sizeof (LongJmp));
82 DWORD dwNumberOfByteWritten;
83 BOOL bRet;
84 bRet = WriteProcessMemory(m_hProcess, (LPBYTE)pRealFuncAddress - 5 , & m_longJmp, sizeof (LongJmp), & dwNumberOfByteWritten);
85 VirtualProtectEx(m_hProcess, (LPBYTE)pRealFuncAddress - 5 , sizeof (LongJmp), dwOldProtect, & dwOldProtect);
86 return bRet;
87 }
88
89 BOOL UnloadShortJmp()
90 {
91 DWORD dwOldProtect;
92 DWORD dwNumberOfBytesWritten;
93 BOOL bRet;
94 VirtualProtectEx(m_hProcess, m_pRealFuncAddress, sizeof (ShortJmp), PAGE_EXECUTE_READWRITE, & dwOldProtect);
95 bRet = WriteProcessMemory(m_hProcess, m_pRealFuncAddress, & m_orgShortJmp, sizeof (ShortJmp), & dwNumberOfBytesWritten);
96 VirtualProtectEx(m_hProcess, m_pRealFuncAddress, sizeof (ShortJmp), dwOldProtect, & dwOldProtect);
97
98 return bRet;
99 }
100
101 BOOL UnloadLongJmp()
102 {
103 DWORD dwOldProtect;
104 DWORD dwNumberOfBytesWritten;
105 BOOL bRet;
106 VirtualProtectEx(m_hProcess, (LPBYTE)m_pRealFuncAddress - 5 , sizeof (LongJmp), PAGE_EXECUTE_READWRITE, & dwOldProtect);
107 bRet = WriteProcessMemory(m_hProcess, (LPBYTE)m_pRealFuncAddress - 5 , & m_longJmp, sizeof (LongJmp), & dwNumberOfBytesWritten);
108 VirtualProtectEx(m_hProcess, (LPBYTE)m_pRealFuncAddress - 5 , sizeof (LongJmp), dwOldProtect, & dwOldProtect);
109
110 return bRet;
111 }
112
113 protected :
114 HANDLE m_hProcess;
115 LPVOID m_pRealFuncAddress;
116 protected :
117
118 DWORD GetRealFuncAddress(LPVOID pFunc)
119 {
120 DWORD realaddr = (DWORD)pFunc;
121 LongJmp longJmp;
122 CopyMemory( & longJmp, pFunc, sizeof (longJmp));
123
124
125 if (longJmp.op == 0xE9 )
126 {
127 realaddr += longJmp.offset + 5 ;
128 }
129
130 return realaddr;
131 }
132
133 DWORD GetFuncOffset(LPVOID pInAddress, LPVOID pFuncAddress, UINT nCodeLen)
134 {
135 return (DWORD)pFuncAddress - (DWORD)pInAddress - nCodeLen;
136 }
137
138 #pragma pack(push, 1 )
139
140 struct LongJmp
141 {
142 BYTE op;
143 DWORD offset;
144 }m_longJmp, m_orgLongJmp; // 把长跳转写入 nop 块
145
146 struct ShortJmp
147 {
148 BYTE op;
149 BYTE offset;
150 }m_shortJmp, m_orgShortJmp; // 短跳,用于跳转到前面的 nop 块
151
152 #pragma pack(pop)
153 };
2 #include < stdio.h >
3 // module: InlineHook.h
4 // author: cntrump
5 // create: 2011-05-11
6
7 #if defined(DEBUG)||defined(_DEBUG)
8 #define HOOKTRACE Trace
9 #else
10 #define HOOKTRACE
11 #endif
12
13 static inline void Trace(LPCWSTR fmt, )
14 {
15 WCHAR wzOut[MAX_PATH];
16 ZeroMemory(wzOut, sizeof (wzOut));
17 va_list arg_list;
18 va_start(arg_list, fmt);
19 _vswprintf_p(wzOut, _countof(wzOut), fmt, arg_list);
20 va_end(arg_list);
21
22 OutputDebugStringW(wzOut);
23 }
24
25 class CHotPatchInlineHook
26 {
27 public :
28 CHotPatchInlineHook(HANDLE hProcess, LPVOID pRealFuncAddress, LPVOID pFakeFuncAddress)
29 :m_hProcess(hProcess)
30 ,m_pRealFuncAddress(pRealFuncAddress)
31 {
32 if ( ! WriteLongJmp(pRealFuncAddress, pFakeFuncAddress))
33 HOOKTRACE(L " WriteLongJmp error " );
34
35 if ( ! WriteShortJmp(pRealFuncAddress))
36 HOOKTRACE(L " WriteShortJmp error " );
37 }
38
39 ~ CHotPatchInlineHook()
40 {
41 UnHook();
42 }
43
44 VOID UnHook()
45 {
46 UnloadShortJmp();
47 UnloadLongJmp();
48 }
49 protected :
50 BOOL WriteShortJmp(LPVOID pRealFuncAddress)
51 {
52 DWORD dwOldProtect;
53 BOOL bRet;
54 bRet = VirtualProtectEx(m_hProcess, pRealFuncAddress, sizeof (ShortJmp), PAGE_EXECUTE_READWRITE, & dwOldProtect);
55
56 if ( ! bRet)
57 return FALSE;
58
59 HOOKTRACE(L " Org Address: %X " , (DWORD)pRealFuncAddress);
60
61 CopyMemory( & m_orgShortJmp, pRealFuncAddress, sizeof (ShortJmp));
62 CopyMemory( & m_shortJmp, pRealFuncAddress, sizeof (ShortJmp));
63 // 构造 jmp $-5
64 m_shortJmp.op = 0xEB ;
65 m_shortJmp.offset = 0xF9 ;
66 DWORD dwNumberOfByteWritten;
67 bRet = WriteProcessMemory(m_hProcess, pRealFuncAddress, & m_shortJmp, sizeof (ShortJmp), & dwNumberOfByteWritten);
68 VirtualProtectEx(m_hProcess, pRealFuncAddress, sizeof (ShortJmp), dwOldProtect, & dwOldProtect);
69
70 return bRet;
71 }
72
73 BOOL WriteLongJmp(LPVOID pRealFuncAddress, LPVOID pFakeFuncAddress)
74 {
75 DWORD dwRealFuncAddress = GetRealFuncAddress(pFakeFuncAddress);
76 // 构造 call xxxxxxxx
77 m_longJmp.op = 0xE8 ;
78 m_longJmp.offset = GetFuncOffset((LPBYTE)pRealFuncAddress - 5 , (LPVOID)dwRealFuncAddress, 5 );
79 DWORD dwOldProtect;
80 VirtualProtectEx(m_hProcess, (LPBYTE)pRealFuncAddress - 5 , sizeof (LongJmp), PAGE_EXECUTE_READWRITE, & dwOldProtect);
81 CopyMemory( & m_orgLongJmp, (LPBYTE)pRealFuncAddress - 5 , sizeof (LongJmp));
82 DWORD dwNumberOfByteWritten;
83 BOOL bRet;
84 bRet = WriteProcessMemory(m_hProcess, (LPBYTE)pRealFuncAddress - 5 , & m_longJmp, sizeof (LongJmp), & dwNumberOfByteWritten);
85 VirtualProtectEx(m_hProcess, (LPBYTE)pRealFuncAddress - 5 , sizeof (LongJmp), dwOldProtect, & dwOldProtect);
86 return bRet;
87 }
88
89 BOOL UnloadShortJmp()
90 {
91 DWORD dwOldProtect;
92 DWORD dwNumberOfBytesWritten;
93 BOOL bRet;
94 VirtualProtectEx(m_hProcess, m_pRealFuncAddress, sizeof (ShortJmp), PAGE_EXECUTE_READWRITE, & dwOldProtect);
95 bRet = WriteProcessMemory(m_hProcess, m_pRealFuncAddress, & m_orgShortJmp, sizeof (ShortJmp), & dwNumberOfBytesWritten);
96 VirtualProtectEx(m_hProcess, m_pRealFuncAddress, sizeof (ShortJmp), dwOldProtect, & dwOldProtect);
97
98 return bRet;
99 }
100
101 BOOL UnloadLongJmp()
102 {
103 DWORD dwOldProtect;
104 DWORD dwNumberOfBytesWritten;
105 BOOL bRet;
106 VirtualProtectEx(m_hProcess, (LPBYTE)m_pRealFuncAddress - 5 , sizeof (LongJmp), PAGE_EXECUTE_READWRITE, & dwOldProtect);
107 bRet = WriteProcessMemory(m_hProcess, (LPBYTE)m_pRealFuncAddress - 5 , & m_longJmp, sizeof (LongJmp), & dwNumberOfBytesWritten);
108 VirtualProtectEx(m_hProcess, (LPBYTE)m_pRealFuncAddress - 5 , sizeof (LongJmp), dwOldProtect, & dwOldProtect);
109
110 return bRet;
111 }
112
113 protected :
114 HANDLE m_hProcess;
115 LPVOID m_pRealFuncAddress;
116 protected :
117
118 DWORD GetRealFuncAddress(LPVOID pFunc)
119 {
120 DWORD realaddr = (DWORD)pFunc;
121 LongJmp longJmp;
122 CopyMemory( & longJmp, pFunc, sizeof (longJmp));
123
124
125 if (longJmp.op == 0xE9 )
126 {
127 realaddr += longJmp.offset + 5 ;
128 }
129
130 return realaddr;
131 }
132
133 DWORD GetFuncOffset(LPVOID pInAddress, LPVOID pFuncAddress, UINT nCodeLen)
134 {
135 return (DWORD)pFuncAddress - (DWORD)pInAddress - nCodeLen;
136 }
137
138 #pragma pack(push, 1 )
139
140 struct LongJmp
141 {
142 BYTE op;
143 DWORD offset;
144 }m_longJmp, m_orgLongJmp; // 把长跳转写入 nop 块
145
146 struct ShortJmp
147 {
148 BYTE op;
149 BYTE offset;
150 }m_shortJmp, m_orgShortJmp; // 短跳,用于跳转到前面的 nop 块
151
152 #pragma pack(pop)
153 };