Android解锁与root

一、Android解锁

1.1 解锁的含义

Android设备解锁BootLoader或者简称为解BL锁。解 BL 锁是刷机的前提条件,通常情况下,一旦某个设备无法解锁 BL,基本上就无法在这个设备进行刷机了。

1.2 什么是 BootLoader

Bootloader 是负责启动计算机的软件。计算机开机的时候,会执行一个相对较小的程序来初始化内存、外设等启动后续操作系统必备的资源,并最终启动用户所使用的操作系统(如 Windows, Android 等);这个程序就是 BootLoader。

操作系统负责管理设备的硬件资源;而BootLoader 是用来启动操作系统的。BootLoader 一个核心的功能就是,确保启动一个可信的操作系统。另外,当设备的操作系统出现问题时,BootLoader 还可以引导启动另外一个正常的可信系统来执行恢复;所以,BootLoader 另外一个功能重要功能就是恢复系统。

1.3 BootLoader启动流程

具体来说,BootLoader 是如何实现这两大功能的呢?以高通设备为例,我们看一下 BootLoader 的启动流程:

1.3.1 PBL (Primary Boot Loader)

当我们按下电源键启动手机的时候,CPU 上电之后开始运行;它最开始运行的代码是 CPU 芯片厂商提供的,写死在某个只读存储上,这段代码一旦出厂便不可更改,我们通常称之为 BootROM 或者 PBL (Primary Boot Loader);PBL 的主要功能是上电自检并启动下一个组件 SBL

1.3.2 SBL(Secondary Boot Loader)

这个 SBL 主要是初始化一些硬件环境(如DDR, clocks 和 USB 等)和代码安全环境 (TrustZone),当然,最重要的还是验证并加载下一个组件——ABL(Android Boot Loader,也叫 aboot)。与 PBL 不同,SBL 程序一般存放在 eMMC 上,这个地方是可以被修改的,因此它可以被刷写和升级。正因如此,SBL 还承载着最底层的恢复设备的重任;我们常说的高通 9008 模式(全称 Emergency Download Mode)就运行在这里。9008 模式,本质上就是强制刷写设备的 eMMC 存储,因此不论你上层操作系统或者应用软件被破坏成什么样,除非硬件损坏,基本上都可以救回来。

为啥要整个 SBL,直接 PBL 一把干完不行吗?实际上,PBL 是芯片相关的,芯片无法预知到它用什么外设,因此这两个阶段被解耦了。

1.3.3 ABL(Android Boot Loader)

SBL 执行完之后会验证并加载 ABL,ABL 的主要功能是从设备验证并加载 bootimg 然后启动 Linux Kernel 进而启动用户操作系统,根据选择的不同,可能会进入到 Android 系统或者 Recovery 模式。ABL 还有一个很重要的功能,它提供了一个 fastboot 协议,用户可以用 PC 通过 USB 连接设备,通过这个 fastboot 协议控制设备;我们通常所说的「线刷」,小米的兔子界面以及我们通过命令行工具 fastboot 刷机实际上就是运行在 ABL 下。正因 ABL 功能比较复杂,它内部其实运行着一个 mini 的操作系统,这个操作系统就是 lk(Little Kernel),Trusty TEE 可信执行环境下的操作系统也是基于 lk 的。

1.3.4 Linux Kernel

ABL 启动 Linux Kernel 之后,内核最终会进入用户态执行 init,init 进而启动 ueventd, watchdogd, surfaceflinger 以及 zygote 等;zygote 启动之后 fork system_server 并启动各种 binder 服务,系统核心 binder 服务启动之后会启动 Launcher 桌面,这样整个系统就启动完毕了。

1.4 BootLoader恢复功能

从上述 BootLoader 启动过程,我们可以很清楚地知道,BootLoader 的恢复功能体现在 SBL 阶段的恢复模式以及 ABL 阶段的 fastboot 线刷模式。实际上,在我们手机底层软件出现问题之后,不论是自己救砖还是去售后,基本都是用的这两种模式。

1.5 BootLoader验证可信系统

