NTFS文件系统介绍及文件定位

Pullarla

发布日期: 2018-12-12 17:18:16 浏览量: 1204
评分:
star star star star star star star star star star
*转载请注明来自write-bug.com

背景

在日常生活中,我们打开我们的电脑操作各种文件。我们都知道,文件数据都存储在硬盘上,但是,硬盘中存储的数据都是0、1的二进制数据,我们的电脑怎么从这一大堆0、1数据中知道哪个是哪个文件呢?

这就是文件系统在起作用,它对硬盘的数据设置格式规则,存储数据的时候,就按这个存储规则进行存储,那么,在读取数据文件的时候,再按照相应规则读取还原数据,就形成了我们看到的文件了。

现在,本文就介绍目前比较流行的 NTFS 文件系统及其格式定义,并给出一个使用 NTFS 文件系统进行文件定位的例子,模拟 NTFS 定位文件的过程原理。我把分析过程整理成文档,分享给大家。

NTFS介绍

NTFS 文件系统概念

文件系统是操作系统用于明确磁盘或分区上的文件的方法和数据结构,即在磁盘上组织文件的方法。文件系统是对应硬盘的分区的,而不是整个硬盘,不管是硬盘只有一个分区,还是几个分区,不同的分区可以有着不同的文件系统。

NTFS(New Technology File System)是运行在 Windows NT 操纵系统环境和Windows NT 高级服务器网络操作环境的文件系统,随着 Windows NT 操作系统的诞生而产生。NTFS 文件系统具有安全性高、稳定性好、不易产生文件碎片的优点,使得它成为主流的文件系统。

NTFS 文件系统相关概念

  • 分区:分区是磁盘的基本组成部分,被划分的磁盘一部分

  • 卷:NTFS以卷为基础,卷建立在分区的基础上,当以NTFS来格式化磁盘分区时就创建了一个卷

  • 簇:NTFS使用簇作为磁盘空间的分配和回收的基本单位

  • 逻辑簇号(LCN):对卷中所有的簇从头至尾进行编号

  • 虚拟簇号(VCN):对于文件内的所有簇进行编号

  • 主文件表(\$MFT):$MFT是卷的核心,存放着卷中所有数据,包括:定位和恢复文件的数据结构、引导程序数据和记录整个卷的分配分配状态的位图等

  • 文件记录:NTFS不是将文件仅仅视为一个文本库或二进制数据,而是将文件作为许多属性和属性值的集合来处理;每个文件或文件夹在元文件\$MFT均有一个文件记录号

  • 常驻属性:文件属性值能直接存储在$MFT记录中

  • 非常驻属性:不能直接存储在\$MFT记录中,需要在\$MFT之外为其分配空间进行存储

NTFS数据存放方式

NTFS 文件系统以文件的形式来对数据进行管理,以簇为单位来存储数据的。在NTFS里边的分区的簇大小的规律:

  • 如果分区小于512M ,簇大小1扇区

  • 如果分区大于512M小于1G,簇大小为2个扇区

  • 如果分区大于1G小于2G,簇大小为4个扇区

  • 如果分区大于2GB,簇大小为8个扇区

NTFS常见元文件列表

分区引导扇区 DBR

$Boot元文件由分区的第一个扇区(即 DBR)和后面的 15 个扇区(即 NTLDR 区域)组成,其中 DBR 由“跳转指令”、“OEM代号”、“BPB”、“引导程序”和“结束标志”组成:

对于,DBR 部分的字段含义如下图所示。其中,我们需要重点关注每个扇区的字节总数、簇大小、\$MFT主文件记录表的开始簇号。

文件记录

在 NTFS 文件系统中,磁盘上的所有数据都是以文件的形式存储,其中包括元文件
每个文件都有一个或多个文件记录,每个文件记录占用两个扇区,即 1024 字节。而 \$MFT 元文件就是专门记录每个文件的文件记录。

由于 NTFS 文件系统是通过 \$MFT 来确定文件在磁盘上的位置以及文件的属性,所以\$MFT 是非常重要的,\$MFT 的起始位置在 DBR 中有描述。\$MFT 的文件记录在物理上是连续的,并且从 0 开始编号;\$MFT 的前 16 个文件记录总是元文件的,并且顺序是固定不变的。

文件记录由两部分构成,一部分是文件记录头,另一部分是属性列表,最后结尾是四个“FF”:

文件记录头解析

