NTFS文件系统解析(三)

1、引言

对于NTFS文件系统而言,无论文件内容本身,抑或真实的文件属性,都被称之为属性。
而正如前文说到的,NTFS预定义了16种属性用于文件系统的管理。
而通常情况下,往往只需要关注其中的某些属性即可。

2、属性头

为了便于管理,NTFS文件系统为所有的属性定义了统一的头部结构,可以称之为属性头。
而由于每种属性的长度不一,因此又额外定义了常驻属性和非常驻属性。

// 长度:0x10
typedef struct {
  b32 attr_type;  // 当前属性类型
  b32 length;     // 属性长度
  b8 non_resident;  // 常驻属性标识:0 - 常驻属性, 1 - 非常驻属性
  b8 name_length;   // 属性名长度:0 - 无名属性
  ub16 name_offset; // 属性名偏移:0x18
  ub16 flags;    //  
  ub16 attr_id;  // 
} AttributeHeader;

// 长度:0x8 + 0x10
typedef struct {
  AttributeHeader header;  // 属性头
  b32 length;              // 属性体长度
  ub16 offset;             // 属性偏移
  b8 index_flag;           // Indexed flag
  b8 padding;              // Padding
} ResidentAttrHeader;

// 长度:0x30 + 0x10
typedef struct {
  AttributeHeader header;  // 属性头
  b64 vcn_begin;           // 起始VCN号
  b64 vcn_end;             // 结束VCN号
  ub16 data_run_offset;    // Data Runs偏移
  ub16 compression_size;   // Compression unit size
  b32 padding;             // Padding
  b64 byte_alloc;          // 分配大小
  b64 byte_use;            // 实际使用大小
  b64 init_size;           // Initialized data size of the stream
} NonResidentAttrHeader;

3、$STANDARD_INFORMATION

NTFS文件系统解析(三)_第1张图片
常驻属性。通常情况下我们可以通过本属性获取文件时间和文件访问属性。

// 文件属性
typedef enum {
  READONLY = 0x0001,
  HIDDEN = 0x0002,
  SYSTEM = 0x0004,
  ARCHIVE = 0x0020,
  DEVICE = 0x0040,
  NORMAL = 0x0080,
  TEMPORARY = 0x0100,
  SPARSEFILE = 0x0200,
  REPARES_Point = 0x0400,
  COMPRESSED = 0x0800,
  OFFLINE = 0x1000,
  NOT_CONTENT_INDEXED = 0x2000,
  ENCRYPTED = 0x4000,
  DIRECTORY = 0x10000000,   //(copy from corresponding bit in MFT record)
  INDEX_VIEW = 0x20000000,  //(copy from corresponding bit in MFT record)
} FileAttrFlags;

// STANDARD_INFORMATION = 0x10,
typedef struct {
  b64 time_create;      // 文件创建时间
  b64 time_update;      // 文件修改时间
  b64 time_mft_change;  // 文件记录修改时间
  b64 time_access;      // 文件访问时间
  b32 file_attribute;   // 文件属性
  b32 max_version;      // 文件最大版本
  b32 version;          // 当前文件版本
  b32 class_id;         // Class Id
  b32 owner_id;         // Owner Id
  b32 security_id;      // Security Id
  b64 quota_charged;    // Quota charged
  b64 usn;              // USN Journel
} StdInformation;

4、$ATTRIBUTE_LIST

常驻/非常驻属性。

当一个文件或者文件夹存在多个文件记录时,主文件记录中会生成一个或多个ATTRIBUTE_LIST属性。在这种情况下,需要通过遍历ATTRIBUTE_LIST属性读取base_record_ref对应的文件记录。

// ATTRIBUTE_LIST = 0x20,
typedef struct {
  b32 attr_type;  // Attribute Type
  ub16 record_length;
  b8 name_length;
  b8 name_offset;
  b64 start_vcn;
  b64 base_record_ref;  // 文件记录号
  ub16 attr_id;
} AttrList;

5、$FILE_NAME

NTFS文件系统解析(三)_第2张图片

常驻属性。通常情况下,一个文件只存在一个FILE_NAME属性,这种情况下,文件的基本属性与STANDARD_INFORMATION是保持一致的。

但是当文件系统结构变化时,如上图所示。或者当文件产生硬链接时,FILE_NAME属性都会增加。这种情况下,就需要对本属性做特殊处理。

// 文件名命名空间
typedef enum {
  POSIX_STYLE = 0,
  WIN32_STYLE,
  DOS_STYLE,
  WIN_DOS_STYLE,
} FileNameSpace;

// FILE_NAME = 0x30,
typedef struct {
  b64 parent_ref;       // 低6位存储当前文件记录号
  b64 time_create;      // 文件创建时间
  b64 time_update;      // 文件修改时间
  b64 time_mft_change;  // 文件记录修改时间
  b64 time_access;      // 文件访问时间
  b64 byte_alloc;       // 分配大小
  b64 byte_use;         // 实际使用大小
  b32 flags;            // 文件属性
  b32 ea_flags;         // 文件EA属性
  ub8 filename_length;  // 文件名长度(单位):字符 
  b8 name_space;        // 命名空间
} FileName;

