C++封装IATHOOK类实例
本文实例讲述了C++封装IATHOOK类的实现方法。分享给大家供大家参考。具体方法如下:
1. 定义成类的静态成员,从而实现自动调用
static CAPIHOOK sm_LoadLibraryA; static CAPIHOOK sm_LoadLibraryW; static CAPIHOOK sm_LoadLibraryExA; static CAPIHOOK sm_LoadLibraryExW; static CAPIHOOK sm_GetProcAddress;
2. ReplaceIATEntryInAllMods中遍历模块的框架
void CAPIHOOK::ReplaceIATEntryInAllMods(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, BOOL bExcludeAPIHookMod) { //取得当前模块句柄 HMODULE hModThis = NULL; if (bExcludeAPIHookMod) { MEMORY_BASIC_INFORMATION mbi; if (0 != ::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) //ReplaceIATEntryInAllMods必须为类的static函数 { hModThis = (HMODULE)mbi.AllocationBase; } } //取得本进程的模块列表 HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32; hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); if (INVALID_HANDLE_VALUE == hModuleSnap) { return; } me32.dwSize = sizeof( MODULEENTRY32 ); if( !Module32First( hModuleSnap, &me32 ) ) { return; } do { //对每一个模块 if (me32.hModule != hModThis) { ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNewFunc, me32.hModule); } } while( Module32Next( hModuleSnap, &me32 ) ); ::CloseHandle(hModuleSnap); //配对写 }
3. 遍历链表摘除自己的框架
CAPIHOOK::~CAPIHOOK(void) { //取消对函数的HOOK ReplaceIATEntryInAllMods(m_pszModName, m_pfnHook, m_pfnOrig, TRUE); //把自己从链表中删除 CAPIHOOK* p = sm_pHeader; if (p == this) { sm_pHeader = this->m_pNext; } else { while(p != NULL) { if (p->m_pNext == this) { p->m_pNext = this->m_pNext; break; } p = p->m_pNext; } } }
4. 在cpp中静态变量写好后,再编译,不然容易出现LINK错误
CAPIHOOK *CAPIHOOK::sm_pHeader = NULL;
源码:
.cpp源文件如下:
#include "APIHOOK.h" #include <Tlhelp32.h> CAPIHOOK *CAPIHOOK::sm_pHeader = NULL; CAPIHOOK CAPIHOOK::sm_LoadLibraryA("kernel32.dll", "LoadLibraryA", (PROC)CAPIHOOK::LoadLibraryA, TRUE); CAPIHOOK CAPIHOOK::sm_LoadLibraryW("kernel32.dll", "LoadLibraryW", (PROC)CAPIHOOK::LoadLibraryW, TRUE); CAPIHOOK CAPIHOOK::sm_LoadLibraryExA("kernel32.dll", "LoadLibraryExA", (PROC)CAPIHOOK::LoadLibraryExA, TRUE); CAPIHOOK CAPIHOOK::sm_LoadLibraryExW("kernel32.dll", "LoadLibraryExW", (PROC)CAPIHOOK::LoadLibraryExW, TRUE); CAPIHOOK CAPIHOOK::sm_GetProcAddress("kernel32.dll", "GetProcAddress", (PROC)CAPIHOOK::GetProcess, TRUE); CAPIHOOK::CAPIHOOK(LPTSTR lpszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod) { //初始化变量 m_pszModName = lpszModName; m_pszFuncName = pszFuncName; m_pfnOrig = ::GetProcAddress(::GetModuleHandleA(lpszModName), pszFuncName); m_pfnHook = pfnHook; //将此对象加入链表中 m_pNext = sm_pHeader; sm_pHeader = this; //在当前已加载的模块中HOOK这个函数 ReplaceIATEntryInAllMods(lpszModName, m_pfnOrig, m_pfnHook, bExcludeAPIHookMod); } CAPIHOOK::~CAPIHOOK(void) { //取消对函数的HOOK ReplaceIATEntryInAllMods(m_pszModName, m_pfnHook, m_pfnOrig, TRUE); //把自己从链表中删除 CAPIHOOK* p = sm_pHeader; if (p == this) { sm_pHeader = this->m_pNext; } else { while(p != NULL) { if (p->m_pNext == this) { p->m_pNext = this->m_pNext; break; } p = p->m_pNext; } } } //防止程序运行期间动态加载模块 void CAPIHOOK::HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags) { if (hModule!=NULL && (dwFlags&LOAD_LIBRARY_AS_DATAFILE)==0) { CAPIHOOK* p = sm_pHeader; //循环遍历链表,对每个CAPIHOOK进入HOOK if (p != NULL) { ReplaceIATEntryInOneMod(p->m_pszModName, p->m_pfnOrig, p->m_pfnHook, hModule); p = p->m_pNext; } } }//防止程序运行期间动态调用API函数 FARPROC WINAPI CAPIHOOK::GetProcess(HMODULE hModule, PCSTR pszProcName) { //得到函数的真实地址 FARPROC pfn = ::GetProcAddress(hModule, pszProcName); //遍历列表 看是不是要HOOK的函数 CAPIHOOK* p = sm_pHeader; while(p != NULL) { if (p->m_pfnOrig == pfn) //是要HOOK的函数 { pfn = p->m_pfnHook; //HOOK掉 break; } p = p->m_pNext; } return pfn; } void CAPIHOOK::ReplaceIATEntryInOneMod(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, HMODULE hModCaller) { IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hModCaller; IMAGE_OPTIONAL_HEADER* pOpNtHeader = (IMAGE_OPTIONAL_HEADER*)((BYTE*)hModCaller + pDosHeader->e_lfanew + 24); //这里加24 IMAGE_IMPORT_DESCRIPTOR* pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hModCaller + pOpNtHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); BOOL bFindDll = FALSE; while (pImportDesc->FirstThunk) { char* pszDllName = (char*)((BYTE*)hModCaller + pImportDesc->Name); if (stricmp(pszDllName, pszExportMod) == 0)//如果找到pszExportMod模块,相当于hook messageboxa时的“user32.dll” { bFindDll = TRUE; break; } pImportDesc++; } if (bFindDll) { DWORD n = 0; //一个IMAGE_THUNK_DATA就是一个导入函数 IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hModCaller + pImportDesc->OriginalFirstThunk); while (pThunk->u1.Function) { //取得函数名称 char* pszFuncName = (char*)((BYTE*)hModCaller+pThunk->u1.AddressOfData+2); //函数名前面有两个.. //printf("function name:%-25s, ", pszFuncName); //取得函数地址 PDWORD lpAddr = (DWORD*)((BYTE*)hModCaller + pImportDesc->FirstThunk) + n; //从第一个函数的地址,以后每次+4字节 //printf("addrss:%X\n", lpAddr); //在这里是比较的函数地址 if (*lpAddr == (DWORD)pfnCurrent) //找到iat中的函数地址 { DWORD* lpNewProc = (DWORD*)pfnNewFunc; MEMORY_BASIC_INFORMATION mbi; DWORD dwOldProtect; //修改内存页的保护属性 ::VirtualQuery(lpAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); ::VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect); ::WriteProcessMemory(GetCurrentProcess(), lpAddr, &lpNewProc, sizeof(DWORD), NULL); ::VirtualProtect(lpAddr, sizeof(DWORD), dwOldProtect, NULL); return; } n++; //每次增加一个DWORD } } } void CAPIHOOK::ReplaceIATEntryInAllMods(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, BOOL bExcludeAPIHookMod) { //取得当前模块句柄 HMODULE hModThis = NULL; if (bExcludeAPIHookMod) { MEMORY_BASIC_INFORMATION mbi; if (0 != ::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) //ReplaceIATEntryInAllMods必须为类的static函数 { hModThis = (HMODULE)mbi.AllocationBase; } } //取得本进程的模块列表 HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32; hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); if (INVALID_HANDLE_VALUE == hModuleSnap) { return; } me32.dwSize = sizeof( MODULEENTRY32 ); if( !Module32First( hModuleSnap, &me32 ) ) { return; } do { //对每一个模块 if (me32.hModule != hModThis) { ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNewFunc, me32.hModule); } } while( Module32Next( hModuleSnap, &me32 ) ); ::CloseHandle(hModuleSnap); //配对写 } //防止自动加载 HMODULE WINAPI CAPIHOOK::LoadLibraryA(LPCTSTR lpFileName) { HMODULE hModule = LoadLibraryA(lpFileName); HookNewlyLoadedModule(hModule, 0); //这个函数中忆检测hModule 了 return hModule; } HMODULE WINAPI CAPIHOOK::LoadLibraryW(LPCTSTR lpFileName) { HMODULE hModule = LoadLibraryW(lpFileName); HookNewlyLoadedModule(hModule, 0); //这个函数中忆检测hModule 了 return hModule; } HMODULE WINAPI CAPIHOOK::LoadLibraryExA(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags) { HMODULE hModule = LoadLibraryExA(lpFileName, hFile, dwFlags); HookNewlyLoadedModule(hModule, dwFlags); //这个函数中忆检测hModule 了 return hModule; } HMODULE WINAPI CAPIHOOK::LoadLibraryExW(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags) { HMODULE hModule = LoadLibraryExW(lpFileName, hFile, dwFlags); HookNewlyLoadedModule(hModule, dwFlags); //这个函数中忆检测hModule 了 return hModule; }
.h头文件如下:
#pragma once #include <Windows.h> class CAPIHOOK { public: CAPIHOOK(LPTSTR lpszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod = TRUE); ~CAPIHOOK(void); private: static void ReplaceIATEntryInOneMod(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, HMODULE hModCaller); static void ReplaceIATEntryInAllMods(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, BOOL bExcludeAPIHookMod); //防止程序运行期间动态加载模块, 当一个新DLL被加载时调用 static void HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags); //跟踪当前进程加载新的DLL static HMODULE WINAPI LoadLibraryA(LPCTSTR lpFileName); static HMODULE WINAPI LoadLibraryW(LPCTSTR lpFileName); static HMODULE WINAPI LoadLibraryExA(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags); static HMODULE WINAPI LoadLibraryExW(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags); //防止程序运行期间动态调用API函数 对于请求已HOOK的API函数,返回用户自定义的函数地址 static FARPROC WINAPI GetProcess(HMODULE hModule, PCSTR pszProcName); private: //定义成静态的,会自动调用,从而实现自动HOOK static CAPIHOOK sm_LoadLibraryA; static CAPIHOOK sm_LoadLibraryW; static CAPIHOOK sm_LoadLibraryExA; static CAPIHOOK sm_LoadLibraryExW; static CAPIHOOK sm_GetProcAddress; private: static CAPIHOOK* sm_pHeader; //钩子链表 CAPIHOOK* m_pNext; //要钩子的函数 PROC m_pfnOrig; PROC m_pfnHook; //要钩子的函数所在的dll LPSTR m_pszModName; //要钩子的函数名称 LPSTR m_pszFuncName; };
希望本文所述对大家的C++程序设计有所帮助。