Estimated difficulty: 💜💜💜🤍🤍
This week I wanted to write the first post of a mini mobile application reverse engineering series! There has been a lot of attention in the news about apps such as TikTok and the COVID-19 NHS track and trace app, where they have been shown to have certain security flaws. By writing this series, my aim is that we can learn together, to understand some of the main practices of reverse engineering Android application packages – Otherwise known as apk files.
When it comes to reverse engineering an apk file, it is important that you don’t just start reverse engineering applications (apk files) willy-nilly. Before we even start getting into the nitty-gritty of this blog post, it is important to read the end-user license agreement, acceptable use policy or anything else similar to this when choosing an apk to decompile! Certain apks or part of the code within the apk can be proprietary and if this is the case the owner may not allow the end-user to reverse engineer their application.
APK Internals
So let’s get into it! First off, what is an apk file? If you have an Android device you might have heard this term being thrown about. This stands for Android Package and they are the applications you install on your phone! You might have a Twitter apk file, Facebook apk file and even a G-Mail apk file. All in all, there are many of them floating about and for the most part, and anyone can make one (this can be a bad and a good thing…)! I haven’t yet picked an app to reverse engineer, as there are just so many to choose from, but this post will look at what an apk is and the tools that you can use to analyse the apk!
An apk is an archive file. Who would have thought it? It wasn’t obvious to me at first and like any good newbie I found this out through a quick Google search. To further look into the files all you need to do is unzip that file. You can do this on any OS pretty easily and you then have access to a bucket-load more files that make up the APK.
Below I have specified the main components of an application (apk).
Activity
Many activities make up an Android application. The activities are mainly used to allow the user to interact with the application. There will be a main class of activities and then many sub-classes of activities. An example of these can be where you go want to go to buy a pair of shoes. You might need to register or login to the app to purchase the shoes and therefore, you might need one activity to login and another to register. Activities need to be specified in the AndroidManifest file and from there you can add things such as permissions, intent filters and anything else that these activities might need to have to successfully run. In this example, the activity shown is a ShareActivity.
A typical lifecycle for an activity is as follows: create, start, restart, resume, pause, stop and destroy.
Service
A service is intended to run in the background, unlike the activities which represent the screens of the app. For example if an activity starts a service, then that service should then continue to run. Within the Telegram application they have a service defined in the AndroidManifest services such as a LocationSharingService as well as a VideoEncodingService, shown in the screenshot below.
There are more to some services than just specifying their name or determining if the service can be initialized or not. There is a better description of all the tags that a service might have on the Android developers website. However below is a list of the tags you might come across:
- android:enabled – true/false – service can be initiated or not
- android:exported – true/false – whether or not components of other services can invoke the service
- android:icon – drawable resource – if there is an icon representing the service
- android:isolated process – true/false – will run as a process isolated from the rest of the system
- android:label – string resource – name for the service displayed to users
- android:name – string – the name of the service
- android:permission – string – the name of the permission
- android:process – string – the name of the process where the service is to run
Content Provider
Content providers are also declared in the AndroidManifest file. The provider is responsible for providing the data that may be otherwise stored locally or remotely and give it to the component requesting the data, provided the component has the permissions to access the data. An example of the entry within the AndroidManifest file is shown below:
<provider android:name="org.telegram.messenger.NotificationImageProvider" android:exported="false" android:authorities="org.telegram.messenger.notification_image_provider" android:grantUriPermissions="true"/>
The tags listed in the example such as grantUriPermissions allows the provider to access the data once, that may otherwise be restricted by other tags such as the read and write permission tags. Similar to how there are multiple tags for the services the same is true for the content provider. Please see a brief list of the tags below that can restrict components interaction with the provider within and outside the application.
- android:authoities – lists providers exposed by application
- android:enabled – tags the system that can initiate the provider
- android:exported – if true then other applications can access the provider
- android:grantUriPermissions – allows the provider to access the data once when otherwise limited with other permissions. If false then access is limited to the databases listed under this tag.
- android:icon – if there is an icon representing the service
- android:initOrder – the order in which the provider is initialised
- android:label – the name visible to the user
- android:multiProcess – lets the application create an instance of the provider in each application process interacting with it.
- android:name – the name of the provider
- android:permissions – permissions set for the client to interact
- android:process – defines the process the provider should run
- android:readPermissions – permissions set for the client to interact to read from the provider
- android:writePermissions – permissions set for the client to interact to write to the provider
- android:syncable – allows data to sync to the provider
Security concerns can arise if access to the content provider is not properly secured. Any data being sent to the provider should checked or alternatively access should be restricted to the activities rather than the users directly. It is also important to make sure that only the necessary permissions are granted to the content provider helping to reduce the risk of SQL Injections or the modification of the data.
Broadcast Receiver
Like the activities, content provider and services, the receiver can also be defined in the AndroidManifest file. I won’t bore you with listing all the tags as there isn’t too much of a change to the ones listed for the content provider, as it also includes basic tags like permissions and process’.
The Broadcast Receiver allows the application to receive and broadcast incoming or outgoing intents (more on that later!). The first receiver tag defined in the screenshot means the public receiver “org.telegram.messenger.AppStartReceiver” will listen to events from “org.telegram.start” and “android.inent.action.BOOT_COMPLETED“, before (from what I understand) the application knows it can start.
Broadcasts sent from an application can be sent to all the receivers listening and it will receive it or ordered broadcasts can be sent to one receiver at a time, where the first receiver adds its result and sends it to the next receiver. It is important that sensitive information is not sent over these broadcasts if any receiver can receive it, as that may result in the leakage of sensitive data. You can set permissions to protect against this.
Intents
Intents are used for the different components of an Android device to communicate with each other. They are used to: start an activity, start a service, communicate with a service, broadcast an event, broadcast a change and the list goes on! There are different types of intents. You can have implicit, explicit and pending intents, as well as intent filters. Like how most of this post seems to go, I have a future more in depth post drafted on intents. However, I have briefly described each of these different intents.
Implicit Intents | If the name of the component is unknown then the action a receiving component needs to do is specified rather than the name. Criteria is specified within the intent object that must be met. |
Explicit Intents | An intent is sent to one known component. For example an activity from one application sends an explicit intent to another application. |
Pending Intents | A pending intent can be described as a job waiting to happen. This intent is waiting to kick start something, be it an activity or service once it has been received by the device. The intent will start once the event it is waiting for has happened. |
Intent Filters | Intent filters are defined for activities, services or receiver jobs within an application. Additional criteria are specified and must be met before the action service or receiver can begin. Some of these filters may include the category of the intent and the type of data to be requested. |
Installing the APK
It is not recommended to install 3rd party apk files. This means you shouldn’t install or download applications from untrusted sources. There are native app stores on your phone. If you are using an Android you will most likely have Google Play Store or an Apple IOS device should have the App Store. I will provide a more technical and practical post on how to install the apk later on in the series. Please see the infographic below for a basic overview of how we might start testing the application.
Tooling
Consider this like an index for all the tools you can use to reverse engineer and analyse apks. I haven’t used all of them yet, but have decided this series will be a learn as I go experience, so will include the ones I will try in this list and add to it as we go along. There are probably plenty that I have missed off, and if so please don’t hesitate to comment or let me know and I can amend this list!
Tool | Description |
unzip | Decompression tool (tool to unzip) |
dex2jar | This tool converts .dex files back to java files so you are able to view the code of that particular file. |
jadx | Decomplies an apk and the dex file to convert all dex files to java. This tool is slightly more automated than dex2jar. |
Android Studio and emulator | You can emulate an Android device and understand how the app you are analysing is working. |
Genymotion | Another Android emulator, which is used in conjunction with Virtual Box. |
MobSF | The Mobile Application Security Framework is used to assess the security of an application. |
adb | Android debugger, it can be used to interact with the phone and look at the files. Push and Pull allows you to push an app to the device and pull it to install or download these applications. |
Zed Attack Proxy (ZAP) | Created by OWASP, this is a web application security testing framework, but can be used to test if an application is vulnerable to sending malicious messages. |
Environment
When it comes to reverse engineering and analysing apk files, I am most comfortable with using Linux. For reasons unbeknown to me, I decided to install Kali Linux on my Pi 4, so ended up using that as my environment, see my previous post on how to do this. Personally, I prefer Linux based systems to Windows when doing any kind of project as I find the command line easier to use. However, if you are more comfortable Windows fan then this is definitely doable on that OS as well. If you would like a Windows tutorial please comment below!
Security
There are many aspects to application security. I have listed some of the risks with these applications to better understand why we might want to start picking apart these apk files!
- Applications may be intentionally malicious/ contain malware
- The storage and transmission of data could be insecure
- Functions used within the applications code are not secure or become vulnerable
- Authentication to sensitive data is not provided
Sources
Here I have listed some sources I have found useful along my journey and in the creating of this post.
- Android Application Security Essentials: by Pragati Ogal Rai. This is a printed book (that I need to send back to my university… Thank you university…).
- Wild Wild West Hackin’ Fest App Testing Talk. Video released here.
I hope you have enjoyed this post and if you have any questions please feel free to comment or message me!
Sarah <3