In the article Sniffing https traffic on Android 11 I described how you can intercept https traffic on Android. This is often very convenient, but sometimes you need to go deeper and look at the raw network packets. If TLS is used things get complicated, so in this article I’m going to explain how to intercept generic TLS traffic that goes to and from an Android device.

To do this you will need a rooted Android device (or emulator) that’s connected to a computer using adb.

Wireshark

Wireshark is a great tool for capturing raw network packets, but if the traffic is encrypted with TLS it makes things complicated.

The traffic is all encrypted, you can't really see much more than the domain
The traffic is all encrypted, you can't really see much more than the domain

There are two ways that Wireshark can decrypt TLS traffic. The first is using the private key the server is using to encrypt the traffic, but this is something you generally don’t have access to when analyzing Android applications.

The other way is to provide Wireshark with the pre-master secret. This is generated by the client when setting up a secure connection with the server. If Wireshark has the pre-master secret it will be able to decrypt the traffic.

Curl and browsers such as Chrome and Firefox for computers can generate these secrets when the connection is set up. But if you want to intercept traffic from other programs or from Android you will generally be out of luck.

Since we’re interested in intercepting TLS traffic on Android this means we can’t use Wireshark to decrypt the traffic. What we need is a TLS proxy that is capable of decrypting TLS encrypted traffic.

PolarProxy

PolarProxy is a neat tool that can help us. It is a transparent TLS proxy that decrypts TLS traffic and can save the decrypted traffic as pcap files. These can later be analyzed using Wireshark. PolarProxy is free to use and available for both Linux and Windows so it should be available to most people.

Since version 0.9 PolarProxy can be run as a transparent proxy, a SOCKS proxy or a HTTP CONNECT proxy. I haven’t been able to get the SOCKS proxy or HTTP CONNECT proxy approach to work for my use cases so I’m going with the transparent proxy approach. Feel free to leave a comment if you can get the SOCKS or HTTP CONNECT proxy working together with Android.

The PolarProxy certificate

Since PolarProxy intercepts and decrypts all TLS traffic going through it, it encrypts the traffic with its own certificate. To make sure that the Android device doesn’t reject the traffic we need to install PolarProxy’s certificate as a trusted certificate.

The first step is to get the actual certificate. To do this you need to start PolarProxy with the --certhttp argument. In the documentation on their web page they are using port 10080 for this, but you should avoid it. Many modern browsers are blocking port 10080, so use something else, like for example 10011.

Start PolarProxy with PolarProxy -p 443,80 --certhttp 10011 and load localhost:10011 in a browser to download PolarProxy’s certificate.

After you’ve downloaded the certificate you can shut down PolarProxy again and install the certificate on your Android device in the same way as described in Sniffing https traffic on Android 11.

Running PolarProxy

Decide which ports you want PolarProxy to listen to and use the -p argument to specify this. If you want PolarProxy to listen to several ports you can use several -p arguments. This argument takes a comma separated list of numbers. The first specifies which port to listen to, the second which port to use in the decrypted pcap file. The third is optional and specifies the outgoing port, if not specified the listening port is used.

You also want to use the -w argument and provide a filename to specify where the decrypted traffic should be saved.

As an example PolarProxy -p 3883,3883 -p 443,80 -w polarproxy.pcap would start PolarProxy and listen to port 3883 and 443 and save the decrypted traffic in the file polarproxy.pcap.

Running PolarProxy and listening on two ports
Running PolarProxy and listening on two ports

Android setup

Since PolarProxy is run as a transparent proxy we can’t use the normal proxy settings and set up PolarProxy as a proxy. Instead we need to route the device’s traffic on the desired ports through PolarProxy. This can be done by using adb reverse and modifying the iptables on the device.

adb reverse

adb reverse is used to set up a reverse socket connection from the Android device to the computer that the device is connected to. Since PolarProxy is listening to port 443 and 3883 we want to set up two reverse connections:

adb reverse tcp:443 tcp:443
adb reverse tcp:3883 tcp:3883

The first argument specifies the port on the Android device while the second specifies the port on the computer the device is connected to. After running this any connection made to port 443 or 3883 on the Android device will be forwarded to the matching port on the computer.

Please keep in mind that this forwarding is only active as long as the adb server is running. If it’s restarted you’ll have to set up the connection again.

A reverse connection set up between Android and the computer
A reverse connection set up between Android and the computer

iptables

With the port forwarding in place we now need to make sure that all outgoing traffic on port 443 and 3883 on the Android device gets routed to port 443 and 3883 on the device. We’ll do this by modifying iptables, which requires root access.

adb root
adb shell
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 127.0.0.1:443
iptables -t nat -A OUTPUT -p tcp --dport 3883 -j DNAT --to-destination 127.0.0.1:3883

If you’re not familiar with iptables the man pages is a good source of information regarding what the options does. In this case the options we use are:

  • -t nat to specify that we want to work with the nat table.
  • -A OUTPUT, which means that we are going to append a rule to the OUTPUT chain which is used to alter locally generated packets before routing.
  • -p tcp to specify the protocol
  • --dport to specify the port
  • -j DNAT --to-destination 127.0.0.1:443 to define the new target for the packets being routed.

Basically we’re adding two rules that say that any outgoing packets on port 443 and 3883 should be routed to 127.0.0.1 using the same port.

If you want to experiment more with iptables two useful commands are iptables -t nat -L to list all rules on the nat table and iptables -t nat -D OUTPUT 1 to delete the first rule in the OUTPUT chain of the nat table. You don’t have to be afraid of breaking things. If you reboot your device the iptables will be reset to the original state.

iptables has been configured to redirect outgoing traffic to localhost
iptables has been configured to redirect outgoing traffic to localhost

Putting it all together

With this setup, any outgoing request on port 443 and 3883 on the Android device will be redirected to localhost, or 127.0.0.1, on the Android device thanks to the iptables configuration. The adb reverse connection forwards these ports to the same ports on the connected computer on which PolarProxy is listening.

Request flow when making a request on the Android device
Request flow when making a request on the Android device

Making sure it works

Now it’s time to test that it works. Open up a browser on your phone and load https://example.com/. As the page is loaded and requests are made you should see that PolarProxy is decoding the traffic.

PolarProxy is now intercepting traffic on port 443 and 3883
PolarProxy is now intercepting traffic on port 443 and 3883

Close down PolarProxy to get the file with the decrypted traffic flushed to disk and open it up in Wireshark to analyze the traffic.

The decrypted network traffic can now be viewed in Wireshark
The decrypted network traffic can now be viewed in Wireshark

Summary

If you know what you’re doing it’s actually not that hard to intercept generic TLS traffic from a rooted Android device and this article has hopefully provided you with that knowledge. As a quick reference, here are the commands needed to intercept traffic on port 443 once you’ve done the initial setup and installed the PolarProxy certificate on your device.

# Start PolarProxy
PolarProxy -p 443,80 -w polarproxy.pcap

# Setup adb reverse connection
adb reverse tcp:443 tcp:443

# iptables setup 
adb root
adb shell
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 127.0.0.1:443