首页
社区
课程
招聘
[分享]一份基于磁盘卷过滤的磁盘重定向研究
发表于: 2013-4-14 01:57 10230

[分享]一份基于磁盘卷过滤的磁盘重定向研究

2013-4-14 01:57
10230
===========================================
首先需要说明的是这份代码可以从网上找到,只是不能支持动态磁盘,还有只能支持和引导盘相同的文件系统格式,不知道咋搞的,公司要做这个玩意,从网上找来了这份代码,让我更改,总之是伤透脑筋了,还好,现在可以了。

具体的代码我就不全放上来了,大家可以从网上找,我就放我更改的。
===========================================
一.文件系统的解析:

1.基本数据结构:
typedef enum
{
    TRKF_NTFS,
    TRKF_FAT32,
    TRKF_OTHER
}TRKF_FILE_SYSTEM_TYPE;
#define _FileSystemNameLength 64
//定义FAT32文件系统签名的偏移量
#define FAT32_SIG_OFFSET 82
//定义NTFS文件系统签名的偏移量
#define NTFS_SIG_OFFSET  3
//这是FAT32文件系统的标志
const UCHAR FAT32***[4] = {'F','A','T','3'};
//这是NTFS文件系统的标志
const UCHAR NTFS***[4] = {'N','T','F','S'};
typedef struct  _DP_FAT32_BOOT_SECTOR
{
    BYTE    JMPCode[3];            /*引导跳转代码*/
    CHAR    System_ID[8];          /*厂商标志和版本号*/
    WORD     BytesPerSector;       /*每扇区字节数*/
    BYTE     SectorsPerCluster;    /*每簇扇区数*/
    WORD     ReservedSectors;      /*保留扇区数*/
    BYTE     FatNum;               /*FAT的个数*/
    WORD     RootEntry;            /*根目录项数*/
    WORD     TotalSectors;         /*分区总扇区数(分区小于32M时)*/
    BYTE     Media;            /*分区介质标识*/
    WORD     SectorsPerFAT;        /*每个FAT占的扇区数*/
    WORD     SectorsPerTrack;      /*每道扇区数*/
    WORD     Heads;                /*磁头数*/
    DWORD     HiddenSectorNum;      /*隐含扇区数*/
    DWORD     BigTotalSectors;     /*分区总扇区数(分区大于32M时)*//*end of 23 Bytes*/
    DWORD    SectorPerFat;                 /*驱动器号*/
    WORD     ExterFlag;          /*含义未知*/
    WORD     Version;        /*磁盘序列号*/
    DWORD    RootDir1stCluster;     
    WORD     FSInfoSector;
    WORD     BackupBootSector;
    char     Reserved[12];
    char     BIOSDriver;
    char     UnUserd;
    char     Ext;
    DWORD    Serial;
    char     Lable[11];
    char     FileSystem[8];
}DP_FAT32_BOOT_SECTOR, *PDP_FAT32_BOOT_SECTOR;
typedef struct _DP_NTFS_BOOT_SECTOR
{
    UCHAR  Jump[3];     //0
    UCHAR  FSID[8];     //3
    USHORT  BytesPerSector;    //11
    UCHAR  SectorsPerCluster;   //13
    USHORT  ReservedSectors;   //14
    UCHAR  Mbz1;      //16  
    USHORT  Mbz2;      //17
    USHORT  Reserved1;     //19
    UCHAR  MediaDesc;     //21
    USHORT  Mbz3;      //22
    USHORT  SectorsPerTrack;   //24
    USHORT  Heads;      //26
    ULONG  HiddenSectors;    //28
    ULONG  Reserved2[2];    //32
    ULONGLONG TotalSectors;    //40
    ULONGLONG MftStartLcn;    //48
    ULONGLONG Mft2StartLcn;    //56
}DP_NTFS_BOOT_SECTOR, *PDP_NTFS_BOOT_SECTOR;
typedef struct {
   
    LARGE_INTEGER StartingLcn;
    LARGE_INTEGER BitmapSize;
    BYTE  Buffer[1];
   
} VOLUME_BITMAP_BUFFER, *PVOLUME_BITMAP_BUFFER;
typedef struct {
   
    LARGE_INTEGER StartingLcn;
   
} STARTING_LCN_INPUT_BUFFER, *PSTARTING_LCN_INPUT_BUFFER;

2.NTFS文件系统部分:
/*
在NTFS怎么读取$Bitmap的内容 $Bitmap是NTFS里一个元文件,读取方法为:
1。首先确定NTFS分区每个簇所占扇区数,在分区第一个扇区中0x0D处,一个字节。
2。确定$MFT的首簇:在分区第一个扇区中0x30处,8个字节。
3。计算$Bitmap条目位置:将前两步结果相乘得$MFT首扇区,
加上12(因为$MFT为第0个文件,$Bitmap为第六个文件,每个FileRecord一般占2个扇区)。
4。读取$Bitmap条目位置处两个扇区。
5。从这两个扇区0x30处开始找80属性:读8个字节,前四个为属性,
如果小于80继续,后四个为此属性所占字节,一直到找到80属性。(30属性是文件名,正好确定此文
件是否确实是$Bitmap)
6。从80属性开始处向后偏移0x20字节处,查看本文件存放位置的位置,一般是0x40,
即从80属性开始处向后偏移0x40字节,此为本文件存放位置。
7。此字节低4位为簇数字节数,高4位为首簇字节数。假如此处为31 6E EB C4 04 00,
则此文件簇数为0x6E,首簇在0x04C4EB,这些簇中就是该文件的内容
*/
NTSTATUS ReadSector_Ntfs(
                             BYTE* lpbuffer,
                             DWORD dwSize,
                             HANDLE filehandle,
                             ULONGLONG nSector,
                             PDP_NTFS_BOOT_SECTOR lpNtfsParam,
                             IO_STATUS_BLOCK* ios
                         );