6、$VOLUME_INFORMATION

常驻属性。通常情况下,卷信息属性只存储在Volume中。不需要特殊处理

// VOLUME_INFORMATION = 0x70,
typedef struct {
  b8 resv1[8];   // 00
  b8 major_ver;  // major version 1--winNT, 3--Win2000/XP
  b8 minor_ver;  // minor version 0--win2000, 1--WinXP/7
  ub16 flag;     // mark
  b8 resv2[4];   // 00
} VolumeInformation;

7、$DATA

常驻/非常驻属性。DATA属性用于存储文件本身的数据。当文件内容较少时,数据直接存储在DATA中。
当数据长度超过一定时,DATA中存储Data Runs,数据本身则异地存储。
注意:文件内容数据只存储在有名DATA属性中,因此通过DATA读取文件内容时需要对name_length进行判断。

8、$INDEX_ROOT

NTFS文件系统解析(三)_第3张图片
常驻属性。索引根节点通常由标准属性头,索引根属性头,索引属性头和索引属性组成。
索引根属性头决定当前块存储的索引类型。通常情况下,索引中存储的都是0x30文件名属性。
正如上图所示,绿色部分代表IndexEntry的头部,紧接着的红色部分和黄色部分就是去除了标准属性头之后的0x30属性,而最后的紫色部分则存储着子节点的VCN号。

typedef enum {
  ENTRY_SUBNODE = 1,  // 存在子节点
  ENTRY_LAST = 2,     // 叶子节点
} IdxEntryTypes;

// INDEX_ROOT = 0x90,
typedef struct {
  // Index Root Header
  b32 attr_type;          // 属性类型
  b32 collation_rule;
  b32 index_size;         // 索引块大小
  b8 clusters_per_index;  // Clusters per index block (same as Bpb?)
  b8 padding[3];          // Padding
  // Index Header
  b32 entry_offset;  // 第一个索引的偏移
  b32 total_size;    // 索引数据的总大小
  b32 alloc_size;    // Allocated size of the index entries
  b8 flags;          // 索引标志
  b8 padding2[3];    // Padding
} IndexRoot;

typedef struct {
  b64 mft_ref;
  ub16 size;         // 索引大小
  ub16 stream_size;  // 数据流长度
  b8 flags;          // 索引标志
  b8 padding[3];     // Padding
  // copy of body(without header) of attribute
  /* Name | Index Of              | Used By
   * --------------------------------------
   * $I30 | Filenames	            | 目录
   * $SDH | Security Descriptors  | $Secure
   * $SII | Security Ids	        | $Secure
   * $O   | Object Ids	          | $ObjId
   * $O   | Owner Ids	            | $Quota
   * $Q   | Quotas	              | $Quota
   * $R   | Reparse Points	      | $Reparse
   */
  b8 stream[1];  // align to 8
  // VCN of the sub-node in the Index Allocation
} IndexEntry;

9、$INDEX_ALLOCATION

NTFS文件系统解析(三)_第4张图片

非常驻属性。INDEX_ALLOCATION的结构与INDEX_ROOT基本一致。唯一的差别在于一个是常驻属性,另一个是非常驻属性。

typedef struct {
  // Index Record Header
  b32 magic;        // "INDX"
  ub16 usn_offset;  // offset of update sequence number
  ub16 usn_size;    // size of update sequence number and array, by words
  b64 lsn;          // $LogFile sequence number
  b64 vcn;          // vcn of this index block in the index allocation
  // Index Header
  b32 entry_offset;  // Offset to the first index entry
  b32 total_size;    // Total size of the index entries
  b32 alloc_size;    // Allocated size of the index entries
  b8 flags;          // Non-leaf node Flag
  b8 padding[3];     // Padding
} IndexBlock;

typedef struct {
  b64 mft_ref;
  ub16 size;         // 索引大小
  ub16 stream_size;  // 数据流长度
  b8 flags;          // 索引标志
  b8 padding[3];     // Padding
  // copy of body(without header) of attribute
  /* Name | Index Of              | Used By
   * --------------------------------------
   * $I30 | Filenames	            | 目录
   * $SDH | Security Descriptors  | $Secure
   * $SII | Security Ids	        | $Secure
   * $O   | Object Ids	          | $ObjId
   * $O   | Owner Ids	            | $Quota
   * $Q   | Quotas	              | $Quota
   * $R   | Reparse Points	      | $Reparse
   */
  b8 stream[1];  // align to 8
  // VCN of the sub-node in the Index Allocation
} IndexEntry;

你可能感兴趣的:(文件系统,NTFS)