首页
社区
课程
招聘
[求助]关于《寒江独钓》键盘过滤的一个困扰
发表于: 2012-10-16 09:41 5616

[求助]关于《寒江独钓》键盘过滤的一个困扰

2012-10-16 09:41
5616
最近在看寒江独钓键盘过滤章节,刚涉入内核编程领域。各种困惑 ,很是无奈....

刚看到书上说当发生按键时,触发0x93号中断例程,在该中断例程会调用i8042prt驱动中的I8042keyboardInterruptService,在该函数中最终会调用 kbdclass驱动的读回调函数procA ,从而将数据读到kbdclass队列中。过程就是如此。而且照书上的是:
接下来就是在I8042prt或kbdhid驱动的设备的扩展体中搜索kbdclass的一个设备对象和那个回调函数(ProcA)地址。书上没给出完整的源码,我就试着照书上的思路写了份测试的代码:

1.这是找开I8042prt或kbdhid 和kbdclass驱动对象的函数,结果从参数中返回:

NTSTATUS _OpenKeyBdDriver(OUT PDRIVER_OBJECT* ppDriverUsing ,OUT PDRIVER_OBJECT* ppDriKbdclass){
  UNICODE_STRING UszDriverName;
  PDRIVER_OBJECT pDriKbdhid = NULL;
  PDRIVER_OBJECT pDriI8024prt = NULL;
  PDRIVER_OBJECT pDriverKbd = NULL;
  NTSTATUS status = STATUS_SUCCESS;

  //Reference Driver Kbdhid 
  RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\Kbdhid");
  status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
                                 *IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriKbdhid);
  if (!NT_SUCCESS(status))
    DbgPrint("Fail To Reference Driver Kbdhid\r\n");
  else
    ObDereferenceObject(pDriKbdhid);

  //Reference Driver I8024prt 
  RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\i8042prt");
  status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
                                 *IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriI8024prt);
  if (!NT_SUCCESS(status))
    DbgPrint("Fail To Reference Driver I8042prt\r\n");
  else
    ObDereferenceObject(pDriI8024prt);

  //Open Driver Kbdclass
  RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\Kbdclass");
  status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
                                *IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriverKbd);
  if (!NT_SUCCESS(status)){
    DbgPrint("Fail To Reference Driver Kbdclass\r\n");
    return status;
  }
  else
    ObDereferenceObject(pDriverKbd);

  //Both failed
  if (!pDriI8024prt && !pDriI8024prt){
    DbgPrint("Haven't Found Keyboard Device In your Machine\r\n");
    return STATUS_INVALID_THREAD;
  }

  //Both Keyboard device
  if (pDriI8024prt && pDriKbdhid){
    DbgPrint("Found Two Keyboard In You Machine\r\n");
    return STATUS_INVALID_THREAD;
  }

  *ppDriverUsing =  (pDriI8024prt? pDriI8024prt : pDriKbdhid);
  *ppDriKbdclass =  pDriverKbd;
  return STATUS_SUCCESS;
}

2.接下来得到了端口驱动对象与类驱动对象之后,就开开始在端口驱动的设备扩展体中搜索那个为类驱动的一个设备指针与回调函数ProcA;
pDriUsing是端口驱动对象指针(I8042prt或kbdhid),pDriKbdclass为类驱动对象指针。
DriParamSt是
//To store searched data
typedef struct _PARAM_OBJ_PROC{
  PDEVICE_OBJECT pKbdclassDevice;
  PKDBCLASSREADCALLBACKPROC pProcAddrInKbdclass;
  PKDBCLASSREADCALLBACKPROC pProcAddrInUsingkbd; 
}PARAM_OBJ_PROC ,*PPARAM_OBJ_PROC;
的一个全局变量;

