Android Mobile Application, Runtime Mischief

Introduction

7 Elements conduct a large number of mobile application penetration tests as part of our security consulting services. An area of interest amongst our customers is our ability to bypass root detection, local application logic and access sensitive objects which are encrypted at rest.

What will this blog cover?

This blog will cover attacking mobile applications at run time using the Xposed framework. Firstly, we need to understand what the Xposed framework is and how it works.

What is the Xposed Framework?

Xposed framework provides a means through which applications can be modified without having to recompile the APK file with new code. The Xposed framework includes modules as part of a repository that can be installed to hack both the android system and applications on the device. These modules are not created for malicious purposes and for example can be used to disable unwanted or untrusted functionality in an application or modify the android system to display different colours or logos.

The following link provides a good description of its capability: Link

How does hooking work?

How Xposed is able to hook and exploit applications at runtime. Quoted from the link above:

There is a process that is called “Zygote”. This is the heart of the Android runtime. Every application is started as a copy (“fork”) of it. This process is started by an /init.rc script when the phone is booted. The process start is done with /system/bin/app_process, which loads the needed classes and invokes the initialization methods.

This is where Xposed comes into play. When you install the framework, an extended app_process executable is copied to /system/bin. This extended startup process adds an additional jar to the classpath and calls methods from there at certain places. For instance, just after the VM has been created, even before the main method of Zygote has been called. And inside that method, we are part of Zygote and can act in its context.”

Therefore, Xposed sits in a very powerful position on the phone and through the modules can “patch” the applications to modify their actions during specific operations.

Root Detection

What is root detection?

Straight from Wikipedia: “Rooting is the process of allowing users of smartphones, tablets and other devices running the Android mobile operating system to attain privileged control (known as root access) over various Android subsystems. As Android uses the Linux kernel, rooting an Android device gives similar access to administrative (superuser) permissions as on Linux or any other Unix-like operating system such as FreeBSD or OS X.”

Common root detections can be seen here: Link

Can Xposed help with bypassing root detection?

Yes, it can due to the powerful position Xposed operates in. We can identify root detection methods disable or return expected data.

All applications make use of different methods as part of root detection, some more basic, while others are constructed by paid for services and defensive frameworks. Therefore, we normally carryout specific engagement based coding to bypass the security controls.

Xposed already includes one good example of a module that can bypass a number of root detection checks. The modules is called RootCloak: Link

Simple Example

A simple example of root detection is to look for known packages on the device using the Android Package Manager. The following code extracted from RootCloak details one method for hooking the native Package Manager application, changing the package being inspected and returning package not found:

findAndHookMethod("android.app.ApplicationPackageManager", lpparam.classLoader, "getPackageInfo", String.class, int.class, new XC_MethodHook() {
 @Override
 protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
         if (debugPref) {
         XposedBridge.log("Hooked getPackageInfo");
         }
         String name = (String) param.args[0];
 
         if (name != null&&stringContainsFromSet(name, keywordSet)) {
         param.args[0]=FAKE_PACKAGE; // Set a fake package name
         if(debugPref) {
         XposedBridge.log("Found and hid package: " + name);
         }
        }
      }
   });

The code above hooks the appropriate package manager class and inspects the package that is being reviewed. If the package matches known list of packages we want to hide, the package is automatically changed to a fake package name. The response to this from the package manager is therefore “did not find the package you were looking for”.

Some applications should be allowed to run on rooted devices, what other defences are there?

Hook Detection

While root detection is important, a number of our clients allow their applications to be run on rooted devices opting instead to use hook detection to stop malicious activity at run time.

What is hook detection?

Hook detection is built into the application and detects if a rogue application has intercepted a called function that resides in a system library or within the application.

Real world example:

On a recent engagement we raised the lack of hook detection as a security issue. On returning to the site the company had implemented a new version of the application with hook detection enabled. The implementation of hook detection was capable of detecting that the application was running on a device flashed with Xposed and therefore permanently hooked and would not execute.

