C++パッケージIATHOOKクラスインスタンス

13003 ワード

本明細書では、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  
 
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
", 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  
 
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++プログラム設計に役立つことを願っています.