首页
社区
课程
招聘
[求助]驱动模拟键鼠,有触控板的电脑找不到KbdServiceCallback函数
发表于: 2016-5-28 22:21 10851

[求助]驱动模拟键鼠,有触控板的电脑找不到KbdServiceCallback函数

2016-5-28 22:21
10851
http://bbs.pediy.com/showthread.php?t=197474
我在学习论坛上大侠开源的驱动模拟键鼠,现在遇到一个问题就是有触摸板的电脑,找不到KbdServiceCallback函数。特来请教各位大侠。

i8042prt两个设备,两个设备的设备栈是
i8042prt->SynTP->XXX
i8042prt->SynTP->kdbclass

键盘是PS2的键盘,i8042prt驱动上有两个设备
这两个设备所处的设备栈的上层设备都是驱动SynTP的设备,在往上就是mouclass或者kbdclass,然而这两个设备栈的所有设备的扩展内都找不到kbdServiceCallback

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 1402
活跃值: (341)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
2016-5-31 15:17
0
雪    币: 12848
活跃值: (9147)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
3
给你个思路:把你的设备对象Attach到kbdclass下的任一个设备对象上,你就可以在你的IRP_MJ_INTERNAL_DEVICE_CONTROL派遣函数里可以取到servicecall。
2016-6-1 15:30
0
雪    币: 1402
活跃值: (341)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
大兄弟 方便给代码看看么。。
2016-6-1 17:22
0
雪    币: 211
活跃值: (118)
能力值: ( 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;  
}

当年写的,不知道能不能用。
2016-6-1 20:32
0
雪    币: 1402
活跃值: (341)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
思路就是这个,然而在pTmpDev->DeviceExtension里没有一个内容是被设备对象指针,找不到那个设备对象,就谈不上找函数了。其他电脑都是正常的,就是这台笔记本不行
2016-6-4 00:40
0
雪    币: 1402
活跃值: (341)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
是不是可以这么认为,Attach上去之后,我生成的那个设备的IRP_MJ_INTERNAL_DEVICE_CONTROL的分发函数就是servicecallback?
如果是,另外调用这个函数时需要传入的设备对象传哪一个呢?或者怎么找进一步找这个设备对象?
2016-6-4 00:41
0
雪    币: 1402
活跃值: (341)
能力值: ( 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里面没有对相应逻辑的处理。

问题:怎么能够得到正确的回调函数地址 或者 正常模拟发送按键信息
2016-6-4 01:01
0
雪    币: 12848
活跃值: (9147)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
9
参考这个吧https://github.com/everdox/HIDInput/blob/master/input.h
2016-6-12 22:40
0
雪    币: 79
活跃值: (59)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
楼主,对于Thinkpad有触摸板的笔记本,有办法找到KeyboardClassServiceCallback吗?你是怎么解决了?
2019-3-13 21:47
0
雪    币: 1402
活跃值: (341)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
yishunjian 楼主,对于Thinkpad有触摸板的笔记本,有办法找到KeyboardClassServiceCallback吗?你是怎么解决了?
没有解决。你呢
2019-6-10 11:12
0
雪    币: 83
活跃值: (1087)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
12
hzqst 给你个思路:把你的设备对象Attach到kbdclass下的任一个设备对象上,你就可以在你的IRP_MJ_INTERNAL_DEVICE_CONTROL派遣函数里可以取到servicecall。
如果游戏在你的下面attach一下 那么键盘的消息 先经过游戏的 最后才经过你的 这样不就被游戏捷足先登了吗 而且游戏还可以hook 你的设备irp dispatch的地址 
2019-6-10 12:11
0
雪    币: 26
活跃值: (470)
能力值: ( 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的地方往前搜就能暴搜到
2019-9-15 20:48
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
wbflike 没有解决。你呢
老铁,解决了吗
2020-11-27 16:18
0
游客
登录 | 注册 方可回帖
返回
//