0%

使用SetWindowsHookEx监控窗口消息(1)

前言

使用 ShellHook 监控窗口消息不需要注入DLL,但是存在着无法抓取子窗口的缺陷,
所以这里使用 SetWindowsHookEx 注入DLL的方式来监控 WH_CBT 消息。

HOOK代码实现

关于 SetWindowsHookEx 的用法,在 低级键盘钩子 文章中曾经介绍过,这里直接给出代码,
注意32位DLL只能注入到32位程序中,64位DLL只能注入到64位程序中,所以在64位系统中,
如果想要监控所有的程序,需要32位程序和64位程序都要进行DLL注入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// DLL中的共享数据块
#pragma data_seg(".shared")
HHOOK g_hHook = NULL;
BOOL g_bEnable = FALSE; // 是否启用
#pragma data_seg()
#pragma comment(linker, "/section:.shared,rws")
// HOOK的回调函数
LRESULT CALLBACK CbtHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// 窗口激活消息
if ((g_bEnable) && (nCode == HCBT_ACTIVATE))
{
char szTitle[260] = { 0 };
GetWindowText((HWND)wParam, szTitle, 512);
if (strcmp(szTitle, "Internet 协议 (TCP/IP) 属性") == 0)
{
// 关闭指定的窗口
SendMessage((HWND)wParam, WM_CLOSE, NULL, NULL);
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
// 注册HOOK
BOOL SetHookDll()
{
g_hHook = SetWindowsHookEx(
WH_CBT, CbtHookProc, (HINSTANCE)GetModuleHandle("CbtHook.dll"), 0);
if (g_hHook == NULL) return FALSE;
return TRUE;
}
// 卸载HOOK
BOOL UnHookDll()
{
return UnhookWindowsHookEx(g_hHook);
}

WM_CBT消息

WM_CBT 中监控各种窗口行为,如果Code值小于0,则必须调用 CallNextHookEx 继续传递消息。

1
2
3
4
5
6
7
8
9
10
11
// CBT Hook Codes
#define HCBT_MOVESIZE 0
#define HCBT_MINMAX 1
#define HCBT_QS 2
#define HCBT_CREATEWND 3
#define HCBT_DESTROYWND 4
#define HCBT_ACTIVATE 5
#define HCBT_CLICKSKIPPED 6
#define HCBT_KEYSKIPPED 7
#define HCBT_SYSCOMMAND 8
#define HCBT_SETFOCUS 9

在如下几种行为中,可以通过返回 0值 来允许本次操作,返回 1值 来阻止本次操作。

1
2
3
4
5
6
7
HCBT_ACTIVATE    (5)
HCBT_CREATEWND (3)
HCBT_DESTROYWND (4)
HCBT_MINMAX (1)
HCBT_MOVESIZE (0)
HCBT_SETFOCUS (9)
HCBT_SYSCOMMAND (8)

更多的信息可以通过如下链接来了解:
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644977(v=vs.85)