Simulate keystroke

Hi all,

I have to find a method to simulate keystrokes from a user mode application without having the “injected” flag set, which is happening if using keybd_event. I am trying right now to prepare a keyboard filter driver that would accomplish this, using custom IOCTLs. I started from the kbfiltr sample in the DDK, then made the changes as described in http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q262305 in order to allow custom IOCTLs. Here is my modified FilterDispatchIo function that processes one custom IOCTL called IOCTL_KEYBOARD_SIMULATE_KEY:

#define IOCTL_KEYBOARD_SIMULATE_KEY CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0F00, METHOD_NEITHER, FILE_ANY_ACCESS)

NTSTATUS
FilterDispatchIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status;

PDEVICE_EXTENSION devExt;
KEYBOARD_INPUT_DATA data;
PKEYBOARD_INPUT_DATA InputDataStart;
PKEYBOARD_INPUT_DATA InputDataEnd;
ULONG InputDataConsumed;
KIRQL prevIrql;

// PAGED_CODE();

devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

//
// Please note that this is a common dispatch point for controlobject and
// filter deviceobject attached to the pnp stack.
//
if(DeviceObject != ControlDeviceObject)
{
//
// We will just the request down as we are not interested in handling
// requests that come on the PnP stack.
//
return KbFilter_DispatchPassThrough(DeviceObject, Irp);
}

//
// Else this is targeted at our control deviceobject so let’s handle it.
// Here we will handle the IOCTl requests that come from the app.
//
status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
irpStack = IoGetCurrentIrpStackLocation (Irp);

switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
DebugPrint((“Create \n”));
break;

case IRP_MJ_CLOSE:
DebugPrint((“Close \n”));
break;

case IRP_MJ_CLEANUP:
DebugPrint((“Cleanup \n”));
break;

case IRP_MJ_DEVICE_CONTROL:
DebugPrint((“DeviceIoControl\n”));
switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_KEYBOARD_SIMULATE_KEY:
{
InputDataStart = (KEYBOARD_INPUT_DATA*)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
InputDataEnd = InputDataStart + irpStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KEYBOARD_INPUT_DATA);

KeRaiseIrql(DISPATCH_LEVEL, &prevIrql);

InputDataConsumed = 0;

(*(PSERVICE_CALLBACK_ROUTINE) devExt->UpperConnectData.ClassService)(
devExt->UpperConnectData.ClassDeviceObject,
InputDataStart,
InputDataEnd,
& InputDataConsumed);

KeLowerIrql(prevIrql);
}
break;

default:
status = STATUS_INVALID_PARAMETER;
break;
}

default:
break;
}

Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}

I am using DeviceIoControl with IOCTL_KEYBOARD_SIMULATE_KEY from an application to simulate keystrokes in this way. The problem is that the filter driver always crashes at the PSERVICE_CALLBACK_ROUTINE call. WinDbg shows something like this:

*** Fatal System Error: 0x000000d1
(0x00000000,0x00000002,0x00000001,0x81AAB78C)

Break instruction exception - code 80000003 (first chance)

I have checked that the simulated keystrokes reach the filter driver just fine via the custom IOCTL, the problem is that I don’t seem to do what’s right in order to pass them next as real keystrokes.

I am new to windows drivers, any ideas would be greatly appreciated.

Thanks,
Adrian

First, you should start with the KMDF kbfiltr example (~src\kmdf\kbfiltr). Much easier to extend and implement properly, it uses a raw PDO instead of a control device. I suggest that you debug this by attaching a kernel debugger and looking at devExt. You are dereferencing NULL. Think about it, who would set the service callback function pointer value in the control device object’s extension?

d
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@baum.ro
Sent: Wednesday, September 24, 2008 11:35 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Simulate keystroke

Hi all,

I have to find a method to simulate keystrokes from a user mode application without having the “injected” flag set, which is happening if using keybd_event. I am trying right now to prepare a keyboard filter driver that would accomplish this, using custom IOCTLs. I started from the kbfiltr sample in the DDK, then made the changes as described in http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q262305 in order to allow custom IOCTLs. Here is my modified FilterDispatchIo function that processes one custom IOCTL called IOCTL_KEYBOARD_SIMULATE_KEY:

#define IOCTL_KEYBOARD_SIMULATE_KEY CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0F00, METHOD_NEITHER, FILE_ANY_ACCESS)

NTSTATUS
FilterDispatchIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status;

PDEVICE_EXTENSION devExt;
KEYBOARD_INPUT_DATA data;
PKEYBOARD_INPUT_DATA InputDataStart;
PKEYBOARD_INPUT_DATA InputDataEnd;
ULONG InputDataConsumed;
KIRQL prevIrql;

// PAGED_CODE();

devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

//
// Please note that this is a common dispatch point for controlobject and
// filter deviceobject attached to the pnp stack.
//
if(DeviceObject != ControlDeviceObject)
{
//
// We will just the request down as we are not interested in handling
// requests that come on the PnP stack.
//
return KbFilter_DispatchPassThrough(DeviceObject, Irp);
}

//
// Else this is targeted at our control deviceobject so let’s handle it.
// Here we will handle the IOCTl requests that come from the app.
//
status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
irpStack = IoGetCurrentIrpStackLocation (Irp);

switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
DebugPrint((“Create \n”));
break;

case IRP_MJ_CLOSE:
DebugPrint((“Close \n”));
break;

case IRP_MJ_CLEANUP:
DebugPrint((“Cleanup \n”));
break;

case IRP_MJ_DEVICE_CONTROL:
DebugPrint((“DeviceIoControl\n”));
switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_KEYBOARD_SIMULATE_KEY:
{
InputDataStart = (KEYBOARD_INPUT_DATA*)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
InputDataEnd = InputDataStart + irpStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KEYBOARD_INPUT_DATA);

KeRaiseIrql(DISPATCH_LEVEL, &prevIrql);

InputDataConsumed = 0;

(*(PSERVICE_CALLBACK_ROUTINE) devExt->UpperConnectData.ClassService)(
devExt->UpperConnectData.ClassDeviceObject,
InputDataStart,
InputDataEnd,
& InputDataConsumed);

KeLowerIrql(prevIrql);
}
break;

default:
status = STATUS_INVALID_PARAMETER;
break;
}

default:
break;
}

Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}

I am using DeviceIoControl with IOCTL_KEYBOARD_SIMULATE_KEY from an application to simulate keystrokes in this way. The problem is that the filter driver always crashes at the PSERVICE_CALLBACK_ROUTINE call. WinDbg shows something like this:

*** Fatal System Error: 0x000000d1
(0x00000000,0x00000002,0x00000001,0x81AAB78C)

Break instruction exception - code 80000003 (first chance)

I have checked that the simulated keystrokes reach the filter driver just fine via the custom IOCTL, the problem is that I don’t seem to do what’s right in order to pass them next as real keystrokes.

I am new to windows drivers, any ideas would be greatly appreciated.

Thanks,
Adrian


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Hello,

this is probably unrelated to your problem, but why did you choose the
METHOD_NEITHER transfer type for your IOCTL?
Kernel-mode drivers must validate all input coming from user mode, because
misbehaving applications could otherwise compromise the whole system.
When using the METHOD_NEITHER transfer type, you have to ensure that the
supplied buffer is valid and also stays valid during the driver’s
operation.
Because the buffers of KEYBOARD_INPUT_DATA packets are most likely going
to be small, I’d choose the METHOD_BUFFERED transfer type instead and let
the I/O manager deal with (and copy) the user-mode buffers.
Of course, you will still have to validate the packets themselves before
passing them to the keyboard stack.

By the way, allowing unrestricted access to your control device by using
the FILE_ANY_ACCESS access type is a security risk in your case, because
less-privileged programs could then send keystrokes/commands to higher
privileged ones.

  • Cay

