D39 focuses on vulnerability research and has identified several critical security flaws, including technical exploitation of mobile, IoT devices, and Linux and Windows operating systems. We have reported dozens of vulnerabilities and dedicate to Samsung Vulnerabilities and Exposures (SVE) and Common Vulnerabilities and Exposures (CVE).
Before diving into the main subject this month, we are glad to announce that TeamT5 is again accepted at Black Hat USA, and our vulnerability research team, D39, will talk at the Black Hat Briefings in the upcoming August. We are honored to share our research findings with researchers and security experts all over the world and expect more recognition of Taiwan's vulnerability researchers in the world.
This article will cover a part of our talk at Black Hat USA in August.
We have found several vulnerabilities in Samsung Secure boot, which can break through Samsung Knox protections. We can even retrieve users' sensitive data from a locked device. The affected Samsung mobiles include Galaxy S8, S9, and S10. Patches to these vulnerabilities have been provided by Samsung.
One of these vulnerabilities allows attackers to execute arbitrary code in Galaxy S8 secure bootloader to access the device. In this article, we will elaborate how we exploit these vulnerabilities to bypass S8 secure bootloader through the USB device and obtain arbitrary code execution in early boot stage.
Note: Another security research team found this vulnerability at the same time and report it to Samsung. ID: SVE-2019-15230 (details below).
As the market leader of smartphone, Samsung conducts a series of protection on Android, known as the Knox Platform, to ensure the security of its devices. During the booting process, Samsung uses S-boot (Secure Boot) to make sure it can only boot a stocked image. If the device tries to boot a custom image, it will trip (turned from 0X0 to 0X1) a one-time programmable bit e-fuse (a.k.a Knox bit). Once a trustzone app (trustlet) detects the Knox bit tripped, it will delete the encryption key of sensitive data to prevent unauthorized data from accessing the locked device.
Smartphones with Samsung Exynos processor use a exclusive secure bootloader named S-boot. S-boot has ODIN mode which allows users to upgrade the firmware manually. Due to the insufficiency in its code, the flash command (opcode: 0x66) in ODIN mode is not able to properly check the flash image size, which leads to buffer overflow.
The flash command in ODIN mode uses a temporary buffer to store the image. In Galaxy S8, the buffer is located at 0xC0000000, right in front of sboot code segment (0xC9000000). Although the system will check to ensure that the size being no larger than 0x1e0000, it uses signed comparison to check the size of the image; thus provide us some space to get around. We therefore provide a size larger than 0x80000000, making buffer overflowed and, in the end, the following segments such as code, stack, and heap will be overwritten.
Although we can overflow the code segment of S-Boot, we still cannot hijack the execution flow. Since USB receivers use physical memory to hold the data it received directly, we cannot affect instruction cache unless the cache line has been invalidated.
Fortunately, the heap segment is not cached due to MMU flag. There are some pointers stored in the heap segment, which can be accessed during the USB process. If we overwrite these pointers with null bytes, the processor will trigger an exception and trap into the exception handler while accessing to NULL pointers. Since the handler has never been executed, it is not cached in the instruction cache. Therefore we can also overwrite the exception handler simultaneously and hijack it directly to our shellcode.
Booting Custom Kernel
Since all the run-time data has been overwritten -- including stack, heap and global variables -- the sboot fail to perform further booting operation. These kinds of data are difficult to recover, so we must re-execute the booting process.
Under normal condition, S-boot calls several functions in a particular function table which is located at 0xC90C7350. To re-execute s-boot, these functions have to be invoked sequentially again. They would initialize the memory of heap and stack, set the global variables, and boot the kernel at the end. However, these functions also involve some SMC calls which cannot be executed twice. Since we only compromised EL1 (Exception Level 1), the trustzone in EL3 (Exception Level 3) cannot be reverted. As a result, we have to overwrite these SMC calls with NOP instruction while overflowing the code segment to ignore those SMC (System Management Controller) calls.
After all the run-time data has been reset, we replace the original kernel with our custom one. Then we execute one last function to boot our custom kernel and get the root privilege without blowing KNOX bit.
2019-10-02 Report Vulnerability 2019-10-08 Informed Vulnerability duplicated and release patch note
Appendix: Potential Exploit Path on Galaxy S10
According to our analysis, this vulnerability affects Galaxy S9, Galaxy S10 and Galaxy Note 10 as well. Among them we find that exploitation can still be trigger at different address. For instance, even the temporary buffer located at different addresss, like 0x890000000 in Galaxy S10, there are still chances to exploit it. To explain the complete exploitation flow, we choose the firmware, G970FXXU1ASD5, as an example.
In Galaxy S9 and later version, there is another feature added to the secure boot - compresseddownload. It uses another buffer to store the flash image. However if compresseddownload failed during the initialization, it will fallback to normal download, and use the buffer (0xC0000000) to store the flash image.
To make S-boot fallback to normal download, we have to make the function
cd_v3_smp_register fail. After reversing, we noticed that the function
cd_v3_smp_register may return failed if there is no available core(
booted_cores > 3) can be booted. Coincidentally, there is a test command - "smpboottest" in the UART (Universal Asynchronous Receiver/Transmitter) console. The command smpboottest will boot a core and add the count of the bootedcores. Although
smp_boot_test shutdown the booted up core immediately, it didn't restore the count. Therefore, the compresseddownloadinit may failed if the command `smpboot_test` has been invoked more than twice before entering the download mode.
If we have the UART debug cable to get the UART console, we can call the command
smp_boot_test 3 times and enter the download mode via the command
compressed_download_init would fail, then the temporary buffer fallback to 0xC0000000. Therefore the arbitrary code execution on S10's bootloader can be achieved as the one in Galaxy S8.
We managed to build our own TypeC debug cable at first. However, after trying every kinds of Pull-up/down resistor value, TypeC accessory mode, TypeC VDM, we cannot yet figure out a cable for RID_523K detection. Still, in the end, we applied other approach that enable us to attain Galaxy S10 Secure Bootloader's permission of arbitrary code without having debug cable.
We will have a thorough display on Black Hat. Stay tuned!
For the latest vulnerability research from D39, please follow:
TeamT5 official website: https://teamt5.org/