Android Reversing Part 3: Tampering with Android Applications

Hello paranoids

 So, after all those theory-related posts, it is time to actually do something. On this post, i will tamper with a simple application for Android. Let us begin:

The Test Application

 As referred on the post about tools there is a website from which you can download APKs, APKMirror. When i first wrote these lines was trying to tamper with a Facebook application (MD5 f96435e9a1c951ed181fb02dd61c4b2c)  downloaded from APKMirror.  However, when i looked at the smali and decompiled sources i was like:

jackie_chan

 The application was protected with Proguard which for a noob as myself is way above my paygrade (for now). So i have dug out my weak Android expertise and put together a simple application (my GitHub) with a weak authentication (hardcoded credentials). The specifications for the emulator are:

  • Android 6.0
  • Marshmallow, API 23
  • x86

Preparing  the Environment

 The development environment i used was Android Studio 2.3 (with SDK tools). All the coding and reversing was done within a VM using VMWare Fusion Professional Version 8.5.6 (5234762). Don’t forget to enable Intel VT-x/EPT support since emulators require this. While this is not a development blogue i will leave some considerations here for future reference and in case someone gets stuck.

Creating an Emulator and Deploying the Application

The easiest way i could find to do this was to create a dummy project on Android Studio (2.3) and then create the emulator. In terms of environment variables i have defined:

ANDROID_SDK_ROOT -> C:\Users\[YOUR_USERNAME]\AppData\Local\Android\sdk

Assuming you are at the window of the project, you should see a button with “AVD Manager”.

  1. Click the icon
  2. Create Virtual Device
  3. You can choose any device. Choices only matter if you need the application to run with a good resolution (AFAIK).
  4. On the next screen you should be prompted to choose the Android image. You may need to click “download” to obtain the image. In this case i am choosing Marshmallow, API 23 for x86.
  5. Then you are prompted to choose a name for the emulator. I will use “test” and i am leaving everything as default (i.e. just put a name and click “Finish”)
  6. Now you should see a list of the devices you have configured. Click on the green arrow to launch the emulator.

If everything goes smooth, you should see the emulator. Also, use adb to check for active devices:

 adb devices -l

You may see:

ADB Device Listing

 If this is the case, you will not be able to deploy the application. The workaround for this is going to (on the emulator):

  1. Enable developer options (Settings->About.. and tap 7 times on the screen)
  2. Go to “Developer Options”-> “Revoke USB debugging authorisations”
  3. Kill the adb server with “adb kill-server” and then restart it with “adb start-server”
  4. Then enable and disable debugging. You should see a prompt to authorise USB debugging. Authorise it. When you list devices you should now see:
Correct Devices List

Correct Devices List

Now, the application can be deployed with (-g grants all runtime permissions):

adb -s emulator-5554 install -g [PATH_TO_APK]\App.apk

 You should see “Success” as the last message. If you now check the emulator should be on the list of applications.

The Base Application

The application is a simple interface that takes a username and a password as input and tests the parameters against internal values:

 

What’s that? I have mad Android Skills? Well, thank you. In order to make this more realistic, i will sign the application. For this you need JavaDK. We first generate the keystore and the key (password legitlegit):

 keytool -genkey -v -keystore hackme_testapp_legit.p12 -alias hackme_testapp_legit -keyalg RSA -keysize 2048 -storetype pkcs12 -validity 365

 Once you fill in some details about your “company” you will have a keystore on your desktop containing a certificate valid for a year (365 days). The alias for the key in this case is hackme_testapp_legit. In order to create a release APK, go to (on Android Studio): Build->Generate Signed APK. Fill in the information about the keystore and click Next. On the last screen, mark V1 (Jar Signature) and V2 (Ful APK Signature). Build type should be release. Click Finish. Your APK is built and should be on the application folder with the name [application name]-release.apk.

 Once more, in order to make things more realistic, we can generate another keystore and key for the rogue apk. Same command as before but you can call both the keystore and the alias hackme_testapp_evil.p12 and hackme_testapp_evil (password evilevil).

Changing the Application

So, what do i want to do here?
 
  1. I want to change used images and strings (resource manipulation)
  2. Find the credentials within the decompiled code (Java) and smali code
  3. Patch the application so we can have a successful login regardless of the password
  4. Demonstrate how to debug the application
 
 
Why all this? Well, this is a basic application and my objective is to show you how to use the tools i have described on {first article}.
 
 

Getting the “original” application

First, we need to use (from dex2jar scripts):
 
d2j-dex2jar.bat app-release.apk -o app-release.jar
 
 
to get a jar containing the .class files belonging to the application. Now, we need to get the resources:
 
apktool d app-release.apk -o app-release
 
 

Manipulating Resources

 Strings displayed on Android activities are classified as resources. As such, they can be found inside the res folder. If you use Windows search within the res folder you will find the strings on res\values\strings.xml. Let us change “HackMe” to “Hacked” and  “Successful Login” to “Ain’t nobody got time fo failure”. As for the images, they may be on mipmap-something or drawable-something folders, or both. The first are typically for launcher icons while the second are for activity images. Since i suck at Android, i ended up using launcher images for activity images so you will find everything on mipmap folders. No science here, just replace what you want with what you want but keep in mind the names should be the same. Also, for mipmaps, png images are used so, adjust your potential JPEGS. I am disregarding image ratios here with the argument “what is the worst that can happen?”. We have pimped the application. I will rebuild the application once i am done with the next part.

