Android bootloader analysis (1) - Qualcomm Secure Boot

Introduction

The bootloader is another essential part of Android security. When the Android device boots up, the bootloader loads and initializes multiple things, including the Trusted Execution Environment (TEE), operating system, etc. At each stage of the boot process, the bootloader performs an integrity check on each boot image. This is called Secure Boot, and the integrity of the whole Android boot process relies on this security mechanism. If the vulnerability occurs in this process, the attacker can load compromised TEE/Android images, leading to the leakage of sensitive user data after unlocking the device or offline brute force of the lock screen password.

This blog post series provides a rough analysis of the latest Qualcomm boot chain, and we’ll also focus on the ABL boot process and analyze common attack vectors in Android bootloaders such as Samsung Odin.

Qualcomm Secure Boot

The bootloader verifies the cryptographic signature of each boot image before loading it on a device. Since the boot process consists of multiple stages, the earlier stage authorizes the next stage’s boot image. If an attacker modifies the intermediate boot image, the earlier stage cannot verify the signature, and the booting fails.

The boot process of each device varies depending on the chipset manufacturer and device vendor implementation. However, the core concept of the boot process is quite similar across the devices. In this blog post, we’ll focus on the Qualcomm chipset.

Primary Boot Loader

The following is the boot process based on the Qualcomm chipset.

Untitled

