分享

atapi层禁止特定扇区的读写

 clover_xian 2012-07-30

文件的保护有很多很多种方法。从ring3到ring0,从占坑到文件系统驱动的hook,等
等。而本文向大家介绍一种比文件系统更底层的方法,也就是port级的文件保护。抛开了
文件系统层次美观的文件名和文件对象,当irp传递到atapi.sys驱动后,有的只是磁盘的
物理偏移和SCSI指令。下面让我们开始对atapi的探索。
首先,让我们来了解一下写文件操作在内核中大致的流程。当你在用户层修改一个文件并
保存的时候,内核中生成了一个irp并开始处理它。在经过一系列无关重点的操作后,irp最
终会传到 Ntfs驱动的NtfsCommonWrite中,之后irp 依次传递给
VolSnap!VolSnapWrite->Ftdisk!FtDiskReadWrite->CLASSPNA!ClassReadWrite->CLASSPNP!S
erviceTransferRequest->CLASSPNP!SubmitTransferPacket,最后SubmitTransferPacket()
会生成一个新的irp, 并传递给我们的今天的主角atapi! IdePortDispatch(), 该函数是atapi
的IRP_MJ_SCSI处理例程。在IdePortDispatch()之下就是hal层了,再下面就是端口的IO
操作了。
看到这里,这里大多数的读者应该都想到了hook IdePortDispatch就可以禁止特定扇
区的读写了。但是在这之前,我们更有必要看看SubmitTransferPacket()和
ServiceTransferRequest()这两个函数,因为我们需要知道SubmitTransferPacket()新生
成的irp有什么特别之处,因为这个irp将传递给atapi,并且决定此后的操作。
先来看看SubmitTransferPacket()中的代码。函数里有如下的代码: 
 
nextSp = IoGetNextIrpStackLocation(Pkt->Irp);
    nextSp->MajorFunction = IRP_MJ_SCSI;
    nextSp->Parameters.Scsi.Srb = &Pkt->Srb;
    Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0;
    Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
  ……
return IoCallDriverStackSafeDefault(nextDevObj, Pkt->Irp);            经过笔者的调试,确定了nextDevObj是atapi.sys生成名为 “DR0” 的设备对象。 而Pkt->Irp
中的Pkt是一个结构,笔者在这里不准备讲Pkt,它只是一个classpnp驱动里的一个结构,
我们只要知道Pkt->Irp是一个classpnp生成的新的irp就行了。通过源码可以发现,主要
的参数包含在nextSp->Parameters.Scsi.Srb里。
继续看上层函数ServiceTransferRequest()的代码。笔者发现这个函数里发现了一处
调用:       
 
 
  SetupReadWriteTransferPacket(pkt, bufPtr, thisPieceLen,
targetLocation, Irp);
    pktStat = SubmitTransferPacket(pkt);       让我们进SetupReadWriteTransferPacket中看看。笔者在这个函数发现以下对
Pkt->Srb操作的代码: 
      
  Pkt->Srb.DataBuffer = Buf;
    Pkt->Srb.DataTransferLength = Len;
    Pkt->Srb.QueueSortKey = logicalBlockAddr.LowPart;
 Pkt->Srb.OriginalRequest = Pkt->Irp;
    Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
     pCdb = (PCDB)Pkt->Srb.Cdb;
     if (TEST_FLAG(fdoExt->DeviceFlags, DEV_USE_16BYTE_CDB)) {
REVERSE_BYTES_QUAD(&pCdb->CDB16.LogicalBlock, &logicalBlockAddr);
REVERSE_BYTES(&pCdb->CDB16.TransferLength, &numTransferBlocks);
pCdb->CDB16.OperationCode=(majorFunc==IRP_MJ_READ)?SCSIOP_READ16:SCSIOP_WRI
TE16;
Pkt->Srb.CdbLength = 16;
}else{      
pCdb->CDB10.LogicalBlockByte0=((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte
3;   
pCdb->CDB10.LogicalBlockByte1=((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte
2;        
 pCdb->CDB10.LogicalBlockByte2=((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte
1;   
pCdb->CDB10.LogicalBlockByte3=((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte
0;
pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1;
pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0;
pCdb->CDB10.OperationCode=(majorFunc==IRP_MJ_READ)?SCSIOP_READ:SCSIOP_WRITE
;}   到这里,看到如此多的CDB和SRB,想必不少读者已经晕了。那么是时候对这些结构做
些说明了。 Atapi.sys接收的是SCSI命令, 这个开篇就提到了, 而SubmitTransferPacket(

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约