Find the Password and Disrupting Workflow

 So now we need to find the credentials. We can either look at the decompiled code (i.e. Java) or smali. Since this is a small and application leveraging to anti-reversing framework, it is peace of cake. Open JD-GUI and drag-and-drop the Jar we generated previously:

Decompiled packages

Decompiled packages

 In Android terms, the main application should be a subfolder within com. This happens because, the terminology to fully qualify an Android application package is [reversed company domain].[application name]. In this case, the company domain would be hackme[.]com and the application would be testapp.

As you can see, and if you click through those class files, only three files are of interest:

  1. HackMeMain.class
  2. SuccessLogin.class
  3. FailureLogin.class

 These files contain classes that inherit from AppCompatActivity and given the fact that we have three screens on the application, this is highly indicative that each of those files represent the Activities for the screens, success screen and failure screen, respectively.  Also, according to the decoded Manifest.xml file, there are indeed three activities. Let us look at the HackMeMain.class file:

HackMe credentials' check

HackMe credentials’ check

 Whenever we click on the Login button, we need an event listener to respond to this. That is what is happening within the setOnClickListener function. Within that function there is a definition of an anonymous class with a single function onClick. There is also an if statement checking the the contents of two EditText views. As a side note, JD-GUI was unable to decompile properly the name of both fields. They should be username and password as opposed to localEditText1 and localEditText2. This is acceptable since during compilation, some data is lost for multiple reasons (e.g. optimisation). So we have two string checks. agains “ADOGETORULETHEMALL” and “VERYZICRET” (username and password respectively). These are the credentials so we have another objective accomplished. Now, we want to patch the application to ignore the verification of the credentials and show the success screen all the time. We can do this in one of two ways:
  • Recreating the application:
    • Use JD-GUI to export the Java files (File->Save All Sources)
    • Create a dummy Android project with Android Studio and then replace all the resources, manifest, packages and code with the ones we managed to obtain.
    • Modify the Java code
    • Use Android studio do create and sign a new APK
  • Modifying the smali code and rebuilding the application

 The first approach is more time consuming and should be avoided if the smali is readable. If you look within the folder created by the apktool, you will see a smali folder. This folder contains the smali code associated with the application. We can look at smali using IDA Pro but, you must provide the .dex file. You can obtain this by opening the original APK with with an archive browser (e.g. Winrar, 7-Zip) and pulling off the .dex file. You can also open the APK file with IDA (with Administrator privileges) and choose the .dex file. When looking at IDA, you have to:

    1. Search for the methods starting with the class name you want: HackMeMain
    2. Choose the method you want: HackMeMain_onCreate@VL
onCreate function

onCreate function

 
 I have “oranged” the relevant part. As you can see, an instance of HackMeMain$2 is instanced and moved to v3. The second line is just the constructor being called. On the last line, setOnClockListener is called with the object associated with the button view, obtained a few lines earlier as well as the HackMeMain$2 instance. So, we must now look at HackMeMain$2_onClick since the credentials’ verification is performed within that method.
 
And without further ado:
 
credentials' check
 
 So basically, the output of String.equals is checked agains zero. If it is zero, it jumps to the failure condition and the due screen is shown (roughly speaking). If you are familiar with Java, the equals method returns True or False which internally are represented as 1 or 0, respectively. In order to patch the program we can simply force a Jump to the success condition. Once you localise the file, you can pretty much break the check (almost) wherever you want:
 
Now, we recompile:
apktool.bat b [APPLICATION_FOLDER] -o ModifiedApp.apk

And we sign using our malicious key:

 jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore hackme_testapp_evil.p12 ModifiedApp.apk hackme_testapp_evil 

Then, deploy:

 

adb -s emulator-5554 install -g [PATH_TO_MODIFIED_APK]\ModifiedApp.apk
 

 

Debugging

 Debugging in this case, where we can import the decompiled application to Android studio is relatively simple. Also, in this case, the credentials are hardcoded so if you can read Java code, you should be able to understand the verification mechanism without going through a debugging process. In any case, let us assume that the algorithm is much more complex and you would like to step through the verification using a debugger. Before debugging the application you can deploy using either adb or Android studio. Mind that if the application is protected using anti-reversing frameworks like Proguard, you will not be able to deploy the application through Android Studio. For those cases, you need adb. Once it is deployed you can attach the debugger through Android Studion. The Proguard case will make more sense when i dive into such topic. For now, let us keep it simple. With the project on Android Studio:

  • Click on the grey bar at a location aligned with the instruction where you want execution to stop:

Android Breakpoint

  • Run->Run ‘[application name]’ and select the device. Press OK
  • Confirm on the emulator that the application was launched
  • On top, click “Attach debugger to Android Process” and select the application. Keep the debugger type as Auto. According to the documentation, if you don’t have native code like C or C++, the debugger will only debug Java code, otherwise, it will switch accordingly (called Dual mode). You should see this:

Debugger is attached

  • Insert the username and the password and click Login. You should see:

Breakpoint Hit

 From this point on, just jump around using the typical instructions: Step Over, Step Into, Step Out, etc. The Variables window allows you to inspect the fields of the Java objects that are within the context of the analysed code.

Final Notes

 The example i have presented here was very simplistic. In the absence of an obuscator/anti-reversing mechanism, you disrupt the workflow of an application by modifying the Smali code or by creating a whole new application with Android studio and modifying to taste. Keep in mind you must sign the application before deploying it. If ProGuard was enabled on Android Studio the reversing process would have been much less smoother. I will dive into that subject on another post later. In any case, this should help you understanding the basics. From here, it is a matter of scaling/increasing effort and time to achieve your purpose.

Stay safe 😉
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s