键盘过滤(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 }
Windows驱动学习