利用HOOK API做进程保护器

d

其实就很简单,只是对TerminateProcess的HOOK,因为要阻止的不是本进程的,所以要用到全局钩子,也就是把他做成dll形式的!

首先,对前面的HOOK API进行封装CAPIHook:

[cpp] view plain copy

  1. /////////////////////////////////////////////////////////  
  2. // APIHook.h文件  
  3.   
  4.   
  5. #ifndef __APIHOOK_H__  
  6. #define __APIHOOK_H__  
  7.   
  8. #include <windows.h>  
  9.   
  10. class CAPIHook    
  11. {  
  12. public:  
  13.     CAPIHook(LPSTR pszModName,   
  14.         LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod = TRUE);  
  15.     virtual ~CAPIHook();  
  16.     operator PROC() { return m_pfnOrig; }  
  17.   
  18. // 实现  
  19. private:  
  20.     LPSTR m_pszModName;     // 导出要HOOK函数的模块的名字  
  21.     LPSTR m_pszFuncName;        // 要HOOK的函数的名字  
  22.     PROC m_pfnOrig;         // 原API函数地址  
  23.     PROC m_pfnHook;         // HOOK后函数的地址  
  24.     BOOL m_bExcludeAPIHookMod;  // 是否将HOOK API的模块排除在外  
  25.   
  26. private:  
  27.     static void ReplaceIATEntryInAllMods(LPSTR pszExportMod, PROC pfnCurrent,   
  28.                 PROC pfnNew, BOOL bExcludeAPIHookMod);  
  29.     static void ReplaceIATEntryInOneMod(LPSTR pszExportMod,   
  30.                 PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller);  
  31.   
  32.   
  33. // 下面的代码用来解决其它模块动态加载DLL的问题  
  34. private:  
  35.     // 这两个指针用来将所有的CAPIHook对象连在一起  
  36.     static CAPIHook *sm_pHeader;  
  37.     CAPIHook *m_pNext;  
  38.   
  39. private:  
  40.     // 当一个新的DLL被加载时,调用此函数  
  41.     static void WINAPI HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags);  
  42.   
  43.     // 用来跟踪当前进程加载新的DLL  
  44.     static HMODULE WINAPI LoadLibraryA(PCSTR  pszModulePath);  
  45.     static HMODULE WINAPI LoadLibraryW(PCWSTR pszModulePath);  
  46.     static HMODULE WINAPI LoadLibraryExA(PCSTR  pszModulePath, HANDLE hFile, DWORD dwFlags);  
  47.     static HMODULE WINAPI LoadLibraryExW(PCWSTR pszModulePath, HANDLE hFile, DWORD dwFlags);  
  48.       
  49.     // 如果请求已HOOK的API函数,则返回用户自定义函数的地址  
  50.     static FARPROC WINAPI GetProcAddress(HMODULE hModule, PCSTR pszProcName);  
  51. private:  
  52.     // 自动对这些函数进行挂钩  
  53.     static CAPIHook sm_LoadLibraryA;  
  54.     static CAPIHook sm_LoadLibraryW;  
  55.     static CAPIHook sm_LoadLibraryExA;  
  56.     static CAPIHook sm_LoadLibraryExW;  
  57.     static CAPIHook sm_GetProcAddress;  
  58. };  
  59.   
  60. #endif // __APIHOOK_H__  

