MouHidInputHook
MouHidInputHook enables users to filter, modify, and inject mouse input data packets into the input data stream of HID USB mouse devices without modifying the mouse device stacks.
Install / Use
/learn @changeofpace/MouHidInputHookREADME
MouHidInputHook
MouHidInputHook enables users to filter, modify, and inject mouse input data packets into the input data stream of HID USB mouse devices without modifying the mouse device stacks.
The MouHid Hook Manager emulates the hook strategy used by the Moufiltr driver by hooking the CONNECT_DATA object inside each MouHid device object. The MouHid driver uses the ClassService field of a CONNECT_DATA object to transfer mouse input data packets to mouse class data queues. By emulating this strategy, we have access to each data packet generated by the mouse device without needing to install a mouse filter driver. This emulation technique has the following benefits:
-
We can safely unhook mouse device stacks and unload the MouHidInputHook driver without needing to unload the hooked device stacks. A standard filter driver for a PnP device can only be unloaded after all of the device objects attached to it are destroyed.
-
The technique is PatchGuard safe.
-
The technique is relatively stealthy from the perspective of a kernel anti-cheat because:
-
The field offset of the CONNECT_DATA object inside a MouHid device object is not defined in a public header.
-
We do not modify the HID USB mouse device stack(s) by attaching a filter device object.
A kernel anti-cheat must resort to heuristics or other potentially unsafe vectors in order to detect the presence of this technique. This is generally impractical because an anti-cheat driver must be reliable, i.e., avoid using undocumented information, in order to support the player base of the protected video game.
This project uses a heuristic to resolve the CONNECT_DATA field offset during driver initialization (described below).
-
The MouHid Hook Manager supports PnP events by registering a PnP notification callback for mouse device interface changes. This callback is invoked each time a MouClass device object is added to or removed from the system.
MouHid Monitor
The MouHid Monitor is an example hook callback which logs the content of each data packet generated by a HID USB mouse. Users can utilize this feature to debug how mouse actions, e.g., moving the mouse or clicking a mouse button, are represented as a sequence of one or more data packets.
For example, we can determine the sequence of data packets required to emulate a left mouse button click action by loading the driver, running the client, and manually clicking the left mouse button. The following items are log output excerpts after performing this action on a local machine and in a virtual machine:
The column data elements refer to CONNECT_DATA and MOUSE_INPUT_DATA fields:
SC: Class service callback invoked to transfer the packet. CONNECT_DATA.ClassService
DO: Device object which contains the target data queue. CONNECT_DATA.ClassDeviceObject
ID: Target device unit id, e.g., '\Device\PointerClassX'. MOUSE_INPUT_DATA.UnitId
IF: Indicator flags. MOUSE_INPUT_DATA.Flags
BF: Transition state of the mouse buttons. MOUSE_INPUT_DATA.ButtonFlags
BD: Wheel data for 'SCROLL' action packets. MOUSE_INPUT_DATA.ButtonData
RB: Raw button state. MOUSE_INPUT_DATA.RawButtons
EX: Device-specific data. MOUSE_INPUT_DATA.ExtraInformation
LX: Signed relative or absolute motion in X direction. MOUSE_INPUT_DATA.LastX
LY: Signed relative or absolute motion in Y direction. MOUSE_INPUT_DATA.LastY
================================= OUTPUT ==================================
Platform: Windows 7 SP1 x64
Environment: Local machine
Mouse: Logitech G303
Action: Hold mouse in the air, click left mouse button, put mouse on surface, move the mouse
Packet 63: SC=FFFFF880040A8858 DO=FFFFFA800FDE78B0 ID=1 IF=0x000 BF=0x000 BD=0 RB=0 EX=0 LX=0 LY=-1
D ->Packet 64: SC=FFFFF880040A8858 DO=FFFFFA800FDE78B0 ID=1 IF=0x000 BF=0x001 BD=0 RB=0 EX=0 LX=0 LY=0
U ->Packet 65: SC=FFFFF880040A8858 DO=FFFFFA800FDE78B0 ID=1 IF=0x000 BF=0x002 BD=0 RB=0 EX=0 LX=0 LY=0
Packet 66: SC=FFFFF880040A8858 DO=FFFFFA800FDE78B0 ID=1 IF=0x000 BF=0x000 BD=0 RB=0 EX=0 LX=0 LY=1
Packet 67: SC=FFFFF880040A8858 DO=FFFFFA800FDE78B0 ID=1 IF=0x000 BF=0x000 BD=0 RB=0 EX=0 LX=0 LY=1
Platform: Windows 7 SP1 x64
Environment: VMware virtual machine, vmusbmouse.sys mouse filter driver active
Mouse: Logitech G303
Action: Hold mouse in the air, click left mouse button, put mouse on surface, move the mouse
Packet 75: SC=FFFFF880025630C0 DO=FFFFFA80040F6A40 ID=1 IF=0x003 BF=0x000 BD=0 RB=0 EX=0 LX=12580 LY=25436
D ->Packet 76: SC=FFFFF88003FE5858 DO=FFFFFA8004106CF0 ID=2 IF=0x000 BF=0x001 BD=0 RB=0 EX=0 LX=0 LY=0
Packet 77: SC=FFFFF880025630C0 DO=FFFFFA80040F6A40 ID=1 IF=0x003 BF=0x000 BD=0 RB=0 EX=0 LX=12580 LY=25436
U ->Packet 78: SC=FFFFF88003FE5858 DO=FFFFFA8004106CF0 ID=2 IF=0x000 BF=0x002 BD=0 RB=0 EX=0 LX=0 LY=0
Packet 79: SC=FFFFF880025630C0 DO=FFFFFA80040F6A40 ID=1 IF=0x003 BF=0x000 BD=0 RB=0 EX=0 LX=12580 LY=25436
Packet 80: SC=FFFFF880025630C0 DO=FFFFFA80040F6A40 ID=1 IF=0x003 BF=0x000 BD=0 RB=0 EX=0 LX=12528 LY=25436
Packet 81: SC=FFFFF880025630C0 DO=FFFFFA80040F6A40 ID=1 IF=0x003 BF=0x000 BD=0 RB=0 EX=0 LX=12474 LY=25544
Packet 82: SC=FFFFF880025630C0 DO=FFFFFA80040F6A40 ID=1 IF=0x003 BF=0x000 BD=0 RB=0 EX=0 LX=12422 LY=25544
Note: The above output was modified to increase readability.
The data packet for the left mouse button down action is indicated by D ->, and the data packet for the left mouse button up action is indicated by U ->.
We can infer the following rules for these environments:
-
The local machine environment uses MOUSE_MOVE_RELATIVE for mouse movement actions, and the virtual machine environment uses MOUSE_MOVE_ABSOLUTE.
-
The local machine environment contains one HID USB mouse device stack, and the virtual machine environment contains two HID USB mouse device stacks. The virtual machine environment uses different (ClassDeviceObject, ClassService) pairs for button action packets and movement action packets. Each pair is represented by a CONNECT_DATA object inside a MouHid device object. Therefore, there must be two MouHid device objects and two device stacks.
-
The virtual machine environment contains multiple unit ids. This implies that there are two named mouse class device objects: \Device\PointerClass1 and \Device\PointerClass2. There must be two class data queues: one for button action packets and one for movement action packets. Therefore, a data packet should never contain both button data and movement data. Conversely, data packets in the local machine environment can contain both data types because there is one class data queue.
-
The virtual machine contains a third party filter driver, vmusbmouse, which generates a movement data packet between a button-down packet and its corresponding button-up packet. This may be related to the mouse smoothing feature of VMware Tools.
MouClassInputInjection
The MouClassInputInjection project is an application of the knowledge acquired from using the MouHid Monitor. This project uses a MouHidInputHook hook callback to dynamically resolve the packet data rules for the HID USB mouse device stacks on the host machine. These rules are used to synthesize and inject valid data packets into the input data stream.
Projects
MouHidInputHook
The core driver project which implements the hook interface.
MouHidMonitor
A command line MouHidInputHook client which enables the MouHid Monitor.
Input Processing Internals
Input Class Drivers
The input class drivers, kbdclass.sys and mouclass.sys, allow hardware-independent operation of input devices by enforcing a non-standard communication protocol between device objects in an input device stack. This protocol divides the device stack into two substacks: the hardware-independent upper stack and the hardware-dependent lower stack. The lower stack transfers input data from a physical device to the upper stack via the class service callback. The class service callback ensures that the upper stack always receives input data in a normalized format.
Class Service Callback
The class service callback for an input device stack is established by the input class driver's AddDevice routine. This routine performs the following actions:
- Creates an upper-level class filter device object.
- Attaches the new device object to the input device stack.
- Initializes a CONNECT_DATA object for this class device object.
- Sends the connect data object inside a connect-device request down the device stack.
The device object whose driver completes this request is the top-level device object in the lower substack. This driver stores the connect data object inside the device extension of the corresponding device object.
Class Data Queue
A class device object contains a circular buffer of input data packets in its device extension. This buffer, referred to as the class data queue, is effectively a producer/consumer queue.
T
