Reverse engineering refers to the process of taking something apart to see how it works, whether it’s a physical object such as a lock or in this case, a mobile application. Decompiling is a form of reverse engineering in which a mobile app is analyzed by looking at its source code. A decompiler program examines the binary and translates its contents from a low-level abstraction to a higher-level abstraction.
The NowSecure services team frequently performs reverse engineering on mobile apps to uncover security vulnerabilities and privacy flaws. We rely on a mix of custom and open-source tools in our pen testing, including decompilers. This tutorial will help you master the basics of analyzing an Android app and what to look for.
What Is Android Reverse Engineering?
Android reverse engineering analyzes the inner workings of a mobile app by examining its code, structure and behavior. Tearing apart an Android app helps people gain insights into its functionality, security mechanisms and vulnerabilities.
The process of reverse engineering an Android mobile app entails extracting code, resources and assets from its compiled form (APK file) back into human-readable format and is typically performed using tools such as decompilers, disassemblers, debuggers and specialized frameworks.
Security researchers, mobile app developers and pen testers typically reverse engineer Android apps for the following legitimate reasons:
- Learn about the app functionality: People can gain insights into how an Android app and the operating system work.
- Conduct code analysis and modification: Developers can analyze the code, identify potential bugs and modify the app with new features or customizations.
- Perform security analysis: Examining the mobile app aids in identifying security and privacy vulnerabilities such as insecure data storage, weak encryption or unsecured network communications.
- Learn about compatibility and interoperability: This can shed light on how an app interacts with other components, libraries or systems.
- Port or migrate an app: Reverse engineering can aid in porting a mobile app from one platform to another or migrating to a new version of the Android mobile operating system.
Android Reverse Engineering Specifics
An Android binary is called an APK, which stands for Android Package Kit. The APK contains application data in the form of zipped Dalvik Executable (.dex) files. DEX files consist of the following components:
- File Header
- String Table
- Class List
- Field Table
- Method Table
- Class Definition Table
- Field List
- Method List
- Code Header
- Local Variable List
For further information on .dex files, refer to the official Android documentation.
A decompiler is a tool that takes the contents of the APK and attempts to show the original code that was used to build the different functionalities of the app. Although this process is fairly consistent, in some special cases the decompiler might fail to reverse a small part of the application.
There are far more aspects of reverse engineering than can be covered here, so this blog will zero in on some of the most common issues we find in production Android apps when we dig in with a decompiler. While there are many decompilers to choose from, I prefer jadx-gui because it’s a simple yet effective tool that has a user-friendly interface. We will use it to analyze the “InsecureBankv2.apk”, an open-source Android application that purposefully contains many vulnerabilities.
Getting Started Analyzing the APK
Open the APK using jadx-gui and you’ll notice a menu on the left hand side of the screen containing some dropdown sub-menus. This is common across all Android applications.
Each dropdown menu is mostly self explanatory. The “Source code” section contains the different files that make up the application’s code. The “com” usually contains the main part of the application code, including core functionalities, while other sections include supportive/complementary components such as libraries, frameworks and other resources utilized to create the application. The “Resources” section contains app assets, versions, certificates, properties, the Android Manifest, APK signature info, etc.
Exploring the Android Manifest
Let’s start by analyzing the app’s manifest, AndroidManifest.xml. This file is an important part of the application because it provides data about the application structure and metadata, its components and the requirements. This is done by establishing user permissions, app activities, intents, actions, etc. Double clicking on the AndroidManifest.xml file in the left hand side menu opens the following file:
Notice how it’s segmented into different sections. The first few lines contain the different user permissions declared by the application. These will always be variable and dependent of the app that you’re trying to reverse engineer but it’s always good practice to make sure the app isn’t requesting more permissions than it should have or needs to use. For example, we’ve seen many apps request location permissions without even having a feature that requires the user’s location. This usually ends up in some kind of user personal information being disclosed and, in most cases, is not even done intentionally by the developer.
Other important things to look out for in the manifest are the
debuggable and the
allowBackup flags. As the name suggests, the first one refers to the app being in debug mode, meaning it’s possible to attach a debugger to the application’s process and execute arbitrary code. For the last few years, Google has not allowed apps that have this flag enabled to be published in the Play Store. However, it’s still important to take this into account when developing an application, especially since builds are often exchanged between developers. If one falls into the wrong hands, it could have negative consequences. The second flag,
allowBackup, defines whether application data can be backed up and restored by a user who has enabled USB debugging. This means that hackers connecting to a device via adb can easily obtain any application data that is stored on the device, including personal data on private storage.
As you see in the screenshot below, the Android Manifest shows that the InsecureBankv2 app has both of these flags enabled.
The Manifest may also include exported components such as activities, broadcast receivers, services, etc. These allow external applications to access data in the application, which is why it’s always important to check for exported components listed as
true because these can potentially leak user data to other applications. Components that are not intended to be accessed by other applications must always be set to
false. In the sample application in question, we can see that multiple content providers are exportable:
Searching for Hardcoded Values
Next, look for hardcoded credentials — that is, anything hardcoded in an app such as usernames, session tokens, secret keys, etc). Attackers can often easily access this information and this app is no exception.
Hardcoded credentials can be found most anywhere within the app so we recommend using jadx’s search function to look for these values. I usually start by looking for hardcoded secret keys. These can be somewhat easy to recognize as they will usually be stored in an array of bytes. In this case, searching for the word ‘secret’ reveals a glimpse of what we might find in the app.
Be sure to go over every result especially when searching for a term like ‘secret’ because it likely reveals sensitive values. Navigating to
com.android.InsecureBankv2.CryptoClass shows some valuable information, including an initialization vector for one of the utilized cryptography methods and the crypto key.
As we can see, the ivBytes variable declares a hardcoded byte array of zeros, which is used as the initialization vector of the cryptographic routines for encryption and decryption that can be seen in the methods aes256encrypt and aes256decrypt. While these routines rely on CBC as a mode for encryption, the usage of a null IV during the initialization process makes CBC mode ineffective as the resulting cryptographic blocks will not have the variation that securely generated IVs would provide, making them prone to collision attacks (similar to ECB mode).
Cool! We have identified a bad crypto practice that we can now turn into a finding. While many other crypto-related findings here could capture our attention, we’ll move along now to cover other things.
Analyzing WebViews in an App
WebViews are an embeddable browser that a native application can use to display web content. They might not be implemented in every application but when they are, they can provide a risky attack vector. Some important parameters/flags to test on WebViews are
EnableSafeBrowsing. The first one allows inspections of WebView content from a remote browser, so it must always be set to false. Searching for this returns no results so we don’t see this being utilized in this test application, but don’t forget to take it into account when reversing other apps. The second one clears the WebView caches from the client device. This can mitigate issues relating to sensitive data stored on the local file system. We actually do see this one used by one Google library imported by the application — not bad!
EnableSafeBrowsing displays warnings when a compromised or known phishing website is loaded in the WebView. We don’t see this one utilized in the application either. By further analyzing WebViews in this app, we find that the
For those who lack the time or expertise to reverse engineer a mobile app to pinpoint mobile app vulnerabilities to remediate, NowSecure has solutions and services that can help. The NowSecure Platform automated mobile appsec testing solution reduces the labor entailed in assessing apps and provides consistency. Our professional services team offers mobile application security training and is available to conduct comprehensive mobile penetration testing. Consult this useful checklist for evaluating mobile application security companies to perform mobile application penetration tests.