绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
Windows键盘驱动结构与消息机制--转
2020-01-10 17:55:04



这里需要特别提出的一个函数是KeyboardClassServiceCallback,这个函数是kbdclass一层的callback,下层设备驱动的所有返回值都需要经过它。所以,如果钩子挂到这里,那么理论上所有的输入都可以被拦截的,已经亲自测试过网银控件的密码会在此被泄露,但QQ不会,QQ2013会启动失败,估计是检查了这个驱动。

顺便说一句,早期的QQ加密没那么恐怖,但它是启动一个线程不停的SetWindowHook,使得自己的hook永远在个,然后过滤掉所有的消息防止被人监听。后来的QQ可能是修改IDT里的键盘中断实现的。

当然病毒也可以通过filter驱动注入到kbdclass和port驱动之间,来实现监听键盘,这也是一种常见的情况。

所以,一个按键的消息产生流程如下:

1)硬件中断/硬件端口数据
//WinIO能模拟,或者修改IDT是在这一层
2)键盘Port驱动(USB or PS/2)
//Filter驱动在此
//KeyboardClassServiceCallback也在这一层被调用
3)kbdclass驱动
//处理键盘布局和键盘语言
4)Windows内核边界(zwCreate/zwReadFile)
----------------------(系统调用)----------------------
5)Windows内核边界(zwCreate/zwReadFile)
6)csrss.exe的win32k!RawInputThread读取,完成scancode和vk的转换
//SetWindowHook工作在这里(全局)
//kbd_event工作在这里
7)csrss.exe调用DispatchMessage等函数分发消息
//SetWindowHook工作在这里(进程)
//PostMessage和SendMessage在这里
8)各个进程处理消息

WinIO这个驱动比较特殊,它提供接口可以允许应用层直接写端口,但只能写PS/2端口,所以有些模拟按键程序通过WinIO来模拟按键。

对于标准的程序,PostMessage等函数可以完成模拟,但对于不太标准的软件,只能用kbd_event来模拟,但有些软件(如网银控件)就只能在更靠近内核的区域模拟了。

同时,有一种输入是很特殊的,就是DirectInput,这是DirectX提供的一种方法,大型游戏中很常见的用法,因为DirectInput的输入速度很快,绕过了消息层。但对于这种软件,在kbdclass一层甚至都无法模拟。目前还不确定DirectInput工作在哪一层,猜测可能是在kbdclass和port驱动之间,也许是一种filter驱动。对于这种输入方法,可以WinIO来模拟,但对于USB键盘则没有办法。

Windows提供了一套API:SendInput,这个驱动发送按键消息时有两种类型,一种是VK模式的,实际上跟kbd_event一样,工作在csrss这一层,而另一种是ScanCode模式,MSDN里有这样的描述:

Windows 2000/XP: Set the KEYEVENTF_SCANCODE flag to define keyboard input in terms of the scan code. This is useful to simulate a physical keystroke regardless of which keyboard is currently being used. 

可以看出,这是能够模拟更底层的按键的,理论上说是可以模拟DirectInput的按键的,实际测试也是这样,但文档中没有说明在vista以后的版本是什么状态,所以暂时也无法知道在WIN7里的工作情况。

架构师日常笔记

分享好友

分享这个小栈给你的朋友们,一起进步吧。

运维部落
创建时间:2019-09-15 22:54:27
关于运维,你想知道的,这里都有
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • stanleylst
    栈主

小栈成员

查看更多
  • 小尾巴鱼
  • Cyj_me
  • lpysky
  • 栈栈
戳我,来吐槽~