其实就很简单,只是对TerminateProcess的HOOK,因为要阻止的不是本进程的,所以要用到全局钩子,也就是把他做成dll形式的!
首先,对前面的HOOK API进行封装CAPIHook:
[cpp] view plain copy
- /
- // APIHook.h文件
- #ifndef __APIHOOK_H__
- #define __APIHOOK_H__
- #include <windows.h>
- class CAPIHook
- {
- public:
- CAPIHook(LPSTR pszModName,
- LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod = TRUE);
- virtual ~CAPIHook();
- operator PROC() { return m_pfnOrig; }
- // 实现
- private:
- LPSTR m_pszModName; // 导出要HOOK函数的模块的名字
- LPSTR m_pszFuncName; // 要HOOK的函数的名字
- PROC m_pfnOrig; // 原API函数地址
- PROC m_pfnHook; // HOOK后函数的地址
- BOOL m_bExcludeAPIHookMod; // 是否将HOOK API的模块排除在外
- private:
- static void ReplaceIATEntryInAllMods(LPSTR pszExportMod, PROC pfnCurrent,
- PROC pfnNew, BOOL bExcludeAPIHookMod);
- static void ReplaceIATEntryInOneMod(LPSTR pszExportMod,
- PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller);
- // 下面的代码用来解决其它模块动态加载DLL的问题
- private:
- // 这两个指针用来将所有的CAPIHook对象连在一起
- static CAPIHook *sm_pHeader;
- CAPIHook *m_pNext;
- private:
- // 当一个新的DLL被加载时,调用此函数
- static void WINAPI HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags);
- // 用来跟踪当前进程加载新的DLL
- 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);
- // 如果请求已HOOK的API函数,则返回用户自定义函数的地址
- static FARPROC WINAPI GetProcAddress(HMODULE hModule, PCSTR pszProcName);
- private:
- // 自动对这些函数进行挂钩
- static CAPIHook sm_LoadLibraryA;
- static CAPIHook sm_LoadLibraryW;
- static CAPIHook sm_LoadLibraryExA;
- static CAPIHook sm_LoadLibraryExW;
- static CAPIHook sm_GetProcAddress;
- };
- #endif // __APIHOOK_H__
[cpp] view plain copy
- //
- // APIHook.cpp文件
- #include "stdafx.h"
- #include "APIHook.h"
- #include "Tlhelp32.h"
- #include <ImageHlp.h> // 为了调用ImageDirectoryEntryToData函数
- #pragma comment(lib, "ImageHlp")
- // CAPIHook对象链表的头指针
- CAPIHook* CAPIHook::sm_pHeader = NULL;
- CAPIHook::CAPIHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod)
- {
- // 保存这个Hook函数的信息
- m_bExcludeAPIHookMod = bExcludeAPIHookMod;
- m_pszModName = pszModName;
- m_pszFuncName = pszFuncName;
- m_pfnHook = pfnHook;
- m_pfnOrig = ::GetProcAddress(::GetModuleHandle(pszModName), pszFuncName);
- // 将此对象添加到链表中
- m_pNext = sm_pHeader;
- sm_pHeader = this;
- // 在所有当前已加载的模块中HOOK这个函数
- ReplaceIATEntryInAllMods(m_pszModName, m_pfnOrig, m_pfnHook, bExcludeAPIHookMod);
- }
- CAPIHook::~CAPIHook()
- {
- // 取消对所有模块中函数的HOOK
- ReplaceIATEntryInAllMods(m_pszModName, m_pfnHook, m_pfnOrig, m_bExcludeAPIHookMod);
- CAPIHook *p = sm_pHeader;
- // 从链表中移除此对象
- if(p == this)
- {
- sm_pHeader = p->m_pNext;
- }
- else
- {
- while(p != NULL)
- {
- if(p->m_pNext == this)
- {
- p->m_pNext = this->m_pNext;
- break;
- }
- p = p->m_pNext;
- }
- }
- }
- void CAPIHook::ReplaceIATEntryInOneMod(LPSTR pszExportMod,
- PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller)
- {
- // 取得模块的导入表(import descriptor)首地址。ImageDirectoryEntryToData函数可以直接返回导入表地址
- ULONG ulSize;
- PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
- ::ImageDirectoryEntryToData(hModCaller, TRUE,
- IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
- if(pImportDesc == NULL) // 这个模块没有导入节表
- {
- return;
- }
- // 查找包含pszExportMod模块中函数导入信息的导入表项
- while(pImportDesc->Name != 0)
- {
- LPSTR pszMod = (LPSTR)((DWORD)hModCaller + pImportDesc->Name);
- if(lstrcmpiA(pszMod, pszExportMod) == 0) // 找到
- break;
- pImportDesc++;
- }
- if(pImportDesc->Name == 0) // hModCaller模块没有从pszExportMod模块导入任何函数
- {
- return;
- }
- // 取得调用者的导入地址表(import address table, IAT)
- PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(pImportDesc->FirstThunk + (DWORD)hModCaller);
- // 查找我们要HOOK的函数,将它的地址用新函数的地址替换掉
- while(pThunk->u1.Function)
- {
- // lpAddr指向的内存保存了函数的地址
- PDWORD lpAddr = (PDWORD)&(pThunk->u1.Function);
- if(*lpAddr == (DWORD)pfnCurrent)
- {
- // 修改页的保护属性
- DWORD dwOldProtect;
- MEMORY_BASIC_INFORMATION mbi;
- ::VirtualQuery(lpAddr, &mbi, sizeof(mbi));
- ::VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
- // 修改内存地址 相当于“*lpAddr = (DWORD)pfnNew;”
- ::WriteProcessMemory(::GetCurrentProcess(),
- lpAddr, &pfnNew, sizeof(DWORD), NULL);
- ::VirtualProtect(lpAddr, sizeof(DWORD), dwOldProtect, 0);
- break;
- }
- pThunk++;
- }
- }
- void CAPIHook::ReplaceIATEntryInAllMods(LPSTR pszExportMod,
- PROC pfnCurrent, PROC pfnNew, BOOL bExcludeAPIHookMod)
- {
- // 取得当前模块的句柄
- HMODULE hModThis = NULL;
- if(bExcludeAPIHookMod)
- {
- MEMORY_BASIC_INFORMATION mbi;
- if(::VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(mbi)) != 0)
- hModThis = (HMODULE)mbi.AllocationBase;
- }
- // 取得本进程的模块列表
- HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ::GetCurrentProcessId());
- // 遍历所有模块,分别对它们调用ReplaceIATEntryInOneMod函数,修改导入地址表
- MODULEENTRY32 me = { sizeof(MODULEENTRY32) };
- BOOL bOK = ::Module32First(hSnap, &me);
- while(bOK)
- {
- // 注意:我们不HOOK当前模块的函数
- if(me.hModule != hModThis)
- ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNew, me.hModule);
- bOK = ::Module32Next(hSnap, &me);
- }
- ::CloseHandle(hSnap);
- }
- // 挂钩LoadLibrary和GetProcAddress函数,以便在这些函数被调用以后,挂钩的函数也能够被正确的处理
- 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::GetProcAddress, TRUE);
- void WINAPI CAPIHook::HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags)
- {
- // 如果一个新的模块被加载,挂钩各CAPIHook对象要求的API函数
- if((hModule != NULL) && ((dwFlags&LOAD_LIBRARY_AS_DATAFILE) == 0))
- {
- CAPIHook *p = sm_pHeader;
- while(p != NULL)
- {
- ReplaceIATEntryInOneMod(p->m_pszModName, p->m_pfnOrig, p->m_pfnHook, hModule);
- p = p->m_pNext;
- }
- }
- }
- HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath)
- {
- HMODULE hModule = ::LoadLibraryA(pszModulePath);
- HookNewlyLoadedModule(hModule, 0);
- return(hModule);
- }
- HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath)
- {
- HMODULE hModule = ::LoadLibraryW(pszModulePath);
- HookNewlyLoadedModule(hModule, 0);
- return(hModule);
- }
- HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszModulePath, HANDLE hFile, DWORD dwFlags)
- {
- HMODULE hModule = ::LoadLibraryExA(pszModulePath, hFile, dwFlags);
- HookNewlyLoadedModule(hModule, dwFlags);
- return(hModule);
- }
- HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszModulePath, HANDLE hFile, DWORD dwFlags)
- {
- HMODULE hModule = ::LoadLibraryExW(pszModulePath, hFile, dwFlags);
- HookNewlyLoadedModule(hModule, dwFlags);
- return(hModule);
- }
- FARPROC WINAPI CAPIHook::GetProcAddress(HMODULE hModule, PCSTR pszProcName)
- {
- // 得到这个函数的真实地址
- FARPROC pfn = ::GetProcAddress(hModule, pszProcName);
- // 看它是不是我们要hook的函数
- CAPIHook *p = sm_pHeader;
- while(p != NULL)
- {
- if(p->m_pfnOrig == pfn)
- {
- pfn = p->m_pfnHook;
- break;
- }
- p = p->m_pNext;
- }
- return pfn;
- }
然后利用这个封装好的类开始做我们的DLL:
[cpp] view plain copy
- bool WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT nExitCode)
- {
- typedef bool (WINAPI *PFNTERMINATEPROCESS)(HANDLE, UINT);
- char szPathName[256];
- ::GetModuleFileName(NULL, szPathName, 256);
- char sz[2048];
- wsprintf(sz, "进程号:%d %s, 进程句柄: %X, 退出代码: %d/n", ::GetCurrentProcess(), szPathName, hProcess, nExitCode);
- COPYDATASTRUCT cds = {::GetCurrentProcessId(), strlen(sz) + 1, sz };
- if(::SendMessage(::FindWindow(NULL, "进程保护器"), WM_COPYDATA, 0, (LPARAM)&cds) != -1)
- {
- return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, nExitCode);
- }
- return true;
- }
- CAPIHook g_TerminateProcess("kernel32.dll", "TerminateProcess", (PROC)Hook_TerminateProcess );
- #pragma data_seg("YCIShared")
- HHOOK g_hHook = NULL;
- #pragma data_seg()
- static HMODULE ModuleFromAddress(void *pv)
- {
- MEMORY_BASIC_INFORMATION mbi;
- if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
- {
- return (HMODULE)mbi.AllocationBase;
- }
- return NULL;
- }
- static LRESULT WINAPI GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
- {
- return ::CallNextHookEx(g_hHook, code, wParam, lParam);
- }
- extern "C" int __declspec(dllexport)SetSysHook(bool bInstall, DWORD dwThreadId)
- {
- bool bOk;
- if(bInstall)
- {
- g_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, ModuleFromAddress(GetMsgProc), dwThreadId);
- bOk = (g_hHook != NULL);
- }
- else
- {
- bOk = ::UnhookWindowsHookEx(g_hHook);
- g_hHook = NULL;
- }
- return bOk;
- }
编译,OK啦,已经做成我们要的DLL!
下面把他加载到我们所需要的程序中,因为DLL通过WM_COPYDATA发送了一个消息给了我们的程序的,因此我在程序中要响应此消息,重载WM_COPYDATA消息
[cpp] view plain copy
- BOOL CHookTermTestDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
- {
- // TODO: Add your message handler code here and/or call default
- GetDlgItem(IDC_EDIT1)->SetWindowText((char *)pCopyDataStruct->lpData);
- bool nForbid = ((CButton *)GetDlgItem(IDC_CHECK1))->GetCheck();
- if(nForbid)
- return -1;
- return TRUE;
- //return CDialog::OnCopyData(pWnd, pCopyDataStruct);
- }
当然,也别忘了要加载那DLL的钩子,和卸载那钩子
[cpp] view plain copy
- void CHookTermTestDlg::OnCheck1()
- {
- // TODO: Add your control notification handler code here
- typedef int(*PFNSETSYSHOOK)(BOOL, DWORD);
- char szDll[] = "HookTerm.dll";
- bool nNeedFree = false;
- HMODULE hModule = ::GetModuleHandle(szDll);
- if(hModule == NULL)
- {
- hModule = ::LoadLibrary(szDll);
- nNeedFree = true;
- }
- if(hModule == NULL)
- {
- }
- PFNSETSYSHOOK mSetSysHook = (PFNSETSYSHOOK)GetProcAddress(hModule, "SetSysHook");
- if(mSetSysHook == NULL)
- {
- if(nNeedFree)
- ::FreeLibrary(hModule);
- return ;
- }
- bool bRet = mSetSysHook(TRUE, 0);
- if(nNeedFree)
- {
- ::FreeLibrary(hModule);
- }
- //SetSysHook(true, 0);
- }
[cpp] view plain copy
- void CHookTermTestDlg::OnButton1()
- {
- // TODO: Add your control notification handler code here
- typedef int(*PFNSETSYSHOOK)(BOOL, DWORD);
- char szDll[] = "HookTerm.dll";
- bool nNeedFree = false;
- HMODULE hModule = ::GetModuleHandle(szDll);
- if(hModule == NULL)
- {
- hModule = ::LoadLibrary(szDll);
- nNeedFree = true;
- }
- if(hModule == NULL)
- {
- }
- PFNSETSYSHOOK mSetSysHook = (PFNSETSYSHOOK)GetProcAddress(hModule, "SetSysHook");
- if(mSetSysHook == NULL)
- {
- if(nNeedFree)
- ::FreeLibrary(hModule);
- return ;
- }
- bool bRet = mSetSysHook(false, 0);
- if(nNeedFree)
- {
- ::FreeLibrary(hModule);
- }
- CDialog::OnCancel();
- }