On Wed, 24 Sep 2008 20:35:00 +0200, wrote:
> Hi all,
>
> I have to find a method to simulate keystrokes from a user mode
> application without having the “injected” flag set, which is happening
> if using keybd_event. I am trying right now to prepare a keyboard filter
> driver that would accomplish this, using custom IOCTLs. I started from
> the kbfiltr sample in the DDK, then made the changes as described in
> http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q262305 in order
> to allow custom IOCTLs. Here is my modified FilterDispatchIo function
> that processes one custom IOCTL called IOCTL_KEYBOARD_SIMULATE_KEY:
>
> #define IOCTL_KEYBOARD_SIMULATE_KEY CTL_CODE(FILE_DEVICE_KEYBOARD,
> 0x0F00, METHOD_NEITHER, FILE_ANY_ACCESS)
>
> NTSTATUS
> FilterDispatchIo(
> IN PDEVICE_OBJECT DeviceObject,
> IN PIRP Irp
> )
> {
> PIO_STACK_LOCATION irpStack;
> NTSTATUS status;
>
> PDEVICE_EXTENSION devExt;
> KEYBOARD_INPUT_DATA data;
> PKEYBOARD_INPUT_DATA InputDataStart;
> PKEYBOARD_INPUT_DATA InputDataEnd;
> ULONG InputDataConsumed;
> KIRQL prevIrql;
>
> // PAGED_CODE();
>
> devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
>
> //
> // Please note that this is a common dispatch point for controlobject
> and
> // filter deviceobject attached to the pnp stack.
> //
> if(DeviceObject != ControlDeviceObject)
> {
> //
> // We will just the request down as we are not interested in handling
> // requests that come on the PnP stack.
> //
> return KbFilter_DispatchPassThrough(DeviceObject, Irp);
> }
>
> //
> // Else this is targeted at our control deviceobject so let’s handle it.
> // Here we will handle the IOCTl requests that come from the app.
> //
> status = STATUS_SUCCESS;
> Irp->IoStatus.Information = 0;
> irpStack = IoGetCurrentIrpStackLocation (Irp);
>
> switch (irpStack->MajorFunction)
> {
> case IRP_MJ_CREATE:
> DebugPrint((“Create \n”));
> break;
>
> case IRP_MJ_CLOSE:
> DebugPrint((“Close \n”));
> break;
>
> case IRP_MJ_CLEANUP:
> DebugPrint((“Cleanup \n”));
> break;
>
> case IRP_MJ_DEVICE_CONTROL:
> DebugPrint((“DeviceIoControl\n”));
> switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
> {
> case IOCTL_KEYBOARD_SIMULATE_KEY:
> {
> InputDataStart =
> (KEYBOARD_INPUT_DATA*)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
> InputDataEnd = InputDataStart +
> irpStack->Parameters.DeviceIoControl.InputBufferLength /
> sizeof(KEYBOARD_INPUT_DATA);
>
> KeRaiseIrql(DISPATCH_LEVEL, &prevIrql);
>
> InputDataConsumed = 0;
>
> (*(PSERVICE_CALLBACK_ROUTINE) devExt->UpperConnectData.ClassService)(
> devExt->UpperConnectData.ClassDeviceObject,
> InputDataStart,
> InputDataEnd,
> & InputDataConsumed);
>
> KeLowerIrql(prevIrql);
> }
> break;
>
> default:
> status = STATUS_INVALID_PARAMETER;
> break;
> }
>
> default:
> break;
> }
>
> Irp->IoStatus.Status = status;
> IoCompleteRequest (Irp, IO_NO_INCREMENT);
> return status;
> }
>
> I am using DeviceIoControl with IOCTL_KEYBOARD_SIMULATE_KEY from an
> application to simulate keystrokes in this way. The problem is that the
> filter driver always crashes at the PSERVICE_CALLBACK_ROUTINE call.
> WinDbg shows something like this:
>
> *** Fatal System Error: 0x000000d1
> (0x00000000,0x00000002,0x00000001,0x81AAB78C)
>
> Break instruction exception - code 80000003 (first chance)
>
> I have checked that the simulated keystrokes reach the filter driver
> just fine via the custom IOCTL, the problem is that I don’t seem to do
> what’s right in order to pass them next as real keystrokes.
>
> I am new to windows drivers, any ideas would be greatly appreciated.
>
> Thanks,
> Adrian