(https://www.qualcomm.com/content/dam/qcomm-martech/dm-assets/documents/secure-boot-and-image-authentication-version_final.pdf)

The very initial boot process begins with a Primary Boot Loader (PBL). The PBL is stored in read-only memory as Systems on Chip, which is immutable. This guarantees the PBL is not compromised, and the chain of trust in the boot sequence starts from here.

The PBL is relatively tiny since it is stored in BootROM. Therefore, it establishes very necessary hardware initializations such as power management, digital signal processing (DSP), and graphics processing. And, the PBL loads the following boot images after verifying the signature.

There are several types of research that exploit vulnerability occurs in PBL. Qualcomm chipset has an Emergency Download Mode (EDL), an alternate boot mode of the PBL. The EDL works as an Android recovery mode so that users can recover partitions, arbitrary read/write memory, etc.

You can refer to Aleph’s EDL exploitation, also known as firehose (https://alephsecurity.com/2018/01/22/qualcomm-edl-1/), and presentation from HexaCon 2023 (https://www.youtube.com/watch?v=3Zs45Cl3HfQ). Further, for MediaTek chipset, you can find the BootROM exploit from MTKClient (https://github.com/bkerler/mtkclient).

eXtensible Boot Loader

The following boot images are the eXtensible Boot Loader (XBL), also known as the Secondary Boot Loader (SBL). Unlike the PBL, XBL is stored in the eMMC or UFS, which means users can analyze it by downloading device firmware or dumping the XBL partition from the device.

The XBL splits into two parallel parts: the Rich Execution Environment (REE) and the Trusted Execution Environment (TEE).

Untitled

The XBL on REE establishes the normal world components such as peripherals, Always-On-Processor (AOP), UEFI, etc. The XBL is also responsible for verifying and loading QHEE (Qualcomm Hypervisor Executed Environment), QTEE (Qualcomm Trusted Executed Environment), and so on. However, we won’t analyze TEE and Hypervisor images at this time.

The following is the initial XBL for Samsung, for example.

Untitled

After initializing the Hypervisor and TEE, the XBL loads UEFI and establishes the Boot and Runtime Services. UEFI provides a standard interface for boot applications, allowing manufacturers and vendors to develop additional features flexibly. The UEFI also verifies and loads ABL (Application Boot Loader).

This is part of the boot log of the Qualcomm device where UEFI is loaded.

...
B -    555222 - AOP Config -  Image Load, Start
D -     11773 - Auth Metadata
D -     16378 - AOP Config -  Image Loaded, Delta - (14138 Bytes)
B -    571631 - AOP -  Image Load, Start
D -     20801 - Auth Metadata
D -     42212 - AOP -  Image Loaded, Delta - (318420 Bytes)
D -         0 - aop_loaded
D -         0 - boot_prepare_cpucp
B -    613812 - CPUCP_DTB -  Image Load, Start
D -     11773 - Auth Metadata
D -     13756 - CPUCP_DTB -  Image Loaded, Delta - (8692 Bytes)
B -    627598 - CPUCPFW -  Image Load, Start
D -     20831 - Auth Metadata
D -     49532 - CPUCPFW -  Image Loaded, Delta - (232822 Bytes)
D -         0 - boot_reset_cpucp
B -    677161 - QSEE Dev Config -  Image Load, Start
D -     12413 - Auth Metadata
D -     24400 - QSEE Dev Config -  Image Loaded, Delta - (368009 Bytes)
B -    701561 - QSEE -  Image Load, Start
D -     21808 - Auth Metadata
D -     94153 - QSEE -  Image Loaded, Delta - (4116976 Bytes)
B -    796934 - DTB: Vibration Enabled
D -      1189 - sbl1_hw_play_vibr
B -    796934 - SEC -  Image Load, Start
D -     12261 - Auth Metadata
D -     14305 - SEC -  Image Loaded, Delta - (4972 Bytes)
B -    811239 - QHEE -  Image Load, Start
D -     20832 - Auth Metadata
D -     35593 - QHEE -  Image Loaded, Delta - (1407936 Bytes)
B -    846832 - APPSBL -  Image Load, Start
D -     11803 - Auth Metadata
D -     38217 - APPSBL -  Image Loaded, Delta - (3068344 Bytes)
D -        30 - sbl1_save_appsbl_index
B -    886055 - SBL1, End
D -    732793 - SBL1, Delta
S - Flash Throughput, 189997 KB/s  (9879861 Bytes,  52118 us)
S - DDR Frequency, 2092 MHz

UEFI Start     [ 1060]
 - 0x0A7001000 [ 1065] Sec.efi
ASLR          : ON
DEP           : ON (RTB)
Timer Delta   : +3 mS
RAM Entry 0   : Base 0x0080000000  Size 0x0001200000
RAM Entry 1   : Base 0x00816E0000  Size 0x0000EC0000
RAM Entry 2   : Base 0x00D8040000  Size 0x0000020000
RAM Entry 3   : Base 0x00D8800000  Size 0x0000000000
RAM Entry 4   : Base 0x00E3BB0000  Size 0x001C450000
RAM Entry 5   : Base 0x0880000000  Size 0x002FB00000
RAM Entry 6   : Base 0x08B0000000  Size 0x0009E00000
RAM Entry 7   : Base 0x08C0000000  Size 0x0140000000
RAM Entry 8   : Base 0x08BA000000  Size 0x0001E00000
RAM Entry 9   : Base 0x0082600000  Size 0x0055A00000
RAM Available : 7926 MB (0x01EF630000)
RAM Installed : 8192 MB (0x0200000000)
{ 1110871 }[ XBL ] Minidump      : ON
Init 1 aux cores of 7
Init CPU core 1
Continue booting UEFI on Core 0
  > Scheduler up on Core 1
{ 1117306 }[ XBL ] UEFI Ver      : 6.0.231228.BOOT.MXF.2.1-01661-LANAI-1
{ 1117306 }[ XBL ] Build Info    : 64b Dec 28 2023 15:15:44
{ 1117337 }[ XBL ] Boot Device   : UFS
{ 1117337 }[ XBL ] PROD Mode     : TRUE
{ 1117367 }[ XBL ] Retail        : TRUE
{ 1152320 }[ XBL ]  - 0x0D30CF000 [ 1150] DxeCore.efi 
{ 1155248 }[ XBL ]  - 0x0D304F000 [ 1152] SecShareInfoDxe.efi 
{ 1155431 }[ XBL ] SecShareInfoDxeInitialize start
{ 1155431 }[ XBL ] SecShareInfoDxeInitialize end
{ 1155523 }[ XBL ]  - 0x0D306C000 [ 1153] EnvDxeEnhanced.efi 
...

On Qualcomm devices, the Android boot application is running under a UEFI TianoCore-based environment. You can find TianoCore edk2 for bootloader source from https://gitlab.com/Codeaurora/abl_tianocore_edk2.

There are also various attack vectors in XBL such as XBLRamDump, Upload Mode for Samsung. These modes are also such of diagnostics mode like EDL and users also can interact via USB.

Application Boot Loader

After loading to UEFI, the boot process enters the Application Boot Loader (ABL). Like the previous boot process, the ABL is also responsible for verifying and loading the upcoming kernel.

ABL operates within the UEFI environment and is constructed as a UEFI application. Among various applications, LinuxLoader is responsible for loading the Linux kernel.

Below is an example of LinuxLoader ABL.

Untitled

LinuxLoader is open source, so you can find reference source code from https://gitlab.com/Codeaurora/abl_tianocore_edk2/-/blob/uefi.lnx.6.4.9.r1-rel/QcomModulePkg/Application/LinuxLoader/LinuxLoader.c. This repository also contains a Fastboot implementation. In the next post, we’ll analyze how LinuxLoader verifies and loads the Android Kernel.

When the verification and loading kernel finishes, the following process is up to the Kernel, and the bootloader’s role ends. The log below shows where the UEFI ends and the Kernel starts.

{ 5169018 }[ ABL ] [USEWP] Adding info of Partition : prism (1:3324416:102400) 
{ 5169170 }[ ABL ] [USEWP] Adding info of Partition : optics (2:3426816:5120) 
{ 5185884 }[ ABL ] [USEWP] Success to set the Secure Write Protect(3), Status(0)
{ 5187897 }[ ABL ] [USEWP] Result : 0x1(3:1)
{ 5189483 }[ ABL ] [ShutDownbkSecApp] shutdown success status=0, BKSecAppId=0
{ 5189727 }[ ABL ] SPU[VALID]:5 
{ 5189758 }[ ABL ] 
Shutting Down UEFI Boot Services: 5191 ms
{ 5192167 }[ ABL ] LogFlush:SecDebugLog Flushing
{ 5198816 }[ XBL ] Start EBS        [ 5200] 
{ 5198969 }[ XBL ] MDPLibProfile: splash enabled
{ 5225565 }[ XBL ] App Log Flush : 0 ms
{ 5226114 }[ XBL ] ScmArmV8ExitBootServicesHandler, Status = 0x0. 
{ 5226144 }[ XBL ] Exit EBS        [ 5228] UEFI End
------ LAST LOGCAT ------

------ KERNEL LOG (dmesg) ------
<6>[    0.000000] [0:        swapper:    0]  Booting Linux on physical CPU 0x0000000000 [0x412fd050]
<5>[    0.000000] [0:        swapper:    0]  Linux version 5.4.86-qgki-23063627-abF711U1UES2BUL7 (dpi@21DJGC13) (Android (6877366 based on r383902b1) clang version 11.0.2 (https://android.googlesource.com/toolchain/llvm-project b397f81060ce6d701042b782172ed13bee898b79), LLD 11.0.2 (https://android.googlesource.com/toolchain/llvm-project b397f81060ce6d701042b782172ed13bee898b79)) #1 SMP PREEMPT Wed Dec 22 12:47:56 KST 2021
<6>[    0.000000] [0:        swapper:    0]  memblock_reserve: 0xcd8d8 setup_arch+0x64/0x1dc
<6>[    0.000000] [0:        swapper:    0]  Machine model: Samsung B2Q PROJECT (board-id,08)
<6>[    0.000000] [0:        swapper:    0]  sec_hw_param:sec_hw_rev_setup() androidboot.revision 8
<6>[    0.000000] [0:        swapper:    0]  androidboot.revision 8
<6>[    0.000000] [0:        swapper:    0]  [SAPA] read_sapa_param: param_time=0
<6>[    0.000000] [0:        swapper:    0]  [sec_hdm] hdm_wifi_flag androidboot.hdm_status = NONE
<6>[    0.000000] [0:        swapper:    0]  efi: Getting EFI parameters from FDT:

The well-known attack vector in Android Bootloader, including ABL, is download mode such as Fastboot and Odin. Download mode is also used to recover when booting is impossible, as all previous attack vectors do. It offers various functions, such as firmware updates and diagnostics. Since download mode can actively interact with users and contains multiple features, it is used as a major attack vector.

You can refer to several previous researches on ABL.

Conclusion

We’ve roughly followed Qualcomm devices’ boot process and known vulnerabilities, as well as research on PBL, XBL, and ABL. In the next blog post, we will analyze the bootloader’s specific components, such as the LinuxLoader and the Fastboot implementation in depth.

·