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 is a great tool for capturing raw network packets, but if the traffic is encrypted with TLS it makes things complicated.
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 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.
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
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 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.
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 natto specify that we want to work with the nat table.
-A OUTPUT, which means that we are going to append a rule to the
OUTPUTchain which is used to alter locally generated packets before routing.
-p tcpto specify the protocol
--dportto specify the port
-j DNAT --to-destination 127.0.0.1:443to 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.
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.
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.
Close down PolarProxy to get the file with the decrypted traffic flushed to disk and open it up in Wireshark to analyze the traffic.
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