导语:高通公司是非苹果智能手机的主要市场硬件供应商,考虑到他们生产的[SoC]占主导地位,进行逆向并接管其引导链,以便在执行过程中拥有最高特权的组件变得越来越有趣,最终目标是能够使用闭源或未记录的组件(例如硬件寄存器或受信任的执行环境软件)进行实验。
高通公司是非苹果智能手机的主要市场硬件供应商,考虑到他们生产的[SoC]占主导地位,进行逆向并接管其引导链,以便在执行过程中拥有最高特权的组件变得越来越有趣,最终目标是能够使用闭源或未记录的组件(例如硬件寄存器或受信任的执行环境软件)进行实验。
分析研究
我研究了一段时间高通公司生产的启动链并完成了以下任务:
· 获得最高特权级别(EL3)来执行代码;
· 转储高级特权组件,例如bootROM或Primary Boot Loader(PBL),Secondary Boot Loader(SBL)并对其进行逆向;
· 接管boot chain;
· 研究高通的安全监控器和未记录的安全寄存器,例如“ XPU”寄存器。
我使用了两种不同的手机型号进行这项研究:Google Nexus 6P和诺基亚6。
如上所述,鉴于Qualcomm硬件的普及程度,许多人已经在研究Qualcomm组件了。特别是,Aleph Security发布了一系列5篇博客文章(aleph aleph2 aleph3 aleph4 aleph5)(以及其工具),描述了他们如何接管诺基亚6引导链并编写了调试器,这些博客文章是我工作的基础。
首先给出了安全启动过程的一般概述,尤其是高通公司使用的过程,然后使用Aleph Security的工具,我将转储Nexus 6P和诺基亚6 bootrom,以便在其中执行代码并注入少量代码。
本节还将说明Aleph Security提供的paylaod所遇到的困难,以及我如何解决这些困难。在将控件传播到引导链的下一个阶段之后,我修补了Qualcomm安全执行环境,添加了一个Hook,为我提供了最高特权级别EL3中的读/写原语。最后,我将简要讨论XPU寄存器。
Context
Armv8 异常级别
Armv8系统具有多个特权级别,称为异常级别或EL,范围从EL0到EL3。异常级别数越低,它具有的特权就越少,此外,借助TrustZone技术提供的软件和硬件隔离,Arv8可以区分“ 非安全”和“ 安全”异常级别。
Armv8.4和更高版本增加了以前缺少的Secure EL2异常级别。
安全启动
总体概述
安全启动链是每个阶段加载,验证(例如使用RSA)然后执行下一个阶段的链。第一步,bootROM是隐式受信任的,因为它通常存储在CPU裸片上,虽然对其进行修改在理论上可能是可行的,但它不可扩展。
完整的可信组件链:
根据Qualcomm安全启动和映像身份验证技术概述文档[QualcommSB],二进制身份验证的设计大致如下:
供应商发出根证书,保留自己的私钥并在bootROM中使用公钥。由于必须隐式地信任它,因此其公钥的哈希存储在硬件中,以确保不会被篡改。
该证书可以签署另一个证书,或直接对签名进行身份验证。最终结果是一个证书链,不同的参与者可以在其中签名系统的各个子组件。
高通的安全启动链
设计
非三星设备上的Qualcomm安全启动链的设计如下:
· BOOTROM,也称为PBL(主引导加载程序),是要由CPU执行的第一部分;
· 下一个组件SBL(辅助引导加载程序)在较旧的硬件版本中曾经被划分为SBL1,SBL2和SBL3:
· XBL(扩展的引导加载程序);
· SBL的负载安全监控和QSEE(QTEE),并在EL3执行。它还加载aboot(现在是ABL,都代表Android Boot Loader)并在EL1中执行;
· aboot(或ABL)加载常规OS或其恢复版本;它可以与一台PC经由USB使用也进行通信 FASTBOOT协议。
EDL
更重要的是,如果满足以下条件之一,则PBL(bootROM)可以执行一种恢复模式,称为 紧急下载模式(EDL):
· SBL损坏和/或其版本无效;
· 板上的特定测试点已缩短;
· 系统将重新引导,并指定bootROM需要转换为EDL模式(实现细节因一个SoC而异)。
进入EDL时,bootROM等待PC发送命令。在这些命令中,一个特别有趣的命令用于通过USB发送签名的图像,为了减轻此任务,Aleph Security开发了一个名为firehorse的工具。
EDL图像(“编程器”)具有以下属性,其中包括:
· 根据手机型号,互联网上可以提供一些签名的图像;
· 程序在EL3中执行;
· 有任意的读写命令(peek和poke)。
利用Nexus 6P
谷歌Nexus6P手机由谷歌和华为共同开发,到2015年它的SoC发布是MSM8994。
进入EDL模式
在此手机上,访问EDL模式相当简单。将手机降级到2017年12月之前的版本就足够了,这很简单,因为Google本身会为你提供所需的图像和说明[OTA]。
植根后,只需执行以下命令即可访问EDL模式:
echo 1 > /sys/module/msm_poweroff/parameters/enable_edl adb reboot edl
转储BootROM(PBL)
设备进入EDL模式后,它将自己标识为 Qualcomm HS-USB 9008,并且bootROM等待命令。
然后,PC必须与电话进行通信以发送签名的 EDL图像,使用Aleph的工具firehorse(它是高通官方工具的包装),命令是:
firehorse -c COM3 -t angler fw hello
假设电话映射到COM3,并且EDL图像在其正确位置。
通过Aleph博客知道了bootROM的地址,转储bootROM(PBL)很简单:
firehorse -c COM3 -t angler fw peek 0xFC010000 0x20000 pbl.bin
bootROM会被镜像到物理地址0。
获得代码执行
一旦可以与EDL进行交流,就可以使用poke命令在任何地址处进行写操作,如Aleph第三篇博客文章aleph3中所述。使用功能强大的原语,可以将代码直接注入堆栈中。
但是,在Aarch64 EDL上,SCTLR_EL3.WXN是一种缓解此类尝试的保护措施。
解决此问题的一种方法是使用ROP。但是,aleph的ROP链似乎在我的测试中不起作用,因此我决定尝试通过修改页表条目尝试其他方法。通过将包含我的代码的1GB区域映射为只读,随后可以使我的代码可执行。此外,由于将不使用虚拟地址范围,因此不需要TLB(转换后备缓冲区)刷新。
使用firehorse代码库,可以得出:
addr = 0xFC100000 path = r"hooks.bin" target = t.get() ttbr0 = target.page_table_base FH_FW.upload64(addr, path) I("uploaded payload") FH_FW.poke64(ttbr0, 0xC0000611) # AP=0b10, read only; map 1GB from 0xC0000000 to VA 0 FH_FW.poke64(target.saved_lr_addr, addr + 4 - 0xC0000000) # jump to our code at addr
已经尝试在获得代码执行后立即禁用SCTLR_EL3.WXN,不幸的是,这没有用。
因此,我必须使用以下gadget禁用MMU:
.text:00000000F803DF38 loc_F803DF38 ; CODE XREF: write_sctlr+C↑j .text:00000000F803DF38 01 10 1E D5 MSR SCTLR_EL3, X1 .text:00000000F803DF3C .text:00000000F803DF3C locret_F803DF3C ; CODE XREF: write_sctlr+14↑j .text:00000000F803DF3C C0 03 5F D6 RET
完成此操作后,现在可以尝试接管Nexus 6P的启动链。
接管引导链:首次尝试
鉴于此,在Google Nexus 6P上,bootROM正在执行Aarch32代码(即32位),而EDL是64位映像,我需要将CPU重置为Aarch32模式。
因此,我尝试将复位地址写入bootROM用来设置64位入口地址0xF900D07C的同一硬件寄存器 ,然后使用标准Armv8寄存器RMR_EL3复位CPU。
但是,经过一些测试,结果证明这是行不通的:
· BootROM镜像到物理地址0;这可能意味着Aarch32复位向量在地址0处进行了硬编码;
· 只是在不尝试更改入口地址的情况下重置CPU也不起作用;这可能表明存在一些奇怪的硬件问题。
逆向 Nexus 6P BootROM
bootROM(也称为PBL)的执行从地址0xFC010000开始,该地址直接跳转到0xFC010050,然后 跳转到0xFC010054。
对应以下代码:
RAM:FC010754 50 0F 0D EE MCR TPIDRURW, R0 RAM:FC010758 90 1F 0D EE MCR TPIDRPRW, R1 RAM:FC01075C B0 0F 10 EE MRC R0, MPIDR RAM:FC010760 0F 00 00 E2 AND R0, R0, #0xF RAM:FC010764 00 00 50 E3 CMP R0, #0 RAM:FC010768 5B 00 00 1A BNE loc_FC0108DC RAM:FC01076C 48 03 9F E5 LDR R0, =0xFC010000 RAM:FC010770 10 0F 0C EE MCR VBAR, R0 RAM:FC010774 44 13 9F E5 LDR R1, =0xFC400204 RAM:FC010778 00 00 91 E5 LDR R0, [R1] RAM:FC01077C 01 00 80 E3 ORR R0, R0, #1 RAM:FC010780 00 00 81 E5 STR R0, [R1] RAM:FC010784 38 13 9F E5 LDR R1, =0xFC400208 RAM:FC010788 00 00 91 E5 LDR R0, [R1] RAM:FC01078C 01 00 80 E3 ORR R0, R0, #1 RAM:FC010790 00 00 81 E5 STR R0, [R1]
bootROM首先将每个线程寄存器(这里似乎用作暂存寄存器)的TPIDRURW和TPIDRPRW设置为r0和r1 ,用于不正确的重置。
bootROM会检查执行代码的处理器的核心ID是否为0,如果不是,则跳至无限循环。
然后,它将异常向量基数设置为0xFC010000,并设置一些其他硬件寄存器,接下来是引导过程选择。
始于:
RAM:FC010794 2C 03 9F E5 LDR R0, =0xFC401780 RAM:FC010798 00 00 90 E5 LDR R0, [R0] RAM:FC01079C 02 08 10 E3 TST R0, #0x20000 RAM:FC0107A0 0C 00 00 0A BEQ loc_FC0107D8 RAM:FC0107A4 20 03 9F E5 LDR R0, =0xFC4BE0F0 RAM:FC0107A8 00 00 90 E5 LDR R0, [R0] RAM:FC0107AC D1 15 00 E3 MOV R1, #0x5D1 RAM:FC0107B0 01 00 50 E1 CMP R0, R1 RAM:FC0107B4 03 00 00 0A BEQ loc_FC0107C8 RAM:FC0107B8 10 03 9F E5 LDR R0, =0xFC4017C0 RAM:FC0107BC 00 00 90 E5 LDR R0, [R0] RAM:FC0107C0 01 00 10 E3 TST R0, #1 RAM:FC0107C4 03 00 00 0A BEQ loc_FC0107D8 RAM:FC0107C8 RAM:FC0107C8 loc_FC0107C8 ; CODE XREF: _init+60↑j RAM:FC0107C8 04 03 9F E5 LDR R0, =sub_FC010040 RAM:FC0107CC A3 00 00 EB BL SetVbar RAM:FC0107D0 00 03 9F E5 LDR R0, =0xFE800000 ; func RAM:FC0107D4 71 2E 00 EB BL resetToAa64
意味着:
(((* (vu32 * )0xFC401780 & 0x20000 ) && (* (vu32 * )0xFC4BE0F0 == 0x5D1 || (* (vu32 * )0xFC4017C0 & 1 ) == 1 ))
也就是说,使用这两种复位方法,如果在安全寄存器中将掩码0x20000设置为0xFC401780(默认情况下不是),则bootROM将异常表设置为无限循环,并立即在Aarch64模式下复位为0xFE800000。这似乎称为 不正确的重置。
所有涉及的3个寄存器都是可写的(或者在HWIO_GCC_RESET_STATUS_ADDR的情况下 ,可以触发看门狗复位)。
然后:
RAM:FC0107D8 FC 02 9F E5 LDR R0, =0xFC102080 RAM:FC0107DC D3 F0 21 E3 MSR CPSR_c, #0xD3 RAM:FC0107E0 00 D0 A0 E1 MOV SP, R0 RAM:FC0107E4 DB F0 21 E3 MSR CPSR_c, #0xDB RAM:FC0107E8 00 D0 A0 E1 MOV SP, R0 RAM:FC0107EC D7 F0 21 E3 MSR CPSR_c, #0xD7 RAM:FC0107F0 00 D0 A0 E1 MOV SP, R0 RAM:FC0107F4 D3 F0 21 E3 MSR CPSR_c, #0xD3 RAM:FC0107F8 00 C0 A0 E3 MOV R12, #0 RAM:FC0107FC 0C 30 A0 E1 MOV R3, R12 ; ............................... boilerplate ..................................
这意味着在上述以外的任何其他情况下,将设置每种Aarch32执行模式的堆栈,并将r3至r12设置为0。
此外:
RAM:FC010860 78 02 9F E5 LDR R0, =0xFC4BE034 RAM:FC010864 00 10 90 E5 LDR R1, [R0] RAM:FC010868 40 00 11 E3 TST R1, #0x40 RAM:FC01086C 02 00 00 1A BNE loc_FC01087C RAM:FC010870 6C 02 9F E5 LDR R0, =sub_FC010060 RAM:FC010874 79 00 00 EB BL SetVbar RAM:FC010878 68 F2 9F E5 LDR PC, =0xFC100000
如果(0xFC4BE034&0x40)为true,则bootROM将异常向量表设置为无限循环,然后跳转到0xFC100000。有关的寄存器是只读的,可能是保险丝寄存器(使用的寄存器似乎与保险丝有关,并参与确定是否启用安全启动)。
最后:
RAM:FC01087C loc_FC01087C ; CODE XREF: _init+118↑j RAM:FC01087C E7 40 00 EB BL initsysregs RAM:FC010880 64 02 9F E5 LDR R0, =main RAM:FC010884 10 FF 2F E1 BX R0 ; main
引导过程继续:进一步的系统寄存器被初始化,然后代码跳至主函数。
在进行了一些其他初始化之后,主函数执行一个函数列表,将相同的单例实例传递给所有函数,有很多功能,但是最著名的功能决定是否进入EDL模式:
· 如果缩短了EDL测试点,则转到EDL;
· 如果某些保险丝有特定的位设置,请转到EDL;
· 如果由Android内核编写的0xFE87FFE0处的三个单词是0x322A4F99 ``0xC67E4350 ``0x77777777,请转到EDL。
接管引导链:使用小型调试器进行第二次尝试
从上面可以看出,通过写0x5D1到0xFC4BE0F0和设置 地址0x20000到0xFC401780和地址0x20000,然后重启系统,我获得早期EL3 Aarch64代码执行。
但是,没有办法重新执行bootROM(这是Aarch32代码)来获得EL3 Aarch32代码执行。
但是,我对Armv8架构进行了以下考虑:
· 较高的Aarch64异常级别可以将较低的异常级别设置为在Aarch32模式下执行;
· 实际上,无论异常级别如何,Aarch32中的所有系统寄存器都以相同的方式编码;
· 如果s-EL1之上的一个异常级别是Aarch64,则安全异常级别的自调试会更容易。
因此,我想到了以安全EL1模式执行Nexus 6P bootROM的想法。这使我能够在安全EL1中启用调试异常,从而将硬件断点放置在bootROM上。
这需要以下步骤。
首先将s-EL1设置为Aarch32:
// Clear NS bit, next exception level is a32, enable smc mrs x0, scr_el3 bic x0, x0, #(1 << 10) bic x0, x0, #(1 << 7) bic x0, x0, #1 msr scr_el3, x0
然后启用调试功能,并使其能够使s-EL1处理s-EL1调试异常:
// Disable OS lock mov x0, xzr msr osdlr_el1, x0 msr oslar_el1, x0 // Disable any kind of EL2 trapping msr mdcr_el2, x0 // Enable secure breakpoints mrs x0, mdcr_el3 bic x0, x0, #(1 << 16) orr x0, x0, #(3 << 14) msr mdcr_el3, x0 // SPIDDis=0, MDBGen=1, KDE=1 mrs x0, mdscr_el1 bic x0, x0, #(1 << 16) orr x0, x0, #(1 << 15) orr x0, x0, #(1 << 13) msr mdscr_el1, x0
然后,代码跳转到设置硬件断点的Aarch32代码,并最终执行bootROM(要特别小心以确保不替换异常向量库)。
断点用于以下目的:
· 让我的Aarch32代码继续执行(从MMU表属性中删除NX位,防止VBAR被替换);
· 使其似乎已禁用安全启动;
· 使用smc指令跳回到EL3 ,然后执行SBL。
一旦命中断点,便会对其进行设置和处理。
我得到以下结果:
· bootROM正常的bootpath 可以很好地与该方法配合使用,在预期的情况下,控制权会转移回EL3。
· 但是,由于某些未知的硬件原因,系统根本无法跳转到SBL!
· 尝试调试EDL路径会导致类似的问题。
简而言之,该方法行之有效,但有一些问题仍未解决。
利用诺基亚6
鉴于我在Nexus 6P上的工作已经过时,我决定尝试另一部手机:诺基亚6,其bootROM和EDL编程器(可在网上找到)都在Aarch32中运行,因此Nexus 6P不会遇到硬件问题。
进入EDL模式
与Nexus 6P相比,在诺基亚6上访问EDL模式要困难得多:
· 没有简单的方法可以访问它,例如,没有adb reboot edl;
· 有一种方法可以通过缩短D +引脚的USB将SBL重新引导到EDL,但是我不小心将手机更新到了9.0;
· 没有任何官方方法可以“解锁手机的引导加载程序”,否则将有助于研究破坏SBL分区。
缩短EDL测试点:
步骤如下:
· 使屏幕周围的胶水融化(耗时超过30分钟);
· 卸下约18颗螺钉访问主板;
· 临时焊接以查看是否可以访问EDL模式;
· 通过按钮开关将EDL测试点链接在一起的最终焊料;如果激活了该开关,则电路闭合并且测试点缩短,从而使bootROM采用EDL引导路径。
还检查了板上的UART引脚(SBL广泛使用UART),但是,不幸的是,好像我使用的手机上的UART端口已被移除。
获得代码执行
这非常简单,甚至比Nexus 6P更容易,因为0x08000000的页面是RWX。因此,我将paylaod上传到该地址,并更改了返回地址(位于0x0805CFDC)。
接管引导链
一旦完成代码执行,就很容易接管启动链,因为bootROM和编程器都是Aarch32代码。
接管BootROM(PBL)
定位bootROM并在地址0x00100000处执行。
我在这里采用了类似于Aleph的方法:
· 将bootROM复制到缓冲区中;
· 修补副本;
· 使用副本重新映射副本(副本具有适当的补丁以保持地址转换有效);
· 运行副本。
修补程序如下:
· 保持地址转换映射有效,确保复制的执行;
· 禁用测试点检查,以便bootROM不会尝试一遍又一遍地进入EDL;
· 将SBL挂钩插入到主要功能列表中。
接管SBL(辅助引导加载程序)
将SBL Hook插入bootROM副本后,我对SBL进行了以下修补:
· 在SBL级别停用安全启动(图像验证和身份验证);
· 注入下一个QSEE(安全监视器)和aboot(Android引导程序)Hook。
修补QSEE和Aboot并与PC通信
接管SBL后,我可以修补安全监视器并在加载它们时进行引导。
对于QSEE,我在“来自较低Aarch32异常级别的同步异常”异常向量上添加了一个Hook,我可以添加通过smc 指令访问的任意EL3读/写原语。
在aboot方面,修补程序如下:
· 实施新的fastboot命令,将上述读取/写入原语公开给PC;
· 使它认为安全启动已禁用,这可以使引导加载程序无需解锁密钥即可解锁。
最终结果是我可以在系统运行时从fastboot读取/写入EL3内存:
学习XPU寄存器
由于我现在可以读写EL3存储器,因此现在终于可以与XPU寄存器进行交互了,而XPU寄存器则没有任何公开文档。
XPU错误处理程序是安全监视器的一项特殊功能,它引用“ ERROR:MPU分区重叠!”,其中包含许多调试字符串和有关XPU寄存器的信息。
具有XPU单元的硬件设备列表
有大量的结构实例,其中包含诺基亚6上各种XPU单元的名称和地址。
列表如下:
· IPA_BAM_NDP, base XPU regs address at 0x7902000
· IPA at 0x38000
· A5X_XPU at 0x1C61000
· Q6PCNOC_CFG at 0x32000
· SDC1_SDCC_ICE at 0x7806000
· LPASS_TOP at 0xC064000
· TLMM at 0x1300000
· TCU at 0x34000
· QDSP at 0x37000
· IMEM_MPU at 0x53000
· GPS at 0x36000
· MCDMA at 0x35000
· BOOT_ROM at 0x1FF000
· VENUS0 at 0x1DF0000
· TCSR_REGS at 0x1936000
· SEC_CTRL_APU at 0xAE000
· RPM_APU at 0x287000
· MSS at 0x4000000
· MPM2 at 0x4A7000
· CLK_CTL at 0x1880000
· SNOC_CFG at 0x2D000
· PCNOC_CFG at 0x2E000
· PMIC_ARB at 0x200E000
· WCSS_APU at 0xA21F000
· DEHR at 0x4B0000
· CRYPTO0_BAM at 0x702000
· BAM_BLSP2_DMA at 0x7AC2000
· BAM_BLSP1_DMA at 0x7882000
· BIMC_MPU_0 at 0x44A000
XPU寄存器结构
通过查看安全监视器中与XPU寄存器有关的功能表,然后对其进行逆向,我发现了所有XPU单元共享的大多数结构。
每个XPU单元都有相同类型的寄存器,控制寄存器组成前0x200字节,然后有可变数量的保护区域寄存器组(每个组的大小为0x80字节)。
一共有3组控制寄存器(每组大小均为0x80),依次为:安全,不安全和“ MSS自认证”(目的仍然未知)。第一个控件控制安全空间的访问(包括对寄存器本身的访问),第二个控件控制正常空间的访问。
typedef struct XpuControlRegisterSet { // Some regs are only in the secure block, // some others only in the nonsec block (like UMR_*, REV_*), some in both... u32 CR; // 0. "Control register"? u32 WDR; // 4 u32 PRTN_RACR_SHADOW0; // 8. only for some types of devices (like BootROM) u32 unk_0c; u32 PRTN_START_SHADOW0; // 0x10. same u32 unk_14; u32 PRTN_END_SHADOW0; // 0x18. same u32 unk_1c; u32 RPU_ACR0; // 0x20 unk_24, unk_28, unk_2c, unk_30, unk_34, unk_38, unk_3c; /* ============Error registers============ */ u64 EAR0; // 0x40 u32 ESR; // 0x48 u32 ESRRESTORE; // 0x4C u32 ESYNR0; // 0x50 u32 ESYNR1; // 0x54 u32 ESYNR2; // 0x58 /* =========End of error registers========= */ u32 unk_5c; u32 UMR_RACR; // 0x60 u32 UMR_WACR; // 0x64 u32 unk_68, unk_6c; u32 UMR_CNTL; // 0x70. nonsec only u32 IDR0; // 0x74. sec only? "Interrupt Description Register 0"? u32 IDR1; // 0x78. sec only? "Interrupt Description Register 0"? u32 REV; // 0x7c } XpuControlRegisterSet; typedef struct XpuProtectionRegisterSet { u32 RACR0; // 0x00 u32 unk_4[7]; u32 WACR0; // 0x20 u32 unk_24[7]; u64 START0; // 0x40 u64 END0; // 0x48 u32 SCR; // 0x50 u32 MCR; // 0x54 u32 CNTL0; // 0x58, only on some. Bit31: mpu partition disabled u32 CNTL1; // 0x5C, same u32 unk_60[8]; } XpuProtectionRegisterSet;
有关所有XPU及其作用的详尽列表,请参见此博客文章的“附件”部分。
XPU的其他发现
在附件中可以看到,控制寄存器具有复位无效位。马上想到一个问题:如果我将XPU单元复位(例如bootROM),我现在可以对受影响的单元进行任何形式的访问吗?
结果如下:
· 清除安全CR实例中的位会使该单元的XPU寄存器不可访问。
· 清除非安全CR实例中的位会使正常空间的所有访问都停止,从而导致错误,但是数据读为0,写操作将被忽略。
这意味着XPU寄存器只是保护外围设备和/或存储器的一种手段,所有这些都可以通过其他技术(例如TrustZone隔离)来保护。
研究结论
简而言之,我使用两部手机全面研究了Qualcomm生态系统。
即使Nexus 6P的工作停滞了,我仍然有机会找到有趣的方法。在诺基亚6上,我已经设法在系统运行时读写所有内存。
参考文献
[aleph] Aleph Security, "Exploiting Qualcomm EDL Programmers (1): Gaining Access & PBL Internals", https://alephsecurity.com/2018/01/22/qualcomm-edl-1/ [aleph2] Aleph Security, "Exploiting Qualcomm EDL Programmers (2): Storage-based Attacks & Rooting", https://alephsecurity.com/2018/01/22/qualcomm-edl-2/ [aleph3] Aleph Security, "Exploiting Qualcomm EDL Programmers (3): Memory-based Attacks & PBL Extraction", https://alephsecurity.com/2018/01/22/qualcomm-edl-3/ [aleph4] Aleph Security, "Exploiting Qualcomm EDL Programmers (4): Runtime Debugger", https://alephsecurity.com/2018/01/22/qualcomm-edl-4/ [aleph5] Aleph Security, "Exploiting Qualcomm EDL Programmers (5): Breaking Nokia 6's Secure Boot", https://alephsecurity.com/2018/01/22/qualcomm-edl-5/ [ROP] Return-oriented programming, https://en.wikipedia.org/wiki/Return-oriented_programming [TLB] Translation lookaside buffer, https://en.wikipedia.org/wiki/Translation_lookaside_buffer [Nokia6] Nokia 6 wikipedia page, https://en.wikipedia.org/wiki/Nokia_6 [Nexus6P] Nexus 6P wikipedia page, https://en.wikipedia.org/wiki/Nexus_6P [QualcommSB] Qualcomm, Secure Boot and Image Authentication Technical Overview, https://www.qualcomm.com/media/documents/files/secure-boot-and-image-authentication-technical-overview-v1-0.pdf [SoCs] System on Chip, integrated circuit integrating all the basic components a system needs: CPU, memory, many peripherals, etc. [OTA] Full OTA Images for Nexus and Pixel Devices, https://developers.google.com/android/ota [firehorse] https://github.com/alephsecurity/firehorse
附录
XPU Registers Description Legend: S = "Secure" NS = "Non Secure" RESn = "Reset to n" CR: Control Register, offset 0x00 Bits Description 31-17 RES0, RO 16 S: RES0, RO NS: ? RW 15-11 RES0, RO 10-9 ? 8 Enables something 7 RES0, RO 6 S: ? NS: RES0, RO 5 S: RES1, RO NS: RES0, RO 4 RES1, RO 3-1 ? 0 Reset deassert Writing 0 to the "XPU unit enable" bit of the secure version of the register (SCR) causes access faults when later accessing the register for this XPU unit, even if the access was made from the Secure World. EAR0: Error Address Register 0, offset 0x40 Contains the physical address of the fault. ESR: Error Status Register, offset 0x48 Bits Description 31 "Multiple" fault 30-4 RES0, RO (?) 3 ? 2 ? 1 "Client" fault 0 "Config" fault ESRRESTORE: Error Status Register Restore (?), offset 0x4C Used to acknowledge and clear errors. Writes to this registers are copied to ESR (maybe?). ESYNR0: Error Synthesis Register 0, offset 0x50 Bits Description 31-24 TID 23-16 VMID 15-13 BID 12-8 PID 7-0 Master ID 0 "Config" fault ESYNR1: Error Synthesis Register 1, offset 0x54 Bits Description 31 ERROR_DCD fault 30 ERROR_AC fault 29 Addr. read-allocate flag 28 Addr. burst flag 27 Addr. "exclusive" flag 26 Addr. write flag 25 Addr. "full" flag 24 Addr. read "BEADNDXEN" flag 23 Addr. out-of-order flag 22 ? 21-19 "pReqPriority" 18-16 "Size" 15 Addr. "MSS SELF AUTH" flag 14-8 "Length" 7 Addr. "instruction" flag 6 Addr. prot. is NS flag 5 Addr. private flag 4 Addr. inner-shared flag 3 Addr. shared flag 2-0 Memory type ESYNR2: Error Synthesis Register 2, offset 0x58 Bits Description 31-4 ?, RES0? 3 Save/restore in progress 2 MSA region match 1 Secure region match 0 Nonsecure region match IDR0: Interrupt Description Register 0, offset 0x74 ? IDR1: Interrupt Description Register 1, offset 0x78 Bits Description 31-11 ? 10 0 for faults 9-0 ?
本文翻译自:https://blog.quarkslab.com/analysis-of-qualcomm-secure-boot-chains.html如若转载,请注明原文地址: