一个模块的导入段包含一组DLL,导入段还包含一个符号表,其中列出了该模块从各DLL中导入的符号,
当该模块调用一个导入函数的时候,线程实际上会先从模块的导入表中得到相应的导入函数的地址,然后再跳转到那个地址。
模块的导入段中所有的字符串都是以ANSI格式保存的,有的编译器会生成多个导入段。
//hook dll
/******************************************************************************
Module: APIHook.h
Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre
******************************************************************************/
#pragma once
///
class CAPIHook {
public:
// Hook a function in all modules
CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook);
// Unhook a function from all modules
~CAPIHook();
// Returns the original address of the hooked function
operator PROC() { return(m_pfnOrig); }
// Hook module w/CAPIHook implementation?
// I have to make it static because I need to use it
// in ReplaceIATEntryInAllMods
static BOOL ExcludeAPIHookMod;
public:
// Calls the real GetProcAddress
static FARPROC WINAPI GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName);
private:
static PVOID sm_pvMaxAppAddr; // Maximum private memory address
static CAPIHook* sm_pHead; // Address of first object
CAPIHook* m_pNext; // Address of next object
PCSTR m_pszCalleeModName; // Module containing the function (ANSI)
PCSTR m_pszFuncName; // Function name in callee (ANSI)
PROC m_pfnOrig; // Original function address in callee
PROC m_pfnHook; // Hook function address
private:
// Replaces a symbol's address in a module's import section
static void WINAPI ReplaceIATEntryInAllMods(PCSTR pszCalleeModName,
PROC pfnOrig, PROC pfnHook);
// Replaces a symbol's address in all modules' import sections
static void WINAPI ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
PROC pfnOrig, PROC pfnHook, HMODULE hmodCaller);
// Replaces a symbol's address in a module's export sections
static void ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName, PROC pfnNew);
private:
// Used when a DLL is newly loaded after hooking a function
static void WINAPI FixupNewlyLoadedModule(HMODULE hmod, DWORD dwFlags);
// Used to trap when DLLs are newly loaded
static HMODULE WINAPI LoadLibraryA(PCSTR pszModulePath);
static HMODULE WINAPI LoadLibraryW(PCWSTR pszModulePath);
static HMODULE WINAPI LoadLibraryExA(PCSTR pszModulePath,
HANDLE hFile, DWORD dwFlags);
static HMODULE WINAPI LoadLibraryExW(PCWSTR pszModulePath,
HANDLE hFile, DWORD dwFlags);
// Returns address of replacement function if hooked function is requested
static FARPROC WINAPI GetProcAddress(HMODULE hmod, PCSTR pszProcName);
private:
// Instantiates hooks on these functions
static CAPIHook sm_LoadLibraryA;
static CAPIHook sm_LoadLibraryW;
static CAPIHook sm_LoadLibraryExA;
static CAPIHook sm_LoadLibraryExW;
static CAPIHook sm_GetProcAddress;
};
End of File //
/******************************************************************************
Module: APIHook.cpp
Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre
******************************************************************************/
#include <Windows.h>
#include <CommCtrl.h>
#include <process.h>
#include <ImageHlp.h>
#pragma comment(lib, "ImageHlp")
#include "APIHook.h"
#include <tlhelp32.h>
#include <tchar.h>
#include <StrSafe.h>
/
// The head of the linked-list of CAPIHook objects
CAPIHook* CAPIHook::sm_pHead = NULL;
// By default, the module containing the CAPIHook() is not hooked
BOOL CAPIHook::ExcludeAPIHookMod = TRUE;
///
CAPIHook::CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook) {
// Note: the function can be hooked only if the exporting module
// is already loaded. A solution could be to store the function
// name as a member; then, in the hooked LoadLibrary* handlers, parse
// the list of CAPIHook instances, check if pszCalleeModName
// is the name of the loaded module to hook its export table and
// re-hook the import tables of all loaded modules.
m_pNext = sm_pHead; // The next node was at the head
sm_pHead = this; // This node is now at the head
// Save information about this hooked function
m_pszCalleeModName = pszCalleeModName;
m_pszFuncName = pszFuncName;
m_pfnHook = pfnHook;
m_pfnOrig =
GetProcAddressRaw(GetModuleHandleA(pszCalleeModName), m_pszFuncName);
// If function does not exit,... bye bye
// This happens when the module is not already loaded
if (m_pfnOrig == NULL)
{
wchar_t szPathname[MAX_PATH];
GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
wchar_t sz[1024];
StringCchPrintfW(sz, _countof(sz),
TEXT("[%4u - %s] impossible to find %S\r\n"),
GetCurrentProcessId(), szPathname, pszFuncName);
OutputDebugString(sz);
return;
}
#ifdef _DEBUG
// This section was used for debugging sessions when Explorer died as
// a folder content was requested
//
//static BOOL s_bFirstTime = TRUE;
//if (s_bFirstTime)
//{
// s_bFirstTime = FALSE;
// wchar_t szPathname[MAX_PATH];
// GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
// wchar_t* pszExeFile