对于文件记录头中每个数据的含义如下,其中,需要重点关注的是偏移为 0x14,长度为 2 字节的第一个属性的偏移地址,根据这个字段可以获取文件记录中第一个属性的位置。

文件记录属性

属性有两种,分为常驻属性和非常驻属性。在属性中,偏移 0x8,长度为 1 字节的字段,就是区分了常驻属性和非常驻属性。值为 0x00 表示常驻属性,0x01 表示非常驻属性。

常驻属性头的每个字段含义如下所示。其中,要重点关注属性类型、属性长度、是否为常驻属性还是非常驻属性。

非常驻属性头的每个字段含义如下所示。其中,要重点关注属性类型、属性长度、是否为常驻属性还是非常驻属性、Data Run 的偏移地址以及 Data Run 的数据信息。

数据运行列表 Data Run List

我们可以由上面知道,当属性为非常驻属性的时候,属性中就会有一个字段来表示 Data Run。当属性不能存放完数据,系统就会在NTFS数据区域开辟一个空间存放,这个区域是以簇为单位的。Data Run List 就是记录这个数据区域的起始簇号和大小。它的含义分析如下:

Data Run的第一个字节分高4位和低4位。其中,高4位表示文件内容的起始簇号在Data Run List中占用的字节数。低4位表示文件内容簇数在Data Run List中占用的字节数。

Data Run的第二个字节开始表示文件内容的簇数,接着表示文件内容的起始簇号。

Data Run可以指示空间的大小以及偏移位置,例如上述中给的例子,起始簇号为:A2 59 00(10639616),数据大小为:C0 14(49172)。

对于多个Data Run的情况,第一个Data Run的起始簇号是一个正整数,而第二个Data Run开始,起始簇号偏移是分正负的。可以根据起始簇号偏移的最高位是否来判断,若为1,则是负整数(补码表示);否则,是正整数。而且,从第二个Data Run开始,起始簇号偏移都是相对于上一个Data Run的起始簇号来说的。下面举个例子,方便大家理解。

例如,有这么一个Data Run如下所示:

  1. 31 01 FD 0A 28 21 01 AB FA 21 01 4A F5 21 01 91 C1 00

我们可以看到上面一共有4个Data Run,分别如下:

第1个Data Run

  • 31 01 FD 0A 28
    • 正整数:第一个Data Run的起始簇号都是正整数
    • 起始簇号:28 0A FD(2624253)

第2个Data Run

  • 21 01 AB FA
    • 负整数:起始簇号偏移FA AB的最高位是1,所以是负整数(补码),所以FA AB(-1365)
    • 起始簇号:相对于上一个Data Run的偏移,所以为:2624253-1365=2622888

第3个Data Run

  • 21 01 4A F5
    • 负整数:起始簇号偏移F5 4A的最高位是1,所以是负整数(补码),所以F5 4A(-2742)
    • 起始簇号:相对于上一个Data Run的偏移,所以为:2622888-2742=2620146

第4个Data Run

  • 21 01 91 C1
    • 负整数:起始簇号偏移C1 91的最高位是1,所以是负整数(补码),所以C1 91(-15983)
    • 起始簇号:相对于上一个Data Run的偏移,所以为:2620146-15983=2604163

几个重要的属性

接下来,我们重点讲解下几个重要的属性:80H属性、90H属性以及 A0H属性。

80H属性

80H属性是文件数据属性,该属性容纳着文件的内容,文件的大小一般指的就是未命名数据流的大小。该属性没有最大最小限制,最小情况是该属性为常驻属性。当在数据在属性内没有办法展示完全的时候,就需要Data Run的帮助,那么这时属性就为常驻属性,文件数据就存储在 Data Run指向的簇当中。

90H属性

90H属性是索引根属性,该属性是实现NTFS的B+树索引的根节点,它总是常驻属性。该属性的结构如下图:

其中,索引根的字段含义如下所示:

索引头的字段含义如下所示:

索引项的字段含义如下所示:

A0属性

A0属性是索引分配属性,也是一个索引的基本结构,存储着组成索引的B+树目录索引子节点的定位信息。它总是常驻属性:

根据上图A0H属性的 Data Run List 可以找到索引区域,偏移到索引区域所在的簇:

其中,标准索引头的解释如下。要注意,下面的索引项偏移加上0x18。

索引项的解释如下:

基于 NTFS 文件定位思路及例子

