前几天电脑修好以后,我找了专门的 Apple 文档还研究了 DFU 这个东西:

其实还有一个维护的 wiki,那我就不爱看了
苹果毕竟设备产品这么多,安全上面要下大功夫的;一方面是隐私安全,另外一方面是不想把配件市场给更大商家;在 Intel 时代,在不得已的情况下,外挂了一颗 T2.

是要保护的呀
然后现代搞了 SOC,更是把这些东西都做在了一起。

哪有怎样,再牛逼也得 SPI

这是 doc 里面复杂的架构
然后, Apple 的安全不是“某个密码很复杂”,而是:每一层只信任上一层验证过的东西,这就是典型的 chain of trust(信任链)。
这份文档最核心的思想,是信任必须有根,而且这个根必须尽可能不可篡改。
这个“根”在 Apple 体系里主要体现为:Boot ROM,制造时固化,不可更改,是最底层硬件信任根;Secure Enclave(安全隔区),独立安全子系统,负责密钥、生物识别、部分高敏感安全逻辑;AES / PKA 等专用硬件引擎,实现密钥不可见的加解密与公钥操作;UID/GID 等硬件绑定密钥材料,把数据和“这台设备”绑定起来;签名验证与启动链,只有受信任的软件才能进入下一阶段执行。

这个是 M4 的主板,我也没有看到雷电的接口不一样
其实是这样的,虽然苹果有两个口,但是是 USB4+霹雳的:

大概是这样
按照文档的意思,DFU 是底层 iBOOT 下的产物,这段引导是提前写入的,也就是说,除非真真正正的硬件错误,否则只要进入 DFU 就可以重新启动引导。
但是还有一个引导设计,在重新开机后:

还是会把安全的解锁信息带过来

在这里有这个描述
另外,还可以进入更多的安全模式:

大开眼界
一般来说做嵌入式的是要深刻理解这个过程的,但是这个要理解需要学很多计算机组成原理的课程,而且现在很多人也这个文章(但是一眼 AI,我感觉对面复制的老哥可能眼神都涣散了)
苹果安全这些我是没有本事研究,但是我们可以先看看普通的,然后做一些感性的理解也不错。
嵌入式系统的启动过程(Boot Process)其实是所有计算系统最基础的运行机制;无论是 MCU、SoC、手机、路由器、FPGA SoC,还是 PC,本质结构都类似,只是复杂程度不同。
从系统工程角度看,启动流程可以概括为一句话:
从不可修改的最小可信代码开始,一层一层加载更复杂的软件。
所有系统启动都遵循同一个原则:ROM → Bootloader → OS → Application
也就是:
不可修改代码
↓
初始化硬件
↓
加载更复杂的软件
↓
运行系统
原因很简单,上电时:RAM 是空的,CPU 没有程序,Flash 还没被读取;所以必须有一段 CPU 知道在哪里的代码;这就是:Boot ROM。

