2026 年 11 月 7 日
一台已经躺了将近两年的手机,终于重新亮起了屏幕
说起来可能有点离谱。这台手机并不是什么特别珍贵的设备,只是一台多亲 F21 Pro+,搭载紫光展锐 T310(UMS312)平台的 Android 手机
但是为了让它重新启动,我前前后后折腾了将近一年零八个月
甚至在最后成功之前,我还在研究展锐的 BootROM、FDL、U-Boot,以及那一大堆看起来名字就很让人头疼的启动组件
而这件事情的起因,其实非常简单
2025 年 3 月,我把它的启动分区搞没了
准确来说,是一次围绕解锁脚本的折腾,让这台手机的 splloader 和 splloader_bak 两个关键分区遭到了破坏
然后,它就再也没能正常启动
0x00 一台失去启动能力的手机
2025 年 3 月 16 日
那时候的我,正在尝试对这台 F21 Pro+ 进行一些底层折腾
事情最开始其实并没有想象中那么复杂。无非是解锁、研究启动链,再看看有没有进一步修改系统的可能
但是,解锁脚本涉及对 splloader 和 splloader_bak 的擦除操作。后来重新读取这两个分区时,我发现它们已经变成了全零数据
这就很尴尬了
对于普通的 Android 用户而言,手机无法开机,可能还可以尝试 Recovery、Fastboot,或者直接刷入官方固件
但是,如果连最前面的启动程序都出了问题呢?
SPLSecondary Program Loader可以理解为启动过程里相当靠前的一环。它负责完成一些早期硬件初始化,并把控制权交给后续的启动程序
而我这台机器的问题就在于,它已经没办法正常走完这条启动链了
手机本身几乎没有什么反应
好在,展锐平台还留着一扇门
BootROM
这是一段位于芯片内部的早期启动代码。即便外部存储里的启动程序损坏,芯片仍然可能通过它提供的下载与诊断通道,与电脑进行通信
至少,在电脑上我还能看到 SPRD U2S Diag
也就是说,芯片没有彻底失联
但是能够通信,和能够重新启动系统,显然是两回事
当时的我并没有找到足够可靠的原厂启动镜像,更没有把握直接重建整条启动链
于是,这台手机就这样暂时被放下了
一放,就是一年多
0x01 BootROM 还活着,那能不能绕过去?
时间来到 2026 年 11 月
不知道为啥,我又想起了这台手机
既然设备仍然能够通过 BootROM 通信,那有没有可能不依赖原本已经损坏的 SPL,直接从内存里把后面的启动程序跑起来?
顺着这个想法,我重新研究了紫光展锐平台的启动流程
这里需要先介绍两个东西
- FDL1:用于早期初始化和建立下载环境的第一阶段程序
- FDL2:负责进一步处理存储设备访问、分区读写等操作的第二阶段程序
简单来说,BootROM 提供了一个最初的入口,FDL1、FDL2 再逐步建立起更完整的操作环境
如果能够成功把这些程序加载到内存里,理论上就有机会在不依赖原有 SPL 的情况下,对存储设备进行恢复操作
听起来似乎很有希望
而且,展锐平台此前还出现过 CVE-2022-38694 等与 BootROM 下载机制相关的安全问题
于是,我开始重新分析手头已有的二进制文件
包括 FDL1、FDL2、U-Boot、SML、TrustOS、TEECFG 等启动组件
期间我还尝试修改 FDL1 的部分行为,希望让它进入特定的下载通信模式
实验确实取得了一点进展
修改后的 FDL1 能够完成预期的握手过程,但是后续 FDL2 的交接并没有真正走通
这也意味着,我还没有实现最初设想的那种完整 RAM 启动恢复方式
有时候底层开发就是这样,你以为自己已经打开了一扇门,结果走进去之后发现,里面还有好几扇门
而且每一扇都上着锁
更麻烦的是,这些启动组件之间还涉及签名、证书链、平台配置等兼容性问题。即便某个二进制文件可以被成功加载,也不代表它就能在目标设备上正确执行
所以折腾到这里,我开始重新考虑另一个方向
或许,我真正缺少的并不是什么神奇的漏洞利用方法,而是一份正确的启动程序。
0x02 寻找那份不知道存不存在的备份
问题又回到了最开始
我的 splloader 和 splloader_bak 已经损坏,而手头并没有一份确认可用的原始备份
网上能够找到的文件,不一定属于同一款设备
即便属于同一型号,也不一定采用相同版本的启动链和签名配置
更何况,这还是一台已经有些年头的小众设备
我开始重新寻找可能拥有底层备份的人
后来,我在酷安联系上了一位叫做 Auth_ 的人
之所以找上他,是因为我看到过他此前在展锐设备上的一些底层折腾经历,包括基带相关的修改
能够做到这种程度的人,手上或许会留下普通用户不会保存的东西。
比如,完整的分区备份
结果还真有
Auth_ 给了我一份大约 1.4GB 的设备原始分区Dump
但是,他还专门提醒我,这份备份包含修改过的扩容分区表,不能直接整包刷入
这句提醒非常重要
尤其是底层分区布局发生过修改的情况下,直接覆盖 GPT 等信息,可能让原本只需要修复启动链的问题变得更加复杂
我已经因为启动分区吃过一次亏了
实在不想再吃第二次
所以这次,我没有选择直接刷入整份备份,而是开始一点一点检查里面的内容
0x03 终于找到 SPL 了
在这份备份中,我找到了一个文件:
SPRD-Backup-splloader.img
文件大小是 4MiB
不过,文件大小和真正有意义的启动程序大小并不是一回事
经过检查,其中实际使用的数据集中在文件前部,后面存在大量零填充
我进一步分析了镜像里的 DHTB 结构、证书信息以及载荷哈希
至少从文件自身来看,相关数据能够相互对应,没发现明显的完整性问题
而且,它与手头已有的部分启动组件,在证书链相关字段上存在兼容的迹象
当然,这不能直接证明它一定可以被我的手机接受
毕竟设备本身的信任根、回滚状态等信息,仍然可能影响最终结果
但是,和之前那些只能从零散固件里提取出来、来源又不太确定的文件相比,这一次至少有了一份值得进一步验证的候选镜像
而且,它来自同型号设备的实际备份
我终于可以开始考虑真正的恢复操作了这次,我不打算再随便试
先检查文件,再确认写入范围,然后写入,最后回读验证
尤其不能把一个带有大段零填充的 4MiB 文件,不加判断地写进一个容量不同的启动区域
折腾了一年多,好不容易找到一点希望,最怕的就是最后因为一次操作失误把希望也送走了
0x04 主备 SPL 恢复成功,但还没结束
接下来是实际恢复,我先后恢复了 splloader 和 splloader_bak
写入之后,没有立即尝试开机,而是重新把对应区域的数据读出来,对比 SHA-256 结果一致
这至少说明,刚刚写入的数据能够按照预期从设备中重新读取
但是,一份成功的回读校验只能证明写入数据一致,不能直接证明启动程序一定能够运行
而且,我又发现了另一个需要处理的地方
uboot_b
在分析可用镜像时,我发现其中一份候选 U-Boot,与原机相关文件只有 12 字节差异,而签名块保持一致
这个发现很有意思
原本以为可能要面对一大堆互不兼容的固件,最后却发现差异缩小到了十几个字节
当然,差异少并不意味着可以完全忽略,尤其是在启动链这种对结构和完整性都比较敏感的地方
于是,我又对候选镜像进行了检查,确认相关数据后,才继续恢复 uboot_b
随后再次回读
在 PowerShell 中,我计算了回读文件的 SHA-256,并与预期值比较
他们是一致的
到这一步,关键的写入与回读检查终于完成了
剩下的,就是开机
说实话,我也不知道它到底能不能成功
毕竟此前的分析证明了很多事情,但唯独没办法提前保证这台设备一定能从头到尾走完启动流程
再完整的静态分析,最后也还是得交给真实的硬件来验证
0x05 复活吧,我的爱人!!!!!!!!!!!
2026 年 11 月 7 日
尝试启动
然后……
它真的开机了
我当时的第一反应基本上就是:
开机了!!!!!!!!!!!
紧接着,设备顺利进了 Android
但其实这时候我还有一件事情没有确认
数据呢?
因为从一开始,我就没打算靠格式化整台设备来解决问题
这台手机里还有当年使用时留下的东西
所以在确认能进入系统之后,我又检查了一下里面的数据
结果,比单纯开机成功还让人意外
东西都在
甚至连锁屏密码,都还是那年的那一个
我之前一直担心,哪怕成功恢复启动链,也可能因为其他原因无法正常访问原有系统和数据
毕竟这台设备已经躺了这么久
结果到最后,它就像是中间什么都没有发生过一样,重新回到了可以使用的状态
对于手机来说,只不过是重新执行了一遍启动流程
对于我来说,却已经过去了一年零八个月
有点恍惚
但又确实挺高兴的
0x06 写在最后
在准备重新折腾这台手机的时候,我其实没有想过一定能够把它修好
更多的是觉得,反正它都已经这样了,不如再仔细研究一次
哪怕最后还是没有成功,至少能够弄清楚之前究竟出了什么问题
结果没想到,真的让我找到了恢复的方法
以前总觉得手机坏了,大不了找个固件重新刷进去
现在看来,事情远没有那么简单
特别是在这些相对小众、固件资源又不那么容易获取的设备上
一次错误的底层操作,可能真的需要很久才能补救回来
最后还是要感谢 Auth_ 愿意分享那份备份,也感谢折腾过程中提供过帮助的人
至于这台 F21 Pro+,接下来应该还会继续被我拿来研究一些东西
不过至少现在,我可以先给它做一份完整的备份了
毕竟,已经救回来一次的东西,我实在不想再救第二次
2025.03.16 — 2026.11.07
一年零八个月
欢迎回来

杂牌机想刷机去掉广告有可能吗,会不会刷成砖,如果刷机是不是需要电脑来刷