Samsung Galaxy S4 Research

Heads up

This isn’t going to be formatted as a white-paper, and is instead, formatted as a narrative, as there’s been a large request for such.

This research was by myself (Nolen Johnson), and Ryan Grachek.

With awesome help from several other people along the way.

Glossary

  • Bootloader: A general term for a link in the boot-chain that has a specific job that is run each cold-boot
  • CAF: The Code-Aurora Foundation, Qualcomm’s open source release entity.
  • cold-boot: Fresh boot from powered off state
  • DTB: Device Tree Blob. Its purpose is to “provide a way to describe non-discoverable hardware” to Linux, read more here
  • EFUSE: Software based fuse whose data is stored in QFPROM
  • QFUSE: Microscopic hardware fuse that is integrated into the SoC - Once physically blown, impossible to reset or replace
  • QFPROM: Qualcomm’s fuse region
  • QSEECOM: A linux kernel driver that allows communication with TrustZone, and the issuing signed and verified SCM calls to do things like blow fuses - Please note that only signed applets and OEM/ODM approved calls can be made
  • ROM: Read only memory - but oddly, in the android world refers to the operating system installation package
  • SCM: Secure Channel Manager (note: not related to Linux’s SMC calls)
  • SMC: The Linux Kernel’s “Secure Monitor Call”, read more here
  • SoC: System-on-chip (your phone’s “motherboard” of sorts)
  • TrustZone: Qualcomm ARM chipset’s “Secure World” implementation

Problem Statement

Starting with the Galaxy S4, Samsung launched their security focused, “KNOX” branding. KNOX brought a number of new security mechanism(s), and allowed carriers to opt-in to disallow end-users to unlock the bootloader on their devices, meaning that the end-user is forced to use whatever operating system is shipped by Samsung, severely limiting both the longevity, and aftermarket support life of devices in question. In the U.S., two of the largest carriers, Verizon and AT&T both opted-in.

As an important preface, the software modification of personal wholly-owned devices was proven to be entirely legal back in 2010 (see here for more information on Jay Freeman’s amazing legal crusade on this), it was not ruled that all devices must be modifiable. This means that device manufacturers are legally allowed to place digital signature verifications in place that prevent running your own operating system, or even, in Apple’s case, your own applications.

This type of behaviour from corporations is always unpleasant to see, as it helps perpetuate device upgrades/sales and sends more devices to the landfill prematurely. All of the above are made much more painful by Samsung’s “TouchWiz” Android skin from this era. It was laggy under load, and thanks to both Verizon’s 2 year contracts at the time, and my… lack of funds, I was stuck with this device for at least 2 years. About a week after purchasing the device, I picked up my very techy friend’s Google Play Edition Galaxy S4, and was in awe at how buttery smooth the OS was in comparison. I figured converting one variant to another couldn’t be that hard, and I can’t state enough how wrong I was.

What are we working with?

For a better understanding of the chain-of-trust and boot-sequence on Qualcomm’s apq8064 platform, see the relevant section on my writeup on the matter, here.

When starting this research, my device was on Android 4.3 I545VRUEMK2, and the only device-specific research available was Dan Rosenberg’s awesome Loki exploit, which makes use of the fact that ramdisk loading addresses aren’t sanity checked before the unverified ramdisk is loaded into memory. Dan used this vulnerability to overwrite specific pieces of the applications-bootloader (aboot) in memory with ARM shellcode to jump to the Linux kernel contained in the boot image, skipping signature checks.

This tool would have been the solution to my problem! But thanks to each major firmware upgrade blowing an incremented value to SW_REV QFUSE region, which is read by the lowest levels of the boot-chain, and the fact that the underlying vulnerability only exists on the firmware the device launched with, I545VRUAMDK, this solution was out of my grasp.

Idea: Variant Conversion

The Google Play Edition Galaxy S4 was at least much faster, right? So, initially, just running the GPE firmware variant would suffice.

Sadly, the Google Play Edition’s images are signed with a different RSA key than the standard Verizon firmware, and the device’s PBL won’t boot an SBL1 that isn’t intended for your specific variant/signed with the correct key, so that makes it impossible to convert fully.

We can, however, attain local root access on the device using GeoHot’s futex vulnerability (CVE-2014-3153) exploit TowelRoot to gain local root access on the device.

NOTE: If you are interested how this exploit works, here is a great writeup by fellow security researcher Elon Gliksberg on the topic.

