首页
社区
课程
招聘
[原创]通用键盘鼠标模拟(包括USB和PS2)
发表于: 2009-11-21 02:28 43597

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

2009-11-21 02:28
43597

通过直接调用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


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 8
支持
分享
最新回复 (25)
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
支持一下~~
2009-11-21 07:04
0
雪    币: 306
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
希望讲解下..应用层与过滤驱动间的通信..
2009-11-21 09:10
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4

过滤驱动有CDO也有FiDO,在DispatchRoutine里判断一下Device不就行了
2009-11-21 10:24
0
雪    币: 306
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
希望出个完整的代码...
我想可以得精华滴...因为我一直在蓝
2009-11-21 17:01
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
6
这个问题以前有人问过,而且别人的解答比我的更详细,我给你找找~
2009-11-21 17:47
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
7
支持一下~~
2009-11-21 19:03
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
8
http://bbs.pediy.com/showthread.php?t=98906
2009-11-21 19:51
0
雪    币: 220
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
mark..
2009-11-22 02:28
0
雪    币: 306
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
严重感谢教主...
偶一直在应用->驱动->过滤驱动..但是不能很好的控制.特别是驱动创建可控IRP->过滤后通讯是蓝得天转地旋....
2009-11-22 10:04
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
下载学习去了
2009-11-23 09:50
0
雪    币: 211
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
顶一下
2009-11-23 21:55
0
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
以前写过一个类似的,但鼠标部分的实现出来问题,学习
2009-11-27 04:58
0
雪    币: 445
活跃值: (52)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
学习呀,谢谢了!
2009-12-8 15:07
0
雪    币: 8216
活跃值: (3887)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
15
支持USB?很强
2010-1-24 17:57
0
雪    币: 808
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
16
正在学习驱动,感谢!
2010-1-25 00:07
0
雪    币: 199
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
17
学习了。。。
2010-1-25 01:17
0
雪    币: 492
活跃值: (53)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
18
好代码,研究一下了
2010-1-25 08:29
0
雪    币: 138
活跃值: (461)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
谢谢分享..
2010-2-1 19:14
0
雪    币: 138
活跃值: (461)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
好代码 .
谢谢分享
2010-2-1 19:15
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
这个,能被查出来吗?
2010-3-1 13:39
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
23
这个没有anti~
2010-3-3 14:47
0
雪    币: 386
活跃值: (46)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
24
严重支持,学习
2010-3-6 20:59
0
雪    币: 4
活跃值: (189)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
楼长...这个是不是必须要创建驱动设备啊?不创建call里面的unid填零,会蓝屏吗?
2017-9-19 00:20
0
游客
登录 | 注册 方可回帖
返回
//