日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

探索NTFS

發(fā)布時(shí)間:2025/3/15 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 探索NTFS 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

探索NTFS

探索NTFS
?????????????????????WebCrazy(tsu00@263.net)

????NTFS是Windows?NT引入的新型文件系統(tǒng),它具有許多新特性。本文旨在探索NTFS的底層結(jié)構(gòu),所敘述的也僅是文件在NTFS卷上的分布。NTFS中,卷中所有存放的數(shù)據(jù)均在一個(gè)叫$MFT的文件中,叫主文件表(Master?File?Table)。而$MFT則由文件記錄(File?Record)數(shù)組構(gòu)成。File?Record的大小一般是固定的,通常情況下均為1KB,這個(gè)概念相當(dāng)于Linux中的inode。File?Record在$MFT文件中物理上是連續(xù)的,且從0開始編號(hào)。$MFT僅供File?System本身組織、架構(gòu)文件系統(tǒng)使用,這在NTFS中稱為元數(shù)據(jù)(Metadata)。以下列出Windows?2000?Release出的NTFS的元數(shù)據(jù)文件(我將要給出的示例代碼的部分輸出結(jié)果)。
????File?Record(inode)?FileName
????------------------?--------
??????????0?????????????$MFT
??????????1?????????????$MFTMirr
??????????2?????????????$LogFile
??????????3?????????????$Volume
??????????4?????????????$AttrDef
??????????5?????????????.
??????????6?????????????$Bitmap
??????????7?????????????$Boot
??????????8?????????????$BadClus
??????????9?????????????$Secure
?????????10?????????????$UpCase
?????????11?????????????$Extend

????Windows?2000中不能使用dir命令(甚至加上/ah參數(shù))像普通文件一樣列出這些元數(shù)據(jù)文件。實(shí)際上File?System?Driver(ntfs.sys)維護(hù)了一個(gè)系統(tǒng)變量NtfsProtectSystemFiles用于隱藏這些元數(shù)據(jù)。默認(rèn)情況下,這個(gè)變量被設(shè)為TRUE,所以使用dir?/ah將得不到任何文件。知道這個(gè)行為后使用i386kd修改NtfsProtectSystemFiles后即可以列出元數(shù)據(jù)文件:

????kd>?x?ntfs!NtfsProtect*
????fe213498??Ntfs!NtfsProtectSystemFiles
????fe21349c??Ntfs!NtfsProtectSystemAttributes
????kd>?dd?ntfs!NtfsProtectSystemFiles?l?2
????fe213498??00000001?00000001
????kd>?ed?ntfs!NtfsProtectSystemFiles?0
????kd>?dd?ntfs!NtfsProtectSystemFiles?l?2
????fe213498??00000000?00000001
????kd>

????D:/>ver

????Microsoft?Windows?2000?[Version?5.00.2195]

????D:/>dir?/ah?$*
?????驅(qū)動(dòng)器?D?中的卷是?W2KNTFS
?????卷的序列號(hào)是?E831-9D04

?????D:/?的目錄

????2000-04-27??19:31???????????????36,000?$AttrDef
????2000-04-27??19:31????????????????????0?$BadClus
????2000-04-27??19:31???????????????67,336?$Bitmap
????2000-04-27??19:31????????????????8,192?$Boot
????2000-04-27??19:31???????<DIR>??????????$Extend
????2000-04-27??19:31???????????13,139,968?$LogFile
????2000-04-27??19:31???????????27,575,296?$MFT
????2000-04-27??19:31????????????????4,096?$MFTMirr
????2000-04-27??19:31??????????????131,072?$UpCase
????2000-04-27??19:31????????????????????0?$Volume
???????????????????9?個(gè)文件?????40,961,960?字節(jié)
???????????????????1?個(gè)目錄?????51,863,552?可用字節(jié)