While a large percentage of the code base was obfuscated, the main activity included a method hDetection_Fail(). Through reverse engineering and code review we discovered that this method was used by application to identify hooking. We then created a module for Xposed that located the running application, hooked the appropriate class and disabled the method before it could kill the application.

The following snippet of code was used to bypass the hook detection:

public class Doug implements IXposedHookLoadPackage {

    public void handleLoadPackage(final LoadPackageParam lpparm) throws Throwable {

        String packageName = "com.App.Test";
        String classToHook = "com.App.Test.MainActivity";

        if (!lpparm.packageName.equals(packageName))
            return;

        XposedBridge.log("Doug is in the App");

        findAndHookMethod(classToHook, lpparm.classLoader, "hDetection_Fail", XC_MethodReplacement.returnConstant(null));

    }

The outcome of loading this module as part of the Xposed framework was that the application ran, identified that it was hooked, jumped into the function hDetection_Fail and then exited the function with null and continued to operate as normal bypassing the hook detection, by using hooking………. Pause for a smile.

Where can I learn more about Xposed?

The Xposed framework syntax is large and its capability vast. The following links detail the functions included in the framework:

More Real World Examples

We downloaded a random password safe app from the Playstore. This password safe application utilises encryption and hashing and stores data in an encrypted format in the database. This demonstration is not to show you how to hack a particular application but instead should demonstrate the depth to which Xposed can impact an application.

Reverse engineering the code base is relatively simple especially when the author does not implement obfuscation routines. OWASP mobile testing, M9 Reverse Engineering – Link.

Let’s focus on the login part of the application and attack it head on

On the application we discovered the following code:

public static boolean validatePassword(String paramString1, String paramString2)

  {

    return validatePassword(paramString1.toCharArray(), paramString2);

This looked interesting and definitely worth dumping the contents of the two string values. Going ahead and doing this produced the following results (Don’t worry code shown in next segment):

07-26 21:13:26.508 8410-8410/? I/Xposed: Doug is in password app

07-26 21:13:32.378 8410-8410/? I/Xposed: Doug – Activity Called……..

07-26 21:13:32.388 8410-8410/? I/Xposed: Doug – Found string1: letmein

07-26 21:13:32.388 8410-8410/? I/Xposed: Doug – Found string2: 1000:161eacdbb11a1d1b01646bc55b351926ec68d3bdc36b0e88:e709c77356120e9e347aac5d7781252919f5f24995762105

Clearly this is no ordinary compare function. However, it should be noted that it is not uncommon to see a compare being undertaken against the actual stored password string. Looking further into the code we see the following output:

public static boolean validatePassword(char[] paramArrayOfChar, String paramString)

  {

    String[] arrayOfString = paramString.split(":");

    int i = Integer.parseInt(arrayOfString[0]);

    byte[] arrayOfByte1 = fromHex(arrayOfString[1]);

    byte[] arrayOfByte2 = fromHex(arrayOfString[2]);

    return slowEquals(arrayOfByte2, pbkdf2(paramArrayOfChar, arrayOfByte1, i, arrayOfByte2.length));

  }

This indicates that the password is stored as a PBKDF2 hash. This sucks, when it comes to bypassing the authentication mechanism. Even with the salt and the number of iteration of the cipher we still need to brute force the password. The good thing is that this can be done offline rather than within the application removing the potential to lock the password safe application.

Let’s take a different approach

Alternatively, we could wait for the user to enter the correct password and check the logs. As this appears to be following reasonably good practices we will chance our luck. The purpose of this function is to return a Boolean value, True or False. Xposed can automatically return any function as a Boolean value. The following code demonstrates dumping the contents of the strings as well as forcing the login by creating a Boolean value of true.

public class Bypass implements IXposedHookLoadPackage {

    public void handleLoadPackage(final LoadPackageParam lpparm) throws Throwable {

        String packageName = "com.Application.password";
        String classToHook = "com.Applicaiton.password.utils.passwords.masterPW ";

        if (!lpparm.packageName.equals(packageName))
            return;

        XposedBridge.log("Doug is in password app");

        findAndHookMethod(classToHook, lpparm.classLoader, "validatePass", String.class, String.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                XposedBridge.log("Doug - Activity Called........");
                //XposedBridge.log("--------------------------------------------");
if (param.args[0] != null ) {

                XposedBridge.log("Doug - Found string1: " + ((String) param.args[0]));
                }
                if (param.args[1] != null ) {
                    XposedBridge.log("Doug - Found string2: " + ((String) param.args[1]));
                }
                if (param.args[0] != null) {
                    // modify the result of the original method
param.setResult(true);

                    XposedBridge.log("Doug says let me in");
                }
                XposedBridge.log("--------------------------------------------");
            }
        });

    }
}

