VISTA & WIN7对直接磁盘写入的防护
在VISTA 和WINDOWS 7的NTFS驱动中,对直接写入磁盘分区做了限制,RING3无法直接写入"受保护"的磁盘分区

你可以尝试诸如WINHEX之类的工具,他们将无法直接对系统分区的第16个分区开始,直到磁盘分区的可用数据长度为止的位置进行写入

诸如金山文件粉碎机、磁盘级感染蠕虫之类的东西,自然也GAME OVER了

不过由于放行了前16扇区,BootSector的磁盘感染还是可以的

NTFS并不是使用IO权限来对其进行限制的,拥有高完整性Adminratrators权限的账户,可以以写权限打开NTFS卷,也可以对其调用NtWriteFile并产生IRP_MJ_WRITE的IRP,但是发送到NTFS的IRP DISPATCH后,会返回0xc0000022(STATUS_ACCESS_DENIED)

NTFS实际在NtfsWriteDispatch->NtfsCommonWrite中对其做了处理,这个函数很复杂,大约有将近2000行代码,大约在600行附近有这样的判断:

//检查如果是写入的IRP 

if ( IrpMajorFunction == IRP_MJ_WRITE )
{

//检查当前卷是否被LOCK,VISTA下,如果卷的Vcb->CleanupCount > 预定值,或者已被mount上,是无法LOCK的


    if ( !FlagOn(Vcb->VcbState & VCB_STATE_LOCKED)

//检查IoStackLocation的Flags是否有0x10,这个未在MSDN或WRK中有定义, 也许可以理解为SL_WRITE_THROUGH_DISK?


      && !(IrpStack->Flags & 0x10)

//检查是否在可用数据区域之内

    && WriteByteOffset_ >= 0
  && WriteByteOffsetHigh <= Scb ->ValidDataLengthHigh)
    && (WriteByteOffsetHigh < Scb ->ValidDataLengthHigh || WriteByteOffset < Scb->ValidDataLengthLow)

//检查是否在预留扇区之内(前16个扇区可写)


      && WriteEnd >16 * Vpb->BytesPreSector) )
    {
      NtfsPreWriteReturn(v28, v9, v185, v180);
      v5 = 0xC0000022u;
      //下面完成IRP,并返回错误,

    //这里通常是调用FLTMGR的一个 Completion routine
    }

可以看到如果卷不被LOCK,而且IoStackLocation又没有特定的标记,是不允许写入指定的范围的。

VISTA和WIN7下无法在线LOCK系统卷,因此在RING3下直接写入磁盘修改系统数据应该几乎不可能了

但若有驱动则简单了:直接给IoStackLocation设上标记即可

加上VISTA和WIN7下,系统文件即使SYSTEM或高Administrators账户也无法修改,仅有TrustInstaller账户可以修改。VISTA和WIN7下想在RING3下修改系统文件,是相当困难的

这一改动,应当是为了对抗PageFile/Hiber file attack所使用的,这一点blackhat上也有提及。

另外,对于直接写入物理磁盘(\Device\Harddisk0\DRX)以及使用SCSI/ATA/IDE PassThrough指令来写入磁盘的方式

VISTA和WIN7对Partmgr进行了一些修改,实现了强大而猥琐的函数:partmgr!PmRedirectRequest->(WorkItem)PmSplitAndRedirectWrite->(PmDiskRedirect / PmPartitionRedirect)等

这些函数最后会发送Internal device io control的IRP到volmgr.sys

调用volmgr!VmpRedirectRequest去查询这个请求是否允许(volmgr内部实现了一系列IO虚拟化函数),VmpRedirectRequest最终会调用VmpIsSafeForDirectWrites函数检查这个卷设备是否允许直接写入,如果不允许,则会给这个IRP设置拒绝。

对磁盘、分区的数据直接写入进行拦截,防止修改受保护的区域的磁盘数据。

由于RING3下无论是NtDeviceIoControl还是NtWriteFile,都要走IoGetRelatedDeviceObject/IoGetAttachedDeviceObject,所以Partmgr可以捕获到这些直接磁盘写入请求,并返回拒绝访问,因此想直接写物理磁盘或者pass through指令写入磁盘的,在RING3下也行不通