????需要指出的是ntfs.sys將元數(shù)據(jù)文件以一種特殊的方式打開,所以在打開NtfsProtectSystemFiles后,如果使用ReadFile等產(chǎn)生IRP_MJ_READ等IRP包時(shí)將會(huì)導(dǎo)致Page?Fault(詳見Gary?Nebbett的《Windows?NT/2000?Native?API?Reference》)。

????以上的討論均是基于$MFT文件而討論的,即基于$MFT中的File?Record(inode)討論的。為更好的繼續(xù)以下的討論,這兒我列出File?Record?Header的結(jié)構(gòu):

????typedef?struct?{
????????ULONG?Type;
????????USHORT?UsaOffset;
????????USHORT?UsaCount;
????????USN?Usn;
????}?NTFS_RECORD_HEADER,?*PNTFS_RECORD_HEADER;

????typedef?struct?{
????????NTFS_RECORD_HEADER?Ntfs;
????????USHORT?SequenceNumber;
????????USHORT?LinkCount;
????????USHORT?AttributesOffset;
????????USHORT?Flags;???????????????//?0x0001?=?InUse,?0x0002?=?Directory
????????ULONG?BytesInUse;
????????ULONG?BytesAllocated;
????????ULONGLONG?BaseFileRecord;
????????USHORT?NextAttributeNumber;
????}?FILE_RECORD_HEADER,?*PFILE_RECORD_HEADER;

????下面我將討論如何定位$MFT。稍微有點(diǎn)操作系統(tǒng)知識(shí)的人都會(huì)知道引導(dǎo)扇區(qū)(Boot?Sector),其物理位置為卷中的第一個(gè)扇區(qū)。以下由dskprobe.exe(Windows?2000?Resource?Kit中的一個(gè)小工具)分析的第一個(gè)扇區(qū)(當(dāng)然也可以使用WinHex等其他應(yīng)用程序):

????File:?d:/Sector00.bin
????Size:?0x00000200?(512)

????Address??|?00?01?02?03-04?05?06?07?:?08?09?0A?0B-0C?0D?0E?0F?|?0123456789ABCDEF
????---------|-------------------------:-------------------------|-----------------
????00000000?|?EB?52?90?4E-54?46?53?20?:?20?20?20?00-02?08?00?00?|??R?NTFS????.....
????00000010?|?00?00?00?00-00?F8?00?00?:?3F?00?F0?00-3F?00?00?00?|?.....?..?.e.?...
????00000020?|?00?00?00?00-80?00?80?00?:?90?C0?41?00-00?00?00?00?|?....€.€.惱A.....
????00000030?|?04?00?00?00-00?00?00?00?:?09?1C?04?00-00?00?00?00?|?................
????00000040?|?F6?00?00?00-01?00?00?00?:?04?9D?31?E8-BB?31?E8?94?|??.......?杌1钄
????????????????????????.?????????????????????????.
????????????????????????.?????????????????????????.
????????????????????????.?????????????????????????.
????000001F0?|?00?00?00?00-00?00?00?00?:?83?A0?B3?C9-00?00?55?AA?|?........儬成..U?



????這512字節(jié)為如下的格式:(摘自Gary?Nebbett書中,本文許多代碼均來自或參考此書。)

????#pragma?pack(push,?1)

????typedef?struct?{
????????UCHAR?Jump[3];
????????UCHAR?Format[8];
????????USHORT?BytesPerSector;
????????UCHAR?SectorsPerCluster;
????????USHORT?BootSectors;
????????UCHAR?Mbz1;
????????USHORT?Mbz2;
????????USHORT?Reserved1;
????????UCHAR?MediaType;
????????USHORT?Mbz3;
????????USHORT?SectorsPerTrack;
????????USHORT?NumberOfHeads;
????????ULONG?PartitionOffset;
????????ULONG?Reserved2[2];
????????ULONGLONG?TotalSectors;
????????ULONGLONG?MftStartLcn;
????????ULONGLONG?Mft2StartLcn;
????????ULONG?ClustersPerFileRecord;
????????ULONG?ClustersPerIndexBlock;
????????ULONGLONG?VolumeSerialNumber;
????????UCHAR?Code[0x1AE];
????????USHORT?BootSignature;
????}?BOOT_BLOCK,?*PBOOT_BLOCK;

