能力值:
( LV2,RANK:10 )
|
-
-
2 楼
|
能力值:
( LV9,RANK:280 )
|
-
-
3 楼
给你个思路:把你的设备对象Attach到kbdclass下的任一个设备对象上,你就可以在你的IRP_MJ_INTERNAL_DEVICE_CONTROL派遣函数里可以取到servicecall。
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
大兄弟 方便给代码看看么。。
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
NTSTATUS SearchServiceFromExt(PDRIVER_OBJECT KbdDriverObject,PDEVICE_OBJECT pPortDev)
{
PDEVICE_OBJECT pTargetDeviceObject = NULL;
UCHAR *DeviceExt;
int i=0;
NTSTATUS status;
PVOID KbdDriverStart;
ULONG KbdDriverSize = 0;
PDEVICE_OBJECT pTmpDev;
UNICODE_STRING kbdDriName;
KbdDriverStart = KbdDriverObject->DriverStart;
KbdDriverSize = KbdDriverObject->DriverSize;
status = STATUS_UNSUCCESSFUL;
RtlInitUnicodeString(&kbdDriName,KBD_DRIVER_NAME);
pTmpDev = pPortDev;
while(pTmpDev->AttachedDevice != NULL)
{
KdPrint(("Att: 0x%x",pTmpDev->AttachedDevice));
KdPrint(("Dri Name : %wZ",&pTmpDev->AttachedDevice->DriverObject->DriverName));
if(RtlCompareUnicodeString(&pTmpDev->AttachedDevice->DriverObject->DriverName,
&kbdDriName,TRUE) == 0)
{
break;
}
pTmpDev = pTmpDev->AttachedDevice;
}
if(pTmpDev->AttachedDevice == NULL)
{
return status;
}
KdPrint(("pTmpDev : 0x%x",pTmpDev));
KdPrint(("pTmpDev->AttachedDevice: 0x%x",pTmpDev->AttachedDevice));
pTargetDeviceObject = KbdDriverObject->DeviceObject;
while(pTargetDeviceObject)
{
KdPrint(("pTargetDeviceObject : 0x%x", pTargetDeviceObject));
//查找kbdclass的父设备
if(pTmpDev->AttachedDevice != pTargetDeviceObject)
{
pTargetDeviceObject = pTargetDeviceObject->NextDevice;
continue;
}
DeviceExt = (UCHAR *)pTmpDev->DeviceExtension;
g_KbdCallBack.classDeviceObject = NULL;
//遍历我们先找到的端口驱动的设备扩展的每一个指针
for (i=0;i<4096;i++, DeviceExt++)
{
PVOID tmp;
if (!MmIsAddressValid(DeviceExt))
{
break;
}
//找到后会填写到这个全局变量中,这里检查是否已经填好了
//如果已经填好了就不用继续找了,可以直接退出
if (g_KbdCallBack.classDeviceObject && g_KbdCallBack.serviceCallBack)
{
status = STATUS_SUCCESS;
break;
}
//在端口驱动的设备扩展里,找到了类驱动设备对象,填好类驱动设备对象后继续
tmp = *(PVOID*)DeviceExt;
if (tmp == pTargetDeviceObject)
{
g_KbdCallBack.classDeviceObject = (PDEVICE_OBJECT)tmp;
continue;
}
//如果在设备扩展中找到一个地址位于KbdClass这个驱动中,就可以认为,这就是我们要找的回调函数
if ((tmp > KbdDriverStart) && (tmp < (UCHAR*)KbdDriverStart+KbdDriverSize) &&
(MmIsAddressValid(tmp)))
{
//将这个回调函数记录下来
g_KbdCallBack.serviceCallBack = (KEYBOARDCLASSSERVICECALLBACK)tmp;
g_KbdCallBack.AddServerCallBack = (PVOID*)DeviceExt;
}
}
if(status == STATUS_SUCCESS)
{
break;
}
//换成下一个设备,继续遍历
pTargetDeviceObject = pTargetDeviceObject->NextDevice;
}
return status;
}
NTSTATUS SearchServiceCallBack(IN PDRIVER_OBJECT DriverObject)
{
//定义用到的一组全局变量,这些变量大多数是顾名思义的
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING uniNtNameString;
PDEVICE_OBJECT pTargetDeviceObject = NULL;
PDRIVER_OBJECT KbdDriverObject = NULL;
PDRIVER_OBJECT KbdhidDriverObject = NULL;
PDRIVER_OBJECT Kbd8042DriverObject = NULL;
PDRIVER_OBJECT UsingDriverObject = NULL;
PDEVICE_OBJECT UsingDeviceObject = NULL;
PVOID UsingDeviceExt = NULL;
//这里的代码用来打开USB键盘端口驱动的驱动对象
RtlInitUnicodeString(&uniNtNameString,USBKBD_DRIVER_NAME);
status = ObReferenceObjectByName(&uniNtNameString,
OBJ_CASE_INSENSITIVE,NULL,0,
*IoDriverObjectType,
KernelMode,
NULL,
(PVOID *)&KbdhidDriverObject);
if (!NT_SUCCESS(status))
{
KdPrint(("Couldn't get the USB driver Object\n"));
}else
{
ObDereferenceObject(KbdhidDriverObject);
KdPrint(("get the USB driver Object\n"));
}
//打开PS/2键盘的驱动对象
RtlInitUnicodeString(&uniNtNameString,PS2KBD_DRIVER_NAME);
status = ObReferenceObjectByName(&uniNtNameString,
OBJ_CASE_INSENSITIVE,
NULL, 0,
*IoDriverObjectType,
KernelMode,
NULL,
(PVOID *)&Kbd8042DriverObject);
if (!NT_SUCCESS(status))
{
KdPrint(("Couldn't get the PS/2 driver Object %08x\n",status));
}else
{
ObDereferenceObject(Kbd8042DriverObject);
KdPrint(("get the PS/2 driver Object\n"));
}
//这段代码考虑有一个键盘起作用的情况。如果USB键盘和PS/2键盘同时存在,直接返回失败即可
if (Kbd8042DriverObject && KbdhidDriverObject)
{
return STATUS_UNSUCCESSFUL;
}
//如果两个设备都没有找到
if (!Kbd8042DriverObject && !KbdhidDriverObject)
{
return STATUS_SUCCESS;
}
//找到合适的驱动对象,不管是USB还是PS/2,反正一定要找到一个
UsingDriverObject = Kbd8042DriverObject? Kbd8042DriverObject:KbdhidDriverObject;
RtlInitUnicodeString(&uniNtNameString,KBD_DRIVER_NAME);
status = ObReferenceObjectByName(&uniNtNameString,
OBJ_CASE_INSENSITIVE,NULL,
0,
*IoDriverObjectType,
KernelMode,
NULL,
(PVOID *)&KbdDriverObject);
if (!NT_SUCCESS(status))
{
//如果没有成功,直接返回即可
KdPrint(("MyAttach: Coundn't get the kbd driver Object\n"));
return STATUS_UNSUCCESSFUL;
}else
{
ObDereferenceObject(KbdDriverObject);
}
//遍历KbdDriverObject下的设备对象
UsingDeviceObject = UsingDriverObject->DeviceObject;
while(UsingDeviceObject)
{
status = SearchServiceFromExt(KbdDriverObject,UsingDeviceObject);
if(status == STATUS_SUCCESS)
{
break;
}
UsingDeviceObject = UsingDeviceObject->NextDevice;
}
//如果成功找到了,就把这个函数替换成我们自己的回调函数
if (g_KbdCallBack.classDeviceObject && g_KbdCallBack.AddServerCallBack && g_KbdCallBack.serviceCallBack)
{
KdPrint(("Hook keyboradClassServiceCallback\n"));
*(KEYBOARDCLASSSERVICECALLBACK *)g_KbdCallBack.AddServerCallBack = MyKeyboardClassServiceCallback;
InitGlobalKey(g_KbdCallBack.classDeviceObject);
}
return status;
}
当年写的,不知道能不能用。
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
思路就是这个,然而在pTmpDev->DeviceExtension里没有一个内容是被设备对象指针,找不到那个设备对象,就谈不上找函数了。其他电脑都是正常的,就是这台笔记本不行
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
是不是可以这么认为,Attach上去之后,我生成的那个设备的IRP_MJ_INTERNAL_DEVICE_CONTROL的分发函数就是servicecallback?
如果是,另外调用这个函数时需要传入的设备对象传哪一个呢?或者怎么找进一步找这个设备对象?
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
查资料,找到了一个和我一样的问题,大兄弟帮看看。
http://www.myexception.cn/embedded-driver/1771517.html
1.创建一个键盘设备
2.在IOCTL_INTERNAL_KEYBOARD_CONNECT中,获取KeyboardClassServiceCallback回调函数地址
3.我的电脑是THINKPAD T430,里面有一个触摸板的驱动:Syntp.sys,这个驱动下面的设备也会附加到
我创建的键盘设备上,这个时候,我得到的KeyboardClassServiceCallback地址就不对了,我再模拟
发送按键不管用。(设备的顺序是这样的:我的设备在最底下,中间是syntp.sys的设备
最上面是keyboardclass中的键盘设备)
我的猜想:syntp.sys下面是一个过滤设备,HOOK了键盘设备的KeyboardClassServiceCallback,然后
把syntp.sys中的地址和设备传给了我。同时syntp.sys里面没有对相应逻辑的处理。
问题:怎么能够得到正确的回调函数地址 或者 正常模拟发送按键信息
|
能力值:
( LV9,RANK:280 )
|
-
-
9 楼
参考这个吧https://github.com/everdox/HIDInput/blob/master/input.h
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
楼主,对于Thinkpad有触摸板的笔记本,有办法找到KeyboardClassServiceCallback吗?你是怎么解决了?
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
yishunjian
楼主,对于Thinkpad有触摸板的笔记本,有办法找到KeyboardClassServiceCallback吗?你是怎么解决了?
没有解决。你呢
|
能力值:
( LV8,RANK:130 )
|
-
-
12 楼
hzqst
给你个思路:把你的设备对象Attach到kbdclass下的任一个设备对象上,你就可以在你的IRP_MJ_INTERNAL_DEVICE_CONTROL派遣函数里可以取到servicecall。
如果游戏在你的下面attach一下 那么键盘的消息 先经过游戏的 最后才经过你的 这样不就被游戏捷足先登了吗 而且游戏还可以hook 你的设备irp dispatch的地址
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
我在弄一个无模块驱动项目的时候也遇到这个问题 因为无模块就不方便创建设备 我去找了7-10几个版本的kbdclass特征 KeyboardClassServiceCallback下面一定调用FF 15 * * * * call cs:__imp_KeAcquireSpinLockAtDpcLevel 整个sys只会调用这个api一次,找KeyboardClassServiceCallback的头部 32位系统直接搜 mov edi, edi push ebp mov ebp, esp,64位版本KeyboardClassServiceCallback前面一定有一堆CC 我找的版本最少有6个 最多有15个 从调用API的地方往前搜就能暴搜到
|
能力值:
( LV1,RANK:0 )
|
-
-
14 楼
|