Thursday, May 23, 2013

Exploiting Samsung Galaxy S4 Secure Boot

Launched in April 2013, the Samsung Galaxy S4 is expected to be one of the top-selling smartphones of the year, having sold 10 million units in its first month of sales. While the majority of released models include an unlocked bootloader, which allows users to flash custom kernels and make other modifications to the software on their own devices, AT&T and Verizon branded devices ship with a locked bootloader that prevents these types of modifications. In this post, I'll provide details on how Samsung implement this locking mechanism, and publish a vulnerability in the implementation that allows bypassing the signature checks to run custom unsigned kernels and recovery images.

Both the AT&T (SGH-I337) and Verizon (SCH-I545) models utilize the Qualcomm APQ8064T chipset. As described in my previous blog post on Motorola's bootloader, Qualcomm leverages software-programmable fuses known as QFuses to implement a trusted boot sequence. In summary, each stage of the boot process cryptographically verifies the integrity of the subsequent stage, with the trust root originating in QFuse values. After the early boot stages bootstrap various hardware components, Samsung's APPSBL ("Application Secondary Bootloader") is loaded and run. This bootloader differs between "locked" and "unlocked" variants of the Galaxy S4 in its enforcement of signature checks on the boot and recovery partitions.

A quick glance at aboot (adopting the name of the partition on which this bootloader resides) revealed that it is nearly identical to the open source lk ("Little Kernel") project, which undoubtedly saved me many hours of tedious reverse engineering. By locating cross-references to strings found in both lk and aboot, I was able to quickly identify the functions that implement signature verification and booting of the Linux kernel.

The central logic to load, verify, and boot the Linux kernel and ramdisk contained in either the boot or recovery partitions is implemented in the boot_linux_from_mmc() function. First, the function determines whether it is booting the main boot partition, containing the Linux kernel and ramdisk used by the Android OS, or the recovery partition, which contains the kernel and ramdisk used by the Android recovery subsystem. Then, the first page of the appropriate partition is read into physical memory from the eMMC flash storage:

  if (!boot_into_recovery) {
    index = partition_get_index("boot");
    ptn = partition_get_offset(index);
    if (ptn == 0) {
      dprintf(CRITICAL, "ERROR: No boot partition found\n");
      return -1;
    }
  }
  else {
    index = partition_get_index("recovery");
    ptn = partition_get_offset(index);
    if (ptn == 0) {
      dprintf(CRITICAL, "ERROR: No recovery partition found\n");
      return -1;
    }
  }

  if (mmc_read(ptn + offset, (unsigned int *) buf, page_size)) {
    dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
    return -1;
  }

This code is straight out of lk's implementation. Next, after performing some sanity-checking of the boot image, which contains a custom header format, the function loads the kernel and ramdisk into memory at the addresses requested in the boot image header:

  hdr = (struct boot_img_hdr *)buf;

  image_addr = target_get_scratch_address();
  kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
  ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask) + 0x200;
  imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
 
  memcpy(image_addr, hdr, page_size);
 
  offset = page_size;

  /* Load kernel */
  if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, kernel_actual)) {
    dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
    return -1;
  }

  memcpy(image_addr + offset, hdr->kernel_addr, kernel_actual);

  offset += kernel_actual;

  /* Load ramdisk */
  if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, ramdisk_actual)) {
    dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
    return -1;
  }

  memcpy(image_addr + offset, hdr->ramdisk_addr, ramdisk_actual);

  offset += ramdisk_actual;

This is still essentially identical to lk's implementation, with the addition of code to copy the individual pieces of the boot image to the image_addr location. Finally, the function performs signature verification of the entire image. If signature verification succeeds, the kernel is booted; otherwise, a tampering warning is displayed and the device fails to boot:

  if (check_sig(boot_into_recovery))
  {
    if (!is_engineering_device())
    {
      dprintf("kernel secure check fail.\n");
      print_console("SECURE FAIL: KERNEL");
      while (1)
      {
        /* Display tampered screen and halt */
        ...
      }
    }
  }
 
  /* Boot the Linux kernel */
  ...

