看流星社区

 找回密码
 注册账号
查看: 2252|回复: 0

封装IATHOOK类

[复制链接]

该用户从未签到

发表于 2017-6-2 13:24:11 | 显示全部楼层 |阅读模式
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:oadLibraryA, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryW("kernel32.dll", "LoadLibraryW", (PROC)CAPIHOOK:oadLibraryW, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryExA("kernel32.dll", "LoadLibraryExA", (PROC)CAPIHOOK:oadLibraryExA, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryExW("kernel32.dll", "LoadLibraryExW", (PROC)CAPIHOOK:oadLibraryExW, 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 &amp;&amp; (dwFlags&amp;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, &amp;mbi, sizeof(MEMORY_BASIC_INFORMATION));
                                ::VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &amp;dwOldProtect);
                                ::WriteProcessMemory(GetCurrentProcess(), lpAddr, &amp;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, &amp;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, &amp;me32 ) )
        {
                return;
        }
        do
        { //对每一个模块
                if (me32.hModule != hModThis)
                {
                        ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNewFunc, me32.hModule);
                }
        } while( Module32Next( hModuleSnap, &amp;me32 ) );


        ::CloseHandle(hModuleSnap); //配对写

}

//防止自动加载
HMODULE WINAPI CAPIHOOK:oadLibraryA(LPCTSTR lpFileName)
{
        HMODULE hModule = LoadLibraryA(lpFileName);
        HookNewlyLoadedModule(hModule, 0); //这个函数中忆检测hModule 了
        return hModule;
}
HMODULE WINAPI CAPIHOOK:oadLibraryW(LPCTSTR lpFileName)
{
        HMODULE hModule = LoadLibraryW(lpFileName);
        HookNewlyLoadedModule(hModule, 0); //这个函数中忆检测hModule 了
        return hModule;
}
HMODULE WINAPI CAPIHOOK:oadLibraryExA(LPCTSTR lpFileName, HANDLE hFile,  DWORD dwFlags)
{
        HMODULE hModule = LoadLibraryExA(lpFileName, hFile, dwFlags);
        HookNewlyLoadedModule(hModule, dwFlags); //这个函数中忆检测hModule 了
        return hModule;
}
HMODULE WINAPI CAPIHOOK:oadLibraryExW(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;
};
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-19 17:11

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表