这里只把我的视线作为一个例子来说明一下, 读者用自己的方法去实现也没问题.
1. DLL 入口函数的相关逻辑
在DLL加载的时候HOOK所有我们希望追踪的系统API.
在DLL卸载的时候取消所有的HOOK.
- #include "hooksTable.h"
- BOOL APIENTRY DllMain( HMODULE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved
- )
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- {
- // 挂钩系统API.
- ReplaceIATEntryInCurrentModules();
- } break;
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- break;
- case DLL_PROCESS_DETACH:
- {
- // 还原系统API.
- ReplaceIATEntryInCurrentModules(true);
- } break;
- }
- return TRUE;
- }
2. HOOK的API列表管理.
2.1. 对外接口 hooksTable.h
GetHookData ==>> 访问被HOOK系统API的相关数据
ReplaceIATEntryInMoudule ==>> 在指定模块中 HOOK 系统 API
ReplaceIATEntryInCurrentModules ==>> 在所有模块中 HOOK 系统 API
- #pragma once
- #include <string>
- #include "windows.h"
- ///////////////////////////////////////////////////////////////////
- ///////////// Data Structure Define Begin./////////////////
- struct HookData{
- std::string nameDLL;
- std::string nameAPI;
- FARPROC originalAPI;
- HookData(){}
- HookData(std::string dll,std::string API);
- };
- // As a key. Reference to 'HookData'.
- typedef void * NewEntryFunc;
- //////////// Data Structure Define End.////////////////////
- ///////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////
- /////////// Interfaces Define Begin.///////////////////////
- HookData * GetHookData(NewEntryFunc pHookFunc);
- void ReplaceIATEntryInMoudule(HMODULE hMoudule);
- void ReplaceIATEntryInCurrentModules(bool bIsRestoreBack = false);
- ////////////// Interfaces Define End.//////////////////////
- ///////////////////////////////////////////////////////////////////
2.2. 内部实现
hooksTable.cppHOOK 表格数据的初始化会在全局变量 g_mapHooksTable 的初始化中完成.
- #include "hooksTable.h"
- #include "ApiHooks.h"
- #include <map>
- #include <string>
- #include <cstdio>
- #include "Tlhelp32.h"
- #include "imagehlp.h"
- #pragma comment(lib, "ImageHlp")
- ///////////////////////////////////////////////////////////////////
- ///////////// Data Structure Implementation Begin./////////////////
- HookData::HookData(std::string dll,std::string API) : nameDLL(dll),nameAPI(API),originalAPI(NULL)
- {
- HMODULE hModule = GetModuleHandleA(nameDLL.c_str());
- if ( ! hModule ) hModule = LoadLibraryA(nameDLL.c_str());
- if ( hModule ) originalAPI = GetProcAddress(hModule,nameAPI.c_str());
- else
- {
- _ASSERTE( ! "LoadLibraryA failed !" );
- }
- }
- struct MapHooks : public std::map<NewEntryFunc,HookData>
- {
- MapHooks()
- {
- insert( std::make_pair( MyLoadLibraryW ,HookData( "Kernel32.dll","LoadLibraryW" ) ) );
- insert( std::make_pair( MyLoadLibraryA ,HookData( "Kernel32.dll","LoadLibraryA" ) ) );
- insert( std::make_pair( MyLoadLibraryExA ,HookData( "Kernel32.dll","LoadLibraryExA" ) ) );
- insert( std::make_pair( MyLoadLibraryExW ,HookData( "Kernel32.dll","LoadLibraryExW" ) ) );
- insert( std::make_pair( MyFreeLibrary ,HookData( "Kernel32.dll","FreeLibrary" ) ) );
- insert( std::make_pair( MyFreeLibraryAndExitThread ,HookData( "Kernel32.dll","FreeLibraryAndExitThread" ) ) );
-
- // TODO. Add the APIs we want to hook here. Take 'ExitProcess' for example.
- insert( std::make_pair( MyExitProcess ,HookData( "Kernel32.dll","ExitProcess" ) ) );
- }
- } g_mapHooksTable;
- //////////// Data Structure Implementation End.////////////////////
- ///////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////
- /////////// Interfaces Implementation Begin.///////////////////////
- HookData * GetHookData(NewEntryFunc pHookFunc)
- {
- MapHooks::iterator it = g_mapHooksTable.find(pHookFunc);
- if ( it != g_mapHooksTable.end() )
- return &(it->second);
- return NULL;
- }
- void ReplaceIATEntryInOneMod(const char * pszCalleeModName, FARPROC pfnCurrent, FARPROC pfnNew, HMODULE hMoudule)
- {
- // Step 1. Get the base address.
- PVOID addressBase = (PVOID)hMoudule;
- // Step 2. Get the address of the module's import section
- PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
- __try {
- ULONG ulSize;
- pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
- addressBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
- } __except (EXCEPTION_EXECUTE_HANDLER) { }
- if (pImportDesc == NULL)
- return; // This module has no import section or is no longer loaded
- // Find the import descriptor containing references to callee's functions
- for (; pImportDesc->Name; pImportDesc++)
- {
- PSTR pszModName = (PSTR) ((PBYTE) addressBase + pImportDesc->Name);
- if (lstrcmpiA(pszModName, pszCalleeModName) != 0) continue ;
- // Get caller's import address table (IAT) for the callee's functions
- PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
- ((PBYTE) addressBase + pImportDesc->FirstThunk);
- FARPROC* ppfn = NULL;
- // Get the address of the function address
- for (; pThunk->u1.Function; pThunk++)
- {
- FARPROC* ppfnTmp = (FARPROC*)&pThunk->u1.Function;
- if ( *ppfnTmp == pfnCurrent )
- ppfn = ppfnTmp;
- }
- if (ppfn == NULL) continue ;
- // Replace current function address with new function address
- if ( !WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
- sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError()) )
- {
- DWORD dwOldProtect;
- if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, &dwOldProtect))
- {
- WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
- sizeof(pfnNew), NULL);
- VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect,
- &dwOldProtect);
- }
- }
- return; // We did it, get out
- }
- }
- void ReplaceIATEntryInMoudule(HMODULE hMoudule)
- {
- MapHooks::iterator it = g_mapHooksTable.begin();
- for ( ; it != g_mapHooksTable.end(); ++it )
- {
- FARPROC funcHook = (FARPROC)it->first;
- const char* nameDll = it->second.nameDLL.c_str();
- FARPROC funcOrig = it->second.originalAPI;
- ReplaceIATEntryInOneMod(nameDll,funcHook,funcOrig,hMoudule);
- }
- }
- void ReplaceIATEntryInCurrentModules(bool bIsRestoreBack)
- {
- MEMORY_BASIC_INFORMATION mbi;
- HMODULE hmodThisMod = ((VirtualQuery(ReplaceIATEntryInCurrentModules, &mbi, sizeof(mbi)) != 0)
- ? (HMODULE) mbi.AllocationBase : NULL);
- HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
- MODULEENTRY32 me = { sizeof(me) };
- Module32First(hSnapshot,&me);
- do {
- // NOTE: We don't hook functions in our own module
- if (me.hModule != hmodThisMod) {
- MapHooks::iterator it = g_mapHooksTable.begin();
- for ( ; it != g_mapHooksTable.end(); ++it )
- {
- FARPROC funcHook = (FARPROC)it->first;
- const char* nameDll = it->second.nameDLL.c_str();
- FARPROC funcOrig = GetProcAddress(GetModuleHandleA(nameDll),it->second.nameAPI.c_str());
- if ( bIsRestoreBack )
- ReplaceIATEntryInOneMod(nameDll,funcHook,funcOrig,me.hModule);
- else
- ReplaceIATEntryInOneMod(nameDll,funcOrig,funcHook,me.hModule);
- }
- }
- }while (Module32Next(hSnapshot,&me));
- }
- ////////////// Interfaces Implementation End.//////////////////////
- ///////////////////////////////////////////////////////////////////
3. 具体要HOOK的系统API的实现代码
除了加载模块和卸载模块的部分, 其他部分没什么特别的意思.
3.1. 头文件明细 ApiHooks.h
- #pragma once
- HMODULE WINAPI MyLoadLibraryW(LPCWSTR lpLibFileName);
- HMODULE WINAPI MyLoadLibraryA(LPCSTR lpLibFileName);
- HMODULE WINAPI MyLoadLibraryExA(LPCSTR lpLibFileName,HANDLE hFile,DWORD dwFlags);
- HMODULE WINAPI MyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile,DWORD dwFlags);
- BOOL WINAPI MyFreeLibrary(HMODULE hLibModule);
- VOID WINAPI MyFreeLibraryAndExitThread (HMODULE hLibModule,DWORD dwExitCode);
- VOID WINAPI MyExitProcess( UINT uExitCode );
3.2. 具体实现
ApiHooks.cpp- #include "stdafx.h"
- #include "hooksTable.h"
- HMODULE WINAPI MyLoadLibraryW(LPCWSTR lpLibFileName)
- {
- //MessageBoxA(NULL,"MyLoadLibraryW","MyLoadLibraryW",0);
- HookData * pHookData = GetHookData(MyLoadLibraryW);
- if ( ! pHookData )
- {
- _ASSERTE( ! "the MyLoadLibraryW has no original API on table g_mapHooksTable!" );
- return NULL;
- }
- // Step 1. Load the module into memory.
- typedef HMODULE (WINAPI *PtrMyApiFunction)(LPCWSTR);
- PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);
- HMODULE hModule = funOrig(lpLibFileName);
- // Step 2. Hook the APIs on this moudle.
- ReplaceIATEntryInCurrentModules();
- return hModule;
- }
- HMODULE WINAPI MyLoadLibraryA(LPCSTR lpLibFileName)
- {
- //MessageBoxA(NULL,"MyLoadLibraryA","MyLoadLibraryA",0);
- HookData * pHookData = GetHookData(MyLoadLibraryA);
- if ( ! pHookData )
- {
- _ASSERTE( ! "the MyLoadLibraryA has no original API on table g_mapHooksTable!" );
- return NULL;
- }
- // Step 1. Load the module into memory.
- typedef HMODULE (WINAPI *PtrMyApiFunction)(LPCSTR);
- PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);
- HMODULE hModule = funOrig(lpLibFileName);
- // Step 2. Hook the APIs on this moudle.
- ReplaceIATEntryInCurrentModules();
- return hModule;
- }
- HMODULE WINAPI MyLoadLibraryExA
- (LPCSTR lpLibFileName,HANDLE hFile,DWORD dwFlags)
- {
- //MessageBoxA(NULL,"","",0);
- HookData * pHookData = GetHookData(MyLoadLibraryExA);
- if ( ! pHookData )
- {
- _ASSERTE( ! "the MyLoadLibraryExA has no original API on table g_mapHooksTable!" );
- return NULL;
- }
- // Step 1. Load the module into memory.
- typedef HMODULE (WINAPI *PtrMyApiFunction)(LPCSTR, HANDLE,DWORD);
- PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);
- HMODULE hModule = funOrig(lpLibFileName,hFile,dwFlags);
- // Step 2. Hook the APIs on this moudle.
- ReplaceIATEntryInCurrentModules();
- return hModule;
- }
- HMODULE WINAPI MyLoadLibraryExW
- (LPCWSTR lpLibFileName, HANDLE hFile,DWORD dwFlags)
- {
- // MessageBoxA(NULL,"","",0);
- HookData * pHookData = GetHookData(MyLoadLibraryExW);
- if ( ! pHookData )
- {
- _ASSERTE( ! "the MyLoadLibraryExW has no original API on table g_mapHooksTable!" );
- return NULL;
- }
- // Step 1. Load the module into memory.
- typedef HMODULE (WINAPI *PtrMyApiFunction)(LPCWSTR, HANDLE,DWORD);
- PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);
- HMODULE hModule = funOrig(lpLibFileName,hFile,dwFlags);
- // Step 2. Hook the APIs on this moudle.
- ReplaceIATEntryInCurrentModules();
- return hModule;
- }
- BOOL WINAPI MyFreeLibrary(HMODULE hLibModule)
- {
- // MessageBoxA(NULL,"MyFreeLibrary","MyFreeLibrary",0);
- // Step 1. Restore the APIs on the current moudle.
- ReplaceIATEntryInMoudule(hLibModule);
- // Step 2. Unload the module out of memory.
- HookData * pHookData = GetHookData(MyFreeLibrary);
- if ( ! pHookData )
- {
- _ASSERTE( ! "the MyFreeLibrary has no original API on table g_mapHooksTable!" );
- return FALSE;
- }
- typedef BOOL (WINAPI *PtrMyApiFunction)(HMODULE);
- PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);
- return funOrig(hLibModule);
- }
- VOID WINAPI MyFreeLibraryAndExitThread (HMODULE hLibModule,DWORD dwExitCode)
- {
- //MessageBoxA(NULL,"MyFreeLibraryAndExitThread","MyFreeLibraryAndExitThread",0);
- // Step 1. Restore the APIs on the current moudle.
- ReplaceIATEntryInMoudule(hLibModule);
- // Step 2. Unload the module out of memory.
- HookData * pHookData = GetHookData(MyFreeLibraryAndExitThread);
- if ( ! pHookData )
- {
- _ASSERTE( ! "the MyFreeLibrary has no original API on table g_mapHooksTable!" );
- return ;
- }
- typedef BOOL (WINAPI *PtrMyApiFunction)(HMODULE,DWORD);
- PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);
- funOrig(hLibModule,dwExitCode);
- }
- VOID WINAPI MyExitProcess( __in UINT uExitCode )
- {
- MessageBoxA(NULL,"MyExitProcess","MyExitProcess",0);
- HookData * pHookData = GetHookData(MyExitProcess);
- if ( ! pHookData )
- {
- _ASSERTE( ! "the MyExitProcess has no original API on table g_mapHooksTable!" );
- return ;
- }
- typedef VOID (WINAPI *PtrMyApiFunction)(UINT);
- PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);
- funOrig(uExitCode);
- }
阅读(2004) | 评论(0) | 转发(1) |