首页
论坛
课程
招聘
雪    币: 261
活跃值: 活跃值 (16)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝

[原创]通用键盘鼠标模拟(包括USB和PS2)

2009-11-21 02:28 36304

[原创]通用键盘鼠标模拟(包括USB和PS2)

2009-11-21 02:28
36304
通过直接调用Kbdclass的回调函数KeyboardClassServiceCallback直接给上层发送键盘驱动。这个方法网上已经公开,参考Hook KeyboardClassServiceCallback实现键盘 Logger,其他的还有很多,可以到网上去查。

简单说一下没有公开的部分,就是按下和松开的模拟,已经扩展键的模拟。

模拟主要是构造KEYBOARD_INPUT_DATA结构,按下和松开的Flags分别对应KEY_MAKE、KEY_BREAK,然后调用KeyboardClassServiceCallback。这里直接用的sudami的代码,在此谢过,懒得改了。代码如下:

case IOCTL_KEY_DOWN :
  {
   if (ioBuf)
   {
    lKeyCode = *(ULONG*)ioBuf;
    dprintf("[KeyMouse] KeymouseDispatchDeviceControl IOCTL_KEY_DOWN = 0x%x\n", lKeyCode);
    dwSize = sizeof(KEYBOARD_INPUT_DATA);
    __asm {
     push eax
      mov kid.UnitId,0  ; 构造 KEYBOARD_INPUT_DATA
      mov eax,lKeyCode
      mov kid.MakeCode,ax
      mov kid.Flags,KEY_MAKE ;模拟按下
      mov kid.Reserved,0
      mov kid.ExtraInformation,0

      lea eax,dwRet
      push eax
      lea eax,kid
      add eax,dwSize
      push eax
      lea eax,kid
      push eax
      push g_kbDeviceObject
      call orig_KeyboardClassServiceCallback ;利用 KeyboardClassServiceCallback 模拟按键

      pop eax
    }   
    status = STATUS_SUCCESS;
   }
   break;
  }
case IOCTL_KEY_UP:
  {
   if (ioBuf)
   {
    lKeyCode = *(ULONG*)ioBuf;
    dprintf("[KeyMouse] KeymouseDispatchDeviceControl IOCTL_KEY_UP = 0x%x\n", lKeyCode);
    dwSize = sizeof(KEYBOARD_INPUT_DATA);
    __asm {
     push eax
      mov kid.UnitId,0  ; 构造 KEYBOARD_INPUT_DATA
      mov eax,lKeyCode
      mov kid.MakeCode,ax
      mov kid.Flags,KEY_BREAK ;模拟松开
      mov kid.Reserved,0
      mov kid.ExtraInformation,0

      lea eax,dwRet
      push eax
      lea eax,kid
      add eax,dwSize
      push eax
      lea eax,kid
      push eax
      push g_kbDeviceObject
      call orig_KeyboardClassServiceCallback ;利用 KeyboardClassServiceCallback 模拟按键

      pop eax
    }
    status = STATUS_SUCCESS;
   }   
   break;
  }

扩展键的区别是按下和松开的Flags分别对应KEY_E0、KEY_E1。其他和上面的一样,这里就不贴代码出来了。主要说一下扩展键有哪几个:(前面是MakeCode,后面代表按钮)

0x1D-RIGHT CONTROL  0x38-RIGHT ALT  0x48-↑ 键  0x50-↓ 键  0x4b-← 键  0x4d-→ 键 0x5B-LEFT WIN 0x5C-RIGHT WIN

重点说一下鼠标的模拟,原理和键盘的一样。查找驱动mouclass.sys中的MouseClassServiceCallback函数,然后获取\\Device\\PointerClass0设备对象指针,构造MOUSE_INPUT_DATA结构,然后调用MouseClassServiceCallback。难点就在与构造MOUSE_INPUT_DATA结构上面。

