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++プログラム設計に役立つことを願っています.