Our Blog

Android hooking with Introspy

Reading time ~8 min

Here’s my first blog where I’ll try to write up how I’ve managed to set up the Introspy framework for the Android emulator.

First things first, if you haven’t downloaded the Android SDK do it now from here.

I am on Ubuntu 14.04 x64 machine but hopefully you will be able to follow this guide as long as you are on a modern linux system.

Sidenote: Since you are gonna run many commands on the emulator I highly recommend that you open a new shell during this proccess (adb shell) and run the logcat command. That way you can see all the debug messages and if something fails, play around and see how can you solve it.

In order to install and use the framework you will first need to install the Cydia Substrate and root the emulator (which I also cover)

My SDK installation is deployed on /home/symeon/Desktop/android-sdk-linux/platform-tools and I have also added that path to my
.bashrc to make my life easier (just change the paths to your needs):

vim ~/.bashrc
export ANDROID_HOME=/home/symeon/Desktop/android-sdk-linux/platform-tools  
export PATH=${PATH}:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
:wq

Lastly, do a

source ~/.bashrc

and you are done.

Next step, we need to install the Android 4.2.2 API since this is the latest version that Cydia supports (actually it’s 4.3 but am guessing that the 4.3.1 API 18 from the SDK patches it), do that by running

$ android

then Select the “Android 4.4.2 (API 19)”, accept the terms and download it.

Continuing you will have to set up an Android Virtual Device (avd), run the manager by invoking

$ android avd

click “Create” and make sure you have the same settings as the ones depicted below:

avd settings

As Etienne mentioned, there might be cases where the application you want to audit uses the native ARM libraries, so first try setting the CPU to Intel Atom (x86) and if that fails, try the ARM one.

Now in order to root the emulator we need to execute it with the following parameters:

$ emulator -verbose -avd introspy_device -partition-size 300 -no-snapshot-load

We also need 2 binaries for that, superuser and su (su binary is available from this link)

$ wget http://www.superuserdownload.com/downloads/com.noshufou.android.su.apk

Hopefully you have everything set up by now and assuming that the afore-mentioned files are on your ~/Downloads folder run these commands to remount your filesystem and transfer them on your device.

$ adb shell mount -o rw,remount -t yaffs2 /dev/block/mtdblock0 /system
$ adb shell chmod 06755 /system/bin/su
$ adb install com.noshufou.android.su.apk

You should see a similar output:

$ adb shell mount -o rw,remount -t yaffs2 /dev/block/mtdblock0 /system

$ adb push su /system/bin/
1626 KB/s (83592 bytes in 0.050s)

$ adb install com.noshufou.android.su.apk
2356 KB/s (1468798 bytes in 0.608s)
        pkg: /data/local/tmp/com.noshufou.android.su.apk
Success

and make sure that you have changed the ‘su’ binary permissions:

$ adb shell
$ ls -l /system/bin/su                                                                 
-rwsr-sr-x root     root        83592 2016-02-09 13:09 su    

Download the Cydia Substrate and install that as well:

$ wget http://www.cydiasubstrate.com/download/com.saurik.substrate.apk
$ adb install com.saurik.substrate.apk

Now that you have both Apps installed, open Substrate click on the “Link Substrate Files”, you should get the following message:

cubstrate_permissions

Tap “Allow” and hopefully you will see the following screen (if not, click the Link Substreate Files one more time). We are still not there yet, Substrate requires a Soft reboot so click on the “Restart System (Soft)”

substrate_restart

Wait for the reboot and you should have Substrate fully working:

cydia_win

If you are still following me, grab a virtual cookie and finally it’s time to fetch the Introspy sources:

$ git clone https://github.com/iSECPartners/Introspy-Android
$ git clone https://github.com/iSECPartners/Introspy-Analyzer

and install the APK files:

$ cd Introspy-Android
$ adb install "Introspy-Android Core.apk"
$ adb install "Introspy-Android Config.apk"

Moving on, you should have the “Introspy Config” app installed on the device.
Tap on it and you will see a list of all the installed apps:

introspy_config

So let’s try that for the WhatsApp app, get it and install it the usual way:

$ wget https://www.whatsapp.com/android/current/WhatsApp.apk && adb install WhatsApp.apk

Open introspy config again, if you try to enable the [WhatsApp] you will see an error (you are running that logcat command, right?):

I/IntrospyGUI( 2498): su -c echo 'GENERAL CRYPTO,KEY,HASH,FS,IPC,PREF,URI,SSL,WEBVIEW,CUSTOM HOOKS' > /data/data/com.whatsapp/introspy.config ; su -c chmod 664 /data/data/com.whatsapp/introspy.config ;            
E/su      ( 2516): Unknown id: 'GENERAL

Let’s do that manually:

$ adb shell
$ cd /data/data/com.whatsapp/
$ echo 'GENERAL CRYPTO,KEY,HASH,FS,IPC,PREF,URI,SSL,WEBVIEW,CUSTOM HOOKS' > introspy.config

and make sure that you indeed have created it:

root@android:/data/data/com.whatsapp # cat introspy.config
GENERAL CRYPTO,KEY,HASH,FS,IPC,PREF,URI,SSL,WEBVIEW,CUSTOM HOOKS                                                                                            root@android:/data/data/com.whatsapp #

