首页
社区
课程
招聘
[讨论][讨论]对键盘钩子函数的简单测试和遇到的问题
发表于: 2010-5-23 02:28 6012

[讨论][讨论]对键盘钩子函数的简单测试和遇到的问题

2010-5-23 02:28
6012
对键盘钩子函数的简单测试和遇到的问题
2010.5.22~2010.5.23
键盘钩子的callback函数:
 
LRESULT CALLBACK KeyDownProc(
       int code,       // hook code
       WPARAM wParam,  // virtual-key code
       LPARAM lParam   // keystroke-message information
        )

   当键盘按键之后,键盘钩子的回调函数到底会被调用几次呢?罗云彬的书上说,“对于每个击键动作,钩子回调函数会在键按下和释放的时候被掉调用两次”。但是我通过对lparam的位31进行测试,屏蔽掉键释放之后还是发现回调函数有时候会被调用了两次。查看网上的资料,对这个问题都没有很好的解释。几个月前,学习得很匆忙,仅仅测试code是否为HC_ACTION,虽然使显示达到目标,但是其中的道理并不明白。今天又偶然遇上了这个问题,觉得应该深入的理解,于是测试了好长一段时间。
一、如果只判断HC_ACTION
   会被hook两次。第一次获取到字符,第二次获取不到字符。

图 1只判断code为HC_ACTION
   也就是说虽然用HC_ACTION作为判断条件可以成功的使字符不重复,但是它还是获取了两次字符,只不过第二次获取的是空字符,所以没有显示出来。
  测试结果:第一次弹出‘a’,是因为WM_KEYDOWN,GetKeyboardState获取了按下的键,转换之后,显示出来'a'。第二次弹出空,是因为WM_KEYUP,GetKeyboardState获取的是按下状态的值,所以当按键弹起之后,获取的是都是空值,所以弹出的消息框没有字符。
 二、如果只判断位31(0序)
   按照书上的说法,这样判断是可以达到不重复的目的的,但是实践的时候却有问题,这也是为什么之前学习的时候,要改用判断是否为HC_ACTION的原因。

图 2键盘钩子回调函数被调用两次
   有时候回调函数会被调用两次。多次测试发现,有的编辑框如:DOC、TXT、一些网页的登陆,不会出现回调函数被调用两次。而一些IM工具如校内网、QQ,回调函数都会被调用两次,百度Hi有时候会,有时候不会,好像是随机的,很奇怪……为什么会有这种情况发生?
   发现回调函数被调用两次的,一次code为HC_ACTION,一次为HC_NOREMOVE。也就是说,之所以处理了按键的按下和释放之后,还会有回调函数被调用两次的问题,是因为没有判断code。键盘钩子的回调函数被调用了两次,code是有先后关系的,HC_ACTION先HC_NOREMOVE后。HC_ACTION跟HC_NOREMOVE的资料可以查看MSDN中的KeyboardProc 函数。
   所以,如果要使钩子的回调函数不被重复调用,必须判断code和lparam参数。
   在网上一些资料有的只判断了lparam,有的只判断了code,这样都是不好的。也有一些资料是都判断了的,但是没有讲清楚原因。很多的键盘钩子的代码在考虑会不会重复调用回调函数时,只强调了按键的按下跟弹起,书上的例子就是这样子。
   为什么有的IM工具的编辑框会出现键盘钩子回调函数被调用两次的情况呢?
没有逆向过,不知道它们是怎么实现的,所以也只能猜测了。可能是这样子的:当按下键之后,产生了WM_KEYDOWN和WM_KEYUP,这两个都是HC_ACTION类型的。然后IM程序用PeekMessage“偷看”了一眼跟键盘相关的消息,之后显示到编辑框上。这里还有个问题,当在钩子的回调函数里边添加个没特殊意义的MessageBox,IM工具的编辑框就没法得到字符了。难道是时间的问题,去掉Messagebox,在钩子回调函数中加了个sleep函数,发现可以显示到编辑框。把sleep函数跟Messagebox都加上去,又发现了另外一个问题,把sleep只跟HC_NOREMOVE对应,当程序还是等了一会儿才弹出消息框。似乎HC_ACTION和HC_NOREMOVE出现的先后关系跟之前发现的不一样了,HC_NOREMOVE先,HC_ACTION后,真是不可思议。越想深入思考,越混乱。
   很混乱,很多都是模棱两可,但是有一点可以确定,当用Messagebox函数阻塞PeekMessage,QQ的编辑框是不会显示出字符的。但这又不是PeekMessage滞留的时间太长导致的,因为用sleep停了很长一段时间,字符还是会显示到QQ的编辑框上。
留下了几个问题:
   1、回调函数被调用两次,它的参数,HC_ACTION跟HC_NOREMOVE到底是哪个先出现?在非IM工具的编辑框中,通过Messagebox函数,发现是HC_ACTION先,那如何解释在HC_NOREMOVE对应的处理块加了Sleep函数之后,IM工具的编辑框会先“睡眠”。
   2、为什么弹出消息框之后,QQ的编辑框就不再显示字符了,这个跟PeekMessage是否关联,还是其他原因?
   3、为什么有的IM工具编辑框要采用PeekMessage,有的就不采用。有什么好处?
 
想不明白……

说明:
    测试的时候,是以罗云彬书第三版 第11章动态链接库和钩子 中的键盘钩子的例子为模板的。测试的时候需要改动的是钩子的回调函数部分。
HookProc proc _dwCode,_wParam,_lParam
local @szKeyState[256]:byte
 
invoke CallNextHookEx,hHook,_dwCode,_wParam,_lParam
.if _dwCode == HC_ACTION
invoke GetKeyboardState,addr @szKeyState
invoke GetKeyState,VK_SHIFT
mov @szKeyState + VK_SHIFT,al
mov ecx,_lParam
shr ecx,16
invoke ToAscii,_wParam,ecx,addr @szKeyState,addr szAscii,0
mov byte ptr szAscii [eax],0
invoke SendMessage,hWnd,dwMessage,dword ptr szAscii,NULL
;invoke MessageBox,0,0,0,0
.endif
;.if _dwCode == HC_NOREMOVE
;invoke Sleep,5000;
;invoke MessageBox,0,0,0,2
; .endif
xor eax,eax
ret
HookProc endp

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 209
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
自然是程序作者故意调用你的钩子的
2010-5-23 11:54
0
游客
登录 | 注册 方可回帖
返回
//