10: GPTs; the FAT filesystem
Announcement
Hadi was out of town briefly earlier this week. He's catching up now on the regrade requests. Please be patient, I promise we'll get to things eventually.
We're hoping to have the midterm graded by next class.
GPTs
Modern PCs and Macs use the GUID Partition Table (GPT) standard on fixed hard disks. The GPT is a more sophisticated system that parallels the MBR in many ways but fixes many of its problems.
A GPT-formatted disk is laid out as follows:
(Image copyright © 2007 Wikimedia Commons and used under Attribution-ShareAlike 2.5 Generic (CC BY-SA 2.5).)
Note that the GPT is duplicated at the start and end of disk, and supposed to be kept in sync. This is a backup to mitigate data corruption.
Also note that there's a "protective MBR". What's that about? If you put a GPT-formatted disk into a MBR-only computer, it contains dummy values (a single maximum size partition of type 0xEE) so that the disk shows up as formatted. Hey, what were those bytes on my Mac's "MBR"? Remember, the first partition starts at 0x1BE:
hexdump -Cv -n 512 disk-image.dd
00000000 33 c0 8e d0 bc 00 7c 8e c0 8e d8 be 00 7c bf 00 |3.....|......|..|
00000010 06 b9 00 02 fc f3 a4 50 68 1c 06 cb fb b9 04 00 |.......Ph.......|
00000020 bd be 07 80 7e 00 00 7c 0b 0f 85 0e 01 83 c5 10 |....~..|........|
00000030 e2 f1 cd 18 88 56 00 55 c6 46 11 05 c6 46 10 00 |.....V.U.F...F..|
00000040 b4 41 bb aa 55 cd 13 5d 72 0f 81 fb 55 aa 75 09 |.A..U..]r...U.u.|
00000050 f7 c1 01 00 74 03 fe 46 10 66 60 80 7e 10 00 74 |....t..F.f`.~..t|
00000060 26 66 68 00 00 00 00 66 ff 76 08 68 00 00 68 00 |&fh....f.v.h..h.|
00000070 7c 68 01 00 68 10 00 b4 42 8a 56 00 8b f4 cd 13 ||h..h...B.V.....|
00000080 9f 83 c4 10 9e eb 14 b8 01 02 bb 00 7c 8a 56 00 |............|.V.|
00000090 8a 76 01 8a 4e 02 8a 6e 03 cd 13 66 61 73 1c fe |.v..N..n...fas..|
000000a0 4e 11 75 0c 80 7e 00 80 0f 84 8a 00 b2 80 eb 84 |N.u..~..........|
000000b0 55 32 e4 8a 56 00 cd 13 5d eb 9e 81 3e fe 7d 55 |U2..V...]...>.}U|
000000c0 aa 75 6e ff 76 00 e8 8d 00 75 17 fa b0 d1 e6 64 |.un.v....u.....d|
000000d0 e8 83 00 b0 df e6 60 e8 7c 00 b0 ff e6 64 e8 75 |......`.|....d.u|
000000e0 00 fb b8 00 bb cd 1a 66 23 c0 75 3b 66 81 fb 54 |.......f#.u;f..T|
000000f0 43 50 41 75 32 81 f9 02 01 72 2c 66 68 07 bb 00 |CPAu2....r,fh...|
00000100 00 66 68 00 02 00 00 66 68 08 00 00 00 66 53 66 |.fh....fh....fSf|
00000110 53 66 55 66 68 00 00 00 00 66 68 00 7c 00 00 66 |SfUfh....fh.|..f|
00000120 61 68 00 00 07 cd 1a 5a 32 f6 ea 00 7c 00 00 cd |ah.....Z2...|...|
00000130 18 a0 b7 07 eb 08 a0 b6 07 eb 03 a0 b5 07 32 e4 |..............2.|
00000140 05 00 07 8b f0 ac 3c 00 74 09 bb 07 00 b4 0e cd |......<.t.......|
00000150 10 eb f2 f4 eb fd 2b c9 e4 64 eb 00 24 02 e0 f8 |......+..d..$...|
00000160 24 02 c3 49 6e 76 61 6c 69 64 20 70 61 72 74 69 |$..Invalid parti|
00000170 74 69 6f 6e 20 74 61 62 6c 65 00 45 72 72 6f 72 |tion table.Error|
00000180 20 6c 6f 61 64 69 6e 67 20 6f 70 65 72 61 74 69 | loading operati|
00000190 6e 67 20 73 79 73 74 65 6d 00 4d 69 73 73 69 6e |ng system.Missin|
000001a0 67 20 6f 70 65 72 61 74 69 6e 67 20 73 79 73 74 |g operating syst|
000001b0 65 6d 00 00 00 63 7b 9a 7d 6e 00 00 00 00 00 fe |em...c{.}n......|
000001c0 ff ff ee fe ff ff 01 00 00 00 a3 70 3d 3a 00 00 |...........p=:..|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00 fe ff ff *ee* fe ff ff 01 00 00 00 a3 70 3d 3a
ee
! Well, there you go then.
Where's the actual GPT data? It starts in a header in the next sector.
https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_table_header_.28LBA_1.29
dd if=disk-image.dd bs=512 count=1 skip=1 | hexdump -Cv
1+0 records in
1+0 records out
512 bytes transferred in 0.000016 secs (31580642 bytes/sec)
00000000 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
00000010 7f 95 63 62 00 00 00 00 01 00 00 00 00 00 00 00 |..cb............|
00000020 a3 70 3d 3a 00 00 00 00 22 00 00 00 00 00 00 00 |.p=:....".......|
00000030 82 70 3d 3a 00 00 00 00 a8 4d 00 00 93 38 00 00 |.p=:.....M...8..|
00000040 3d 11 00 00 f3 62 00 00 02 00 00 00 00 00 00 00 |=....b..........|
00000050 80 00 00 00 80 00 00 00 81 d5 7a 4e 00 00 00 00 |..........zN....|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000200
Note, for example, we have the right header (EFI PART
), and that the partition entries (partition table) offset is located at byte 0x48 and is equal to 2 (that is, it's at the next sector on the disk). There's also a 4-byte value for the number of entries and the size of each entry at 0x50 and 0x54 (very much like the IFD). In this image, there are 128 entries (little endian: 08 00 00 00
) each 128 bytes long (which is typical).
Let's pull out the next sector to see the first few entries:
dd if=disk-image.dd bs=512 count=1 skip=2 | hexdump -Cv
1+0 records in
1+0 records out
512 bytes transferred in 0.000478 secs (1071599 bytes/sec)
00000000 28 73 2a c1 1f f8 d2 11 ba 4b 00 a0 c9 3e c9 3b |(s*......K...>.;|
00000010 e3 22 00 00 4b 2b 00 00 1e 43 00 00 72 0b 00 00 |."..K+...C..r...|
00000020 28 00 00 00 00 00 00 00 27 40 06 00 00 00 00 00 |(.......'@......|
00000030 00 00 00 00 00 00 00 00 45 00 46 00 49 00 20 00 |........E.F.I. .|
00000040 73 00 79 00 73 00 74 00 65 00 6d 00 20 00 70 00 |s.y.s.t.e.m. .p.|
00000050 61 00 72 00 74 00 69 00 74 00 69 00 6f 00 6e 00 |a.r.t.i.t.i.o.n.|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 72 6f 74 53 67 61 aa 11 aa 11 00 30 65 43 ec ac |rotSga.....0eC..|
00000090 41 5a 00 00 e1 30 00 00 8a 74 00 00 df 60 00 00 |AZ...0...t...`..|
000000a0 28 40 06 00 00 00 00 00 7f 9a e1 22 00 00 00 00 |(@........."....|
000000b0 00 00 00 00 00 00 00 00 49 00 72 00 6f 00 6e 00 |........I.r.o.n.|
000000c0 00 00 6d 00 65 00 72 00 00 00 00 00 00 00 00 00 |..m.e.r.........|
000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 74 6f 6f 42 00 00 aa 11 aa 11 00 30 65 43 ec ac |tooB.......0eC..|
00000110 40 0b 46 a0 6e 7e 24 42 91 02 75 57 32 ab c9 dd |@.F.n~$B..uW2...|
00000120 80 9a e1 22 00 00 00 00 9f f9 f4 22 00 00 00 00 |..."......."....|
00000130 00 00 00 00 00 00 02 00 52 00 65 00 63 00 6f 00 |........R.e.c.o.|
00000140 76 00 65 00 72 00 79 00 20 00 48 00 44 00 00 00 |v.e.r.y. .H.D...|
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000180 00 53 46 48 00 00 aa 11 aa 11 00 30 65 43 ec ac |.SFH.......0eC..|
00000190 c0 34 9b 30 09 0b fb 41 95 02 8b 95 10 1f 4e 41 |.4.0...A......NA|
000001a0 00 00 f5 22 00 00 00 00 7f 70 39 3a 00 00 00 00 |...".....p9:....|
000001b0 00 00 00 00 00 00 00 00 41 00 70 00 70 00 6c 00 |........A.p.p.l.|
000001c0 65 00 5f 00 48 00 46 00 53 00 5f 00 55 00 6e 00 |e._.H.F.S._.U.n.|
000001d0 74 00 69 00 74 00 6c 00 65 00 64 00 5f 00 32 00 |t.i.t.l.e.d._.2.|
000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000200
Entries look like: https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries
Let's look at the first few:
00000000 28 73 2a c1 1f f8 d2 11 ba 4b 00 a0 c9 3e c9 3b |(s*......K...>.;|
00000010 e3 22 00 00 4b 2b 00 00 1e 43 00 00 72 0b 00 00 |."..K+...C..r...|
00000020 28 00 00 00 00 00 00 00 27 40 06 00 00 00 00 00 |(.......'@......|
00000030 00 00 00 00 00 00 00 00 45 00 46 00 49 00 20 00 |........E.F.I. .|
00000040 73 00 79 00 73 00 74 00 65 00 6d 00 20 00 70 00 |s.y.s.t.e.m. .p.|
00000050 61 00 72 00 74 00 69 00 74 00 69 00 6f 00 6e 00 |a.r.t.i.t.i.o.n.|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Each entry starts with a 16-byte partition type GUID. This one's is: 28 73 2a c1 1f f8 d2 11 ba 4b 00 a0 c9 3e c9 3b
. Hmm, it doesn't seem to be in the list at https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs. What might it be? Turns out it's: an EFI System Partition (spoiler: the name is stored as UTF-16LE text!). https://en.wikipedia.org/wiki/EFI_system_partition. Bootable drives in UEFI systems put the bootloader and associated utilities on this partition, which is FAT-lie (though actually standardized as part of UEFI, so not exactly FAT). Different OSes put different stuff here; it's a standardized, extensible way to get more than the 446 bytes the MBR provided for a full-featured boot loader (and whatever else your OS provider wants to give you).
At 0x10, the next 16 bytes are a unique-to-this-partition-on-this-computer GUID.
At 0x20, there are 8 bytes (LE) telling you the first LBA of this partition, then 8 bytes telling you the last (inclusive).
struct.unpack('<QQ', bytes.fromhex('28 00 00 00 00 00 00 00 27 40 06 00 00 00 00 00'))
# => (40, 409639)
Again, does that match what mmls
told us?
mmls /dev/rdisk0
GUID Partition Table (EFI)
Offset Sector: 0
Units are in 512-byte sectors
Slot Start End Length Description
000: Meta 0000000000 0000000000 0000000001 Safety Table
001: ------- 0000000000 0000000039 0000000040 Unallocated
002: Meta 0000000001 0000000001 0000000001 GPT Header
003: Meta 0000000002 0000000033 0000000032 Partition Table
004: 000 0000000040 0000409639 0000409600 EFI system partition
005: 001 0000409640 0585210495 0584800856 Iron
006: 002 0585210496 0586480031 0001269536 Recovery HD
007: ------- 0586480032 0586481663 0000001632 Unallocated
008: 003 0586481664 0976842879 0390361216 Apple_HFS_Untitled_2
009: ------- 0976842880 0977105059 0000262180 Unallocated
Yup, exactly right. Then 8 bytes of "attribute flags," with only the first three bits being universally defined so far, and the last 16 defined by each partition type. Finally at 0x38 the partition name, in 72 bytes of UTF-16LE encoded text.
The next one looks like:
00000080 72 6f 74 53 67 61 aa 11 aa 11 00 30 65 43 ec ac |rotSga.....0eC..|
00000090 41 5a 00 00 e1 30 00 00 8a 74 00 00 df 60 00 00 |AZ...0...t...`..|
000000a0 28 40 06 00 00 00 00 00 7f 9a e1 22 00 00 00 00 |(@........."....|
000000b0 00 00 00 00 00 00 00 00 49 00 72 00 6f 00 6e 00 |........I.r.o.n.|
000000c0 00 00 6d 00 65 00 72 00 00 00 00 00 00 00 00 00 |..m.e.r.........|
000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
This is an Apple partition, and you can see it's named "Iron", which is my Mac's primary partition's name.
If we kept going, you'd see that unused entries are zeroed out (that is, they consist entirely of bytes set to the value 00
).
So you get the idea here, anyway. GPTs are a fairly straightforward binary data structure to store hard disk partition information. They're slightly more complex than MBRs, but they don't require the contortions of MBRs (which is a legacy format originally designed for computers and disks over 30 years ago!).
So that's it for lecture content on volumes and partitions, though you will probably want to Read the Book, supplemented with more recent web resources, for the fine details of MBRs and GPTs.
Filesystems
Filesystems are provided by operating systems to programs (and ultimately, to users). They provide a mechanism to store data in a structured way, usually organized around "files" and "directories".
The filesystem doesn't worry about the internal structure of files (like the JPEGs we've dealt with); it treats them as blobs of bytes to be stored and retrieved when requested.
The filesystem instead manages the files that are stored and the space in which they are stored. Minimally, a file system must be able to store, retrieve, and remove data from a partition corresponding to a particular file. To do so, it must keep track of:
- free and allocated space within the partition that it is responsible for;
- the location of each file within the partition
- the user-visible name of each file (the filename)
- the user-visible location of each file (the path to the file)
Carrier refers to these items as essential and therefore "more trustworthy" in some sense than nonessential items. The reasoning here is that the above must be correct, or the filesystem isn't fulfilling its basic purpose.
Filesystems might also track many other items of metadata including:
- creation, modification, or last-accessed time
- ownership information
- permissions (readable, writeable, executable, by who?)
Carrier provides a broad overview of the analysis techniques you might use at an abstract level in Chapter 8; we're going to jump right into the details of the FAT filesystem and see them as we go along.
FAT
The File Allocation Table (FAT) filesystem is simple (maybe too simple, in some ways) and extraordinarily widespread. While to doesn't see much use on new computers, it was the domininant filesystem on PCs from the early 80s through the late 90s / early 00s.
Being simple and nearly ubiquitious, virtually every OS (not just Microsoft's) had and have full support for it.
It lives on as the filesystem on virtually every USB thumb drive and SD-card (either FAT16, FAT32, or "exFAT"), and as a variant in the EFI System partition on every bootable GPT volume.
There are several variants you might encounter: FAT16, FAT32, and exFAT, with the latter two more common now (as FAT16 cannot support partitions larger than 2GB, and even "small" USB thumbdrives are generally larger than this nowadays).
FAT allocates storage in units called "clusters"; a cluster is the minimum allocable unit on a FAT filesystem. Clusters are a number of sectors; the number must be a power of two.
FAT layout
FAT manages files, directories, and free space using two data structures:
- The directory entry, which contains the file (or directory) name, size, starting address, and other metadata; and
- The file allocation table, which has two functions. First, it tracks the allocation status of clusters (that is, is part of a file stored at a given cluster?). Second, if a file is split across more than one cluster, it lets you find the clusters after the first (the first's address being stored in the directory entry).
At a high level, FAT filesystems have three parts:
- the reserved area, which stores essential data the describes the remainder of the filesystem,
- the FAT area, where one or more (typically two) copies of the FAT structures are stored, and
- the data area, where directory entries and file data are stored.
Let's look at each of these in turn.
Reserved area
Let's do these on the reserved area of my USB key. Remember, we can use mmls
to view the partition map, or parse the MBR (or GPT) ourselves.
mmls /dev/rdisk2
Password:
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors
Slot Start End Length Description
000: Meta 0000000000 0000000000 0000000001 Primary Table (#0)
001: ------- 0000000000 0000000031 0000000032 Unallocated
002: 000:000 0000000032 0003913727 0003913696 DOS FAT16 (0x06)
So the FAT partition begins on sector 32 of the drive. Let's extract it and view it:
dd if=/dev/rdisk2 bs=512 skip=32 count=1 | hexdump -Cv
1+0 records in
1+0 records out
512 bytes transferred in 0.001643 secs (311591 bytes/sec)
00000000 eb 3c 90 4d 53 44 4f 53 35 2e 30 00 02 40 01 00 |.<.MSDOS5.0..@..|
00000010 02 00 02 00 00 f8 ef 00 3f 00 ff 00 20 00 00 00 |........?... ...|
00000020 e0 b7 3b 00 00 00 29 02 97 72 68 4d 41 52 43 27 |..;...)..rhMARC'|
00000030 53 20 55 53 42 20 46 41 54 31 36 20 20 20 33 c9 |S USB FAT16 3.|
00000040 8e d1 bc f0 7b 8e d9 b8 00 20 8e c0 fc bd 00 7c |....{.... .....||
00000050 38 4e 24 7d 24 8b c1 99 e8 3c 01 72 1c 83 eb 3a |8N$}$....<.r...:|
00000060 66 a1 1c 7c 26 66 3b 07 26 8a 57 fc 75 06 80 ca |f..|&f;.&.W.u...|
00000070 02 88 56 02 80 c3 10 73 eb 33 c9 8a 46 10 98 f7 |..V....s.3..F...|
00000080 66 16 03 46 1c 13 56 1e 03 46 0e 13 d1 8b 76 11 |f..F..V..F....v.|
00000090 60 89 46 fc 89 56 fe b8 20 00 f7 e6 8b 5e 0b 03 |`.F..V.. ....^..|
000000a0 c3 48 f7 f3 01 46 fc 11 4e fe 61 bf 00 00 e8 e6 |.H...F..N.a.....|
000000b0 00 72 39 26 38 2d 74 17 60 b1 0b be a1 7d f3 a6 |.r9&8-t.`....}..|
000000c0 61 74 32 4e 74 09 83 c7 20 3b fb 72 e6 eb dc a0 |at2Nt... ;.r....|
000000d0 fb 7d b4 7d 8b f0 ac 98 40 74 0c 48 74 13 b4 0e |.}.}....@t.Ht...|
000000e0 bb 07 00 cd 10 eb ef a0 fd 7d eb e6 a0 fc 7d eb |.........}....}.|
000000f0 e1 cd 16 cd 19 26 8b 55 1a 52 b0 01 bb 00 00 e8 |.....&.U.R......|
00000100 3b 00 72 e8 5b 8a 56 24 be 0b 7c 8b fc c7 46 f0 |;.r.[.V$..|...F.|
00000110 3d 7d c7 46 f4 29 7d 8c d9 89 4e f2 89 4e f6 c6 |=}.F.)}...N..N..|
00000120 06 96 7d cb ea 03 00 00 20 0f b6 c8 66 8b 46 f8 |..}..... ...f.F.|
00000130 66 03 46 1c 66 8b d0 66 c1 ea 10 eb 5e 0f b6 c8 |f.F.f..f....^...|
00000140 4a 4a 8a 46 0d 32 e4 f7 e2 03 46 fc 13 56 fe eb |JJ.F.2....F..V..|
00000150 4a 52 50 06 53 6a 01 6a 10 91 8b 46 18 96 92 33 |JRP.Sj.j...F...3|
00000160 d2 f7 f6 91 f7 f6 42 87 ca f7 76 1a 8a f2 8a e8 |......B...v.....|
00000170 c0 cc 02 0a cc b8 01 02 80 7e 02 0e 75 04 b4 42 |.........~..u..B|
00000180 8b f4 8a 56 24 cd 13 61 61 72 0b 40 75 01 42 03 |...V$..aar.@u.B.|
00000190 5e 0b 49 75 06 f8 c3 41 bb 00 00 60 66 6a 00 eb |^.Iu...A...`fj..|
000001a0 b0 4e 54 4c 44 52 20 20 20 20 20 20 0d 0a 4e 54 |.NTLDR ..NT|
000001b0 4c 44 52 20 69 73 20 6d 69 73 73 69 6e 67 ff 0d |LDR is missing..|
000001c0 0a 44 69 73 6b 20 65 72 72 6f 72 ff 0d 0a 50 72 |.Disk error...Pr|
000001d0 65 73 73 20 61 6e 79 20 6b 65 79 20 74 6f 20 72 |ess any key to r|
000001e0 65 73 74 61 72 74 0d 0a 00 00 00 00 00 00 00 00 |estart..........|
000001f0 00 00 00 00 00 00 00 00 00 00 00 ac bf cc 55 aa |..............U.|
00000200
Note that like in the MBR, multibyte values in the FAT boot sector are little-endian.
0x0, 3 bytes: The reserved area starts with machine code that (in older bootable FAT partitions) tells the CPU how far ahead to JMP to the next part of the boot loader.
0x3, 8 bytes: Then 8 bytes of ASCII-coded OEM. "MSDOS5.0"
0xB, 2 bytes: bytes per sector "00 02" -> 512
0xD, 1 byte: sectors per cluster "40" -> 64 (so a cluster is 64 * 512 = 32KB on this USB key)
0xE, 2 bytes: size of the reserved area, in sectors "01 00" -> 1
0x10, 1 byte: # FATs "02"
0x11 2 bytes: (0 in FAT32) (in FAT16: max # files in root directory) "00 02" -> 512
0x13 2 bytes: # sectors; if doesn't fit in 2 bytes, should be zero "00 00 "
0x15 1 byte: media type (0xf8 fixed disk, 0xf0 removable) "f8"
0x16 2 bytes: (in FAT32: 0) (in FAT16: size in sectors of the FAT) "ef 00" -> 239
0x18 2 bytes: sectors per track "3f 00"
0x1A 2 bytes: # heads "ff 00"
0x1C 4 bytes: # sectors before start of partition (from beginning of disk, or extended partition) "20 00 00 00" -> 32
0x20 4 bytes: # sectors in file system (will be zero if bytes at 0x13 are non-zero, and vice versa) "e0 b7 3b 00" -> 3913696
0x24 1 byte: BIOS INT13h drive number (see https://en.wikipedia.org/wiki/INT_13H; not used these days)
0x25 1 byte: not used
0x26 1 byte: signature for validity of next entries; 0x29 if valid.
0x27 4 bytes: volume (partition) serial number
0x2b 11 bytes: volume (partition) label, ASCII
0x36 8 bytes: FS type label in ASCII -- usually "FAT16"
0x3e--0x1FE: unused by FAT; sometimes contains boot code (it might be what's jumped to by the JMP instructions)
0x1FE (2 bytes): signature value (55 AA)
This boot sector is the only thing in its reserved area; the reserved area in FAT32 might contain a few more things (including a FSINFO structure) but we'll skip those details here.
We can use fsstat
to view this information via Sleuthkit. We have to tell it where the filesystem if we access the volume directly, as it doesn't do partition table parsing itself:
fsstat -o 32 /dev/rdisk2
FILE SYSTEM INFORMATION
--------------------------------------------
File System Type: FAT16
OEM Name: MSDOS5.0
Volume ID: 0x68729702
Volume Label (Boot Sector): MARC'S USB
Volume Label (Root Directory):
File System Type Label: FAT16
Sectors before file system: 32
File System Layout (in sectors)
Total Range: 0 - 3913695
* Reserved: 0 - 0
** Boot Sector: 0
* FAT 0: 1 - 239
* FAT 1: 240 - 478
* Data Area: 479 - 3913695
** Root Directory: 479 - 510
** Cluster Area: 511 - 3913662
** Non-clustered: 3913663 - 3913695
METADATA INFORMATION
--------------------------------------------
Range: 2 - 62611478
Root Directory: 2
CONTENT INFORMATION
--------------------------------------------
Sector Size: 512
Cluster Size: 32768
Total Cluster Range: 2 - 61144
FAT CONTENTS (in sectors)
--------------------------------------------
511-574 (64) -> EOF
...more output...
Immediately following the reserved area (whose size is described above) comes the FATs themselves, with no header or footer.
File Allocation Tables
The FATs come next. In our example, there are 2 of them, each 239 sectors long. In FAT16, they are a sequence of 16-bit entries, one per cluster in the data area.
Entries corresponding to unallocated clusters store the value zero.
Entries corresponding to file/directories that are the last (including only) cluster allocated to the file contain any value greater than or equal to 0xFFF8 (again, little endian).
Entries containing 0xFFF7 indicate a bad sector (modern hard drives usually handle this, though it might matter if someone was attempting to hide data).
Other values tell you the next cluster of a file (or directory), given the current cluster.
Weirdly, the address of the first cluster in the data area is 2. And so the first two entries of the FAT don't correspond to clusters; they are usually used store a copy of the media type, and the "dirty status" --- whether the disk was ejected properly and/or the OS was shut down before poweroff.
Let's look at the start of our FAT:
sudo dd if=/dev/rdisk2 bs=512 skip=33 count=1 | hexdump -Cv
1+0 records in
1+0 records out
512 bytes transferred in 0.000679 secs (754032 bytes/sec)
00000000 f8 ff ff 7f ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000030 ff ff ff ff ff ff ff ff 1d 00 ff ff 1f 00 ff ff |................|
00000040 ff ff ff ff ff ff 00 00 ff ff 00 00 00 00 28 00 |..............(.|
00000050 29 00 2a 00 ff ff 2c 00 2d 00 2e 00 ff ff 30 00 |).*...,.-.....0.|
00000060 ff ff 00 00 ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000070 ff ff ff ff ff ff ff ff ff ff ff ff ff ff 43 00 |..............C.|
00000080 00 00 ff ff 00 00 ff ff ff ff ff ff ff ff 00 00 |................|
00000090 ff ff ff ff ff ff ff ff ff ff ff ff 00 00 ff ff |................|
000000a0 ff ff ff ff 00 00 ff ff 00 00 ff ff ff ff ff ff |................|
000000b0 ff ff ff ff ff ff 5c 00 64 00 5e 00 7c 00 00 00 |......\.d.^.|...|
000000c0 ff ff 62 00 ff ff ff ff ff ff 00 00 00 00 00 00 |..b.............|
000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000e0 00 00 00 00 00 00 ff ff 00 00 00 00 00 00 00 00 |................|
000000f0 00 00 00 00 7b 00 ff ff ff ff 00 00 00 00 00 00 |....{...........|
00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000200
fsstat
shows us some of this too, but note all TSK tools use sectors instead of clusters, so the offsets differ.
fsstat -o 32 /dev/rdisk2
FAT CONTENTS (in sectors)
--------------------------------------------
511-574 (64) -> EOF
575-638 (64) -> EOF
639-702 (64) -> EOF
703-766 (64) -> EOF
767-830 (64) -> EOF
831-894 (64) -> EOF
895-958 (64) -> EOF
959-1022 (64) -> EOF
1023-1086 (64) -> EOF
1087-1150 (64) -> EOF
1151-1214 (64) -> EOF
1215-1278 (64) -> EOF
1279-1342 (64) -> EOF
1343-1406 (64) -> EOF
1407-1470 (64) -> EOF
1471-1534 (64) -> EOF
1535-1598 (64) -> EOF
1599-1662 (64) -> EOF
1663-1726 (64) -> EOF
1727-1790 (64) -> EOF
1791-1854 (64) -> EOF
1855-1918 (64) -> EOF
1919-1982 (64) -> EOF
1983-2046 (64) -> EOF
2047-2110 (64) -> EOF
2111-2174 (64) -> EOF
2175-2302 (128) -> EOF
2303-2430 (128) -> EOF
2431-2494 (64) -> EOF
2495-2558 (64) -> EOF
2559-2622 (64) -> EOF
2687-2750 (64) -> EOF
2879-3134 (256) -> EOF
3135-3390 (256) -> EOF
3391-3518 (128) -> EOF
3583-3646 (64) -> EOF
3647-3710 (64) -> EOF
3711-3774 (64) -> EOF
3775-3838 (64) -> EOF
3839-3902 (64) -> EOF
3903-3966 (64) -> EOF
3967-4030 (64) -> EOF
4031-4094 (64) -> EOF
4095-4158 (64) -> EOF
4159-4222 (64) -> EOF
4223-4286 (64) -> EOF
4287-4350 (64) -> EOF
4351-4414 (64) -> EOF
4415-4478 (64) -> 4671
4543-4606 (64) -> EOF
4671-4734 (64) -> EOF
4735-4798 (64) -> EOF
4799-4862 (64) -> EOF
4863-4926 (64) -> EOF
4991-5054 (64) -> EOF
5055-5118 (64) -> EOF
5119-5182 (64) -> EOF
5183-5246 (64) -> EOF
5247-5310 (64) -> EOF
5311-5374 (64) -> EOF
5439-5502 (64) -> EOF
5503-5566 (64) -> EOF
5567-5630 (64) -> EOF
5695-5758 (64) -> EOF
5823-5886 (64) -> EOF
5887-5950 (64) -> EOF
5951-6014 (64) -> EOF
6015-6078 (64) -> EOF
6079-6142 (64) -> EOF
6143-6206 (64) -> EOF
6207-6334 (128) -> 6783
6335-6462 (128) -> 8319
6527-6590 (64) -> EOF
6591-6718 (128) -> EOF
6719-6782 (64) -> EOF
6783-6846 (64) -> EOF
7743-7806 (64) -> EOF
8191-8318 (128) -> EOF
8319-8382 (64) -> EOF