Google CTF 2017 : Android RE Challenge

The challenge was consist of three parts.
1.Android application loading native library (ARM or x86) depending on platform.
2.Native library drops a dex file and dynamically loads it.
3.Native library modify bytes (in memory) of loaded dex file in step2.

1.Android application loading native library
Decompiling food.apk file using JADX (Dex to Java decompiler) and looking at AndroidManifiest.xml we see activity is implemented in FoodActivity class.


Looking at FoodActivity class it only loads the native library cook.The argument to System.loadLibrary is a library name chosen arbitrarily by the programmer. The system follows a standard, but platform-specific, approach to convert the library name to a native library name. For example, a Solaris system converts the name cook to libcook.so, while a Win32 system converts the same cook name to cook.dll.

2.Attaching to libcook.so.
We will be using IDA Pro.Refer to http://www.hexblog.com/?p=809 for how to attach to native library loaded by android application.
We will be using ARM specific native library. JNI_OnLoad function exported by libcook.so will be called once it is loaded.


JNI_OnLoad contains lot of obfuscated strings and sub_1034 is decryption routine which is called to decrypt strings.



Below is python implementation of above code.
#v is list of words to decrypt.
v = [0xB651776,0xF201572,0x9652E6D,0x1A690564,0x216D0675,0x9684F20,0x4610165,0x2E2E0674,0x36F0F20,0xF6E1761,0x11700F65]
for i in range(0,len(v)):
    r1 = v[i]
    r7 = (0xFF << 8) & 0xFFFFFFFF
    r7 = r7 & r1
    r6 = (r1 << 0x18) & 0xFFFFFFFF
    r7 = (r7 >> 0x8) & 0xFFFFFFFF
    r6 = (r6 >> 0x18) & 0xFFFFFFFF
    r5 = ~(r7)
    r5 = (r5 | r6)
    r6 = ~(r6)
    r6 = r6 | r7
    r6 = r6 & r5
    r6 = ~(r6)
    o = o + chr(r6)
    r6 = 0xFF0000
    r6 = (r6 & r1) & 0xFFFFFFFF
    r6 = (r6 >> 0x10)
    r1 = (r1 >> 0x18)
    r1 = (r1 ^ r6)& 0xFF
    o = o + chr(r1)
print(o)


Before dropping dex file native library loads libdvm.so (dalvik vm library) .If libdvm.so cannot be found it throws error.

From android version 4.4(KitKat, SDK version 19) google introduced Android Run Time (ART). Therefore user can select between Dalvik and ART to execute their apps.Android version 7.0 and above (SDK version 24 and above) uses ART by default.




ART(libart.so) and Dalvik(libdvm.so) libraries located at /system/lib directory.

3.Dropping dex file and dynamically loads it.
create directory /files/odex/ at location /data/data/<app_package_name>.
open d.dex file in write mode.
write 0x15A8 (5544) bytes to d.dex file which is stored in native library at offset 0x2F18.



Next, a DexClassLoader is instantiated to load class S of the dropped d.dex file. Below is the code to create a DexClassLoader.

DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent)

Code executed by native library to instantiate DexClassLoader.
dalvik/system/DexClassLoader <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V
Below is representation of above code.
dalvik/system/ - package
DexClassLoader - class
<init> - call constructor of DexClassLoader
(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;) - parameters to constructor of DexClassLoader
 V - Return type void.

Below are the parameters passed to constructor of DexClassLoader.
1.Ljava/lang/String - dexPath - /data/data/com.google.ctf.food/files/d.dex
2.Ljava/lang/String - optimizedDirectory - /data/data/com.google.ctf.food/files/odex
3.Ljava/lang/String - librarySearchPath - null
4.Ljava/lang/ClassLoader - parent

To get value of Ljava/lang/ClassLoader below code is executed and implemented in sub_11F4.

java/lang/ClassLoader/getSystemClassLoader()Ljava/lang/ClassLoader; 
Below is representation of above code. 
1.java/lang - package
2.ClassLoader - class
3.getSystemClassLoader() - method
4.Ljava/lang/ClassLoader - return type

After DexClassLoader is instantiated, loadClass method is called to load class S of d.dex file.
loadClass(Ljava/lang/String;)Ljava/lang/Class;
Ljava/lang/String - com/google/ctf/food/S
Ljava/lang/Class - return type


After class S of d.dex file is loaded its constructor is called using below code.
<init>(Landroid/app/Activity;)V
<init> - class S contructor
Landroid/app/Activity - parameter to constructor of Class S is activity object -  activity Landroid/app/Activity
V - return type void

After Class S of d.dex file is loaded native library deletes d.dex and /files/odex/ directory it created.
While instantiating DexClassLoader 2nd parameter passed is optimizedDirectory = /data/data/com.google.ctf.food/files/odex. 
odex directory will contain d.dex file that is execution ready for Dalvik VM and need not to be parsed again by dalvik VM.

Lets pull dropped d.dex file using adb pull command and decompile it with JADX to see what it contains.

As mentioned above once class S is loaded and its constructor is called with activity object passed as parameter.Class S constructor sends broadcast as highlighted below and broadcast receiver is implemented by class F.

onReceive method in Class F calls method cc() as highlighted below.

Bytes of method cc is corrupted and JADX is not able to decompile it.

4.Native library modify bytes (in memory) of loaded d.dex file
Reading memory and patching bytes is implemented in sub_1098 of native binary.

Use /proc/self/map to get current process memory.

read 0x100 bytes from current process memory.

buffer containing read bytes.

search /d.dex in above read bytes.

if /d.dex is found in read bytes.Get start address of memory map which is 0x822e3000 as shown above and find offest of loaded d.dex file in memory map by searching magic bytes "dex".


if magic bytes "dex" is found copy 0x90 bytes stored in native library at offset 0x2e88.

Encrypted bytes in native library at offset 0x2e88.

Decrypt bytes stored in native library at offset 0x2e88 by xoring with byte 0x5A.Write the decrypted bytes at offset 0x720 from address of "dex" magic bytes found in memory map.

Bytes at offset 0x720 in d.dex file before patching.

Bytes at offset 0x720 in d.dex file after patching.

Lets look at cc() function of class F in patched d.dex file.cc() function calls method C in class R which decrypts flag bytes.

Implementing logic in method C of class R we get below flag bytes.
CTF{bacon_lettuce_tomato_lobster_soul}

Comments

Popular posts from this blog

VIrtual Machine Detection Techniques

DoublePulsar Backdoor

Debugging MBR : IDA Pro and Bochs Emulator

Analyzing ATM Malwares

PaloAlto CTF 2017 : Binary Challenge 2

FireEye FLARE CTF 2017 : APK Challenge 8

NotPetya\Petya : Overwriting System MBR

WannaCry Encryption Flow

Samsung CTF : Chicken or Egg Reversing Challenge