同样的键盘钩子,只有KeyboardProc不一样
程序1 是
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int i = CallNextHookEx(g_hhook, nCode, wParam ,lParam);
CString str;
str.Format("i's value !!! %d",i);
AfxMessageBox(str);
return 0;
}
程序2 是
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int i = CallNextHookEx(g_hhook, nCode, wParam ,lParam);
CString str;
str.Format("i's value %d",i);
AfxMessageBox(str);
return 1;
}
1、如果只启动程序1
键入字母m效果是:
i's value !!! 0;
i's value !!! 0;
在记事本显示:m
2、如果只启动程序2
键入字母m效果是:
i's value 0;
i's value 0;
1、如果先启动程序1,再启动程序2。
键入字母m效果是:
i's value !!! 0;
i's value 0;
i's value !!! 0;
i's value 0;
2、如果先启动程序2,再启动程序1。
键入字母m效果是:
i's value 0;
i's value !!! 1;
i's value 0;
i's value !!! 1;
在记事本显示:m
解释:
1、消息成对出现是因为:按一次键,将产生KEY_UP 和KEY_DOWN的两个键盘消息,两者都将被视为:WH_KEYBOARD消息。
2、后挂的钩子在钩子链的最顶端(后加入的钩子加在原来存在的钩子的前面。后加入的钩子先获得消息)。
3、当CallNextHookEx的时候会执行钩子链的下一个hook函数,CallNextHookEx将返回一个值,如果是0表示成功,如果是1表示失败。
4、消息并不是从 顶端hook函数 --> 底端hook 函数 --> 系统 传递的。一般情况下(钩子函数的形式如下,通常的钩子函数形式也是这样的)
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(g_hhook, nCode, wParam ,lParam);
}
执行hook函数是一个递归的过程:
顶端(n)hook函数 --> (n-1)hook函数 -> (n-2)hook函数 -> (n-i)hook函数 -> (1) hook函数
|------<----| |------<----| |------<----| |------<----|
5、如果在一个钩子函数中使用return 1,或者 return 0 ,那么这个返回值将是上层钩子函数调用CallNextHookEx的返回值。
6、现在关注顶端hook函数:
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// doing something
return CallNextHookEx(g_hhook, nCode, wParam ,lParam);
}
如果CallNextHookEx(g_hhook, nCode, wParam ,lParam);的返回值是1,那么消息不会被传递给系统来处理。(返回值为1的出现的情况:a,在钩子链中使用过return1, b,系统传递钩子消息失败)如果CallNextHookEx(g_hhook, nCode, wParam ,lParam);的返回值是0,那么消息将经过钩子链以后再传递给系统来处理。
7、做一个扩展假设,如果使用下面的钩子函数,并且该钩子函数在钩子链的顶端
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return 0;
}
那么键盘消息将不会传递给钩子链上的其他钩子函数,而直接传递给系统。那么如果这个钩子函数在hook chain的最顶端,那么它就可以屏蔽掉有键盘记录功能的木马或者外挂。