阅读:1263回复:5
请问一个键盘过滤驱动的问题
我参考Ctrl2cap做了一个键盘过滤驱动,总是出问题,请帮忙看一下。我只列重点的部分,太多不好看
入口代码 NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath ) { NTSTATUS status = STATUS_SUCCESS; int i; __try { DbgPrint(" DriverEntry... \n"); g_DriverObject.pDriverObj = theDriverObject; for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { g_DriverObject.pDriverObj->MajorFunction = DispatchMajorFunction; } g_DriverObject.pDriverObj->DriverUnload = DriverUnload; status = CreateDeviceAndLink(DEVICE_NAME,LINK_NAME); 。。。。。。 } 然后就是创建设备对象的代码,我创建了两个,一个是FILE_DEVICE_UNKNOWN,一个是FILE_DEVICE_KEYBOARD //创建设备和符号 NTSTATUS CreateDeviceAndLink(PCWSTR DeviceName,PCWSTR LinkName) { NTSTATUS status = STATUS_SUCCESS; CCHAR ntNameBuffer[64]; STRING ntNameString; UNICODE_STRING ntUnicodeString; __try { DbgPrint(" CreateDeviceAndLink …… \n"); // 创建、初始化设备对象 // 设备名称 RtlInitUnicodeString(&g_DriverObject.ustrDevName, DeviceName); // 创建设备对象 status = IoCreateDevice(g_DriverObject.pDriverObj, sizeof(DEVICE_EXTENSION), // 为设备扩展结构申请空间, &g_DriverObject.ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_DriverObject.pDeviceObj); if(!NT_SUCCESS(status)) { DbgPrint(" CreateDevice Failed \n"); return status; } // 创建符号连接名称 // 符号连接名称 RtlInitUnicodeString(&g_DriverObject.ustrLinkName, LinkName); // 创建关联 status = IoCreateSymbolicLink(&g_DriverObject.ustrLinkName, &g_DriverObject.ustrDevName); if(!NT_SUCCESS(status)) { DbgPrint(" CreateLink Failed \n"); IoDeleteDevice(g_DriverObject.pDeviceObj); return status; } //创建键盘对象 sprintf( ntNameBuffer, "\\Device\\KeyboardClass0" ); RtlInitAnsiString( &ntNameString, ntNameBuffer ); RtlAnsiStringToUnicodeString( &ntUnicodeString, &ntNameString, TRUE ); status = IoCreateDevice( g_DriverObject.pDriverObj, 0, NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &g_DriverObject.pKBDDeviceObj ); if( !NT_SUCCESS(status) ) { DbgPrint(("Ctrl2cap: Keyboard hook failed to create device!\n")); RtlFreeUnicodeString( &ntUnicodeString ); return STATUS_SUCCESS; } // // Keyboard uses buffered I/O so we must as well. // g_DriverObject.pKBDDeviceObj->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; g_DriverObject.pKBDDeviceObj->Flags &= ~DO_DEVICE_INITIALIZING; // // Attach to the keyboard chain. // status = IoAttachDevice( g_DriverObject.pKBDDeviceObj, &ntUnicodeString, &g_DriverObject.pKbdTopOfStack ); if( !NT_SUCCESS(status) ) { DbgPrint(("Ctrl2cap: Connect with keyboard failed!\n")); IoDeleteDevice( g_DriverObject.pKBDDeviceObj ); RtlFreeUnicodeString( &ntUnicodeString ); } RtlFreeUnicodeString( &ntUnicodeString ); DbgPrint(" CreateDeviceAndLink OK \n"); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("Exception occured, caught in CreateDeviceAndLink(). Unknown error\n"); } return status; } 然后就是在这里,IoAttachDevice的时候,前面设置的DispatchMajorFunction函数被调用了,这个函数是这样的: NTSTATUS DispatchMajorFunction(PDEVICE_OBJECT pDevObj, PIRP pIrp) { //这里需要对驱动对象进行区分 __try { PIO_STACK_LOCATION irpStack = NULL; PIO_STACK_LOCATION nextIrpStack = NULL; irpStack = IoGetCurrentIrpStackLocation(pIrp); //键盘设备对象 if(pDevObj==g_DriverObject.pKBDDeviceObj) { pIrp->IoStatus.Status = STATUS_SUCCESS; switch(irpStack->MajorFunction) { case IRP_MJ_READ: nextIrpStack = IoGetNextIrpStackLocation(pIrp); *nextIrpStack = *irpStack; IoSetCompletionRoutine(pIrp, OnKbdReadComplete, pDevObj, TRUE, TRUE, TRUE ); // Return the results of the call to the keyboard class driver. return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp); default: pIrp->CurrentLocation++; pIrp->Tail.Overlay.CurrentStackLocation++; // pass this onto whoever we stole it from... return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp); } } //默认的设备对象 else if(pDevObj==g_DriverObject.pDeviceObj) { switch(irpStack->MajorFunction) { case IRP_MJ_CREATE: case IRP_MJ_CLOSE: return DispatchCreateClose(pDevObj,pIrp); case IRP_MJ_DEVICE_CONTROL: return DispatchIoctl(pDevObj,pIrp); } } // 完成请求 pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } __finally { DbgPrint("Exception occured, caught in DispatchMajorFunction(). Unknown error\n"); } return STATUS_SUCCESS; } 第一次调用到这个函数的时候执行了 default: pIrp->CurrentLocation++; pIrp->Tail.Overlay.CurrentStackLocation++; // pass this onto whoever we stole it from... return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp); 这部分代码,然后就在IoCallDriver出错了~ 以后每次到这个函数都会在调用IoCallDriver是出错。请问是哪儿的问题啊? |
|
沙发#
发布于:2008-04-13 22:01
用ctrl2cap的代码倒是不会出错,但是
status = IoAttachDevice( HookDeviceObject, &ntUnicodeString, &kbdDevice ); 这样连接上以后如何删除呢? VOID DriverUnload(PDRIVER_OBJECT pDriverObj) { IoDetachDevice(kbdDevice); IoDeleteDevice(HookDeviceObject); } 这样的方式会出错 |
|
板凳#
发布于:2008-04-13 22:58
用ctrl2cap的代码倒是不会出错,是不是我的
DispatchMajorFunction函数写的有问题呢? 另外, status = IoAttachDevice( HookDeviceObject, &ntUnicodeString, &kbdDevice ); 这样连接上以后如何删除呢? VOID DriverUnload(PDRIVER_OBJECT pDriverObj) { IoDetachDevice(kbdDevice); IoDeleteDevice(HookDeviceObject); } 这样的方式会出错 |
|
地板#
发布于:2008-04-15 23:23
用户被禁言,该主题自动屏蔽! |
|
地下室#
发布于:2008-04-16 00:01
TO tracera:
深表感谢! 我参考了SINISTER的一篇键盘过滤驱动的文章,还有rootkit网站的klog的代码,这个地方大概明白了,需要等待到最后一个键盘读IRP处理完才退出。 但是还有一个问题,我用 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction = DispatchMajorFunction; } 把所有处理过程放一起了,而原程序是分开的(IRP_MJ_READ是单独的)。结果这个统一处理的函数总是出意外: NTSTATUS DispatchMajorFunction(PDEVICE_OBJECT pDevObj, PIRP pIrp) { //这里需要对设备对象进行区分,也许会有多个 __try { PIO_STACK_LOCATION irpStack = NULL; PIO_STACK_LOCATION nextIrpStack = NULL; irpStack = IoGetCurrentIrpStackLocation(pIrp); //键盘设备对象 if(pDevObj==HookDeviceObject) { pIrp->IoStatus.Status = STATUS_SUCCESS; switch(irpStack->MajorFunction) { case IRP_MJ_READ: nextIrpStack = IoGetNextIrpStackLocation(pIrp); *nextIrpStack = *irpStack; IoSetCompletionRoutine(pIrp, Ctrl2capReadComplete, pDevObj, TRUE, TRUE, TRUE ); // Return the results of the call to the keyboard class driver. return IoCallDriver(kbdDevice, pIrp); default: pIrp->CurrentLocation++; pIrp->Tail.Overlay.CurrentStackLocation++; // pass this onto whoever we stole it from... return IoCallDriver(kbdDevice, pIrp);//就是这里,第一次调用到这里就出错了!看起来和分开写的没什么区别呀 } } else { pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest (pIrp, IO_NO_INCREMENT ); } } __finally { DbgPrint("Exception occured, caught in DispatchMajorFunction(). Unknown error\n"); } return pIrp->IoStatus.Status; } 我不是做驱动开发的,只是对有些东西比较感兴趣,只了解一些皮毛,基础不好 ![]() 我打算一点一点把没问题的代码改变为有问题的代码,看看到底是哪不对。 不过还是希望能看出问题的大虾指点一下啊~我的机器已经蓝屏N多次了~痛苦~ |
|
5楼#
发布于:2008-04-19 17:30
真是奇怪了,我把
switch(irpStack->MajorFunction) { case IRP_MJ_READ: nextIrpStack = IoGetNextIrpStackLocation(pIrp); *nextIrpStack = *irpStack; IoSetCompletionRoutine(pIrp, Ctrl2capReadComplete, pDevObj, TRUE, TRUE, TRUE ); // Return the results of the call to the keyboard class driver. return IoCallDriver(kbdDevice, pIrp); default: pIrp->CurrentLocation++; pIrp->Tail.Overlay.CurrentStackLocation++; // pass this onto whoever we stole it from... return IoCallDriver(kbdDevice, pIrp); } 改为 if(IRP_MJ_READ == (currentIrpStack->MajorFunction)) { *nextIrpStack = *currentIrpStack; IoSetCompletionRoutine( Irp, Ctrl2capReadComplete, DeviceObject, TRUE, TRUE, TRUE ); //µ÷ÓÃÍê³ÉÀý³Ì // // ½« IRP ¼ÆÊýÆ÷¼ÓÒ»£¬ÎªÖ§³Ö SMP ʹÓÃ×ÔÐýËø // KeAcquireSpinLock( &MySpinLock, &IrqLevel ); InterlockedIncrement( &g_number_of_pending_IRPs ); KeReleaseSpinLock( &MySpinLock, IrqLevel ); return IoCallDriver( kbdDevice, Irp ); } else { IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver( kbdDevice, Irp ); } 就没问题了。不知道是为什么 |
|