????#pragma?pack(pop)

????各個(gè)字段的詳細(xì)意義從字段名中即可大致清楚。在linux-ntfs的GNU工程(http://sf.net/projects/linux-ntfs)中也有詳細(xì)的文檔,限于篇幅我不將其列出。可以使用如下代碼讀出卷中的第一個(gè)扇區(qū):


????hVolume?=?CreateFile(drive,?GENERIC_READ,?FILE_SHARE_READ?|?FILE_SHARE_WRITE,?0,
?????????????????????????OPEN_EXISTING,?0,?0);

????ReadFile(hVolume,?&bootb,?sizeof(bootb),?&n,?0);

????bootb是一個(gè)BOOT_BLOCK結(jié)構(gòu),在我的卷中如下格式(請(qǐng)對(duì)應(yīng)Sector00.bin分析):

????Dump?BootBlock?at?below:
????????BytesPerSector:200
????????SectorsPerCluster:8
????????BootSectors:0
????????SectorsPerTrack:3F
????????NumberOfHeads:F0
????????PartitionOffset:3F
????????TotalSectors:41C090
????????MftStartLcn:4
????????Mft2StartLcn:41C09
????????ClustersPerFileRecord:F6
????????ClustersPerIndexBlock:1
????????VolumeSerialNumber:E8319D04
????????BootSignature:AA55


????以上的MftStartLcn其實(shí)是$MFT在卷中的簇(Cluster)號(hào)。簇是NTFS的基本單位,最小單位。一個(gè)只有1Byte的文件也要占用一簇的空間。NTFS使用LCN(Logical?Cluster?Number)來代表NTFS卷中的物理位置,其簡(jiǎn)單的從0到卷中的總簇?cái)?shù)減一進(jìn)行編號(hào)。對(duì)于一個(gè)特定的文件NTFS則使用VCN(Virtual?Cluster?Number)來映射LCN實(shí)現(xiàn)文件的組織。從MftStartLcn的值4可以知道$MFT的LCN為4與SectorsPerCluster、BytesPerSector的大小即可定位$MFT的位置。得到$MFT的位置后,如果遍歷$MFT中所有的File?Record即可以得到卷中所有的文件列表(前面已經(jīng)提到File?Record只是簡(jiǎn)單的從0開始編號(hào))。也就是說到目前為止已經(jīng)可以對(duì)文件組織有最簡(jiǎn)單的認(rèn)識(shí),但如何得到文件的信息呢,如文件名等等。NTFS中所有文件包括普通的用戶文件、元數(shù)據(jù)文件均用同樣的方式組織數(shù)據(jù)、屬性等。我將nfi.exe(來自Windows?NT/2000?OEM?Support?Tools)的輸出結(jié)果列出,作為我敘述的開始:

????D:/>copy?con?file
????testforntfs^Z
????已復(fù)制?????????1?個(gè)文件。

????D:/>nfi?d:/file
????NTFS?File?Sector?Information?Utility.
????Copyright?(C)?Microsoft?Corporation?1999.?All?rights?reserved.

????/file
????????$STANDARD_INFORMATION?(resident)
????????$FILE_NAME?(resident)
????????$DATA?(resident)

????D:/>echo?testforattr>file:ATTR

????D:/>nfi?d:/file
????NTFS?File?Sector?Information?Utility.
????Copyright?(C)?Microsoft?Corporation?1999.?All?rights?reserved.

????/file
????????$STANDARD_INFORMATION?(resident)
????????$FILE_NAME?(resident)
????????$DATA?(resident)
????????$DATA?ATTR?(resident)

