Hook导入表 —— 实现挂钩FreeLibaray和HOOK延迟加载模块的API
        
        Windows上Ring3的HOOK导入表所用的类大同小异,本文改进了一个HOOK导入表的类,实现了HOOK延迟加载模块的API和FreeLibaray的HOOK的实现。欢迎大家批评指正!
    
  最近在研究Windows Ring3上的API Hook,对HOOK导入表这种方法进行了研究。HOOK导入表所用的C++类大同小异,不同的就是如何实现HOOK一个延迟加载的模块中的函数,以及FreeLibaray某个函数之后再次LoadLibaray加载这个模块所导致的模块基地址不同的时候,这时该如何HOOK住这个模块中的API。
  显然地,挂钩LoadLibarayA/W、LoadLibarayExA/W、GetProcAddress这些函数还不够,还需要挂钩FreeLibrary函数。这里我参考了《Windows核心编程》(第五版)中的一个程序,封装了一个C++类,能够HOOK住FreeLibrary,同时也能解决延迟加载的问题。
  以下是这个类的声明:

 CApiHook类声明
CApiHook类声明#ifndef __API_HOOK_CLASS__
#define __API_HOOK_CLASS__
///////////////////////////////////////////////////////////////////////////////
class CApiHook
{
public:
CApiHook();
// 构造函数 —— 在所有模块中HOOK函数pszFuncName,将其替换为pfnHook
CApiHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook);
// 析构
~CApiHook();
// 返回原来的函数地址
operator PROC()
{
return m_pfnOrig; // 返回原函数地址
}
// 是否挂钩本模块中的函数
static BOOL ExcludeAPIHookMod;
public:
// GetProcAddressRaw调用实际的GetProcAddress函数
static FARPROC WINAPI GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName);
BOOL WINAPI HookApi(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook); // HOOK某个函数
void WINAPI UnHook(); // 撤销挂钩
protected:
void WINAPI Init();
void WINAPI Uninit();
private:
static PVOID sm_pvMaxAppAddr;
static PROC sm_pFunFreeLibrary; // FreeLibrary的实际地址
static CApiHook * sm_pHead; // 对象链表头节点
CApiHook * m_pNext; // 下一个对象节点
PCSTR m_pszCalleeModName; // 要HOOK函数所在的模块名称(ANSI)
PCSTR m_pszFuncName; // 要HOOK的函数的函数名(ANSI)
PROC m_pfnOrig; // 函数原地址
PROC m_pfnHook; // HOOK替换函数的地址
HMODULE m_hMod; // 模块句柄
private:
// 在一个模块的导入节区挂钩一个函数
static BOOL WINAPI ReplaceIATEntryInAllMods(PCSTR pszCalleeModName,
PROC pfnOrig, PROC pfnHook);
// 在所有模块的导入节区挂钩一个函数
static void WINAPI ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
PROC pfnOrig, PROC pfnHook, HMODULE hmodCaller);
// 在某个模块的导出节区挂钩一个函数
static void WINAPI ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName, PROC pfnNew);
private:
// 当一个DLL被新加载的时候使用该函数HOOK一个函数
static void WINAPI FixupNewlyLoadedModule(PCSTR pszModName, HMODULE hmod, DWORD dwFlags);
// 当一个DLL调用FreeLibaray等函数卸载某个模块时,调用此函数
static BOOL WINAPI FixupNewlyUnLoadModule(HMODULE hmod);
// 一些替换函数
static HMODULE WINAPI LoadLibraryA_Hook(PCSTR pszModulePath);
static HMODULE WINAPI LoadLibraryW_Hook(PCWSTR pszModulePath);
static HMODULE WINAPI LoadLibraryExA_Hook(PCSTR pszModulePath,
HANDLE hFile, DWORD dwFlags);
static HMODULE WINAPI LoadLibraryExW_Hook(PCWSTR pszModulePath,
HANDLE hFile, DWORD dwFlags);
static FARPROC WINAPI GetProcAddress_Hook(HMODULE hmod, PCSTR pszProcName);
static BOOL WINAPI FreeLibrary_Hook(HMODULE hLibModule);
private:
// 挂钩某些特殊函数的CApiHook对象
static CApiHook sm_LoadLibraryA; // 挂钩LoadLibryraA函数的CApiHook对象
static CApiHook sm_LoadLibraryW; // 挂钩LoadLibryraW函数的CApiHook对象
static CApiHook sm_LoadLibraryExA; // 挂钩LoadLibryraExA函数的CApiHook对象
static CApiHook sm_LoadLibraryExW; // 挂钩LoadLibryraExW函数的CApiHook对象
static CApiHook sm_GetProcAddress; // 挂钩GetProcAddress函数的CApiHook对象
static CApiHook sm_FreeLibrary; // 挂钩FreeLibrary函数的CApiHook对象
};
//////////////////////////////// End of File //////////////////////////////////
#endif // __API_HOOK_CLASS__
  想必其中某些函数不需要说了,需要说明的是FreeLibaray_Hook函数,这个函数是FreeLibaray的替换函数,通过sm_FreeLibrary对象进行HOOK。
  开始写这个函数的时候,遇到了困难,理由是这样的,因为如果这段代码作为DLL注入到目标进程中去,如果通过钩子的方法注入到目标进程中时,那么卸载钩子时,会引发目标进程调用FreeLibaray来释放这个DLL,此时会调用FreeLibaray_Hook函数,哪怕在这个函数的最后“return ::FreeLibaray(hLibModule)”,也会出现问题。因为这个函数会产生了C/C++运行时的框架代码,就会在返回之后调用一些框架代码,比如调用C++类的析构函数之类,而此时该模块已经从目标进程中卸载,这必然会导致内存访问违规。因此,必须如下定义该函数:
