用户模式也就是通常说的应用程序调用以下函数:
HidD_GetManufacturerString
HidD_GetProductString
HidD_GetSerialNumberString
会生成对应IRP给内核模式的hidclass.sys,其CTL_CODE分别为
IOCTL_HID_GET_MANUFACTURER_STRING
IOCTL_HID_GET_PRODUCT_STRING
IOCTL_HID_GET_SERIALNUMBER_STRING
而后hidclass.sys会调用mini驱动,CTL_CODE均为
IOCTL_HID_GET_STRING
这是老衲跟踪调试发现的. 不过有个问题,很多文献,材料,书籍,stuff,what ever,都用类似的方法:
PIO_STACK_LOCATION IrpStack; USHORT wStrId = ((PUSHORT)IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)[0]; LANGID wLngId = ((PUSHORT)IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)[1]; // also USHORT
当我执行是,我得到了这个,很完美,性感,让人热血澎湃的画面:
蓝屏代码 0x0000008E微软的MSDN说明是: KERNEL_MODE_EXCEPTION_NOT_HANDLED 内核模式异常未处理
代码 0xC0000005则是STATUS_ACCESS_VIOLATION, 这个在用户模式下一般是弹出一个 xxxx指令引用 xxxx内存 该内存不能为xxxx
几经挣扎, 回头仔细查看MSDN发现了答案, 思想里又回想多年前战地二小队长的无线电: 不能这么做!
Parameters.DeviceIoControl.Type3InputBuffer in the I/O stack location of the IRP contains a composite value. The two most significant bytes contain the language ID of the string to be retrieved. The two least significant bytes contain one
of the following three constant values:
- HID_STRING_ID_IMANUFACTURER
- HID_STRING_ID_IPRODUCT
- HID_STRING_ID_ISERIALNUMBER
这个并不是一个指针, 而是两个WORD合成的DWORD, 比如HidD_GetProductString的Type3InputBuffer:
// 0x0409000F 0F 00 09 04 : HID_STRING_ID_IPRODUCT(0x000F) English American ENU(0x0409,MSDN)
于是有了前面的兴奋, 下面就不敢乱来了,至少要确认老婆不在家, 于是我使用内存指针之前都Probe
结果还是异常, 不过可以通过dbgView查看,而不用导致虚拟机崩溃, 使用代码
ProbeForWrite(Irp->UserBuffer, xxx, x);
仍然是0xC0000005 STATUS_ACCESS_VIOLATION, 狠心不Probe居然没有错,中文资料都像金元宝一样噎着藏着等下崽
我只好跑去微软了,结果
Do not use this routine on kernel-mode addresses; it will raise an exception.
If Irp->RequestorMode = KernelMode, the
Irp->AssociatedIrp.SystemBuffer and Irp->UserBuffer fields do not contain user-mode addresses, and a call to
ProbeForWrite to probe a buffer pointed to by either field will raise an exception.
If Length = 0, ProbeForWrite does no checking of the address. In this case, the routine does not raise an exception for an address that is misaligned or is outside the range of valid user addresses.
还是那句话, 不能这么做!
具体我就不翻译了, 只能传一个用户模式的地址 0x80000000以前的,而不能传递一个内核模式的地址
虽然hidclass的CTL_CODE都是METHOD_NEITHER即直接内存访问,但是传递的地址是内核模式的地址,调试显示0xf7bc5830
看来,这种事情,老婆不在家也不能做啊.
2014-12-01 01:53:09.
大家不要紧张,这只是一个笔记!