== FAT32 ==
FAT32文件系统有自己的格式,其中比较重要的概念包括:
=== MBR ===
MBR(master boot record),即主引导记录,有时也称主引导扇区。位于整个硬盘的0柱面0磁头1扇区(可以看作是硬盘的第一个扇区),bios在执行自己固有的程序以后就会jump到mbr中的第一条指令(
在我们的操作中BIOS负责LOAD内核,并且跳转到内核加载地址,并不涉及硬盘的MBR,MBR可能与GRUB有关)。将系统的控制权交由mbr来执行。在总共512byte的主引导记录中,MBR的引导程序占了其中的前446个字 节(偏移0H~偏移1BDH),随后的64个字节(偏移1BEH~偏移1FDH)为DPT(Disk PartitionTable,硬盘分区表),最后的两个字节“55 AA”(偏移1FEH~偏移1FFH)是分区有效结束标志。
在Linux下使用dd命令获得MBR
root@llc-loongson:~# fdisk -l
Disk /dev/sda: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xe467e467
Device Boot Start End Blocks Id System
/dev/sda1 * 1 3901 31334751 c W95 FAT32 (LBA)
/dev/sda2 3902 9125 41961780 7 HPFS/NTFS
/dev/sda3 9126 17001 63263970 7 HPFS/NTFS
/dev/sda4 17002 19458 19729409 5 Extended
/dev/sda5 17002 19215 17776640 83 Linux
/dev/sda6 19215 19458 1951744 82 Linux swap / Solaris
root@llc-loongson:~# dd if=/dev/sda of=./MBR count=1 bs=512
记录了1+0 的读入
记录了1+0 的写出
512字节(512 B)已复制,0.000296544 秒,1.7 MB/秒
然后使用vim查看MBR
root@llc-loongson:~# vim MBR
在vim中使用底行模式
:%!xxd查看二进制
由于前446字节为引导程序,从1BEH开始为DPT(分区表)
00001b0: cd10 ac3c 0075 f4c3 67e4 67e4 0000 8001 ...<.u..g.g.....
00001c0: 0100 0cfe ffff 3f00 0000 be42 bc03 0000 ......?....B....
00001d0: c1ff 07fe ffff fd42 bc03 6892 0005 0000 .......B..h.....
00001e0: c1ff 07fe ffff 65d5 bc08 c4a9 8a07 00fe ......e.........
00001f0: ffff 05fe ffff fe7f 4710 0218 5a02 55aa ........G...Z.U.
字节位移
字段长度
值
字段名和定义
0x01BE
BYTE
0x80
引导指示符(Boot Indicator) 指明该分区是否是活动分区。(0x80表示活动,0x00表示非活动)
0x01BF
BYTE
0x01
开始磁头(Starting Head)
0x01C0
6位
0x01
开始扇区(Starting Sector) 只用了0~5位。后面的两位(第6位和第7位)被开始柱面字段所使用
0x01C1
10位
0x00
开始柱面(Starting Cylinder) 除了开始扇区字段的最后两位外,还使用了1位来组成该柱面值。开始柱面是一个10位数,最大值为1023
0x01C2
BYTE
0x0c
系统ID(System ID) 定义了分区的类型,详细定义,请参阅图4
0x01C3
BYTE
0xFE
结束磁头(Ending Head)
0x01C4
6位
0xFF
结束扇区(Ending Sector) 只使用了0~5位。最后两位(第6、7位)被结束柱面字段所使用
0x01C5
10位
0x1FF
结束柱面(Ending Cylinder) 除了结束扇区字段最后的两位外,还使用了1位,以组成该柱面值。结束柱面是一个10位的数,最大值为1023
0x01C6
DWORD
0x0000003F 相对扇区数(Relative Sectors) 从该磁盘的开始到该分区的开始的位移量,以扇区来计算
0x01CA
DWORD
0x03BC42BE 总扇区数(Total Sectors) 该分区中的扇区总数
由于分区表只能表示4个分区,所以分区表中最后的分区是扩展分区的统一表示。
扩展分区
扩展分区中的每个逻辑驱动器都存在一个类似于MBR的扩展引导记录( Extended Boot Record, EBR),也有人称之为虚拟mbr或扩展mbr,意思是一样的。扩展引导记录包括一个扩展分区表和该扇区的标签。扩展引导记录将记录只包含扩展分区中每个逻辑驱动器的第一个柱面的第一面的信息。一个逻辑驱动器中的引导扇区一般位于相对扇区32或63。但是,如果磁盘上没有扩展分区,那么就不会有扩展引导记录和逻辑驱动器。第一个逻辑驱动器的扩展分区表中的第一项指向它自身的引导扇区。第二项指向下一个逻辑驱动器的EBR。如果不存在进一步的逻辑驱动器,第二项就不会使用,而且被记录成一系列零。如果有附加的逻辑驱动器,那么第二个逻辑驱动器的扩展分区表的第一项会指向它本身的引导扇区。第二个逻辑驱动器的 扩展分区表的第二项指向下一个逻辑驱动器的EBR。扩展分区表的第三项和第四项永远都不会被使用。
=== DBR ===
每一个分区的起始扇区为DBR区,在这512个字节中,其实又是由跳转指令,厂商标志和操作系统版本号,BPB(BIOS Parameter Block),扩展BPB,os引导程序,结束标志几部分组成。跳转指令是为了引导系统,引导过程中MBR会将CPU引导过来,这里不关注。从偏移0x0B开始的是一段描述能够使可执行引导代码找到相关参数的信息。通常称之为BPB(BIOS Parameter Block),BPB一般开始于相同的位移量,因此,标准的参数都处于一个已知的位置。磁盘容量和几何结构变量都被封在BPB之中。
使用dd命令得到分区的DBR
root@llc-loongson:~# dd if=/dev/sda1 of=./DBR bs=512 count=1
查看二进制得到BPB
0000000: eb58 904d 5344 4f53 352e 3000 0220 2600 .X.MSDOS5.0.. &.
0000010: 0200 0000 00f8 0000 3f00 ff00 3f00 0000 ........?...?...
0000020: a042 bc03 bd3b 0000 0000 0000 0200 0000 .B...;..........
0000030: 0100 0600 0000 0000 0000 0000 0000 0000 ................
0000040: 8000 29f3 576c 744e 4f20 4e41 4d45 2020 ..).WltNO NAME
位移
字段长度(字节)
对应取值
名称和定义
0x0B
2
0x0200
扇区字节数(Bytes Per Sector) 硬件扇区的大小。
0x0D
1
0x20
每簇扇区数(Sectors Per Cluster),一簇中的扇区数。
0x0e
2
0x0026
保留扇区数(Reserved Sector) 第一个FAT开始之前的扇区数,包括引导扇区。
0x10
1
0x02
FAT数(Number of FAT) 该分区上FAT的副本数。本字段的值一般为2
0x11
2
0x0000
根目录项数(Root Entries)只有FAT12/FAT16使用此字段。对FAT32分区而言,本字段必须设置为 0
0x13
2
0x0000
小扇区数(Small Sector)(只有FAT12/FAT16使用此字段)对FAT32分区而言,本字段必须设置为0
0x15
1
0xF8
媒体描述符( Media Descriptor)提供有关媒体被使用的信息。值0xF8表示硬盘,0xF0表示高密度的3.5寸软盘。
0x16
2
0x0000
每FAT扇区数(Sectors Per FAT)只被FAT12/FAT16所使用,对FAT32分区而言,本字段必须设置为0
0x18
2
0x003F
每道扇区数(Sectors Per Track)
0x1A
2
0x00FF
磁头数(Number of Head)
0x1C
4
0x003F
隐藏扇区数(Hidden Sector) 该分区上引导扇区之前的扇区数。在引导序列计算到根目录的数据区的绝对位移的过程中使用了该值。
0x20
4
0x03bc42a0
总扇区数(Large Sector) 本字段包含FAT32分区中总的扇区数
0x24
4
0x00003bbd
每FAT扇区数(Sectors Per FAT)(只被FAT32使用)该分区每个FAT所占的扇区数。
0x28
2
0x00
扩展标志(Extended Flag)
0x2A
2
0x0000
文件系统版本(File ystem Version)只供FAT32使用,高字节是主要的修订号,而低字节是次要的修订号。
0x2C
4
0x00000002
根目录簇号(Root Cluster Number)(只供FAT32使用) 根目录第一簇的簇号。本字段的值一般为2,但不总是如此
0x30
2
0x0001
文件系统信息扇区号(File System Information SectorNumber)(只供FAT32使用)
0x32
2
0x0006
备份引导扇区(只供FAT32使用)
0x34
12
12个字节均为0x00
保留(只供FAT32使用)供以后扩充使用的保留空间。本字段的值总为0
=== 寻找原理 ===
硬盘分区结构
引导扇区 |
其余保留扇区 |
FAT1 |
FAT2(重复的) |
根文件夹首簇 |
其他文件夹及所有文件 |
剩余扇区 |
1扇区 |
|
实际情况取大小 |
同FAT1 |
第2簇 |
|
不足一簇 |
保留扇区 |
|
|
┗━━━━━━━━数据区━━━━━━━━┛
|
先介绍簇的概念:
簇可以表示成扇区的集合,以簇为单位而不以扇区为单位进行磁盘的分配,是因为当分区容量较大时,采用大小为512B的扇区管理会增加fat表的项数,对大文件存取增加消耗,文件系统效率不高。分区的大小和簇的取值是有关系的。我们不关心。
FAT为文件链表,以簇为单位。FAT32文件系统都是从根目录进行寻找。
下面用一个实际的例子进行演练:
根据DBR信息,找出第一个FAT前的扇区数与FAT所占的分区数。根据上面的信息我就可使用:
dd if=/dev/sda1 of=./ROOT skip=38 count=15293 bs=512
得到FAT表,FAT表表示文件之间的链接关系,特别是一个大文件不能在一个簇里面存下,用FAT表可以将一个文件链起来
0000000: f8ff ff0f ffff ffff ffff ff0f ffff ff0f ................
0000010: 1000 0000 ffff ff0f 3d0f 0400 ffff ff0f ........=.......
0000020: ffff ff0f 410f 0400 ffff ff0f ffff ff0f ....A...........
0000030: 440f 0400 ffff ff0f 6611 0400 ffff ff0f D.......f.......
0000040: fb01 0000 0000 0000 ffff ff0f 1800 0000 ................
0000050: ffff ff0f ffff ff0f e6e9 0000 ffff ff0f ................
0000060: d700 0000 1a00 0000 1b00 0000 1c00 0000 ................
0000070: 1d00 0000 1e00 0000 1f00 0000 2000 0000 ............ ...
0000080: ffff ff0f 2200 0000 2300 0000 2400 0000 ...."...#...$...
0000090: 2500 0000 2600 0000 2700 0000 2800 0000 %...&...'...(...
00000a0: ffff ff0f 2a00 0000 2b00 0000 2c00 0000 ....*...+...,...
00000b0: 2d00 0000 2e00 0000 2f00 0000 3000 0000 -......./...0...
00000c0: ffff ff0f ffff ff0f ffff ff0f ffff ff0f ................
00000d0: ffff ff0f ffff ff0f ffff ff0f ffff ff0f ................
00000e0: ffff ff0f ffff ff0f ffff ff0f ffff ff0f ................
00000f0: ffff ff0f ffff ff0f 5ae4 0000 5900 0000 ........Z...Y...
0000100: ffff ff0f 4c00 0000 ffff ff0f ffff ff0f ....L...........
0000110: ffff ff0f ffff ff0f ffff ff0f ffff ff0f ................
前8字节为介质描述不关注,偏移0x8--0xb为0fffffff表示本文件只占用了一簇。0x85--0x88为00000022表示本文件的下一个簇在22号簇我们再去10号簇即偏移0x88--0x8b(计算簇号的时候使用16进制)依次类推22->23->24...->28->29结束。
有了文件链接表,我们还需要根文件夹。
使用:
dd if=/dev/sda1 of=./ROOT skip=30624 count=32 bs=512
得到根文件目录。
介绍短文件名与长文件名:
字节偏移
字节数
定义
0x0~0x7
8
文件名
0x8~0xA
3
扩展名
0xB*
1
属性字节
00000000(读写)
00000001(只读)
00000010(隐藏)
00000100(系统)
00001000(卷标)
00010000(子目录)
00100000(归档)
0xC
1
系统保留
0xD
1
创建时间的10毫秒位
0xE~0xF
2
文件创建时间
0x10~0x11
2
文件创建日期
0x12~0x13
2
文件最后访问日期
0x14~0x15
2
文件起始簇号的高16位
0x16~0x17
2
文件的最近修改时间
0x18~0x19
2
文件的最近修改日期
0x1A~0x1B
2
文件起始簇号的低16位
0x1C~0x1F
4
表示文件的长度
我们截取两端典型
53 0000340: 4167 007a 0072 006f 006d 000f 00aa 2e00 Ag.z.r.o.m......
54 0000350: 6200 6900 6e00 0000 ffff 0000 ffff ffff b.i.n...........
55 0000360: 475a 524f 4d20 2020 4249 4e20 0000 5960 GZROM BIN ..Y`
56 0000370: 1241 1241 0000 5960 1241 46e7 77e2 1e00 .A.A..Y`.AF.w...
可以看出它的起始簇号为0000 e746然后我们就去FAT表寻找,注意FAT表里面字节顺序。我们可以计算出位置,或者直接搜索47e7 0000(存放下一个簇号),通过一簇中的扇区数我们就能找到数据了。
开始簇号(0xe746 - 2(根目录从第二簇开始))*0x20(每簇扇区数) + FAT扇区*2 + 保留扇区
在sda1里面我们有一个gzrom.bin的文件,从名字长度上看应该属于一个短文件名,但是读出的是长文件名,下面的
457 0001c80: 4455 4f4d 4920 2020 2020 2012 0835 e491 DUOMI ..5..
458 0001c90: b240 b240 0800 e591 b240 175b 0000 0000 .@.@.....@.[....
duomi文件夹是短文件,其中的区别在于...怀疑是不同的程序或者系统在对文件名的操作不同。
长文件名的处理上会截断13个字符
11 00000a0: 4220 0053 0065 0074 0074 000f 004a 6900 B .S.e.t.t...Ji.
12 00000b0: 6e00 6700 7300 0000 ffff 0000 ffff ffff n.g.s...........
13 00000c0: 0144 006f 0063 0075 006d 000f 004a 6500 .D.o.c.u.m...Je.
14 00000d0: 6e00 7400 7300 2000 6100 0000 6e00 6400 n.t.s. .a...n.d.
15 00000e0: 444f 4355 4d45 7e31 2020 2010 004c a97a DOCUME~1 ..L.z
16 00000f0: 233d ec40 0000 aa7a 233d 09cc 0000 0000 #
[email protected]#=......
Documents and Settings,从and处截断,紧随长文件名的是其对应的短文件名,其中包括起始簇号。
通过读取根目录我们知道了文件的起始簇号,就可以在FAT表中找到其数据区的链表。我们就不查看了,至于子目录,子目录里面存放的是其下目录项
1 0000000: 2e20 2020 2020 2020 2020 2010 0035 e491 . ..5..
2 0000010: b240 b240 0800 e591 b240 175b 0000 0000 .@.@.....@.[....
3 0000020: 2e2e 2020 2020 2020 2020 2010 0035 e491 .. ..5..
4 0000030: b240 b240 0000 e591 b240 0000 0000 0000 .@.@.....@......
5 0000040: 4341 4348 4520 2020 4441 5422 1838 e491 CACHE DAT".8..
6 0000050: b240 0441 0800 4c6c 0441 905c 0060 5209
[email protected].\.`R.
7 0000060: 5245 4144 4d45 2020 5458 5420 1838 e491 README TXT .8..
8 0000070: b240 b240 0800 e591 b240 185b ba00 0000 .@.@.....@.[....
duomi的数据区。