上面我们多次提到了验证并加载。BootLoader 的各个启动过程串起来就是一个启动链,这个启动链的各个阶段在进行过渡和跳转的时候是需要进行验证的。也就是说,上一阶段在启动下一阶段的时候,会验证下一阶段的代码是否可信;只有在验证通过的情况下,整个启动过程才会继续进行。在计算里面,这个验证的过程实际上就是比对数字签名。

如果 BootLoader 的每一个阶段都严格验证数字签名,在代码逻辑都正确的情况下,用户是无法通过 BootLoader 去加载一个修改过的第三方系统的(也就是无法刷机)。

解锁 BootLoader 实际上就是让 BootLoader 启动链上某些阶段的签名验证不生效。如果让 BootROM 不验证 SBL,那我们就可以任意加载 XBL 从而接管接下来的操作流程如 TEE,lk, Linux Kernel;如果让 SBL 不验证 ABL,那我们就可以任意加载 ABL 从而接管 lk 和 Linux Kernel;如果让 ABL 不验证 boot.img,我们就可以控制 Linux Kernel。在现实场景中,人们最需要的就是刷入自定义 boot.img,毕竟这是用户能接触到的最上层系统 Android 的一部分。修改 TEE 和 LK 理论上不是不可以,但是修改这部分人们感知不强,并且通常这部分组件并不开源,也让很多人无从下手。因此实际上,我们通常所说的解锁 BootLoader 特指让 ABL(aboot) 在加载 bootimage 时不进行验证。

某些设备厂商提供了解锁功能,实际上就是通过某种方式关闭了 ABL 中对 bootimage 的加载验证。

小问题:镜像远大于内存的情况下,如何计算镜像的数字签名呢

1.6 BootLoader确保信任根受信

想办法篡改这个签名,那不是就可以解锁了?比如我们可以这样操作:把 bootimage 修改并用自己的签名,然后把 ABL 中存放签名的地方暴力改成我们的签名;这样 ABL 在校验签名的时候就会通过。但问题是,如果我们要修改 ABL 中存放签名的地方,势必要修改 ABL,那么 SBL 在加载 ABL 的时候就会验证签名不通过;这样的话,我们继续修改 SBL,然后把 PBL 中存签名的地方改掉?看起来或许可以。实际上,整个启动链之所以能保障安全,是因为它的信任传递机制——正因为第一个角色可信,第二个角色才可信,并一步步向下传递。如果有办法破坏掉启动链的第一个角色,那就破坏了整个信任链。所以,在 BootLoader 启动过程中,PBL(BootROM) 所持有的签名是所有安全的基石,也即信任根(Root of Trust)。在 BootLoader 中,有两个机制确保信任根受信:

  1. BootROM 的代码存放在只读存储器中,一旦出厂不可更改。

  2. 下一阶段的可信数字签名存放在独有的硬件设备之中(eFuse,一次性可编程存储器),一旦写入就会被破坏(三星设备解锁之后会「熔断」指的就是类似特性)。

因此,如果所有的组件都按照理想情况下工作,我们就无法更改 BootROM 所持有的信任根,进而无法破坏启动过程中的信任链,也就无法解锁设备。

当然,一切建立在所有的代码都正常工作的条件下。一旦某个阶段的代码有漏洞,那我们就有希望突破信任链,进而强制解锁设备。

事实上,这种漏洞并非天方夜谭。iOS 上著名的 checkmate 漏洞就是 BootROM 中的代码存在问题,通过这个漏洞人们可以越狱设备。

如果设备提供商偷懒,并没有完整地实现整个安全启动链,那也是可能强制解锁的。比如老的华为设备,其解锁码存放在 proinfo 分区下,这个分区是可以被刷写的;因此你可以拿别的设备的解锁码和 proinfo 分区刷入直接通过验证。还有,曾经的 vivo 对 bootimage 的验证并不严格,用户自定义一个 fastboot 就可以直接解锁。

总体来说,如果想绕过限制强制解锁,基本上只有非常规手段

小问题:解了BootLoader锁的Android手机,如果不慎丢失,里面的个人隐私资料会被轻易获取吗?

二、Android root

通常来说,我们给手机解锁 Bootloader 就是为了获取 Root 权限。