typedef struct _MOUSE_INPUT_DATA {
    USHORT UnitId;
    USHORT Flags;
    union {
        ULONG Buttons;
        struct  {
            USHORT  ButtonFlags;
            USHORT  ButtonData;
        };
    };
    ULONG RawButtons;
    LONG LastX;
    LONG LastY;
    ULONG ExtraInformation;
} MOUSE_INPUT_DATA, *PMOUSE_INPUT_DATA;

通过调试操作系统调用MouseClassServiceCallback的参数,主要的标示有3个。

Flags标志是标示鼠标的坐标属性(即相对坐标、绝对坐标等)

ButtonFlags标志是左右中键按下和松开的标志

LastX是鼠标X坐标,与Flags标志有关

LastY是鼠标Y坐标,与Flags标志有关

其他几项可以填0。

具体模拟代码如下:

case IOCTL_MOUSE_LEFT_BUTTON_DOWN:
  {
   MouseFlags = MOUSE_LEFT_BUTTON_DOWN;
   goto __MouseCallBack;
  }
case IOCTL_MOUSE_LEFT_BUTTON_UP:
  {
   MouseFlags = MOUSE_LEFT_BUTTON_UP;
   goto __MouseCallBack;
  }
case IOCTL_MOUSE_RIGHT_BUTTON_DOWN:
  {
   MouseFlags = MOUSE_RIGHT_BUTTON_DOWN;
   goto __MouseCallBack;
  }
case IOCTL_MOUSE_RIGHT_BUTTON_UP:
  {
   MouseFlags = MOUSE_RIGHT_BUTTON_UP;
   goto __MouseCallBack;
  }
case IOCTL_MOUSE_MIDDLE_BUTTON_DOWN:
  {
   MouseFlags = MOUSE_MIDDLE_BUTTON_DOWN;
   goto __MouseCallBack;
  }
case IOCTL_MOUSE_MIDDLE_BUTTON_UP:
  {
   MouseFlags = MOUSE_MIDDLE_BUTTON_UP;
__MouseCallBack:
   mid.UnitId = 0;
   mid.Flags = MOUSE_MOVE_RELATIVE;
   mid.Buttons = 0;
   mid.ButtonFlags = MouseFlags;
   mid.RawButtons = 0;
   mid.LastX = *((ULONG*)ioBuf);
   mid.LastY = *((ULONG*)ioBuf+1);
   mid.ExtraInformation = 0;

   InputDataStart = ∣
   InputDataEnd = InputDataStart+1;

   orig_MouseClassServiceCallback(
   g_mouDeviceObject,
   InputDataStart,
   InputDataEnd,
   &InputDataConsumed
   );

   status = STATUS_SUCCESS;
   break;
  }
case IOCTL_MOUSE_MOVE_RELATIVE:
  {
   mid.Flags = MOUSE_MOVE_RELATIVE; //相对坐标
   goto __MouseMoveCallBack;
  }
case IOCTL_MOUSE_MOVE_ABSOLUTE:
  {
   mid.Flags = MOUSE_MOVE_ABSOLUTE; //绝对坐标
   goto __MouseMoveCallBack;
  }
case IOCTL_MOUSE_VIRTUAL_DESKTOP:
  {
   mid.Flags = MOUSE_VIRTUAL_DESKTOP; //虚拟桌面
__MouseMoveCallBack:
   mid.UnitId = 1;  
   mid.Buttons = 0;

   mid.RawButtons = 0;
   mid.LastX = *((ULONG*)ioBuf);
   mid.LastY = *((ULONG*)ioBuf+1);
   mid.ExtraInformation = 0;

   InputDataStart = ∣
   InputDataEnd = InputDataStart+1;

   orig_MouseClassServiceCallback(
   g_mouDeviceObject,
   InputDataStart,
   InputDataEnd,
   &InputDataConsumed
   );
   status = STATUS_SUCCESS;
   break;
  }

驱动在windows XP SP2上测试通过。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mergerly/archive/2009/11/19/4838655.aspx

[看雪官方培训]《安卓高级研修班(网课)》9月班开始招生!顶尖技术、挑战极限、工资翻倍!

