键盘过滤(HOOK分发函数)--Windows内核学习记录

编译环境: Windows10 x64

  Dirver.h

 

 1 #pragma once
 2 #include <ntddk.h>
 3 #include <wdm.h>
 4 
 5 #define KBD_DRIVER_NAME    L"\\Driver\\Kbdclass"            // 键盘类驱动
 6 #define USBKBD_DRIVER_NAME L"\\Driver\\Kbdhid"            // USB键盘 端口驱动
 7 #define PS2KBD_DRIVER_NAME L"\\Driver\\i8042prt"        // PS/2键盘 端口驱动
 8 
 9 
10 // 键盘按下Shift CapsLock  NumLock标志
11 #define K_SHFIT 1
12 #define K_CAPS    2
13 #define K_NUM    4    
14 
15 
16 //  自定义键盘扫描码的ASCII字符数组
17 //  主键键盘数字1-10 字母小写字符(qwertyuiop)
18 char UnShift[] = {
19     0, 0, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2d, 0x3d, 0, 0,
20     0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x6C, 0x6F, 0x70 };
21 
22 //  上键盘符号 字母大写(QWERTYUIOP)
23 char IsShfit[] = {
24     0,0,0x21,0x40, 0x23, 0x24, 0x25, 0x5e, 0x26, 0x2a, 0x28, 0x29, 0x5f, 0x2b, 0, 0,
25     0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4f, 0x50 };
26 
27 
28 /* 自定义设备扩展*/
29 typedef struct _C2P_DEV_EXT    
30 {
31     ULONG NodeSize;                            // 此结构的大小
32     KSPIN_LOCK IoRequestsSpinLock;            // 同时调用保护锁
33     KEVENT IoInProgressEvent;                // 进程间同步处理
34     PDEVICE_OBJECT FilterDeviceObject;        // 生成的过滤设备对象
35     PDEVICE_OBJECT TargetDeviceObject;        // 成功被绑定的设备对象指针
36     PDEVICE_OBJECT LowerDeviceObject;        // 获取键盘驱动得到的设备对象
37 // TargetDeviceObject与TargetDeviceObject是同一个指针,一个是通过获取驱动对象时,指向驱动的设备得到的,一个是绑定设备时获取的
38 }C2P_DEV_EXT, *PC2P_DEV_EXT;
39 
40 /* 键盘扫描码传递结构*/
41 typedef struct _KEYBOARD_INPUT_DATA
42 {
43     USHORT UnitId;    // 对于\\DEVICE\\KeyboardPort0这个值是0,\\DEVICE\\KeyboardPort1这个值是1,依此类推
44     USHORT MakeCode;    // 扫描码
45     USHORT Flags;        // 标志,标志一个键按下还是弹起
46     USHORT Reserved;        // 保留
47     ULONG ExtraInformation; // 扩展信息
48 }KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA;
49 
50 
51 /* 键盘类驱动服务回调例程结构*/
52 typedef VOID(_stdcall* KeyBoardClassServiceCallback)(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA InputDataStart,
53     PKEYBOARD_INPUT_DATA InputDataEnd, PULONG InputDataConsumed);
54 
55 
56 // 通过名字获得驱动对象指针函数声明,微软文档未公开,声明直接使用
57 NTSTATUS ObReferenceObjectByName(PUNICODE_STRING ObjectName, ULONG Attributes, PACCESS_STATE AccessState,
58     ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PVOID ParseContext, PVOID* Object);
59 
60 
61 
62 NTSTATUS cwkDispatch(PDEVICE_OBJECT dev, PIRP Irp);            // 主要驱动分发函数(不过滤处理的消息)
63 NTSTATUS c2pDispatchPower(PDEVICE_OBJECT dev, PIRP Irp);    //  电源操作分发函数
64 NTSTATUS c2pDispatchPNP(PDEVICE_OBJECT dev, PIRP Irp);        // 设备插拔
65 NTSTATUS c2pDispatchRead(PDEVICE_OBJECT dev, PIRP Irp);        // 驱动读分发函数
66 NTSTATUS c2pReadCompletion(PDEVICE_OBJECT dev, PIRP Irp, PVOID Context);    // 读操作的完成回调函数
67 void c2pDataAnalysis(PIRP Irp);                                // 获取的数据解析键扫描码
68 void __stdcall c2pKeyboardDown(UCHAR uch);                    // 当键盘按下,进行数据过滤
69 UCHAR __stdcall KeyboarFindAssic(UCHAR uch);                // 扫描码转字符串
70 
71 // 获得键盘设备绑定键盘过滤
72 NTSTATUS c2pAttachDevices(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);    
73 
74 // 初始化设备扩展
75 NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt, IN PDEVICE_OBJECT pFilterDeviceObject, IN PDEVICE_OBJECT pTargetDeviceObject, IN PDEVICE_OBJECT pLowerDeviceObject);
76 
77 VOID c2pUnload(IN PDRIVER_OBJECT DriverObject);    // 卸载驱动的过滤设备
78 VOID c2pDetach(IN PDEVICE_OBJECT DeviceObject);    // 过滤设备绑定并删除
79 
80 
81 /* Hook顶层键盘类驱动的IRP分发函数*/
82 NTSTATUS c2pSetHookIrp(PDRIVER_OBJECT DriverObject);
83 NTSTATUS c2pHookDispatch(PDEVICE_OBJECT dev, PIRP Irp);
84 NTSTATUS c2pHookReadDisp(PDEVICE_OBJECT dev, PIRP Irp);        // Hook消息分发函数
85 NTSTATUS c2pHookUnload(PDRIVER_OBJECT DriverObject);
86 
87 
88 /* HOOK键盘 端口驱动 */
89 NTSTATUS FindDriverObject(PDRIVER_OBJECT DriverObject);        // 获取中间层端口驱动并查找设备扩展里类驱动回调例程函数地址
90 BOOLEAN searchServiceCallback(PDEVICE_OBJECT DeviceObject, PVOID DeviceExt);        // 搜索保存在设备扩展里的类驱动设备队形和回调处理函数

 

 

  Dirver.c

  1 #include "Dirver.h"
  2 #include <immintrin.h>
  3 
  4 /* 自定义键盘 类驱动设备指针和回调函数例程结构*/
  5 typedef struct _KBD_CALLBACK
  6 {
  7     PDEVICE_OBJECT DeviceObject;
  8     KeyBoardClassServiceCallback ServiceCallback;
  9 }KBD_CALLBACK, * PKBD_CALLBACK;
 10 
 11 extern POBJECT_TYPE* IoDriverObjectType;        // 通过键盘驱动对象的类型
 12 
 13 static int Kb_Status = K_NUM;                // 键盘键位按下标志
 14 static int downKeyNum = 5;                    // HOOK按键驱动KbdclassIRP处理消息的次数
 15 ULONG gC2pKeyCount = 0;                            // IRP请求计数器
 16 
 17 BOOLEAN IsAttachDevUp = 0;                    // 是否添加新设备到键盘设备栈栈顶
 18 BOOLEAN IsHookKbdIRP = 0;                    // 是否HOOK Kbdclass IRP例程
 19 
 20 PDRIVER_DISPATCH oldDriverDispatch[IRP_MJ_MAXIMUM_FUNCTION + 1] = {0};
 21 
 22 KBD_CALLBACK gKbdCallBack = { 0 };            // 设备对象指针和类驱动回调函数地址
 23 
 24 
 25 void DriverUnload(PDRIVER_OBJECT DirverObject)
 26 {
 27     UNREFERENCED_PARAMETER(DirverObject);
 28     DbgPrint("[Message]: The Driver start Unloading...\n");
 29 
 30     if (IsAttachDevUp)
 31         c2pUnload(DirverObject);
 32 
 33     if(IsHookKbdIRP)
 34         c2pHookUnload(DirverObject);
 35 }
 36 
 37 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
 38 {
 39     DbgPrint("[Message]: Start Load Driver!\n");
 40     NTSTATUS nStatus = STATUS_SUCCESS;
 41     if (!DriverObject)
 42         return STATUS_UNSUCCESSFUL;
 43 
 44     if (!RegistryPath)
 45         return STATUS_UNSUCCESSFUL;
 46 
 47     DriverObject->DriverUnload = DriverUnload;
 48 
 49     for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
 50         DriverObject->MajorFunction[i] = cwkDispatch;
 51 
 52     DriverObject->MajorFunction[IRP_MJ_READ] = c2pDispatchRead;        // 读操作分发函数
 53     DriverObject->MajorFunction[IRP_MJ_POWER] = c2pDispatchPower;    // 电源操作分发函数
 54     DriverObject->MajorFunction[IRP_MJ_PNP] = c2pDispatchPNP;        // 设备插拔分发函数
 55 
 56     ///* TODO: 设备栈顶层添加新设备*/
 57     //nStatus = c2pAttachDevices(DriverObject, RegistryPath);
 58     //if(!NT_SUCCESS(nStatus))
 59     //    DbgPrint(("[Message]: Function c2pAttachDevices Init error, Dirver Load! \n"));
 60 
 61 
 62     ///* TODO: 键盘类驱动IRP劫持 */
 63     //c2pSetHookIrp(DriverObject);
 64 
 65     nStatus = FindDriverObject(DriverObject);
 66     DbgPrint(("[Message]: Function FindDriverObject Ret %x! \n"), nStatus);
 67 
 68     KdBreakPoint();
 69 
 70     return STATUS_UNSUCCESSFUL;
 71 }
 72 
 73 // 获得键盘设备 生成虚拟设备过滤键盘
 74 NTSTATUS c2pAttachDevices(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
 75 {
 76     UNREFERENCED_PARAMETER(RegistryPath);
 77     NTSTATUS nStatus = STATUS_UNSUCCESSFUL;
 78     UNICODE_STRING UniNtNameString = { 0 };
 79     PC2P_DEV_EXT devExt;                            /* 自定义设备扩展结构 指针*/
 80     PDEVICE_OBJECT pFilterDeviceObject = NULL;        // 生成过滤设备对象指针
 81     PDEVICE_OBJECT pTargetDeviceObject = NULL;        // 绑定成功后的真实设备对象指针,函数返回赋值为0表示绑定失败
 82     PDEVICE_OBJECT pLowerDeviceObject = NULL;        // 键盘驱动设备栈的设备对象
 83     PDRIVER_OBJECT KbdDriverObject = NULL;            // 键盘驱动对象
 84     ULONG iNum = 0;                                    /* 设备栈绑定设备对象数量*/
 85 
 86     //TODO: 通过名字获取驱动对象指针, 获取完毕释放对象,保存指针
 87     RtlInitUnicodeString(&UniNtNameString, KBD_DRIVER_NAME);
 88 
 89     nStatus = ObReferenceObjectByName(&UniNtNameString, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType,
 90         KernelMode, NULL, &KbdDriverObject);
 91 
 92     // 判断获取驱动对象是否成功
 93     if (!NT_SUCCESS(nStatus))
 94     {
 95         DbgPrint("[Message]: Could't get the MyTest Device Object, ErrorCode:%x\n", nStatus);
 96         return nStatus;
 97     }
 98     DbgPrint(("[Message]: Get the MyTest Device Object OK\n"));
 99     pTargetDeviceObject = KbdDriverObject->DeviceObject;
100 
101      // 调用ObReferenceObjectByName会使驱动对象的引用计数增加,释放驱动对象引用
102     ObDereferenceObject(KbdDriverObject);
103 
104     while (pTargetDeviceObject)
105     {
106         //TODO: 生成过滤设备对象并绑定
107         // 生成过滤设备
108         nStatus = IoCreateDevice(DriverObject, sizeof(C2P_DEV_EXT), NULL, pTargetDeviceObject->DeviceType,
109             pTargetDeviceObject->Characteristics, FALSE, &pFilterDeviceObject);
110         if (!NT_SUCCESS(nStatus))
111         {
112             DbgPrint("[Message]: Could't Create the New MyFilter Device Object, ErrorCode:%x\n", nStatus);
113             return nStatus;
114         }
115 
116         // 绑定设备过滤设备
117         pLowerDeviceObject = IoAttachDeviceToDeviceStack(pFilterDeviceObject, pTargetDeviceObject);
118         if (!pLowerDeviceObject)
119         {
120             DbgPrint(("[Message]: Could't attach to MyTest Device Object\n"));
121             IoDeleteDevice(pFilterDeviceObject);
122             pFilterDeviceObject = NULL;
123             return (nStatus);
124         }
125 
126         //TODO:  初始化设备对象扩展(生成设备对象时指定的大小)
127         devExt = (PC2P_DEV_EXT)(pFilterDeviceObject->DeviceExtension);
128         c2pDevExtInit(devExt, pFilterDeviceObject, pTargetDeviceObject, pLowerDeviceObject);
129 
130         DbgPrint("[Message]: DeviceObject=[%p] ,pFilterDevObj=[%p], pTargetDevObj=[%p], pLowerDevObj=[%p]\n", pFilterDeviceObject,
131             devExt->FilterDeviceObject, pTargetDeviceObject, pLowerDeviceObject);
132 
133         //TODO:  拷贝复制重要标志和属性
134         pFilterDeviceObject->DeviceType = pLowerDeviceObject->DeviceType;
135         pFilterDeviceObject->Characteristics = pLowerDeviceObject->Characteristics;
136         pFilterDeviceObject->StackSize = pLowerDeviceObject->StackSize;
137         pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);
138         DbgPrint("[Message]:The Device Object is Nunber %u", iNum++);
139         pTargetDeviceObject = pTargetDeviceObject->NextDevice;
140     }
141     DbgPrint("[Message]:The Driver Object's have Device Object %u\n", iNum);
142 
143     IsAttachDevUp = 1;
144     return nStatus;
145 }
146 
147 
148 NTSTATUS c2pDevExtInit(PC2P_DEV_EXT devExt, PDEVICE_OBJECT pFilterDeviceObject,
149             PDEVICE_OBJECT pTargetDeviceObject, PDEVICE_OBJECT pLowerDeviceObject)
150 {
151     //TODO: 重置PC2P_DEV_EXT设备结构
152     memset(devExt, 0, sizeof(C2P_DEV_EXT));
153     devExt->NodeSize = sizeof(C2P_DEV_EXT);
154 
155     //TODO: 初始化结构里的自旋锁
156     KeInitializeSpinLock(&(devExt->IoRequestsSpinLock));
157     KeInitializeEvent(&(devExt->IoInProgressEvent), NotificationEvent, FALSE);
158     
159     //TODO: 结构体 设备对象指针赋值
160     devExt->FilterDeviceObject = pFilterDeviceObject;
161     devExt->TargetDeviceObject = pTargetDeviceObject;
162     devExt->LowerDeviceObject = pLowerDeviceObject;
163     return STATUS_SUCCESS;
164 }
165 
166 // 删除绑定的过滤设备
167 VOID c2pUnload(IN PDRIVER_OBJECT DriverObject)
168 {
169     PDEVICE_OBJECT DeviceObject= NULL;
170     PKTHREAD CurrentThread = NULL;            // 当前线程
171     LARGE_INTEGER Interval = {0};            // 线程等待时间
172 
173     //TODO: 获取当前线程句柄并设置线程优先级为实时优先级
174     CurrentThread = KeGetCurrentThread();
175     KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY);
176 
177     //TODO:    循环遍历本驱动设备栈所有设备,解除设备绑定并删除
178     DeviceObject = DriverObject->DeviceObject;
179 
180     while (DeviceObject)
181     {
182         c2pDetach(DeviceObject);        // 解除设备绑定
183         DeviceObject = DeviceObject->NextDevice;
184     }
185     ASSERT(DriverObject->DeviceObject == NULL);
186 
187     //TODO:    设置线程等待时间
188     Interval.QuadPart = 500 * ((-10) * 1000);        // 500毫秒
189     //Interval = RtlConvertLongToLargeInteger(500* ( (-10)*1000 ) );
190     while (gC2pKeyCount)
191         KeDelayExecutionThread(KernelMode, FALSE, &Interval);
192 
193     DbgPrint("[Message]: The Device of this driver unloading OK!\n");
194     return;
195 }
196 
197 VOID c2pDetach(IN PDEVICE_OBJECT DeviceObject)
198 {
199     PC2P_DEV_EXT devExt = NULL;
200     //TODO: 获取设备对象的扩展
201 
202     devExt = DeviceObject->DeviceExtension;
203     if (!devExt->FilterDeviceObject)
204         return;
205 
206     //TODO: 解除设备扩展里面绑定的设备对象的绑定
207     IoDetachDevice(devExt->TargetDeviceObject);
208     devExt->FilterDeviceObject = NULL;
209     devExt->TargetDeviceObject = NULL;
210     devExt->LowerDeviceObject = NULL;
211     IoDeleteDevice(DeviceObject);
212     return;
213 }
214 
215 // 主要驱动分发函数(所有不处理的IRP)
216 NTSTATUS cwkDispatch(PDEVICE_OBJECT dev, PIRP Irp)
217 {
218     // TODO: 请求不处理, 将请求直接下发
219     IoSkipCurrentIrpStackLocation(Irp);
220     return IoCallDriver(((PC2P_DEV_EXT)(dev->DeviceExtension))->LowerDeviceObject, Irp);    // 将IRP发送给真实设备的驱动
221 }
222 
223 
224 // 电源操作例程
225 NTSTATUS c2pDispatchPower(PDEVICE_OBJECT dev, PIRP Irp)
226 {
227 
228     //UNREFERENCED_PARAMETER(dev);
229     //PDRIVER_OBJECT KbdDriverObject = NULL;
230     //UNICODE_STRING DirverName;
231     //NTSTATUS nStatus = STATUS_UNSUCCESSFUL;
232 
233     //RtlInitUnicodeString(&DirverName, KBD_DRIVER_NAME);
234     //nStatus = ObReferenceObjectByName(&DirverName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType,
235     //    KernelMode, NULL, &KbdDriverObject);
236     //if (!NT_SUCCESS(nStatus))
237     //{
238     //    DbgPrint("[Message]: Could't get the MyTest Device Object, ErrorCode:%x\n", nStatus);
239     //    return nStatus;
240     //}
241     //DbgPrint("[Message]: Try error code start\n");
242     //KbdDriverObject->MajorFunction[IRP_MJ_POWER](KbdDriverObject->DeviceObject, Irp);
243     //DbgPrint("[Message]: Try error code End\n");
244 
245     //ObDereferenceObject(KbdDriverObject);
246     PoStartNextPowerIrp(Irp);
247     IoSkipCurrentIrpStackLocation(Irp);
248     return PoCallDriver(((PC2P_DEV_EXT)(dev->DeviceExtension))->LowerDeviceObject, Irp);    // 替代函数IoCallDriver
249 }
250 
251 
252 NTSTATUS c2pDispatchPNP(PDEVICE_OBJECT dev, PIRP Irp)
253 { 
254     PIO_STACK_LOCATION Irpsp = NULL;
255     PC2P_DEV_EXT devExt = NULL;
256     NTSTATUS nStatus = STATUS_UNSUCCESSFUL;
257 
258     // TODO; 请求直接下发, 然后判断是否是硬件拔出,如果是硬件拔出解除设备绑定,删除生成的过滤设备, 
259     Irpsp = IoGetCurrentIrpStackLocation(Irp);
260     devExt = dev->DeviceExtension;
261     IoSkipCurrentIrpStackLocation(Irp);
262     nStatus = IoCallDriver(devExt->LowerDeviceObject, Irp);
263     if (Irpsp->MinorFunction == IRP_MN_REMOVE_DEVICE)
264     {
265         DbgPrint("[Messag]: The device IRP_MN_REMOVE_DEVICE !\n");
266         c2pDetach(dev);
267     }
268     return nStatus;
269 }
270 
271 
272 NTSTATUS c2pDispatchRead(PDEVICE_OBJECT dev, PIRP Irp)
273 {
274     //PIO_STACK_LOCATION Irpsp = NULL;
275     //TODO: 判断当前IRP是否在IRP栈最底端,如果是 这是错误的请求,结束IRP传递, 返回IRP
276     if (Irp->CurrentLocation == 1)
277     {
278         DbgPrint("[Message]: ->Error Dispatch encountered bogus current location\n");
279         Irp->IoStatus.Information = 0;
280         Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
281         IoCompleteRequest(Irp, IO_NO_INCREMENT);
282         return STATUS_INVALID_DEVICE_REQUEST;
283     }
284     //TODO: 不在IRP栈最底端,IRP计数器加1
285     gC2pKeyCount++;
286     //TODO: 获取被过滤设备指针, 拷贝当前IRP栈空间,设置完成例程发送给下层驱动
287     IoCopyCurrentIrpStackLocationToNext(Irp);
288     IoSetCompletionRoutine(Irp, c2pReadCompletion, dev, TRUE, TRUE, TRUE);
289     return IoCallDriver(((PC2P_DEV_EXT)(dev->DeviceExtension))->LowerDeviceObject, Irp);
290 }
291 
292 // IRP完成回调函数
293 NTSTATUS c2pReadCompletion(PDEVICE_OBJECT    dev, PIRP Irp, PVOID Context)
294 {
295     UNREFERENCED_PARAMETER(dev);
296     UNREFERENCED_PARAMETER(Context);
297     //TODO:    IRP计数器减1,
298     gC2pKeyCount--;
299 
300     //TODO: 判断当前IRP请求是否执行成功,如果执行成功读取设备流过数据,否则数据没有意义
301     if (NT_SUCCESS(Irp->IoStatus.Status))
302         c2pDataAnalysis(Irp);
303 
304     // 判断IRP的调度标识是否时是挂起状态, 如果否,手动设置IRP调度挂起状态
305     if (Irp->PendingReturned)
306         IoMarkIrpPending(Irp);
307 
308     return Irp->IoStatus.Status;
309 }
310 
311 
312 // 获取的数据解析键扫描码
313 void c2pDataAnalysis(PIRP Irp)
314 {
315     KEYBOARD_INPUT_DATA* pKeyData = NULL;                /* 设备流过数据*/
316     LONGLONG bufLen = 0;            /* 数据长度*/
317     ULONGLONG KeyBoardNum = 0;            // KEYBOARD_INPUT_DATA结构个数
318     pKeyData = Irp->AssociatedIrp.SystemBuffer;
319     bufLen = Irp->IoStatus.Information;
320     KeyBoardNum = bufLen / sizeof(KEYBOARD_INPUT_DATA);
321     for (int i = 0; i < KeyBoardNum; i++)
322     {
323         /*
324         switch (pKeyData->Flags)
325         {
326         case 0:
327             DbgPrint("[Message]: 键盘按下,ScanCode[%x]", pKeyData->MakeCode);
328             break;
329         case 1:
330             DbgPrint("[Message]: 键盘弹起,ScanCode[%x]", pKeyData->MakeCode);
331             break;
332         default:
333             DbgPrint("[Message]: 键盘操作,ScanCode[%x]", pKeyData->MakeCode);
334             break;
335         }
336 
337         //测试,这里将扫描码++操作, 证实键盘按键是可以拦截修改的
338         pKeyData->MakeCode += 1;
339         */
340 
341         // 键盘按下
342         if (!pKeyData->Flags)
343             c2pKeyboardDown((UCHAR)pKeyData->MakeCode);
344         
345         // Shfit键弹起的时候, 还原Shfit标志
346         if(pKeyData->Flags && (pKeyData->MakeCode== 0x36|| pKeyData->MakeCode == 0x2a))
347             Kb_Status ^= K_SHFIT;
348 
349         pKeyData++;
350     }
351 
352     return;
353 }
354 
355 void __stdcall c2pKeyboardDown(UCHAR uch)
356 {
357     //如果uch小于十进制128,则结果等于,if表达式成立
358     //if ((uch & 0x80) == 0)
359     //{
360     //    if (uch < 0x47 || (uch >= 0x47 && uch < 0x54 && Kb_Status & K_NUM))
361     //        ch = 0;
362     //}
363     UCHAR ch = 0;
364     switch (uch)
365     {
366     case 0x3a:        // 按下大小写键 CapsLock
367         Kb_Status ^= K_CAPS;
368         return;
369 
370     case 0x36:        // 右Sshfit键
371     case 0x2a:        // 左Shfit键
372         Kb_Status |= K_SHFIT;
373         return;
374 
375     case 0x45:        // NumLock键
376         Kb_Status ^= K_NUM;
377         return;
378 
379     default:
380         break;
381     }
382 
383     ch = KeyboarFindAssic(uch);
384     if(ch)
385         DbgPrint("[Message]: 键盘按下-->ScanCode[%x], Data:[%c]\n", uch, ch);
386 }
387 
388 UCHAR __stdcall KeyboarFindAssic(UCHAR uch)
389 {
390     char ch = 0;
391     // 根据uch的值为索引去寻找自定义数组中存储的对应的ASIIC码的值  键盘扫描码表和ASCII码表中所代表的字符在表中的索引不同
392     
393     if ((uch >= 0x2 && uch <= 0xd))        
394         (Kb_Status & K_SHFIT) ? (ch = IsShfit[uch]) : (ch = UnShift[uch]);
395 
396     else if (uch >= 0x10 && uch <= 0x19)
397     {
398         if (Kb_Status & K_SHFIT)    // 判断是否 开了大写键的同时按下Shift键
399             (Kb_Status & K_CAPS) ? (ch = UnShift[uch]) : (ch = IsShfit[uch]);
400         else
401             (Kb_Status & K_CAPS) ? (ch = IsShfit[uch]) : (ch = UnShift[uch]);
402     }
403     
404     return ch;
405 }
406 
407 NTSTATUS c2pSetHookIrp(PDRIVER_OBJECT DriverObject)
408 {
409     UNREFERENCED_PARAMETER(DriverObject);
410     PDRIVER_OBJECT KbdDriverObject = NULL;
411     UNICODE_STRING DirverName;
412     NTSTATUS nStatus = STATUS_UNSUCCESSFUL;
413 
414     RtlInitUnicodeString(&DirverName, KBD_DRIVER_NAME);
415     nStatus = ObReferenceObjectByName(&DirverName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType,
416         KernelMode, NULL, &KbdDriverObject);
417     if (!NT_SUCCESS(nStatus))
418     {
419         DbgPrint("[Message]: Could't get the MyTest Device Object, ErrorCode:%x\n", nStatus);
420         return nStatus;
421     }
422     DbgPrint("[Message]: Function c2pHookDispatch Address:%p KbdDriverObject[IRP_MJ_READ]=%p\n", c2pHookDispatch,
423                                                     KbdDriverObject->MajorFunction[IRP_MJ_READ]);
424     for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
425     {
426         oldDriverDispatch[i] = KbdDriverObject->MajorFunction[i];
427         //KbdDriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)&c2pHookDispatch;
428         InterlockedExchangePointer((PVOID*)&KbdDriverObject->MajorFunction[i], (PVOID)&c2pHookDispatch);
429     }
430 
431 
432     DbgPrint("[Message]: oldDispatchFunc:%p  newHookDispatch=%p\n", oldDriverDispatch[IRP_MJ_READ],
433             KbdDriverObject->MajorFunction[IRP_MJ_READ]);
434     
435     ObDereferenceObject(KbdDriverObject);
436     IsHookKbdIRP = 1;
437     return STATUS_SUCCESS;
438 }
439 
440 NTSTATUS  c2pHookDispatch(PDEVICE_OBJECT dev, PIRP Irp)
441 {
442 
443     ULONG IrpType = 0;            // IRP消息宏
444     PIO_STACK_LOCATION isIrp = IoGetCurrentIrpStackLocation(Irp);
445 
446     IrpType = isIrp->MajorFunction;
447     DbgPrint("[Message]: Hook Kbdclass Get Data Start -------------\n");
448     if (IrpType == IRP_MJ_READ && NT_SUCCESS(Irp->IoStatus.Status))
449         c2pHookReadDisp(dev, Irp);
450 
451     oldDriverDispatch[IrpType](dev, Irp);
452 
453     if (IrpType == IRP_MJ_READ && NT_SUCCESS(Irp->IoStatus.Status))
454         c2pHookReadDisp(dev, Irp);
455 
456     DbgPrint("[Message]: -------------Hook Kbdclass Get Data End\n");
457     downKeyNum--;
458     return Irp->IoStatus.Status;
459 }
460 
461 NTSTATUS  c2pHookReadDisp(PDEVICE_OBJECT dev, PIRP Irp)        // Hook读消息例程
462 {
463     UNREFERENCED_PARAMETER(dev);
464     PKEYBOARD_INPUT_DATA pBuf = NULL;
465     ULONGLONG buLen = 0;
466     ULONGLONG boardNum = 0;
467     
468     pBuf = Irp->AssociatedIrp.SystemBuffer;
469     buLen = Irp->IoStatus.Information;
470     boardNum = buLen / sizeof(C2P_DEV_EXT);
471     DbgPrint("[Message]: Hook Kbdclass , Buffer Size:%8x\n", buLen);
472     for (int i = 0; i < boardNum; i++)
473     {
474         // 键盘按下
475         if (!pBuf->Flags)
476             c2pKeyboardDown((UCHAR)pBuf->MakeCode);
477             
478         // Shfit键弹起的时候, 还原Shfit标志
479         if (pBuf->Flags && (pBuf->MakeCode == 0x36 || pBuf->MakeCode == 0x2a))
480             Kb_Status ^= K_SHFIT;
481 
482         pBuf++;
483     }
484 
485     return Irp->IoStatus.Status;
486 }
487 
488 NTSTATUS c2pHookUnload(PDRIVER_OBJECT DriverObject)
489 {
490     UNREFERENCED_PARAMETER(DriverObject);
491     PDRIVER_OBJECT KbdDriverObject = NULL;
492     UNICODE_STRING DirverName;
493     NTSTATUS nStatus = STATUS_UNSUCCESSFUL;
494 
495     RtlInitUnicodeString(&DirverName, KBD_DRIVER_NAME);
496     nStatus = ObReferenceObjectByName(&DirverName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType,
497         KernelMode, NULL, &KbdDriverObject);
498     if (!NT_SUCCESS(nStatus))
499     {
500         DbgPrint("[Message]:HookUnload Could't get the MyTest Device Object, ErrorCode:%x\n", nStatus);
501         return nStatus;
502     }
503 
504     for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
505         KbdDriverObject->MajorFunction[i] = oldDriverDispatch[i];
506 
507     DbgPrint("[Message]: Unload Kbdclass Hook OK!\n");
508     ObDereferenceObject(KbdDriverObject);
509     return STATUS_SUCCESS;
510 }
511 
512 // 获取中间层端口驱动并查找设备扩展里类驱动回调例程函数地址
513 NTSTATUS FindDriverObject(PDRIVER_OBJECT DriverObject)
514 {
515     UNREFERENCED_PARAMETER(DriverObject);
516     NTSTATUS nStatus = STATUS_SUCCESS;
517     UNICODE_STRING DirverNameString = { 0 };
518     PDRIVER_OBJECT KbdhidDriverObject = NULL;        // USB键盘驱动对象指针
519     PDRIVER_OBJECT i8042DirverObject = NULL;        // PS2键盘驱动对象指针
520     PDRIVER_OBJECT usingDriverObject = NULL;    // 保存获取成功的驱动对象指针
521     PDEVICE_OBJECT usingDeviceObject = NULL;    // 保存驱动对象的设备指针
522     PVOID DeviceExt = NULL;                        // 指向设备对象扩展
523     
524     // TODO: 获取USB键盘和PS/2键盘的驱动对象
525         // 获取USB键盘端口驱动
526     RtlInitUnicodeString(&DirverNameString, USBKBD_DRIVER_NAME);
527     nStatus = ObReferenceObjectByName(&DirverNameString, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType,
528         KernelMode, NULL, &KbdhidDriverObject);
529     if (NT_SUCCESS(nStatus))
530     {
531         ObDereferenceObject(KbdhidDriverObject);
532         DbgPrint("[Message]: Get USB Driver Object OK!\n");
533     }else
534         DbgPrint("[Message]: Get USB Driver Object fail ErrorCode=%X!\n", nStatus);
535 
536         // 获取PS/2键盘端口驱动
537     RtlInitUnicodeString(&DirverNameString, PS2KBD_DRIVER_NAME);
538     nStatus = ObReferenceObjectByName(&DirverNameString, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType,
539         KernelMode, NULL, &i8042DirverObject);
540     if (NT_SUCCESS(nStatus))
541     {
542         ObDereferenceObject(i8042DirverObject);
543         DbgPrint("[Message]: Get PS/2 Driver Object OK!\n");
544     }else
545         DbgPrint("[Message]: Get PS/2 Driver Object fail ErrorCode=%X!\n", nStatus);
546 
547     // TODO: 只考虑两种类型的键盘驱动只有一个起作用的情况下,如果同时搜索到两种型号的键盘驱动或者未搜索到直接返回错误
548     if (KbdhidDriverObject && i8042DirverObject)
549     {
550         DbgPrint("[Message]: Get PS/2 driver object and  USB driver object at the same time!\n");
551         return STATUS_UNSUCCESSFUL;
552     }
553     if (KbdhidDriverObject == 0 && i8042DirverObject == 0)
554     {
555         DbgPrint("[Message]: Get PS/2 driver object and  USB driver object at the fail!\n");
556         return STATUS_UNSUCCESSFUL;
557     }
558     // TODO: 如果搜索到两种端口驱动中的其中一个驱动,获取驱动设备,获取设备的扩展,驱动空间起始地址和大小
559     usingDriverObject = KbdhidDriverObject ? KbdhidDriverObject : i8042DirverObject;
560     usingDeviceObject = usingDriverObject->DeviceObject;
561     DeviceExt = usingDriverObject->DriverExtension;
562     if (!searchServiceCallback(usingDeviceObject, DeviceExt))
563         return STATUS_UNSUCCESSFUL;
564 
565     return STATUS_SUCCESS;
566 }
567 
568 // 搜索保存在设备扩展里的 类驱动设备队形和回调处理函数
569 BOOLEAN searchServiceCallback(PDEVICE_OBJECT DeviceObject, PVOID DeviceExt)
570 {
571     NTSTATUS nStatus = STATUS_SUCCESS;
572     UNICODE_STRING DriverName = { 0 };
573     PDRIVER_OBJECT KbdClassObject = NULL;            // 键盘 类驱动指针
574     PVOID KbdDriverStart = NULL;                    // 驱动起始地址
575     ULONG KbdDriverSize = 0;                        // 驱动大小
576     PDEVICE_OBJECT TempDeviceObject = NULL;            // 临时设备对象指针
577     PCHAR usingDeviceExt;                            // 设备扩展遍历指针
578     PVOID AddreServiceCallback = NULL;
579     KBD_CALLBACK m_KbdCallBack = { 0 };
580     
581     // TODO: 获取类驱动对象
582     RtlInitUnicodeString(&DriverName, KBD_DRIVER_NAME);
583     nStatus = ObReferenceObjectByName(&DriverName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, KernelMode,
584         NULL, &KbdClassObject);
585     if (!NT_SUCCESS(nStatus))
586     {
587         DbgPrint("[Message]: Get Kbdclass driver object at the fail!\n");
588         return FALSE;
589     }
590     KbdDriverStart = KbdClassObject->DriverStart;
591     KbdDriverSize = KbdClassObject->DriverSize;
592     DbgPrint("[Message]: Kbdclass driver Address %p - %p!\n", KbdDriverStart, (PCHAR)KbdDriverStart+KbdDriverSize);
593     // TODO: 遍历扩展里数据 是否有类驱动对象里的设备或者在类驱动里的地址,如果有保存
594     TempDeviceObject = DeviceObject;
595     while (TempDeviceObject)
596     {
597         usingDeviceExt = DeviceExt;
598         for (int i = 0; i < 4096; i++, usingDeviceExt += sizeof(PCHAR))
599         {
600             PVOID tmp;
601             if (!MmIsAddressValid(usingDeviceExt))
602                 break;
603 
604             if (m_KbdCallBack.DeviceObject && m_KbdCallBack.ServiceCallback)
605             {
606                 gKbdCallBack.DeviceObject = m_KbdCallBack.DeviceObject;
607                 gKbdCallBack.ServiceCallback = m_KbdCallBack.ServiceCallback;
608             }
609 
610             tmp = *(PVOID*)usingDeviceExt;
611 
612             if (tmp == TempDeviceObject)
613             {
614                 m_KbdCallBack.DeviceObject = *(PVOID*)tmp;
615                 DbgPrint("[Message]: Get the kbdclass driver at the Device OK!  DeviceObject=%p\n", m_KbdCallBack.DeviceObject);
616                 continue;
617             }
618 
619             // 键盘类驱动处理函数位于驱动设备之后,并且由于使用了未公开数据结构,这种方式可能暂时是有效的或者在某些情况下是有效的
620             if (tmp > KbdDriverStart && tmp < (PVOID)((PCHAR)KbdDriverStart + KbdDriverSize)&& MmIsAddressValid(tmp))
621             {
622                 if (!m_KbdCallBack.DeviceObject)
623                     continue;
624                 m_KbdCallBack.ServiceCallback = (KeyBoardClassServiceCallback)tmp;
625                 AddreServiceCallback = (PVOID)usingDeviceExt;
626                 DbgPrint("[Message]: Get the kbdclass driver at the Callback OK!  tmp=%p AddreServiceCallback=%p!\n", *(PVOID*)usingDeviceExt, (PVOID)usingDeviceExt);
627             }
628         }
629         TempDeviceObject = TempDeviceObject->NextDevice;
630     }
631 
632     if (AddreServiceCallback && m_KbdCallBack.DeviceObject)
633     {
634         DbgPrint("[Message]: AddreServiceCallback=%p m_KbdCallBack.DeviceObject=%p m_KbdCallBack.ServiceCallback= %p\n",  
635             AddreServiceCallback, m_KbdCallBack.DeviceObject, m_KbdCallBack.ServiceCallback);
636         return TRUE;
637     }
638     return FALSE;
639 }

 

posted @ 2021-04-21 19:21  伤痕累累的笨蛋  阅读(470)  评论(0编辑  收藏  举报