您现在的位置: 论文网 >> 计算机论文 >> 计算机应用论文 >> 探索NTFS论文

探索NTFS

作者:未知
出处:论文网
时间:2007-04-13



    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的输出结果$STANDARD_INFORMATION、$FILE_NAME、$DATA等在NTFS中称为属性(Attribute)。属性分为常驻属性(Resident Attribute)与非常驻属性(Nonresident Attribute)。文件的数据也包含在属性中,似乎与属性这个名称有点混谣。不过这又让NTFS有了更加统一的组织文件的形式。这也同时让NTFS有MultiStreams的特性(上面也演示了这个特性)。通过指定的File Record定位给定的Attribute的实现代码如下:

    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提供的这个FindAttribute函数在Attribute name(即第三个参数)不为空串时可能会出现bug,主要原因是_wcsicmp对UNICODE字符串比较时应该是以结束的标准的C字符串。我在提供的代码中已经纠正了这个错误。 

    下面我将通过使用SoftICE来分析这段代码得到$MFT的$FILE_NAME属性来得到$MFT的file name。这个示例同样适用于得到其它文件的$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, "x01"
     unsigned short LinkCount = 0x1, "x01"
     unsigned short AttributesOffset = 0x30, "0"
     unsigned short Flags = 0x1, "x01"
     unsigned long BytesInUse = 0x2D8, "x02xD8"
     unsigned long BytesAllocated = 0x400, "x04"
     unsigned quad BaseFileRecord = 0x0, ""
     unsigned short NextAttributeNumber = 0x6, "x06"

    file参数我传入的是$MFT,从$MFT的LCN=4可以得到其在卷中的物理地址,这在上面已说明。你也可以使用dskprobe(我机子中为第LCN*SectorsPerCluster=4*8扇区)得到底下SoftICE的输出结果:

    :dd @file //以下的注释可对照文中开头列出的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      ....`...........
                  --------  --------
                     |         |_指出这个Attribute的长度。定义如下。
                     |_根据AttributeOffset得到的Attribute头,定义如下。00000010指出这个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是一个Enum型定义。其中00000010为StandardInformation。30为FileName。因为FileNameAttribute总是一个常驻Attribute,所以我将RESIDENT_ATTRIBUTE定义也给出。OK,现在可以继续Dump下一个Attribute:

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

    :dd @file+30+60
    0023:00344DC8 00000030  00000068  00180000  00030000      0...h...........
                  --------            ------
                     |                   |___这里的NameLength与NameOffset指FileNameAttribute名。不要与$MFT FileName混谣。
                     |_指出这是一个FileNameAttribute。
    0023:00344DD8 0000004A  00010018  00000005  00050000      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的一个具体方法。最后我将给出遍历File Record的代码,在给出代码前应该说明一下$MFT中$BITMAP属性。NTFS的这个Attribute相当于LINUX EXT2的s_inode_bitmap数组(Linux 2.0版本)。所以很容易明白$BITMAP的作用,即每bit指出相应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 %.*wsn", i, int(name->NameLength),name->Name)
             }
        }
    }

    本文引用Gary Nebbett的些定义可能对Windows 2000版本有些很小的出入,不过Internet有其神奇的地方,虽然Microsoft不提供这些信息,但诸如linux-ntfs GNU工程等均是学习NTFS的一个很好的资料,本文也参考了很多它提供的文档。另外Mark Russinovich的《Inside Win2K NTFS》、《Inside NTFS》、《Exploring NTFS On-disk Structures》等也是很好的NTFS资料。本文仍未涉及NTFS中目录的组织(B+树)等等,可能的话我会另行介绍。文中介绍的完整代码可到http://webcrazy.yeah.net下载。出现的错误也欢迎来信指教(tsu00@263.net)!

    最后感谢Anton Altaparmakov,感谢我的同事在出差时抽空给我买到Gary Nebbett的书。感谢我看到的所有资料的原作者们。感谢他们!

参考资料:
    1.Gary Nebbett《Windows NT/2000 Native API Reference》
    2.Linux-NTFS Project NTFS Documentation Version 0.4
    3.Mark Russinovich相关文档
    4.David Solomom《Inside Windows NT,2nd Edition》

上一页 [1] [2]

论文搜索
关键字:NTFS 计算机
最新计算机应用论文
基于网络信息安全技术管理的计算机应用研究
浅析人工智能体系建设
抖音短视频平台视频推荐模式研究
应用电子技术中可编程控制器的应用探讨
用友NC信息系统的实施应用实践研究
基于校园一卡通数据系统的学生行为分析研究
云环境下基于蚁群算法的动态容错技术研究
自拍图像中的记忆痕迹
抖音短视频用户使用动机研究
基于创新扩散理论的Vlog传播
热门计算机应用论文
学生成绩管理系统的设计与实现
浅析计算机病毒及防范的措施
学籍管理系统软件
对计算科学与计算机发展的思考
计算机应用型人才的培养模式研究
物资管理信息系统开发
计算机信息管理在第三方物流中的应用
嵌入式系统数字图像采集接口电路设计
基于B/S体系结构开发应用系统
项目管理在软件中的应用