前言
今天的软件安全课程介绍了部分的磁盘相关的知识,但是课件上的内容属实有些难以理解,而且略有些落后于时代,这里收集总结了部分与磁盘相关的知识。
内容大概包括:
- 磁盘分区类型
- MBR
- GPT
- 文件系统
- FAT32
- NTFS
参考文献:
- https://en.wikipedia.org/wiki/GUID_Partition_Table
- https://en.wikipedia.org/wiki/Master_boot_record
- https://juejin.im/post/5b7ec7516fb9a019e6434224#heading-6。
- https://ntfs.com
- https://www.cnblogs.com/mwwf-blogs/archive/2015/05/04/4467687.html NTFS 文件系统解析
磁盘分区类型
刚开始学习的时候可能会搞不清楚磁盘分区类型,文件系统之间的关系。
拿到一个磁盘,其存储的物理内容无非是一个超级长的二进制排列,磁盘分区的类型决定了整个磁盘的内容具有怎样的格式(例如以什么二进制串开头,某些偏移处的某些信息如何理解),以及如何表达磁盘的分区。而每个分区可以拥有自己的文件系统。文件系统解释了文件以及目录以何种格式组织、何种格式表达,解决的关键问题包括文件目录项的格式(即如何表示一个文件存在于文件系统,以及如何存储相关信息,如文件名,创建日期,访问控制等),以及如何表示文件内容在磁盘上的位置。
磁盘分区类型中最常用的2种为 MBR 和 GPT。目前较新的磁盘大多均采用 GPT , 而 MBR 趋于淘汰。
MBR ( Master Boot Record)
MBR 即 主引导记录,是一个多义词。在这里我们把它当作一种磁盘分区类型来介绍,但是除此之外,它本身也可表达磁盘的第一个扇区(512字节)
绝大多数情况下,一个扇区为512字节。由于当扇区为512字节时,MBR允许的最大磁盘大小为 2 TB ,于是部分磁盘制造商曾经选择增大扇区容量以提高磁盘容量,这导致了1KB 等多种大小的扇区的磁盘出现。但是绝大多数情况下,我们默认一个扇区为512字节。),即 CHS 表达为(0, 0, 1)。而继续除此之外,我们也会将 MBR 这个扇区开头的 446 字节叫做 MBR,这就涉及到了 MBR 分区类型的结构。
首先我们看第一个扇区的内部结构。
地址 | 描述 | 长度 |
---|---|---|
0000 |
代码区 | 440 (最大446) |
01B8 |
选用磁盘标志 | 4 |
01BC |
一般为空值; 0x0000 | 2 |
01BE |
标准MBR分区表规划 (四个16 byte的主分区表入口) |
64 |
01FE |
55 h , MBR有效标志:0x55AA | 1 |
01FF |
AA h, MBR有效标志:0x55AA | 1 |
上面的图是我在一个 Win7 的虚拟机中,使用 Winhex 的截图。可以看到错误信息的字符串也在里面。这一部分是引导代码。仔细观察 01B8 地址的数据是 9E 18 94 3D , 其后跟着 2 个字节的 0 ,表示即将开始的分区表。
MBR扇区中第二个重点就是分区表。
偏移 | 长度 (字节) | 意义 |
---|---|---|
00H | 1 | 分区状态:00–>非活动分区;80–>活动分区; 其它数值没有意义 |
01H | 1 | 分区起始磁头号(HEAD),用到全部8位 |
02H | 2 | 分区起始扇区号(SECTOR),占据02H的位0-5; 该分区的起始磁柱号(CYLINDER),占据 02H的位6-7和03H的全部8位 |
04H | 1 | 文件系统标志位 |
05H | 1 | 分区结束磁头号(HEAD),用到全部8位 |
06H | 2 | 分区结束扇区号(SECTOR),占据06H的位0-5; 该分区的结束磁柱号(CYLINDER),占据 06H的位6-7和07H的全部8位 |
08H | 4 | 分区起始相对扇区号 |
0CH | 4 | 分区总的扇区数 |
分区表中存储了分区的部分属性,以及开始位置及长度等。
对于大于8.4G的现代硬盘,CHS已经无法表示, BIOS使用LBA模式,对于超出的部分,CHS值通常设为0xFEFFFF,并加以忽略,直接使用Offset 0x08-0x0c的4字节相对值,再进行内部转换。
分区表之后就是各个分区了,由于MBR只留了4个分区项的地方,当需要的分区超过4个时,需要将一个原来的4个分区项之一设置为扩展分区。扩展分区会指示自己的分区起始位置及长度,以及下一个扩展分区的位置。即一个链式结构,这样的问题也显而易见,如果其中一个分区出了问题,后面所有的分区都无法被正确的读取。
GPT (GUID Partition Table)
GPT 即 全局唯一标识分区表。GPT 的名字起源于 GUID , 即 Globally Unique Identifier,全局唯一标识符。有时候也被叫做 UUID。通常为一个 128 位的类随机数。GPT 是用于取代 MBR 的分区方式。
GPT的格式如下。开头第一个扇区考虑到兼容性与 MBR 保持一致。图中的 LBA 是 Logical Block Address,即 逻辑块地址的意思。简单理解就是原来 CHS 的磁盘地址索引方式不好用,把 CHS 展开成一维线性用了。每个 LBA 代表的依然是一个扇区或者说叫一个块。
第二个扇区存储分区表头的信息。其格式如下表
起始字节 | 长度 | 内容 |
---|---|---|
0 | 8字节 | 签名(”EFI PART”, 45 46 49 20 50 41 52 54) |
8 | 4字节 | 修订(在1.0版中,值是00 00 01 00) |
12 | 4字节 | 分区表头的大小(单位是字节,通常是92字节,即5C 00 00 00) |
16 | 4字节 | 分区表头(第0-91字节)的CRC32校验,在计算时,把这个字段作为0处理,需要计算出分区序列的CRC32校验后再计算本字段 |
20 | 4字节 | 保留,必须是0 |
24 | 8字节 | 当前LBA(这个分区表头的位置) |
32 | 8字节 | 备份LBA(另一个分区表头的位置) |
40 | 8字节 | 第一个可用于分区的LBA(主分区表的最后一个LBA + 1) |
48 | 8字节 | 最后一个可用于分区的LBA(备份分区表的第一个LBA − 1) |
56 | 16字节 | 硬盘GUID(在类UNIX系统中也叫UUID) |
72 | 8字节 | 分区表项的起始LBA(在主分区表中是2) |
80 | 4字节 | 分区表项的数量 |
84 | 4字节 | 一个分区表项的大小(通常是128) |
88 | 4字节 | 分区序列的CRC32校验 |
92 | * | 保留,剩余的字节必须是0(对于512字节LBA的硬盘即是420个字节) |
从第三个扇区开始,接下来的 32 个扇区用于存储具体的分区表项的内容,每个扇区可以存储 4 个分区表项。故总共有 128 个分区表项,每个 128 字节。分区表项格式如下表。其中可以看到 起始地址 和 末尾地址 都升级为了 8 个字节, 也就是支持 2^64 个扇区。使得支持的磁盘大小大大增长。
起始字节 | 长度 | 内容 |
---|---|---|
0 | 16字节 | 分区类型GUID |
16 | 16字节 | 分区GUID |
32 | 8字节 | 起始LBA(小端序) |
40 | 8字节 | 末尾LBA |
48 | 8字节 | 属性标签(如:60 表示“只读”) |
56 | 72字节 | 分区名(可以包括36个UTF-16(小端序)字符) |
文件系统
按照前面所述,根据磁盘的分区类型,每个磁盘会被分为多个分区。而每个分区都可以使用不同的文件系统来具体表示其内部的目录与文件。
NTFS (New Technology File System)
NTFS 大概是目前最广泛使用的文件系统之一了,几乎新款的 Windows PC 机中的分区均使用 NTFS。相比之下 Linux 中使用较多的可能为 ext2, ext3 等。NTFS 的出现取代了 FAT32 , 这些文件系统以后如果有空可以追加一下。
说回 NTFS, 那么 NTFS 的内部又是如何组织表达的呢?
按照上图,从左至右依次介绍。
Partition Boot Sector
分区引导扇区是分区的第一个扇区。其内部结构如下表。
Byte Offset | Field Length | Field Name |
---|---|---|
0x00 | 3 bytes | Jump Instruction |
0x03 | LONGLONG | OEM ID |
0x0B | 25 bytes | BPB(Boot Parameter Block) |
0x24 | 48 bytes | Extended BPB |
0x54 | 426 bytes | Bootstrap Code |
0x01FE | WORD | 扇区结束标志 |
下面是 BPB 及 扩展 BPB 的内容格式表。
Byte Offset | Field Length | Sample Value | Field Name |
---|---|---|---|
0x0B | WORD | 0x0002 | Bytes Per Sector |
0x0D | BYTE | 0x08 | Sectors Per Cluster |
0x0E | WORD | 0x0000 | Reserved Sectors |
0x10 | 3 BYTES | 0x000000 | always 0 |
0x13 | WORD | 0x0000 | not used by NTFS |
0x15 | BYTE | 0xF8 | Media Descriptor |
0x16 | WORD | 0x0000 | always 0 |
0x18 | WORD | 0x3F00 | Sectors Per Track |
0x1A | WORD | 0xFF00 | Number Of Heads |
0x1C | DWORD | 0x3F000000 | Hidden Sectors |
0x20 | DWORD | 0x00000000 | not used by NTFS |
0x24 | DWORD | 0x80008000 | not used by NTFS |
0x28 | LONGLONG | 0x4AF57F0000000000 | Total Sectors |
0x30 | LONGLONG | 0x0400000000000000 | Logical Cluster Number for the file $MFT |
0x38 | LONGLONG | 0x54FF070000000000 | Logical Cluster Number for the file $MFTMirr |
0x40 | DWORD | 0xF6000000 | Clusters Per File Record Segment |
0x44 | BYTE | 0x01 | Clusters Per Index Buffer |
0x45 | 3 BYTES | 0x000000 | not used by NTFS |
0x48 | LONGLONG | 0x14A51B74C91B741C | Volume Serial Number |
0x50 | DWORD | 0x00000000 | Checksum |
Master File Table
MFT 是 NTFS 中存储文件信息的重要结构。
MFT 的内部结构如下图所示。
最开始的16项都是保存系统关键信息所用。从第24项开始记录的就是普通文件或目录的描述信息。
关于 MFT 内部的每一项(一个文件记录)都由两部分组成。分别是 表头 和 属性列表。
施工中……