This post documents how to proxy HTTP/HTTPS traffic from an emulated Android device through the Burp Suite proxy. I’ll also cover a few prerequisites, such as setting up an emulator using Android Studio as well as some basics of the Android Debug Bridge (ADB). If you’re only interested in the parts that cover Burp, feel free to skip ahead.
Setting up an emulator in Android Studio
Android Studio includes everything required for a development environment and to quickly emulate numerous devices types and API versions. You can download and install Android Studio from https://developer.android.com/studio, accepting the default installation options. Android Studio is a fully featured development environment, but I’m only going to touch on what you need to know to emulate devices so you can start testing.
After installation is complete and Android Studio starts up, select Start a new Android Studio project, accepting any defaults.
After the project loads, On the top right corner, click the AVD Manager icon (also available under the Tools menu).
The Android Virtual Device Manager window will appear. At the bottom of the window, click Create Virtual Device…
The next window allows you to select the hardware device to emulate (it is convenient to have a Play Store compatible device, but if it is a production build it may be difficult to root the device). Select your device and click Next.
Next, you need to select an image. If you have never set up an emulator before, you’ll also need to download the image, which you can do from this window. Select download next to the image of your choice (I’m using KitKat), which will then be downloaded and extracted.
Although KitKat is an older API, I’m using it mainly because I’ve noticed that this API levels has no issues with installing Burp’s SSL Certificate. After API 23, you can no longer install Burp’s certificate in the first ways I mention in this post. I’ve also noted occasional SSL issues with even on Lollipop and Marshmallow releases, but KitKat seems to work 100% of the time for me.
When the download is finished, select the image (which will no longer have the Download link next to it) and click Next. Take note of the AVD name (rename it if you want…I’m naming mine KitKat), and select Finish. You can then start the device via the AVD manager by pressing the triangle play icon, but you can also run the emulator and interact with the emulated device via commandline tools that were installed as a part of the SDK when you installed Android Studio.
The SDK was installed for me at
C:\Users\Jake\AppData\Local\Android\Sdk, but they were not added to my path. Some of the tools look for the Environment variable
ANDROID_SDK_ROOT, so I created and set that to
C:\Users\Jake\AppData\Local\Android\Sdk. The Sdk folder has multiple subfolders containing the various tools, so to interact with these via the command line, I added the following to my path:
C:\Users\Jake\AppData\Local\Android\Sdk\emulator C:\Users\Jake\AppData\Local\Android\Sdk\tools\bin C:\Users\Jake\AppData\Local\Android\Sdk\platform-tools
After adding these to your path, you should be able to open a new command prompt/terminal and type the command
emulator -list-avds. This should present you a list of your devices, including the one you downloaded and created via the AVD manager GUI (this will be your only AVD if you’ve never done this before). To start the device, type the command
emulator -avd <avd_name>, and your emulated device should show up (it might take a few minutes to boot).
When you start a device, the ADB (Android Debug Bridge) server is started on your local machine, port 5037, which will then listen for commands from ADB client processes on any devices, as well as set up connects to the devices. You can learn more about ADB here, but for the purpose of this post, the important thing to know is that we will be using the adb commandline tool that came with the SDK to interact with the emulated device(s).
You can do a lot of things with ADB. Here are a few:
List the number of devices connected to the ADB server:
C:\Users\Jake>adb devices List of devices attached emulator-5554 device
Drop into a shell on a device:
C:\Users\Jake>adb shell generic_x86_64:/ $ id uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:shell:s0 generic_x86_64:/ $ exit
If there are multiple devices listed, specify the device using
-s <device name>, so to drop into a shell when multiple devices are listed, you can do
adb -s emulator-5554 shell, where my device name was emulator-5554 .
If the device is a non-production build, then you can get root access on a device incredibly easily:
You are now root.
If you want to run a command, but not drop into an interactive shell, you can specify
adb shell <command>:
C:\Users\Jake>adb shell id uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:su:s0
Next, I’ll use ADB to install an Android app that I want to take a look at. You can get the apps from multiple places, most notably being the Google Play store, but I chose to quickly grab an app from one of the many third party sites that host APK files. It’s not guaranteed to be the latest and greatest (or safest) apps, but APKmonk has a decent reputation. I downloaded ‘Libby, the library app’ from https://www.apkmonk.com/app/com.overdrive.mobile.android.libby/, and then used ADB to install the APK on to the emulated device. An APK file is a package file format used by Android, and contains all of a program’s code (such as .dex files), resources, assets, certificates, and manifest file.
To install the app with ADB:
adb install <path\to\file.apk>
When the command completes, you should be able to go to the apps section on the emulator and see the app on the device.
In this case, the APK was available to us via APKMonk, but if you want to pull an APK file from a device, the process is a bit different.
Use ADB to list the installed packages, piping the output to findstr (or grep) to quickly filter. This will return the package name:
adb shell pm list packages | findstr -i "libby" package:com.overdrive.mobile.android.libby
Next, find the path of the package:
adb shell pm path package:com.overdrive.mobile.android.libby WARNING: linker: libdvm.so has text relocations. This is wasting memory and is a security risk. Please fix.
This shows me nothing except an error, however this works for most apps, and you can finish pulling the APK using adb pull and supplying the path:
adb pull </path/to/apk/on/device.apk> <local\destination\path>
Another way for me to get the path for Libby is to get all the third party packages. I can use the following command to accomplish this:
adb shell pm list packages -f -3 WARNING: linker: libdvm.so has text relocations. This is wasting memory and is a security risk. Please fix. package:/data/app/SmokeTestApp.apk=com.android.smoketest package:/data/app/com.overdrive.mobile.android.libby-1.apk=com.overdrive.mobile.android.libby package:/data/app/WidgetPreview.apk=com.android.widgetpreview package:/data/app/CubeLiveWallpapers.apk=com.example.android.livecubes package:/data/app/ApiDemos.apk=com.example.android.apis package:/data/app/GestureBuilder.apk=com.android.gesture.builder package:/data/app/SoftKeyboard.apk=com.example.android.softkeyboard package:/data/app/SmokeTest.apk=com.android.smoketest.tests
So this command gives me the error, but also gives me the path to Libby.
The adb pull command will not uninstall the package from the device, however. To uninstall, do
adb uninstall <package_name>
Setting up Burp Suite (Prior to Android Nougat)
To monitor the network traffic coming from the emulated device, you can capture traffic only from the device, as well as set up Burp Suite to be able to proxy and view and modify the HTTPS traffic.
I have Burp Suite configured on my host machine at 127.0.0.1:8080, but prior to configuring the emulator to send the traffic through Burp, I want to install the Burp Suite CA certificate on the emulated device so I can inspect the HTTPS traffic without errors. First, I will walk through this manually, installing the Burp CA cert as a user cert.
Install as a User trusted certificate
On your host machine navigate to the Burp Web UI (mine is at http://127.0.0.1:8080) and click the CA Certificate link in the top, right-hand corner of the screen (http://127.0.0.1:8080/cert), which will download the certificate link. To get this to my emulated device, I start an HTTP server in the same directory to host the file, which I can then browse to and download the certificate file from my emulated device:
The Burp documentation recommends renaming the cacert.der to cacert.cer, but it hasn’t mattered for me. I used Python’s built-in HTTP server to host the file on my 127.0.0.1:8000. On my emulator, browsing to 127.0.0.1:8000 will not work (since that is the loopback on the emulator), but there is an alias to the host’s loopback at 10.0.2.2, so to browse to my Python webserver I navigated to http://10.0.2.2:8000, which presented me a directory listing for location that I started my server. I clicked on the cacert.der link, and the emulator prompts me to name the certificate. I named mine cacert and clicked OK. The emulator will then require you to set a lockscreen password if none exists, and after that the Burp Suite certificate will be installed.
To configure a proxy on the emulator you can select the ellipsis at the bottom of the emulator control panel, which will bring up the extended controls window. At the bottom, select the Settings tab, click the Proxy tab, and then set the proxy configuration to your proxy host and port:
Now any app that uses HTTP/HTTPS will be proxied through Burp.
You can actually specify an output pcap file as well as an HTTP(S) proxy at start up using the emulator command line tool:
emulator -avd KitKat -tcpdump kitkat_traffic.pcap -http-proxy 127.0.0.1:8080
Install as a system trusted certificate
This method works on rooted devices by installing the Burp Suite certificate as a trusted CA, and is almost entirely based on this blogpost. I used Python3 to automate all of this, as well as check the environment to make sure everything is present (ADB, Burp, an emulated device, etc.). The script is located on my GitHub, and requires the pyOpenSSL module. If you’d like to use the script, close your running emulator and restart it, adding the “-writable-system” argument to the emulator command:
emulator -avd KitKat -writable-system
Then run the script. If you have adb in your path, a connected device, root access, burp running, and writable access to /system, then the script will download your Burp cert and convert it to what Android wants, root your device, transfer the cert to the device, and then reboot the emulator:
Setting up Burp Suite (Android Nougat and beyond)
With the release of Nougat, User certificates were no longer trusted and therefore could not be simply installed via the methods already discussed. While installing the certificate as a system trusted certificate should work, I must admit that it hasn’t worked for me. So, I’ve resorted to unpacking the APK, adding/editing the network-security-config to allow the Burp certificate, decoding/editing the AndroidManifest to reference the config, and then repackaging the APK. This technique is discussed in the aforementioned blog post, and the network-security-config specifics are covered in-depth here.
I’ve also automated all of the above using Python3. It requires that you have a few tools in your path and have Burp running, but it should check for everything and tell you if you’re missing anything. The script is available here, so feel free to use it, as well as examine the code to see how I’ve implemented all of the steps. Running the script gives you the following output:
Hopefully this post has been helpful to you.