Thanks for your suggestions. I have called UpperConnectData.ClassService stored in the device extension of the device object because this is what the driver does in KbFilter_ServiceCallback, as a result of a key being pressed or released on the physical keyboard. However, using WinDbg I have noticed that the PDEVICE_OBJECT parameter of the FilterDispatchIo function (the control device object?) different than the one of the KbFilter_ServiceCallback (the filter device object?). I don’t know how can I get a pointer to the filter device object in FilterDispatchIo and as a patch, I just stored the pointer of the PDEVICE_OBJECT parameter in case it is different from the control device object, which is already stored in a global variable. This way, simulating keystrokes works.

However it seems it doesn’t work for USB keyboards. I will try to adapt the KMDF kbfiltr sample, as suggested.

Thanks,
Adrian

Any idea where from get I download WdfCoInstaller01007.dll? I didn’t find it at http://connect.microsoft.com as suggested at http://blogs.msdn.com/doronh/archive/2008/04/17/the-wdf-1-7-cointstallers-are-now-available.aspx. I suppose I need it when installing the KMDF kbfiltr driver because I get an error “Setup cannot copy the file WdfCoInstaller01007.dll”. Thanks.

I just checked the Microsoft connect site and the coinstaller is there. Did
you sign in?

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com]
On Behalf Of xxxxx@baum.ro
Sent: Tuesday, September 30, 2008 12:14 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Simulate keystroke

Any idea where from get I download WdfCoInstaller01007.dll? I didn’t find it
at http://connect.microsoft.com as suggested at
http://blogs.msdn.com/doronh/archive/2008/04/17/the-wdf-1-7-cointstallers-ar
e-now-available.aspx. I suppose I need it when installing the KMDF kbfiltr
driver because I get an error “Setup cannot copy the file
WdfCoInstaller01007.dll”. Thanks.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Thanks Bill, I have found it now. The package is described as “WDF (KMDF and UMDF) for the WDK Windows Server 2008 - This is version 1.7 of the WDF redistributable coinstallers.” It is under the “Windows Driver Kit (WDK), Windows Logo Kit (WLK) and Windows Driver Framework (WDF)” section in the “Developoler Tools” category.

I have adapted the kbfiltr KMDF driver in order to simulate keystrokes via a custom IOCTL. However I can install this driver only if I have a PS/2 keyboard connected. Is there a way to install it in order to work with USB keyboards also? In the DDK sample there is a paragraph saying:

"This driver filters input for a particular keyboard on the system. If you want to filter keyboard inputs from all the keyboards plugged into the system then you can install this driver as a class filter below the kbdclass filter driver by adding the service name of this filter driver before the kbdclass filter in the registry at “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4D36E96B-E325-11CE-BFC1-08002BE10318}\UpperFilters”.

I have added “kbfiltr” in front of “kdclass” for that string value, however this is not enough to properly install the driver. Any ideas how can I accomplish this? Thanks.

Did you install the driver as a service as well? there is an NT insider article about installing a kmdf class driver that should help you here …BUT… with folks who want to inject input, I ask the same question: is a filter the right choice? IMHO, no it is not. There may be no keyboard (think tablet) or the keyboard is not standardized through kbdclass or there is 2+ keyboards (which one will you inject through?). What I think you should do is create your own virtual keyboard that you insert input into. This way you do not need to filter all keyboards and you know your keyboard will always be there. There is a kmdf sample on how to write a HID miniport that lets you enumerate your own keyboard.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@baum.ro
Sent: Friday, October 03, 2008 6:24 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Simulate keystroke

I have adapted the kbfiltr KMDF driver in order to simulate keystrokes via a custom IOCTL. However I can install this driver only if I have a PS/2 keyboard connected. Is there a way to install it in order to work with USB keyboards also? In the DDK sample there is a paragraph saying:

"This driver filters input for a particular keyboard on the system. If you want to filter keyboard inputs from all the keyboards plugged into the system then you can install this driver as a class filter below the kbdclass filter driver by adding the service name of this filter driver before the kbdclass filter in the registry at “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4D36E96B-E325-11CE-BFC1-08002BE10318}\UpperFilters”.

I have added “kbfiltr” in front of “kdclass” for that string value, however this is not enough to properly install the driver. Any ideas how can I accomplish this? Thanks.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer