首页
论坛
课程
招聘
[原创]驱动中实现模拟键盘按键
2007-4-19 11:35 26207

[原创]驱动中实现模拟键盘按键

2007-4-19 11:35
26207
在ring3中实现模拟键盘按键有N^N种方式,比如SendInput()、keybd_event()……但在驱动中要怎么模拟呢?

1、写端口大法
#define defI8042_DATA_PORT ((PUCHAR)0x60)
#define defI8042_CTRL_PORT ((PUCHAR)0x64)
#define defOBUFFER_FULL 0x01

BOOLEAN
WaitForKeyboardWrite(VOID)
{
    INT i;
    UCHAR c;

    for (i = 0; i < 1000; ++i)
    {
        KeStallExecutionProcessor(50);
        c = READ_PORT_UCHAR(defI8042_CTRL_PORT);
        if ((c & defOBUFFER_FULL) == defOBUFFER_FULL)
            break;
    }

    return i ? TRUE : FALSE;
}

VOID PressKeyByScanCode(
    IN CONST BYTE ScanCode
)
{
    WRITE_PORT_UCHAR(defI8042_CTRL_PORT, 0xd2);

    WaitForKeyboardWrite();

    WRITE_PORT_UCHAR(defI8042_DATA_PORT, ScanCode);
}

搞定,简单易行!缺点是只对PS/2键盘有效,USB的就一边凉快去吧。

2、构造IRP大法
这个比较麻烦,而且由于某些原因,略……

3、调用KeyboardClassServiceCallback()大法
kbdclass驱动是在I8042prt和kbdhid这两个驱动之上的,所以直接调用它的KeyboardClassServiceCallback()是能对PS/2和USB同时生效的,由于某些原因偶也不想给出具体的代码来。大致指点一下方向:

KeyboaredClassServiceCallback函数的原型如下:

typedef VOID (* PFN_KeyboardClassServiceCallback)(
    IN PDEVICE_OBJECT DeviceObject,
    IN PKEYBOARD_INPUT_DATA InputDataStart,
    IN PKEYBOARD_INPUT_DATA InputDataEnd,
    IN OUT PULONG InputDataConsumed
    );

第一个参数DeviceObject是kbdclass的DeviceObject,怎么得到它呢?思路:先找到kbdclass的DriverObject,然后从DriverObject得到DeviceObject。
第二和第三个参数是KEYBOARD_INPUT_DATA,自己填充,想模拟什么按键就写什么MakeCode和Flags吧。注意第三个参数应该为第二个参数的指针地址值+1。
第四个参数,随便弄个ULONG型的变量给它就行了,反正是可以丢弃的。(I8042prt里面用到了它,但我们自己的模拟按键不用也行)

缺点:每个系统的kbdclass.sys中的KeyboardClassServiceCallback的RVA都不相同,要自己hardcode一下,不过写驱动本来就是那么麻烦,习惯了就好。

看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

收藏
点赞0
打赏
分享
最新回复 (28)
雪    币: 200
活跃值: 活跃值 (29)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
Lvg 活跃值 5 2007-4-19 11:48
2
0
最后一个方法强,学习了
雪    币: 200
活跃值: 活跃值 (18)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
shoooo 活跃值 16 2007-4-19 11:51
3
0
学习一下
123456
雪    币: 4656
活跃值: 活跃值 (11835)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2007-4-19 11:53
4
0
现在老罗很忙,难得来泡坛了
雪    币: 219
活跃值: 活跃值 (59)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
foxabu 活跃值 13 2007-4-19 12:54
5
0
常用的貌似还是WinIo 模拟。
不过我觉得还是挂钩屏蔽PS/2 伪造一个USB的Input设备 来实现输入比较好。不过貌似很复杂
雪    币: 195
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
aki 活跃值 2 2007-4-19 13:36
6
0
刚在你blog上看到,就帖这里来了。另外你的调用xp隐藏赛车游戏的方法蛮好用的,
win+u+u
雪    币: 304
活跃值: 活跃值 (46)
能力值: ( LV13,RANK:330 )
在线值:
发帖
回帖
粉丝
HSQ 活跃值 8 2007-4-19 20:47
7
0
谈到写驱动总是有些胆怯,相关资料比较少.
雪    币: 246
活跃值: 活跃值 (11)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
Isaiah 活跃值 10 2007-4-20 02:45
8
0
学习~
驱动模拟才是王道。。
对于游戏,直接hook Dinput也能有效,不过属于旁门左道。。
雪    币: 2071
活跃值: 活跃值 (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
Aker 活跃值 4 2007-4-20 08:44
9
0
罗大虾是难得看到了,学习...........
雪    币: 206
活跃值: 活跃值 (55)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
云重 活跃值 1 2007-4-20 19:40
10
0
这就是传说中的罗聪大侠,
不过没必要做这么麻烦,方法实在太多了
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
仙剑太郎 活跃值 2 2007-4-20 21:37
11
0
大侠浮上水面了...
雪    币: 216
活跃值: 活跃值 (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
berglob 活跃值 3 2007-4-20 23:17
12
0
学习!
雪    币: 205
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
scship 活跃值 2007-4-21 01:17
13
0
师兄我下午还去你的blog留言
晚上来看雪就看了。。。
来迟了。。。
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
colboy 活跃值 2007-4-21 12:22
14
0
学习`~~~!!!!!!!!!!1
雪    币: 106
活跃值: 活跃值 (366)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
nbw 活跃值 24 2007-4-21 22:12
15
0
我看了罗老的blog有这篇文章,正要来这里举报,没想到这个也是罗老,难道素同一个人?
雪    币: 243
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:410 )
在线值:
发帖
回帖
粉丝
王仁军 活跃值 10 2007-5-14 13:23
16
0
久闻大名,今日得见
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
beeve 活跃值 2007-5-14 15:53
17
0
值得学习,,好好研究下,
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ohmyzi 活跃值 2007-5-14 16:33
18
0
好文章 收藏了 慢慢学习
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SoulEdge 活跃值 2007-5-15 06:46
19
0
受教了,收下
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
humanlili 活跃值 2007-5-15 14:49
20
0
强人啊!学习了
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
humanlili 活跃值 2007-5-15 14:50
21
0
学习了。THANKS
雪    币: 217
活跃值: 活跃值 (52)
能力值: ( LV9,RANK:1210 )
在线值:
发帖
回帖
粉丝
softworm 活跃值 30 2007-5-15 19:34
22
0
看来搞游戏是大势所趋呀
雪    币: 119
活跃值: 活跃值 (207)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
Lenus 活跃值 3 2007-5-15 20:52
23
0
来晚了...老大的帖子不能不支持!!
雪    币: 1901
活跃值: 活跃值 (1068)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 活跃值 2007-5-26 02:03
24
0
收藏!!!!!!!!!!!!!!
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cngage 活跃值 2007-5-26 09:57
25
0
关于写端口部分,不知道楼住从哪里找的代码,写错了吧。
BOOLEAN
WaitForKeyboardWrite(VOID)
{
    INT i;
    UCHAR c;

    for (i = 0; i < 1000; ++i)
    {
        KeStallExecutionProcessor(50);
        c = READ_PORT_UCHAR(defI8042_CTRL_PORT);
        if ((c & defOBUFFER_FULL) == defOBUFFER_FULL)
            break;
    }

    return i ? TRUE : FALSE;
}

判断状态寄存器是否为空,判断条件应该是
if ((c & 0x02)==0)
下面这句判断出的结果是输出buffer为满的情况
if ((c & defOBUFFER_FULL) == defOBUFFER_FULL)
游客
登录 | 注册 方可回帖
返回