Windows Practice_Dll&Hook_封装IAT Hook
2017-09-24 12:32
459 查看
进程保护器的实现
本程序实现了一个简单的暴力的进程保护器,其原理也很简单,就是修改导入表,挂钩TerminateProcess函数,因为这个函数可以远程无条件的结束其它进程,所以我们要挂钩这个函数。因为每一个程序都有可能结束要保护的程序,所以我们必须以Dll的形式注入到每一个进程中,这就涉及到注入的问题了,而Windows给我们提供了一个简单的全局挂钩的函数,即SetWindowsHook函数。
本工程主要有三个程序,分别是ProcessProtectorDll、ProcessProtectorExe以及TerminateProcessExe,从这三个程序的名字相信大家也都知道这些程序的作用了,就不再多做解释了。
下面我们一一将它们的源代码附上并稍作解释。
ProcessProtectorDll动态链接库程序
该程序主要是用来被其它的可执行程序调用,从而达到全局挂钩并保护相应进程的目的。代码如下:// IATHook.h文件 #pragma once #include <string> namespace PoEdu { class CIATHook { public: // 初始化即Hook // 挂哪个Dll的哪个函数的钩 // 新的函数的地址 // 现有的所有Module CIATHook(const std::string &dll_name, const std::string &func_name, void *new_func_addr); HMODULE WINAPI LoadLibraryA(_In_ LPCSTR lpFileName); HMODULE WINAPI LoadLibraryW(_In_ LPCWSTR lpFileName); HMODULE WINAPI LoadLibraryExA(_In_ LPCSTR lpFileName, _Reserved_ HANDLE hFile, _In_ DWORD dwFlags); HMODULE WINAPI LoadLibraryExW(_In_ LPCWSTR lpFileName, _Reserved_ HANDLE hFile, _In_ DWORD dwFlags); FARPROC WINAPI GetProcAddress(_In_ HMODULE hModule, _In_ LPCSTR lpProcName ) const; private: void HookAllModule() const; void HookOneModule(HMODULE hModule) const; private: std::string dll_name_; void *new_func_addr_; void *old_func_addr_; }; }
//IATHook.cpp文件 #include "stdafx.h" #include "IATHook.h" #include <TlHelp32.h> #include <DbgHelp.h> #include <winbase.h> #pragma comment(lib, "DbgHelp.lib") // 这个类还有有些不足 // 在启用新进程的时候还是挂不上 namespace PoEdu { CIATHook::CIATHook(const std::string& dll_name, const std::string& func_name, void* new_func_addr) : dll_name_(dll_name), new_func_addr_(new_func_addr) { old_func_addr_ = GetProcAddress(GetModuleHandleA(dll_name.c_str()), func_name.c_str()); // 开始挂钩 // 每个Module都有自己的IAT,所以需要遍历所有的Module HookAllModule(); } HMODULE CIATHook::LoadLibraryA(LPCSTR lpFileName) { HMODULE hModule = ::LoadLibraryA(lpFileName); HookOneModule(hModule); return hModule; } HMODULE CIATHook::LoadLibraryW(LPCWSTR lpFileName) { HMODULE hModule = ::LoadLibraryW(lpFileName); HookOneModule(hModule); return hModule; } HMODULE CIATHook::LoadLibraryExA(LPCSTR lpFileName, HANDLE hFile, DWORD dwFlags) { HMODULE hModule = ::LoadLibraryExA(lpFileName, hFile, dwFlags); HookOneModule(hModule); return hModule; } HMODULE CIATHook::LoadLibraryExW(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags) { HMODULE hModule = ::LoadLibraryExW(lpFileName, hFile, dwFlags); HookOneModule(hModule); return hModule; } FARPROC CIATHook::GetProcAddress(HMODULE hModule, LPCSTR lpProcName) const { FARPROC pAddr = ::GetProcAddress(hModule, lpProcName); if (pAddr == old_func_addr_) { return static_cast<FARPROC>(new_func_addr_); } else { return pAddr; } } void CIATHook::HookAllModule() const { HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); MODULEENTRY32 me32 = { sizeof(MODULEENTRY32) }; BOOL bNext = ::Module32FirstW(hSnap, &me32); while (bNext) { // 给每个Module挂钩 HookOneModule(me32.hModule); bNext = Module32NextW(hSnap, &me32); } CloseHandle(hSnap); } void CIATHook::HookOneModule(HMODULE hModule) const { ULONG ulSize = 0; PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = static_cast<PIMAGE_IMPORT_DESCRIPTOR>(ImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize)); if (!pImageImportDescriptor) { return; } while (pImageImportDescriptor->Name) { char *pDllName = reinterpret_cast<char *>(reinterpret_cast<BYTE *>(hModule) + pImageImportDescriptor->Name); if (dll_name_.compare(pDllName) == 0) { break; } ++pImageImportDescriptor; } if (pImageImportDescriptor->Name) { PIMAGE_THUNK_DATA pImageThunkData = reinterpret_cast<PIMAGE_THUNK_DATA>(reinterpret_cast<BYTE *>(hModule) + pImageImportDescriptor->FirstThunk); while (pImageThunkData->u1.Function) { DWORD *pDwAddr = &(pImageThunkData->u1.Function); if (*pDwAddr == reinterpret_cast<DWORD>(old_func_addr_)) { MEMORY_BASIC_INFORMATION mbi; VirtualQuery(pDwAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); DWORD dwOldProtection = 0; VirtualProtect(pDwAddr, sizeof(DWORD_PTR), PAGE_READWRITE, &dwOldProtection); // 为了安全起见,可以使用WriteProcessMemory函数进行远进程写入,这样即使权限不够,也不会报异常 if (!WriteProcessMemory(GetCurrentProcess(), pDwAddr, &new_func_addr_, sizeof(DWORD_PTR), nullptr)) { MessageBoxW(nullptr, L"WriteProcessMemory", L"WriteProcessMemory", MB_OK); } VirtualProtect(pDwAddr, sizeof(DWORD_PTR), dwOldProtection, nullptr); break; } ++pImageThunkData; } } } }
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "stdafx.h" #include "IATHook.h" // 找到当前注入后的 IAT 表 Hook TerminateProcess //PoEdu::CIATHook g_MyHook; DWORD g_dwPID = 0; HHOOK g_hHook = nullptr; BOOL WINAPI MyTerminateProcess(_In_ HANDLE hProcess, _In_ UINT uExitCode) { return FALSE; // DWORD dwPID = GetProcessId(hProcess); // if (g_dwPID == dwPID) // { // MessageBoxW(nullptr, L"这是我要保护的进程,请不要无条件终止它!", L"警告", MB_OK); // return TRUE; // } //return TerminateProcess(hProcess, uExitCode); } PoEdu::CIATHook g_MyHook("KERNEL32.dll", "TerminateProcess", MyTerminateProcess); BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; default: break; } return TRUE; } HMODULE GetFuncModule(void * pFuncAddr) { HMODULE hRet = nullptr; MEMORY_BASIC_INFORMATION mbi; if (VirtualQuery(pFuncAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0) { hRet = static_cast<HMODULE>(mbi.AllocationBase); } return hRet; } LRESULT CALLBACK GetMsgProc(_In_ int code, _In_ WPARAM wParam, _In_ LPARAM lParam) { //MessageBoxW(nullptr, L"GetMsgProc", L"GetMsgProc", MB_OK); return CallNextHookEx(g_hHook, code, wParam, lParam); } // 用SetWindowsHook做的注入 extern "C" _declspec(dllexport) BOOL StartProtecting(DWORD dwPID) //extern "C" _declspec(dllexport) BOOL StartProtecting() { BOOL bRet = FALSE; if (g_hHook == nullptr) { g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, GetFuncModule(GetMsgProc), 0); if (g_hHook != nullptr) { g_dwPID = dwPID; bRet = TRUE; } } return bRet; } extern "C" _declspec(dllexport) BOOL EndProtecting() { BOOL bRet = FALSE; if (g_hHook != nullptr) { if (UnhookWindowsHookEx(g_hHook)) { bRet = TRUE; } } return bRet; }
上面主要有问题的是MyTerminateProcess函数,从这个函数的实现可以看出,我们屏蔽的是所有的TerminateProcess,因为每一个进程在调用ProcessProtectorDll动态链接库的时候都是重新复制一份,所以没法简单的在挂钩的时候传递一个要保护的进程ID,因为在新的进程调用该动态链接库的时候,一切都是初始化状态,并没有要保护的进程ID,只能通过共享空间实现所有进程的数据共享,这里我们没有实现,感兴趣的朋友可以实现一下。。。
ProcessProtectorExe程序源码
该程序主要是加载ProcessProtectorDll动态链接库从而达到保护进程不被远程无条件结束的目的。// ProcessProtectorExe.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> #include <clocale> // 选择需要保护的进程 // 启动Hook typedef BOOL(*FUNC)(DWORD dwPID); void PrintErrorMessage(DWORD dwErrorCode) { setlocale(LC_ALL, "chs"); TCHAR strErrorMessage[MAXBYTE] = { 0 }; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, dwErrorCode, 0, strErrorMessage, MAXBYTE, nullptr); wprintf(L"错误代码是:%d %s\r\n", dwErrorCode, strErrorMessage); } int main() { HMODULE hDllModule = nullptr; FUNC StartProtecting = nullptr; FARPROC EndProtecting = nullptr; do { // 查找窗口 char strProcessName[MAXBYTE] = "计算器"; HWND hWnd = FindWindowA(nullptr, strProcessName); if (hWnd == nullptr) { printf("the handle of window do not found!\r\n"); break; } // 根据窗口句柄查找进程ID DWORD dwProcessId = 0; GetWindowThreadProcessId(hWnd, &dwProcessId); if (dwProcessId == NULL) { printf("process Id do not found!\r\n"); break; } // 打开进程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess == nullptr) { printf("open the process failed!\r\n"); break; } // LoadLibray hDllModule = LoadLibrary(L"ProcessProtectorDll.dll"); if (hDllModule == nullptr) { PrintErrorMessage(GetLastError()); break; } // SetHook StartProtecting = reinterpret_cast<FUNC>(GetProcAddress(hDllModule, "StartProtecting")); if (StartProtecting == nullptr) { PrintErrorMessage(GetLastError()); break; } if (!StartProtecting(dwProcessId)) { PrintErrorMessage(GetLastError()); break; } printf("进程保护成功!\r\n"); MSG msg; BOOL ret; while ((ret = GetMessage(&msg, nullptr, 0, 0))) { if (ret == -1) break; TranslateMessage(&msg); DispatchMessage(&msg); } // UnHook EndProtecting = GetProcAddress(hDllModule, "EndProtecting"); if (EndProtecting == nullptr) { PrintErrorMessage(GetLastError()); break; } if (!EndProtecting()) { PrintErrorMessage(GetLastError()); break; } } while (false); if (hDllModule) { FreeLibrary(hDllModule); } system("pause"); return 0; }
由于动态链接库是被所有进程调用的,所以这里保护的是所有的进程不被远程无条件结束掉,而不只是计算器这个程序,这个需要注意一下。
**
// TerminateProcessExe.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> int main() { do { // 查找窗口 char strProcessName[MAXBYTE] = "计算器"; HWND hWnd = FindWindowA(nullptr, strProcessName); if (hWnd == nullptr) { printf("the handle of window do not found!\r\n"); break; } // 根据窗口句柄查找进程ID DWORD dwProcessId = 0; GetWindowThreadProcessId(hWnd, &dwProcessId); if (dwProcessId == NULL) { printf("process Id do not found!\r\n"); break; } // 打开进程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess == nullptr) { printf("open the process failed!\r\n"); break; } MessageBoxW(nullptr, L"", L"", MB_OK); if (TerminateProcess(hProcess, 1)) { printf("已经被终止运行!\r\n"); } else { printf("没有被终止运行!\r\n"); } } while (false); system("pause"); return 0; }
本程序就是尝试远程结束计算器程序,当开启了我们的进程保护器后,我们是无法终止计算器的,这也就达到了要保护的目的。
当然了,这种全局挂钩的方式是存在问题的,它会使我们的系统变得非常的慢。我们的这个进程保护器目的只是让大家了解一下什么是IAT Hook,它的原理是什么,实际上基本上不会用这种方式来实现进程保护器的。
相关文章推荐
- Windows Practice_Dll&Hook_IAT Hook
- Windows Practice_Dll&Hook_DetourHook库
- 封装 JMail 4.4 的 POP3 为 .Net 组件 (.dll 程序集),实现 "邮件(附件) 到达" 等 "事件"!
- Win32 DLL和MFC DLL 中封装对话框<转>
- Windows Practice_Dll&Hook_消息钩子
- 系统本身的dll之间也有一大堆iat hook?
- WINCE 开发,Coredll.dll 的C#封装
- 修改导入表HOOK API(ring3_iat_exe_hook_Messagebox)<转>
- Windows Practice_Dll&Hook_Hook是什么?
- HOOK&DLL编写
- 把vc中的类封装成dll的简单方法
- 不用DLL即可Hook得到按键代码(支持XP)
- 使用FDO封装XML&ADO实现与服务端数据通信
- C++封装SQLite实例<五>
- 未能加载文件或程序集''file:///C:/Program Files (x86)/ArcGIS/DeveloperKit10.0/DotNet/ESRI.ArcGIS.ADF.Local.dll'
- JS封装HTML <scrtpt type ="text/HTML"> JSPOP跨域请求
- 安装Wamp2.5一直提示"计算机中丢失 MSVCR110.dll"解决方案
- dll封装后,ASP调用
- ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)
- 【iOS开发】封装聊天输入框MKInputBar,语音支持iOS & Android平台