分享
 
 
 

hook使用指南(一)

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

1.Hooks

hook指出了系统消息处理机制。利用hook,可以在应用程序中安装子程序监视系统和进程之间的消息传递,这个监视过程是在消息到达目的窗口过程之前。

下面简述hook,并且解释在Win32系统下,如何使用hook编程。

2.About Hooks

hook将使程序效率降低,因为它们增加了系统必须处理的消息总数。你应该在需要时才使用,并及时删除它。我将以下面的主题描述hook。

Hook Chains(hook链)

系统支持很多不同类型的hooks;不同的hook提供不同的消息处理机制。比如,应用程序可以使用WH_MOUSE_hook来监视鼠标消息的传递。

系统为不同类型的hook提供单独的hook链。hook链是一个指针列表,这个列表的指针指向指定的,应用程序定义的,被hook过程调用的回调函数。当与指定的hook类型关联的消息发生时,系统就把这个消息传递到hook过程。一些hook过程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个hook过程或者目的窗口。

Hook Procedures(hook过程)

为了利用特殊的hook类型,开发者提供了hook过程,使用SetWindowsHookEx函数来把hook过程安装到关联的hook链。hook过程必须按照以下的语法:

LRESULT CALLBACK HookProc(

int nCode,

WPARAM wParam,

LPARAM lParam

);

HookProc是应用程序定义的名字。

nCode参数是hook代码,hook过程使用这个参数来确定任务。这个参数的值依赖于hook类型,每一种hook都有自己的hook代码特征字符集。wParam和lParam参数的值依赖于hook代码,但是它们的典型值是包含了关于发送或者接收消息的信息。

SetWindowsHookEx函数总是在hook链的开头安装hook过程。当指定类型的hook监视的事件发生时,系统就调用与这个hook关联的hook链的开头的hook过程。每一个hook链中的hook过程都决定是否把这个事件传递到下一个hook过程。hook过程传递事件到下一个hook过程需要调用CallNextHookEx函数。

有些类型hook的hook过程只能监视消息,不管是否调用了CallNextHookEx函数,系统都把消息传递到每一个hook过程。

全局hook监视同一桌面的所有线程。而特定线程的hook只能监视单独的线程。全局hook过程可以被同一桌面的任何应用程序调用,就象调用线程一样,所以这个过程必须和DLL模块分开。特定线程hook过程只可以被相关线程调用。只有在有调试目的的时候才使用全局hook,应该避免使用,全局hook损害了系统性能。

Hook Types

每一种类型的hook可以使应用程序能够监视不同类型的系统消息处理机制。下面描述所有可以利用的hook类型。

WH_CALLWNDPROC and WH_CALLWNDPROCRET Hooks

WH_CALLWNDPROC and WH_CALLWNDPROCRET Hook使你可以监视发送到窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC hook过程,并且在窗口过程处理完消息之后调用WH_CALLWNDPROCRET Hook过程。

WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT结构,再传递到hook过程。CWPRETSTRUCT结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。

WH_CBT Hook

在以下事件之前,系统都会调用WH_CBT Hook过程,这些事件包括:激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;完成系统指令;来自系统消息队列中的移动鼠标,键盘事件;设置输入焦点事件;同步系统消息队列事件。hook过程的返回值确定系统是否允许或者防止这些操作中的一个。

WH_DEBUG Hook

在系统调用系统中与其他hook关联的hook过程之前,系统会调用WH_DEBUG Hook过程。你可以使用这个hook来决定是否允许系统调用与其他hook关联的hook过程。

WH_FOREGROUNDIDLE Hook

当应用程序的前景线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE Hook执行低优先级的任务。当应用程序的前景线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDLE Hook过程。

WH_GETMESSAGE Hook

应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。

WH_JOURNALPLAYBACK Hook

WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可以使用这个hook回放通过使用WH_JOURNALRECORD hook记录下来的连续的鼠标和键盘事件。只要WH_JOURNALPLAYBACK hook已经安装,正常的鼠标和键盘事件就是无效的。WH_JOURNALPLAYBACK hook是全局hook,它不能象线程特定hook一样使用。WH_JOURNALPLAYBACK hook返回超时值,这个值告诉系统在处理来自回放hook当前消息之前需要等待多长时间(毫秒)。这就使hook可以控制实时事件的回放。

WH_JOURNALRECORD Hook

WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这个hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook来回放。WH_JOURNALRECORD hook是全局hook,它不能象线程特定hook一样使用。

WH_KEYBOARD Hook

在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使用这个hook来监视输入到消息队列中的键盘消息。

WH_KEYBOARD_LL Hook

WH_KEYBOARD_LL Hook监视输入到线程消息队列中的键盘消息。

WH_MOUSE Hook