The output of this looks as follows:

07-26 21:13:32.378 8410-8410/? I/Xposed: Doug – Activity Called……..

07-26 21:13:32.388 8410-8410/? I/Xposed: Doug – Found string1: bang

07-26 21:13:32.388 8410-8410/? I/Xposed: Doug – Found string2: 1000:161eacdbb11a1d1b01646bc55b351926ec68d3bdc36b0e88:e709c77356120e9e347aac5d7781252919f5f24995762105

07-26 21:13:32.388 8410-8410/? I/Xposed: Doug says let me in

So the cool thing is that the application allowed us to gain entry to the password safe application but unfortunately all the values and contents were encrypted using the password and therefore the details contained within each entry are unintelligible. As they used the password bang to decrypt the data in the application.

The following screenshot shows the password safe application in operation but the values are of no use to an attacker:

Hooking Blog - Encrypted pass-safe

While we could not break into the application using this method; it demonstrates yet another way in which the code can be manipulated at run time in line with its current workflow.

To recap, we have the password being sent into the application by any user, so we could capture the password at this point of the workflow. Secondly, we have the salt, the number of iteration and the hashing mechanism, to attempt password guessing techniques offline. This may be a viable attack vector as a lot of password safes can destroy themselves after a number of failed login attempts.

Okay, I am getting upset now, let us take another approach!

While the application can be attacked straight on through offline brute forcing, it is not really the result we hoped for. Let’s look at another attack vector to target users while they use the application. By using the application, we can see that it makes use of the clipboard to copy passwords out of the application to be pasted into login forms or other applications. It is possible to attack the application by targeting the clipboard.

Step Back! Why am I doing all the work…. what about you?

Getting started with this type of code manipulation can be difficult. Therefore, it’s always useful to have good examples of applications or hooks that other users have written. There is a really good application for security testing called Inspeckage, that has a number of prebuild hooks and allows users to set new hooks based on the Class name or the Method within the application. Writing your own code means deploying a module and then having to reboot the phone so that the module can be enabled. Inspeckage once enabled can be modified to carry out new actions through the hook+ option that will automatically take effect. This can be really useful when testing an application that is obfuscated. It allows the tester to see what variables are being passed between methods, which is a great starting point.

Inspeckage can be found via the following Link.

Demo of Inspeckage, capturing clipboard data

We can use Inspeckage to capture all the clipboard interactions from within the specific application, as previously discussed. The following output details the Inspeckage hook application capturing the clipboard information every time some data is passed to it. This information is output to Logcat and then displayed through the Inspeckage web page under the Misc category, as detailed below:

Hooking Blog - Inspec

Conclusions

Hopefully we have been able to demonstrate that it is possible to manipulate applications to bypass root detection, hook detection and retrieve sensitive information all at run time. The following recommendations should be reviewed when coding an application.

  1. Deploy complex root detection routines where possible. This should also terminate the application locally and not send information back to a back end server to terminate the communications (SSL Pinning issues – sure to be another blog sometime).
  2. Deploy additional hook detection in sensitive functions to minimise misuse.
  3. Smart coding. Smart coding covers building applications in line with the software development lifecycle and including security into each stage of an applications development. Too often we see obfuscation routines being used as the only security mechanism in an application.
  4. Obfuscate all code everywhere. This can be achieved both throug h automated means by paid for services but also in the coding themselves. Taking away the context of variables and functions to minimize an attackers understanding of the application.

There are loads of additional good practices that could be a blog on their own. For more information check out OWASP Mobile Security Project – Link