2.1 root是最高权限

在类 Unix 系统中,root 是在所有模式(单用户或多用户)下对所有文件和程序拥有所有权利或许可的用户的名称。

现代操作系统(本文主要讨论 Android 系统,下同)一般都是多用户的,那个名为 root 的用户所拥有的权限就是 root 权限

在类 Unix 系统中, 一切皆文件。而这些文件通常以一个分层的树形结构在文件系统中呈现,每一个文件都有一个父目录,而那个最顶层的父目录被称之为根目录(root directory);root 用户之所以被称之为 root,大概是因为它是唯一能修改 root directory 的用户。

因为 root 用户拥有最高权限,因此它也通常被称之为超级用户(superuser);在类 Unix 系统中,每一个用户都有一个 ID,root 用户的 ID 是 0,从传统意义上讲,uid 为 0 就是 root 用户,也就拥有最高权限。

2.2 最高权限具体指的哪些?

手机是由多个零部件组成的,比如说,CPU、内存、闪存、各种硬件设备(如相机,屏幕、传感器等),所谓最高权限,就是对所有这些设备的控制权。

对于 CPU 来说,现在的 CPU 芯片一般都有不同的特权等级,这些不同的等级可以执行不同的指令。

经典x86处理器的Ring0~Ring3:

AArch64 构架来说,CPU 有四个特权等级,EL0 ~ EL3:

在不考虑 Secure World 的情况下,EL0 就是通常所谓的用户空间,应用程序一般运行在 EL0 级别,操作系统(Linux 内核及驱动)运行在 EL1,EL2 上运行的则是虚拟化相关程序,EL3 则运行管理 Secure World 和 Normal Wrold 的 Secure Monitor。

从严格意义上来说,既然 root 权限意味着最高权限,这应该代表着它可以在 EL0 ~ EL3 中的任意 level 上执行任意的 CPU 指令。然而,当前的各种 root 实现并非如此,它们一般能在 EL0 上执行任意指令,在某些情况下可以在 EL1 上执行任意指令;更高的特权等级就不行了。因为 root 用户是操作系统的概念,因此 root 权限顶多是操作系统中的最高权限;在类 Unix 系统中,它仅能触及 EL1 也就不算奇怪了。

对于内存、闪存以及各种外设来说,它们一般由操作系统内核和驱动来管理,而内核和驱动运行的指令通常位于 EL1,因此,root 权限意味着对所有的硬件(不包括 TEE 相关硬件)和外设拥有完全的控制权。

总结一下就是,root 权限所拥有的最高权限,是我们的用户操作系统能管理的所有权限,包括各种硬件和外设以及一部分 CPU 指令的执行权限。

2.3 实现 root 的各种方法

实现 root 的方式整体上可以分为两种:

  1. 解锁 Bootloader,通过修改 Android 系统的某一部分实现 root。

  2. 通过某些系统漏洞提取,进而获取 root 权限。

解锁 Bootloader 实际上就允许我们刷入第三方或者被修改过的操作系统;如果我们可以解锁 Bootloader,那么理论上讲我们就可以任意修改其操作系统,而 root 权限只不过是操作系统的某种机制,因此获取 root 权限自然不在话下。而这种修改方式常见的如下:

  1. 通过直接刷入第三方系统实现;在这个第三方系统中,系统自带 root 权限。

  2. 通过修改原系统的init 实现;因为 init 进程是 Linux 系统的第一个进程,因此它实际上就以 root 身份执行的;通过修改 init 也可以实现 root 访问;Magisk 就是通过代理 init 实现的 root 权限。

  3. 通过自定义内核实现;因为 root 权限实际上是内核操控的,因此自定义内核然后刷入自然可以获取 root 权限。

如果我们不能解锁 Bootloader,那么可以通过系统漏洞来提权,进而拥有 root 权限。在远古时代(特别是 Android 6.0 以前),各种一键 root 满天飞,比如 kingroot,360 一键 root,他们本质上都是通过系统漏洞来获取特殊权限;然而,随着 Android 系统的演进,这种通过漏洞提权获取 root 的方式已经很难出现在普通的大众视野里面了。

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值