__declspec(naked) BOOL WINAPI CApiHook::FreeLibrary_Hook(HMODULE hLibModule)
这样,VC编译器就不会对CApiHook::FreeLibaray_Hook函数产生一些框架代码,就需要自己写内联汇编来维持堆栈的平衡。这里给出这个函数的定义:

 CApiHook::FreeLibrary_Hook
CApiHook::FreeLibrary_Hook__declspec(naked) BOOL WINAPI CApiHook::FreeLibrary_Hook(HMODULE hLibModule)
{
__asm
{
push ebp;
mov ebp, esp;
pushad;
push dword ptr[FreeLibrary_Hook];
call dword ptr[ModuleFromAddress];
cmp [ebp + 8], eax; ; [ebp + 8]中是参数模块句柄的值
jne NotMe;
mov eax, sm_pHead;
Next:
cmp eax, NULL;
je CallTrue;
mov edx, [eax].m_pNext;
push edx;
push eax; ; 这里相当于压入this指针
call UnHook; ; 相当于调用[eax].UnHook
pop eax;
jmp Next;
CallTrue:
popad;
pop ebp;
jmp dword ptr[sm_pFunFreeLibrary]; ; 如果是卸载本模块,则可能是其他程序调用,需要跳转到真正的FreeLibaray函数的地址
; 不是卸载的本模块
NotMe:
push [ebp + 8];
call FixupNewlyUnLoadModule; ; 不是本模块卸载,则调用修正的FreeLibrary函数
popad;
pop ebp;
mov eax, TRUE;
ret 4;
}
}
这里给出CApiHook类的完整定义:

 CApiHook类和一些辅助函数的定义
CApiHook类和一些辅助函数的定义 #include <windows.h>
#include <windows.h> #include <ImageHlp.h>
#include <ImageHlp.h> #pragma comment(lib, "ImageHlp")
#pragma comment(lib, "ImageHlp")
 #include "APIHook.h"
#include "APIHook.h" #include <tlhelp32.h>
#include <tlhelp32.h>

 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////

 // 从指定地址得到包含该地址的模块句柄
