GPT 分区表(GUID Partition Table)

大容量设备与现代系统的分区方案,EFI 标准的一部分。U 盘场景遇到 GPT 的典型情况:

  • 容量 > 2TB(MBR 的 32 位 LBA 上限约 2.2TB,超了必须 GPT)
  • Mac / Linux 上制作或格式化的 U 盘
  • Windows To Go、多分区 U 盘(Win10 1703+)

特征:LBA 0 是保护性 MBR(唯一表项类型 0xEE),真正的分区信息在 LBA 1 的 GPT 头和随后的分区表项里,盘尾还有一整套备份。

整体布局

LBA 0      ┌──────────────────────────────┐
           │  保护性 MBR(类型 0xEE)      │ ← 骗过旧工具,别去解析它
LBA 1      ├──────────────────────────────┤
           │  GPT 头(Primary Header)     │ ← "EFI PART",取证核心
LBA 2~33   ├──────────────────────────────┤
           │  分区表项 128 项 × 128 字节   │ ← 默认占 32 个扇区
LBA 34~    ├──────────────────────────────┤
           │  分区数据区                   │ ← 实际首分区通常对齐到 LBA 2048
           ├──────────────────────────────┤
LBA -33~-2 │  备份分区表项                 │
LBA -1     ├──────────────────────────────┤
           │  备份 GPT 头(Backup Header) │ ← 主表损坏时的救命稻草
           └──────────────────────────────┘

保护性 MBR(LBA 0)

结构与普通 MBR 相同,但只有一条类型 0xEE 的表项,声明”全盘被一个 GPT 分区占用”(扇区数超 32 位时填 0xFFFFFFFF)。作用仅是让不认识 GPT 的旧工具(如老 fdisk)认为盘已被占用,防止误格式化。

取证判读:MBR 里看到 0xEE → 立即跳转 LBA 1 验证 "EFI PART" 签名;0xEE 存在但 LBA 1 没有签名 → 主头被擦除,先去盘尾找备份头。

GPT 头(LBA 1,共512字节,有效 92 字节)

typedef struct _GPT_HEADER {            // 共92字节有效,扇区剩余部分置0
    CHAR    Signature[8];               // +0x00 "EFI PART" (45 46 49 20 50 41 52 54)
    DWORD   Revision;                   // +0x08 版本,通常 0x00010000
    DWORD   HeaderSize;                 // +0x0C 头大小 = 92 (0x5C)
    DWORD   HeaderCRC32;                // +0x10 头的CRC32 ← 校验时此字段先按0算
    DWORD   Reserved;                   // +0x14 必须为0
    QWORD   CurrentLBA;                 // +0x18 本头所在LBA(主头=1,备份头=最后扇区)
    QWORD   BackupLBA;                  // +0x20 对方头的LBA(主头中=盘最后扇区)
    QWORD   FirstUsableLBA;             // +0x28 数据区起点(通常34)
    QWORD   LastUsableLBA;              // +0x30 数据区终点(通常倒数34扇区)
    BYTE    DiskGUID[16];               // +0x38 磁盘GUID ← 取证关联点
    QWORD   PartTableLBA;               // +0x48 分区表起始LBA(主表中=2)
    DWORD   PartEntryCount;             // +0x50 表项数(通常128)
    DWORD   PartEntrySize;              // +0x54 每项字节数(通常128=0x80)
    DWORD   PartTableCRC32;             // +0x58 分区表整体的CRC32
} GPT_HEADER;

分区表项(每项 128 字节,默认 128 项)

typedef struct _GPT_ENTRY {             // 共128字节
    BYTE    PartTypeGUID[16];           // +0x00 分区类型GUID,全0=空表项
    BYTE    UniqueGUID[16];             // +0x10 本分区唯一GUID ← 挂载记录关联点
    QWORD   FirstLBA;                   // +0x20 分区起始LBA ← 重点
    QWORD   LastLBA;                    // +0x28 分区结束LBA(含本扇区)← 重点
    QWORD   AttrFlags;                  // +0x30 属性位
    WCHAR   PartName[36];               // +0x38 分区名(UTF-16LE,72字节)
} GPT_ENTRY;

与 MBR 的关键差异:没有 CHS、没有扩展分区/EBR、没有 4 个分区的上限;“删除分区”只是把类型 GUID 清零。

GUID 字节序陷阱(手工解析必踩)

GPT 中 GUID 的前三段按小端存储,后两段原样(mixed-endian)。例如 Microsoft Basic Data 的 GUID:

标准写法:  EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
盘上字节:  A2 A0 D0 EB  E5 B9  33 44  87 C0 68 B6 B7 26 99 C7
           └──小端──┘ └小端┘ └小端┘ └────── 原样 ──────┘

