Chinaunix首页 | 论坛 | 博客
  • 博客访问: 348769
  • 博文数量: 88
  • 博客积分: 1695
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-06 15:48
个人简介

喜欢美食, 旅行..

文章分类

全部博文(88)

文章存档

2014年(2)

2013年(12)

2012年(14)

2010年(8)

2009年(52)

我的朋友

分类: WINDOWS

2012-12-16 23:17:05

这里只把我的视线作为一个例子来说明一下, 读者用自己的方法去实现也没问题.
关于如何把自己的DLL导入到指定的进程,请参考我的另一篇博文[windows平台] 给进程注入代码 -- 导入DLL到指定进程的地址空间
1. DLL 入口函数的相关逻辑
在DLL加载的时候HOOK所有我们希望追踪的系统API.
在DLL卸载的时候取消所有的HOOK.
  1. #include "hooksTable.h"
  2. BOOL APIENTRY DllMain( HMODULE hModule,
  3.                        DWORD ul_reason_for_call,
  4.                        LPVOID lpReserved
  5.                      )
  6. {
  7.     switch (ul_reason_for_call)
  8.     {
  9.     case DLL_PROCESS_ATTACH:
  10.         {
  11.             // 挂钩系统API.
  12.             ReplaceIATEntryInCurrentModules();
  13.         } break;
  14.     case DLL_THREAD_ATTACH:
  15.     case DLL_THREAD_DETACH:
  16.         break;
  17.     case DLL_PROCESS_DETACH:
  18.         {
  19.             // 还原系统API.
  20.             ReplaceIATEntryInCurrentModules(true);
  21.         } break;
  22.     }
  23.     return TRUE;
  24. }
2. HOOK的API列表管理. 
2.1. 对外接口 hooksTable.h
GetHookData ==>> 访问被HOOK系统API的相关数据
ReplaceIATEntryInMoudule ==>> 在指定模块中 HOOK 系统 API
ReplaceIATEntryInCurrentModules ==>> 在所有模块中 HOOK 系统 API
  1. #pragma once

  2. #include <string>
  3. #include "windows.h"

  4. ///////////////////////////////////////////////////////////////////
  5. ///////////// Data Structure Define Begin./////////////////

  6. struct HookData{
  7.     std::string nameDLL;
  8.     std::string nameAPI;
  9.     FARPROC originalAPI;
  10.     HookData(){}
  11.     HookData(std::string dll,std::string API);
  12. };

  13. // As a key. Reference to 'HookData'.
  14. typedef void * NewEntryFunc;

  15. //////////// Data Structure Define End.////////////////////
  16. ///////////////////////////////////////////////////////////////////

  17. ///////////////////////////////////////////////////////////////////
  18. /////////// Interfaces Define Begin.///////////////////////

  19. HookData * GetHookData(NewEntryFunc pHookFunc);
  20. void ReplaceIATEntryInMoudule(HMODULE hMoudule);
  21. void ReplaceIATEntryInCurrentModules(bool bIsRestoreBack = false);

  22. ////////////// Interfaces Define End.//////////////////////
  23. ///////////////////////////////////////////////////////////////////
