《寒江独钓_Windows内核安全编程》中修改类驱动分发函数
最近在阅读《寒江独钓_Windows内核安全编程》一书的过程中,发现修改类驱动分发函数这一技术点,书中只给出了具体思路和部分代码,没有完整的例子。
按照作者的思路和代码,将例子补充完整,发现将驱动安装在WIN7 32位环境下,键盘失效。
经调试发现,可能的原因是替换了\\Driver\\Kbdclass类驱动的所有分发函数导致,如果只替换分发IRP_MJ_READ的函数,不会有问题,以下为代码
1 //替换分发函数 来实现过滤 2 #include <wdm.h> 3 #include <Ntddkbd.h> 4 // Kbdclass驱动的名字 5 #define KBD_DRIVER_NAME L"\\Driver\\Kbdclass" 6 //旧的函数地址 7 PDRIVER_DISPATCH OldDispatchFun[IRP_MJ_MAXIMUM_FUNCTION+1]; 8 extern POBJECT_TYPE *IoDriverObjectType; 9 PDRIVER_DISPATCH OldDIspatchRead; 10 // 这个函数是事实存在的,只是文档中没有公开。声明一下 11 // 就可以直接使用了。 12 NTSTATUS 13 ObReferenceObjectByName( 14 PUNICODE_STRING ObjectName, 15 ULONG Attributes, 16 PACCESS_STATE AccessState, 17 ACCESS_MASK DesiredAccess, 18 POBJECT_TYPE ObjectType, 19 KPROCESSOR_MODE AccessMode, 20 PVOID ParseContext, 21 PVOID *Object 22 ); 23 //新的分发函数地址 24 NTSTATUS c2pDispatchGeneral( 25 IN PDEVICE_OBJECT DeviceObject, 26 IN PIRP Irp 27 ) 28 { 29 PIO_STACK_LOCATION irpStack=IoGetCurrentIrpStackLocation(Irp); 30 DbgPrint("irpStack->MinorFunction=%x\n",irpStack->MinorFunction); 31 return OldDIspatchRead(DeviceObject,Irp); 32 //return OldDispatchFun[irpStack->MinorFunction](DeviceObject,Irp); 33 } 34 #define DELAY_ONE_MICROSECOND (-10) 35 #define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000) 36 #define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000) 37 //卸载时候 要替换回来 38 VOID c2pUnload(IN PDRIVER_OBJECT DriverObject) 39 { 40 NTSTATUS Status = STATUS_UNSUCCESSFUL; 41 int nIndex = 0; 42 PDRIVER_OBJECT KeyBoardDriverObject = NULL; 43 UNICODE_STRING KeyBoardName; 44 LARGE_INTEGER Delay; 45 46 RtlInitUnicodeString(&KeyBoardName, L"\\Driver\\Kbdclass"); 47 48 Status = ObReferenceObjectByName(&KeyBoardName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, 49 KernelMode, NULL, &KeyBoardDriverObject); 50 51 if (!NT_SUCCESS(Status)) 52 { 53 DbgPrint("UnloadDriver Get Keyboard Driver Object Error\n"); 54 return; 55 } 56 57 58 //交换原来的分发函数 59 60 // for (nIndex; nIndex < IRP_MJ_MAXIMUM_FUNCTION; nIndex++) 61 // { 62 // InterlockedExchangePointer(&KeyBoardDriverObject->MajorFunction[nIndex], OldDispatchFun[nIndex]); 63 // } 64 InterlockedExchangePointer(&KeyBoardDriverObject->MajorFunction[IRP_MJ_READ], OldDIspatchRead); 65 DbgPrint("Change MajorFunction Successful!\n"); 66 67 Delay = RtlConvertLongToLargeInteger(5* DELAY_ONE_MILLISECOND); 68 // 延时等待完成 69 KeDelayExecutionThread(KernelMode, FALSE, &Delay); 70 ObReferenceObject(KeyBoardDriverObject); 71 } 72 //驱动程序入口 73 NTSTATUS DriverEntry( 74 IN PDRIVER_OBJECT DriverObject, 75 IN PUNICODE_STRING RegistryPath 76 ) 77 { 78 ULONG i; 79 NTSTATUS status; 80 81 UNICODE_STRING uniNtNameString; 82 //返回kdbclass驱动对象 83 PDRIVER_OBJECT KbdDriverObject = NULL; 84 85 KdPrint(("MyAttach\n")); 86 87 // 初始化一个字符串,就是Kdbclass驱动的名字。 88 #if DBG 89 _asm int 3; 90 #endif 91 RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME); 92 // 请参照前面打开设备对象的例子。只是这里打开的是驱动对象。 93 status = ObReferenceObjectByName ( 94 &uniNtNameString, 95 OBJ_CASE_INSENSITIVE, 96 NULL, 97 0, 98 *IoDriverObjectType, 99 KernelMode, 100 NULL, 101 &KbdDriverObject 102 ); 103 // 如果失败了就直接返回 104 if(!NT_SUCCESS(status)) 105 { 106 DbgPrint("MyAttach: Couldn't get the MyTest Device Object %x\n",status); 107 return( status ); 108 } 109 else 110 { 111 // 这个打开需要解应用。早点解除了免得之后忘记。 112 //解释为 可能导致DriverObject引用计数加1 113 114 } 115 116 117 118 OldDIspatchRead=KbdDriverObject->MajorFunction[IRP_MJ_READ]; 119 InterlockedExchangePointer(&KbdDriverObject->MajorFunction[IRP_MJ_READ],c2pDispatchGeneral); 120 ObDereferenceObject(KbdDriverObject); 121 // 卸载函数。 122 DriverObject->DriverUnload = c2pUnload; 123 124 125 return status; 126 }