900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > linux ps2键盘驱动 通用键盘鼠标模拟(包括USB和PS2)

linux ps2键盘驱动 通用键盘鼠标模拟(包括USB和PS2)

时间:2018-12-10 17:41:07

相关推荐

linux ps2键盘驱动 通用键盘鼠标模拟(包括USB和PS2)

通过直接调用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上测试通过。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。