????nfi的輸出結(jié)果$STANDARD_INFORMATION、$FILE_NAME、$DATA等在NTFS中稱為屬性(Attribute)。屬性分為常駐屬性(Resident?Attribute)與非常駐屬性(Nonresident?Attribute)。文件的數(shù)據(jù)也包含在屬性中,似乎與屬性這個(gè)名稱有點(diǎn)混謠。不過這又讓NTFS有了更加統(tǒng)一的組織文件的形式。這也同時(shí)讓NTFS有MultiStreams的特性(上面也演示了這個(gè)特性)。通過指定的File?Record定位給定的Attribute的實(shí)現(xiàn)代碼如下:

????template?<class?T1,?class?T2>?inline?
????T1*?Padd(T1*?p,?T2?n)?{?return?(T1*)((char?*)p?+?n);?}

????PATTRIBUTE?FindAttribute(PFILE_RECORD_HEADER?file,
?????????????????????????????ATTRIBUTE_TYPE?type,?PWSTR?name)
????{
????????for?(PATTRIBUTE?attr?=?PATTRIBUTE(Padd(file,?file->AttributesOffset));
?????????????attr->AttributeType?!=?-1;
?????????????attr?=?Padd(attr,?attr->Length))?{

????????????if?(attr->AttributeType?==?type)?{
????????????????if?(name?==?0?&&?attr->NameLength?==?0)?return?attr;

????????????????if?(name?!=?0?&&?wcslen(name)?==?attr->NameLength
????????????????????&&?_wcsicmp(name,?PWSTR(Padd(attr,?attr->NameOffset)))?==?0)?return?attr;
????????????}
????????}

????????return?0;
????}??

????Gary?Nebbett提供的這個(gè)FindAttribute函數(shù)在Attribute?name(即第三個(gè)參數(shù))不為空串時(shí)可能會(huì)出現(xiàn)bug,主要原因是_wcsicmp對(duì)UNICODE字符串比較時(shí)應(yīng)該是以/0結(jié)束的標(biāo)準(zhǔn)的C字符串。我在提供的代碼中已經(jīng)糾正了這個(gè)錯(cuò)誤。?

????下面我將通過使用SoftICE來分析這段代碼得到$MFT的$FILE_NAME屬性來得到$MFT的file?name。這個(gè)示例同樣適用于得到其它文件的$FILE_NAME(如上面的file)、還有其它的屬性如$DATA等等。

????:bpx?FindAttribute

????Break?due?to?BPX?FindAttribute??(ET=6.89?seconds)

????:locals
????????[EBP-4]?+struct?ATTRIBUTE?*?attr?=?0x00344D68?<{...}>
????????[EBP+8]?+struct?FILE_RECORD_HEADER?*?file?=?0x00344D38?<{...}>?
????????[EBP+C]??enum?ATTRIBUTE_TYPE?type?=?AttributeFileName?(30)
????????[EBP+10]?+unsigned?short?*?name?=?0x004041BC?<"$MFT">

????:?file
????struct?FILE_RECORD_HEADER?*?=?0x00344D38?<{...}>
?????struct?NTFS_RECORD_HEADER?Ntfs?=?{...}
?????unsigned?short?SequenceNumber?=?0x1,?"/0/x01"
?????unsigned?short?LinkCount?=?0x1,?"/0/x01"
?????unsigned?short?AttributesOffset?=?0x30,?"/00"
?????unsigned?short?Flags?=?0x1,?"/0/x01"
?????unsigned?long?BytesInUse?=?0x2D8,?"/0/0/x02/xD8"
?????unsigned?long?BytesAllocated?=?0x400,?"/0/0/x04/0"
?????unsigned?quad?BaseFileRecord?=?0x0,?"/0/0/0/0/0/0/0/0"
?????unsigned?short?NextAttributeNumber?=?0x6,?"/0/x06"

????file參數(shù)我傳入的是$MFT,從$MFT的LCN=4可以得到其在卷中的物理地址,這在上面已說明。你也可以使用dskprobe(我機(jī)子中為第LCN*SectorsPerCluster=4*8扇區(qū))得到底下SoftICE的輸出結(jié)果:

