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 *.class
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 metadataMETA-INF/*
: Other files (for example*.version
) that are used to add more detailclasses.dex
,classes[1-9].dex
: Compiled and bundled Android classes*.properties
: Used to store some configuration parameters for frameworks used by the app, and other purposesres/**
: Various static resources bundled so that they could be used at run-time by the appresources.arsc
: A file of compiled resources that are bundled together, similar toclasses.dex
but 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
The 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 appAndroidManifest.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 storedres/
: 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 heresmali/
: The disassembled Smali code for each of the APK’s classes from itsclasses.dex
unknown/
: Additional files that are not parsed byapktool
apktool.yml
The 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
The 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 app-release.apk
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, com.google.android.gms.location.sample.geofencing
.
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 MainActivity
:
<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.
Reassembling APKs
The 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
The 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 apktool
, dex2jar
is primarily focused
on working with the *.dex
files.
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 *.jar
:
d2j-dex2jar -o output.jar /mnt/app-release.apk