The is_engineering_device() function simply returns the value of a global variable that is set at an earlier stage in the boot process based on whether or not the chipset ID (an unchangeable hardware value) of the device indicates it is an engineering or production device.

Examining the check_sig() function in more detail revealed that aboot uses the open-source mincrypt implementation of RSA for signature validation. The bootloader uses an RSA-2048 public key contained in aboot to decrypt a signature contained in the boot image itself, and compares the resulting plaintext against the SHA1 hash of the boot image. Since any modifications to the boot image would result in a different SHA1 hash, it is not possible to generate a valid signed boot image without breaking RSA-2048, generating a specific SHA1 collision, or obtaining Samsung's private signing key.

The astute reader will have already noticed the design flaw present in the above program logic. Notice the order in which the steps are performed: first, aboot loads the kernel and ramdisk into memory at the addresses requested by the boot image header, and then signature validation is performed after this loading is complete. Because the boot image header is read straight from eMMC flash prior to any signature validation, it contains essentially untrusted data. As a result, it's possible to flash a maliciously crafted boot image whose header values cause aboot to read the kernel or ramdisk into physical memory directly on top of aboot itself!

Exploitation of this flaw proved to be fairly straightforward. I prepare a specially crafted boot image that specifies a ramdisk load address equal to the address of the check_sig() function in aboot physical memory. In my malicious boot image, I place shellcode where the ramdisk is expected to reside. I flash this image by leveraging root access in the Android operating system to write to the boot block device. When aboot reads the supposed ramdisk from eMMC flash, it actually overwrites the check_sig() function with my shellcode, and then invokes it. The shellcode simply patches up the boot image header to contain sane values, copies the actual kernel and ramdisk into appropriate locations in memory, and returns zero, indicating the signature verification succeeded. At this point, aboot continues the boot process and finally boots my unsigned kernel and ramdisk. Victory!

Thanks to ralekdev for the helpful exchange of ideas and suggestions.

