The phone belonged to an Android developer, so he'd already rooted it, enabled developer tools, etc... He'd also installed a packet capture application which worked, but didn't allow me to see things in real time.
The Android SDK bundle contains the adb binary, which is required for connecting to the phone. Extract adb and drop it somewhere in $PATH
# run adb as root: adb root # connect to the phone over WiFi (the phone's owner had # already enabled this feature with 'adb tcpip' via USB): adb connect <phone's wifi ip address> # check that we get a root shell on the phone: adb shell 'id'
It turns out that the packet capture application included a tcpdump binary at /data/data/lv.n3o.shark/files/tcpdump, and invoking it from the adb shell worked normally. It produced the usual startup message, and then a one line summary of each packet.
adb shell '/data/data/lv.n3o.shark/files/tcpdump -c 2' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on wlan0, link-type EN10MB (Ethernet), capture size 96 bytes 12:37:04.053553 IP 192.168.1.8.rplay > 192.168.1.22.57182: P 2817938036:2817938134(98) ack 1887364010 win 1358
12:37:04.054244 IP 192.168.1.8.42742 > google-public-dns-a.google.com.domain: 12160+ PTR? 126.96.36.199.in-addr.arpa. (44)
Progress, but not wireshark. I expected that adding the '-w -' flag (write pcap data to STDOUT) to tcpdump would allow me to collect pcap data from adb's STDOUT on my macbook, and feed it into wireshark, but didn't give the result I wanted. There were two problems:
- Tcpdump's informational messages got mingled with the pcap data when the data came out of adb shell. This was a problem.
- Binary data pipelined through the adb shell got corrupted. The adb shell is a tty of some flavor, I guess, and this is not a safe way to pass binary data.
I solved the first problem by trashing tcpdump's informational messages. These go to STDERR on the phone, but were mingled with STDOUT when they reached the shell on the macbook. '2>/dev/null' (trash stderr) got rid of problem #1.
Problem #2 was resolved by base64 encoding the pcap data on the phone, before handing it to adb shell, and then removing the base64 encoding on the macbook. Fortunately there's a base64 binary in the root user's path on this Android phone.
The bits that go into the final solution are:
- adb shell 'command' (run command on the phone)
- tcpdump -w - 2>/dev/null | base64 (run tcpdump, trash STDERR, encode the output)
- base64 -D (undo the base64 encoding - this runs on the mac)
- wireshark -ki - (wireshark '-k' means start capture immediately, '-i -' means read from stdin)
Putting it all together we have:
adb shell '/data/data/lv.n3o.shark/files/tcpdump -w - 2>/dev/null | base64' | base64 -D | wireshark -ki -
Job done. The command above connects to the remote Android phone, fires up tcpdump on the phone, fires up wireshark on my laptop, and bolts the two together, making it possible to work with packets (as seen by the phone) in real time on a laptop.
It's not 100% real time, there's some batching and latency, but it was okay for my purposes. Adding tcpdump's '-U' flag might help here.