Essentially the config is a simple file which Introspy reads – you are free
to remove any of those (e.g. you might be interested in hooking only the GENERAL and CRYPTO)

Before running the app, you might want to save all your treasure to a file:

$ adb logcat -s "Introspy" -f > introspy.txt

Fire up the app … et voilà!

.. snip ..
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/com.whatsapp_preferences.xml]
I/Introspy( 2600): ### PREF:com.whatsapp:getSharedPref:getString; name: [com.whatsapp.RegisterPhone.prev_country_code], default: []; retrieves: []
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/RegisterPhone.xml]
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/RegisterPhone.xml]
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/RegisterPhone.xml]
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/com.whatsapp_preferences.xml]
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/com.whatsapp_preferences.xml]
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/com.whatsapp_preferences.xml]
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/com.whatsapp_preferences.xml]
I/Introspy( 2600): ### FS:com.whatsapp:[/dev/urandom]
I/Introspy( 2600): ### KEY ### com.whatsapp - javax.crypto.spec.SecretKeySpec->SecretKeySpec()
I/Introspy( 2600): -> Key: [cQf6myPv5Zy/pn1OfVnW4If9vRU=], algo: AES
I/Introspy( 2600): ### KEY ### com.whatsapp - javax.crypto.spec.PBEKeySpec->PBEKeySpec()
I/Introspy( 2600): -> Passcode: [SR
I/Introspy( 2600): D??????????F:!i)WA44123456], Salt: [....], iterations: 16
I/Introspy( 2600): ### KEY ### com.whatsapp - javax.crypto.spec.SecretKeySpec->SecretKeySpec()
I/Introspy( 2600): -> Key: [R/ManGH5Myyv2KLMD1kH1A==], algo: AES
I/Introspy( 2600): ### KEY ### com.whatsapp - javax.crypto.spec.SecretKeySpec->SecretKeySpec()
I/Introspy( 2600): -> Key: [R/ManGH5Myyv2KLMD1kH1A==], algo: AES/OFB/NoPadding
I/Introspy( 2600): ### GENERAL CRYPTO ### com.whatsapp - javax.crypto.Cipher->init()
I/Introspy( 2600): -> Mode: ENCRYPT_MODE, Key format: RAW, Key: [R/ManGH5Myyv2KLMD1kH1A==]
I/Introspy( 2600): ### GENERAL CRYPTO ### com.whatsapp - javax.crypto.Cipher->init()
I/Introspy( 2600): -> Mode: ENCRYPT_MODE, Key format: RAW, Key: [R/ManGH5Myyv2KLMD1kH1A==]
I/Introspy( 2600): ### GENERAL CRYPTO ### com.whatsapp - javax.crypto.Cipher->doFinal()
I/Introspy( 2600): -> Input data is not in a readable format, base64: [cQf6myPv5Zy/pn1OfVnW4If9vRU=]
I/Introspy( 2600): -> Output data is not in a readable format, base64: [g8HustqCucpm70Z6ByaHeR1+Sik=]
I/Introspy( 2600): -> Algo: AES/OFB/NoPadding; IV: CCnI/6FSvP/1R72Wml0Fxg==
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/files/rc]
I/Introspy( 2600): ### HASH ### com.whatsapp - java.security.MessageDigest->update()
I/Introspy( 2600): -> Hash of : [AAJbQgAABBE=] is: [2jmj7l5rSw0yVb/vlWAYkK/YBwk=] , Algo: [SHA]
W/Introspy( 2600): ### FS ### com.whatsapp - java.io.FileOutputStream->FileOutputStream()
W/Introspy( 2600): -> !!! Read/write on sdcard: [/mnt/sdcard/WhatsApp/Profile Pictures/.nomedia]
I/Introspy( 2600): ### FS:com.whatsapp:[/data/data/com.whatsapp/shared_prefs/com.whatsapp_preferences.xml]
I/Introspy( 2600): ### IPC ### com.whatsapp - android.content.ContextWrapper->startService()
.. snip ..

You can see under the hood which crypto functions they use, requests, strings, etc etc.

While you are testing the app, everything is stored on a file “introspy.db” which is located here:

/data/data/app_name/databases/introspy.db

Finally to export all that findings to a nice html report you will have just to do the following:

$ cd ~/Desktop/Introspy-Analyzer
$ mkdir whatsapp_db && adb pull /data/data/com.whatsapp/databases/introspy.db ./whatsapp_db/introspy.db
$ python -m introspy -p android -o whatsapp_findings whatsapp_db/introspy.db

If everything succeeds, you’ll have a folder named whatsapp_findings/report.html, open it with your favorite browser and see what you can get from.

Last but not least you might also want to visit the introspy webpage to see how you can add some custom hooks.

Big thanks to Etienne for the great tips and guidance and greets to Willem too for the amazing Mobile Training Slides (make sure to read them if you are new like me to Android stuff)

That’s it, enjoy!

References:
http://forum.xda-developers.com/showthread.php?t=1731095
http://stackoverflow.com/questions/17615412/android-write-failed-epipe-broken-pipe-error-on-write-file
http://blog.elsdoerfer.name/2011/12/10/installing-susuperuser-apk-in-icsandroid-4-0-emulator/