We can then make use of Hashcode’s amazing tool, SafeStrap to gain access to a pre-boot minimal Linux environment that allows us full access to the non-running system. From this pre-boot environment, we can modify the system partition, meaning that we can change a lot about how the system looks and feels. I ended up spending weeks reverse-engineering various components from the stock system, and trying to adapt the Google Play Edition’s system image to work on our stock boot image, as remember, thanks to signature checks, we can’t use a custom kernel/ramdisk. After a lot of tinkering with what components need to be included from the Samsung TouchWiz ROM, and a lot of trial and error, I released KitPop, which was a simple GPE based ROM with several select libraries, services, all the stock kernel modules, and my favorite apps/modifications pre-included. It looked and ran a lot more like what I expected from a $650 phone.

Ultimately, this worked pretty well, things like Wi-Fi HotSpot, USB data-storage, and voice over LTE were broken, but I lived with it for a lot longer that I should have.

Changing the Goal

If we can’t run legitimate Google Play Edition images, LineageOS is a solid alternative, it’s an OSS distribution of Android that can be easily ported to new devices in most cases. What’s even better? They already support the SCH-I545! Apparently there are “Developer Edition” devices that can be purchased that have factory unlocked bootloaders, and as mentioned earlier, some early firmware revisions of the typical end-user model are vulnerable to the Loki exploit.

Thanks to relying on a custom kernel/ramdisk combo, to run LineageOS we can either:

  • Unlock the bootloader fully
  • Make the device think it is a developer edition, which would skip signature checks

Digging in

I began my research by dropping the SCH-I545’s I545VRUFNK1 aboot.mbn into IDA, only to discover that, as I had somewhat expected, it had been stripped of symbols. I then proceeded to grep the bootloader for a relevant CAF tag to give me some clue as what revision of Qualcomm’s LittleKernel this was based on. After finding the closest match, I built it for the apq8064 platform, I converted it to a .sig file containing just the ELF info, and loaded it into IDA alongside aboot.mbn so I could at least resolve non-Samsung functions.

TESTBIT

In late 2014, the Verizon Note 3 had an important, and revealing leak. The firmware VRUFNC2 leaked, which was an early, internal Android 4.4 KitKat build, with drum roll full symbols! I decided to apply what I knew to this new firmware, and try to later back-port my findings to the Galaxy S4 family. Thankfully, they’re very similar in terms of locking mechanisms.

Before I get into it, let me take a second to give Dan Rosenberg a shoutout here for helping me get my foot in the door, and answering my plethora of questions about this.

The function that checks TESTBIT (QFUSE row @ 0xfc4b80ac) against the bit-mask for SYS_REV (@ 0x80030) is sub_F80306C, the function is called from two places, sub_F821514, which doesn’t appear to do anything cool, beyond providing some diagnostic output about various security settings, and in sub_F808704, which is far more interesting.

sub_F808704 appears to check local SYS_REV against the installed firmware’s value. One might assume that the logic would dictate that the fuse row be blown to a value that would prevent malicious hackers from disabling rollback, right? Well, not in this case, if we take TESTBIT and mask it to 0x80030, the device will, in essence, skip rollback verification, jackpot!

It’s worth noting at this point that there is an additional call to sub_F818FFC when flashing firmware via Samsung’s ODIN flash software, which gets the relevant SYS_REV value at flash-time, and ODIN will fail with “SW REV CHECK FAIL : Fused XXX > Binary XXX”.

I then hunted TESTBIT down on the aforementioned Galaxy S4 firmware, and some logical flows from IDA can be seen below:

Using the above, we can also deduce that the value of TESTBIT’s shadow in memory is 0x700438+0x4000.

With this info, we /should/ be able to use JTAG on the bare-board from a Galaxy S4 to use hardware interrupts, hand-set the value and boot an MDK about, meaning we can use Dan’s Loki exploit to boot custom firmware! This isn’t a full solution, as JTAG isn’t feasible in every-day usage, but as a PoC, sure!

The only way to permanently blow the fuse would be to use a flaw/vulnerability in TrustZone blow the base fuse to our desired value. Dan’s QSEE exploit could easily be leveraged. We could even likely apply M0nk’s work on msm8974 to run shellcode as TZ to blow the fuse.

However, I had missed something, it became clear that this wasn’t feasible, as on the Note 3 at least, I had missed that this logic was in the application’s bootloader itself, and that the lower level bootloader, SBL1, never checked that fuse, and therefore, this fuse could be used to boot older recovery/boot images, but not aboot images, ugh.

