Smartphone manufacturers often use signature verification to protect their firmware. In order to get root access, the signature verification mechanism needs to be disabled. This requires contacting the manufacturers to get the phone to get the phone unlocked. Besides this, custom tooling is required in order to unlock the bootloader from the device. If you own you should be able to pwn it!
On the authors Android device, there is a signature verification being done on the firmware, which is verified by the bootloader. When updating the device over USB, most Android bootloaders speak fastboot. This is a basic USB interface with a myriad of commands for flashing, updating and gathering much information. It should be noted that since most bootloaders are open source and modified, it is important to analyze the firmware directly with a disassembler.
Since custom modifications are a great location for finding bugs, the author looked there first. They noticed that the flash command had been modified to allow flashing of specific custom partitions, even when the bootloader was locked. When making a custom fastboot binary, the author accidentally caused a crash with improper ordering of the commands. This appeared to be a buffer overflow in some parsing functionality.
But, how do you find the result of the crash without having a debuggable setup? You cannot just add GDB to this! In addition, a hard reset is required in order to get the phone working. To dump the memory of the phone (to learn more about the current state). So, the author wrote an automated script that would overflow by a SINGLE byte then see if a crash occurred. If not, we checked the next byte. If the phone crash, we tried another value. Although this is not perfect, it is good enough for identifying.
The author viewed the data from the crash and determined that it was opcodes. From there, they searched for similar patterns and values in the disassembled version of the bootloader to find out it was part of the bootloader itself! The buffer overflow was overwriting the bootloader itself in RAM.
The author tested the same vulnerability on a different phone and found the same issue but using a different amount of bytes until the crash. This implies that the vulnerability is present but the phones just use a different memory layout. The issue affected the SDM66 chip from Qualcomm.
The Qualcomm chip encrypts the userdata partition. This prevents chip-off analysis using an internal security mechanism on a chip. If an unlocked bootloader tries to access the partition, it is identified as corrupted. The keys are inaccessible (even with code execution) and the EFI API to decrypt the partition is not modifiable. The API verifies whether the bootloader is unlocked and whether the firmware is signed before allowing access to the keys. The new goal is to bypass this to decrypt the partition.
The author was looking at how the flow of execution works. They noticed that there is a large difference between where the
verification is done and the
execution is done; this is a classic bug known as
time of check - time of use (TOCTOU). The author had to modify the bootloader in a very particular ways in order to exploit this:
- Verify with one image the actually use another malicious one.
- Change the
boot command to be accessible. Since the bootloader is locked, the Android image can access the keys. Game Over!
This video is really long and has two different exploits of two different chips. So, this is going to be part 1 of my analysis.