HidD_GetInputReport的功能
HidD_GetInputReport用于获取输入报告(input report)。
然而,微软对此函数有一个特殊的解释,即只能获得,无法连续获取,因为数据可能会丢失。因此,如果要连续获取输入报告,则需要使用它ReadFile函数。 同时,有些设备可能不支持HidD_GetInputReport,因此,使用此函数时可能没有响应。 更多详见:
- https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/hidsdi/nf-hidsdi-hidd_getinputreport
- https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/obtaining-hid-reports#obtaining-hid-reports-by-user-mode-applications
HidD_GetInputReport应用层
HidD_GetInputReport函数在ReactOS实现如下:
HIDAPI BOOLEAN WINAPI HidD_GetInputReport(IN HANDLE HidDeviceObject, IN OUT PVOID ReportBuffer, IN ULONG ReportBufferLength) { DWORD RetLen; return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INPUT_REPORT, NULL, 0, ReportBuffer, ReportBufferLength, &RetLen, NULL) != 0; }
源代码路径为:
E:\reactos\ReactOS-0.4.13-src-2020-0731\ReactOS-0.4.13\dll\win32\hid\hid.c
可以看出,函数是通过的IOCTL_HID_GET_INPUT_REPORT实现了。因此,我们需要驱动核心hidclass检查驱动中内核的实现情况。
HidD_GetInputReport内核层
在最新的ReactOS其实这个IOCTL并未实现。
case IOCTL_HID_GET_INPUT_REPORT: { DPRINT1("[HIDUSB] IOCTL_HID_GET_INPUT_REPORT not implemented \n"); ASSERT(FALSE); Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NOT_IMPLEMENTED; }
不过,REACTOS未实现并不意味着windows因为reactos不是半成品工程。 所以既然已经知道这个函数是实现的hidclass.sys因此,需要一些特殊的方法。 这里结合IDA分析。 我们看过HidRegisterMinidriver了解原始源代码的源代码hidusb驱动的回调函数进行了HOOK,这应用层下发时IOCTL_HID_GET_INPUT_REPORT后,会进入HIDCLASS设置的回调函数名为:HidpMajorHandler。
#define IRP_MJ_DEVICE_CONTROL 0x0e ... v20->MajorFunction[14] = (int (__fastcall *)(_DEVICE_OBJECT *, _IRP *))HidpMajorHandler; ...
在其函数HidpMajorHandler继续跟踪内部
case 14: v15 = HidpIrpMajorDeviceControl(v8, v4, -1073741824, a4);
所以HidpIrpMajorDeviceControl才是真实的IOCTL_HID_GET_INPUT_REPORT实现。 通过http://www.pnpon.com/import/ioctl.html 查询IOCTL_HID_GET_INPUT_REPORT的值为0xb01a2,故需要在HidpIrpMajorDeviceControl内部查找关于它的代码。 可见代码为:
case 0xB0191u: //IOCTL_HID_SET_FEATURE case 0xB0192u: //IOCTL_HID_GET_FEATURE case 0xB0195u: //IOCTL_HID_SET_OUTPUT_REPORT case 0xB01A2u: //IOCTL_HID_GET_INPUT_REPORT case 0xB01A6u: // v12 = HidpGetSetReport(a1, v4, (unsigned int)v109[6], v108); v105 = v12;
在这个函数中,会做出一些必要的判断,然后调用hidusb中.
v35 = HidpCallDriverSynchronous(*(_QWORD *)v8, v45);
所以看,这还是进去了miniport设备中。 在hidusb其实就是下发IRP驱动到总线,然后获取输入报告的内容。当然,输入报告指针中的第一个字节是ReportID.
进入HIDUSB.SYS驱动后,它被执行HIDCLASS.SYS hook掉的ioctl对应的函数HumInternalIoctl。 在HumInternalIoctl找对应的IOCTL 0xB01A2u: 。。。
请查看后续部分:http://www.usbzh.com/article/detail-933.html