Well hey, a fun learning process and a lot was learned.

Converting to a Developer Edition?

On boot, the last bootloader of the SBL chain reads out the eMMC CID on boot, and compares it against an optionally present hash of the CID in the footer of the aboot partition of the device to determine whether or not the device is a Developer Edition, and by proxy if it should be unlocked. Unfortunately, on Toshiba eMMC’s (which the S4 has), there are no vendor commands to write the device’s CID. On the Galaxy S5, which uses Samsung eMMC’s, this concept was later leveraged into SamDunk by Sean Beapure, which ultimately unlocked bootloader of most of the Samsung msm8974 family, doh! So close!

Moving on

What if we didn’t exploit the applications-bootloader, what if instead we just overwrite the kernel in memory to run a custom kernel? Enter kexec.

kexec is a tool used to overwrite the Linux kernel in memory with a new kernel, and then execute the new kernel without ever taking the system down for full reboot (hardware always remains live). It has become increasingly more common to see kexec implementations to bypass android device Bootloader security, as many times, it is far simpler than finding a vulnerability that would allow a full unlock.

kexec must be loaded in as a kernel module to work correctly. So, to even attempt this method bring up, we first need root access and the ability to load custom (un-signed) kernel modules. I will be speaking about the Verizon Galaxy S4 almost exclusively here, although this theoretically applies to most apq8064 Samsung devices.

As described above, we already have root-access, but to process we would need to be able to load unsigned kernel modules. In the Linux kernel, the process that checks to see if kernel module signatures are require is called LKM. There is a known exploit by XDA forum user Jeboo that was initially created for Android 4.3 JellyBean called BypassLKM, that was later ported to Android 4.4.2 KitKat by XDA forum user Surge1223.

In short, BypassLKM just uses devmem2 to write to specific addresses in /dev/mem and change the value that dictates whether LKM is enforced.

I then unpacked the VRUFNK1 boot image, and decompressed the zImage, then loaded it into IDA, and traced the function back to find the relevant addresses in memory.

I then proceeded to pack the process up into a script I called modload and ran it, as you can see below:

Now, we build the kexec.ko kernel module in the Samsung provided NK1 kernel source to ensure that that Linux kernel’s magic (yes, it’s called magic) values match.

Now to actually execute it! We then boot up, unmount everything we can, push the built relevant modules, custom ramdisk, and custom kernel to the root of the device, connect the device to your computer via USB, and run commands with similar syntax(s) to these: adb shell

su # Get root

insmod kexec_arm.ko && insmod kexec_machine.ko && insmod kexec.ko # Load our kernel modules (in order)

kexec -l /stock_nk1_zImage --ramdisk=/ramdisk.cpio.gz --append="($cat $cmdline)" --atags-file=/atags # Load the kernel into memory

unmount –a # Unmount all possible partitions

kexec -e # Execute the kernel

Protip: Run adb shell su –c “dmesg” in another terminal to debug the process.

The system then attempted to soft-boot the kernel. It then failed due to a Samsung implemented mitigation to this inside of KNOX/Samsung TIMA. I spent about 2 months debugging the various hangups I hit, and ultimately gave up.

Accepting semi-success?

I mean, KitPop wasn’t that bad, I can just live with that, right?

Nah, Backstreet’s Back Again

I finally came back to this project after a few years, and ultimately discovered that an old vulnerability that I had missed actually applied to this device! In a Windows Insider leak, a bug in SBL1 was described wherein PBL doesn’t load SBL1 by partition name, and instead loads it by block location. The more engage of you may already have ideas about what to do with that information.

We are therefore able to craft a custom GPT (partition table) that shaves off a small portion of SBL1, and labels it as a new partition called hack, we can then write ARM32 shellcode to that partition, and PBL jumps to it. From there we can do… well, anything.

As a fun note, we used this to shine a spotlight on a friend of ours, whose face (with his permission), we packed into the ODIN flash mode in place of the typical Android-mascot logo…

Alongside this, I then worked with others to get the S4 booting a modern Android version, and am maintaining LineageOS builds for all Galaxy S4 variants, you can find the builds, and installation instructions, here:

Now my Verizon Galaxy S4 is running Android R flawlessly!

It feels good to finally solve this problem! Sadly we solved it about 3 years too late for it to be useful to me as my daily-driver device, haha. Still a fun find though!

Written on May 10, 2015