// 从指定地址得到包含该地址的模块句柄 static HMODULE WINAPI ModuleFromAddress(PVOID pv)
static HMODULE WINAPI ModuleFromAddress(PVOID pv)

 {
{ MEMORY_BASIC_INFORMATION mbi;
    MEMORY_BASIC_INFORMATION mbi; return((VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
    return((VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)  ? (HMODULE) mbi.AllocationBase : NULL);
        ? (HMODULE) mbi.AllocationBase : NULL); }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 异常过滤函数
// 异常过滤函数 LONG WINAPI InvalidReadExceptionFilter(PEXCEPTION_POINTERS pep)
LONG WINAPI InvalidReadExceptionFilter(PEXCEPTION_POINTERS pep)

 {
{ LONG lDisposition = EXCEPTION_EXECUTE_HANDLER;
    LONG lDisposition = EXCEPTION_EXECUTE_HANDLER; return lDisposition;
    return lDisposition; }
}

 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 CApiHook* CApiHook::sm_pHead = NULL;    // CApiHook对象链表头结点
CApiHook* CApiHook::sm_pHead = NULL;    // CApiHook对象链表头结点
 BOOL CApiHook::ExcludeAPIHookMod = TRUE;    // 是否排除HOOK本模块的函数
BOOL CApiHook::ExcludeAPIHookMod = TRUE;    // 是否排除HOOK本模块的函数
 PROC CApiHook::sm_pFunFreeLibrary = NULL;    // FreeLibrary的内存中的地址
PROC CApiHook::sm_pFunFreeLibrary = NULL;    // FreeLibrary的内存中的地址


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 构造函数
// 构造函数 CApiHook::CApiHook()
CApiHook::CApiHook()

 {
{ if (sm_pFunFreeLibrary == NULL)
    if (sm_pFunFreeLibrary == NULL)
 
     {
{ sm_pFunFreeLibrary = GetProcAddressRaw(GetModuleHandleW(L"Kernel32.dll"), "FreeLibrary");
        sm_pFunFreeLibrary = GetProcAddressRaw(GetModuleHandleW(L"Kernel32.dll"), "FreeLibrary"); }
    }
 // 前插一个结点
    // 前插一个结点 m_pNext  = sm_pHead;
    m_pNext  = sm_pHead; sm_pHead = this;
    sm_pHead = this; Init();        // 初始化
    Init();        // 初始化 }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 构造函数
// 构造函数 CApiHook::CApiHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook)
CApiHook::CApiHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook)

 {
{ if (sm_pFunFreeLibrary == NULL)
    if (sm_pFunFreeLibrary == NULL)
 
     {
{ sm_pFunFreeLibrary = GetProcAddressRaw(GetModuleHandleW(L"Kernel32.dll"), "FreeLibrary");
        sm_pFunFreeLibrary = GetProcAddressRaw(GetModuleHandleW(L"Kernel32.dll"), "FreeLibrary"); }
    } // 前插一个结点
    // 前插一个结点 m_pNext = sm_pHead;
    m_pNext = sm_pHead; sm_pHead = this;
    sm_pHead = this; HookApi(pszCalleeModName, pszFuncName, pfnHook);    // 挂钩某个API函数
    HookApi(pszCalleeModName, pszFuncName, pfnHook);    // 挂钩某个API函数 }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////

 CApiHook::~CApiHook()
CApiHook::~CApiHook()

 {
{ // 从链表中删除本节点
    // 从链表中删除本节点 CApiHook * p = sm_pHead;
    CApiHook * p = sm_pHead; if (p == this)
    if (p == this)
 
     {
{ sm_pHead = p->m_pNext;
        sm_pHead = p->m_pNext;  }
    } else
    else
 
     {
{ BOOL bFound = FALSE;
        BOOL bFound = FALSE;
 for (; p->m_pNext != NULL; p = p->m_pNext)
        for (; p->m_pNext != NULL; p = p->m_pNext)
 
         {
{ if (p->m_pNext == this)
            if (p->m_pNext == this)
 
             {
{  p->m_pNext = p->m_pNext->m_pNext;
                p->m_pNext = p->m_pNext->m_pNext;  break;
                break; }
            } }
        } }
    } UnHook();        // 撤销挂钩
    UnHook();        // 撤销挂钩 }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 void CApiHook::Init()
void CApiHook::Init()

 {
{ m_hMod = NULL;
    m_hMod = NULL; m_pszCalleeModName = NULL;
    m_pszCalleeModName = NULL; m_pszFuncName = NULL;
    m_pszFuncName = NULL; m_pfnOrig = NULL;
    m_pfnOrig = NULL; m_pfnHook = NULL;
    m_pfnHook = NULL; }
}

 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 void CApiHook::Uninit()
void CApiHook::Uninit()

 {
{ // 这里不把模块名、函数名和替换函数地址设置为NULL,防止重复加载
    // 这里不把模块名、函数名和替换函数地址设置为NULL,防止重复加载 m_hMod = NULL;
    m_hMod = NULL; m_pfnOrig = NULL;
    m_pfnOrig = NULL; }
}

 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 本函数不能为inline类型 —— 得到函数的实际地址
// 本函数不能为inline类型 —— 得到函数的实际地址 FARPROC WINAPI CApiHook::GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName)
FARPROC WINAPI CApiHook::GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName)

 {
{ return(::GetProcAddress(hmod, pszProcName));    // 得到函数的真实地址
    return(::GetProcAddress(hmod, pszProcName));    // 得到函数的真实地址 }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 在某个模块中HOOK某个API函数 —— 重要
// 在某个模块中HOOK某个API函数 —— 重要 BOOL WINAPI CApiHook::HookApi(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook)
BOOL WINAPI CApiHook::HookApi(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook)

 {
{ if (m_pszCalleeModName != NULL)
    if (m_pszCalleeModName != NULL) UnHook();
        UnHook();
 // 得到HOOK信息
    // 得到HOOK信息 m_hMod = GetModuleHandleA(pszCalleeModName);    // 得到模块句柄
    m_hMod = GetModuleHandleA(pszCalleeModName);    // 得到模块句柄 m_pszCalleeModName = pszCalleeModName;
    m_pszCalleeModName = pszCalleeModName; m_pszFuncName = pszFuncName;
    m_pszFuncName = pszFuncName; m_pfnHook = pfnHook;    // 替换函数地址
    m_pfnHook = pfnHook;    // 替换函数地址 if (m_hMod)
    if (m_hMod) m_pfnOrig = GetProcAddressRaw(m_hMod, m_pszFuncName);    // 原函数地址
        m_pfnOrig = GetProcAddressRaw(m_hMod, m_pszFuncName);    // 原函数地址
 // 如果原函数地址为NULL,可能是因为模块并没有加载(比如延迟加载DLL就会出现该问题)
    // 如果原函数地址为NULL,可能是因为模块并没有加载(比如延迟加载DLL就会出现该问题) if (m_pfnOrig == NULL)
    if (m_pfnOrig == NULL)
 
     {
{ #ifdef _DEBUG
#ifdef _DEBUG wchar_t szPathname[MAX_PATH];
        wchar_t szPathname[MAX_PATH]; GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
        GetModuleFileNameW(NULL, szPathname, _countof(szPathname)); wchar_t sz[1024];
        wchar_t sz[1024]; wsprintfW(sz, L"[%4u - %s] impossible to find %S\r\n",
        wsprintfW(sz, L"[%4u - %s] impossible to find %S\r\n",  GetCurrentProcessId(), szPathname, pszFuncName);
            GetCurrentProcessId(), szPathname, pszFuncName); OutputDebugString(sz);
        OutputDebugString(sz); #endif
#endif return FALSE;
        return FALSE; }
    }
 #ifdef _DEBUG
#ifdef _DEBUG // This section was used for debugging sessions when Explorer died as
    // This section was used for debugging sessions when Explorer died as  // a folder content was requested
    // a folder content was requested //
    //  //static BOOL s_bFirstTime = TRUE;
    //static BOOL s_bFirstTime = TRUE; //if (s_bFirstTime)
    //if (s_bFirstTime) //{
    //{ //   s_bFirstTime = FALSE;
    //   s_bFirstTime = FALSE;
 //   wchar_t szPathname[MAX_PATH];
    //   wchar_t szPathname[MAX_PATH]; //   GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
    //   GetModuleFileNameW(NULL, szPathname, _countof(szPathname)); //   wchar_t* pszExeFile = wcsrchr(szPathname, L'\\') + 1;
    //   wchar_t* pszExeFile = wcsrchr(szPathname, L'\\') + 1; //   OutputDebugStringW(L"Injected in ");
    //   OutputDebugStringW(L"Injected in "); //   OutputDebugStringW(pszExeFile);
    //   OutputDebugStringW(pszExeFile); //   if (_wcsicmp(pszExeFile, L"Explorer.EXE") == 0)
    //   if (_wcsicmp(pszExeFile, L"Explorer.EXE") == 0) //   {
    //   { //      DebugBreak();
    //      DebugBreak(); //   }
    //   } //   OutputDebugStringW(L"\n   --> ");
    //   OutputDebugStringW(L"\n   --> "); //   wsprintfW(szPathname, L"%S", pszFuncName);
    //   wsprintfW(szPathname, L"%S", pszFuncName); //   OutputDebugStringW(szPathname);
    //   OutputDebugStringW(szPathname); //   OutputDebugStringW(L"\n");
    //   OutputDebugStringW(L"\n"); //}
    //} #endif
#endif
 // HOOK某个函数
    // HOOK某个函数 ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook);
    ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook); return TRUE;
    return TRUE; }
}

 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 撤销挂钩
// 撤销挂钩 void WINAPI CApiHook::UnHook()
void WINAPI CApiHook::UnHook()

 {
{ if (m_pfnHook == NULL)
    if (m_pfnHook == NULL) return;
        return;
 // 撤销挂钩 —— 将函数地址复原
    // 撤销挂钩 —— 将函数地址复原 ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnHook, m_pfnOrig);
    ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnHook, m_pfnOrig);
 Uninit();
    Uninit(); }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 将本进程中所有模块的IAT中的指定函数地址pfnCurrent替换为pfnNew
// 将本进程中所有模块的IAT中的指定函数地址pfnCurrent替换为pfnNew BOOL CApiHook::ReplaceIATEntryInAllMods(PCSTR pszCalleeModName,
BOOL CApiHook::ReplaceIATEntryInAllMods(PCSTR pszCalleeModName,  PROC pfnCurrent, PROC pfnNew)
                                        PROC pfnCurrent, PROC pfnNew)

 {
{ if (pszCalleeModName == NULL || pfnCurrent == NULL || pfnNew == NULL)
    if (pszCalleeModName == NULL || pfnCurrent == NULL || pfnNew == NULL) return FALSE;
        return FALSE;
 // 得到当前模块(即包含这段代码的模块)
    // 得到当前模块(即包含这段代码的模块) HMODULE hmodThisMod = ExcludeAPIHookMod
    HMODULE hmodThisMod = ExcludeAPIHookMod  ? ModuleFromAddress(ReplaceIATEntryInAllMods) : NULL;
        ? ModuleFromAddress(ReplaceIATEntryInAllMods) : NULL;
 // 得到本进程中的模块列表
    // 得到本进程中的模块列表 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); if (hSnapshot == INVALID_HANDLE_VALUE)
    if (hSnapshot == INVALID_HANDLE_VALUE) return FALSE;
        return FALSE;


 MODULEENTRY32 me =
    MODULEENTRY32 me =  { sizeof(me) };
{ sizeof(me) };
 for (BOOL bOk = Module32First(hSnapshot, &me); bOk; bOk = Module32Next(hSnapshot, &me))
    for (BOOL bOk = Module32First(hSnapshot, &me); bOk; bOk = Module32Next(hSnapshot, &me))
 
     {
{ // 不替换当前模块的函数
        // 不替换当前模块的函数 if (me.hModule != hmodThisMod)
        if (me.hModule != hmodThisMod)
 
         {
{ ReplaceIATEntryInOneMod(pszCalleeModName, pfnCurrent, pfnNew, me.hModule);
            ReplaceIATEntryInOneMod(pszCalleeModName, pfnCurrent, pfnNew, me.hModule); }
        } }
    }
 CloseHandle(hSnapshot);
    CloseHandle(hSnapshot);
 return TRUE;
    return TRUE; }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////

 // 替换模块导入表中的函数地址
// 替换模块导入表中的函数地址 void WINAPI CApiHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
void WINAPI CApiHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,  PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller)
                                       PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller)

 {
{ ULONG ulSize;
    ULONG ulSize;
 // 一个异常可能被触发,因为诸如explorer.exe这样的进程能够快速地加载和卸载模块
    // 一个异常可能被触发,因为诸如explorer.exe这样的进程能够快速地加载和卸载模块 PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL; __try
    __try
 
     {
{ pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToDataEx(
        pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToDataEx( hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize, NULL);
            hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize, NULL); }
    }  __except (InvalidReadExceptionFilter(GetExceptionInformation()))
    __except (InvalidReadExceptionFilter(GetExceptionInformation()))
 
     {
{ 
         }
    }
 if (pImportDesc == NULL)
    if (pImportDesc == NULL) return;
        return;
 // 在导入描述符中查找导入信息
    // 在导入描述符中查找导入信息 for (; pImportDesc->Name; ++pImportDesc)
    for (; pImportDesc->Name; ++pImportDesc)
 
     {
{ // 得到模块名pszModName(模块基地址 + 名称偏移)
        // 得到模块名pszModName(模块基地址 + 名称偏移) PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
        PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
 // 判断模块名是否为指定模块
        // 判断模块名是否为指定模块 if (lstrcmpiA(pszModName, pszCalleeModName) == 0)
        if (lstrcmpiA(pszModName, pszCalleeModName) == 0)
 
         {
{ // 取得调用者导入函数地址表的在模块中的函数地址(模块基址 + 偏移)
            // 取得调用者导入函数地址表的在模块中的函数地址(模块基址 + 偏移) PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
            PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)  ((PBYTE)hmodCaller + pImportDesc->FirstThunk);
                ((PBYTE)hmodCaller + pImportDesc->FirstThunk);
 // 用新的函数地址替换当前函数地址
            // 用新的函数地址替换当前函数地址 for (; pThunk->u1.Function; pThunk++)
            for (; pThunk->u1.Function; pThunk++)
 
             {
{
 // 取得函数地址
                // 取得函数地址 PROC* ppfn = (PROC*) &pThunk->u1.Function;
                PROC* ppfn = (PROC*) &pThunk->u1.Function;
 // 是否是需要替换的函数(比较函数地址)
                // 是否是需要替换的函数(比较函数地址) BOOL bFound = (*ppfn == pfnCurrent);
                BOOL bFound = (*ppfn == pfnCurrent); if (bFound)
                if (bFound)
 
                 {
{ // 修改地址
                    // 修改地址 if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
                    if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,  sizeof (pfnNew), NULL) && (ERROR_NOACCESS == GetLastError()))
                        sizeof (pfnNew), NULL) && (ERROR_NOACCESS == GetLastError()))
 
                     {
{ // 如果失败,则更改页保护属性
                        // 如果失败,则更改页保护属性 DWORD dwOldProtect;
                        DWORD dwOldProtect; if (VirtualProtect(ppfn, sizeof (pfnNew), PAGE_WRITECOPY,
                        if (VirtualProtect(ppfn, sizeof (pfnNew), PAGE_WRITECOPY,  &dwOldProtect))
                            &dwOldProtect))
 
                         {
{
 WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
                            WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,  sizeof (pfnNew), NULL);
                                sizeof (pfnNew), NULL); VirtualProtect(ppfn, sizeof (pfnNew), dwOldProtect,
                            VirtualProtect(ppfn, sizeof (pfnNew), dwOldProtect,  &dwOldProtect);
                                &dwOldProtect); }
                        } }
                    } return;
                    return; }
                } }
            } }
        } }
    } }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 替换模块导出表中函数的地址
