Monday, 9 September 2013

Swerving 'Root' detection on Android...

Last week I was having problems with an Android application that had root detection built in. I don't do a great deal with Android so it's not something I have had to look at before. A user at work had 'rooted' their device to tweak it a little and disable a load of 'bloatware' which was apparently causing performance issues.

Once they had rooted it one of their key applications stopped working as it appeared to be doing some 'root' detection, having looked at iOS jailbreak detection and defeated that for some apps I decided to have a crack and see if something similar could be done. I have played around with Android Debugging Bridge (adb) before so already had the Android SDK installed.

First up was grabbing a copy of the .apk from the device, this was pretty easy as I could list the apps via adb shell and then use adb pull to copy the .apk across to my laptop. Simples.

$ adb shell
shell@mako:/ $ pm list packages -f | grep <name of application>
$ adb pull <path to .apk>

Once I had a copy of the .apk I just needed to decompile it to work out what was going on. A quick google and I found 'apktool'. I installed it and then ran against the .apk which generated a load of directories and crucially some smali code. Smali is an assembler/disassembler for the dex format used by davlik (Android), more info on it here

To disassemble the application it was pretty easy, no decrypting 'FairPlay' like you see on iOS:

$ apktool d <path to .apk>

A quick grep of the .smali files for the keyword 'rooted' and I was able to find all the files that might be related to the root detection, this was a bit of guess work but I got lucky! I was soon able to find a couple of methods called 'isRootedDevice' and 'isRooted' in a couple of the smali files. Had the developers called the method something else it might not have been quite so easy. 

$grep -ri rooted

This looked promising so I opened each smali file and searched for 'isRooted'. 

From examining the code I worked out that the developers were looking for the file /system/app/Superuser.apk and also something called 'test-keys'.

I googled what Superuser.apk is and found a few posts on StackOverflow and the following blog:

It seems Superuser.apk is used to manage what applications have su (root) access. It would make sense for the developer to check for this as I guess it is used on most rooted devices (a bit like cydia). If I could change the .apk file that the app was looking for I might be able to defeat this step. The other item that is being checked is 'Test-Keys', apparently this is a generic key for signing packages.

I modified the smali code so that the application would only report it was rooted if it found a random apk or string. As these would never be found the device would not report that it was rooted.

Next I used the apktool to recompile the binary:

$ apktool b <directory with source smali in>

Now I had a package, I could install it onto my device using adb. I tried to install but got the error 'Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]':

It seems I need to sign the package before Android will let me install it. A bit of 'Google Power' and I found that you need to sign the package with javasigner. First of all I would need a certificate so I created a key store and cert with key tool  and then signed as below:

keytool -genkey -v -keystore testing.keystore -alias testing -keyalg RSA -keysize 2048 -validity 10000

$ jarsigner -verbose -keystore testing.keystore -digestalg SHA1 -sigalg MD5withRSA <path to apk> testing

Once this was done I installed on a rooted device and bingo... no prompt to say the device was rooted!

I was surprised how easy this was, I had expected it to be a little more challenging. It's quite easy to see how simple it would be to modify a binary add a trojan or some malware and then distribute.

No comments:

Post a Comment