56 comments:

  1. Thank you very much for this. I won't be getting an SGS4, but in general I find it exponentially more valuable to have understanding and an exploit, than simply believing in magic.

    ReplyDelete
  2. Thank D.R. for letting us know about the technical details. Awesome find with the Little Kernel OSP! Excellent security research.

    ReplyDelete
  3. Thank you sir, you rock.
    Well written and executed.

    ReplyDelete
  4. That's a great hack. Thank you for this.

    ReplyDelete
  5. It is ridiculous how good you are at this stuff.

    Thanks from the entire SGS4 community!

    ReplyDelete
  6. Dan, as usual, you rock ;)

    ReplyDelete
  7. Hopefully you are well compensated for your intelligence :)

    ReplyDelete
  8. Very nice! This is a great expoit and pretty easy one too :) good job on noticing the lk similarities.

    ReplyDelete
  9. Good post . Thanks a lot.

    ReplyDelete
  10. hey could you take a crack at the pantech bootloader for the flex

    ReplyDelete
  11. the correct design would likely not solely involve verifying the signature on eMMC but also when copying into RAM calculating a SHA2 and comparing with the verified image. This will be to mitigate a TOCTOU style attack.

    ReplyDelete
  12. Could Samsung have signature-checked the boot header to make sure it doesn't load ontop of aboot, not overwriting checkSig()?

    ReplyDelete
  13. Can you do some hack to unlock iPhone 5? Thank you!

    ReplyDelete
  14. So we have learned today that it is otherwise POINTLESS for carriers and manufacturers to 'lock' their bootloaders, or roms, etc.

    the lesson to be learned here: if you are designing something make it possible to 'lock' your ROM and bootloaders with cryptographic keys of extreme and lengthy strength. Otherwise, just GIVE USERS THE DARN KEYS FROM THE START!

    ReplyDelete
  15. Can you do the same thing to a iPad mini?

    ReplyDelete
  16. YES please. Thank you! Was so tired of touchwiz. NOW I can see why you waited until Verizons phone was out.

    ReplyDelete
  17. Would you elaborate more on how to Root SGs4? Thanks a million.

    ReplyDelete
  18. So I'm curious, why couldn't this exploit be use to replace the aboot image with an image that is patched to always see the qfuse unblown? thus effectively unlocking the bootloader without needing loki to flash kernels and recoveries.

    ReplyDelete
  19. Anonymous:
    I'm not sure what QFuse you're talking about, since whether a Galaxy S4's aboot is "unlocked" or not is not dependent on a QFuse.

    You can't replace aboot itself because signatures are validated at each stage of the boot chain (pbl -> sbl1 -> sbl2 -> sbl3 -> aboot). Writing a tampered aboot would cause sbl3 to fail signature validation.

    ReplyDelete
  20. Dan I meant the QFuse for loading kernels or recoveries not a QFuse for aboot. But the second part of your reply answered my question. I thought maybe aboot would check the signature when loading a new aboot I didn't know it checked it every time you boot.

    ReplyDelete
  21. I like this blog and the statements which you have used in this blog.I found so many things in this page so i saved it in my favourite.

    ReplyDelete
  22. Any chance you'll take a crack at any of their new firmwares?

    ReplyDelete
  23. I have brand new galaxy, "galaxy s4 lte-a(E330S)".
    but your program can not find check function in its aboot.img
    Is there any way to crack this?

    ReplyDelete
  24. I'd like to know what changed in the vzw update that killed this.

    ReplyDelete
  25. Any chance you can apply your talents to the LG Optimus L9. All dev attempts have failed.

    ReplyDelete
  26. Very informative post about Exploiting Samsung Galaxy S4 Secure Boot, Galaxy S4 users will once again be able to move apps to their SD car, assuming the apps allow the option. There has been a Secure Boot Image added for use with Knox, but the bootloader itself still isn't locked and is still easily rooted. Thanks for sharing.

    ReplyDelete
  27. I don't think he will. Everyone has given up on the new locks.

    ReplyDelete
  28. It is possoble you turn a i9505 to i9505g?

    ReplyDelete
  29. I'd love to see this masterpiece working ;)
    Please share your work at http://forum.xda-developers.com/
    Great Work!

    ReplyDelete
  30. Thank you for the light in tunnel. Now we can override this Knox Crap.

    ReplyDelete
  31. Can you please share your ida pro aboot.mbn loader plugin?

    ReplyDelete
  32. very very clever nice to have a little insight into how it works,thanks for the info

    ReplyDelete
  33. I am having a "Samsung Galaxy S4-i337 AT&T" which i got as a gift from US.
    Model no: SAMSUNG-SGH-I337
    ANDROID VERSION: 4.2.2
    BASEBAND VERSION: I337UCUAMDL
    KERNAL VERSION: 3.4.0-453947
    SE.INFRA@SEI-46#1
    SAT APR 27 17:06:05 KST 2013
    BUILD NO: JDQ39.I337UCUAMDL
    IMEI : XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX (I AM HESITANT TO POST IT)
    NETWORK UNLOCK CODE : 5XXXXXXX

    Currently i am staying in India, When i put a new 3g BSNL sim card in it , phone asked for network unlock code, unfortunately i didn't know the importance of it and i entered some random numbers(more than 5 times) and now my network unlocking is permanently blocked by AT&T. I have contacted them they saying my phone is permanently locked and can use only with AT&T network sim card. I have tried to unlock with the method mentioned in XDA forums but unfortunately negative result. I have contacted Samsung , AT&T and BSNL service centers nobody could give a solution to my problem.
    What can i do with my phone now to use it with BSNL sim card in India...
    Thanks in advance.....all genius people out there help me please........
    this post is last hope...

    ReplyDelete
  34. I‘am using S4(SC-04E,DCM) now, my nuild is SC04EOMUAMF2, I am trying to modify the "aboot.mbn", can you help to locate the entry point by IDA, or give me some tips about mbn file?

    I have already locate the strings in mbn by IDA, but I can find cross-references.

    ReplyDelete
  35. Nice read Dan! I am a developer interesting in researching an MF3 bootloader exploit. Any tips?

    ReplyDelete
  36. Great work Dan. I hate to be a noob (and I really should know the answer to this question..), but how did you figure out the aboot.mbn entry points? How big are the RAM/ROM sections, header, signature, and program? Are these features of ARM in general that I'm somehow missing, or is this specific to the partition? I've explored lk and still not finding a way to successfully disassemble the image. On another point, how would I know if the image is encrypted? I'm guessing I wouldn't see legible output when I run the binary through 'strings', correct?

    Cheers,
    Mike

    ReplyDelete
  37. Thanks so much Dan, but i have a problem
    Well, i try to make my patch, but i have the response:

    [+] loki_patch v2.1
    [-] Failed to find function to patch.

    Using SCH-i545 4.3

    Some news about this?

    ReplyDelete
  38. Dan, would you care to take a look a little at this thread on XDA and give us some feedback if the (accidental) presence of SECUREBOOT:NONE would be of any help in fully unlocking the N9005? Thank you very much!

    http://forum.xda-developers.com/showthread.php?p=48579747

    ReplyDelete
  39. Samsung ... naturally stupid

    should be used in their next commercials ....

    ReplyDelete
  40. Thank for sharing your idea about secure boot Galaxy S4

    ReplyDelete
  41. Galaxy S4 is the best model of all Notes and SX models

    ReplyDelete
  42. Can you do this for LG G2 kitkat version?

    ReplyDelete
  43. Can you please look into the Lg g flex

    ReplyDelete
  44. Hey will it work for galaxy grand 2

    ReplyDelete
  45. Please do the same on Samsung Galaxy Note3 SM-N9005

    ReplyDelete
  46. Please help us out with the AT&T and Verizon note 3

    ReplyDelete
  47. Dan is there a place I can download this unsigned image from, that you used to make your s4 boot?

    ReplyDelete
  48. Unlocking your AT&T HTC Aria by remote unlock code is 100% safe. These phones were built to accept unlock codes. It is the same method service providers will use to unlock their devices. Cellphone unlocking is also 100% legal and will not void warranty on your device.
    http://www.attphoneunlockingshop.us/

    ReplyDelete
  49. Hi Dan! How can I use this information to actually unfuse a smartphone? I'm programmer and enrolled in a Automation Engineering course, I already done some custom ROMs but I don't know the firsts steps that I need to take in order to break the secure boot. I must enter in shell (via adb), debug some kernel object (with gdb) and call this function? Or must I change the kernel source, put this function call, recompile the ROM and upload? Or I need to change the machine code of the ROM binaries to hack this? Or I need to do this via a JTAG? Or I need to pull a partition and save to a file, edit this binary file in machine code to force that call and update the partition with this edited file? I know how to do things like this, but I don't know how path I have to take.

    ReplyDelete
  50. i have a s4 build i545vrufnk1 i have tried everything i could on line when in odin everything connects but when i try and start odin it fails any help would be great

    ReplyDelete
  51. Do you have a tool to unloki? I am trying to edit my boot, but it's got loki and I'm new to this. I compiled loki_tool but came to realize this is for patching when a mod is already ready.

    ReplyDelete
  52. Hello, Dan,
    great exploit. Do you know can it be applied to NEC Terrain? Or other way around: do you know that it cannot by the different nature of the boot lock? For the moment it was a problem that even root (temporary) cannot write to partitions. I found a snaky way and CAN write, so I can flash whatever on the internal memory. I can provide I hope everything upon your request.
    Now I'm waiting for my other guys to disasm and decompile the aboot binary. Everything suggests that the story is VERY similar or identical to your findings in S4, LG, etc. I hope to find the address of the important function myself.
    Will you, however, be able to help by supporting (or correcting) my findings about the function address. My problem is that I'm quite new for arm, android, etc. I'm pc c/c++/assembler guy.
    What might you need? aboot image I guess and the boot image (or atleast it first portion as the image itself is big, 10M), correct?
    Thanks in advance, Alex alex-kas at altaray dot com

    ReplyDelete