苹果这个太复杂了,我的看不清
最简单情况,如STM32,启动过程:
Power on
│
▼
Reset
│
▼
PC ← Reset Vector
│
▼
执行 Flash 中代码
CPU 上电后,程序计数器 PC 会被设置为:0x00000000或者某个固定地址;这个地址叫:Reset Vector,这里存放程序入口地址。(因为 CPU 只会忠实的运行 PC 指向的指令)
例如 ARM Cortex-M:
0x00000000 初始SP
0x00000004 Reset Handler
启动过程:
CPU reset
│
读取 SP
│
读取 PC
│
跳转 Reset_Handler
Reset Handler 是 C 程序之前的初始化代码:
Reset_Handler:
初始化堆栈
初始化 .data
清零 .bss
初始化时钟
调用 main()
流程:
Reset
│
startup.s
│
system_init()
│
main()
这就是 MCU 启动。
开机以后,第一步是重置,所有寄存器保证在可控状态;接着是ARM Cortex-M 处理器复位后,硬件会自动从地址 0x00000000 获取 MSP (主堆栈指针) 初始值以建立内存栈区,随后从 0x00000004 读取 复位向量 并存入 PC(其最低位必须为 1 以进入 Thumb 状态),从而引导 CPU 跳转至 Reset_Handler 开始执行初始化代码及进入主程序。
Reset Handler 是汇编语言,但也是程序,它首先完成 C 运行环境的准备工作,包括通过 初始化堆栈 确保内存空间可用、将 .data 段从 Flash 拷贝到 RAM 以及将 .bss 段清零;随后配置系统时钟以确保硬件频率正常,最后通过跳转指令调用 main() 函数,实现从底层汇编到上层应用程序的平滑过渡。
另外需要注意,在 Reset_Handler 中,通常会先调用一个名为 SystemInit() 的 C 函数(由芯片厂商提供),它的主要工作就是配置系统时钟(设置 PLL、HSE/HSI、AHB/APB 总线分频等)。只有时钟稳定后,CPU 才能以更快的速度执行后续的 .data 拷贝和 main() 函数。(我们不要小看这个时钟系统,另外 MCU 本来就是数学电路需要时钟)
SoC 比 MCU 复杂很多,因为:OS 很大,存储复杂,有 DRAM。
典型 SoC 启动:
Power on
│
▼
Boot ROM
│
▼
Stage1 Bootloader
│
▼
Stage2 Bootloader
│
▼
OS Kernel
│
▼
Userspace
因为Boot ROM 代码必须极小,如:32 KB;所以它只能做:初始化最小硬件,加载 bootloader,而Linux kernel > 10MB,Boot ROM 不可能直接加载。。
典型 Bootloader:
Stage0 Boot ROM
Stage1 SPL
Stage2 U-Boot
Stage3 Kernel
在芯片内部:ROM code;来初始化 CPU,初始化 SRAM,读取 Boot device,加载 Stage1
Boot device 可能是:
NAND
NOR
eMMC
SD
USB
UART
SPL,Secondary Program Loader,来初始化 DRAM,然后加载 Stage2
那为什么要单独 SPL?
因为:DRAM 初始化非常复杂,如 DDR 有PLL,timing,calibration;但Boot ROM 不会做这些。
U-Boot 是最常见 bootloader;用来初始化外设,加载 kernel,加载 device tree,加载 initramfs;然后:jump to kernel。
安卓时代喜欢刷机,而且现在也能经常听见要什么解 BL 锁,其实就是这个地方的问题;一个新的 ROM,需要最底层开始一级一级的引导。
再说回STM32 启动流程:
Reset
│
Boot mode pins
│
├─ Flash
├─ System ROM
└─ SRAM
如果选择:Flash;执行:0x08000000;如果选择:System ROM;进入:ST Bootloader;支持:USART,USB,CAN,I2C。

这里需要骂一下 ADI 的启动
bootloader 需要我自己写!操。
启动系统的三个核心问题:
CPU 从哪里取第一条指令,Boot ROM
如何加载更大程序?Bootloader
如何保证安全?Secure Boot(知道大家不爱看,没写)
最终结构可以总结为:
Power
│
Reset
│
Boot ROM
│
Bootloader Stage1
│
Bootloader Stage2
│
Kernel
│
Init
│
Applications
DFU(Device Firmware Update)模式是 Apple 设备安全架构中一个非常关键但经常被误解的组件。它不是“绕过安全”的后门,而是受信启动链的一部分,用于恢复系统或重新安装固件。
如果理解 Apple 的安全模型,DFU 其实非常有代表性,因为它涉及:Boot ROM,Secure Boot chain,签名验证,恢复模式,USB 设备协议。
Apple 设备启动大致分为几个阶段:
硬件上电
│
▼
Boot ROM(不可修改)
│
▼
LLB / iBoot
│
▼
Kernel
│
▼
iOS / iPadOS / macOS
而 DFU 模式存在于 Boot ROM 阶段,换句话说:
DFU 是 Boot ROM 内置的 USB 固件更新协议。
因为 Boot ROM 在芯片生产时就写死在硅片里,所以:无法被软件更新,无法被系统篡改,永远存在;这就是 DFU 的安全基础。
如果设备启动失败,例如:系统损坏,iBoot 损坏,更新中断,NAND 损坏,用户强制恢复设备必须有一种最低级别恢复机制,否则设备就会变成砖。
所以 Apple 设计:
Boot ROM
├── 正常启动路径
└── DFU 恢复路径
如果正常启动失败,Boot ROM 可以:直接进入 DFU 模式,通过 USB 接收新的固件镜像。
DFU 模式本质是一个 USB DFU 协议设备,当 iPhone/iPad 进入 DFU 时;电脑看到的设备不是 iPhone,而是:
Apple Mobile Device (DFU Mode)
USB Vendor ID:
0x05AC
Product ID(不同设备不同)。
此时设备只运行Boot ROM;没有:iBoot,kernel,iOS,drivers,文件系统,这个设备几乎是“裸芯片”。
电脑端(Finder / iTunes / idevicerestore):
发送固件
│
▼
Boot ROM 接收
│
▼
验证签名
│
▼
写入 NAND
│
▼
重启
关键步骤是:签名验证,否则 DFU 就会成为 jailbreak 永久后门(开心死啦)。
Apple 的 secure boot 是:
Boot ROM
↓ verify
LLB
↓ verify
iBoot
↓ verify
Kernel
每一步都会验证签名。

