Setup Android HTTPS Proxy using mitmproxy on Linux

I recently wanted to debug/reverse engineer the Web-API an Android app speaks with. I expected this to be much easier than it turned out to be in the end and had to do lots of trial and error, which is why I decided to write a little post about it.

I used Android-X86 in a QEMU VM, however other virtualization software like Virtualbox will work just as well. You need to create a virtual machine like any other and point it to the Android-X86 iso. The only important thing for this tutorial is that you choose NAT Networking.

You might be able to do this with a rooted physical phone with a little tweaking, however I haven't tried it.

Throughout this article the phone's IP will be 192.168.122.70 and the computer's 192.168.122.1. You will need to replace them with your own ones.

Installation

In the installer make sure to choose a writable /system directory when prompted and then later in android's graphical installation connect to the virtual WiFi network.

ADB Setup

Once you're in the Android interface, we will setup adb. Unlike with the usual USB method, in order to connect via adb over WiFi you will need to authorize your computer's public key by adding it to /data/misc/adb/adb_keys. I didn't setup clipboard sharing so I transfered it to the VM via netcat.

Open a terminal on the phone and run:

su
nc -lp 1337 >> /data/misc/adb/adb_keys

Then transfer the public key to the phone by running this on the computer:

cat ~/.android/adbkey.pub | nc 192.168.122.70 1337

Then start the adb server on the phone:

su
start adbd

Now you should be able to connect to the phone via adb:

adb connect 192.168.122.70

Install root certificate

Next we will install mitmproxy's root certificate onto the device. This allows mitmproxy to decrypt HTTPS traffic.

In android CA certificates are named by the subject hash followed by .0. You can get the subject hash by running

openssl x509 -in ~/.mitmproxy/mitmproxy-ca.pem -subject_hash_old -noout

For me it was c8750f0d and it will probably be the same for you.

On the computer run:

cp ~/.mitmproxy/mitmproxy-ca.pem c8750f0d.0
openssl x509 -text -in ~/.mitmproxy/mitmproxy-ca.pem -text -noout >> c8750f0d.0
adb push c8750f0d.0 /data/local/tmp

Then launch an adb shell using

adb shell

and run the following commands on the phone:

su
mv /data/local/tmp/c8750f0d.0 /system/etc/security/cacerts/
chown root:root /system/etc/security/cacerts/c8750f0d.0
chmod 644 /system/etc/security/cacerts/c8750f0d.0

Finally you will need to reboot for the newly installed certificate to take effect:

reboot

Setup mitmproxy

Now the certificate is installed, so just set the proxy in the settings and you're good to go? Right? Wrong. HTTP Proxy settings on Android are weird and don't really apply to all apps. Or any apps at all for that matter. But traffic goes through the virtual network interface of the VM on the computer anyways and we can do whatever we want there without being handicapped by android.

Make sure iptables is running and create 2 rules to redirect all HTTP and HTTPS traffic coming from the vm to mitmproxy:

sudo iptables -t nat -A PREROUTING -s 192.168.122.0/24 -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -t nat -A PREROUTING -s 192.168.122.0/24 -p tcp --dport 443 -j REDIRECT --to-port 8080

And then start mitmproxy in transparent mode:

mitmweb --mode=transparent

That's it! If you surf around in the web browser or curl websites you should see the requests pop up in mitmproxy!