2.2. 内部实现 hooksTable.cpp
HOOK 表格数据的初始化会在全局变量 g_mapHooksTable 的初始化中完成.
  1. #include "hooksTable.h"
  2. #include "ApiHooks.h"

  3. #include <map>
  4. #include <string>
  5. #include <cstdio>

  6. #include "Tlhelp32.h"
  7. #include "imagehlp.h"
  8. #pragma comment(lib, "ImageHlp")

  9. ///////////////////////////////////////////////////////////////////
  10. ///////////// Data Structure Implementation Begin./////////////////

  11. HookData::HookData(std::string dll,std::string API) : nameDLL(dll),nameAPI(API),originalAPI(NULL)
  12. {
  13.  HMODULE hModule = GetModuleHandleA(nameDLL.c_str());
  14.  if ( ! hModule ) hModule = LoadLibraryA(nameDLL.c_str());
  15.  if ( hModule ) originalAPI = GetProcAddress(hModule,nameAPI.c_str());
  16.  else
  17.  {
  18.      _ASSERTE( ! "LoadLibraryA failed !" );
  19.  }
  20. }

  21. struct MapHooks : public std::map<NewEntryFunc,HookData>
  22. {
  23.     MapHooks()
  24.     {
  25.         insert( std::make_pair( MyLoadLibraryW ,HookData( "Kernel32.dll","LoadLibraryW" ) ) );
  26.         insert( std::make_pair( MyLoadLibraryA ,HookData( "Kernel32.dll","LoadLibraryA" ) ) );
  27.         insert( std::make_pair( MyLoadLibraryExA ,HookData( "Kernel32.dll","LoadLibraryExA" ) ) );
  28.         insert( std::make_pair( MyLoadLibraryExW ,HookData( "Kernel32.dll","LoadLibraryExW" ) ) );
  29.         insert( std::make_pair( MyFreeLibrary ,HookData( "Kernel32.dll","FreeLibrary" ) ) );
  30.         insert( std::make_pair( MyFreeLibraryAndExitThread ,HookData( "Kernel32.dll","FreeLibraryAndExitThread" ) ) );
  31.         
  32.         // TODO. Add the APIs we want to hook here. Take 'ExitProcess' for example.
  33.         insert( std::make_pair( MyExitProcess ,HookData( "Kernel32.dll","ExitProcess" ) ) );
  34.     }

  35. } g_mapHooksTable;

  36. //////////// Data Structure Implementation End.////////////////////
  37. ///////////////////////////////////////////////////////////////////

  38. ///////////////////////////////////////////////////////////////////
  39. /////////// Interfaces Implementation Begin.///////////////////////

  40. HookData * GetHookData(NewEntryFunc pHookFunc)
  41. {
  42.     MapHooks::iterator it = g_mapHooksTable.find(pHookFunc);
  43.     if ( it != g_mapHooksTable.end() )
  44.         return &(it->second);
  45.     return NULL;
  46. }

  47. void ReplaceIATEntryInOneMod(const char * pszCalleeModName, FARPROC pfnCurrent, FARPROC pfnNew, HMODULE hMoudule)
  48. {
  49.     // Step 1. Get the base address.
  50.     PVOID addressBase = (PVOID)hMoudule;

  51.     // Step 2. Get the address of the module's import section
  52.     PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
  53.     __try {
  54.         ULONG ulSize;
  55.         pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
  56.             addressBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
  57.     } __except (EXCEPTION_EXECUTE_HANDLER) { }

  58.     if (pImportDesc == NULL)
  59.         return; // This module has no import section or is no longer loaded

  60.     // Find the import descriptor containing references to callee's functions
  61.     for (; pImportDesc->Name; pImportDesc++)
  62.     {
  63.         PSTR pszModName = (PSTR) ((PBYTE) addressBase + pImportDesc->Name);
  64.         if (lstrcmpiA(pszModName, pszCalleeModName) != 0) continue ;

  65.         // Get caller's import address table (IAT) for the callee's functions
  66.         PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
  67.             ((PBYTE) addressBase + pImportDesc->FirstThunk);

  68.         FARPROC* ppfn = NULL;
  69.         // Get the address of the function address
  70.         for (; pThunk->u1.Function; pThunk++)
  71.         {
  72.             FARPROC* ppfnTmp = (FARPROC*)&pThunk->u1.Function;
  73.             if ( *ppfnTmp == pfnCurrent )
  74.                 ppfn = ppfnTmp;
  75.         }
  76.         if (ppfn == NULL) continue ;

  77.         // Replace current function address with new function address
  78.         if ( !WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
  79.             sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError()) )
  80.         {
  81.             DWORD dwOldProtect;
  82.             if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, &dwOldProtect))
  83.             {
  84.                 WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
  85.                     sizeof(pfnNew), NULL);
  86.                 VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect,
  87.                     &dwOldProtect);
  88.             }
  89.         }
  90.         return; // We did it, get out
  91.     }
  92. }

  93. void ReplaceIATEntryInMoudule(HMODULE hMoudule)
  94. {
  95.     MapHooks::iterator it = g_mapHooksTable.begin();
  96.     for ( ; it != g_mapHooksTable.end(); ++it )
  97.     {
  98.         FARPROC funcHook = (FARPROC)it->first;
  99.         const char* nameDll = it->second.nameDLL.c_str();
  100.         FARPROC funcOrig = it->second.originalAPI;
  101.         ReplaceIATEntryInOneMod(nameDll,funcHook,funcOrig,hMoudule);
  102.     }
  103. }

  104. void ReplaceIATEntryInCurrentModules(bool bIsRestoreBack)
  105. {
  106.     MEMORY_BASIC_INFORMATION mbi;
  107.     HMODULE hmodThisMod = ((VirtualQuery(ReplaceIATEntryInCurrentModules, &mbi, sizeof(mbi)) != 0)
  108.         ? (HMODULE) mbi.AllocationBase : NULL);

  109.     HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
  110.     MODULEENTRY32 me = { sizeof(me) };
  111.     Module32First(hSnapshot,&me);
  112.     do {
  113.         // NOTE: We don't hook functions in our own module
  114.         if (me.hModule != hmodThisMod) {
  115.             MapHooks::iterator it = g_mapHooksTable.begin();
  116.             for ( ; it != g_mapHooksTable.end(); ++it )
  117.             {
  118.                 FARPROC funcHook = (FARPROC)it->first;
  119.                 const char* nameDll = it->second.nameDLL.c_str();
  120.                 FARPROC funcOrig = GetProcAddress(GetModuleHandleA(nameDll),it->second.nameAPI.c_str());
  121.                 if ( bIsRestoreBack )
  122.                     ReplaceIATEntryInOneMod(nameDll,funcHook,funcOrig,me.hModule);
  123.                 else
  124.                     ReplaceIATEntryInOneMod(nameDll,funcOrig,funcHook,me.hModule);
  125.             }
  126.         }
  127.     }while (Module32Next(hSnapshot,&me));
  128. }

  129. ////////////// Interfaces Implementation End.//////////////////////
  130. ///////////////////////////////////////////////////////////////////