WH_MOUSE Hook监视从GetMessage or PeekMessage function返回的鼠标消息。使用这个hook监视输入到消息队列中的鼠标消息。

WH_MOUSE_LL Hook

WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标消息。

WH_MSGFILTER and WH_SYSMSGFILTER Hooks

WH_MSGFILTER and WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。WH_MSGFILTER hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通过安装了hook过程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook监视所有应用程序消息。

WH_MSGFILTER and WH_SYSMSGFILTER Hooks使我们可以在模式循环期间过滤消息,这等价于在主消息循环中过滤消息。

通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER hook。通过使用这个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循环里一样。

WH_SHELL Hook

外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook过程。

按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自己。

3.Using Hooks

Installing and Releasing Hook Procedures

可以使用SetWindowsHookEx function安装hook过程并且指定hook类型,指定是否需要把hook过程与所有线程关联,或者关联指定的线程,并且指向hook过程入口点。

必须把全局hook过程放进DLL,以和应用程序安装的hook过程分开。在应用程序安装hook过程之前,它必须有一个指向DLL模块的句柄。为了得到这个句柄,可以在调用LoadLibrary函数时使用DLL名字参数。在得到这个句柄以后,可以调用GetProcAddress函数来得到hook过程的指针。最后,使用SetWindowsHookEx函数安装hook过程地址进应用程序hook链。这个过程可以用下面的事例说明:

HOOKPROC hkprcSysMsg;

static HINSTANCE hinstDLL;

static HHOOK hhookSysMsg;

hinstDLL = LoadLibrary((LPCTSTR) "c:\\windows\\sysmsg.dll"); file://loading DLL

hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc"); file://get address

hhookSysMsg = SetWindowsHookEx(WH_SYSMSGFILTER,hkprcSysMsg,hinstDLL,0); file://install hook

当应用程序不再需要与特定线程相关hook时,需要调用UnhookWindowsHookEx函数删除相关的hook过程。对于全局hook,也需要调用UnhookWindowsHookEx函数,但是这个函数不能释放DLL包含的hook过程。这是因为全局hook过程是被所有应用程序进程调用的,这就导致了所有的进程都隐性的调用了LoadLibrary函数。所以必须调用FreeLibrary函数释放DLL。

Monitoring System Events

下面的例子使用了不同的特定线程hook过程去监视系统事件。它示范了怎样使用下面的hook过程去处理事件:

WH_CALLWNDPROC

WH_CBT

WH_DEBUG

WH_GETMESSAGE

WH_KEYBOARD

WH_MOUSE

WH_MSGFILTER

用户可以通过使用菜单安装或者移走hook过程。当hook过程已经安装并且过程监视的时间发生时,hook过程将在应用程序主窗口客户区写出事件信息。原代码如下:

#define NUMHOOKS 7

// Global variables

typedef struct _MYHOOKDATA

{

int nType;

HOOKPROC hkprc;

HHOOK hhook;

} MYHOOKDATA;

MYHOOKDATA myhookdata[NUMHOOKS];

LRESULT WINAPI MainWndProc(HWND hwndMain, UINT uMsg, WPARAM wParam,

LPARAM lParam)

{

static BOOL afHooks[NUMHOOKS];

int index;

static HMENU hmenu;

switch (uMsg)

{

case WM_CREATE:

// Save the menu handle.

hmenu = GetMenu(hwndMain);

// Initialize structures with hook data. The menu-item

// identifiers are defined as 0 through 6 in the

// header file. They can be used to identify array

// elements both here and during the WM_COMMAND

// message.

myhookdata[IDM_CALLWNDPROC].nType = WH_CALLWNDPROC;

myhookdata[IDM_CALLWNDPROC].hkprc = CallWndProc;

myhookdata[IDM_CBT].nType = WH_CBT;

myhookdata[IDM_CBT].hkprc = CBTProc;

myhookdata[IDM_DEBUG].nType = WH_DEBUG;

myhookdata[IDM_DEBUG].hkprc = DebugProc;

myhookdata[IDM_GETMESSAGE].nType = WH_GETMESSAGE;

myhookdata[IDM_GETMESSAGE].hkprc = GetMsgProc;

myhookdata[IDM_KEYBOARD].nType = WH_KEYBOARD;

myhookdata[IDM_KEYBOARD].hkprc = KeyboardProc;

myhookdata[IDM_MOUSE].nType = WH_MOUSE;

myhookdata[IDM_MOUSE].hkprc = MouseProc;

myhookdata[IDM_MSGFILTER].nType = WH_MSGFILTER;

myhookdata[IDM_MSGFILTER].hkprc = MessageProc;

// Initialize all flags in the array to FALSE.

memset(afHooks, FALSE, sizeof(afHooks));

return 0;

case WM_COMMAND:

switch (LOWORD(wParam))

{

// The user selected a hook command from the menu.

case IDM_CALLWNDPROC:

case IDM_CBT:

case IDM_DEBUG:

case IDM_GETMESSAGE:

case IDM_KEYBOARD:

case IDM_MOUSE:

case IDM_MSGFILTER:

// Use the menu-item identifier as an index

// into the array of structures with hook data.

index = LOWORD(wParam);

// If the selected type of hook procedure isn't

// installed yet, install it and check the

// associated menu item.

if (!afHooks[index])

{

myhookdata[index].hhook = SetWindowsHookEx(

myhookdata[index].nType,

myhookdata[index].hkprc,

(HINSTANCE) NULL, GetCurrentThreadId());

CheckMenuItem(hmenu, index,

MF_BYCOMMAND | MF_CHECKED);

afHooks[index] = TRUE;

}

// If the selected type of hook procedure is

// already installed, remove it and remove the

// check mark from the associated menu item.

else

{

UnhookWindowsHookEx(myhookdata[index].hhook);

CheckMenuItem(hmenu, index,

MF_BYCOMMAND | MF_UNCHECKED);

afHooks[index] = FALSE;

}

default:

return (DefWindowProc(hwndMain, uMsg, wParam,

lParam));

}

break;

//

// Process other messages.

//

default:

return DefWindowProc(hwndMain, uMsg, wParam, lParam);

}

return NULL;

}

