In this introduction series to Android application reverse engineering, after having talked about the APK format, aapt and dex2jar, the next thing we’re going to turn our attention to is Apktool.
As we have seen, resources in an APK are compressed and stored in binary format and neither aapt nor dex2jar can help us to view and edit them: the former is essentially a read-only tool, useful to extract information, while with the latter we can work with the executable code of the APK but not the resources.
According to the official website, Apktool is:
A tool for reverse engineering 3rd party, closed, binary Android apps. It can decode resources to nearly original form and rebuild them after making some modifications; it makes possible to debug smali code step by step. Also it makes working with an app easier because of project-like file structure and automation of some repetitive tasks like building apk, etc.
So it seems a good candidate, because it’s able to decode resources.
As it’s underlined, it’s important to remember that this tool is not intended for piracy and other non-legal uses.
The installation procedure is described here in great details: just check to have the proper Java version installed and then jump to the instructions related to any of the supported environments: Windows, Linux and Mac OS X.
All the examples of the article will be run using this Apktool version:
If everything is correctly installed and set up, we should get this output simply typing
apktool in a terminal window.
Before starting to issue the very first command, we still need to take care of one aspect: choose an application. As I did for the dex2jar article, I picked RGB Tool because it’s an open source application and I’m part of the project, so there will be no issue in reverse engineering it: we can get the APK here.
For all the examples, I have used RGB Tool v1.4.3 and a Nexus 6 running Android 6.0.
Frameworks are important when we decompile framework dependent APKs or system applications. In fact, on any device or emulator, as part of the system image, there is always an APK file containing all the resources of the ROM: images, animations, sounds, splash screens, …
The actual file is usually:
Simply put, this file contains essential resources for the general look and feel of our device, which are used by system or other applications, so any manufacturer, such as Samsung, HTC, Motorola, LG, … provides its own framework APK file.
Apktool, by default, uses the framework from the AOSP and place a copy of this file at this location (on a Mac OS X):
If we need to decompile system applications which are based on a different framework, we have the possibility to install it, otherwise we could get the following error:
The first thing to do is to retrieve the framework APK file from a device with the
adb pull command: usually we can find it in
/system/framework, but we can double check here to have the complete list of all the possible locations in case is not there.
Then we can install it:
apktool if FRAMEWORK.apk
After this operation, we will be able to decompile a system application.
Note: next sections of the article use the default AOSP framework, so it’s not required to install a custom one.
The decode operation of an APK can be easily run with the following command:
apktool d FILENAME.apk
The tool creates a folder named after the APK file just decoded.
Please notice the content of the output folder depends on the specific APK and the files packaged in it.
The first thing to note is the
apktool.yml file: it contains important information like application version name and code, min and target SDK version, … This file is essential when we build back the APK file, specially if we want to change any of those values.
Then we have the
AndroidManifest.xml file in XML format, not binary, so we can view and modify it.
original folder usually contains the
AndroidManifest.xml file in binary format and the
META-INF folder with the JAR manifest and the signature of the APK. Basically these two items are copied directly from the APK without any modification.
smali folder contains the application source code in smali format: I’ve already talked about it in my previous article, so I just mention a couple of things. First, the code is organized in folders by package name and what we get is the full executable code: this means code from dependencies is also present in the folder. Then, having the option to rebuild the APK as we’ll see later, we can modify these files and it will be reflected in the newly produced APK.
The last folder is
res, and as we can guess this is the resources folder: Apktool is able to decode resource files (remember inside the APK they are stored in a binary file called
resources.arsc), so we can view and of course also modify them. Here there’s one important thing to highlight: since what we decode is the APK, so an application that can be run on any device, resources from the dependencies of the application are also present in this folder. So don’t be surprised if we see more resources than the one we have in our Android Studio projects. To make it clear, if we declare the AppCompat v7 as a dependency in our project, here we will also get its resources (the ones starting with
Last thing to note, the names of the subfolders of
res could not exactly match the ones in our project or the original application: Apktool creates them in order to be able to build back a working APK, so it needs to name them taking that into account.
The build process can be started issuing the following command:
apktool b APKTOOL_DECODE_OUTPUT_DIR
This builds the output folder resulted from a decode operation and places the resulting APK in
Otherwise we can also specify the destination APK:
Please notice that the APK built with Apktool is not signed, so it cannot be installed on a device.
In fact, if we try to install the APK in the
dist folder, we get the following error:
So, before installing the APK on our device, we must sign it with the following command (it prompts us for passwords for the keystore and key):
If it’s not a release build, we can always rely on the debug keystore, the same used by Android Studio to sign debug builds. The actual file is usually stored in an hidden folder (home folder depends on the specific environment):
Keystore password is
android, key alias is
androiddebugkey and key password again
Instead, if we need to create the keystore, we can refer to the official documentation (it also suggest us to zipalign the APK after the signature process).
Let’s have a bit of fun!
Now that we know how to decompile and re-build an application, let’s try to do some small changes, just to test Apktool features.
First of all, let’s have a look at the original application main view, just to be able to compare it later after our modifications.
Application name and main theme
As a first thing, let’s change the application name and the main theme colors.
If we look at the manifest file, we can see the application name is stored in a string resource called
app_name. So let’s open
values/string.xml file and change the value from RGB Tool to MyRGB Tool.
About the theme colors, let’s again have a look at the manifest file to check if a theme is set at application level: it is and it’s called
Theme.Rgbtool. We can find its declaration in
values/styles.xml, and what interests us is this part:
So, let’s move to
values/colors.xml and change these colors. Regarding this point and more in general main theme colors, I suggest you to bookmark Material Palette.
I have defined the new colors as it follows:
Let’s build the application, sign the APK and have a look at our changes. Please remember we always have to resign the APK every time is built and it has to overwrite the existing application on the device too.
In the same way, we can update the icon of the application because as we know it’s just a drawable PNG file and its name is set in the manifest file again, as for the previous attributes. So, the change is very trivial, in fact it’s just necessary to update few PNG files (there could be a PNG for different screen densities) with new resources and build again the APK.
For this specific examples, the icon is set as
To help us create a simple set of valid launcher icons, we could take advantage of the Android Asset Studio, choosing Launcher icons option.
After having updated the PNG files, built and signed the APK, this is the new application icon displayed on the launcher:
So far, we have just replaced existing resources, using the same file name, but what if we would introduce a completely new resource in the application? Let’s try to do that.
If we open the application and we decrease the value of the opacity (O), we can see an Android robot appearing in the background:
The resource is called
@drawable/robot and it’s used in a bunch of layouts: let’s take it, duplicate, change its color and call it
robot_apktool. Then, we have to replace in all the XML layouts the reference
robot_apktool. Done that, we can rebuild the APK, sign and install it on our device.
Our new robot is there! That was easy honestly, because that resource is only referenced by XML files but never in any Java class. That’s a crucial difference when we have to add new resources: we’ll see why in a moment.
Can we change the source code?
Yes, as said before in the article, Apktool decompiles the executable code of the application and produces
.smali files, so we can directly change them and rebuild the APK. Of course, working with smali it’s not like working with Java classes, the syntax is quite verbose and not so easy to understand at the beginning. We can open these files with any text editor, even if we would miss important features like syntax highlighting and autocompletion. On the positive side, we can easily search strings with
grep for example.
There are also a couple of tools to mention: one is an open source syntax highlighter, while the other one is fully featured solution which actually does more than smali editing.
Let’s try a very simple change just to have to deal with smali: if we click on the Print color option (it could be necessary first to click on the overflow menu icon), the following dialog appears on the screen.
What we’re going to do is change Skip button text to Apktool: this example is significant because the string resource is used in a Java class and not in an XML resource file.
The resource name is
action_common_skip: so let’s create a new string item in
res/values/strings.xml, calling it
action_common_skip_apktool. There are also Italian and French resources, but for this example it’s enough the default value.
Now, if we search for
action_common_skip, we see that it’s present in the 3 string resource files (default, Italian and French) and in file called
public.xml. That’s interesting, no smali files appears in the search results even though, looking at the original Java class, we know that this string resource is actually used in the source code. So, let’s open this XML file and also the smali file of the dialog,
public.xml is the list of all the resources of the application, such as strings, layouts, drawables, colors, … and for each resource an hexadecimal id is set. These ids are actually the values present in the
R.java file create by the Android Build System when we build a project: that’s it, Apktool creates this XML file while it extracts the resources of an APK and it decompiles the code. As already pointed out in the previous article of this series, if we reference a resource in our Java class, such as an Activity, what it’s actually used is an id, an integer, which is stored in the generated class
So, let’s try to search the id of our resource in the smali file:
Interesting again! It’s actually used (please notice that using another application or building RGB Tool cloning the repository, could result in having a different id value from the one this example):
So, the id value is stored in a const called v2, then it’s used as a parameter for a virtual method invocation (which would be
setTitle). A good summary list of opcodes can be found here.
Now we have all the elements: we know we must update the
public.xml file, adding our newly defined string, and also the id value in the smali file.
For the first change we need to be careful: as we can notice, the resources are ordered by type and the ids are sequential, so we cannot set any value we want. We need to search for the last string resource and then add the new one, adding 1 for the id (remember those are hexacedimal values). In the example, last string id is
0x7f070051, so that’s what is required to be added:
The second update is instead very simple, just replace the old id value with the new one in
Now, let’s rebuild, sign and install the new APK on the device: as we can see our new string is displayed.
That’s all for this update and the main features of Apktool: I encourage you to test it using an APK for which you have the original source code. It’s really much easier to understand how resources decoding works and to read smali code. Modifying and rebuilding an APK really depends on the changes you perform and on the original version of the application.
In the next update I will focus on Androguard.