Analysis of Mobile Apps - An Introduction

Analysis of Mobile Apps

An Introduction

Tomaso Vasella
by Tomaso Vasella
on August 11, 2022
time to read: 17 minutes

Keypoints

How to Analyze Mobile Apps

  • Mobile apps are part of our everyday life, their security is therefore very important
  • Getting started with mobile app analysis is not difficult
  • Many powerful tools and utilities exist
  • Static and dynamic analysis allow deep insights into mobile apps
  • Even with simple means you often get pretty far

Mobile applications, usually simply called apps, are applications designed for use on mobile devices such as mobile phones or tablets. Mobile apps must take into account the requirements and limitations of mobile devices, however, current mobile devices have considerable memory and processing power. Apps exist for virtually every conceivable purpose from the simplest utilities and entertainment applications to comprehensive programs such as online banking and they are a part of everyday life. By mid-2022, the leading app stores – the digital distribution platforms for apps – include over 2 million apps.

Many apps use sensitive, often personal data or have access to it and communicate with various services on the Internet. Against this background, it is useful and interesting to analyze the functionality and data communication of apps from a security perspective. This article shows a pragmatic introduction to the possibilities of analyzing Android apps.

Reverse engineering generally refers to the technical investigation of a ready-made application or system with the goal of obtaining as much detailed and accurate information as possible about how it works, often with the aim of recovering the source code or a representation of it. Depending on the intention, the focus can also be only on the behavior or communication of an application (see also the articles Introduction to the World of Disassembling and Decompiling and Reverse Engineering).

A large number of useful tools exists for reverse engineering. The use of some of them with regard to the analysis of Android apps is illustrated in the following sections.

Anatomy of an Android App

For the following considerations, an intentionally insecure Android app from the MSTG Hacking Playground which was created for testing purposes is used. Android Apps exist as APK files (Android Package Kit) and they are normal ZIP archives:

$ file MSTG-Android-Java.apk 
MSTG-Android-Java.apk: Zip archive data, at least v0.0 to extract, compression method=deflate

$ unzip -q MSTG-Android-Java.apk -d MSTG-Android-Java
$ ls MSTG-Android-Java
AndroidManifest.xml  assets  classes.dex  lib  META-INF  res  resources.arsc

The usual contents of an APK file which are also listed in the above example are:

Static Analysis of APK Files

In the following sections static analysis of Android apps is discussed.

Extraction

For unpacking and analyzing APK files, there are various tools with different functionalities. The Android Studio contains an APK Analyzer and therefore is one of the most convenient tools, even though it is rather resource-hungry. The APK analyzer can be started through the menu Build / Analyze APK.

An APK opened in Android Studio

The content of the APK is unpacked and can be further analyzed. The resources present in the APK as binary files are also unpacked and for example the AndroidManifest.xml file can be viewed in plain text.

Analysis of the Dalvik Byte Code

When analyzed via Android Studio, the Dalvik bytecode from the classes.dex file is automatically decoded and can be viewed directly.

Dalvik Byte Code in Android Studio

If you want to have a closer look at the code, you can display the bytecode directly by right-clicking:

Dalvik Byte Code in Android Studio

The byte code is displayed as smali, a human readable representation (disassembler syntax) of the byte code. It is also possible to convert the Dalvik byte code to Java byte code. This often works even if the Android app was originally written in Kotlin. Subsequently, the Java bytecode can be analyzed with a Java decompiler, which allows even more convenient viewing.

As an alternative to using Android Studio, the command line tool Apktool can be used. This tool sometimes achieves even better results, especially when dealing with more complex apps:

$ java -jar apktool_2.6.1.jar d MSTG-Android-Java.apk 
I: Using Apktool 2.6.1 on MSTG-Android-Java.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: ~/.local/share/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...

$ ls MSTG-Android-Java
AndroidManifest.xml  apktool.yml  assets  lib  original  res  smali