上传的附件:
最新回复 (24)
雪    币: 7063
活跃值: 活跃值 (21)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-11-21 07:04
2
0
支持一下~~
雪    币: 292
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
dplayer 活跃值 1 2009-11-21 09:10
3
0
希望讲解下..应用层与过滤驱动间的通信..
雪    币: 7063
活跃值: 活跃值 (21)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-11-21 10:24
4
0

过滤驱动有CDO也有FiDO,在DispatchRoutine里判断一下Device不就行了
雪    币: 292
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
dplayer 活跃值 1 2009-11-21 17:01
5
0
希望出个完整的代码...
我想可以得精华滴...因为我一直在蓝
雪    币: 7063
活跃值: 活跃值 (21)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-11-21 17:47
6
0
这个问题以前有人问过,而且别人的解答比我的更详细,我给你找找~
雪    币: 258
活跃值: 活跃值 (80)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
riusksk 活跃值 41 2009-11-21 19:03
7
0
支持一下~~
雪    币: 7063
活跃值: 活跃值 (21)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-11-21 19:51
8
0
http://bbs.pediy.com/showthread.php?t=98906
雪    币: 214
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
metalqiang 活跃值 2009-11-22 02:28
9
0
mark..
雪    币: 292
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
dplayer 活跃值 1 2009-11-22 10:04
10
0
严重感谢教主...
偶一直在应用->驱动->过滤驱动..但是不能很好的控制.特别是驱动创建可控IRP->过滤后通讯是蓝得天转地旋....
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
robar 活跃值 2009-11-23 09:50
11
0
下载学习去了
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qwertyzm 活跃值 2009-11-23 21:55
12
0
顶一下
雪    币: 306
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小原 活跃值 2009-11-27 04:58
13
0
以前写过一个类似的,但鼠标部分的实现出来问题,学习
雪    币: 441
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
叶xiang 活跃值 2009-12-8 15:07
14
0
学习呀,谢谢了!
雪    币: 2190
活跃值: 活跃值 (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
sisess 活跃值 1 2010-1-24 17:57
15
0
支持USB?很强
雪    币: 793
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
zyr零零发 活跃值 1 2010-1-25 00:07
16
0
正在学习驱动,感谢!
雪    币: 191
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
linyud 活跃值 2010-1-25 01:17
17
0
学习了。。。
雪    币: 466
活跃值: 活跃值 (11)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
fhurricane 活跃值 1 2010-1-25 08:29
18
0
好代码,研究一下了
雪    币: 3
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
icqking 活跃值 2010-2-1 19:14
19
0
谢谢分享..
雪    币: 3
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
icqking 活跃值 2010-2-1 19:15
20
0
好代码 .
谢谢分享
雪    币: 34
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
qoozon 活跃值 2010-3-1 13:39
22
0
这个,能被查出来吗?
雪    币: 2648
活跃值: 活跃值 (105)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
cvcvxk 活跃值 10 2010-3-3 14:47
23
0
这个没有anti~
雪    币: 373
活跃值: 活跃值 (18)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
lovesuae 活跃值 1 2010-3-6 20:59
24
0
严重支持,学习
雪    币: 7
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Mco令海 活跃值 2017-9-19 00:20
25
0
楼长...这个是不是必须要创建驱动设备啊?不创建call里面的unid填零,会蓝屏吗?
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
yanrkchina 活跃值 2020-7-6 15:05
26
0
请问一下,如果一个进程忽略了WM_MOUSEMOVE,而用的是WM_INPUT来处理鼠标移动信息,如何来模拟RAWINPUT信息呢?我尝试过自己构造RAWINPUT消息,通过PostMessage发送过去,但接受方在GetDeviceData (HRAWINPUT)的时候会失败,通过MSDN查看HRAWINPUT,发现其实现是隐藏了的。本想看驱动是否能解决,但是MOUSE_INPUT_DATA这个结构里面并没有指定接收窗口的字段。
游客
登录 | 注册 方可回帖
返回