Step 1: Install the Android SDK
The first thing you need to do is make sure you have the Android SDK installed and up-to-date. The simplest option here is to install Android Studio, though you can install the SDK directly or through other tools (VS Code, for example). This post assumes you are using Android Studio, which is available for download from the top menu at https://developer.android.com.
If this is your first time setting up the Android SDK, then for convenience you will want to make sure the tools are available in your path. To do this: Add $ANDROID_SDK/platform-tools
to your path, where $ANDROID_SDK is in:~/Library/Android/sdk
on Macc:\Users\username\AppData\Local\Android\Sdk
on Windows
You can test that you have done this correctly by opening a terminal window and simply typing the command adb
to see the help for the Android Debug Bridge.
Step 2: Create an Android Virtual Device
Next, you will want to create an Android Virtual Device, or AVD. You can find the AVD Manager inside the tools menu of Android Studio. Once you open up the AVD Manager you will be presented with a list of existing virtual devices and the option to create a new one. Creating a new one will pop up a screen like so:
Make sure you pick a virtual hardware version that does not include the Play Store. This is important because we need to be able to put the device in developer mode, and the non-Play-Store images are already in this mode by default, and are trivial to root.
The next screen will prompt you for a System Image, and should look something like the following screenshot:
You can choose almost any Google APIs image; however, note that the next couple of steps don’t seem to work for API release 30 (codename R). I will post an update once I figure out what is different about that one. For this exercise, I chose Oreo (API 27) because it is still widely supported but not bleeding edge technology.
Finally, start the Android Virtual Device. You can test that your image is rootable by running the command adb root
from a terminal on your host.
Step 3: Setting up the Proxy
Set up your interception proxy (e.g. Burp or ZAP) to run as you normally would to test a web application. Usually this means your proxy is listening on port 8080 and bound to 127.0.0.1. You will also want to export your proxy’s CA certificate in DER format, and give it the file extension .crt. Although other file extensions may work on some platforms, .crt is the only extension that seems to be universally accepted across all versions of Android. Put your certificate file somewhere you can easily access it.
Next, navigate to the Proxy settings for the AVD. Use the following screenshot as a reference. From the three dots at the bottom of the side menu, open the extended controls, choose the Settings menu, then choose the Proxy sub-menu.
Once you are in the Proxy menu, choose Manual proxy configuration and set up the host name and port number to match those of your proxy (e.g. 127.0.0.1 and 8080).
You can now test that the proxy is working by opening up a web browser inside the AVD and then looking in your interception proxy to verify that you are seeing web traffic from the device. At this stage, only unencrypted (HTTP) traffic should work because our AVD does not yet trust our proxy’s certificate.
Step 4: Installing the Certificate
The next step is to install the certificate that you exported from your interception proxy in the previous step. To install the certificate, start by dragging it onto your AVD. This will drop the certificate into the user’s Downloads folder.
Now that the certificate is on the device, you need to install it from the Settings. The specific settings page for doing this varies depending on the version of Android, so the easiest way to figure this part out is to open up Settings and search for “certificate”. It is important to note that there may be multiple options for installing certificates. For example, we do not want to install a client certificate for a wifi connection. What we are looking for is the specific screen for installing a CA certificate. On Android Oreo, this option is called: Install from SD card
. Also, depending on the version of Android you may be prompted to set up a device PIN before you can install a CA certificate. Follow the on-screen prompts if necessary.
Once the certificate is installed, you can visit an HTTPS website in Chrome and then verify that you are not getting a certificate warning, and that the HTTPS request and response traffic are showing up in your proxy history.
Step 5: Copy the Certificate to System
Unfortunately for those of us performing penetration testing, more recent versions of Android limit access to user-installed CA certificates. What this means is that although the certificate installed in the previous step worked fine for browsing websites in Chrome, it won’t work for another installed applications. To get other applications to work, you will need to copy the certificate from the user’s certificate space to the system space. To accomplish this, you will need to restart the AVD with a special flag. Follow these steps:
- Shut down your AVD if it is running
- From the command line, run
emulator -list-avds
, and note the name of your virtual device (replacing [IMAGE] in the next command with the name of your image). - From the command line, start up your AVD with a writeable filesystem with the following command:
emulator -avd [IMAGE] -writable-system
At this stage you will need a second terminal to get into the AVD and move the certificate. This is done with the following set of commands:
adb root
adb remount
adb shell
cp /data/misc/user/0/cacerts-added/9a5ba575.0 /system/etc/security/cacerts/
exit
Finally, restart your AVD one more time and test out the configuration by opening up a mobile application and checking your interception proxy history for HTTPS traffic.
Done!
And that’s all there is to it! There are, of course, exceptions such as applications that make use of unusual features or that include natively compiled code. However, most of the time this approach should work fine for analyzing request / response traffic from an Android application.