为梦想而生

碧海青天的追梦之旅

   ::  :: 新随笔  ::  ::  :: 管理

见过网上有很多ApiHook的类,但是都不尽入人意,要么就是写的不够好不够完善,要么就是跑不起来.

用别人写的代码总是有种不安心,所以自己就花了一晚上写了CApiHook类.已经尽量确保自己写的类是非常完善的.

 

//20151208稍微改变了一下ApiHook的逻辑,重写GetApiHookStatus函数并重命名为GetProcHookStatus,

  并且很认真负责的测试了WinXP x86/Win7 x86/Win7 x64/Win8.1 x64系统下的GetProcHookStatus有效性.

 

//20150728稍微改进了一下ApiHook的稳定性,和增加了一个检测系统Api Hook状态的函数GetApiHookStatus

 

//编写和测试环境: Microsoft Visual Studio 2015 Enterprise RC / Microsoft Windows 7 Ultimate x86

 

 1 //    CApiHook, Last Code By gwsbhqt@163.com At 20151208
 2 
 3 #pragma once
 4 
 5 #ifndef __CAPIHOOK_H__
 6 #define __CAPIHOOK_H__
 7 
 8 #include <cstdio>
 9 #include <windows.h>
10 
11 using namespace std;
12 
13 class CApiHook
14 {
15 private:
16     BOOL bStatus;        //    当前钩子状态
17     BOOL bSuspend;        //    当前钩子暂停状态
18     HMODULE hModule;    //    目标函数所在的动态链接库的句柄
19     LPVOID lpProc;        //    目标函数地址
20     LPVOID lpBaseAddr;    //    目标函数基地址
21     LPVOID lpNewProc;    //    新函数地址
22     BYTE bRawData[5];    //    目标函数原数据
23     BYTE bJMPStmt[5];    //    JMP指令语句
24     
25     BOOL WriteData(LPCVOID lpBuffer);    //    将缓冲区内容写入目标函数地址
26 
27 public:
28     CApiHook();
29     ~CApiHook();
30 
31     BOOL Install(LPCSTR szModuleName, LPCSTR szProcName, FARPROC pNewProc);    //    初始化钩子
32     BOOL Suspend();    //    暂停钩子
33     BOOL Resume();    //    恢复钩子
34     BOOL Uninstall();    //    卸载钩子
35 
36     BOOL GetHookStatus();
37 };
38 
39 BOOL GetProcHookStatus(LPCSTR lpModuleName, LPCSTR lpProcName);    //    获取目标函数的钩子状态
40 
41 #endif    //    __CAPIHOOK_H__
CApiHook.h

 

  1 //    CApiHook, Last Code By gwsbhqt@163.com At 20151208
  2 
  3 #include "CApiHook.h"
  4 
  5 CApiHook::CApiHook()
  6 {
  7     memset(this, 0, sizeof(CApiHook));
  8 }
  9 
 10 CApiHook::~CApiHook()
 11 {
 12     if (bStatus)
 13         Uninstall();
 14 }
 15 
 16 //    将缓冲区内容写入目标函数地址
 17 BOOL CApiHook::WriteData(LPCVOID lpBuffer)
 18 {
 19     //    更改目标函数基地址的保护状态为可读写
 20     DWORD dwOldProtect;
 21     if (!VirtualProtectEx(GetCurrentProcess(), lpBaseAddr, 5, PAGE_READWRITE, &dwOldProtect))
 22         return FALSE;
 23 
 24     //    将缓冲区内容写入目标函数地址
 25     if (!WriteProcessMemory(GetCurrentProcess(), lpProc, lpBuffer, 5, NULL))
 26         return FALSE;
 27 
 28     //    恢复目标函数基地址的保护状态
 29     if (!VirtualProtectEx(GetCurrentProcess(), lpBaseAddr, 5, dwOldProtect, &dwOldProtect))
 30         return FALSE;
 31 
 32     return TRUE;
 33 }
 34 
 35 //    初始化钩子
 36 BOOL CApiHook::Install(LPCSTR szModuleName, LPCSTR szProcName, FARPROC fpNewProc)
 37 {
 38     if (bStatus)
 39         return FALSE;
 40 
 41     //    获取目标函数所在的动态链接库的句柄
 42     hModule = GetModuleHandleA(szModuleName);
 43     if (NULL == hModule)
 44         hModule = LoadLibraryA(szModuleName);
 45     if (NULL == hModule)
 46         return FALSE;
 47 
 48     lpNewProc = (LPVOID)fpNewProc;    //    获取新函数地址
 49     lpProc = (LPVOID)GetProcAddress(hModule, szProcName);    //    获取目标函数地址
 50     if (NULL == lpNewProc || NULL == lpProc)
 51         return FALSE;
 52 
 53     //    获取并保存目标函数地址的原数据
 54     RtlMoveMemory(bRawData, lpProc, 5);
 55 
 56     //    构造JMP指令语句
 57     bJMPStmt[0] = 0xE9;    //    JMP指令
 58     *((PDWORD)(&(bJMPStmt[1]))) = (DWORD)lpNewProc - (DWORD)lpProc - 5;
 59 
 60     //    获取目标函数基地址
 61     MEMORY_BASIC_INFORMATION mbi = {};
 62     if (sizeof(mbi) != VirtualQueryEx(GetCurrentProcess(), lpProc, &mbi, sizeof(mbi)))
 63         return FALSE;
 64     lpBaseAddr = mbi.BaseAddress;
 65 
 66     //    将JMP指令语句写入目标函数地址
 67     if (!WriteData(bJMPStmt))
 68         return FALSE;
 69 
 70     bStatus = TRUE;
 71 
 72     return TRUE;
 73 }
 74 
 75 //    暂停钩子
 76 BOOL CApiHook::Suspend()
 77 {
 78     if (!bStatus || bSuspend)
 79         return FALSE;
 80 
 81     //    将目标函数原数据写入目标函数地址
 82     BOOL ret = WriteData(bRawData);
 83     if (!ret)
 84         return FALSE;
 85 
 86     bSuspend = TRUE;
 87 
 88     return TRUE;
 89 }
 90 
 91 //    恢复钩子
 92 BOOL CApiHook::Resume()
 93 {
 94     if (!bStatus || !bSuspend)
 95         return FALSE;
 96 
 97     //    将JMP指令语句写入目标函数地址
 98     BOOL ret = WriteData(bJMPStmt);
 99     if (!ret)
100         return FALSE;
101 
102     bSuspend = FALSE;
103 
104     return TRUE;
105 }
106 
107 //    卸载钩子
108 BOOL CApiHook::Uninstall()
109 {
110     if (!bStatus)
111         return FALSE;
112 
113     //    将目标函数原数据写入目标函数地址
114     if (!WriteData(bRawData))
115         return FALSE;
116 
117     if (hModule != NULL)
118         FreeLibrary(hModule);
119     memset(this, 0, sizeof(*this));
120 
121     return TRUE;
122 }
123 
124 BOOL CApiHook::GetHookStatus()
125 {
126     return bStatus;
127 }
128 
129 //    获取目标函数的钩子状态
130 //    该函数暂仅对在WinXPx86/Win7x86/Win7x64/Win8.1x64下的ntdll.dll/kernel32.dll/user32.dll负责
131 BOOL GetProcHookStatus(LPCSTR lpModuleName, LPCSTR lpProcName)
132 {
133     //    获取目标函数所在的动态链接库的句柄
134     HMODULE hModule = GetModuleHandleA(lpModuleName);
135     if (hModule == NULL)
136         hModule = LoadLibraryA(lpModuleName);
137     if (hModule == NULL)
138         return ERROR;
139 
140     //    获取目标函数的地址
141     FARPROC fpProc = GetProcAddress(hModule, lpProcName);
142     if (fpProc == NULL)
143         return ERROR;
144 
145     //    获取目标函数地址的前7字节
146     BYTE buf[7] = {};
147     if (!ReadProcessMemory(GetCurrentProcess(), fpProc, &buf, 7, NULL))
148         return ERROR;
149 
150     /*
151     E9
152     B8 XX XX XX XX FF E0
153 
154     例外
155     E9 XX XX XX 00
156     E9 XX XX XX FA
157     E9 XX XX XX FC
158     E9 XX XX XX FF
159     E9 XX XX XX XX 90
160     */
161 
162     //    判断前7字节是否存在JMP/MOV指令语句并排除例外
163     if ((buf[0] == 0xB8 && buf[5] == 0xFF && buf[6] == 0xE0) ||
164         (buf[0] == 0xE9 && buf[4] != 0x00 && buf[4] != 0xFA && buf[4] != 0xFC && buf[4] != 0xFF && buf[5] != 0x90))
165         return TRUE;
166 
167     return FALSE;
168 }
CApiHook.cpp

 

 1 #include <cstdio>
 2 #include <windows.h>
 3 
 4 #include "CApiHook.h"
 5 
 6 CApiHook HookMessageBoxA;
 7 
 8 int WINAPI NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
 9 {
10     printf("PAY ATTENTION!! FOUND CALLING : MessageBoxA(%d, \"%s\", \"%s\", %d)\n", hWnd, lpText, lpCaption, uType);
11 
12     char cText[MAX_PATH];
13     strcpy(cText, lpText);
14     strcat(cText, " [Hijack]");
15 
16     char cCaption[MAX_PATH];
17     strcpy(cCaption, lpCaption);
18     strcat(cCaption, " [Hijack]");
19 
20     HookMessageBoxA.Suspend();
21 
22     int ret = MessageBoxA(NULL, cText, cCaption, MB_ICONERROR);
23 
24     HookMessageBoxA.Resume();
25 
26     return ret;
27 }
28 
29 int main()
30 {
31     MessageBoxA(NULL, "Text1", "Caption1", MB_ICONINFORMATION);
32 
33     printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
34     HookMessageBoxA.Install("User32.dll", "MessageBoxA", (FARPROC)NewMessageBoxA);
35     printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
36 
37     MessageBoxA(NULL, "Text2", "Caption2", MB_ICONINFORMATION);
38 
39     printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
40     HookMessageBoxA.Uninstall();
41     printf("MessageBoxA Hook Status: %s\n", GetApiHookStatus("User32.dll", "MessageBoxA") ? "YES" : "NO");
42 
43     MessageBoxA(NULL, "Text3", "Caption3", MB_ICONINFORMATION);
44 
45     system("pause > nul");
46     return 0;
47 }
main.cpp

 

posted on 2015-07-01 04:49  gwsbhqt  阅读(578)  评论(0编辑  收藏  举报