现在的位置: 首页 > 综合 > 正文

USB过滤驱动,实现U盘只读控制

2014年02月10日 ⁄ 综合 ⁄ 共 2635字 ⁄ 字号 评论关闭



看到很多人都把自己的东西拿出来共享,我也来写一点。

功能:

这是一个简单的USB过滤驱动,采用标准的WDM过滤,以DDK中的filter为原形。实现了U盘的只读控制。

说明:

1 在整个编写过程中,受到tiamo等众多高手的帮助,感激不尽。还要向他们多多学习。

2 这是我写的具有具体功能的第一个驱动,高兴。

3 本人是一位就读于排名在300名以外的大学的大四学生,水平有限,有错误的地方请各位指出。见笑了。

开发中使用的工具和环境:

vc 6.0+2000ddk 用DbgViewer查看信息。 用DeviceTree查看驱动加载情况

正文:

我从开始看驱动就认为,一个完整的驱动是改出来的。

因此我修改了ddk中toaster/filter程序。这个程序写的思路很清晰,把一个标准的过滤驱动程序应该有的各个模块都写了出来。特

别是很完整的做了PNP的相关操作。

作为一个标准过滤驱动,应该在AddDevice中将创建的设备IoAttachDeviceToDeviceStack到欲过滤的设备上。而这个设备就是

AddDevice的第二个参数。这里要说明的是,我过滤的设备对象是usbstor.sys,是一个FlowerFilters。 在注册表中加入相应的项(这个

过程应该是INF做的,我不会做,因此直接加的),系统在加载usbstor.sys这个驱动的时候,根据注册表中FlowerFilters对应的值就会

自动去加载你的驱动,非常的方便。

系统加载你的设备以后就进入了AddDevice,此时你可以IoAttachDeviceToDeviceStack,填写你的PDEVICE_EXTENSION等等。

这样完成以后,你的设备就可以在DeviceTree中看到,位置在USBSTOR打开以后,展开可以看到。

剩下的不用我说,大家也知道。就是拦截相应的IRP了。对应不同的过滤功能,需要拦截的IRP也不同,以我这为例子,我想拦截

所有的写操作,就是使U盘成为只读的。开始我去拦截IRP_MJ_WRITE,跟踪发现,写U盘的时候根本不走这个地方。询问后知道要

拦截相应的scsi命令,关于SCSI命令有相关的规范去看。对SCSI命令的取得和操作大致如下:

1 得到当前的SCSI命令:

DbgPrint(/"IRP_MJ_SCSI/");

irpStack = IoGetCurrentIrpStackLocation(irp);

CurSrb=irpStack->Parameters.Scsi.Srb;

cdb=CurSrb->Cdb;

opCode=cdb->CDB6GENERIC.OperationCode;

现在opCode中就是当前的SCSI命令。

2 分析SCSI命令(由于SCSI命令很多,找到真正要拦截的SCSI命令,还需要参看实例)

if(opCode==SCSIOP_MODE_SENSE)//一个mode sense结构

{ }

if(opCode==SCSIOP_WRITE||opCode==SCSIOP_WRITE6)//写操作

{ }

其他的参看SCSI规范

当我拦截到SCSI命令以后,认为一切边的顺利起来。但是实际上,我在只拦截SCSIOP_WRITE的时候,虽然系统不会真正的写东西到

U盘上,但却要过很久才会提示延时写错误。这样的程序显然是不能给用户的。这个时候tiamo告诉我一个方法,这个方法来源于市场

上的一种“带写保护功能”的U盘,他可以象软盘一样的写保护。当然他是硬件上实现的。软件实现更加的简单,如下:

irpStack = IoGetCurrentIrpStackLocation(Irp);

CurSrb=irpStack->Parameters.Scsi.Srb;//Get Current Scsi SRB, Analysis SCSI Command here!

cdb=CurSrb->Cdb;

opCode=cdb->CDB6GENERIC.OperationCode;

if(opCode==SCSIOP_MODE_SENSE && CurSrb->DataBuffer
&& CurSrb->DataTransferLength >=
sizeof(MODE_PARAMETER_HEADER)

{

modeData = (PMODE_PARAMETER_HEADER)CurSrb->DataBuffer;

modeData->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;

}

具体就是modeData->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;这句话了。

写到这里,U盘的只读功能就完成了。效果很好。

写这个文章的时候我正在完善这个程序,希望用一个应用层的程序和他配合。可以控制U盘只读、读写、全锁定等等。遇到一些大问题。

当我完成那个功能的时候,再把这些详细的东西加上。

抱歉!评论已关闭.