BL锁的原理是什么?
折腾总匠手机丢了后,你无需担心艳照流失,而且一般人很难据为已用。这是靠现代信息安全技术支撑起来的,而 BL 锁是信息安全的基础,本回答将为你讲透 BL 锁的原理。
BL 即 bootloader,引导程序,我们的操作系统,不管是 PC 上的 Windows/Linux 还是移动端的 Android/ iOS,都是通过多级 bootloader 一级一级往后引导,最后才启动主系统。
如何防止主系统被人意外修改,是信息安全的基石。恶意程序(如盗号软件)要想实现目的,必然需要 root 权限,修改系统配置文件就能轻易获取最高权限;要想让盗抢的手机解除锁定(ID锁),也需要修改系统镜像才能清除系统中的防盗程序。
如果我们有办法检测系统镜像被第三方修改那怕一丁点,就拒绝启动系统,不就可以让所有非法手段失效了吗?因为引导程序 bootloader 就是厂家自己开发的,想怎么检测系统分区、要不要引导下一级系统,全由厂家说了算。
实现这个想法也不难,使用数字签名即可。大致流程是,厂家发布的系统镜像,都先经过了厂家自己的签名。bootloader 拒绝引导任何没有签名或者签名不对的系统镜像。而攻击者修改过的系统镜像(不管是 boot.img 还是 recovery.img)和第三方出品的 ROM,是不可能通过 bootloader 的签名验证的,这就给设备加了一把强大的锁,即我们常说的 BL 锁。
那 bootloader 的签名验证是怎么实现的?为什么能实现烧录镜像的精准授权?
数字签名是现代信息安全的基石,能实现比传统手写签名更好的效果(不可抵赖性更强)。每个人都可以申请一个数字证书,其中包含一对密钥:对外公开的公钥和私人密藏的私钥。这对密钥的神奇之处在于,用其中一个密钥加密的密文,只能通过另一个密钥解密。即是,如果签名者用私钥加密一份文档,任何人都可以通过公开的公钥解密出来,而且因为私钥只有签名者自己知道,全世界有且只有签名者能整出这么一份密文出来,因此具有不可抵赖性。又因为别人不可能修改文档(修改后就解密不出来了),还具有完整性(权威性)。
数字签名和验证的过程如下图所示,中间增加了哈希算法,因此具有签名大文档的能力。哈希算法是这么一个神奇的算法,它可以对任意长度的文档,快速计算出一个简短的指纹码(即哈希码)。说它是指纹码,是因为目前很难找出另一份内容有所不同、但拥有完全相同哈希码的文档(即使有也是乱码)。
有了哈希算法的加持,签名一个文档,只需要对这份文档的指纹码进行加密了,签名的效率大大提升。一份已签的文档,会包含原始文档以及签名码(即私钥加密过的哈希码)。当某人想验证这份签名文档的权威性时,只需要分离出原始文档和签名码,然后分两路计算出两个哈希码,只要两个哈希码相等,就可以认为,这份已签文档是完整的(中间没有人修改过),且一定出自签名者。
BL 锁就是借助数字签名,来实现安全引导(完整性验证)的。
作为设备厂家,我们首先要创建一对(非对称)密钥,有没有给数字证书的权威机构备案都没有关系。对于私钥,打死都不要拷贝给任何人,最好把它私钥加密并做进一个基于HASH算法的签名软件中,任何人都看不到私钥的内容,只有签名软件能读取调用。
当我们开发好一个系统镜像后,运行签名软件对整个镜像进行签名,最后会生成一个签名码,我们把这个签名码串接在系统镜像后即可,这么一个串接了签名码的镜像,就是一个授权镜像,任何没有经过我们签名软件处理过的镜像,都是非法镜像。因为只有我们的签名软件能读取私钥,第三方根据不可能计算出正确的签名码。
然后,我们把公钥放到 bootloader 代码中,并让 bootloader 在引导系统镜像之前,先做签名验证,即用HASH算法重新计算系统镜像的指纹码,并用公钥解密镜像所附的签名码,解密出来的码值理应与刚计算出来的指纹码一致,不一致就说明镜像有更改,就拒绝引导。
聪明如你,一定发现了一个严重的问题。
因为我们的公钥保存在 bootloader 中,攻击者完全可以把 bootloader 中的公钥换成它们的公钥,然后用他们的私钥来签名第三方镜像。或者更简单点,直接编译一个没带数字签名的 bootloader,烧录替换掉我们的 bootloader ,不就可以引导任何系统了?
事实上也是如此,某些手机直接用高通的 EDL 工具(通过工程线让手机进入 9008 模式)烧录无锁的 bootloader,即可把 BL 锁去掉。
问题的关键在于,不管是 bootloader 还是公钥,都存储在可被擦写的 Flash 中。如果我们能把 bootloader 和公钥都存储在不可改写的 ROM 芯片中,攻击者就无计可施了,除非把 ROM 芯片换掉,换成无锁 bootloader 的ROM芯片。而 ROM 芯片引脚少价格便宜,更换还是很容易的。
更保险的做法是,把 bootloader 和 公钥做到 CPU 中 Boot ROM 中,或者说,把第一级的引导程序 PBL 就加上签名验证功能,这样的话,攻击者唯一的手段就是换上一片同型号无锁(PBL 没带签名验证)的 CPU。这个成本是很高昴的,因为一台手机的主要成本就集成中 CPU 身上,而且 CPU 引脚密集,更换的难度较大。
但这个方案有一个大问题,就是 CPU 厂家不止服务于一家手机厂商,难道要为每个厂家都推出一个特定公钥的版本出来,仅仅是因为公钥不同?
解决方案是在 CPU 内部集成一种特殊的存储器 —— 一次性可编程存储器(OTP,写入一次即变 ROM),比如 eFuse —— 电子保险丝,一种熔丝性器件,属于一次性可编程存储器。其原理如下图,集成了保险丝一样的电阻 Rsense,CPU 出厂后,这片 eFuse 空间内所有比特全为“1”。如果向一位 eFuse 单元写入“0”,在较高电压的作用下,这个单元的电阻 Rsense 就会融断,那么就彻底变为 0 值了,再也无法回到 “1” 了。
借助 eFuse,CPU 厂家只管出一个版本(Boot ROM 中的 PBL 完全一样),手机厂家拿到 CPU 后,自己在 eFuse 中烧入公钥即可。这个公钥一旦被烧录,eFuse 自动变为 ROM,从而实现了与全 ROM 一样的效果。
某些设备厂家不需要授权管控(安全引导)怎么办?CPU 厂家可以在 eFuse 中选取一位作为开关标志(Secure Boot),出厂状态是未融断,PBL 启动时读取这个开关的融断状态决定是否要做签名验证。如果厂家不想要安全启动,就不要融断这个开关,想安全启动,就往这个位写入 0 即可。当然,开关一旦被融断,就再也不能回到无锁状态了,CPU 厂家也无法帮你。
eFuse 的容量是很有限的,有些甚至都不能完整保存下整个公钥。业内的通常做法是,eFuse 保存公钥的指纹码(较短)即可。完整的公钥可保存在容器巨大的 Flash 中,PBL 在签名验证时,会先验证 Flash 中的公钥是否被篡改(其指纹码是否与 eFuse 中的一样),只有未被篡改,才会继续往下执行签名验证。
我们知道,为了灵活性,PBL 不会直接引导主系统,而是引导 SBL(二级 bootload),SBL 再引导 ABL(LK,三级 bootload),ABL 才最后引导主系统。在这一级级的引导中,是否依然可以实现最后的安全引导?
以高通 CPU 为例,如下图,绿色部分为实现安全启动的关键机制。
SoC 的 eFuse 中固化有厂家的根CA证书公钥的哈希码,可对下一级启动程序(SBL)内容进行完整性验证——这通过验证 SBL 的数字签名实现的。在手机生产之前,厂家已经把自己的 SBL 程序用自己的私钥签名了,生产烧录时,会把 eFuse 对应的公钥、 SBL 及其签名码一并烧录到 bootloader 分区。当手机启动时,PBL 会先验证公钥的完整性,再用公钥去验证 SBL 的可信度(是否出自高通)和完整性(是否修改过),只有验证通过才会正常启动 SBL。
SBL 会做另一些初始化的工作,最后又会尝试引导下一级的 bootloader —— Little Kernel (LK)。当然,这之前需要验证下一级 BL 是否可信且完整,即是否出自 SBL 自己证书(私钥)的签名。
LK 跟 SBL 或 PLB 类似,也同样带了自己证书的公钥,因此在引导下一级系统镜像( 无论是 boot.img 还是 recovery.img)之前,也得验证镜像的可信度和完整性,只有经过自己证书签名的系统镜像,才会回正常启动。
从破解的思路看,我们把LK自带的公钥改掉,改成自己的,再用自己的私钥对系统镜像进行签名,不就可以正常启动后级系统了?不行!因为你改了LK,无论是改了其中的公钥还是改了其中程序,就会被上一级的 SBL 觉察,根本不会启动你改过的 LK。
可以看到,一级一级 bootloader(BL)构成了信任链,只要保证最初的 PLB 所用的公钥的哈希码不可更改(ROM是改不了的),就能保障最后启动的系统镜像是可信的(厂家发布的)且未经第三方修改。这种一级一级BL启动链的信任传递过程,构成了完整的 Secure Boot,也即大家口中的 BL 锁。
综上,BL 锁(Secure Boot 安全引导机制)的目的,是为了保证最终能用的操作系统一定出自厂家官方,杜绝任何非授权的系统。有了 BL 锁的加持,极客或黑客的 root 越狱提权行为才能从根源上得以杜绝,是系统安全的重要保障。BL 锁不但让越狱提权变得困难重重,也阻止了极客刷第三方系统的可能性。
不但移动设备上实现了 Secure Boot,传统的 PC 界,在 UEFI BIOS 时代到来后,也迎来了 Secure Boot 的供应链升级。只是,主板 BIOS 上的 Secure Boot 开关通常是可以关闭的。
虽然 SoC 的 eFuse 中可以一次性固化手机厂家的证书公钥(指纹),经过一级级的安全传递,手机厂家仍可以牢牢控制系统镜像的授权,但某些较温和的厂家(比如小米),仍然可以在最后一级的 BL 中放弃对最终系统的完整性验证,这就是官解 BL 锁。
一般情况下,设备的 BL 默认都是开了安全启动的(带锁),用户若想解开 BL 锁,需要按照厂家的规则提出申请,比如在没有 ID 锁定的情况下,把手机绑定一个帐号,等待若干天厂家同意后,通过厂家提供的软件,可以烧录一个不验证系统镜像签名的 BL 版本。解锁成功后,这个 BL 可以启动任何系统镜像(不局限于安卓)或第三方 Recovery。
聪明如你,一定也想到了官解 BL 锁的隐患。假如你向厂家申请了解锁,你将得到了一个官方授权且无锁的 bootloader。你把这个 bootloader 从 Flash 中提取出来,公开上传到搞机论坛上,那么,其他人也能轻易把这个 bootloader 刷到他们的手机,整个 Secure Boot 机制就这样被你轻松搞崩了!
厂家当然不会允许这种事情发生。事实上,你申请的官解 bootloader,仅在你手机上能用,其它手机大概率是用不了的。厂家只要在官解的 bootloader 中植入解锁手机的 ID(可以是 CPU ID、IMEI、MAC 或组合),上一级的 SBL 在验证完这个官解 BL 的完整性后,再查验里面的 ID 是否跟手机硬件上的 ID 一致,只有完全一致才会引导它。你手动改别人 bootloader 的 ID,改为自己手机的,就会破坏完整性,签证验证都通不过。可见,厂家也不容易,他要单独为你的 bootloader 做一次签名,还不能把签名功能放在客户端,得放在服务器才安全。一般厂家可能也不会为了给用户解锁 BL,专门弄出这么一套比较复杂的分布式程序,所以也不要骂厂家不厚道了。
还有些手机厂家出于某些目的,并没有打开 SoC 上的 Secure Boot 开关,只是在最后一级的 bootloader 上了 BL 锁。这种锁并不彻底,没有完全保证,攻击者只需要把这个 bootloader 换成无锁的 (通过更上一级的 EDL 刷机工具,如高通 9008),即可轻易破解。
如果你的设备厂家根本不支持官解,而且 CPU 也打开了 Secure Boot 开关(eFuse 不可能再关闭),还有没有办法强行解锁?
通过分析 BL 锁的原理可知,整条 BL 启动的信任链虽然设计得很巧妙,但绝非无懈可击。只要是软件,就会有 bug,毕竟程序员不可能考虑到所有场景的所有可能性;有 bug 就能充分利用,就能想尽办法绕过数字签名的验证过程,直接引导后级 BL 或系统,从而瓦解整条信任链。
整条安全启动链,要经过三级引导,只要有一级 BL 出现 bug,我们就能攻破 BL 锁跳过签名验证,直接引导无签名的系统,实现第三方系统镜像的刷机或 root。这就是传说中的 BL 锁破解。
例如 iOS 上著名的 checkmate 漏洞,就是 Boot ROM 中的代码有 bug,利用这个 bug ,就可以绕开签名验证,最终引导另外一个非苹果管控的操作系统(比如魔性版 iOS 甚至 Android)。联发科的芯片,也曾经出现过不少 BootROM 漏洞,比如 amonet 和 kamakiri 漏洞。
而后两级的 Bootloader,虽然太多都是闭源代码,且跟特定硬件绑定,很难进行逆向工程,但也不是完全牢不可破。比如高通旧版的 LK 系统,就存在 CVE-2014-9798 漏洞。
加州大学圣芭芭拉分校的研究人员研究了多家主流芯片厂商的安卓 bootloader ,从中发现了多个漏洞,如下表,这些漏洞可导致引导信任链被攻破,启动任何未授权的系统。他们甚至还开发了一个名为 BootStomp 的扫描工具,来专门甄别各家 BL 的潜在漏洞。
不可否认,随着一个个已知漏洞被陆续封堵,功能单一的 Bootloader 被变得越来越安全,破解 BL 锁将变得越来越费劲。
至此,相信你已经彻底理解了 BL 锁的原理。也许你还在纠结我一开始抛出的艳照流失和盗抢手机据为已用的话题,文中那是只字未讲,只因为,虽然内容相关但离题太远。你可以从下面这篇回答中获得这些问题的详尽的答案。
技术文章创作不易,如果本文对你有帮助,请点赞收藏加关注,我是折腾总匠,喜欢从第一性原理讲解一些有趣的技术,欢迎关注,让我们一起探讨学习,一起驰骋于浩瀚的知识海洋。
版权所有,禁止任何形式的转载!
本文参考自: