Question(s) about handles...

Long story short im interested in a way to communicate with my keyboards driver. This is for my own personal use and maybe for a friend or 2 but its nothing nefarious.

What I've done so far has been to use setupapi.h and im able to enumerate the device interfaces on my system. These device interface's can then be communicated with using a handle returned by createfileA(). The problem is that when I attempt to open a handle to a keyboard or mouse device the error code returned is access denied...

Now to my question. I believe there's a way to retrieve all the handles on a specific system using ntquerygetsysteminformation(). I haven't explored this yet. If im able to get all the handles that are open in a given system and then somehow identify which handles are associated with what. Could I hijack that handle for my purposes? Or possibly create a duplicate handle or something along those lines?

I'm able to retrieve a device handle by registering to receive a windows message WM_INPUT. Im curious if im able to use that device handle for certain operations but its most likely read only or possibly just an identifier? (haven't explored this yet either) and don't even know if that matters. Im more interested in just retrieving all the handles on a system and attempting to create a dup of it or something along those lines. Sry long post. Any help would be great. Im even exploring the option of creating a simple driver to get my foot in the door but thats kinda the nuclear option...thanks in advance.

What exactly are you trying to do?

Duplicating a handle is something that's almost never needed. It's usually only needed when a process needs to grant access to a resource to a child process that can't itself request that access. If you have enough permissions to enumerate and duplicate all open handles then you can simply just open a new handle to the resource you need directly.
I think the issue is that access to keyboard or mouse devices is exclusive. im assuming that once the device is created and interface handle is opened for i/o to it thats the only handle available. Or its possible that the handles created have kernel mode only flag or possibly both.

The goal is to send scan codes to the keyboard in an attempt to mimic physical keyboard input.

You don't need access to the keyboard to do that. The keyboard is an input device, so you can't write to it anyway.
If you want to simulate keystrokes all you need is a handle to the foreground window and a way to insert keyboard events into its queue. This is done with SendInput(). If you google "windows api simulate keystrokes" you can find examples of how to do this. This is the first result that showed up for me: https://batchloaf.wordpress.com/2012/04/17/simulating-a-keystroke-in-win32-c-or-c-using-sendinput/
Yes thats how you send virtual keystrokes and in most cases thats fine. However I'm after simulating actual physical keystrokes. By device interface im assuming that means driver, not the actual device. A physical keystroke produces a WM_INPUT message that simply doesn't exist with a virtual keystroke. Hence if a program wanted to ignore virtual keystrokes entirely it could just register for raw keyboard input and listen for that exclusively.

I definitely don't understand the intricacies on how physical usb devices interact with a computer but even if by interface we were actually talking about the physical device, an interface has an in pipe and an out pipe. So writing to the out pipe would result in passing information between the device and the drivers. All I know is I looped through every device interface on my system and opened handles to them using create file and it was either successful, not present, mouse and keyboard were the only that returned access denied.
Last edited on
You can't write to the "out pipe" of a keyboard interface. The driver owns the writing end of that pipe and it's not going to just give some random user space process writing access.
If you want input that's completely indistinguishable from a physical device's then you'll need to write a driver that presents itself to the system as a keyboard driver, but actually all the input it produces comes from an IOCTL from user space.
i've definitely researched the option of writing my own driver and it actually seems like the path of least resistance.

However i'd still like to know more about handles. I guess i'm going to have to do a small test just to see if I can grab a handle opened via createfile with exclusive access from one program and use it in another.

I can tell you right now you can, as long as the calling process has administrative privileges. I don't think you can do anything with such a handle to solve your problem, though.
ya grabbing a handle isn't going to work. I figured it was worth looking into. I had fun writing a function that converts a handle to a string. I'd call it a waste of time but you always learn something new. The good news is that I already have a vm setup to play around with testing drivers on. I'm just skeptical of the tool that is widely available to turn signature enforcement off. I've looked through the source line by line and on the surface it all seems legit but includes a "vulnerable driver" that looks like its just a binary dumped to hex and theres just no way to know what is going on in there.
I'm just skeptical of the tool that is widely available to turn signature enforcement off. I've looked through the source line by line and on the surface it all seems legit but includes a "vulnerable driver" that looks like its just a binary dumped to hex and theres just no way to know what is going on in there.
I would suggest that you use that if you don't mind installing on your machine other people's rootkits for them.
Either disable signature enforcement at boot or pay for a code signing certificate (about USD 200).
OK so heres a new development. I actually made some type of progress. Not sure if this progress would translate to other setups bc mine isn't exactly typical. With this laptop I use a bluetooth mouse bc I can't stand using the little touch pad. What's unusual is that this mouse's dongle must be designed in a way that it reports a HID keyboard as well as the mouse. I'd assume that this is so that this same dongle could be used with a wireless kybd and mouse combo in the various combinations from the manufacturer. So when I enumerate the device interfaces and filter them down to just keyboards i've just discovered that i'm actually able to open a handle to this "keyboard" with write permissions.

This has got me thinking that I know that I read somewhere that some devices that are integrated system components like a default keyboard on a laptop may be impossible to open a handle to because the manufacture provides metadata in the driver or hardware that prevents the opening. This maybe the case of what i'm dealing with. I need to do more testing bc when i did my original tests to attempt to open all connected devices I just used a generic template that attempted to open all the devices with GENERIC_ALL access. When I attempted to do that with this second keyboard it failed access denied. When I tried it with just GENERIC_WRITE it was successful. Either way any handle opened is a win bc now I can query attributes from the device which means I should be able to find the endpoints.

Shit 200$ for a code signing certificate.... that might be worth it. Where can I get one for that?

Another update. I am able to open a handle with write permissions to my bluetooth mouse IF I set the sharing mode to read and write. If I attempt to open it with exclusive access the error returned is something along the lines of device is in use by another application.


Update... and just like that I'm able to open a handle to the regular keyboard. with write permissions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
int main() {


    HANDLE DeviceInfoSet = GetDeviceInfoSetInterfaces();

        if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
            cout << "invalid handle";
            return 0;
        }
        vector<SP_DEVINFO_DATA> v_Device_Info_Data = GetDeviceInfoData(DeviceInfoSet);
        vector<SP_DEVICE_INTERFACE_DATA> v_Device_Interface_Data = GetDeviceInterfaceData(DeviceInfoSet, v_Device_Info_Data, GUID_DEVINTERFACE_KEYBOARD);

        PSP_DEVICE_INTERFACE_DETAIL_DATA dida{};
        HANDLE h{};

        if (!v_Device_Interface_Data.empty()) {
            dida = GetDeviceInterfaceDetailData(DeviceInfoSet, v_Device_Interface_Data[0]);
            h = CreateFile((LPCWSTR)dida->DevicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

            if (h == INVALID_HANDLE_VALUE) {
                cout << "error = " << GetLastError();
            }
            else {
                cout << "success";
                CloseHandle(h);
            }


        }
       
        if (DeviceInfoSet) {
            
            SetupDiDestroyDeviceInfoList(DeviceInfoSet);
        }

}

Last edited on
But what happens when you write to that handle? I really do not think you're going to get input by doing that, I think it's meant as an interface to send data to the device. Such as for example to program specific functions, like custom function keys.

Last time we bought ours from GoDaddy, IIRC.
Topic archived. No new replies allowed.