C++封裝IATHOOK類實(shí)例
本文實(shí)例講述了C++封裝IATHOOK類的實(shí)現(xiàn)方法。分享給大家供大家參考。具體方法如下:
1. 定義成類的靜態(tài)成員,從而實(shí)現(xiàn)自動(dòng)調(diào)用
static CAPIHOOK sm_LoadLibraryW;
static CAPIHOOK sm_LoadLibraryExA;
static CAPIHOOK sm_LoadLibraryExW;
static CAPIHOOK sm_GetProcAddress;
2. ReplaceIATEntryInAllMods中遍歷模塊的框架
{
//取得當(dāng)前模塊句柄
HMODULE hModThis = NULL;
if (bExcludeAPIHookMod)
{
MEMORY_BASIC_INFORMATION mbi;
if (0 != ::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) //ReplaceIATEntryInAllMods必須為類的static函數(shù)
{
hModThis = (HMODULE)mbi.AllocationBase;
}
}
//取得本進(jìn)程的模塊列表
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
{ //對每一個(gè)模塊
if (me32.hModule != hModThis)
{
ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNewFunc, me32.hModule);
}
} while( Module32Next( hModuleSnap, &me32 ) );
::CloseHandle(hModuleSnap); //配對寫
}
3. 遍歷鏈表摘除自己的框架
{
//取消對函數(shù)的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中靜態(tài)變量寫好后,再編譯,不然容易出現(xiàn)LINK錯(cuò)誤
源碼:
.cpp源文件如下:
#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;
//在當(dāng)前已加載的模塊中HOOK這個(gè)函數(shù)
ReplaceIATEntryInAllMods(lpszModName, m_pfnOrig, m_pfnHook, bExcludeAPIHookMod);
}
CAPIHOOK::~CAPIHOOK(void)
{
//取消對函數(shù)的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;
}
}
}
//防止程序運(yùn)行期間動(dòng)態(tài)加載模塊
void CAPIHOOK::HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags)
{
if (hModule!=NULL && (dwFlags&LOAD_LIBRARY_AS_DATAFILE)==0)
{
CAPIHOOK* p = sm_pHeader; //循環(huán)遍歷鏈表,對每個(gè)CAPIHOOK進(jìn)入HOOK
if (p != NULL)
{
ReplaceIATEntryInOneMod(p->m_pszModName, p->m_pfnOrig, p->m_pfnHook, hModule);
p = p->m_pNext;
}
}
}
//防止程序運(yùn)行期間動(dòng)態(tài)調(diào)用API函數(shù)
FARPROC WINAPI CAPIHOOK::GetProcess(HMODULE hModule, PCSTR pszProcName)
{
//得到函數(shù)的真實(shí)地址
FARPROC pfn = ::GetProcAddress(hModule, pszProcName);
//遍歷列表 看是不是要HOOK的函數(shù)
CAPIHOOK* p = sm_pHeader;
while(p != NULL)
{
if (p->m_pfnOrig == pfn) //是要HOOK的函數(shù)
{
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模塊,相當(dāng)于hook messageboxa時(shí)的“user32.dll”
{
bFindDll = TRUE;
break;
}
pImportDesc++;
}
if (bFindDll)
{
DWORD n = 0;
//一個(gè)IMAGE_THUNK_DATA就是一個(gè)導(dǎo)入函數(shù)
IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hModCaller + pImportDesc->OriginalFirstThunk);
while (pThunk->u1.Function)
{
//取得函數(shù)名稱
char* pszFuncName = (char*)((BYTE*)hModCaller+pThunk->u1.AddressOfData+2); //函數(shù)名前面有兩個(gè)..
//printf("function name:%-25s, ", pszFuncName);
//取得函數(shù)地址
PDWORD lpAddr = (DWORD*)((BYTE*)hModCaller + pImportDesc->FirstThunk) + n; //從第一個(gè)函數(shù)的地址,以后每次+4字節(jié)
//printf("addrss:%X\n", lpAddr);
//在這里是比較的函數(shù)地址
if (*lpAddr == (DWORD)pfnCurrent) //找到iat中的函數(shù)地址
{
DWORD* lpNewProc = (DWORD*)pfnNewFunc;
MEMORY_BASIC_INFORMATION mbi;
DWORD dwOldProtect;
//修改內(nèi)存頁的保護(hù)屬性
::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++; //每次增加一個(gè)DWORD
}
}
}
void CAPIHOOK::ReplaceIATEntryInAllMods(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, BOOL bExcludeAPIHookMod)
{
//取得當(dāng)前模塊句柄
HMODULE hModThis = NULL;
if (bExcludeAPIHookMod)
{
MEMORY_BASIC_INFORMATION mbi;
if (0 != ::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) //ReplaceIATEntryInAllMods必須為類的static函數(shù)
{
hModThis = (HMODULE)mbi.AllocationBase;
}
}
//取得本進(jìn)程的模塊列表
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
{ //對每一個(gè)模塊
if (me32.hModule != hModThis)
{
ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNewFunc, me32.hModule);
}
} while( Module32Next( hModuleSnap, &me32 ) );
::CloseHandle(hModuleSnap); //配對寫
}
//防止自動(dòng)加載
HMODULE WINAPI CAPIHOOK::LoadLibraryA(LPCTSTR lpFileName)
{
HMODULE hModule = LoadLibraryA(lpFileName);
HookNewlyLoadedModule(hModule, 0); //這個(gè)函數(shù)中憶檢測hModule 了
return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryW(LPCTSTR lpFileName)
{
HMODULE hModule = LoadLibraryW(lpFileName);
HookNewlyLoadedModule(hModule, 0); //這個(gè)函數(shù)中憶檢測hModule 了
return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryExA(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{
HMODULE hModule = LoadLibraryExA(lpFileName, hFile, dwFlags);
HookNewlyLoadedModule(hModule, dwFlags); //這個(gè)函數(shù)中憶檢測hModule 了
return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryExW(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{
HMODULE hModule = LoadLibraryExW(lpFileName, hFile, dwFlags);
HookNewlyLoadedModule(hModule, dwFlags); //這個(gè)函數(shù)中憶檢測hModule 了
return hModule;
}
.h頭文件如下:
#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);
//防止程序運(yùn)行期間動(dòng)態(tài)加載模塊, 當(dāng)一個(gè)新DLL被加載時(shí)調(diào)用
static void HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags);
//跟蹤當(dāng)前進(jìn)程加載新的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);
//防止程序運(yùn)行期間動(dòng)態(tài)調(diào)用API函數(shù) 對于請求已HOOK的API函數(shù),返回用戶自定義的函數(shù)地址
static FARPROC WINAPI GetProcess(HMODULE hModule, PCSTR pszProcName);
private: //定義成靜態(tài)的,會(huì)自動(dòng)調(diào)用,從而實(shí)現(xiàn)自動(dòng)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;
//要鉤子的函數(shù)
PROC m_pfnOrig;
PROC m_pfnHook;
//要鉤子的函數(shù)所在的dll
LPSTR m_pszModName;
//要鉤子的函數(shù)名稱
LPSTR m_pszFuncName;
};
希望本文所述對大家的C++程序設(shè)計(jì)有所幫助。
上一篇:C++廣播通信實(shí)例
欄 目:C語言
下一篇:C++進(jìn)程共享數(shù)據(jù)封裝成類實(shí)例
本文標(biāo)題:C++封裝IATHOOK類實(shí)例
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3239.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲方式詳解
- 01-10深入理解C/C++混合編程


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法