[cpp] view plain copy

  1. //////////////////////////////////////////////////////////////  
  2. // APIHook.cpp文件  
  3. #include "stdafx.h"  
  4. #include "APIHook.h"  
  5. #include "Tlhelp32.h"  
  6.   
  7. #include <ImageHlp.h> // 为了调用ImageDirectoryEntryToData函数  
  8. #pragma comment(lib, "ImageHlp")  
  9.   
  10.   
  11. // CAPIHook对象链表的头指针  
  12. CAPIHook* CAPIHook::sm_pHeader = NULL;  
  13.   
  14. CAPIHook::CAPIHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod)  
  15. {  
  16.     // 保存这个Hook函数的信息  
  17.     m_bExcludeAPIHookMod = bExcludeAPIHookMod;  
  18.     m_pszModName = pszModName;  
  19.     m_pszFuncName = pszFuncName;  
  20.     m_pfnHook = pfnHook;  
  21.     m_pfnOrig = ::GetProcAddress(::GetModuleHandle(pszModName), pszFuncName);  
  22.   
  23.     // 将此对象添加到链表中  
  24.     m_pNext = sm_pHeader;  
  25.     sm_pHeader = this;  
  26.       
  27.     // 在所有当前已加载的模块中HOOK这个函数  
  28.     ReplaceIATEntryInAllMods(m_pszModName, m_pfnOrig, m_pfnHook, bExcludeAPIHookMod);   
  29. }  
  30.   
  31. CAPIHook::~CAPIHook()  
  32. {  
  33.     // 取消对所有模块中函数的HOOK  
  34.     ReplaceIATEntryInAllMods(m_pszModName, m_pfnHook, m_pfnOrig, m_bExcludeAPIHookMod);  
  35.   
  36.     CAPIHook *p = sm_pHeader;  
  37.   
  38.     // 从链表中移除此对象  
  39.     if(p == this)  
  40.     {  
  41.         sm_pHeader = p->m_pNext;  
  42.     }  
  43.     else  
  44.     {  
  45.         while(p != NULL)  
  46.         {  
  47.             if(p->m_pNext == this)  
  48.             {  
  49.                 p->m_pNext = this->m_pNext;  
  50.                 break;  
  51.             }  
  52.             p = p->m_pNext;  
  53.         }  
  54.     }  
  55.   
  56. }  
  57.   
  58. void CAPIHook::ReplaceIATEntryInOneMod(LPSTR pszExportMod,   
  59.                    PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller)  
  60. {  
  61.     // 取得模块的导入表(import descriptor)首地址。ImageDirectoryEntryToData函数可以直接返回导入表地址  
  62.     ULONG ulSize;  
  63.     PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)  
  64.                 ::ImageDirectoryEntryToData(hModCaller, TRUE,   
  65.                     IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);  
  66.     if(pImportDesc == NULL) // 这个模块没有导入节表  
  67.     {  
  68.         return;  
  69.     }  
  70.   
  71.     // 查找包含pszExportMod模块中函数导入信息的导入表项  
  72.     while(pImportDesc->Name != 0)  
  73.     {  
  74.         LPSTR pszMod = (LPSTR)((DWORD)hModCaller + pImportDesc->Name);  
  75.         if(lstrcmpiA(pszMod, pszExportMod) == 0) // 找到  
  76.             break;  
  77.   
  78.         pImportDesc++;  
  79.     }  
  80.     if(pImportDesc->Name == 0) // hModCaller模块没有从pszExportMod模块导入任何函数  
  81.     {  
  82.         return;  
  83.     }  
  84.   
  85.     // 取得调用者的导入地址表(import address table, IAT)  
  86.     PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(pImportDesc->FirstThunk + (DWORD)hModCaller);  
  87.   
  88.     // 查找我们要HOOK的函数,将它的地址用新函数的地址替换掉  
  89.     while(pThunk->u1.Function)  
  90.     {  
  91.         // lpAddr指向的内存保存了函数的地址  
  92.         PDWORD lpAddr = (PDWORD)&(pThunk->u1.Function);  
  93.         if(*lpAddr == (DWORD)pfnCurrent)  
  94.         {  
  95.             // 修改页的保护属性  
  96.             DWORD dwOldProtect;  
  97.             MEMORY_BASIC_INFORMATION mbi;  
  98.             ::VirtualQuery(lpAddr, &mbi, sizeof(mbi));  
  99.             ::VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);  
  100.   
  101.             // 修改内存地址  相当于“*lpAddr = (DWORD)pfnNew;”  
  102.             ::WriteProcessMemory(::GetCurrentProcess(),   
  103.                         lpAddr, &pfnNew, sizeof(DWORD), NULL);  
  104.   
  105.             ::VirtualProtect(lpAddr, sizeof(DWORD), dwOldProtect, 0);  
  106.             break;  
  107.         }  
  108.         pThunk++;  
  109.     }  
  110. }  
  111.   
  112. void CAPIHook::ReplaceIATEntryInAllMods(LPSTR pszExportMod,   
  113.                     PROC pfnCurrent, PROC pfnNew, BOOL bExcludeAPIHookMod)  
  114. {  
  115.     // 取得当前模块的句柄  
  116.     HMODULE hModThis = NULL;  
  117.     if(bExcludeAPIHookMod)  
  118.     {  
  119.         MEMORY_BASIC_INFORMATION mbi;  
  120.         if(::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(mbi)) != 0)  
  121.             hModThis = (HMODULE)mbi.AllocationBase;  
  122.     }  
  123.   
  124.     // 取得本进程的模块列表  
  125.     HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ::GetCurrentProcessId());  
  126.   
  127.     // 遍历所有模块,分别对它们调用ReplaceIATEntryInOneMod函数,修改导入地址表  
  128.     MODULEENTRY32 me = { sizeof(MODULEENTRY32) };  
  129.     BOOL bOK = ::Module32First(hSnap, &me);  
  130.     while(bOK)  
  131.     {  
  132.         // 注意:我们不HOOK当前模块的函数  
  133.         if(me.hModule != hModThis)  
  134.             ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNew, me.hModule);  
  135.   
  136.         bOK = ::Module32Next(hSnap, &me);  
  137.     }  
  138.     ::CloseHandle(hSnap);  
  139. }  
  140.   
  141.   
  142. // 挂钩LoadLibrary和GetProcAddress函数,以便在这些函数被调用以后,挂钩的函数也能够被正确的处理  
  143.   
  144. CAPIHook CAPIHook::sm_LoadLibraryA("Kernel32.dll", "LoadLibraryA",     
  145.                     (PROC)CAPIHook::LoadLibraryA, TRUE);  
  146.   
  147. CAPIHook CAPIHook::sm_LoadLibraryW("Kernel32.dll", "LoadLibraryW",     
  148.                     (PROC)CAPIHook::LoadLibraryW, TRUE);  
  149.   
  150. CAPIHook CAPIHook::sm_LoadLibraryExA("Kernel32.dll", "LoadLibraryExA",   
  151.                     (PROC)CAPIHook::LoadLibraryExA, TRUE);  
  152.   
  153. CAPIHook CAPIHook::sm_LoadLibraryExW("Kernel32.dll", "LoadLibraryExW",   
  154.                     (PROC)CAPIHook::LoadLibraryExW, TRUE);  
  155.   
  156. CAPIHook CAPIHook::sm_GetProcAddress("Kernel32.dll", "GetProcAddress",   
  157.                     (PROC)CAPIHook::GetProcAddress, TRUE);  
  158.   
  159.   
  160.   
  161. void WINAPI CAPIHook::HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags)  
  162. {  
  163.     // 如果一个新的模块被加载,挂钩各CAPIHook对象要求的API函数  
  164.     if((hModule != NULL) && ((dwFlags&LOAD_LIBRARY_AS_DATAFILE) == 0))  
  165.     {  
  166.         CAPIHook *p = sm_pHeader;  
  167.         while(p != NULL)  
  168.         {  
  169.             ReplaceIATEntryInOneMod(p->m_pszModName, p->m_pfnOrig, p->m_pfnHook, hModule);  
  170.             p = p->m_pNext;  
  171.         }  
  172.     }  
  173. }  
  174.   
  175.   
  176. HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath)   
  177. {  
  178.     HMODULE hModule = ::LoadLibraryA(pszModulePath);  
  179.     HookNewlyLoadedModule(hModule, 0);  
  180.     return(hModule);  
  181. }  
  182.   
  183. HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath)   
  184. {  
  185.     HMODULE hModule = ::LoadLibraryW(pszModulePath);  
  186.     HookNewlyLoadedModule(hModule, 0);  
  187.     return(hModule);  
  188. }  
  189.   
  190. HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszModulePath, HANDLE hFile, DWORD dwFlags)   
  191. {  
  192.     HMODULE hModule = ::LoadLibraryExA(pszModulePath, hFile, dwFlags);  
  193.     HookNewlyLoadedModule(hModule, dwFlags);  
  194.     return(hModule);  
  195. }  
  196.   
  197. HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszModulePath, HANDLE hFile, DWORD dwFlags)   
  198. {  
  199.     HMODULE hModule = ::LoadLibraryExW(pszModulePath, hFile, dwFlags);  
  200.     HookNewlyLoadedModule(hModule, dwFlags);  
  201.     return(hModule);  
  202. }  
  203.   
  204. FARPROC WINAPI CAPIHook::GetProcAddress(HMODULE hModule, PCSTR pszProcName)  
  205. {  
  206.     // 得到这个函数的真实地址  
  207.     FARPROC pfn = ::GetProcAddress(hModule, pszProcName);  
  208.   
  209.     // 看它是不是我们要hook的函数  
  210.     CAPIHook *p = sm_pHeader;  
  211.     while(p != NULL)  
  212.     {  
  213.         if(p->m_pfnOrig == pfn)  
  214.         {  
  215.             pfn = p->m_pfnHook;  
  216.             break;  
  217.         }  
  218.   
  219.         p = p->m_pNext;  
  220.     }  
  221.   
  222.     return pfn;  
  223. }  