This tool converts the Dalvik bytecode directly to smali:

$ head -20 smali/sg/vp/owasp_mobile/OMTG_Android/MyActivity.smali 
.class public Lsg/vp/owasp_mobile/OMTG_Android/MyActivity;
.super Landroidx/appcompat/app/AppCompatActivity;
.source "MyActivity.java"

# static fields
.field public static final EXTRA_MESSAGE:Ljava/lang/String; = "com.mycompany.myfirstapp.MESSAGE"

# direct methods
.method public constructor <init>()V
    .locals 0

    .line 12
    invoke-direct {p0}, Landroidx/appcompat/app/AppCompatActivity;-><init>()V

    return-void
.end method

A big advantage of using the the Apktool is that the decoded files (XML etc.) but also the decoded smali code can be edited and afterwards an APK can be recreated with the edited files.

Conversion to Java Code

Another useful tool in the analysis arsenal is dex2jar, which converts the Dex files contained in APKs directly to Java classes. Afterwards, the Java code can be easily decompiled.

$ dex-tools-2.1/d2j-dex2jar.sh MSTG-Android-Java.apk
dex2jar MSTG-Android-Java.apk -> ./MSTG-Android-Java-dex2jar.jar

The .jar file created in this way can then be analyzed with a Java decompiler, in the following example the JD-GUI is used for this purpose.

Java Code in JD-GUI

Similar results can be obtained with the tool jadx, which also converts Dex bytecode to Java.

As an example of a possible approach for static analysis, we will use one of the test cases in the test app mentioned above. This app contains a function for creating an encrypted SQLite database.

MSTG App Encrypted SQLite MSTG App Encrypted SQLite

The corresponding code is easy to find in the decompiled version:

Java Code for the SQLite Encrption

When looking at the method SQLiteEnc() it becomes apparent that the secret used for the encryption of the database must be returned from the method stringFromJNI(). Interesting is the method System.loadLibrary() which loads a native library compiled for the CPU architecture in use. The method stringFromJNI() is prefixed with the keyword native which means that this method is implemented in native code using the JNI (Java Native Interface). Listing the directory lib/x86 shows the following files:

$ ls MSTG-Android-Java/lib/x86
libnative-lib.so  libsqlcipher.so

$ file libnative-lib.so
libnative-lib.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=5feb6239bf0911b46bbdf5ff1bccd29570bbb00f, stripped

The secret we are looking for must therefore be generated by a function of the libnative-lib.so file. There are various possible approaches for the static analysis of this library. As an illustration a short analysis with the tool Ghidra is shown here. First, a new project must be created via the menu Menu File / New Project, then the library can be loaded via drag and drop, whereby the defaults are already correct here:

Import in Ghidra

Double click on the imported file opens the code browser, which suggests an analysis of the file. In this example all suggested defaults are accepted.

Analysis in Ghidra

After that we search for the name of the function we found in the Java code: Search / Program Text:

Searching for the Function Name

The locations of the identified functions are then displayed:

Found Function Names

Clicking on the name navigates to the corresponding code location:

Navigation to the Function

If the mouse pointer is hovered over the hex values of the variable puVar1, it can be seen that this code seems to construct a string from dwords. The dwords are 32 bits long, therefore the instructions EAX + 0×4, EAX + 0×8, etc.:

Displaying Characters

By right-clicking the hex values can be converted with the following result:

Converted hex values

The sequence \0 suggests a string terminated with a null byte and it can be assumed that the wanted string must be read backwards, resulting in the secret we are looking for: S3cr3tString!!! While this example is interesting and illustrative, one could have simply searched for existing strings in the binary:

$ strings /tmp/MSTG-Android-Java/lib/x86/libnative-lib.so
...
[^_]
[^_]
S3cr3tString!!!
cannot allocate __cxa_eh_globals
std::__libcpp_tls_set failure in __cxa_get_globals()
execute once failure in __cxa_get_globals_fast()
...

