TNB Library
TnbApiHooker.h
[詳解]
1#pragma once
11#include "TnbSimpleVector.h"
12#include "TnbWindowsVersion.h"
13
14
15
16
17
18//TNB Library
19namespace TNB
20{
21
22
23
78template<class PFNC>
80{
81public:
82
93 static PFNC Replace(LPCSTR lpszDllName, LPCSTR lpszFuncName, PFNC pFnc, HMODULE hModule = NULL)
94 {
96 bool r = a.Hook(lpszDllName, lpszFuncName, pFnc, hModule);
97 return r ? a() : NULL;
98 }
99
100
101 //----
102
103
105 CApiHookerT(void) : m_pOrignalFnc(NULL), m_hModule(NULL)
106 {
107 }
108
120 bool Hook(LPCSTR lpszDllName, LPCSTR lpszFuncName, PFNC pFnc, HMODULE hModule = NULL)
121 {
122 Unhook();
124 if ( ! wv.IsWow64() )
125 {
126 if ( hModule == NULL )
127 {
129 }
130 m_modules.RemoveAll();
131 m_pOrignalFnc = m_Replace(hModule, lpszDllName, lpszFuncName, pFnc);
132 if ( m_pOrignalFnc != NULL )
133 {
134 m_hModule = hModule;
135 m_strDllName = lpszDllName;
136 m_strFuncName = lpszFuncName;
137 return true;
138 }
139 }
140 return false;
141 }
142
149 bool Unhook(void)
150 {
151 if ( m_pOrignalFnc != NULL )
152 {
153 LPCSTR lpszFuncName = m_strFuncName;
154 m_modules.RemoveAll();
155 if ( m_Replace(m_hModule, m_strDllName, lpszFuncName, m_pOrignalFnc) == NULL )
156 {
157 return false;
158 }
159 m_pOrignalFnc = NULL;
160 m_strDllName.Empty();
161 m_strFuncName.Empty();
162 m_hModule = NULL;
163 }
164 return true;
165 }
166
172 PFNC operator()(void)
173 {
174 return m_pOrignalFnc;
175 }
176
177private:
178 PFNC m_pOrignalFnc;
179 HMODULE m_hModule;
180 CSimpleAscii m_strDllName;
181 CSimpleAscii m_strFuncName;
182 CSimpleVectorT<HMODULE> m_modules;
183
185 LPVOID m_DosHead(IMAGE_DOS_HEADER* pDos, DWORD offset)
186 {
187 return reinterpret_cast<LPVOID>(reinterpret_cast<DWORD>(pDos) + offset);
188 }
189
191 PFNC m_Replace(HMODULE hModule, LPCSTR lpszDllName, LPCSTR lpszFuncName, PFNC pFnc)
192 {
193 IMAGE_DOS_HEADER* pDOS = reinterpret_cast<IMAGE_DOS_HEADER*>(hModule);
194 ASSERT( ! ::IsBadReadPtr(pDOS, sizeof(IMAGE_DOS_HEADER)) );
195 if ( pDOS->e_magic != IMAGE_DOS_SIGNATURE )
196 {
197 return NULL;
198 }
199 IMAGE_NT_HEADERS* pPE = static_cast<IMAGE_NT_HEADERS*>(m_DosHead(pDOS, pDOS->e_lfanew));
200 if ( pPE->Signature != IMAGE_NT_SIGNATURE )
201 {
202 return NULL;
203 }
204 IMAGE_DATA_DIRECTORY* pDataDir
205 = reinterpret_cast<IMAGE_DATA_DIRECTORY*>(pPE->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT);
206 if ( pDataDir->VirtualAddress == 0 || pDataDir->Size == 0 )
207 {
208 return NULL;
209 }
210 m_modules.Add(hModule);
211 PFNC pResultFnc = NULL;
212 //-- 下のDLLを検索
213 // import DLL table
214 IMAGE_IMPORT_DESCRIPTOR* pImpDsc = static_cast<IMAGE_IMPORT_DESCRIPTOR*>(m_DosHead(pDOS, pDataDir->VirtualAddress));
215 for ( ; pImpDsc->FirstThunk != NULL; pImpDsc++ )
216 {
217 LPCSTR lpszName = static_cast<LPCSTR>(m_DosHead(pDOS, pImpDsc->Name));
218 TTRACE1A("Found DLL = [%s]\n", lpszName);
219 HMODULE h = ::GetModuleHandleA(lpszName);
220 if ( h != NULL )
221 {
222 bool isFound = false;
223 loop ( i, m_modules.GetSize() )
224 {
225 if ( m_modules[i] == h )
226 {
227 isFound = true;
228 break;
229 }
230 }
231 if ( ! isFound )
232 {
233 PFNC PF = m_Replace(h, lpszDllName, lpszFuncName, pFnc);
234 if ( PF != NULL )
235 {
236 if ( pResultFnc != NULL && pResultFnc != PF )
237 {
238 ASSERTLIB( false );
239 }
240 pResultFnc = PF;
241 }
242 }
243 }
244 }
245 //
246 pImpDsc = static_cast<IMAGE_IMPORT_DESCRIPTOR*>(m_DosHead(pDOS, pDataDir->VirtualAddress));
247 for ( ; pImpDsc->FirstThunk != NULL; pImpDsc++ )
248 {
249 LPCSTR lpszName = static_cast<LPCSTR>(m_DosHead(pDOS, pImpDsc->Name));
250 TTRACE1A("Found DLL = [%s]\n", lpszName);
251 if ( lpszDllName != NULL && stricmp(lpszName, lpszDllName) != 0 )
252 {
253 continue;
254 }
255 //-- 対象のDLL発見
256 // address table
257 IMAGE_THUNK_DATA* pIAT = static_cast<IMAGE_THUNK_DATA*>(m_DosHead(pDOS, pImpDsc->FirstThunk));
258 // name table
259 IMAGE_THUNK_DATA* pINT = static_cast<IMAGE_THUNK_DATA*>(m_DosHead(pDOS, pImpDsc->OriginalFirstThunk));
260 for ( ; pIAT->u1.Function != NULL; pIAT++, pINT++ )
261 {
262 if ( IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal) )
263 {
264 continue;
265 }
266 IMAGE_IMPORT_BY_NAME* pImpName = static_cast<IMAGE_IMPORT_BY_NAME*>(m_DosHead(pDOS, pINT->u1.AddressOfData));
267 LPCSTR lpszName = reinterpret_cast<LPCSTR>(pImpName->Name);
268 TTRACE1A(" - Found Func = [%s]\n", lpszName);
269 if( strcmp(lpszName, lpszFuncName) == 0 )
270 {
271 //-- 対象の関数発見
272 DWORD oldProt;
273 ::VirtualProtect(&pIAT->u1.Function, sizeof(DWORD), PAGE_READWRITE, &oldProt);
274 PFNC PF = reinterpret_cast<PFNC>(pIAT->u1.Function);
275 ASSERTLIB( PF != NULL );
276 pIAT->u1.Function = reinterpret_cast<DWORD>(pFnc);
277 DWORD dummy;
278 ::VirtualProtect(&pIAT->u1.Function, sizeof(DWORD), oldProt, &dummy);
279 if ( pResultFnc != NULL && pResultFnc != PF )
280 {
281 ASSERTLIB( false );
282 }
283 pResultFnc = PF;
284 break;
285 }
286 }
287 if ( lpszDllName != NULL )
288 {
289 break;
290 }
291 }
292 return pResultFnc;
293 }
294};
295
296
297
298};//TNB
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
簡易配列型情報管理関係のヘッダ
ウィンドウズバージョン関係のヘッダ
APIフック管理
Definition: TnbApiHooker.h:80
bool Hook(LPCSTR lpszDllName, LPCSTR lpszFuncName, PFNC pFnc, HMODULE hModule=NULL)
[実行] 処理フック
Definition: TnbApiHooker.h:120
CApiHookerT(void)
コンストラクタ
Definition: TnbApiHooker.h:105
bool Unhook(void)
[実行] 処理アンフック
Definition: TnbApiHooker.h:149
static PFNC Replace(LPCSTR lpszDllName, LPCSTR lpszFuncName, PFNC pFnc, HMODULE hModule=NULL)
[実行] 処理変更
Definition: TnbApiHooker.h:93
PFNC operator()(void)
[取得] フック前の処理アドレス
Definition: TnbApiHooker.h:172
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
簡易文字列管理クラス.
Definition: TnbDef.h:869
void Empty(void)
[操作] 空化
Definition: TnbDef.h:932
void RemoveAll(void)
[削除] 空化
size_t GetSize(void) const
[取得] サイズ取得
INDEX Add(const TYP &t)
[追加] 要素一つ追加.
ウィンドウズバージョン情報
bool IsWow64(void) const
[確認] 64bitチェック
HINSTANCE GetInstanceHandleByTnb(EInstanceType type=EI_Process)
[取得] インスタンスハンドル取得.
Definition: TnbDef.h:1341
@ EI_Process
プロセス用
Definition: TnbDef.h:1259
TNB Library
Definition: TnbDoxyTitle.txt:2