然后利用这个封装好的类开始做我们的DLL:

[cpp] view plain copy

  1. bool WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT nExitCode)  
  2. {  
  3.     typedef bool (WINAPI *PFNTERMINATEPROCESS)(HANDLE, UINT);  
  4.     char szPathName[256];  
  5.     ::GetModuleFileName(NULL, szPathName, 256);  
  6.     char sz[2048];  
  7.     wsprintf(sz, "进程号:%d   %s, 进程句柄: %X, 退出代码: %d/n", ::GetCurrentProcess(), szPathName, hProcess, nExitCode);  
  8.     COPYDATASTRUCT cds = {::GetCurrentProcessId(), strlen(sz) + 1, sz };  
  9.     if(::SendMessage(::FindWindow(NULL, "进程保护器"), WM_COPYDATA, 0, (LPARAM)&cds) != -1)  
  10.     {  
  11.         return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, nExitCode);  
  12.     }  
  13.     return true;  
  14. }  
  15. CAPIHook g_TerminateProcess("kernel32.dll", "TerminateProcess", (PROC)Hook_TerminateProcess );  
  16.   
  17. #pragma data_seg("YCIShared")  
  18. HHOOK g_hHook = NULL;  
  19. #pragma data_seg()  
  20. static HMODULE ModuleFromAddress(void *pv)  
  21. {  
  22.     MEMORY_BASIC_INFORMATION mbi;  
  23.     if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)  
  24.     {  
  25.         return (HMODULE)mbi.AllocationBase;  
  26.     }  
  27.     return NULL;  
  28. }  
  29. static LRESULT WINAPI GetMsgProc(int code, WPARAM wParam, LPARAM lParam)  
  30. {  
  31.     return ::CallNextHookEx(g_hHook, code, wParam, lParam);  
  32. }  
  33.   
  34. extern "C" int __declspec(dllexport)SetSysHook(bool bInstall, DWORD dwThreadId)  
  35. {  
  36.     bool bOk;  
  37.     if(bInstall)  
  38.     {  
  39.         g_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, ModuleFromAddress(GetMsgProc), dwThreadId);  
  40.         bOk = (g_hHook != NULL);  
  41.     }  
  42.     else  
  43.     {  
  44.         bOk = ::UnhookWindowsHookEx(g_hHook);  
  45.         g_hHook = NULL;  
  46.     }  
  47.     return bOk;  
  48.   
  49. }  