Similar functionality is available in Ghidra via Window / Defined Strings

Viewing the Defined Strings

Dynamic Analysis

Now that we have seen some methods for static analysis of APKs and their contents, it is useful to also take a look at the possibilities for dynamic analysis, i.e. analyzing the behavior of Android apps at their runtime. Conveniently, with the Android Emulator as part of Android Studio, there is a comprehensive way to emulate Android devices, including the ability to install apps from the Google Play Store. A new virtual device can be created via Tools / Device Manager / Create Device where the desired Android version can be chosen as well as a version with or without Playstore. Hint: If you want to easily gain root rights on the virtual device later, you have to choose an Android image without Playstore.

Creating a Virtual Device

The virtual device is created at ~/.android/avd/<device-name>.avd/ and can be started via the Android Studio or usind the command line. As soon as the virtual device is started, it can be reached with the Android Debug Bridge:

> ~/Android/Sdk/platform-tools/adb devices
List of devices attached
emulator-5554    device

A variety of different methods and tools are available for the dynamic analysis of Android apps, one of the best known and most powerful is probably Frida sein. In the following section, a convenient method for analyzing the communication behavior of Android apps is shown, a step that is required in practially every analysis. An obvious idea for this is to route the communication of apps or of the entire device through a proxy and thus be able to follow the communication. With the emulator, a proxy can be set very easily via the GUI:

Proxy Settings in the Android Emulator

With older Android versions, this worked quite well after the proxy’s certificate is installed in the device’s trust store and as long as the apps do not use certificate pinning. With Android versions from Android Nougat onwards, however, it will quickly become evident that most apps no longer communicate with this setup. One reason for this is that in such versions, the apps no longer trust the certificates installed in the user trust store. One could decompile the app, alter the file network_security_policy.xml and then recompile the app to get the app to trust the certificate in the user store.

A more convenient method is to install the custom certificates in Android’s system trust store which is located at /system/etc/security/cacerts. However, this requires obtaining root privileges on the device which is very simple to achieve on virtual devices using the Android Emulator and a system image without Playstore. Conveniently, there is the relatively new tool HTTP Toolkit which makes this very simple. After the tool is unpacked and started, it can be connected directly to a started emulator via “Android device via ADB”.

Connection with HTTP Toolkit

As long as the system image in use allows root privileges, the following steps are fully automated.

Installed HTTP Toolkit

HTTP Toolkit includes a request browser that can be used to easily view the communication. In this example, the MSTG Test App was used again.

Web Request of the MSTG App Viewing the Requests in HTTP Toolkit

Summary

Today, many tools, some of them very powerful, are readily available for the analysis of Android apps. Simple static and dynamic analyses can be realized with relatively little effort and without overly complex environments. Although in practice much more difficult cases occur regularly, whether due to code obfuscation or for other reasons, one often gets quite far with simple steps. Even when spending only a limited amount of time on looking under the hood of mobile apps and viewing their basic behaviour, is is often possible to find weaknesses, especially since insecure practices such as usind hard-coded API keys or credentials are unfortunately still rather common in mobile apps.

About the Author

Tomaso Vasella

Tomaso Vasella has a Master in Organic Chemistry at ETH Zürich. He is working in the cybersecurity field since 1999 and worked as a consultant, engineer, auditor and business developer. (ORCID 0000-0002-0216-1268)

Links

You want to test the security of your firewall?

Our experts will get in contact with you!

×
Security Testing

Security Testing

Tomaso Vasella

The new NIST Cybersecurity Framework

The new NIST Cybersecurity Framework

Tomaso Vasella

Flipper Zero WiFi Devboard

Flipper Zero WiFi Devboard

Tomaso Vasella

Denial of Service Attacks

Denial of Service Attacks

Tomaso Vasella

You want more?

Further articles available here

You need support in such a project?

Our experts will get in contact with you!

You want more?

Further articles available here