DFU 也是同样,DFU 接收固件后:
Boot ROM
↓
验证 Apple 签名
↓
允许执行
如果固件没有 Apple 签名:Boot ROM → 拒绝;这就是为什么:不能随便刷自定义系统(因为软件签名不对,底层硬件是拒绝的)
很多人听过SHSH blobs,这其实也和 DFU 密切相关;因为Apple 不仅要求:固件必须 Apple 签名;还要求:固件必须针对这台设备签名。
服务器流程:
电脑
│
▼
Apple TSS server
│
▼
生成 SHSH
│
▼
设备验证
这就是为什么:旧版本 iOS 很难刷回去,因为 Apple 停止签名。(这个 jb 封闭啊)
很多人混淆这两个,但是区别非常重要。
模式 | 运行代码 | USB 显示 | 能力 |
|---|---|---|---|
Recovery | iBoot | iTunes + cable | 普通恢复 |
DFU | Boot ROM | 黑屏 | 最底层恢复 |
Boot ROM 代码无法更新,所以如果 Boot ROM 有漏洞:那漏洞 = 永久漏洞(我在说正确的废话)
这就是著名的:checkm8(Boot ROM exploit。)
影响:A5 → A11;攻击流程:USB → DFU → Boot ROM exploit,利用 DFU USB stack 的漏洞,然后可以控制 Boot ROM
checkm8 漏洞利用流程首先需要将设备强制进入 DFU 模式,在 BootROM 处于等待 USB 接收固件的阶段,利用其 USB 控制传输回调函数中的堆溢出或释放后使用(UaF)漏洞实施劫持;随后通过注入 Shellcode 直接在内存中绕过官方签名验证,从而获取 Root 最高权限并实现任意镜像的加载与越狱。
因为 DFU 解决一个关键问题:设备可恢复性;如果没有 DFU:设备更新失败就彻底砖;Apple 的设计原则是:DFU 必须存在,但 DFU 不允许绕过签名。
所以:Boot ROM 固定,必须验证签名,USB 接口最小化
如果把 Apple 安全体系画成结构:
┌────────────────────┐
│ iOS / Apps │
├────────────────────┤
│ Kernel │
├────────────────────┤
│ iBoot │
├────────────────────┤
│ LLB │
├────────────────────┤
│ Boot ROM │
├────────────────────┤
│ DFU mode │
└────────────────────┘
DFU 的作用是当上面全部损坏时仍然可以恢复系统。
(我本来还有一段猜测 Apple 如何设计 DFU 的,但是觉得无关紧要了)
最近几年固件安全好少,大佬们不知道哪里去了;另外研究这些也不是全无意义,当你在设计产品时不可避免的要和启动这个“不起眼的”事情打交道,深入理解过程才能写出好代码。