????:dd?@file?//以下的注釋可對(duì)照文中開頭列出的FILE_RECORD_HEADER定義。
????0023:00344D38?454C4946??0003002A??6D4AC04D??00000000??????FILE*...M.Jm....
????0023:00344D48?00010001??00010030??000002D8??00000400??????....0...........
????????????????????????????????----
?????????????????????????????????|__AttributeOffset
????0023:00344D58?00000000??00000000??04340006??0000FA0D??????..........4.....
????0023:00344D68?00000010??00000060??00180000??00000000??????....`...........
??????????????????--------??--------
?????????????????????|?????????|_指出這個(gè)Attribute的長(zhǎng)度。定義如下。
?????????????????????|_根據(jù)AttributeOffset得到的Attribute頭,定義如下。00000010指出這個(gè)Attribute為StandardInformation

????0023:00344D78?00000048??00000018??2C1761D0??01BFB03C??????H........a.,<...

????Attribute頭如下定義:

????typedef?struct?{
????????ATTRIBUTE_TYPE?AttributeType;
????????ULONG?Length;
????????BOOLEAN?Nonresident;
????????UCHAR?NameLength;
????????USHORT?NameOffset;
????????USHORT?Flags;???????????????//?0x0001?=?Compressed
????????USHORT?AttributeNumber;
????}?ATTRIBUTE,?*PATTRIBUTE;

????typedef?struct?{
????????ATTRIBUTE?Attribute;
????????ULONG?ValueLength;
????????USHORT?ValueOffset;
????????USHORT?Flags;???????????????//?0x0001?=?Indexed
????}?RESIDENT_ATTRIBUTE,?*PRESIDENT_ATTRIBUTE;

????typedef?struct?{
????????ULONGLONG?DirectoryFileReferenceNumber;
????????ULONGLONG?CreationTime;???//?Saved?when?filename?last?changed
????????ULONGLONG?ChangeTime;?????//?ditto
????????ULONGLONG?LastWriteTime;??//?ditto
????????ULONGLONG?LastAccessTime;?//?ditto
????????ULONGLONG?AllocatedSize;??//?ditto
????????ULONGLONG?DataSize;???????//?ditto
????????ULONG?FileAttributes;?????//?ditto
????????ULONG?AlignmentOrReserved;
????????UCHAR?NameLength;
????????UCHAR?NameType;???????????//?0x01?=?Long,?0x02?=?Short
????????WCHAR?Name[1];
????}?FILENAME_ATTRIBUTE,?*PFILENAME_ATTRIBUTE;


????ATTRIBUTE_TYPE是一個(gè)Enum型定義。其中00000010為StandardInformation。30為FileName。因?yàn)镕ileNameAttribute總是一個(gè)常駐Attribute,所以我將RESIDENT_ATTRIBUTE定義也給出。OK,現(xiàn)在可以繼續(xù)Dump下一個(gè)Attribute:

????//?dd?@file+file->AttributeOffset+length(StandardInformationAttribute)

????:dd?@file+30+60
????0023:00344DC8?00000030??00000068??00180000??00030000??????0...h...........
??????????????????--------????????????------
?????????????????????|???????????????????|___這里的NameLength與NameOffset指FileNameAttribute名。不要與$MFT?FileName混謠。
?????????????????????|_指出這是一個(gè)FileNameAttribute。
????0023:00344DD8?0000004A??00010018??00000005??00050000??????J...............
??????????????????--------??????----??--------
?????????????????????|????????????|???????|_根據(jù)ValueOffset的值,得到FILENAME_ATTRIBUTE的具體位置。
?????????????????????|????????????|_ValueOffset值
?????????????????????|_ValueLength值
????0023:00344DE8?2C1761D0??01BFB03C??2C1761D0??01BFB03C??????.a.,<....a.,<...
????0023:00344DF8?2C1761D0??01BFB03C??2C1761D0??01BFB03C??????.a.,<....a.,<...
????0023:00344E08?00004000??00000000??00004000??00000000??????.@.......@......
????0023:00344E18?00000006??00000000??00240304??0046004D??????..........$.M.F.
????????????????????????????????????????????--??--------
????????????????????????????????????????????|??????|___找到$MFT的FileName了吧。
????????????????????????????????????????????|_NameLength
????0023:00344E28?00000054??00000000??00000080??00000190??????T...............
????0023:00344E38?00400001??00010000??00000000??00000000??????..@.............

????這兒給出了Dump?Attribute的一個(gè)具體方法。最后我將給出遍歷File?Record的代碼,在給出代碼前應(yīng)該說明一下$MFT中$BITMAP屬性。NTFS的這個(gè)Attribute相當(dāng)于LINUX?EXT2的s_inode_bitmap數(shù)組(Linux?2.0版本)。所以很容易明白$BITMAP的作用,即每bit指出相應(yīng)File?Record的在用情況。以下是DumpAllFileRecord的代碼:


????BOOL?bitset(PUCHAR?bitmap,?ULONG?i)
????{
????????return?(bitmap[i?>>?3]?&?(1?<<?(i?&?7)))?!=?0;
????}

????VOID?DumpAllFileRecord()
????{
????????PATTRIBUTE?attr?=?FindAttribute(MFT,?AttributeBitmap,?0);
????????PUCHAR?bitmap?=?new?UCHAR[AttributeLengthAllocated(attr)];

????????ReadAttribute(attr,?bitmap);

????????ULONG?n?=?AttributeLength(FindAttribute(MFT,?AttributeData,?0))?/?BytesPerFileRecord;

????????PFILE_RECORD_HEADER?file?=?PFILE_RECORD_HEADER(new?UCHAR[BytesPerFileRecord]);

????????for?(ULONG?i?=?0;?i?<?n;?i++)?{
????????????if?(!bitset(bitmap,?i))?continue;

????????????ReadFileRecord(i,?file);

????????????if?(file->Ntfs.Type?==?'ELIF'?&&?(file->Flags?&?3?))?{
????????????????attr?=?FindAttribute(file,?AttributeFileName,?0);
????????????????if?(attr?==?0)?continue;

????????????????PFILENAME_ATTRIBUTE?name
????????????????????=?PFILENAME_ATTRIBUTE(Padd(attr,?PRESIDENT_ATTRIBUTE(attr)->ValueOffset));

????????????????printf("%8lu?%.*ws/n",?i,?int(name->NameLength),name->Name)
?????????????}
????????}
????}

????本文引用Gary?Nebbett的些定義可能對(duì)Windows?2000版本有些很小的出入,不過Internet有其神奇的地方,雖然Microsoft不提供這些信息,但諸如linux-ntfs?GNU工程等均是學(xué)習(xí)NTFS的一個(gè)很好的資料,本文也參考了很多它提供的文檔。另外Mark?Russinovich的《Inside?Win2K?NTFS》、《Inside?NTFS》、《Exploring?NTFS?On-disk?Structures》等也是很好的NTFS資料。本文仍未涉及NTFS中目錄的組織(B+樹)等等,可能的話我會(huì)另行介紹。文中介紹的完整代碼可到http://webcrazy.yeah.net下載。出現(xiàn)的錯(cuò)誤也歡迎來信指教(tsu00@263.net)!

????最后感謝Anton?Altaparmakov,感謝我的同事在出差時(shí)抽空給我買到Gary?Nebbett的書。感謝我看到的所有資料的原作者們。感謝他們!

參考資料:
????1.Gary?Nebbett《Windows?NT/2000?Native?API?Reference》
????2.Linux-NTFS?Project?NTFS?Documentation?Version?0.4
????3.Mark?Russinovich相關(guān)文檔
????4.David?Solomom《Inside?Windows?NT,2nd?Edition》

總結(jié)

以上是生活随笔為你收集整理的探索NTFS的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。