// 替换模块导出表中函数的地址 void WINAPI CApiHook::ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName, PROC pfnNew)
void WINAPI CApiHook::ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName, PROC pfnNew)

 {
{ // 得到模块导出节地址
    // 得到模块导出节地址 ULONG ulSize;
    ULONG ulSize;
 // 得到导出节目录地址
    // 得到导出节目录地址 PIMAGE_EXPORT_DIRECTORY pExportDir = NULL;
    PIMAGE_EXPORT_DIRECTORY pExportDir = NULL; __try
    __try
 
     {
{ pExportDir = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(
        pExportDir = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ulSize);
            hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ulSize); }
    }  __except (InvalidReadExceptionFilter(GetExceptionInformation()))
    __except (InvalidReadExceptionFilter(GetExceptionInformation()))
 
     {
{ 
         }
    }
 if (pExportDir == NULL)
    if (pExportDir == NULL) return;
        return;
 PDWORD pdwNamesRvas = (PDWORD) ((PBYTE) hmod + pExportDir->AddressOfNames);
    PDWORD pdwNamesRvas = (PDWORD) ((PBYTE) hmod + pExportDir->AddressOfNames); PWORD pdwNameOrdinals = (PWORD)
    PWORD pdwNameOrdinals = (PWORD)  ((PBYTE) hmod + pExportDir->AddressOfNameOrdinals);
        ((PBYTE) hmod + pExportDir->AddressOfNameOrdinals); PDWORD pdwFunctionAddresses = (PDWORD)
    PDWORD pdwFunctionAddresses = (PDWORD)  ((PBYTE) hmod + pExportDir->AddressOfFunctions);
        ((PBYTE) hmod + pExportDir->AddressOfFunctions);
 // 遍历模块函数名表
    // 遍历模块函数名表 for (DWORD n = 0; n < pExportDir->NumberOfNames; n++)
    for (DWORD n = 0; n < pExportDir->NumberOfNames; n++)
 
     {
{ // 取得函数名
        // 取得函数名 PSTR pszFuncName = (PSTR) ((PBYTE) hmod + pdwNamesRvas[n]);
        PSTR pszFuncName = (PSTR) ((PBYTE) hmod + pdwNamesRvas[n]);
 // 如果不是指定的函数,则继续遍历
        // 如果不是指定的函数,则继续遍历 if (lstrcmpiA(pszFuncName, pszFunctionName) != 0)
        if (lstrcmpiA(pszFuncName, pszFunctionName) != 0) continue;
            continue;
 // 得到这个指定函数的序号
        // 得到这个指定函数的序号 WORD ordinal = pdwNameOrdinals[n];
        WORD ordinal = pdwNameOrdinals[n];
 // 得到函数地址
        // 得到函数地址 PROC * ppfn = (PROC*) &pdwFunctionAddresses[ordinal];
        PROC * ppfn = (PROC*) &pdwFunctionAddresses[ordinal];
 // 用RVA(相对虚拟地址)更换成新的地址
        // 用RVA(相对虚拟地址)更换成新的地址 pfnNew = (PROC) ((PBYTE) pfnNew - (PBYTE) hmod);
        pfnNew = (PROC) ((PBYTE) pfnNew - (PBYTE) hmod);
 // 用新的函数地址替换当前函数地址
        // 用新的函数地址替换当前函数地址 if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof (pfnNew), NULL)
        if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof (pfnNew), NULL)  && (ERROR_NOACCESS == GetLastError()))
            && (ERROR_NOACCESS == GetLastError()))
 
         {
{ DWORD dwOldProtect;
            DWORD dwOldProtect; if (VirtualProtect(ppfn, sizeof (pfnNew), PAGE_WRITECOPY,
            if (VirtualProtect(ppfn, sizeof (pfnNew), PAGE_WRITECOPY,  &dwOldProtect))
                &dwOldProtect))
 
             {
{
 WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
                WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,  sizeof (pfnNew), NULL);
                    sizeof (pfnNew), NULL); VirtualProtect(ppfn, sizeof (pfnNew), dwOldProtect, &dwOldProtect);
                VirtualProtect(ppfn, sizeof (pfnNew), dwOldProtect, &dwOldProtect); }
            } }
        } break;
        break; }
    } }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 替换LoadLibaray*函数和GetProcAddress函数