010 Editor 等模板会自动转换;手工比对时必须先转,否则所有 GUID 都”对不上”。

常见分区类型 GUID

GUID(标准写法)含义
00000000-0000-0000-0000-000000000000空表项
EBD0A0A2-B9E5-4433-87C0-68B6B72699C7Microsoft Basic Data(FAT/exFAT/NTFS 共用,需进 DBR 分辨)
C12A7328-F81F-11D2-BA4B-00A0C93EC93BEFI 系统分区(ESP,FAT32)
E3C9E316-0B5C-4DB8-817D-F92DF00215AEMicrosoft 保留分区(MSR)
DE94BBA4-06D1-4D40-A16A-BFD50179D6ACWindows 恢复分区
0FC63DAF-8483-4772-8E79-3D69D8477DE4Linux 文件系统
0657FD6D-A4AB-43C4-84E5-0933C84B4F4FLinux swap
48465300-0000-11AA-AA11-00306543ECACApple HFS+
7C3457EF-0000-11AA-AA11-00306543ECACApple APFS

属性位(AttrFlags)

位含义
bit 0平台必需分区(系统启动依赖)
bit 1EFI 忽略该分区
bit 2Legacy BIOS 可引导
bit 60只读
bit 62隐藏(Windows 不显示)
bit 63不自动分配盘符

bit 62/63 置位说明有人故意让系统不挂载这个分区——取证中遇到必须手工按 LBA 范围提取。

手工解码示例

GPT 头(LBA 1)前 16 字节:

45 46 49 20 50 41 52 54  00 00 01 00 5C 00 00 00
└──────┬──────────────┘  └────┬────┘ └────┬────┘
   "EFI PART"              版本1.0     头大小=0x5C=92

一条分区表项(LBA 2 起):

A2 A0 D0 EB E5 B9 33 44 87 C0 68 B6 B7 26 99 C7   ← 类型GUID:EBD0A0A2-...(Microsoft Basic Data)
28 57 DE 71 22 68 CB 43 A2 37 2B BF 47 1F 04 8C   ← 唯一GUID
00 08 00 00 00 00 00 00 FF F7 3D 00 00 00 00 00   ← FirstLBA=0x800=2048,LastLBA=0x3DF7FF
00 00 00 00 00 00 00 00                            ← 无属性位
55 00 73 00 62 00 64 00 69 00 73 00 6B 00 ...      ← 分区名 "usbdisk"(UTF-16LE)

→ 分区范围 = 扇区 2048 ~ 0x3DF7FF,文件系统入口偏移 = 0x800 × 512 = 0x100000。

备份机制与修复(取证高频)

  • GPT 头中有 BackupLBA 指向盘尾备份头,备份头再指向备份分区表(主表之后是镜像排列)。
  • 主表损坏/被擦除:gdisk 打开时会自动提示用备份恢复;sgdisk -b 可先备份现有结构再动。手工场景:从盘尾倒数第 1 扇区读备份头 → 其 PartTableLBA 指向备份表。
  • CRC 校验定位坏点:头 CRC 坏但表 CRC 好 → 只坏头;反之只坏表。两者都对但内容不同 → 主备不一致,说明被手工改过(篡改/藏数据线索)。
  • 用备份修复后,记得修复动作本身会写入磁盘——取证只读副本上操作,原件不动。

取证要点

  1. DiskGUID(头 0x38)和分区 UniqueGUID 都可与 Windows 注册表 HKLM\SYSTEM\MountedDevices 关联(GPT 盘的挂载值含 GUID 而非磁盘签名),证明”这个盘插过这台电脑”。
  2. 头中 CurrentLBA/BackupLBA/LastUsableLBA 与实际镜像大小不符 → 镜像被截断,或盘被扩容造假(小卡刷大容量)。
  3. 藏数据区:LastUsableLBA 之后到备份表之间、128 个表项中未使用的槽位(可能残留旧表项的非 GUID 字段)、表项首尾 LBA 之间的缝隙。
  4. 空表项只清类型 GUID,PartName 等字段常残留 → 可推断曾经存在过的分区名称与范围。
  5. 属性位 bit 62/63 的分区系统不挂载,取证工具可能也不自动列——按 LBA 手工提取。
  6. Hybrid MBR(Mac 制作常见):LBA 0 同时有 0xEE 和真实 DOS 分区表项,两套表可能不一致,两个视角都要解析。
  7. 工具侧:mmls 显示 GUID Partition Table (EFI);X-Ways/FTK 均原生支持,主表坏时会提示是否使用备份。