函数如下:
NTSTATUS _ToSearch(IN PDRIVER_OBJECT pDriverUsing ,IN PDRIVER_OBJECT pDriKbdclass ,OUT PPARAM_OBJ_PROC pParamSt){
  int nAddrStart = (int)pDriKbdclass->DriverStart;
  int nAddrSize  = (int)pDriKbdclass->DriverSize;
  PDEVICE_OBJECT pDevUsing  = pDriverUsing->DeviceObject;
  PDEVICE_OBJECT pDevTarget = pDriKbdclass->DeviceObject;

  //init var
  pParamSt->pProcAddrInKbdclass = pParamSt->pProcAddrInUsingkbd = NULL;
  pParamSt->pKbdclassDevice = NULL;
  int* pDevExtUsing = NULL;

  while(pDevTarget)
  {
    pDevExtUsing = (int*)pDevUsing->DeviceExtension;
    for (int i = 0 ;i < 4096 ;i++ , pDevExtUsing++)
    {
      //address flow
      if (!MmIsAddressValid(pDevExtUsing))
        break;

      //searched ok
      if (pParamSt->pKbdclassDevice && pParamSt->pProcAddrInKbdclass){
        DbgPrint("pDevTarget : %x\r\n" ,(int)pParamSt->pKbdclassDevice);
        DbgPrint("pReadCallback in Kbdclass: %x\r\n" ,(int)pParamSt->pProcAddrInKbdclass);
        DbgPrint("pReadCallback in DevKbdExtUsing : %x\r\n" ,(int)pParamSt->pProcAddrInUsingkbd);
        return STATUS_SUCCESS;
      }

      //found Kdbclass Device
      if (*pDevExtUsing == (int)pDevTarget){
        DbgPrint("Found DevKbdclass In DevKbdUing Extension\r\n");
        pParamSt->pKbdclassDevice = pDevTarget;
      }

      //found Kbdclass read Callback proc
      if (*pDevExtUsing > nAddrStart && *pDevExtUsing < nAddrStart + nAddrSize &&
        MmIsAddressValid((PVOID)*pDevExtUsing)){
        DbgPrint("Found Kbdclass Read Callback Proc In DevKbdUing Extension\r\n");
        pParamSt->pProcAddrInKbdclass = (PKDBCLASSREADCALLBACKPROC)*pDevExtUsing;
        pParamSt->pProcAddrInUsingkbd = (PKDBCLASSREADCALLBACKPROC)pDevExtUsing;
      }
      DbgPrint("i : %d\r\n" ,i);
    }
    pDevTarget = pDevTarget->NextDevice;
  }
  return STATUS_INVALID_THREAD;
}

下面是DriverEntry:
#pragma INITCODE
extern "C"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriver ,IN PUNICODE_STRING pRegPath){

#ifdef DBG
  __asm int 3
#endif

  PDRIVER_OBJECT pDriverUsing = NULL;
  PDRIVER_OBJECT pDriKbdclass = NULL;
  NTSTATUS status = STATUS_SUCCESS;
  int* pProcAddr = NULL;

  pDriver->DriverUnload = DriverUnload;
  status = _OpenKeyBdDriver(&pDriverUsing ,&pDriKbdclass);
  if (!NT_SUCCESS(status))
    return status;

  status = _ToSearch(pDriverUsing ,pDriKbdclass ,&DriParamSt);
  if (!NT_SUCCESS(status)){
    DbgPrint("Fail to search Kbdclass read callback proc\r\n");
    return status;
  }

  pProcAddr = (int*)DriParamSt.pProcAddrInUsingkbd;
  *pProcAddr = (int)_ReadCallbackNew;
  return STATUS_SUCCESS;
}

其中_ReadCallbackNew是自己写的用来替换那个回调函数的函数,很简单,如下:

void _ReadCallbackNew(IN PDEVICE_OBJECT pDevice ,IN PKEYBOARD_INPUT_DATA pDataBeg,
  IN PKEYBOARD_INPUT_DATA pDataEnd ,OUT PULONG nDataConsumed){
    PKDBCLASSREADCALLBACKPROC pProcOld = DriParamSt.pProcAddrInKbdclass;
    PKEYBOARD_INPUT_DATA pQueueBeg = pDataBeg;

    while (pQueueBeg != pDataEnd){
      DbgPrint("Scancode : %x\r\n" ,pQueueBeg->MakeCode);
      pQueueBeg++;
    }

    pProcOld(pDevice ,pDataBeg ,pDataEnd ,nDataConsumed);
}

代码大致就是上面这些了,但拷到VM上发现总是测试不成功,问题是搜索不到kbdclass类驱动的那个设备对象指针与那个回调函数,很无奈,真心知道错在哪,,代码和书上都差不多了,觉得应该不会错,那就是错在思路上了,还是说书上的这种方法已经不适用了,我是在win7下测试的。不知道还有谁去实践尝试过书上这个例子,可以的话分享下心得,一直被这个问题困扰着,找了很多资料也没有找到答案,看雪的各位大侠,能否给个建议或思路啊,谢谢谢谢

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

上传的附件:
  • a.jpg (59.42kb,97次下载)
收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 260
活跃值: (249)
能力值: ( LV12,RANK:350 )
在线值:
发帖
回帖
粉丝
2
自己顶一下,别沉下去了,在线等答案......
2012-10-16 13:59
0
游客
登录 | 注册 方可回帖
返回
//