// 替换LoadLibaray*函数和GetProcAddress函数
 CApiHook CApiHook::sm_LoadLibraryA  ("Kernel32.dll", "LoadLibraryA",
CApiHook CApiHook::sm_LoadLibraryA  ("Kernel32.dll", "LoadLibraryA",    (PROC) CApiHook::LoadLibraryA_Hook);
                                     (PROC) CApiHook::LoadLibraryA_Hook);
 CApiHook CApiHook::sm_LoadLibraryW  ("Kernel32.dll", "LoadLibraryW",
CApiHook CApiHook::sm_LoadLibraryW  ("Kernel32.dll", "LoadLibraryW",    (PROC) CApiHook::LoadLibraryW_Hook);
                                     (PROC) CApiHook::LoadLibraryW_Hook);
 CApiHook CApiHook::sm_LoadLibraryExA("Kernel32.dll", "LoadLibraryExA",
CApiHook CApiHook::sm_LoadLibraryExA("Kernel32.dll", "LoadLibraryExA",  (PROC) CApiHook::LoadLibraryExA_Hook);
                                     (PROC) CApiHook::LoadLibraryExA_Hook);
 CApiHook CApiHook::sm_LoadLibraryExW("Kernel32.dll", "LoadLibraryExW",
CApiHook CApiHook::sm_LoadLibraryExW("Kernel32.dll", "LoadLibraryExW",  (PROC) CApiHook::LoadLibraryExW_Hook);
                                     (PROC) CApiHook::LoadLibraryExW_Hook);
 CApiHook CApiHook::sm_GetProcAddress("Kernel32.dll", "GetProcAddress",
CApiHook CApiHook::sm_GetProcAddress("Kernel32.dll", "GetProcAddress",  (PROC) CApiHook::GetProcAddress_Hook);
                                     (PROC) CApiHook::GetProcAddress_Hook);
 CApiHook CApiHook::sm_FreeLibrary("Kernel32.dll", "FreeLibrary",
CApiHook CApiHook::sm_FreeLibrary("Kernel32.dll", "FreeLibrary",  (PROC) CApiHook::FreeLibrary_Hook);
                                     (PROC) CApiHook::FreeLibrary_Hook);


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 防止运行时加载模块(如线程调用LoadLibarayW等函数)
// 防止运行时加载模块(如线程调用LoadLibarayW等函数) void CApiHook::FixupNewlyLoadedModule(PCSTR pszModPath, HMODULE hmod, DWORD dwFlags)
void CApiHook::FixupNewlyLoadedModule(PCSTR pszModPath, HMODULE hmod, DWORD dwFlags)

 {
{ // 如果一个新的模块被加载,重新挂钩函数
    // 如果一个新的模块被加载,重新挂钩函数 if ((hmod != NULL) &&
    if ((hmod != NULL) && (hmod != ModuleFromAddress(FixupNewlyLoadedModule)) &&
        (hmod != ModuleFromAddress(FixupNewlyLoadedModule)) &&  ((dwFlags & LOAD_LIBRARY_AS_DATAFILE) == 0) &&
        ((dwFlags & LOAD_LIBRARY_AS_DATAFILE) == 0) && ((dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) == 0) &&
        ((dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) == 0) && ((dwFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) == 0)
        ((dwFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) == 0) )
        )
 
     {
{ // 遍历CApiHook对象链,挂钩个对象要求的API函数
        // 遍历CApiHook对象链,挂钩个对象要求的API函数 for (CApiHook* p = sm_pHead; p != NULL; p = p->m_pNext)
        for (CApiHook* p = sm_pHead; p != NULL; p = p->m_pNext)
 
         {
{ // 如果某个对象的原函数地址为NULL,可能是延迟加载等原因导致原来DLL不在内存中而引起的
            // 如果某个对象的原函数地址为NULL,可能是延迟加载等原因导致原来DLL不在内存中而引起的 // 因此在这里根据模块名获得函数现在的地址
            // 因此在这里根据模块名获得函数现在的地址 if (p->m_pfnOrig == NULL)
            if (p->m_pfnOrig == NULL)
 
             {
{ if (lstrcmpiA(p->m_pszCalleeModName, pszModPath) == 0)
                if (lstrcmpiA(p->m_pszCalleeModName, pszModPath) == 0)
 
                 {
{ p->m_hMod = hmod;
                    p->m_hMod = hmod; p->m_pfnOrig = p->GetProcAddressRaw(hmod, p->m_pszFuncName);
                    p->m_pfnOrig = p->GetProcAddressRaw(hmod, p->m_pszFuncName); }
                } }
            } if (p->m_pfnOrig != NULL)
            if (p->m_pfnOrig != NULL)
 
             {
{ // 重新挂钩每个函数
                // 重新挂钩每个函数 ReplaceIATEntryInAllMods(p->m_pszCalleeModName, p->m_pfnOrig, p->m_pfnHook);
                ReplaceIATEntryInAllMods(p->m_pszCalleeModName, p->m_pfnOrig, p->m_pfnHook); }
            } else
            else
 
             {
{ #ifdef _DEBUG
#ifdef _DEBUG // 可能是延迟加载导致p->m_pfnOrig为空
                // 可能是延迟加载导致p->m_pfnOrig为空 wchar_t szPathname[MAX_PATH];
                wchar_t szPathname[MAX_PATH]; GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
                GetModuleFileNameW(NULL, szPathname, _countof(szPathname)); wchar_t sz[1024];
                wchar_t sz[1024]; wsprintfW(sz, L"[%4u - %s] impossible to find %S\r\n",
                wsprintfW(sz, L"[%4u - %s] impossible to find %S\r\n",  GetCurrentProcessId(), szPathname, p->m_pszCalleeModName);
                    GetCurrentProcessId(), szPathname, p->m_pszCalleeModName); OutputDebugString(sz);
                OutputDebugString(sz); #endif
#endif }
            } }
        } }
    } }
}

 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 防止运行时卸载模块(如线程调用FreeLibrary等函数)
