Introduction to Android Apps and Tools
by Coleman Kane
In the previous week’s lectures, we covered analysis of compiled Java programs, and particularly, JAR applications. Turns out that this sets up a good foundation for Android malware analysis. The APK file format, used to package android applications, is an extension to the JAR file format that we covered in the prior lectures. It includes all of the same required content from a JAR file, with additional structure that’s specific to the Android OS. In particular, it will contain files describing the local device access rights needed by the application, as well as has defined support for packaging native-architecture libraries for different platforms into a single file, among other features.
The APK file format also typically contains classes that originally began as Java code, which was
then compiled and translated into another bytecode targeting a virtual machine called the Android Run Time (ART).
This evolved from the earlier “Dalvik” bytecode & VM, which you will find is still commonly referenced in literature
and tools. The classes are often packaged into a file named
classes.dex, rather than having individual
files within archive, as this storage mechanism is designed to improve performance at the expense of static analysis.
Introducing Some Tools
Though not a comprehensive examination of all of the tools available for Android malware analysis, the below list provides a lot of unique functionality from each one of the tools that will mirror a lot of the capability you’ve had for more traditional OS environments during the course of this class.
- apktool - Tool to automate a lot of the steps when reverse-engineering and analyzing Android “APK” applications. Performs static analysis.
- dex2jar - Can deconstruct an APK’s DEX file into a JAR file that can then be analyzed with most Java analysis tools.
- Anbox - “Android in a Box” Can be used to virtualize/emulate Android hardware and various OS stacks. Has a lot of dynamic instrumentation.
- Android Studio / SDK - The official development suite for Android apps. This is a freely-available product, and proves very useful for analyzing & debugging compiled Android apps.
Generally speaking, and APK is a ZIP file based on the JAR variant, that contains the following:
META-INF/MANIFEST.MF: Same use as in the JAR format. May have additional key/value pairs for Android-specific metadata
META-INF/*: Other files (for example
*.version) that are used to add more detail
classes[1-9].dex: Compiled and bundled Android classes
*.properties: Used to store some configuration parameters for frameworks used by the app, and other purposes
res/**: Various static resources bundled so that they could be used at run-time by the app
resources.arsc: A file of compiled resources that are bundled together, similar to
classes.dexbut for non-executable objects
Note on Apple iOS Applications
Though iOS has been around for longer, and ultimately has roots in the Mac OS X operating system, Linux-based Android is the dominant platform in the mobile market. Additionally, the open-source roots of the Android OS give us a large number of tools and techniques for malware analysis on Android, that either don’t exist for iOS, or are prohibitively expensive. That said, some of the concepts are similar, and there will be some transferability of the concepts in this section to the iOS platform and the tools available there. For these reasons, we will limit discussion here to Android applications.
apktool utility gives you the ability to extract the contents of APK
archives into a (more) human-readable format than the contents are packaged with. As a lot of heavy optimization goes
into an Android app, many of the files that are traditionally plain text are compressed or otherwise packed into a
binary representation, such as
AndroidManifest.xml, the XML file describing the application, its requirements, and
its entry point. Additionally, it will disassemble the ART bytecode into a mix of Java-like code and Java-like
disassembly called Smali, as well as generate a YAML file that contains
a manifest of the discovered artifacts within the APK.
For the following examples, I’ve put together the following APK: app-release.apk
The source code for it is available here (though you don’t actually need it for this exercise): android/location-samples Geofencing on gitHub
To deconstruct the APK using
apktool, you can execute the following command:
apktool d -o app-release-apktool app-release.apk
The above command will create a new folder named
app-release-apktool and will walk through the archive extracting
data into this folder. At the top level will be the following files/folders:
apktool.yml: An extracted metadata file that describes some properties about the app
AndroidManifest.xml: This is the XML file assembled by the build system, and is used by Android OS to determine how to launch the app, set up its environment, and request permissions.
original/: This is the folder where all of the unzipped raw contents from the APK are stored
res/: These are the assets/resources packaged up for the app to use - things like icons, static HTML, and other non-executable assets used by the application are reconstructed here
smali/: The disassembled Smali code for each of the APK’s classes from its
unknown/: Additional files that are not parsed by
apktool.yml file contains a long list of YAML markup entities that describe the APK
file, according to what
apktool found. There is some particularly useful information in here:
... sdkInfo: minSdkVersion: '16' targetSdkVersion: '28' ...
The above can tell you which range of versions of the Android SDK that the app is compatible with. You can use the Wikipedia page below to match these to their corresponding Android OS versions:
From the above, we can determine that the app is compatible with Android OS version 4.1 (a.k.a. “Jelly Bean”) through 8.0 (a.k.a. “Oreo”). This will be helpful for determining what features may or may not be used by the app, as well as so that we can pick the appropriate VMs to test executing it with.
AndroidManifest.xml file is put together by the build system to help inform the Android OS how to set up the
environment for the app, what platform features it will need access to, and how to launch it. The
has the following content in its
AndroidManifest.xml (some whitespace added for readability):
<?xml version="1.0" encoding="utf-8" standalone="no"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="28" android:compileSdkVersionCodename="9" package="com.google.android.gms.location.sample.geofencing" platformBuildVersionCode="28" platformBuildVersionName="9"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-feature android:glEsVersion="0x00020000" android:required="true"/> <application android:allowBackup="true" android:appComponentFactory="androidx.core.app.CoreComponentFactory" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.Base"> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/> <activity android:label="@string/app_name" android:name="com.google.android.gms.location.sample.geofencing.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <receiver android:enabled="true" android:exported="true" android:name="com.google.android.gms.location.sample.geofencing.GeofenceBroadcastReceiver"/> <service android:exported="true" android:name="com.google.android.gms.location.sample.geofencing.GeofenceTransitionsJobIntentService" android:permission="android.permission.BIND_JOB_SERVICE"/> <uses-library android:name="org.apache.http.legacy" android:required="false"/> <activity android:exported="false" android:name="com.google.android.gms.common.api.GoogleApiActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar"/> </application> </manifest>
In the above, the following information provides insight into which version of the Android SDK was used to build & compile this APK (but not necessarily to run it):
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="28" android:compileSdkVersionCodename="9" package="com.google.android.gms.location.sample.geofencing" platformBuildVersionCode="28" platformBuildVersionName="9">
The above also gives us the package name of the application,
This can be used to find the launch application’s deconstructed files in the
smali/ folder, as it will be stored
under the folder
smali/com/google/android/gms/location/sample/geofencing/. The APK is typically bundled not only
with the application classes, but also numerous other supporting classes, often from different authors, that implement
frameworks and utility libraries that the application employs.
The following XML describes what permissions the app will be asking for permission to use:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/>
Unlike your general purpose PC, mobile platforms initially install apps with a “least privilege” access control. Apps must then ask the owner of the device to access various data stores and features within the phone, explicitly, for permission, which can be denied or permitted. This information can give insight to what data that a malicious application is programmed to steal or corrupt.
The following XML tells us that the “main” class for the application is
<activity android:label="@string/app_name" android:name="com.google.android.gms.location.sample.geofencing.MainActivity">
Many of the other fields are for more specific features, and I won’t go into them here. However, do use the following Android documentation to help understand what the presence of each means within the XML file above.
apktool utility also has the capability to reconstruct an APK from a modified application folder created from
apktool d .... There are some limitations to this, but the underlying principle is that you could make some small
modifications, and then repackage the APK.
usage: apktool b[uild] [options] <app_path> -f,--force-all Skip changes detection and build all files. -o,--output <dir> The name of apk that gets written. Default is dist/name.apk -p,--frame-path <dir> Uses framework files located in <dir>.
dex2jar utility is useful for converting between the DEX and JAR formats. The main benefit to this is so that
you may analyze and work with the Android app using tools that were designed to work on JAR files. Similar to
apktool, it has features to translate the DEX contents, as well as create them from the file types it can output.
It supports java
*.class as well as the Smali format we discussed. Unlike
dex2jar is primarily focused
on working with the
On the Kali image that was provided to you all, there are the following tools that are part of this package:
d2j-apk-sign d2j-dex2jar d2j-jar2dex d2j-smali d2j-asm-verify d2j-dex2smali d2j-jar2jasmin d2j-std-apk d2j-baksmali d2j-dex-recompute-checksum d2j-jar-access d2j-class-version-switch d2j-dex-weaver d2j-jar-weaver d2j-decrypt-string d2j_invoke d2j-jasmin2jar
You can use
d2j-dex2jar to convert the
*.dex into a
d2j-dex2jar -o output.jar /mnt/app-release.apk