BOOL  GetClusterList(
                      IN BYTE* lpbuffer,
                      IN PDP_NTFS_BOOT_SECTOR lpNtfsParam,
                      OUT PVOLUME_BITMAP_BUFFER* lpBitMap,
                      IN HANDLE filehandle,
                      IN IO_STATUS_BLOCK* ios
                     );
NTSTATUS     UpdataServerialData(char* lpbuffer, PDP_NTFS_BOOT_SECTOR lpNtfsParam);
char*    FindFileRecord(
                            IN char* lpbuffer,
                            IN LONGLONG nSector,
                            IN char chAttrTypeId,  
                            IN HANDLE fileHandle,
                            IN PDP_NTFS_BOOT_SECTOR lpNtfsParam,
                            IO_STATUS_BLOCK* ios
                        );
LONGLONG GetBitmapFileSector(IN PDP_NTFS_BOOT_SECTOR lpNtfsParam);
char*   GetBitmap80Attr(char* lpbuffer);
NTSTATUS GetNtfsBitmapInfo(IN PUNICODE_STRING uVolumeDosName,
                           LIST_ENTRY* head);

NTSTATUS ReadSector_Ntfs(
                             OUT  BYTE* lpbuffer,
                             IN  DWORD dwSize,
                             IN  HANDLE filehandle,
                             IN  ULONGLONG nSector,
                             IN  PDP_NTFS_BOOT_SECTOR lpNtfsParam,
                             IO_STATUS_BLOCK* ios
                         )
{
    NTSTATUS status = STATUS_SUCCESS;
    LARGE_INTEGER li;
    FILE_POSITION_INFORMATION fpi ;
    ULONGLONG Offset = (ULONGLONG)nSector * (ULONGLONG)lpNtfsParam->BytesPerSector;   //获取扇区偏移
    li.QuadPart = Offset;
    fpi.CurrentByteOffset = li;
   
    if ((dwSize % 512 != 0) || lpNtfsParam == NULL)
    {
        return STATUS_UNSUCCESSFUL;
    }
   
    status = ZwSetInformationFile (                                                  //定位到指定位置
        filehandle,
        ios,
        &fpi,
        sizeof (FILE_POSITION_INFORMATION),
        FilePositionInformation);
    if (status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&filehandle, Executive, KernelMode, FALSE, 0);
        status = ios->Status;
    }
    if (NT_SUCCESS(status))
    {
        status = ZwReadFile(filehandle,                                             //读取指定位置,指定大小的磁盘扇区内容
                                NULL,
                                NULL,
                                NULL,
                                ios,
                                lpbuffer,
                                dwSize,  
                                &li,
                                NULL
                            );                           
        if (status == STATUS_PENDING)
        {
            KeWaitForSingleObject(&filehandle, Executive, KernelMode, FALSE, 0);
            status = ios->Status;
        }
        if (NT_SUCCESS(status))
        {
            return status;//UpdataServerialData(lpbuffer, lpNtfsParam);
        }
    }
   
    return status ;
}
char*   GetBitmap80Attr(char* lpbuffer)                                             //在指定缓冲区内查找0x80属性的位置
{
    char *lpCur = lpbuffer;
   
    if (lpbuffer == NULL)
    {
        return NULL;
    }
   
    lpCur =(char*) ((DWORD)lpCur + (DWORD)lpCur[0x20]);
    return lpCur;
}
//获取簇链,连续簇链只记录起始簇和长度
#define sw32(x) \
    ((ULONG)( \
    (((ULONG)(x) & (ULONG)0x000000ff) << 24) | \
    (((ULONG)(x) & (ULONG)0x0000ff00) << 8) | \
    (((ULONG)(x) & (ULONG)0x00ff0000) >> 8) | \
(((ULONG)(x) & (ULONGLONG)0xff000000) >> 24) ))
#define btos(x) sw32(x)
BOOL GetClusterList(  IN BYTE* lpbuffer,                                          //获取$bitmap元文件所在的起始簇和长度,这个比较特别,因为是连续的只要知道开始和长度就可以了
                      IN PDP_NTFS_BOOT_SECTOR lpNtfsParam,
                      OUT PVOLUME_BITMAP_BUFFER* lpBitMap,
                      IN HANDLE filehandle,
                      IN IO_STATUS_BLOCK* ios)
{
    __try
    {
        BYTE* lpszbuf = (BYTE*)&lpbuffer[0];
        ULONG nHigh = 0;
        ULONG nLow  = 0;
        ULONG BitMapSize = 0;
        NTSTATUS status = STATUS_UNSUCCESSFUL;
        char   buffer[20] = {0};
        char   buffer1[20] = {0};
        ULONG  nCount = 0;
        ULONG nOffset = 0;
        ULONG nLen;
        BYTE szbuf[20] = {0};  
        BYTE* lpszOffset = NULL;
        nHigh = ((int)lpszbuf[0] & 0x0F0) >> 4;                                 //高4位,起始簇
        nLow  = (int)lpszbuf[0] & 0x0F;                                         //低4位,长度
        nLen = nHigh + nLow;                                                    //第一个字节的高,低4位之和是这个run data的总长度
        memcpy(szbuf, lpszbuf, nLen + 1);
        lpszOffset = (char*)ExAllocatePool(NonPagedPool, nHigh);
        
        if (lpszOffset == NULL)
        {
            return FALSE;
        }
        
        memcpy(lpszOffset, lpszbuf + nLow + 1, nHigh);
        memcpy(&nOffset, lpszOffset, nHigh);
        memcpy(&nCount, &lpszbuf[1], nLow);
        if (lpszOffset)
        {
            ExFreePool(lpszOffset);
            lpszOffset = NULL;
        }
        if (nOffset & (ULONG)0x00800000)                                       //有可能是负的,但对于$bitmap只能是正的
            nOffset |= (ULONG)0xFF000000;
        else
                nOffset &= (ULONG)0xFFFFFF;
        
        DbgPrint("StartLcn: %08X, End:%08X, Count:%08X\r\n", nOffset, nOffset + nCount, nCount);
        BitMapSize = nCount * lpNtfsParam->BytesPerSector * lpNtfsParam->SectorsPerCluster;
        *lpBitMap = (PVOLUME_BITMAP_BUFFER)__malloc(BitMapSize + 2 * sizeof(LARGE_INTEGER));
        
        if (*lpBitMap != NULL)
        {
           
            (*lpBitMap)->BitmapSize.QuadPart = BitMapSize;
            (*lpBitMap)->StartingLcn.QuadPart = lpNtfsParam->MftStartLcn;
            status = ReadSector_Ntfs((*lpBitMap)->Buffer,                   //读取$bitmap信息
                                        BitMapSize,
                                        filehandle,
                                        (ULONG)nOffset * lpNtfsParam->SectorsPerCluster,
                                        lpNtfsParam,
                                        ios);
           if (status == STATUS_UNSUCCESSFUL)
           {
               return FALSE;
           }
           else if (status == STATUS_SUCCESS)
           {
               return TRUE;
           }
           else
           {
               return FALSE;
           }
        }
    }
    __except(0)
    {
        return FALSE;
    }

    return TRUE;
}
//更新序列号
/*
更新序列号(Update Sequence)
在NTFS里面,有一些结构为了检查一致性就存在更新号。
这些结构是文件记录,索引记录,日志记录。 在记录写入磁盘以前,每个扇区的最后2个字母被复制到头部的一个数组里面。 这个更新序列号于是被增加和写入每个扇区的末尾。 如果发生任何磁盘错
误的话,这项技术能够探测到它。
更新序列号数组(usa)是一个数组,它是由属于每个扇区最后2个字节的无符
号16位整数组成的。注意开始的一个条目是更新序列号(usn),它记录了被保
护的记录块被写入磁盘的次数。值0和-1(例:0xffff)是不被使用的。所有扇区的最
后2个字节应该是等于更新序列号(在读的过程中)的或者设置它(在写
的过程中)。如果没有这样,那么一定是当数据被写的时候一个不完全的
多扇区转移已经发生。最大的更新序列号数组的大小被固定为:
最大值=usa_ofs + (usa_count * 2) = 510 bytes
510个字节来自于这样一个事实:数组中的最后的16位整数显然应该
在第一个512字节大小的扇区之前完成的。这个规范能够被在usa_ofs +
(usa_count * 2)小于510的时候被用来作为一项一致性检查
*/
NTSTATUS     UpdataServerialData(char* lpbuffer, PDP_NTFS_BOOT_SECTOR lpNtfsParam)
{
    unsigned short UpdateNoOffset = (unsigned short)lpbuffer[0x4];
    unsigned short UpdateNoLen    = (unsigned short)lpbuffer[0x6];
    int j = 0;
    for (j = 0; j < UpdateNoLen - 1; j++ )
    {
        char ch1, ch2;
        __try
        {
            ch1 = lpbuffer[lpNtfsParam->BytesPerSector*j + (lpNtfsParam->BytesPerSector - 2)];
            ch2 = lpbuffer[UpdateNoOffset + 2 * (j + 1)];
            //ProbeForRead();
            ch1 = ch2;
        }
        __except(0)
        {
            return STATUS_UNSUCCESSFUL;
        }
     
    }
    return STATUS_SUCCESS;
}
//读取两个扇区(因为每个FILE_RECORD占用2个扇区),获取指定属性(0x80 0x30 0x90 0xA0.....)
char*    FindFileRecord(
                            IN char* lpbuffer,
                            IN LONGLONG nSector,
                            IN char chAttrTypeId,
                            IN HANDLE fileHandle,
                            IN PDP_NTFS_BOOT_SECTOR lpNtfsParam,
                            IO_STATUS_BLOCK* ios
                        )
{
    NTSTATUS status = STATUS_SUCCESS;
    char* lpCurPointer = lpbuffer;
    char  szbuf[30] = {0};
    if (lpbuffer == NULL)
    {
        return NULL;
    }
    __try
    {
        status = ReadSector_Ntfs(lpbuffer, lpNtfsParam->BytesPerSector * 2, fileHandle, nSector, lpNtfsParam, ios);
        
        if (status == STATUS_SUCCESS)
        {
            WORD FirstArriOffset = (WORD)lpbuffer[0x14];
            DWORD nSizeOfArri;
            lpCurPointer += FirstArriOffset;
            
            while (((DWORD)lpCurPointer[0]) != 0xFFFFFFFF)                            //这个写死了,因为我就要0x80属性,具体怎么个找法,可以查看相关资料
            {
                if ( (lpCurPointer[0]) == chAttrTypeId )
                {
                    return lpCurPointer;
                }
                nSizeOfArri  = (DWORD)lpCurPointer[0x4];;
                lpCurPointer += nSizeOfArri;
            }
        }
    }
    __except(0)
    {
        return NULL;
    }

   
    return NULL;
}
LONGLONG GetBitmapFileSector(PDP_NTFS_BOOT_SECTOR lpNtfsParam)                      //因为$bitmap的文件记录号是6,
              //而且每一个FILE RECORD占据两个扇区,所以就直接可以找到$bitmap的
{                     // MFT起始扇区号
    return (LONGLONG)(lpNtfsParam->SectorsPerCluster * (lpNtfsParam->MftStartLcn) + ( 6 * 2 ));
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 182
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
2.FAT32解析:
NTSTATUS GetFatTableInfo(DP_FAT32_BOOT_SECTOR * lpBpbFat, PVOLUME_BITMAP_BUFFER* lpBitMap, HANDLE filehandle);
NTSTATUS GetSpecificBPB(
                        IN PUNICODE_STRING uVolumeDosName,
                        OUT DP_FAT32_BOOT_SECTOR* lpBpbFat
                        );
NTSTATUS ReadSector_FAT(
                    IN  __int64 SectorNum,
                    OUT BYTE* buffer,
                    ULONG     uSize,
                    IN  HANDLE filehandle,
                    IN  DP_FAT32_BOOT_SECTOR * lpBpbFat
                     );

#define $END   0x0FFFFFFF
#define $BAD   0xFFFFFFF7
NTSTATUS GetSpecificBPB(IN PUNICODE_STRING uVolumeDosName,
                        OUT DP_FAT32_BOOT_SECTOR* lpBpbFat)
{
    NTSTATUS status = STATUS_SUCCESS;
    IO_STATUS_BLOCK IoStatusBlock = {0};
    OBJECT_ATTRIBUTES  oa = {0};
    char     BpbBuffer[READSIZE] = {0};
    HANDLE fileHandle;
   
    __try
    {
        if (uVolumeDosName == NULL ||
            uVolumeDosName->Length == 0)

        {
            return STATUS_UNSUCCESSFUL;
        }
        
        InitializeObjectAttributes(&oa,
                                    uVolumeDosName,
                                    OBJ_CASE_INSENSITIVE,
                                    NULL,
                                    NULL);
        
        status = ZwCreateFile( &fileHandle,
                                GENERIC_READ | SYNCHRONIZE,
                                &oa,
                                &IoStatusBlock,
                                NULL,
                                0,
                                FILE_SHARE_READ ,
                                FILE_OPEN,
                                FILE_SYNCHRONOUS_IO_NONALERT | FILE_NO_INTERMEDIATE_BUFFERING, // 同步读写
                                NULL,
                          0);
        if (status == STATUS_PENDING)
        {
            if (status == STATUS_PENDING)
            {
                KeWaitForSingleObject(&fileHandle, Executive, KernelMode, FALSE, 0);
                status = IoStatusBlock.Status;
            }
        }
        else if (NT_SUCCESS(status))
        {
            status = ZwReadFile(fileHandle,
                                NULL,
                                NULL,
                                NULL,
                                &IoStatusBlock,
                                BpbBuffer,
                                READSIZE,
                                0,
                                NULL);           
            ZwClose(fileHandle);
            return status;
        }
        else
        {
            if (fileHandle)
                ZwClose(fileHandle);
            return status;
        }
    }
    __except(0)
    {
        if (fileHandle)
            ZwClose(fileHandle);
        return STATUS_UNSUCCESSFUL;
    }
    if (fileHandle)
        ZwClose(fileHandle);
    return status;
}
NTSTATUS ReadSector_FAT(
                    IN  __int64 SectorNum,
                    OUT BYTE* buffer,
                    ULONG     uSize,
                    IN  HANDLE filehandle,
                    IN  DP_FAT32_BOOT_SECTOR * lpBpbFat
                )
{
    NTSTATUS status = STATUS_SUCCESS;
    LARGE_INTEGER li;
    IO_STATUS_BLOCK ios;
    FILE_POSITION_INFORMATION fpi ;
    li.QuadPart = (__int64)SectorNum * lpBpbFat->BytesPerSector;
    fpi.CurrentByteOffset = li;
    if (uSize % 512 != 0)
    {
        return STATUS_UNSUCCESSFUL;
    }
    status = ZwSetInformationFile (
                                    filehandle,
                                    &ios,
                                    &fpi,
                                    sizeof (FILE_POSITION_INFORMATION),
                                    FilePositionInformation);
    if (NT_SUCCESS(status))
    {
        status = ZwReadFile(filehandle,
            NULL,
            NULL,
            NULL,
            &ios,
            buffer,
            uSize,  
            &li,
            NULL);
    }

    return status;
}
NTSTATUS GetFatTableInfo(DP_FAT32_BOOT_SECTOR * lpBpbFat,
                         PVOLUME_BITMAP_BUFFER* lpBitMap,
                         HANDLE filehandle)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    DWORD    dwSectors = 0;
    ULONG    uSectorPerFat = lpBpbFat->SectorPerFat == 0 ? lpBpbFat->SectorsPerFAT : lpBpbFat->SectorPerFat;
    ULONG    BitMapSize = uSectorPerFat * lpBpbFat->BytesPerSector;
    (*lpBitMap) = (PVOLUME_BITMAP_BUFFER)__malloc(BitMapSize + 2 * sizeof(LARGE_INTEGER));
    if (lpBitMap != NULL)
    {
        RtlZeroMemory(*lpBitMap,  BitMapSize +2 * sizeof(LARGE_INTEGER));
        (*lpBitMap)->BitmapSize.QuadPart = (__int64)BitMapSize;
        (*lpBitMap)->StartingLcn.QuadPart = (__int64)uSectorPerFat * 2 + lpBpbFat->ReservedSectors ;
        DbgPrint("%08X, %08X\r\n", uSectorPerFat, lpBpbFat->ReservedSectors);
        status =  ReadSector_FAT(lpBpbFat->ReservedSectors,
                                (*lpBitMap)->Buffer,
                                BitMapSize,
                                filehandle,
                                lpBpbFat);
    }
   
    return status;
}
2013-4-14 01:59
0
雪    币: 182
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
3.下面是几个主要更改的函数了:
//获取磁盘卷信息
NTSTATUS
flt_getVolumeInfo(WCHAR volume, PVOLUME_INFO info)
{
NTSTATUS status;
HANDLE fileHandle;
UNICODE_STRING fileName;
OBJECT_ATTRIBUTES oa;
IO_STATUS_BLOCK IoStatusBlock;
WCHAR volumeDosName[50];
BYTE DBR[512] = { 0 };
ULONG DBRLength = 512;
PDP_NTFS_BOOT_SECTOR pNtfsBootSector = (PDP_NTFS_BOOT_SECTOR)DBR;
PDP_FAT32_BOOT_SECTOR pFat32BootSector = (PDP_FAT32_BOOT_SECTOR)DBR;
LARGE_INTEGER readOffset = { 0 };
TRKF_FILE_SYSTEM_TYPE type;
swprintf(volumeDosName, L"\\??\\%c:", volume);
RtlInitUnicodeString(&fileName, volumeDosName);

InitializeObjectAttributes(&oa,
&fileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = flt_GetFileSystemBpbInfo(&fileName, DBR, 512, &type);
status = ZwCreateFile(&fileHandle,
GENERIC_ALL | SYNCHRONIZE,
&oa,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT, // 同步读写
NULL,
0);

dprintf("open %wZ ret 0x%x\n", &fileName, status);

if (NT_SUCCESS(status))
{
IO_STATUS_BLOCK ioBlock;
PARTITION_INFORMATION partitionInfo;
ULONG buff[256];
PVOLUME_DISK_EXTENTS diskExtents;

diskExtents = (PVOLUME_DISK_EXTENTS)buff;

// 得到此卷所在的硬盘号,不考虑跨盘卷
status = ZwDeviceIoControlFile( fileHandle,
NULL,
NULL,
NULL,
&ioBlock,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL,
0,
diskExtents,
sizeof(buff)
);

if (status == STATUS_PENDING)
{
KeWaitForSingleObject(fileHandle, Executive, KernelMode, FALSE, 0L);
status = ioBlock.Status;
}

if (NT_SUCCESS(status))
{
info->diskNumber = diskExtents->Extents[0].DiskNumber;
// 得到下层设备
info->LowerDevObj = _lowerDeviceObject[info->diskNumber];
}

// 得到此卷的一类型,在物理硬盘的上的偏移等信息

status = ZwDeviceIoControlFile( fileHandle,
NULL,
NULL,
NULL,
&ioBlock,
IOCTL_DISK_GET_PARTITION_INFO,
NULL,
0,
&partitionInfo,
sizeof(partitionInfo)
);

if (status == STATUS_PENDING)
{
KeWaitForSingleObject(fileHandle, Executive, KernelMode, FALSE, 0L);
status = ioBlock.Status;
}

if (NT_SUCCESS(status))
{
info->partitionNumber = partitionInfo.PartitionNumber;
info->partitionType = partitionInfo.PartitionType;
info->physicalStartingOffset = partitionInfo.StartingOffset.QuadPart;
info->bootIndicator = partitionInfo.BootIndicator;
}
if (NT_SUCCESS(status))
{
switch(type)
{
case TRKF_NTFS:
{
info->bytesPerCluster = pNtfsBootSector->BytesPerSector * pNtfsBootSector->SectorsPerCluster;
info->bytesPerSector = pNtfsBootSector->BytesPerSector;
info->bytesTotal = pNtfsBootSector->TotalSectors * pNtfsBootSector->BytesPerSector;
info->HiddenSector = pNtfsBootSector->HiddenSectors + pNtfsBootSector->ReservedSectors;
info->firstDataSector = 0;
info->sectorCount = pNtfsBootSector->TotalSectors;
info->VolumeType = type;
info->SectorsPerCluster = pNtfsBootSector->SectorsPerCluster;
info->StartLcn = pNtfsBootSector->MftStartLcn;
break;
}
case TRKF_FAT32:
{
ULONG uSectorPerFat = pFat32BootSector->SectorPerFat == 0 ? pFat32BootSector->SectorsPerFAT: pFat32BootSector->SectorPerFat;
ULONG uTotalSectors = pFat32BootSector->BigTotalSectors == 0 ? pFat32BootSector->TotalSectors:pFat32BootSector->BigTotalSectors;
info->bytesPerCluster = pFat32BootSector->BytesPerSector * pFat32BootSector->SectorsPerCluster;
info->bytesPerSector = pFat32BootSector->BytesPerSector;
info->bytesTotal = uTotalSectors * pFat32BootSector->BytesPerSector;
info->HiddenSector = uSectorPerFat * pFat32BootSector->FatNum + pFat32BootSector->ReservedSectors;
info->firstDataSector = info->HiddenSector;
info->sectorCount = uTotalSectors;
info->VolumeType = type;
info->StartLcn = pFat32BootSector->RootDir1stCluster;
info->SectorsPerCluster = pFat32BootSector->SectorsPerCluster;
break;
}

}
}
}
if (fileHandle != NULL)
ZwClose(fileHandle);
return status;
}
////////////////////////////////////////////////////////////////////////
NTSTATUS flt_GetFileSystemBpbInfo(IN PUNICODE_STRING uVolumeDosName,
OUT void* lpBpbBuffer,
IN DWORD dwSize,
OUT TRKF_FILE_SYSTEM_TYPE* theType)
{
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES oa;
HANDLE fileHandle = NULL;
BYTE DBR[512] = { 0 };
ULONG DBRLength = 512;
PDP_NTFS_BOOT_SECTOR pNtfsBootSector = (PDP_NTFS_BOOT_SECTOR)DBR;
PDP_FAT32_BOOT_SECTOR pFat32BootSector = (PDP_FAT32_BOOT_SECTOR)DBR;
LARGE_INTEGER readOffset = { 0 };
__try
{
if (uVolumeDosName == NULL ||
uVolumeDosName->Length == 0||
lpBpbBuffer == NULL||
dwSize == 0)
{
return STATUS_UNSUCCESSFUL;
}
InitializeObjectAttributes(&oa,
uVolumeDosName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = ZwCreateFile(&fileHandle,
GENERIC_READ | SYNCHRONIZE,
&oa,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT, // 同步读写
NULL,
0);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&fileHandle, Executive, KernelMode, FALSE, NULL);
status = IoStatusBlock.Status;
}
else if (NT_SUCCESS(status))
{
IO_STATUS_BLOCK IoStatusBlock2;
status = ZwReadFile(fileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock2,
DBR,
dwSize,
0,
NULL);

if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&fileHandle, Executive, KernelMode, FALSE, NULL);
status = IoStatusBlock2.Status;
}

else if (NT_SUCCESS(status))
{
if (*(DWORD*)NTFS*** == *(DWORD*)&DBR[NTFS_SIG_OFFSET])
{
RtlCopyMemory(lpBpbBuffer, DBR, dwSize);
*theType = TRKF_NTFS;
}
else if (*(DWORD*)FAT32*** == *(DWORD*)&DBR[FAT32_SIG_OFFSET])
{
RtlCopyMemory(lpBpbBuffer, DBR, dwSize);
*theType = TRKF_FAT32;
}
else
{
RtlCopyMemory(lpBpbBuffer, DBR, dwSize);
*theType = TRKF_OTHER;
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
}
else
{
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
}

else
{
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
_finished:

if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&fileHandle, Executive, KernelMode, FALSE, NULL);
status = IoStatusBlock.Status;
}

if (fileHandle)
{
ZwClose(fileHandle);
}

return status;
}
__except(0)
{
if (fileHandle)
{
ZwClose(fileHandle);
}
return STATUS_UNSUCCESSFUL;
}
return status;
}
///获取文件系统位图信息
NTSTATUS flt_GetFileSystemBitmap(IN PUNICODE_STRING uVolumeDosName,
OUT PVOLUME_BITMAP_BUFFER* lpBitMap)
{
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES oa;
HANDLE fileHandle = NULL;
BYTE DBR[512] = { 0 };
ULONG DBRLength = 512;
PDP_NTFS_BOOT_SECTOR pNtfsBootSector = (PDP_NTFS_BOOT_SECTOR)DBR;
PDP_FAT32_BOOT_SECTOR pFat32BootSector = (PDP_FAT32_BOOT_SECTOR)DBR;
LARGE_INTEGER readOffset = { 0 };
__try
{
if (uVolumeDosName == NULL ||
uVolumeDosName->Length == 0)
{
return STATUS_UNSUCCESSFUL;
}
InitializeObjectAttributes(&oa,
uVolumeDosName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = ZwCreateFile(&fileHandle,
GENERIC_READ | SYNCHRONIZE,
&oa,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&fileHandle, Executive, KernelMode, FALSE, NULL);
status = IoStatusBlock.Status;
}
else if (NT_SUCCESS(status))
{
IO_STATUS_BLOCK IoStatusBlock2;
status = ZwReadFile(fileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock2,
DBR,
DBRLength,
0,
NULL);

if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&fileHandle, Executive, KernelMode, FALSE, NULL);
status = IoStatusBlock2.Status;
}

else if (NT_SUCCESS(status))
{
if (*(DWORD*)NTFS*** == *(DWORD*)&DBR[NTFS_SIG_OFFSET])
{
char szbuffer[1024] = {0};
LONGLONG BitmapSector ;
IO_STATUS_BLOCK ios;
char* lpBimapRundata = NULL;
BitmapSector = GetBitmapFileSector(pNtfsBootSector);
lpBimapRundata = FindFileRecord(szbuffer,
BitmapSector,
0x80,
fileHandle,
pNtfsBootSector,
&ios);

if (lpBimapRundata != NULL)
{
char *lpCluseterArray = GetBitmap80Attr(lpBimapRundata);
if ( lpCluseterArray != NULL)
{
if (GetClusterList(lpCluseterArray,pNtfsBootSector,lpBitMap,fileHandle,
&ios))
{
status = STATUS_SUCCESS;
goto _finished;
}
else
{
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
}

else
{
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
}
else
{
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
}
else if (*(DWORD*)FAT32*** == *(DWORD*)&DBR[FAT32_SIG_OFFSET])
{
status = GetFatTableInfo((DP_FAT32_BOOT_SECTOR*) DBR, lpBitMap, fileHandle);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&fileHandle, Executive, KernelMode, FALSE, NULL);
status = IoStatusBlock.Status;
}
else if (status == STATUS_SUCCESS)
{
status = STATUS_SUCCESS;
goto _finished;
}
else
{
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
}
else
{
//走到这里,可能是其它任何文件系统,但是不是windows认识的文件系统,我们统一返回错
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
}
else
{
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
}

else
{
status = STATUS_UNSUCCESSFUL;
goto _finished;
}
_finished:

if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&fileHandle, Executive, KernelMode, FALSE, NULL);
status = IoStatusBlock.Status;
}

if (fileHandle)
{
ZwClose(fileHandle);
}

return status;
}
__except(0)
{
if (fileHandle)
{
ZwClose(fileHandle);
}
return STATUS_UNSUCCESSFUL;
}
return status;
}