// 防止运行时卸载模块(如线程调用FreeLibrary等函数) BOOL WINAPI CApiHook::FixupNewlyUnLoadModule(HMODULE hmod)
BOOL WINAPI CApiHook::FixupNewlyUnLoadModule(HMODULE hmod)

 {
{ if (hmod == NULL || hmod == ModuleFromAddress(FixupNewlyUnLoadModule))
    if (hmod == NULL || hmod == ModuleFromAddress(FixupNewlyUnLoadModule)) return FALSE;
        return FALSE;
 BOOL bFree = TRUE;
    BOOL bFree = TRUE; wchar_t szModPath[MAX_PATH];
    wchar_t szModPath[MAX_PATH]; szModPath[0] = L'\0';
    szModPath[0] = L'\0';
 if (!GetModuleFileNameW(hmod, szModPath, MAX_PATH))
    if (!GetModuleFileNameW(hmod, szModPath, MAX_PATH)) return FALSE;
        return FALSE;
 if (!::FreeLibrary(hmod))
    if (!::FreeLibrary(hmod)) return FALSE;
        return FALSE;
 bFree = TRUE;
    bFree = TRUE; 
     if (GetModuleFileNameW(hmod, szModPath, MAX_PATH))
    if (GetModuleFileNameW(hmod, szModPath, MAX_PATH))
 
     {
{ // 如果还能够得到地址,则说明该模块在进程地址空间中并没有真正卸载
        // 如果还能够得到地址,则说明该模块在进程地址空间中并没有真正卸载 if (GetModuleHandleW(szModPath))
        if (GetModuleHandleW(szModPath)) bFree = FALSE;
            bFree = FALSE; }
    }
 // 如果卸载了,则撤销某些挂钩
    // 如果卸载了,则撤销某些挂钩 if (bFree)
    if (bFree)
 
     {
{ for (CApiHook * p = sm_pHead; p; p = p->m_pNext)
        for (CApiHook * p = sm_pHead; p; p = p->m_pNext)
 
         {
{ if (p->m_pfnOrig && p->m_hMod == hmod)
            if (p->m_pfnOrig && p->m_hMod == hmod) p->UnHook();
                p->UnHook(); }
        } }
    } return TRUE;
    return TRUE; }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 挂钩LoadLibarayA的替换函数
// 挂钩LoadLibarayA的替换函数 HMODULE WINAPI CApiHook::LoadLibraryA_Hook(PCSTR pszModulePath)
HMODULE WINAPI CApiHook::LoadLibraryA_Hook(PCSTR pszModulePath)

 {
{ HMODULE hmod = ::LoadLibraryA(pszModulePath);
    HMODULE hmod = ::LoadLibraryA(pszModulePath); FixupNewlyLoadedModule(pszModulePath, hmod, 0);
    FixupNewlyLoadedModule(pszModulePath, hmod, 0); return hmod;
    return hmod; }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 挂钩LoadLibraryW的替换函数
// 挂钩LoadLibraryW的替换函数 HMODULE WINAPI CApiHook::LoadLibraryW_Hook(PCWSTR pszModulePath)
HMODULE WINAPI CApiHook::LoadLibraryW_Hook(PCWSTR pszModulePath)

 {
{ HMODULE hmod = ::LoadLibraryW(pszModulePath);
    HMODULE hmod = ::LoadLibraryW(pszModulePath); char szModPath[MAX_PATH];
    char szModPath[MAX_PATH]; WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pszModulePath, -1,
    WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pszModulePath, -1, szModPath, MAX_PATH * sizeof (char), NULL, NULL);
                szModPath, MAX_PATH * sizeof (char), NULL, NULL); FixupNewlyLoadedModule(szModPath, hmod, 0);
    FixupNewlyLoadedModule(szModPath, hmod, 0); return hmod;
    return hmod; }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 挂钩LoadLibraryExA的替换函数
// 挂钩LoadLibraryExA的替换函数 HMODULE WINAPI CApiHook::LoadLibraryExA_Hook(PCSTR pszModulePath,
HMODULE WINAPI CApiHook::LoadLibraryExA_Hook(PCSTR pszModulePath,  HANDLE hFile, DWORD dwFlags)
                                        HANDLE hFile, DWORD dwFlags)

 {
{ HMODULE hmod = ::LoadLibraryExA(pszModulePath, hFile, dwFlags);
    HMODULE hmod = ::LoadLibraryExA(pszModulePath, hFile, dwFlags); FixupNewlyLoadedModule(pszModulePath, hmod, dwFlags);
    FixupNewlyLoadedModule(pszModulePath, hmod, dwFlags); return hmod;
    return hmod; }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 挂钩LoadLibraryExW的替换函数
// 挂钩LoadLibraryExW的替换函数 HMODULE WINAPI CApiHook::LoadLibraryExW_Hook(PCWSTR pszModulePath,
HMODULE WINAPI CApiHook::LoadLibraryExW_Hook(PCWSTR pszModulePath,  HANDLE hFile, DWORD dwFlags)
                                        HANDLE hFile, DWORD dwFlags)

 {
{
 HMODULE hmod = ::LoadLibraryExW(pszModulePath, hFile, dwFlags);
    HMODULE hmod = ::LoadLibraryExW(pszModulePath, hFile, dwFlags); char szModPath[MAX_PATH];
    char szModPath[MAX_PATH]; WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pszModulePath, -1,
    WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pszModulePath, -1, szModPath, MAX_PATH * sizeof (char), NULL, NULL);
                szModPath, MAX_PATH * sizeof (char), NULL, NULL); FixupNewlyLoadedModule(szModPath, hmod, dwFlags);
    FixupNewlyLoadedModule(szModPath, hmod, dwFlags); return hmod;
    return hmod; }
}


 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 挂钩GetProcAddress的替换函数
