Under the Hood: Reversing Android Applications
For several years now, there has been an explosive increase in the use of mobile applications. Included in this staggering increase of mobile software are applications that store, process, and transmit personal and sensitive data. While they are not the only players, the Google Android and Apple IOS platforms have altered our daily computing habits.
Have you ever wondered what's under the hood of your favorite mobile app? In this article, we will explore how you can go behind the scenes and see what's under the hood of your favorite applications for the Android platform. We will outline what the Android development process looks like, what's inside an Android application, and what tools can be used to examine them. We will also explore how one might modify an existing Android application, to what extent it can be done, and some caveats.
Behind the Curtain
Before we dive right in to detailing exactly how to crack open your favorite mobile applications, let's talk a bit about what goes in to developing these programs.
Android applications are really Java applications based around Google's R class, which extends java.lang.Object. Google developed the Android API in Java and all Android applications extend some part of this functionality. Other components include XML configuration files (AndriodManifest.xml, strings.xml, and main.xml to name a few) that define graphic resources, what permissions the application requires, how things are laid out and positioned on the screen, as well as other technical requirement definitions.
When they are compiled into byte code, Android apps are ultimately .dex (Dalvik executable) files. These .dex files are interpreted by the Dalvik virtual machine and executed as applications. We'll talk more about the .dex format when we cover which tools can be used to reverse an Android application.
One interesting aspect of the Android platform is that the packaged applications have no built-in protection mechanism to prevent reversing. The protection is essentially built into the Android operating system in the way of mechanisms meant to disallow access to parts of the file system on your device. Since there is only interpreted code and no compiled code in this environment, reversing applications is essentially as easy as finding the right tools and using them effectively. Of course, more direct access to the code means more opportunity to find flaws in business logic, implementation flaws, or the use of poor coding practices.
A Brief Outline of Developing for Android
When breaking apart .apk archives, a general understanding of the Android development process is very helpful. Below is a generalized, high-level version of the process to give you a basic understanding of how it all works:
- Set up an Android development environment. Google has detailed this process in the document entitled 'Installing the SDK' here http://developer.android.com/sdk/installing.html. All major operating systems are supported.
- Develop code in Java. We'll go over a sample application later.
- Create packages. This can be done via the Eclipse IDE http://www.eclipse.org or by using command-line tools.
- Test applications in a VM or on a real device
- Deploy to the Market
This overview of the development process is sufficient for the purposes of this article. However, if you'd like more details on developing Android applications, take a look at Google's Android Developer Guide http://developer.android.com/guide/index.html.
Now that we have an idea of what the end-to-end development process is like, let's take a look inside the .apk file itself.
Android Packages Dissected
Let's take a quick look at what goes in to an .apk file. Android applications have a basic structure that must be followed. This list is not meant to be a comprehensive one, but rather a place to start.
The following is a short list of important items that are included in any Android source project:
AndroidManifest.xml – This is an essential XML configuration file for your application that defines properties such as the package name, the minimum required Android OS version this application will run under, icon, and label definitions. One of the most widely known properties of an Android application is defined in this configuration file: the required application permissions.
/src – The location of your source (.java) files.
/res – A resources folder that contains files related to user presentation. Graphics and layout XML documents are typically found here.
/res/layout/main.xml – This configuration file contains definitions that control the layout of the main application. The file name 'main.xml' is a default value.
/res/values/strings.xml – As one can imagine, the strings.xml configuration file contains strings. These are static string definitions that are referenced in other places by your application. One important string object name is "app_name", which contains the name of your Android application. The file name 'strings.xml' is a default value.
When reversing an .apk, you are likely to encounter these files:
AndroidManifest.xml – This is the same configuration file that originates in your source project, except it is has been converted into a binary format.
/META-INF – This folder contains the following files: CERT.RSA, CERT.SF, and MANIFEST.MF. These files contain the application digital certificate, as well as a relative path and SHA1 digest for each file in the .apk.
classes.dex – The .dex archive containing all of the Java .class files
Security
Previously, we mentioned the AndroidManifest.xml configuration file and how it contains application permission definitions. The following line is an example of a directive to add permissions to an application:
[sourcecode]
<uses-permission android:name="android.permission.INTERNET" />
[/sourcecode]
The value "android.permission.INTERNET" denotes what permission is being required. This specific value allows the application to create network sockets, effectively giving it access to the Internet. The table below lists some additional common values. For a more exhaustive list, please see the android.Manifest.permission page found herehttp://developer.android.com/reference/android/Manifest.permission.html
Some common android.Manifest.permission values:
ACCESS_COARSE_LOCATION - Allows coarse location access (Cell / WiFi)
ACCESS_FINE_LOCATION - Allows fine location access (GPS)
ACCESS_WIFI_STATE - Allows access to WiFi network information
GET_ACCOUNTS - Allows access to account lists on the device
INTERNET - Allows network / Internet access
READ_CONTACTS - Allows access to contact data
VIBRATE - Allows access to vibration control / state
WRITE_EXTERNAL_STORAGE - Allows writing to external storage (i.e. SD)
The presence of these entries in AndroidManifest.xml is the reason you receive the following dialog from the Android Market:
Reversing
Now that we have an idea of what's inside of an Android application, how does one properly break these mobile programs down into something resembling their original form? There are a variety of open source tools that allow us to reverse the packaging and conversion processes necessary to create an Android application.
The following tools can be used to extract information from Android apk files:
apktool – a tool used for manipulating .apk files
Download: http://code.google.com/p/android-apktool/
jad – a Java decompiler (Windows only)
Download: http://www.varaneckas.com/jad
JD-Core + JD-GUI – another Java decompiler, supporting newer Java versions and features
Download: http://java.decompiler.free.fr
dex2jar – a tool for converting .dex files to .class files
Download: http://code.google.com/p/dex2jar/downloads/list (dex2jar)
The process for decompiling / reversing an Android app is as follows:
-Download the app that you wish to analyze from the Market onto your Android device.
-Copy the .apk file from your Android device to a PC. This requires full access to the file system of the device. I used a rooted Motorola Droid for this reason.The default path to the .apk files on a device is /data/app.
At this point, we should determine what our goal is. If we would simply like to examine or alter XML documents or graphics from the application, then using the following method is sufficient:
[sourcecode]
java –jar apktool.jar d file.apk destination_directory
[/sourcecode]
This will decompress the .apk file, re-creating the directory structure of the project. It will also convert the binary XML files into plain text XML. This is a quick and simple way to examine AndroidManifest.xml to see what specific permissions an application requires. During this process, the .dex code is also converted into the .smali format. The .smali format is essentially a disassembled version of .dex byte code. This is roughly equivalent to using a utility to generate assembly language from a binary that was written in C. While you will not get the original source code back from this process, you will get a very accurate representation of the original code that can be converted back into byte code.
If the goal is to examine .java source code, a more manual approach is needed. That process is detailed below.
-Decompress the .apk file(unzip file.apk)
-Convert classes.dex to a .jar file
dex2jar classes.dex
-Decompress the .jar file (unzip classes_dex2jar.jar)
-Decompile the byte code with jad (or similar tool)
jad –s .java *.class
At this point, you now have Java source files that are essentially equivalent to the original application. If you combine these two methods, you can acquire a very good understanding of how the original application works by reviewing XML configuration files and Java source files. While this is all well and good, you may be asking yourself - where do we go from here? Let's take a look at some more practical things that we can do aside from a simple review of source files.
Taking it to the Next Level
One thing you may be contemplating is how you can alter applications and rebuild them for installation on your device. From the perspective of security, the easiest targets of a reversed Android application using the methods described so far are the XML configuration files. Altering these files does not require a change in Java the source code. It also allows the alteration of permissions to be granted to the entire application. This can be useful if you want to inhibit the ability of an application to access certain resources or add additional permissions. One good example of this is removing android.permission.INTERNET from AndroidManifest.xml. This would effectively prevent the application from making network connections – perhaps for the purpose of disabling built-in ads. However, the impact of making such a change is much less than that of altering the Java source itself.
This approach can also be problematic as it does not take into consideration how the application is coded. It is very possible that removing a specific set of permissions will cripple the application and render it completely unusable.
There are a few challenges with altering the Java source of an existing Android application and repackaging it. First, the package must be signed with a key. There is a debug key available that is used for testing Android applications in VMs and on devices. However, signing with this key has a few side effects. Since you are not installing software from the market, the Android device must be configured to allow the installation of software from unknown sources. The other challenge here is that the zipalign tool will not be used on the package. According to the Android documentation this will cause the application to use more memory. This could make rolling your own applications undesirable without a developer key.
It's worth noting that there is an application that does exactly what has been described in the previous two paragraphs. That is to say, it appears to unpack .apk files, check for and remove undesirable permissions in AndroidManifest.xml, then rebuild and reinstall packages signed with a valid key. It's called Privacy Blocker and it is available in the Android Market. You can read more about it at the following URL: https://market.android.com/details?id=com.xeudoxus.privacy.blocker&hl=en
Our Example Application
To illustrate some of the points we have covered here, I have created a very simple sample application. The program simply fetches a pre-defined URL (Google's favicon) and displays it in a Webview container. The application requires android.permission.INTERNET.
The following screenshot illustrates the application with proper permissions on the left and the application with the permissions removed on the right.
Notice how the program attempts to load and display the graphic regardless of the fact that the application does not have the proper permissions to access the resource. This is because I did not code it to perform any type of check! This illustrates the previous point that changing permissions in the configuration files may have unintended consequences.
You can download the source here fetch.zip and the application here fetch.apk.
11 courses, 8+ hours of training
In Closing
We've covered what components comprise an Android application, how to break an .apk down to examine the contents, and what tools we can use to further analyze the components of the program. We also took a look at the Android permission-based system in AndroidManifest.xml, how it allows access to device resources, and how and where to alter these controls. In a future article, we will cover altering the application using .smali code, repackaging .apk files, and vulnerability assessment tools.