• 通过修改i8042prt端口驱动中类驱动Kbdclass的回调函数地址,达到过滤键盘操作的例子


    同样也是寒江独钓的例子,但只给了思路,现贴出实现代码

    原理是通过改变端口驱动中本该调用类驱动回调函数的地方下手

    //替换分发函数  来实现过滤
    #include <wdm.h>
    #include <ntddk.h>
    #include <Ntddkbd.h>
    #include <windef.h>
    // Kbdclass驱动的名字
    #define KBD_DRIVER_NAME  L"\Driver\Kbdclass"
    //ps2的端口驱动
    #define PS2_DRIVER_NAME  L"\Driver\i8042prt"
    //usb的端口驱动
    #define USB_DRIVER_NAME  L"\Driver\Kbdhid"
    // 这个函数是事实存在的,只是文档中没有公开。声明一下
    // 就可以直接使用了。
    
    PVOID pOldFucAddr;
    PVOID pOldValue;
    NTSTATUS
    ObReferenceObjectByName(
                            PUNICODE_STRING ObjectName,
                            ULONG Attributes,
                            PACCESS_STATE AccessState,
                            ACCESS_MASK DesiredAccess,
                            POBJECT_TYPE ObjectType,
                            KPROCESSOR_MODE AccessMode,
                            PVOID ParseContext,
                            PVOID *Object
                            );
    BOOLEAN MmIsAddressValid(
      PVOID VirtualAddress
    );
    extern POBJECT_TYPE *IoDriverObjectType;
    
    //定义要查找的回调函数的类型
    typedef VOID(_stdcall *KEYBOARDCLASSSERVICECALLBACK)
    (IN PDEVICE_OBJECT DeviceObject,
    IN PKEYBOARD_INPUT_DATA InputDataStart,
    IN PKEYBOARD_INPUT_DATA InputDataEnd,
    IN OUT PULONG InputDataConsumed);
    
    
    
    typedef struct _KBD_CALLBACK
    {
        PDEVICE_OBJECT classDeviceObject;
        KEYBOARDCLASSSERVICECALLBACK serviceCallBack;
        BOOLEAN bSearch;
    }KBD_CALLBACK,PKBD_CALLBACK;
    KBD_CALLBACK g_KbdCallBack;
    
    #define  DELAY_ONE_MICROSECOND  (-10)
    #define  DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
    #define  DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
    //卸载时候   要替换回来
    VOID  c2pUnload(IN PDRIVER_OBJECT DriverObject) 
    {
        KdPrint(("DriverEntry unLoading...
    ")); 
        InterlockedExchangePointer(pOldFucAddr,g_KbdCallBack.serviceCallBack);
    }
    
    
    VOID _stdcall MyCallBackFun
    (IN PDEVICE_OBJECT DeviceObject,
    IN PKEYBOARD_INPUT_DATA InputDataStart,
    IN PKEYBOARD_INPUT_DATA InputDataEnd,
    IN OUT PULONG InputDataConsumed)
    {
        DbgPrint("makecode %d flags %d
    ",InputDataStart->MakeCode,InputDataStart->Flags);
        g_KbdCallBack.serviceCallBack(DeviceObject,InputDataStart,InputDataEnd,InputDataConsumed);
    }
    NTSTATUS SearchKbdDevice()
    {
      //定义一些局部变量
      NTSTATUS status = STATUS_UNSUCCESSFUL;
      UNICODE_STRING uniNtNameString;
      PDEVICE_OBJECT pUsingDeviceObject = NULL;//目标设备
      PDRIVER_OBJECT KbdDriverObject = NULL;//类驱动
      PDRIVER_OBJECT KbdhidDriverObject = NULL;//USB 端口驱动
      PDRIVER_OBJECT Kbd8042DriverObject = NULL;//PS/2 端口驱动
      PDRIVER_OBJECT UsingDriverObject = NULL;
    
      PVOID KbdDriverStart = NULL;//类驱动起始地址
      ULONG KbdDriverSize = 0;
      PBYTE UsingDeviceExt = NULL;
      ULONG i=0;
       PVOID pTemp;
      PDEVICE_OBJECT pAttachedKbdDevice;
      //这部分代码打开PS/2键盘的驱动对象
      RtlInitUnicodeString(&uniNtNameString,PS2_DRIVER_NAME);
      status = ObReferenceObjectByName(
        &uniNtNameString,
        OBJ_CASE_INSENSITIVE,
        NULL,
        0,
        *IoDriverObjectType,
        KernelMode,
        NULL,
        (PVOID*)&Kbd8042DriverObject
        );
      if (!NT_SUCCESS(status))
      {
        DbgPrint("Couldn't get the PS/2 driver Object
    ");
      }
      else
      {
        //解除引用
        ObDereferenceObject(Kbd8042DriverObject);
        DbgPrint("Got the PS/2 driver Object
    ");
      }
    
      //打开USB 键盘的端口驱动
      RtlInitUnicodeString(&uniNtNameString,USB_DRIVER_NAME);
      status = ObReferenceObjectByName(
        &uniNtNameString,
        OBJ_CASE_INSENSITIVE,
        NULL,
        0,
        *IoDriverObjectType,
        KernelMode,
        NULL,
        (PVOID*)&KbdhidDriverObject
        );
      if (!NT_SUCCESS(status))
      {
        DbgPrint("Couldn't get the USB driver Object
    ");
      }
      else
      {
        ObDereferenceObject(KbdhidDriverObject);
        DbgPrint("Got the USB driver Object
    ");
      }
    
      //如果同时有两个键盘,使用i8042prt
      if (Kbd8042DriverObject && KbdhidDriverObject)
      {
        DbgPrint("More than one keyboard!
    ");
      }
    
      //两种键盘都没有 也返回失败
      if (!Kbd8042DriverObject && KbdhidDriverObject)
      {
        DbgPrint("Not found keyboard!
    ");
        return STATUS_UNSUCCESSFUL;
      }
    
      //找到合适的驱动对象
      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)) 
      { 
        DbgPrint("Couldn't get the MyTest Device Object
    "); 
        return STATUS_UNSUCCESSFUL; 
      }
      else
      {
        // 这个打开需要解应用。
        ObDereferenceObject(KbdDriverObject);
      }
      //如果成功,找到Kbdclass开始地址和大小 
      KbdDriverStart =KbdDriverObject->DriverStart; 
      KbdDriverSize = KbdDriverObject->DriverSize; 
    
      //遍历UsingDriverObject下的设备对象,找到Kbdclass Attach的那个设备对象
      pUsingDeviceObject = UsingDriverObject->DeviceObject;
      
      while (pUsingDeviceObject)
      {
    Label_Continue:
        pAttachedKbdDevice=KbdDriverObject->DeviceObject;
        while(pAttachedKbdDevice)
        {
          PDEVICE_OBJECT pAttached=pUsingDeviceObject->AttachedDevice;
          while(pAttached)
          {
            if(pAttachedKbdDevice==pAttached)
            {
              DbgPrint("pAttachedKbdDevice :%8x
    ",pAttachedKbdDevice);
              
              UsingDeviceExt=(PBYTE)pUsingDeviceObject->DeviceExtension;
              //遍历找到的端口驱动设备扩展下的每个指针
              for (i=0;i<4096;i++,UsingDeviceExt += sizeof(PBYTE))
              {
                if (!MmIsAddressValid(UsingDeviceExt))
                {
                  pUsingDeviceObject=pUsingDeviceObject->AttachedDevice;
                  goto Label_Continue;
                }
    
                //在端口驱动的设备扩展中,找到了类驱动的设备对象,填好类驱动设备对象后继续
               
                pTemp = *(PVOID*)UsingDeviceExt;
                if (pTemp == pAttachedKbdDevice)
                {
                  g_KbdCallBack.classDeviceObject = (PDEVICE_OBJECT)pTemp;
                  DbgPrint("classDeviceObject %8x
    ",pTemp);
    
                  pTemp = *(PVOID*)(UsingDeviceExt+4);
                  if ((pTemp > KbdDriverStart)&&(pTemp < (PBYTE)KbdDriverStart+KbdDriverSize)&&MmIsAddressValid(pTemp))
                  {
                    //记录回调函数的地址
                    g_KbdCallBack.serviceCallBack = (KEYBOARDCLASSSERVICECALLBACK)pTemp;
                    g_KbdCallBack.bSearch=TRUE;
                    status=STATUS_SUCCESS;
                    DbgPrint("serviceCallBack :%8x
    ",pTemp);
                    
                    DbgPrint("替换函数");
                    pOldFucAddr=(PVOID*)(UsingDeviceExt+4);
                    InterlockedExchangePointer((PVOID*)(UsingDeviceExt+4),MyCallBackFun);
                    goto Label_Exit;
                  }
                  break;
                }
              }
              pUsingDeviceObject=pUsingDeviceObject->AttachedDevice;
              goto Label_Continue;
            }
            pAttached=pAttached->AttachedDevice;
          }
          pAttachedKbdDevice=pAttachedKbdDevice->NextDevice;
        }
        pUsingDeviceObject=pUsingDeviceObject->NextDevice;
      }
    
    Label_Exit:
      //如果成功找到,可以返回了
      return status;
    }
    //驱动程序入口
    NTSTATUS DriverEntry( 
                         IN PDRIVER_OBJECT DriverObject, 
                         IN PUNICODE_STRING RegistryPath 
                         ) 
    {     
        // 卸载函数。
        DriverObject->DriverUnload = c2pUnload; 
    
    
        return SearchKbdDevice(); 
    }

  • 相关阅读:
    C#下载文件
    艾宾浩斯记忆曲线背单词(转)
    .net(c#)在循环语句中执行WebBrowser.Navigate();方法,每次循环等待网页加载完后继续执行的解决方案.
    是非人生 — 一个菜鸟程序员的5年职场路 第34节
    是非人生 — 一个菜鸟程序员的5年职场路 第20节
    是非人生 — 一个菜鸟程序员的5年职场路 第21节
    是非人生 — 一个菜鸟程序员的5年职场路 第27节
    关于.net多层架构的网站如何在底层类库中获取网站的物理路径
    C#写的对系统用户和组操作的类(可以实现用户和组的添加、删除、修改)
    是非人生 — 一个菜鸟程序员的5年职场路 第33节
  • 原文地址:https://www.cnblogs.com/zwt1234/p/4453597.html
Copyright © 2020-2023  润新知