/****************************************************************

WH_CALLWNDPROC hook procedure

****************************************************************/

LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)

{

CHAR szCWPBuf[256];

CHAR szMsg[16];

HDC hdc;

static int c = 0;

int cch;

if (nCode < 0) // do not process message

return CallNextHookEx(myhookdata[CALLWNDPROC].hhook, nCode,

wParam, lParam);

// Call an application-defined function that converts a message

// constant to a string and copies it to a buffer.

LookUpTheMessage((PMSG) lParam, szMsg);

hdc = GetDC(hwndMain);

switch (nCode)

{

case HC_ACTION:

cch = wsprintf(szCWPBuf,

"CALLWNDPROC - tsk: %ld, msg: %s, %d times ",

wParam, szMsg, c++);

TextOut(hdc, 2, 15, szCWPBuf, cch);

break;

default:

break;

}

ReleaseDC(hwndMain, hdc);

return CallNextHookEx(myhookdata[CALLWNDPROC].hhook, nCode,

wParam, lParam);

}

/****************************************************************

WH_GETMESSAGE hook procedure

****************************************************************/

LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)

{

CHAR szMSGBuf[256];

CHAR szRem[16];

CHAR szMsg[16];

HDC hdc;

static int c = 0;

int cch;

if (nCode < 0) // do not process message

return CallNextHookEx(myhookdata[GETMESSAGE].hhook, nCode,

wParam, lParam);

switch (nCode)

{

case HC_ACTION:

switch (wParam)

{

case PM_REMOVE:

lstrcpy(szRem, "PM_REMOVE");

break;

case PM_NOREMOVE:

lstrcpy(szRem, "PM_NOREMOVE");

break;

default:

lstrcpy(szRem, "Unknown");

break;

}

// Call an application-defined function that converts a

// message constant to a string and copies it to a

// buffer.

LookUpTheMessage((PMSG) lParam, szMsg);

hdc = GetDC(hwndMain);

cch = wsprintf(szMSGBuf,

"GETMESSAGE - wParam: %s, msg: %s, %d times ",

szRem, szMsg, c++);

TextOut(hdc, 2, 35, szMSGBuf, cch);

break;

default:

break;

}

ReleaseDC(hwndMain, hdc);

return CallNextHookEx(myhookdata[GETMESSAGE].hhook, nCode,

wParam, lParam);

}

/****************************************************************

WH_DEBUG hook procedure

****************************************************************/

LRESULT CALLBACK DebugProc(int nCode, WPARAM wParam, LPARAM lParam)

{

CHAR szBuf[128];

HDC hdc;

static int c = 0;

int cch;

if (nCode < 0) // do not process message

return CallNextHookEx(myhookdata[DEBUG].hhook, nCode,

wParam, lParam);

hdc = GetDC(hwndMain);

switch (nCode)

{

case HC_ACTION:

cch = wsprintf(szBuf,

"DEBUG - nCode: %d, tsk: %ld, %d times ",

nCode,wParam, c++);

TextOut(hdc, 2, 55, szBuf, cch);

break;

default:

break;

}

ReleaseDC(hwndMain, hdc);

return CallNextHookEx(myhookdata[DEBUG].hhook, nCode, wParam,

lParam);

}

/****************************************************************

WH_CBT hook procedure

****************************************************************/

LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)