//初始化位图
NTSTATUS
flt_initVolumeLogicBitMap(PVOLUME_INFO volumeInfo)
{
NTSTATUS status;
PVOLUME_BITMAP_BUFFER bitMap = NULL;
// 逻辑位图大小
ULONGLONG logicBitMapMaxSize = 0;
ULONGLONG index = 0;
ULONGLONG i = 0;
ULONGLONG Clusters = 0;
ULONGLONG Sectors = 0;
status = flt_getVolumeInfo(volumeInfo->volume, volumeInfo);
if (!NT_SUCCESS(status))
{
return status;
}
status = flt_getVolumeBitmapInfo(volumeInfo->volume, &bitMap);

if (!NT_SUCCESS(status))
{
return status;
}
// 获取此卷上有多少个扇区, 用bytesTotal这个比较准确,如果用其它的比如fsinfo,会少几个扇区发现
volumeInfo->sectorCount = volumeInfo->bytesTotal / volumeInfo->bytesPerSector;

// 得到逻辑位图的大小bytes
logicBitMapMaxSize = (volumeInfo->sectorCount / 8) + 1;

// 上次扫描的空闲簇的位置
volumeInfo->last_scan_index = 0;
dprintf("------------------------\n");
dprintf("extend cluster = %08I64d physicalStartingOffset = 0x%08I64x bitMapSize = 0x%I64x\n"
"bytesPerSector = %d bytesPerCluster = %d sectorsPerCluster = %d\n",
volumeInfo->firstDataSector, volumeInfo->physicalStartingOffset, logicBitMapMaxSize,
volumeInfo->bytesPerSector, volumeInfo->bytesPerCluster, volumeInfo->SectorsPerCluster);
Clusters =volumeInfo->sectorCount / volumeInfo->SectorsPerCluster;
Sectors = volumeInfo->sectorCount;
if (volumeInfo->VolumeType == TRKF_NTFS)
{
// 以扇区为单位的位图
if (!NT_SUCCESS(DPBitMap_Create(&volumeInfo->bitMap_Redirect, Sectors, SLOT_SIZE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}

// 以簇为单位的位图
if (!NT_SUCCESS(DPBitMap_Create(&volumeInfo->bitMap_Protect, Clusters, SLOT_SIZE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}

// 以扇区为单位的位图, 如果一次申请内存过大,会失败,用dpbitmap申请不连续的内存
if (!NT_SUCCESS(DPBitMap_Create(&volumeInfo->bitMap_Free, volumeInfo->bytesTotal / volumeInfo->bytesPerSector, SLOT_SIZE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}

for (i = 0; i < volumeInfo->HiddenSector; i++)
{
if (!NT_SUCCESS(DPBitMap_Set(volumeInfo->bitMap_Free, i, TRUE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}
}

for (i = 0; i < bitMap->BitmapSize.QuadPart; i++)
{
if (bitmap_test((PULONG)&bitMap->Buffer, i))
{
ULONGLONG j = 0;
ULONGLONG base = (i * volumeInfo->SectorsPerCluster);
for (j = 0; j < volumeInfo->SectorsPerCluster; j++)
{
if (!NT_SUCCESS(DPBitMap_Set(volumeInfo->bitMap_Free, base + j, TRUE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}
}
}
}
/*
{
BYTE* lpbuffer = bitMap->Buffer;
ULONGLONG i = 0;
for (i = 0 ; i < (ULONGLONG)bitMap->BitmapSize.QuadPart; i++)
{
ULONG bit = 1;
ULONG j = 0;
for (j = 1; j < 8; j++)
{
if ((lpbuffer[i] & bit ) != 0)
{
ULONGLONG base = bit + (i * 8) - 1;//计算对应占用的簇号
ULONGLONG uSector = base * volumeInfo->SectorsPerCluster;
ULONG Index = 0;
for (Index = 0; Index < volumeInfo->SectorsPerCluster; Index++)
{
if (!NT_SUCCESS(DPBitMap_Set(volumeInfo->bitMap_Free,uSector + Index, TRUE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild ;
}
}
}

bit <<= j;
}
}

} */

}
else if (volumeInfo->VolumeType == TRKF_FAT32)
{
// 以扇区为单位的位图

if (!NT_SUCCESS(DPBitMap_Create(&volumeInfo->bitMap_Redirect, Sectors, SLOT_SIZE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}

// 以簇为单位的位图
if (!NT_SUCCESS(DPBitMap_Create(&volumeInfo->bitMap_Protect, Clusters, SLOT_SIZE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}

// 以扇区为单位的位图, 如果一次申请内存过大,会失败,用dpbitmap申请不连续的内存
if (!NT_SUCCESS(DPBitMap_Create(&volumeInfo->bitMap_Free, Sectors, SLOT_SIZE)))
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}
for (i = 0; i < volumeInfo->firstDataSector ; i++)
{
if (DPBitMap_Set(volumeInfo->bitMap_Free, i, TRUE) == STATUS_UNSUCCESSFUL)
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}
}
{
PULONG lpBitmap = (PULONG)bitMap->Buffer;
ULONG j = 2;
for ( j = 3; j < (ULONG)bitMap->BitmapSize.QuadPart / 4; j++)
{
ULONGLONG uCluster = 0;
ULONGLONG uSector = 0;
ULONGLONG base = 0;

if (((ULONG)lpBitmap[j] >= (ULONG)2) && ((ULONG)lpBitmap[j] <= (ULONG)0x0FFFFFFE))
{

//FAT i 获取该文件的扇区号
if (($DIRTY == (ULONG)lpBitmap[j])|| ((ULONG)0xFFFFFFFF == lpBitmap[j]))
{
continue;
}
else if (((ULONG)$BAD == lpBitmap[j]))
{
base = (ULONG)(j) * volumeInfo->SectorsPerCluster;
}
else
{
if (((ULONG)$END) == lpBitmap[j])//结束簇
base = (ULONG)(lpBitmap[j - 1])* volumeInfo->SectorsPerCluster;
else
base = (ULONG)(lpBitmap[j]) * volumeInfo->SectorsPerCluster;
}

for ( uSector = 0; uSector < volumeInfo->SectorsPerCluster; uSector++)
{
if (DPBitMap_Set(volumeInfo->bitMap_Free, base + uSector, TRUE) != STATUS_SUCCESS)
{
status = STATUS_UNSUCCESSFUL;
goto __faild;
}
}
}
}
lpBitmap = NULL;
}
}
else
{
status = STATUS_UNRECOGNIZED_VOLUME;
goto __faild ;
}

if (volumeInfo->bootIndicator)
{
setBitmapDirectRWFile(volumeInfo->volume,
(*NtBuildNumber >= 2600) ? L"\\Windows\\bootstat.dat" : L"\\WINNT\\bootstat.dat",
volumeInfo->bitMap_Protect);
}
// 页面文件
setBitmapDirectRWFile(volumeInfo->volume, L"\\pagefile.sys", volumeInfo->bitMap_Protect);
setBitmapDirectRWFile(volumeInfo->volume, L"\\hiberfil.sys", volumeInfo->bitMap_Protect);
RtlInitializeGenericTable(&volumeInfo->redirectMap, CompareRoutine, AllocateRoutine, FreeRoutine, NULL);
status = STATUS_SUCCESS;
__faild:
if (!NT_SUCCESS(status))
{
if (volumeInfo->bitMap_Redirect)
{
DPBitMap_Free(volumeInfo->bitMap_Redirect);
volumeInfo->bitMap_Redirect = NULL;
}
if (volumeInfo->bitMap_Protect)
{
DPBitMap_Free(volumeInfo->bitMap_Protect);
volumeInfo->bitMap_Protect = NULL;
}
if (volumeInfo->bitMap_Free)
{
DPBitMap_Free(volumeInfo->bitMap_Free);
volumeInfo->bitMap_Free = NULL;
}
}
__free_Safe(bitMap);

return STATUS_SUCCESS;
}

自己比较菜吧,总之是拆东墙补西墙。。。。好歹凑合着能用了。牛人看了,就不要喷了!
2013-4-14 02:03
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
4
这代码贴的一片混乱~~
不知道你说的代码是不是这个
http://diskflt.googlecode.com
2013-4-14 02:54
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
5
楼主和大大,熬夜伤身啊!
2013-4-14 09:27
0
雪    币: 11246
活跃值: (17864)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
来支持一下啊
2013-4-17 17:49
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
过于深奥........
2013-6-6 08:35
0
雪    币: 443
活跃值: (83)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
标记一下
2013-6-6 08:56
0
雪    币: 166
活跃值: (62)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢楼主分享代码,大概看了下,其中GetSpecificBPB函数,不知道楼主在哪儿调用的,另外楼主有没有解决原版拷贝超过2G文件死机的BUG
2013-7-4 14:04
0
雪    币: 623
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
mark
2013-9-17 10:37
0
游客
登录 | 注册 方可回帖
返回
//