编译,OK啦,已经做成我们要的DLL!

下面把他加载到我们所需要的程序中,因为DLL通过WM_COPYDATA发送了一个消息给了我们的程序的,因此我在程序中要响应此消息,重载WM_COPYDATA消息

[cpp] view plain copy

  1. BOOL CHookTermTestDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)   
  2. {  
  3.     // TODO: Add your message handler code here and/or call default  
  4.     GetDlgItem(IDC_EDIT1)->SetWindowText((char *)pCopyDataStruct->lpData);  
  5.     bool nForbid = ((CButton *)GetDlgItem(IDC_CHECK1))->GetCheck();  
  6.     if(nForbid)  
  7.         return -1;  
  8.     return TRUE;  
  9.     //return CDialog::OnCopyData(pWnd, pCopyDataStruct);  
  10. }  

当然,也别忘了要加载那DLL的钩子,和卸载那钩子

[cpp] view plain copy

  1. void CHookTermTestDlg::OnCheck1()   
  2. {  
  3.     // TODO: Add your control notification handler code here  
  4.     typedef int(*PFNSETSYSHOOK)(BOOL, DWORD);  
  5.     char szDll[] = "HookTerm.dll";  
  6.     bool nNeedFree = false;  
  7.     HMODULE hModule = ::GetModuleHandle(szDll);  
  8.     if(hModule == NULL)  
  9.     {  
  10.         hModule = ::LoadLibrary(szDll);  
  11.         nNeedFree = true;  
  12.     }  
  13.     if(hModule == NULL)  
  14.     {  
  15.   
  16.     }  
  17.     PFNSETSYSHOOK mSetSysHook = (PFNSETSYSHOOK)GetProcAddress(hModule, "SetSysHook");  
  18.     if(mSetSysHook == NULL)  
  19.     {  
  20.         if(nNeedFree)  
  21.             ::FreeLibrary(hModule);  
  22.         return ;  
  23.     }  
  24.     bool bRet = mSetSysHook(TRUE, 0);  
  25.     if(nNeedFree)  
  26.     {  
  27.         ::FreeLibrary(hModule);  
  28.     }  
  29.     //SetSysHook(true, 0);  
  30.       
  31. }  