{

CHAR szBuf[128];

CHAR szCode[128];

HDC hdc;

static int c = 0;

int cch;

if (nCode < 0) // do not process message

return CallNextHookEx(myhookdata[CBT].hhook, nCode, wParam,

lParam);

hdc = GetDC(hwndMain);

switch (nCode)

{

case HCBT_ACTIVATE:

lstrcpy(szCode, "HCBT_ACTIVATE");

break;

case HCBT_CLICKSKIPPED:

lstrcpy(szCode, "HCBT_CLICKSKIPPED");

break;

case HCBT_CREATEWND:

lstrcpy(szCode, "HCBT_CREATEWND");

break;

case HCBT_DESTROYWND:

lstrcpy(szCode, "HCBT_DESTROYWND");

break;

case HCBT_KEYSKIPPED:

lstrcpy(szCode, "HCBT_KEYSKIPPED");

break;

case HCBT_MINMAX:

lstrcpy(szCode, "HCBT_MINMAX");

break;

case HCBT_MOVESIZE:

lstrcpy(szCode, "HCBT_MOVESIZE");

break;

case HCBT_QS:

lstrcpy(szCode, "HCBT_QS");

break;

case HCBT_SETFOCUS:

lstrcpy(szCode, "HCBT_SETFOCUS");

break;

case HCBT_SYSCOMMAND:

lstrcpy(szCode, "HCBT_SYSCOMMAND");

break;

default:

lstrcpy(szCode, "Unknown");

break;

}

cch = wsprintf(szBuf, "CBT - nCode: %s, tsk: %ld, %d times ",

szCode, wParam, c++);

TextOut(hdc, 2, 75, szBuf, cch);

ReleaseDC(hwndMain, hdc);

return CallNextHookEx(myhookdata[CBT].hhook, nCode, wParam,

lParam);

}

/****************************************************************

WH_MOUSE hook procedure

****************************************************************/

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)

{

CHAR szBuf[128];

CHAR szMsg[16];

HDC hdc;

static int c = 0;

int cch;

if (nCode < 0) // do not process the message

return CallNextHookEx(myhookdata[MOUSE].hhook, nCode,

wParam, lParam);

// Call an application-defined function that converts a message

// constant to a string and copies it to a buffer.

LookUpTheMessage((PMSG) lParam, szMsg);

hdc = GetDC(hwndMain);

cch = wsprintf(szBuf,

"MOUSE - nCode: %d, msg: %s, x: %d, y: %d, %d times ",

nCode, szMsg, LOWORD(lParam), HIWORD(lParam), c++);

TextOut(hdc, 2, 95, szBuf, cch);

ReleaseDC(hwndMain, hdc);

return CallNextHookEx(myhookdata[MOUSE].hhook, nCode, wParam,

lParam);

}

/****************************************************************

WH_KEYBOARD hook procedure

****************************************************************/

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)

{

CHAR szBuf[128];

HDC hdc;

static int c = 0;

int cch;

if (nCode < 0) // do not process message

return CallNextHookEx(myhookdata[KEYBOARD].hhook, nCode,

wParam, lParam);

hdc = GetDC(hwndMain);

cch = wsprintf(szBuf, "KEYBOARD - nCode: %d, vk: %d, %d times ",

nCode, wParam, c++);

TextOut(hdc, 2, 115, szBuf, cch);

ReleaseDC(hwndMain, hdc);

return CallNextHookEx(myhookdata[KEYBOARD].hhook, nCode, wParam,

lParam);

}

/****************************************************************

WH_MSGFILTER hook procedure

****************************************************************/

LRESULT CALLBACK MessageProc(int nCode, WPARAM wParam, LPARAM lParam)

{

CHAR szBuf[128];

CHAR szMsg[16];

CHAR szCode[32];

HDC hdc;

static int c = 0;

int cch;

if (nCode < 0) // do not process message

return CallNextHookEx(myhookdata[MSGFILTER].hhook, nCode,

wParam, lParam);

switch (nCode)

{

case MSGF_DIALOGBOX:

lstrcpy(szCode, "MSGF_DIALOGBOX");

break;

case MSGF_MENU:

lstrcpy(szCode, "MSGF_MENU");

break;

case MSGF_SCROLLBAR:

lstrcpy(szCode, "MSGF_SCROLLBAR");

break;

default:

wsprintf(szCode, "Unknown: %d", nCode);

break;

}

// Call an application-defined function that converts a message

// constant to a string and copies it to a buffer.

LookUpTheMessage((PMSG) lParam, szMsg);

hdc = GetDC(hwndMain);

cch = wsprintf(szBuf,

"MSGFILTER nCode: %s, msg: %s, %d times ",

szCode, szMsg, c++);

TextOut(hdc, 2, 135, szBuf, cch);

ReleaseDC(hwndMain, hdc);

return CallNextHookEx(myhookdata[MSGFILTER].hhook, nCode,

wParam, lParam);

}

未完待续。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有