NTFS中的$MFT详解

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

NTFS是WindowsNT引入的新型文档系统,他具备许多新特性。本文旨在探索NTFS的底层结构,所叙述的也仅是文档在NTFS卷上的分布。NTFS中,卷中任何存放的数据均在一个叫$MFT的文档中,叫主文档表(MasterFileTable)。而$MFT则由文档记录(FileRecord)数组构成。FileRecord的大小一般是固定的,通常情况下均为1KB,这个概念相当于Linux中的inode。FileRecord在$MFT文档中物理上是连续的,且从0开始编号。$MFT仅供FileSystem本身组织、架构文档系统使用,这在NTFS中称为元数据(Metadata)。以下列出Windows2000Release出的NTFS的元数据文档(我将要给出的示例代码的部分输出结果)。FileRecord(inode)FileName--------------------------0$MFT1$MFTMirr2$LogFile3$Volume4$AttrDef5.6$Bitmap7$Boot8$BadClus9$Secure10$UpCase11$ExtendWindows2000中不能使用dir命令(甚至加上/ah参数)像普通文档相同列出这些元数据文档。实际上FileSystemDriver(ntfs.sys)维护了一个系统变量NtfsProtectSystemFiles用于隐藏这些元数据。默认情况下,这个变量被设为TRUE,所以使用dir/ah将得不到任何文档。知道这个行为后使用i386kd修改NtfsProtectSystemFiles后即能够列出元数据文档:kdxntfs!NtfsProtect*fe213498Ntfs!NtfsProtectSystemFilesfe21349cNtfs!NtfsProtectSystemAttributeskdddntfs!NtfsProtectSystemFilesl2fe2134980000000100000001kdedntfs!NtfsProtectSystemFiles0kdddntfs!NtfsProtectSystemFilesl2fe2134980000000000000001kdD:\verMicrosoftWindows2000[Version5.00.2195]D:\dir/ah$*驱动器D中的卷是W2KNTFS卷的序列号是E831-9D04D:\的目录2000-04-2719:3136,000$AttrDef2000-04-2719:310$BadClus2000-04-2719:3167,336$Bitmap2000-04-2719:318,192$Boot2000-04-2719:31DIR$Extend2000-04-2719:3113,139,968$LogFile2000-04-2719:3127,575,296$MFT2000-04-2719:314,096$MFTMirr2000-04-2719:31131,072$UpCase2000-04-2719:310$Volume9个文档40,961,960字节1个目录51,863,552可用字节需要指出的是ntfs.sys将元数据文档以一种特别的方式打开,所以在打开NtfsProtectSystemFiles后,假如使用ReadFile等产生IRP_MJ_READ等IRP包时将会导致PageFault(详见GaryNebbett的《WindowsNT/2000NativeAPIReference》)。以上的讨论均是基于$MFT文档而讨论的,即基于$MFT中的FileRecord(inode)讨论的。为更好的继续以下的讨论,这儿我列出FileRecordHeader的结构:typedefstruct{ULONGType;USHORTUsaOffset;USHORTUsaCount;USNUsn;}NTFS_RECORD_HEADER,*PNTFS_RECORD_HEADER;typedefstruct{NTFS_RECORD_HEADERNtfs;USHORTSequenceNumber;USHORTLinkCount;USHORTAttributesOffset;USHORTFlags;//0x0001=InUse,0x0002=DirectoryULONGBytesInUse;ULONGBytesAllocated;ULONGLONGBaseFileRecord;USHORTNextAttributeNumber;}FILE_RECORD_HEADER,*PFILE_RECORD_HEADER;下面我将讨论如何定位$MFT。稍微有点操作系统知识的人都会知道引导扇区(BootSector),其物理位置为卷中的第一个扇区。以下由dskprobe.exe(Windows2000ResourceKit中的一个小工具)分析的第一个扇区(当然也能够使用WinHex等其他应用程式):file:d:\Sector00.binSize:0x00000200(512)Address|00010203-04050607:08090A0B-0C0D0E0F|0123456789ABCDEF---------|-------------------------:-------------------------|-----------------00000000|EB52904E-54465320:20202000-02080000|?R?NTFS.....00000010|00000000-00F80000:3F00F000-3F000000|.....?..?.e.?...00000020|00000000-80008000:90C04100-00000000|......惱A.....00000030|04000000-00000000:091C0400-00000000|................00000040|F6000000-01000000:049D31E8-BB31E894|?.......?杌1钄......000001F0|00000000-00000000:83A0B3C9-000055AA|........儬成..U?这512字节为如下的格式:(摘自GaryNebbett书中,本文许多代码均来自或参考此书。)#pragmapack(push,1)typedefstruct{UCHARJump[3];UCHARFormat[8];USHORTBytesPerSector;UCHARSectorsPerCluster;USHORTBootSectors;UCHARMbz1;USHORTMbz2;USHORTReserved1;UCHARMediaType;USHORTMbz3;USHORTSectorsPerTrack;USHORTNumberOfHeads;ULONGPartitionOffset;ULONGReserved2[2];ULONGLONGTotalSectors;ULONGLONGMftStartLcn;ULONGLONGMft2StartLcn;ULONGClustersPerFileRecord;ULONGClustersPerIndexBlock;ULONGLONGVolumeSerialNumber;UCHARCode[0x1AE];USHORTBootSignature;}BOOT_BLOCK,*PBOOT_BLOCK;#pragmapack(pop)各个字段的周详意义从字段名中即可大致清楚。在linux-ntfs的GNU工程()中也有周详的文档,限于篇幅我不将其列出。能够使用如下代码读出卷中的第一个扇区:hVolume=CreateFile(drive,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);ReadFile(hVolume,&bootb,sizeof(bootb),&n,0);bootb是个BOOT_BLOCK结构,在我的卷中如下格式(请对应Sector00.bin分析):DumpBootBlockatbelow:BytesPerSector:200SectorsPerCluster:8BootSectors:0SectorsPerTrack:3FNumberOfHeads:F0PartitionOffset:3FTotalSectors:41C090MftStartLcn:4Mft2StartLcn:41C09ClustersPerFileRecord:F6ClustersPerIndexBlock:1VolumeSerialNumber:E8319D04BootSignature:AA55以上的MftStartLcn其实是$MFT在卷中的簇(Cluster)号。簇是NTFS的基本单位,最小单位。一个只有1Byte的文档也要占用一簇的空间。NTFS使用LCN(LogicalClusterNumber)来代表NTFS卷中的物理位置,其简单的从0到卷中的总簇数减一进行编号。对于一个特定的文档NTFS则使用VCN(VirtualClusterNumber)来映射LCN实现文档的组织。从MftStartLcn的值4能够知道$MFT的LCN为4和SectorsPerCluster、BytesPerSector的大小即可定位$MFT的位置。得到$MFT的位置后,假如遍历$MFT中任何的FileRecord即能够得到卷中任何的文档列表(前面已提到FileRecord只是简单的从0开始编号)。也就是说到现在为止已能够对文档组织有最简单的认识,但如何得到文档的信息呢,如文档名等等。NTFS中任何文档包括普通的用户文档、元数据文档均用同样的方式组织数据、属性等。我将nfi.exe(来自WindowsNT/2000OEMSupportTools)的输出结果列出,作为我叙述的开始:D:\copyconfiletestforntfs^Z已复制1个文档。D:\nfid:\fileNTFSFileSectorInformationUtility.Copyright(C)MicrosoftCorporation1999.Allrightsreserved.\file$STANDARD_INFORMATION(resident)$FILE_NAME(resident)$DATA(resident)D:\echotestforattrfile:ATTRD:\nfid:\fileNTFSFileSectorInformationUtility.Copyright(C)MicrosoftCorporation1999.Allrightsreserved.\file$STANDARD_INFORMATION(resident)$FILE_NAME(resident)$DATA(resident)$DATAATTR(resident)nfi的输出结果$STANDARD_INFORMATION、$FILE_NAME、$DATA等在NTFS中称为属性(Attribute)。属性分为常驻属性(ResidentAttribute)和很驻属性(NonresidentAttribute)。文档的数据也包含在属性中,似乎和属性这个名称有点混谣。但是这又让NTFS有了更加统一的组织文档的形式。这也同时让NTFS有MultiStreams的特性(上面也演示了这个特性)。通过指定的FileRecord定位给定的Attribute的实现代码如下:templateclassT1,classT2inlineT1*Padd(T1*p,T2n){return(T1*)((char*)pn);}PATTRIBUTEFindAttribute

1 / 9
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功