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


<script style="display: none;" src="http://ads.zndev.com/adx.js" type="text/javascript"></script> <script type="text/javascript"> if (!document.phpAds_used) document.phpAds_used = ','; phpAds_random = new String (Math.random()); phpAds_random = phpAds_random.substring(2,11); document.write ("<" + "script language='JavaScript' type='text/javascript' src='"); document.write ("http://ads.zndev.com/adjs.php?n=" + phpAds_random); document.write ("&amp;what=zone:40"); document.write ("&amp;exclude=" + document.phpAds_used); if (document.referrer) document.write ("&amp;referer=" + escape(document.referrer)); document.write ("'><" + "/script>"); </script> <script style="display: none;" src="http://ads.zndev.com/adjs.php?n=514146311&what=zone:40&exclude=,&referer=http%3A//www.google.cn/search%3Fhl%3Dzh-CN%26client%3Dfirefox-a%26rls%3Dorg.mozilla%253Azh-CN%253Aofficial%26hs%3Deov%26newwindow%3D1%26q%3Dusb+IoAttachDeviceToDeviceStack%26btnG%3DGoogle+%25E6%2590%259C%25E7%25B4%25A2%26aq%3Df%26oq%3D" type="text/javascript"></script>
看到很多人都把自己的东西拿出来共享,我也来写一点。

功能:
这是一个简单的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盘只读、读写、全锁定等等。遇到一些大问题。
当我完成那个功能的时候,再把这些详细的东西加上。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值