可信启动流程
可信启动
基准值
在一些硬件平台的实现中,初始平台度量值用来表示平台首次启动时的度量基线,这些初始值是由硬件厂商或系统集成商预设的,通常存储在TPM的非易失性存储区中。
TCG规范
《TCG PC Client Platform Firmware Profile Specification》
-
章节:7.4.1 Root of Trust for Measurement (RTM)
“The RTM is the component that performs the first measurement and extends it into a Platform Configuration Register (PCR).
The firmware code and configuration used by the RTM are defined at manufacture time and cannot be modified post-manufacture except by an authorized update process.”第一次度量动作(测量 Boot Block)由 出厂时定义的代码执行;
该代码及其基准(即被信任的初始哈希或签名公钥)在制造阶段写入;
后续不可随意更改,除非有授权更新(厂商签名更新 BIOS)。
国家标准
《GM/T 0054-2018 可信计算平台 软件度量与验证规范》
-
第6章:
“可信基准值由可信软件发布者或平台提供者在受控环境下计算产生,并在平台生产或初始化阶段写入可信平台控制模块或固件中。”
这些标准要求在设备制造时通过硬件信任根(例如芯片内的加密密钥和证书)进行最初的基准值写入,后续启动过程中的所有度量值都将与这些预设的基准值进行比对。
硬件厂商标准
Intel BootGuard Specification
“Platform owners or OEMs fuse the Boot Policy Manifest (BPM) and hash of the BIOS public key into the Platform Controller Hub (PCH) Field Programmable Fuses (FPFs) at manufacturing time.”
AMD Platform Security Processor (PSP)
“The PSP verifies the initial BIOS image using a public key hash fused at manufacturing.
The key hash is programmed into the SoC fuses and cannot be modified after fabrication.”
系统启动流程
PSP核启动后加载PSP的bootloader,由bootloader做各种初始化,随后BootLoader
关键组件和代码度量
| 关键组件 |
|---|
| BIOS/U-BOOT |
| PciRoot(0x0)/Pci(0x8,0x1)/Pci(0x0,0x2)/Sata(0x6,0xFFFF,0x0)/HD(1,GPT,D43E84F4-0E97-4488-91B3-8A727A8A9572,0x800,0x100000)/\EFI\ubuntu\grubx64.efi |
| (hd1,gpt3)/boot/grub/x86_64-efi/normal.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/terminal.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/crypto.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/bufio.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/extcmd.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/boot.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/gettext.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/gzio.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/command.lst |
| (hd1,gpt3)/boot/grub/x86_64-efi/fs.lst |
| (hd1,gpt3)/boot/grub/x86_64-efi/crypto.lst |
| (hd1,gpt3)/boot/grub/x86_64-efi/terminal.lst |
| (hd1,gpt3)/boot/grub/grub.cfg |
| grub_cmd: [ -s (hd1,gpt3)/boot/grub/grubenv ] |
| (hd1,gpt3)/boot/grub/x86_64-efi/test.mod |
| (hd1,gpt3)/boot/grub/grubenv |
| grub_cmd: load_env |
| (hd1,gpt3)/boot/grub/x86_64-efi/loadenv.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/disk.mod |
| (hd1,gpt3)/boot/grub/grubenv |
| grub_cmd: [ ] |
| grub_cmd: set default=Advanced options for Ubuntu |
| grub_cmd: [ xy = xy ] |
| grub_cmd: menuentry_id_option=–id |
| grub_cmd: export menuentry_id_option |
| grub_cmd: font=unicode |
| grub_cmd: loadfont unicode |
| (hd1,gpt3)/boot/grub/x86_64-efi/font.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/video.mod |
| (hd1,gpt3)/boot/grub/fonts/unicode.pf2 |
| grub_cmd: set gfxmode=auto |
| grub_cmd: load_video |
| grub_cmd: insmod all_video |
| (hd1,gpt3)/boot/grub/x86_64-efi/all_video.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/efi_gop.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/video_fb.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/efi_uga.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/video_bochs.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/video_cirrus.mod |
| grub_cmd: insmod gfxterm |
| (hd1,gpt3)/boot/grub/x86_64-efi/gfxterm.mod |
| grub_cmd: set locale_dir=(hd1,gpt3)/boot/grub/local |
| grub_cmd: set lang=en_US |
| grub_cmd: insmod gettext |
| grub_cmd: terminal_output gfxterm |
| grub_cmd: set timeout_style=hidden |
| grub_cmd: set timeout=2 |
| grub_cmd: [ -f (hd1,gpt3)/boot/grub/custom.cfg ] |
| grub_cmd: setparams Advanced options for Ubuntu GN |
| grub_cmd: setparams Ubuntu GNU/Linux, with Linux 5 |
| grub_cmd: load_video |
| grub_cmd: insmod all_video |
| grub_cmd: set gfxpayload=keep |
| grub_cmd: insmod gzio |
| grub_cmd: insmod part_gpt |
| grub_cmd: insmod ext2 |
| grub_cmd: set root=hd0,gpt3 |
| grub_cmd: search --no-floppy --fs-uuid --set=root |
| (hd1,gpt3)/boot/grub/x86_64-efi/search.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/search_fs_uuid.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/search_fs_file.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/search_label.mod |
| grub_cmd: echo Loading Linux 5.10.112-hygon … |
| (hd1,gpt3)/boot/grub/x86_64-efi/echo.mod |
| grub_cmd: linux /boot/vmlinuz-5.10.112-hygon root=UUID |
| (hd1,gpt3)/boot/grub/x86_64-efi/linux.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/relocator.mod |
| (hd1,gpt3)/boot/grub/x86_64-efi/mmap.mod |
| /boot/vmlinuz-5.10.112-hygon |
| kernel_cmdline: /boot/vmlinuz-5.10.112-hygon root= |
| grub_cmd: echo Loading initial ramdisk … |
| grub_cmd: initrd /boot/initrd.img-5.10.112-hygon |
| /boot/initrd.img-5.10.112-hygon |
1) 固件与设备路径(上电 → 固件)
主板固件(BIOS/UEFI 或 U-Boot)启动后会做硬件初始化(CPU、内存、PCI 总线、存储控制器),然后按固件配置选择一个设备(比如哪个 SATA 端口、哪个 NVMe)来读取并执行第一级引导程序(例如 EFI 下的 bootloader)。固件还可能验证引导程序签名(Secure Boot)或按启动顺序选择设备。 上电后跑的代码是 BIOS/UEFI 或 U-Boot,它决定从哪块盘、哪条总线把引导器拉起来。固件被改了,后面所有东西都可能是假象。BIOS/U-BOOT、PciRoot(...)/Sata(...)、(hd1,gpt3) 就是这个层面的文件。
2) 加载grub本体
固件把 GRUB 的主可执行文件(例如 EFI/BOOT/grubx64.efi 或 /boot/efi/.../grubx64.efi)载入内存并运行。这一步会把 GRUB 的基础执行环境建立起来,准备加载 GRUB 的模块和配置文件。替换这个文件或它的签名会导致后续的启动甚至不是启动用户自己的操作系统。要度量的是 EFI 下的 grub 二进制和最早被加载的模块( .../boot/grub/x86_64-efi/... )。
3) GRUB 模块加载
GRUB 的很多功能并非内建在一个巨大的单体程序里,而是以模块(.mod 文件)形式存在。举例:ext2 模块实现读取 ext 分区,search_fs_uuid.mod 实现按 UUID 查分区,linux.mod 实现把内核映像加载到内存,crypto.mod 实现加密/解密支持,gzio.mod 实现 gzip 解压。GRUB 启动时按需 insmod(加载)这些模块来完成具体动作。
模块被替换能在很早就注入恶意行为,典型文件有 linux.mod, disk.mod, search.mod, crypto.mod, gzio.mod, gfxterm.mod 等。
4) 配置与环境(grub.cfg / grubenv)
实际要做什么、用什么参数启动,这些都写在 grub.cfg 或 grubenv。攻击者常用的手法不是改二进制,而是改脚本:偷偷加一条菜单、在 kernel 行加 init=/bin/sh。所以把这些文本文件和 GRUB 在启动时执行的命令记录当做度量对象很重要。
5) 定位与读取(search / filesystem)
GRUB 要先找到一个分区再去读文件。search --fs-uuid、part/FS 模块(part_gpt、ext2)和路径 (hd1,gpt3)/boot/... 是这一层的关键。这里被干的最简单也最常见:换盘、替换 /boot/vmlinuz 或 /boot/initrd。度量磁盘路径、search 模块和盘上这些文件,是检测文件级篡改的必做事。
6) 内核与 initrd(权力移交点)
当 GRUB 把内核(vmlinuz-*)和 initrd(initrd.img-*)加载并把命令行交给它们,控制权就转交了。内核或 initrd 被改,系统基本完蛋。一定要度量内核映像、initrd 和负责加载它们的模块(relocator.mod/mmap.mod 等)。
7) 解密/UI/早期脚本(initrd、crypto、字体)
如果有加密盘,GRUB 或 initrd 里会有解密逻辑;同时早期界面(gfxterm, terminal, 字体、gettext)是用户输入密码的点。攻击者常把这两者结合:伪造界面记录密码或用假 crypto 模块绕过解密。度量这些组件能防止口令泄露与解密被篡改。