C++封装IATHOOK类实例


本文向大家介绍C++封装IATHOOK类实例,包括了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++程序设计有所帮助。