// 挂钩GetProcAddress的替换函数 FARPROC WINAPI CApiHook::GetProcAddress_Hook(HMODULE hmod, PCSTR pszProcName)
FARPROC WINAPI CApiHook::GetProcAddress_Hook(HMODULE hmod, PCSTR pszProcName)

 {
{ // 取得函数的实际地址
    // 取得函数的实际地址 FARPROC pfn = GetProcAddressRaw(hmod, pszProcName);
    FARPROC pfn = GetProcAddressRaw(hmod, pszProcName);
 CApiHook * p = sm_pHead;
    CApiHook * p = sm_pHead; for (; (pfn != NULL) && (p != NULL); p = p->m_pNext)
    for (; (pfn != NULL) && (p != NULL); p = p->m_pNext)
 
     {
{ // 查看是否是想挂钩的函数,如果是,则返回新的替换函数
        // 查看是否是想挂钩的函数,如果是,则返回新的替换函数 if (pfn == p->m_pfnOrig)
        if (pfn == p->m_pfnOrig)
 
         {
{ // 返回我们的替换函数地址
            // 返回我们的替换函数地址 pfn = p->m_pfnHook;
            pfn = p->m_pfnHook; break;
            break; }
        } }
    } return pfn;    // 返回替换函数地址
    return pfn;    // 返回替换函数地址 }
}

 /**////////////////////////////////////////////////////////////////////////////////
/**////////////////////////////////////////////////////////////////////////////////
 // 拦截FreeLibrary的替换函数
// 拦截FreeLibrary的替换函数 // 注意函数采用内联汇编进行编写,需要使用__declspec(naked)标记函数,让编译器不产生框架代码,自己维护堆栈平衡
// 注意函数采用内联汇编进行编写,需要使用__declspec(naked)标记函数,让编译器不产生框架代码,自己维护堆栈平衡 __declspec(naked) BOOL WINAPI CApiHook::FreeLibrary_Hook(HMODULE hLibModule)
__declspec(naked) BOOL WINAPI CApiHook::FreeLibrary_Hook(HMODULE hLibModule)

 {
{ __asm
    __asm
 
     {
{ push ebp;
        push ebp; mov ebp, esp;
        mov ebp, esp; pushad;
        pushad; push dword ptr[FreeLibrary_Hook];
        push dword ptr[FreeLibrary_Hook]; call dword ptr[ModuleFromAddress];
        call dword ptr[ModuleFromAddress]; cmp [ebp + 8], eax;
        cmp [ebp + 8], eax; jne NotMe;
        jne NotMe; mov eax, sm_pHead;
        mov eax, sm_pHead; Next:
Next: cmp eax, NULL;
        cmp eax, NULL; je    CallTrue;
        je    CallTrue; mov edx, [eax].m_pNext;
        mov edx, [eax].m_pNext; push edx;
        push edx; push eax;        ; 这里相当于压入this指针
        push eax;        ; 这里相当于压入this指针 call UnHook;    ; 相当于调用[eax].UnHook
        call UnHook;    ; 相当于调用[eax].UnHook pop eax;
        pop eax; jmp    Next;
        jmp    Next; CallTrue:
CallTrue: popad;
        popad; pop ebp;
        pop ebp; jmp dword ptr[sm_pFunFreeLibrary];    ; 如果是卸载本模块,则可能是其他程序调用,需要跳转到真正的FreeLibaray函数的地址
        jmp dword ptr[sm_pFunFreeLibrary];    ; 如果是卸载本模块,则可能是其他程序调用,需要跳转到真正的FreeLibaray函数的地址
 ; 不是卸载的本模块
        ; 不是卸载的本模块 NotMe:
NotMe: push [ebp + 8];
        push [ebp + 8]; call FixupNewlyUnLoadModule;    ; 不是本模块卸载,则调用修正的FreeLibrary函数
        call FixupNewlyUnLoadModule;    ; 不是本模块卸载,则调用修正的FreeLibrary函数
 popad;
        popad; pop ebp;
        pop ebp; mov eax, TRUE;
        mov eax, TRUE; ret 4;
        ret 4; }
    } }
}


 /**///////////////////////////////// End of File //////////////////////////////////
/**///////////////////////////////// End of File //////////////////////////////////
如上就可以实现挂钩FreeLibaray函数的功能了。
同时,这里在HOOK所有LoadLibaray*函数的时候,调用了FixupNewlyLoadedModule函数,该函数会遍历所有CApiHook对象,查看是否存在某个对象的API原地址为NULL,如果是,就检测模块名是否一致,这样就可以通过模块得到这个API原始地址了,这样就可以解决延迟加载的问题。 
                    
                     
                    
                 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号 