[cpp] view plain copy

  1. void CHookTermTestDlg::OnButton1()   
  2. {  
  3.     // TODO: Add your control notification handler code here  
  4.     typedef int(*PFNSETSYSHOOK)(BOOL, DWORD);  
  5.     char szDll[] = "HookTerm.dll";  
  6.     bool nNeedFree = false;  
  7.     HMODULE hModule = ::GetModuleHandle(szDll);  
  8.     if(hModule == NULL)  
  9.     {  
  10.         hModule = ::LoadLibrary(szDll);  
  11.         nNeedFree = true;  
  12.     }  
  13.     if(hModule == NULL)  
  14.     {  
  15.   
  16.     }  
  17.     PFNSETSYSHOOK mSetSysHook = (PFNSETSYSHOOK)GetProcAddress(hModule, "SetSysHook");  
  18.     if(mSetSysHook == NULL)  
  19.     {  
  20.         if(nNeedFree)  
  21.             ::FreeLibrary(hModule);  
  22.         return ;  
  23.     }  
  24.     bool bRet = mSetSysHook(false, 0);  
  25.     if(nNeedFree)  
  26.     {  
  27.         ::FreeLibrary(hModule);  
  28.     }  
  29.     CDialog::OnCancel();  
  30. }  

猜你喜欢

转载自blog.csdn.net/bruce135lee/article/details/81387197