[Upgrading, Modifying and Unlocking] jb881122:
OutOfRange: Boot unsigned images on some 10-year-old Samsung devices with locked bootloaders​

Some Background​

In May of 2013, @djrbliss published a tool called Loki, which exploited a lack of checks in the Android bootloader for boot images overlapping the bootloader itself. Unfortunately (for people wanting to run custom ROMs), bootloader updates were quickly released patching this vulnerability.

The CodeAurora commit that closes the Loki vulnerability: 0e163a4eec7b7fcaa4fe066b0207802e5503e10f

Although this commit appeared shortly after Loki came out and does proper range-checking for bootloader overlaps, Samsung didn't add this commit to their bootloaders until a while later, instead opting for their own range checks in the meantime. Although these checks were able to specifically close out the Loki vulnerability, they are insufficient for detecting all possible overlapping with the bootloader.

Why This Works​

We target range-checking code that only checks the endpoints of where the kernel and ramdisk will be loaded. Essentially, these bootloaders check whether two addresses (load_addr, load_addr + size) fall within the bootloader's memory range. If they both lie outside any troublesome locations, the data proceeds to be loaded. This misses the case where the memory range completely surrounds the bootloader's range, meaning both endpoints would be "good" addresses but the range would still overlap the bootloader.

How This Works​

This exploit works by setting the ramdisk load address to be just before the start of the bootloader and the size slightly larger than the bootloader's memory range (hence, both endpoints are OutOfRange, get it?). By doing this, the bootloader checks the endpoints, thinks that there is no overlap, and proceeds to load whatever data we put in the ramdisk, overwriting the bootloader code.

The code we overwrite the bootloader with is the same as the original bootloader code, with a few exceptions:

Code is added just before the start of the bootloader, which fixes the bootloader and sets it up to boot without any signature checks

The beginning of the mmc_boot_fifo_read function is overwritten with code to jump to our code. The rest of the function is replaced by the opposite of a NOP slide, where each instruction branches to the previous. This function is used by mmc_read to get the actual data from the MMC chip, so this is where execution will be happening while the bootloader is being overwritten.

The undefined instruction handler is overwritten to also jump to our code. This is done for the roughly 1-in-20 chance that execution runs into a partially-patched instruction and causes an exception

Once the phone starts executing our code, we end up in a bit of an odd state because the MMC chip was in the middle of reading data. Because of that, the first few steps taken are to:

Restore the original code in the places where we overwrote it

Call the mmc_boot_fifo_read function to finish the MMC read at a scratch address

Re-initialize the MMC interface

Once those tasks are done, we take one of two paths:

If we loaded another boot image as the kernel, we proceed to move that image's kernel and ramdisk to the proper locations and copy the header to the location that the bootloader looks at for the unified boot method. This will cause the bootloader to skip any loading and checking of the already-loaded image.

If we were configured to boot from a different partition, booting to recovery is disabled, the pointer to the "boot" partition name is changed to point to the new partition name, and the check_sig function is modified to return 0.

Finally, we call the boot_linux_from_mmc function to allow the bootloader to boot whatever code we want it to.

Is My Device Vulnerable?​

One easy way to check: The above-linked commit contains the string "kernel/ramdisk addresses overlap with aboot addresses". If you find this string in your bootloader, the vulnerability was almost certainly patched. If you don't find it, that doesn't mean it's vulnerable (it's hard to check for sure without some disassembly), but there's a decent chance, especially if it's a Samsung device from around 2013 or so.

In case you're curious: To find Samsung's Loki check, look for the string "ERROR: Not valid address of boot-header" instead. Some newer non-vulnerable bootloaders include both checks.

Where Can I Find This / What Can I Do?​

A tool I made to actually make use of this exploit can be found on GitHub. So far, this only supports the bootloaders that I have personally been able to test with.

If you believe your device/bootloader version is vulnerable but not supported by the above tool:

If you're well-versed with how Android bootloaders work and know how to disassemble them, follow the instructions in the readme to get the necessary offsets and values for the tool to work. After testing and making sure the resulting images work, submit a pull request.

Otherwise, provide information about your device, including what model it is and what bootloader version you are on. I can see if it's vulnerable, try to find the appropriate configuration values, and give you a couple of patched images to test with before adding support for the tool.

Feel free to report any bugs/issues you find or make any improvements that would be useful to include in the tool.

If you are a ROM developer wanting to use this tool to support a device, it should be able to be integrated in a similar way to the Loki tool. The repository can be cloned into a path like "external/out-of-range" and built when "oor" is added to PRODUCT_PACKAGES.

I am currently working on a LineageOS 11 ROM for my SM-G730A, which could be used as an example of this tool being integrated into a ROM. Specifically, see the releasetools folder and these lines in goldenlteatt.mk.

Concluding Remarks​

I understand that this is a large amount of effort to go through for a bunch of 10-year-old phones. However, since these phones are so old and the solution to this vulnerability is almost as old, I highly doubt any vulnerable bootloaders will be patched to close this vulnerability. This pretty much makes ROM developers home free on the devices which this works on. Hopefully, this can help make a few more phones a little more useful than they otherwise would have been.