As part of the devices I researched for my upcoming book on Android Internals, I got myself an HTC One M8. A chief factor in my decision was knowing that it had a working 1-click root, since I didn't want to root it using a bootloader unlock (which would ruin the prospects of selling it on eBay once I'm done).
The exploit for the One M8 is called WeakSauce, and has been published on XDA Developers by members jcase (who discovered the vulnerability) and beaups (who helped exploit it). It's packaged as a simple APK, which you can download and push to the device, but I couldn't find much documentation on how it works, though it had been classified as an HTC specific vulnerability, and not a generic one in KitKat. Since I have a chapter dealing with security, it made sense to try and figure out exactly what the exploit is doing.
This article was created to detail the process, and is written as a tutorial. Going along, I hope to publish more of these articles as updates to the book, as I have with the OS X/iOS book.
Step I: Examine the APK
Getting the APK is a simple enough matter, as it is freely and readily downloadable. After getting it, we can unzip to examine its contents:
As the above shows, the APK has no JNI functionality (otherwise it would have a lib/ subfolder). The only "unusual" thing about it are the assets - the APK packages busybox (the all-in-one-binary, statically compiled) and an image of xbin (An ext4 loopback mount image). The manifest is also quite simple (I XMLized the relevant portions):
The only thing that's intriguing is why WeakSauce needs BlueTooth permissions. This will be explained shortly.
Step II: dexter
The dexter is a simple DEX file parser and extractor I wrote as an appendix to Chapter 10 of the book, which deals with the internals of the Dalvik VM. The tool is an improvement on the well known dexdump utility, in that it is more Java-aware, and can also perform some decompilation. Using it to dump the classes revealed some 521 classes, of which the vast majority were Android support classes - so these could be outright ignored.
Aside from the android support classes, which are nothing special), only has the com.cunninglogic.weaksauce package classes - obfuscated, as is readily seen from the class names - and the com.htc.engine.system.SystemAccess.class - which is a replacement class for the similarly named class on the phone.
Step II': dex2jar
Since imgtool is not out yet at the time I'm writing this (it will be released with the book), you can use the dex2jar tool to unpack the classes. This is a simple, yet powerful utility, which undoes the work performed by the SDK's dx. Whereas the latter takes the Java classes of the APK, in JAR form, and creates a classes.dex, the former converts the classes.dex back into a JAR file. The usage is straightforward. Unpacking, you should get a classes-dex2jar.jar file, which you can unzip.
Step III: Deobfuscation
The classes extracted from the APK are obfuscated, but it's a simple enough matter to deobfuscate them. Looking at the SystemAccess as an example, we see:
Which implies the strings (in this case, presumably the name of a native library) are also obfuscated. The implementation of i.m shows:
The i.m method relies on its caller - obtained through the stack trace - as a key to the obfuscation. With that in mind, it's simple to create an m2, which also gets the class and method names as arguments. That is:
So, after a little bit of search and replace we can reveal that the above string is really: "system/lib/libdm-systemaccess.so". It turns out there is a similarly named m method in SystemClass.java, used extensively by the Weak class (which performs the bulk of the work). This method obfuscates by taking using the classname, and then the method name (that is, in reverse). Deobfuscating all of the strings used in Weak class yields:
So - what do we have? A lot of shell commands. Root access is somehow obtained, then these commands are run. Of particular interest is data/data/com.cunninglogic.weaksauce/temp/pwn.sh, which looks like the "pwn script". Note (in the above echo command) it gets written to /sys/kernel/uevent_helper, which is expected to contain the name of a binary launched by the kernel on device addition. This file is writable only by root, however, so the exploit must be doing something before writing to it. Indeed, looking at the device post-exploitation, we see:
Showing that /sys/kernel/uevent_helper has been chown'ed to be WeakSauce's. Since the root exploit works and we have access to all the directories, we can just navigate to WeakSauce's directory, and see:
So all that would be needed is to get the kernel to detect a new device. This is why Weaksauce required bluetooth permissions - looking at the Weak class we see:
The call to CopyFileCtl is the important one here - this was defined as a native method of the replaced com.htc.engine.system.SystemAccess class. As it so happens, this does, in fact, turn out to be a JNI library, with the corresponding method defines as:
The fault lies in this function, which calls HTC's dmagent (thorugh the /dev/socket/dmsocket socket). The daemon (running as root, naturally) performs the copying, but along the way the file permissions get incorrectly chmod'ed. Game over.
Summary
This article detailed how WeakSauce works. To recap:
WeakSauce creates a replacement class for HTC's SystemAccess.
Using JNI, it triggers a file copy operation, passing /sys/kernel as one of its arguments
The dmagent daemon happily complies, and chowns the permissions on /sys/kernel/uevent_helper
WeakSauce readily exploits this by writing its pwn.sh as the uevent handler
WeakSauce disables/enables BlueTooth, which makes the kernel trigger the uevent_helper - that is, pwn.sh
From this point on, it's all downhill - DaemonSu is installed, which is required in KitKat since a simple setuid /system/xbin/su wouldn't work - The SELinux context would confine even a root owned process to be u:r:shell:s0 (This is explained in Chapter 21, which deals with security). This way, when you type "su", you're actually going to a daemonsu, which runs as u:r:kernel:s0, and spawns you an unrestricted tmp-mksh. You can see that with ps -Z:
.. And that's all. If you haven't yet checked out the book, please do so now, and feel free to drop me a line at j@ (this domain) for any questions, comments, or requests.
Greets
jcase and beaups - Great work, you guys. HTC owes you another customer (for now, at least)