executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
re-uefiUEFI/BIOS 固件:SEC/PEI/DXE/BDS 阶段判定、DXE 驱动、UEFI 模块、bootkit。 触发词:UEFI、BIOS、DXE、PEI、SEC、PEIM、HOB、bootkit、Secure Boot、EFI 固件、runtime driver
Independent GitHub snapshot · Automated classification · Original documentation governs
第一步永远是判阶段与模块类型:
SEC → PEI → DXE → BDS → OS / Runtime(+ SMM 独立一路)
同一份固件里,不同阶段的模块运行在完全不同的执行环境:可用内存不同、可调用的服务不同(PPI / Protocol / Runtime Services)、生命周期不同(DXE_DRIVER 与 DXE_RUNTIME_DRIVER 不是一回事)。
所以顺序是:先判阶段与类型,再谈逻辑——类型判错,后面所有"它为什么这么写"的推理都会错。详见 [[pi-stages]]。 </CORE RULE>
| 类型 | 阶段 | 服务形式 / 生命周期 |
|---|---|---|
| SEC | 最早 | 安全与初始化入口,无通用内存环境 |
| PEIM | PEI | PPI;PEI 主要任务之一是建立永久内存 |
| DXE driver | DXE | Protocol;仅存在于 boot services 环境 |
| DXE runtime driver | DXE + Runtime | 跨生命周期:ExitBootServices() 后仍存在,SetVirtualAddressMap() 时被重定位 |
| UEFI driver / application | DXE/BDS 之后 | 跑在 UEFI 环境里的驱动/应用,与固件内建模块不是一回事 |
| SMM/MM driver | 独立 | SMM 内执行,特权层级与生命周期自成一套 |
三条高频判据(细节与决策树见 [[pi-stages]]):
LocateProtocol(&guid) → 做 GUID 字典解析,恢复成 EFI_XXX_PROTOCOL_GUID 与接口 vtable;协议图比直接调用图更有意义所有工具先验证再使用。固件镜像解析/模块静态分析可免沙箱;OVMF 仿真(步骤 5)是动态执行,默认沙箱 + 网络隔离([[re-analyze/platform-tips]] 最高原则)。
apt install uefitool uefitool-cli(官方包:GUI + CLI;CLI 含 UEFIExtract/UEFIFind)yay -S uefitool(或 uefitool-git;非官方仓库)choco install uefitool 如镜像可用)uefiextract --help 输出用法;GUI uefitool 能打开固件镜像uefifind imagefile {header|body|all} {list|count} pattern,无 -g/-t 选项uefiextract fw.bin <GUID>(见下)uefifind --helpapt install ovmf(/usr/share/OVMF/OVMF_CODE.fd、OVMF_VARS.fd)dnf install edk2-ovmf(路径 /usr/share/edk2/ovmf/OVMF_CODE.fd——旧 /usr/share/OVMF 布局已废弃)pacman -S edk2-ovmf(仅装 /usr/share/edk2/x64/OVMF_CODE.4m.fd,4m 格式)brew install qemu 自带固件($(brew --prefix)/share/qemu/edk2-x86_64-code.fd,随 qemu 包)ls /usr/share/OVMF/OVMF_CODE.fd;Fedora/RHEL ls /usr/share/edk2/ovmf/OVMF_CODE.fd;Arch ls /usr/share/edk2/x64/OVMF_CODE.4m.fd;macOS 用 brew 前缀路径apt install qemu-system-x86dnf install qemu-system-x86-core(完整虚拟化组为 dnf install @virtualization)pacman -S qemu-system-x86brew install qemuqemu-system-x86_64 --version按顺序执行,每步记录证据(路径 + sha256,见 [[re-triage]])。初勘先做:file fw.bin + 熵确认是否 UEFI 结构([[re-triage]])。
固件镜像解析(Firmware Volume → File → Section):
file fw.bin
uefiextract fw.bin all # 全量递归解包(含嵌套 FV 与压缩节,见坑 1/2)
ls fw.bin.dump/ # 树:Volume0/ → File0/ → Section0/ → PE32 等
DXE 驱动提取:
ueifind fw.bin all list <GUID> # 按模式串(含 GUID 文本)定位文件——NE 版仅位置参数语法,无 -g/-t
# 按 GUID 直接提取指定文件(UEFIExtract 的 GUID 参数模式):
# -m 合法值: all|body|header|info|file;-t 是十六进制节类型(PE32=0x10,即 -t 10)
uefiextract fw.bin <GUID> -o driver.efi -m body -t 10
file driver.efi # 期望输出: PE32+ executable (EFI boot service driver)
sha256sum 存证([[re-triage]]),再进反编译器模块分析(入口 / Protocol 服务):
gBS->LocateProtocol(&guid,...)(获取服务)、gBS->InstallProtocolInterface(...)(注册服务)、gBS->CreateEvent(...)(事件/回调)、gST->ConOut(控制台输出)strings driver.efi | grep -iE 'protocol|runtime|efi_' | head -30
bootkit 定位(SMM / 定时器回调 / 启动路径挂钩):
gBS->CreateEvent(EVT_TIMER, TPL, Callback, ...) + gBS->SetTimer(..., PERIODIC/ONESHOT, ...) → 回调函数就是周期执行恶意逻辑的地方(最常见挂点)SmiHandlerRegister / SMST 服务 → SMM driver 注册 SMI handler(SMM 内执行的代码,比内核 ring0 更高特权、SMRAM 内执行的持久层)gRT->SetVariable/GetVariable 等 Runtime Services 指针OVMF 仿真验证(运行恶意代码——沙箱内,网络 -net none):
# 只读代码固件 + 可写变量固件(两片 pflash 标准做法);OVMF_CODE.fd 路径按发行版:
# Debian/Ubuntu: /usr/share/OVMF/OVMF_CODE.fd
# Fedora/RHEL: /usr/share/edk2/ovmf/OVMF_CODE.fd(旧 /usr/share/OVMF 布局已废弃)
# Arch: /usr/share/edk2/x64/OVMF_CODE.4m.fd(4m 格式)
qemu-system-x86_64 -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE.fd \
-drive if=pflash,format=raw,file=OVMF_VARS.fd \
-m 1024 -net none -boot menu=on
Build*Hob 在 DXE 会断言);GUID 字典解析(Protocol/PPI/FFS/HOB/变量命名空间/配置表);FV → FFS → section → PE 层次(别按 PE 魔数直接 carve);DXE_DRIVER vs DXE_RUNTIME_DRIVER(ExitBootServices 后 boot services 全不可用、EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 通知函数禁调任何服务、ConvertPointer、EFI_RUNTIME_ARCH_PROTOCOL 的 VirtualMode/AtRuntime 判据)uefiextract fw.bin all 全量递归展开(自动处理嵌套),或 GUI 里逐层展开子 FV;先确认镜像结构再分析uefiextract fw.bin <GUID> -m body 导出裸 PE,导出后 file 确认输出含 "PE32+ executable (EFI boot service driver)" 再进反编译器;手工提取要按 Section 布局算偏移LocateProtocol 一类调用还原成语义名与接口 vtable,用协议图补足调用图DXE_DRIVER 与 DXE_RUNTIME_DRIVER:现象——拿固件里的地址与 OS runtime 阶段抓到的地址比对,判定被 hook;原因——runtime driver 在 ExitBootServices() 后仍存在、并会按 SetVirtualAddressMap() 的映射被重定位,固件地址本就不等于 runtime 地址;对策——先判模块类型与所处生命周期(EFI_RUNTIME_ARCH_PROTOCOL 的 VirtualMode/AtRuntime 是现成判据),再谈一致性([[pi-stages]])