3. 具体要HOOK的系统API的实现代码
除了加载模块和卸载模块的部分, 其他部分没什么特别的意思.
3.1. 头文件明细 ApiHooks.h
  1. #pragma once

  2. HMODULE WINAPI MyLoadLibraryW(LPCWSTR lpLibFileName);
  3. HMODULE WINAPI MyLoadLibraryA(LPCSTR lpLibFileName);
  4. HMODULE WINAPI MyLoadLibraryExA(LPCSTR lpLibFileName,HANDLE hFile,DWORD dwFlags);
  5. HMODULE WINAPI MyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile,DWORD dwFlags);
  6. BOOL WINAPI MyFreeLibrary(HMODULE hLibModule);
  7. VOID WINAPI MyFreeLibraryAndExitThread (HMODULE hLibModule,DWORD dwExitCode);

  8. VOID WINAPI MyExitProcess( UINT uExitCode );
3.2. 具体实现 ApiHooks.cpp
  1. #include "stdafx.h"
  2. #include "hooksTable.h"

  3. HMODULE WINAPI MyLoadLibraryW(LPCWSTR lpLibFileName)
  4. {
  5.     //MessageBoxA(NULL,"MyLoadLibraryW","MyLoadLibraryW",0);
  6.     HookData * pHookData = GetHookData(MyLoadLibraryW);
  7.     if ( ! pHookData )
  8.     {
  9.         _ASSERTE( ! "the MyLoadLibraryW has no original API on table g_mapHooksTable!" );
  10.         return NULL;
  11.     }

  12.     // Step 1. Load the module into memory.
  13.     typedef HMODULE (WINAPI *PtrMyApiFunction)(LPCWSTR);
  14.     PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);

  15.     HMODULE hModule = funOrig(lpLibFileName);

  16.     // Step 2. Hook the APIs on this moudle.
  17.     ReplaceIATEntryInCurrentModules();

  18.     return hModule;
  19. }

  20. HMODULE WINAPI MyLoadLibraryA(LPCSTR lpLibFileName)
  21. {
  22.     //MessageBoxA(NULL,"MyLoadLibraryA","MyLoadLibraryA",0);
  23.     HookData * pHookData = GetHookData(MyLoadLibraryA);
  24.     if ( ! pHookData )
  25.     {
  26.         _ASSERTE( ! "the MyLoadLibraryA has no original API on table g_mapHooksTable!" );
  27.         return NULL;
  28.     }

  29.     // Step 1. Load the module into memory.
  30.     typedef HMODULE (WINAPI *PtrMyApiFunction)(LPCSTR);
  31.     PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);

  32.     HMODULE hModule = funOrig(lpLibFileName);

  33.     // Step 2. Hook the APIs on this moudle.
  34.     ReplaceIATEntryInCurrentModules();

  35.     return hModule;
  36. }

  37. HMODULE WINAPI MyLoadLibraryExA
  38. (LPCSTR lpLibFileName,HANDLE hFile,DWORD dwFlags)
  39. {
  40.     //MessageBoxA(NULL,"","",0);
  41.     HookData * pHookData = GetHookData(MyLoadLibraryExA);
  42.     if ( ! pHookData )
  43.     {
  44.         _ASSERTE( ! "the MyLoadLibraryExA has no original API on table g_mapHooksTable!" );
  45.         return NULL;
  46.     }

  47.     // Step 1. Load the module into memory.
  48.     typedef HMODULE (WINAPI *PtrMyApiFunction)(LPCSTR, HANDLE,DWORD);
  49.     PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);

  50.     HMODULE hModule = funOrig(lpLibFileName,hFile,dwFlags);

  51.     // Step 2. Hook the APIs on this moudle.
  52.     ReplaceIATEntryInCurrentModules();

  53.     return hModule;
  54. }

  55. HMODULE WINAPI MyLoadLibraryExW
  56. (LPCWSTR lpLibFileName, HANDLE hFile,DWORD dwFlags)
  57. {
  58.     // MessageBoxA(NULL,"","",0);
  59.     HookData * pHookData = GetHookData(MyLoadLibraryExW);
  60.     if ( ! pHookData )
  61.     {
  62.         _ASSERTE( ! "the MyLoadLibraryExW has no original API on table g_mapHooksTable!" );
  63.         return NULL;
  64.     }

  65.     // Step 1. Load the module into memory.
  66.     typedef HMODULE (WINAPI *PtrMyApiFunction)(LPCWSTR, HANDLE,DWORD);
  67.     PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);

  68.     HMODULE hModule = funOrig(lpLibFileName,hFile,dwFlags);

  69.     // Step 2. Hook the APIs on this moudle.
  70.     ReplaceIATEntryInCurrentModules();

  71.     return hModule;
  72. }

  73. BOOL WINAPI MyFreeLibrary(HMODULE hLibModule)
  74. {
  75.     // MessageBoxA(NULL,"MyFreeLibrary","MyFreeLibrary",0);
  76.     // Step 1. Restore the APIs on the current moudle.
  77.     ReplaceIATEntryInMoudule(hLibModule);

  78.     // Step 2. Unload the module out of memory.
  79.     HookData * pHookData = GetHookData(MyFreeLibrary);
  80.     if ( ! pHookData )
  81.     {
  82.         _ASSERTE( ! "the MyFreeLibrary has no original API on table g_mapHooksTable!" );
  83.         return FALSE;
  84.     }

  85.     typedef BOOL (WINAPI *PtrMyApiFunction)(HMODULE);
  86.     PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);

  87.     return funOrig(hLibModule);
  88. }

  89. VOID WINAPI MyFreeLibraryAndExitThread (HMODULE hLibModule,DWORD dwExitCode)
  90. {
  91.     //MessageBoxA(NULL,"MyFreeLibraryAndExitThread","MyFreeLibraryAndExitThread",0);
  92.     // Step 1. Restore the APIs on the current moudle.
  93.     ReplaceIATEntryInMoudule(hLibModule);

  94.     // Step 2. Unload the module out of memory.
  95.     HookData * pHookData = GetHookData(MyFreeLibraryAndExitThread);
  96.     if ( ! pHookData )
  97.     {
  98.         _ASSERTE( ! "the MyFreeLibrary has no original API on table g_mapHooksTable!" );
  99.         return ;
  100.     }

  101.     typedef BOOL (WINAPI *PtrMyApiFunction)(HMODULE,DWORD);
  102.     PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);

  103.     funOrig(hLibModule,dwExitCode);
  104. }

  105. VOID WINAPI MyExitProcess( __in UINT uExitCode )
  106. {
  107.     MessageBoxA(NULL,"MyExitProcess","MyExitProcess",0);

  108.     HookData * pHookData = GetHookData(MyExitProcess);
  109.     if ( ! pHookData )
  110.     {
  111.         _ASSERTE( ! "the MyExitProcess has no original API on table g_mapHooksTable!" );
  112.         return ;
  113.     }

  114.     typedef VOID (WINAPI *PtrMyApiFunction)(UINT);
  115.     PtrMyApiFunction funOrig = (PtrMyApiFunction)(pHookData->originalAPI);

  116.     funOrig(uExitCode);
  117. }

阅读(2011) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~