头文件内容
#include <windows.h> // Inline Hook: 原理是修改程序执行流程上的代码,使代码可以从目标地址跳转到 // 指定的位置,从而获取函数的调用情况。微软专门给所有的库函数 // 提供了 6 字节的垃圾指令进行 Hook。 // Inline Hook 要注意的地方: 线程安全。如果在修改指令的同时,其它的线程正 // 在调用该地址的指令,那么由于指令修改完成了一半,得到的OpCode // 是不确定的,会导致崩溃。解决方式是 // ①:在 Hook 前,暂停当前进程的所有其它线程 // ②:使用原子操作: InterLocked 系列函数,原理是锁地址总线 lock // 保存 Hook 之前的原始 OpCode BYTE OldOpCode[5] = { 0x00 }; // 保存新的用于跳转的 OpCode: E9 xxxxxxxx BYTE JmpOpCode[5] = { 0xE9 }; // 保存需要修改的函数所在的地址 LPVOID Addr = nullptr; // 保存需要保护的 PID LONG Pid = 0; // 1. 我要 Hook 的是哪一个进程, OD 和 Taskmgr // 2. 为了 OD 不能附加目标进程,可以 Hook 函数 OpenProcess // 3. 编写自己的函数,务必保证原型完全一致,用于接管原始函数,主要执行[筛选]工作 // 开启关闭 Hook void EnableHook(BOOL Enable = TRUE) { DWORD OldProtect = 0; // 1. 修改目标地址所在分页的属性 VirtualProtect(Addr, 5, PAGE_EXECUTE_READWRITE, &OldProtect); // 2. 根据开启或关闭,向内填充新的旧的 OpCode memcpy(Addr, Enable ? JmpOpCode : OldOpCode, 5); // 3. 还原目标地址所在分页的属性 VirtualProtect(Addr, 5, OldProtect, &OldProtect); } // 自己编写的函数,在不满足条件的情况下,应该要调用原始函数 HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) { HANDLE Handle = 0; // 如果 pid 是 0x1515 就返回 -1 if (dwProcessId == Pid) { Handle = INVALID_HANDLE_VALUE; } else { // 为了不产生递归,应该先还原被 Hook 的指令 EnableHook(FALSE); Handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); // 为了下一次,还会进入 MyOpenProcess,要继续 Hook EnableHook(); } return Handle; } // 执行初始化的函数,例如保存原始指令,构建新的指令 void initialize() { // 1. 获取需要 Hook 的函数的地址,在系统运行时, // 所有[系统模块]在不同进程中的地址都是相同的 Addr = GetProcAddress(LoadLibraryA("kernel32.dll"), "OpenProcess"); // 2. 保存原始的指令,为了恢复原始代码 InterlockedExchang() memcpy(OldOpCode, Addr, 5); // 3. 计算跳转偏移: 新的函数地址 - 旧的函数地址 - 5(E9XXXXXXXX) DWORD Offset = (DWORD)MyOpenProcess - (DWORD)Addr - 5; // 4. 组合成新的 OpCode *(DWORD*)&JmpOpCode[1] = Offset; // 5. 获取需要保护的 Pid,第三个参数返回上一次的信号个数 HANDLE Semaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, L"MYPID"); ReleaseSemaphore(Semaphore, 1, &Pid); }
Dllmain文件内容
#include "framework.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: initialize(); EnableHook(); break; case DLL_PROCESS_DETACH: EnableHook(FALSE); break; } return TRUE; }
#include <windows.h> // 务必确保使用的是绝对路径 const char* DllName = "C:\Users\Administrator\Desktop\2\D15安全卫士0701\Debug\HookDll.dll"; int main() { // 在编写 dll 时,最初应该在自己的程序上使用 LoadLibrary 进行测试 // 创建了一个信号量,保存了一些数值(初始信号Pid,最大信号Pid+1) HANDLE Semaphore = CreateSemaphore(NULL, GetCurrentProcessId(), GetCurrentProcessId() + 1, "MYPID"); // 1. 通过窗口名称确定目标的 Pid DWORD Pid = 0, Size = 0; HWND hWnd = FindWindow(NULL, "任务管理器"); //HWND hWnd = FindWindow(NULL, "吾愛破解 - [LCG]"); GetWindowThreadProcessId(hWnd, &Pid); // 2. 使用对应的权限打开目标进程 HANDLE Handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); // 3. 申请空间,主要用于存放的是 LoadLibrary 的参数,务必确保版本(A/W)对应 LPVOID Addr = VirtualAllocEx(Handle, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // 4. 写入数据,注意写入的长度 WriteProcessMemory(Handle, Addr, DllName, strlen(DllName) + 1, &Size); // 5. 创建远程线程,注意版本 CreateRemoteThread(Handle, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryA, Addr, NULL, NULL); system("pause"); return 0; }