NTFS定位文件大致过程如下:

  • 根据BDP,获取扇区大小、簇大小以及\$MFT起始扇区

  • 根据$MFT位置,计算根目录的文件记录,一般在 5 号文件记录

  • 查找80H、90H、A0H属性,注意常驻属性和非常驻属性

  • 获取 Data Run,从 Data Run 中定位到起始簇后,再分析索引项可以得到文件名等信息

  • 根据80H属性中的数据流就可以找到文件真正的数据

接下来,我来演示怎么使用 NTFS 文件系统定位出 H:\NtfsTest\520.exe 文件。

首先,我们使用 WinHex 软件,打开 H 盘的分区引导扇区 DBR,我们可以从中获取:每个扇区大小为 0x200 字节;每个簇大小为 0x08 个扇区;\$MFT 开始簇号为 0x0C0000。

所以,我们根据以上信息计算出 $MFT 开始的偏移地址为:

  1. 0x0C0000 * 0x08 * 0x200 = 0xC000 0000

然后,我们就开始计算根目录的文件记录,它是 5 号文件记录,而且每个文件记录大小为两个扇区 1024 字节。所以,根目录的偏移地址为:

  1. 0xC000 0000 + 0x5 * 0x2 * 0x200 = 0xC000 1400

接着,我们跳转到 0xC000 1400 地址处,从从文件记录中,查找 80H、90H、10H 属性,因为是要获取 NtfsTest 文件夹的位置,所以,我们定位到 A0H 属性:

我们可以从偏移 0x20 处获取 Data Run 的偏移地址 0x0048。然后,在偏移 0x0048 中获取 Data Run 数据:11 01 2C 00。从 Data Run 中,可以知道数据大小为 0x01 个簇,起始簇号为 0x2C。其中,0x2C 簇的偏移地址为 0x2C000。

我们跳转到 0x2C000 地址处,开始按照标准索引头、索引项的含义,从标准索引头中获取第一个索引项的偏移位置,注意要加上0x18;然后,再从索引项中获取文件名称的偏移位置,查看名称是否为 NtfsTest 文件夹,若不是,则继续获取下一索引项的偏移位置,继续获取名称匹配。若找到名称,则获取文件的 \$MTF 参考号。

按照上面的顺序,我们找到了 NtfsTest 所在的索引项:

所以,我们可以获取到文件的 \$MTF 参考号为:0x58E0。那么,偏移地址为:

  1. 0xC000 0000 + 0x58E0 * 2* 0x200 = 0xC163 8000

我们继续跳转到偏移位置 0xC163 8000,接下来要寻找 520.exe 文件名称.:我们根据文件记录找到第一个属性的偏移位置,然后再根据属性大小,获取下一个属性的偏移位置。以此查找 80H 属性、90H 属性、A0H 属性。

我们可以在 90H 属性中,从索引项中获取到 520.exe 的文件名称,然后可以得到 520.exe 文件的 \$MTF 参考号为:0x5A0B。那么偏移地址为:

  1. 0xC000 0000 + 0x5A0B * 2* 0x200 = 0xC168 2C00

然后,我们直接跳转到 0xC168 2C00 地址处,就是 520.exe 的文件记录了。我们直接找到 80H 文件数据属性,从偏移 0x20 获取 Data Run 的偏 移 0x40,然后在偏移 0x40 获取 Data Run 数据:32 42 2E C7 85 64 00。

根据 Data Run,我们知道数据大小为 0x2E42 个簇,数据起始簇号为 0x6485C7,即偏移地址为:

  1. 0x6485C7 * 0x8 * 0x200 = 0x6 485C 7000

这样,0x6 485C 7000 地址处就存储着 H:\NtfsTest\520.exe 文件的数据。

本文参考自《WINDOWS黑客编程技术详解》、内核篇、第十三章 文件管理技术、第三小节 文件管理之NTFS解析

上传的附件

keyboard_arrow_left上一篇 : 编程实现根据NTFS文件系统定位文件在磁盘上的偏移地址 编程实现对MBR数据读写 : 下一篇keyboard_arrow_right



Pullarla
2018-12-12 17:24:42
本文摘抄自《WINDOWS黑客编程技术详解》、内核篇、第十三章 文件管理技术、第三小节 文件管理之NTFS解析

发送私信

你在背后说我,因为我走在你前面

14
文章数
8
评论数
最近文章
eject