Go Deep on iOS Packet Analysis

Mike Furtak
5 min readJun 25, 2017

--

In the course of my recent work, I needed to analyze the TLS handshake between an iOS device and a web server. I found success using three tools in concert:

rvictl

Since iOS 5, devices have included a Remote Virtual Interface (RVI) facility. An RVI allows us to forward packets from a connected iOS device to a virtual network interface on your Mac.

tcpdump

With an RVI set up on your Mac, it’s trivial to capture the device’s packets to disk using the Unix workhorse tcpdump.

Wireshark

tcpdump is great, but its output is not human readable. To filter and analyze the raw packet data, we’ll be using Wireshark.

As I walk you through getting started with this setup, I’ll be assuming that you:

  1. Are comfortable using a Mac and the command line
  2. Have Xcode installed
  3. Have an iOS device and USB cable handy
  4. Have downloaded and installed Wireshark

Ready? Let’s go!

Set up a Remote Virtual Interface

The first step is to connect your iOS device to your Mac, and note its device identifier (UDID). Start Xcode and open the Devices window from the Window menu. Your device’s UDID is listed as the identifier.

You can select and copy that identifier text, so don’t transcribe it manually!

Next, let’s take a quick look at what network interfaces are currently available on your Mac.

$ ifconfig -l
lo0 gif0 stf0 en0 en1 en2 bridge0 p2p0 awdl0 utun0

Great! To create the RVI, use the rvictl command and pass the UDID of your connected iOS device. On Catalina, you can find it in /Library/Apple/usr/bin.

$ rvictl -s dd55c5b6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXStarting device dd55c5b6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [SUCCEEDED] with interface rvi0

If you run ifconfig again, you should now see an RVI interface listed.

$ ifconfig -l
lo0 gif0 stf0 en0 en1 en2 bridge0 p2p0 awdl0 utun0 rvi0

Capture some packets

We can now run tcpdump to capture packets from the RVI and write them out to a local file.

$ sudo tcpdump -i rvi0 -w trace.pcap

You’ll be prompted for your account password because of the sudo, but after that, you should be capturing!

Password:
tcpdump: WARNING: rvi0: That device doesn't support promiscuous mode
(BIOCPROMISC: Operation not supported on socket)
tcpdump: listening on rvi0, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes

Now’s the time to use your application and trigger the network traffic you’d like to capture. When you’re done, press Ctrl+C to terminate tcpdump.

^C3369 packets captured
3369 packets received by filter
0 packets dropped by kernel

With tcpdump stopped, you can tear down the RVI with another call to rvictl.

$ rvictl -x dd55c5b6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXStopping device dd55c5b6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [SUCCEEDED]

Review the captured packets

Start Wireshark and open the trace.pcap file that tcpdump generated. If you see an error warning you about the capture file having been cut short in the middle of a packet…

¯\_(ツ)_/¯

…don’t sweat it! It shouldn’t affect the operation of Wireshark. You should now be able to see the list of packets that were sent and received by your device during the capture.

There’s a lot going on in here, but Wireshark can help us make sense of it!

Wireshark is an incredibly powerful tool, and there’s a ton of great information out there about how to use it well. That said, here are a few quick tips that helped me find the information I needed.

Use filters

Wireshark understands the structure of many network protocols, and provides a display filter language to help you find exactly the right packets.

By entering ssl.handshake, we can narrow the list to just the packets that were part of a TLS handshake.

Colorize conversations

So now we’ve filtered the packets down to just TLS handshake packets, but it’s likely that there are many instances of this kind of exchange in the capture. It’d be great if we could visualize where one handshake stops and the next one begins.

Wireshark calls complete network exchanges “conversations”, and allows you to change the background color for all rows in a particular conversation. To do this, right click on a packet and select Colorize Conversation > TCP > Color 1 from the menu.

Poof! The bounds of that handshake conversation become clear as day.

Follow a stream

Another way to approach filtering is to ask Wireshark to follow the stream. Right click on a packet and select Follow > SSL Stream from the menu.

The result displays just the packets in the first TCP stream we recorded. You’ll notice that this clears the ssl.handshake filter we applied earlier, and substitutes another filter expression, tcp.stream eq 0.

No problem! We can combine the expressions to get exactly the packets we want. Change the filter expression to be tcp.stream eq 0 and ssl.handshake, and we’re down to just seven packets.

Examine packet contents

All that’s left is to look through the data. The bottom part of the window displays the structure and contents of the packet selected in the list above, and expanding the tree structure reveals the fields and data contained therein.

If you’re like me, and you want to nerd out on the raw data, you can expose it by dragging up another hidden split view from the bottom of the window.

Raw hex, anyone?

Wireshark will helpfully highlight the relevant bytes in the bottom display as you select data fields in the tree view above.

Go Deep

So there you have it. With this workflow you can combine rvictl, tcpdump, and Wireshark to easily capture and review detailed information about an iOS device’s network traffic. The next time you need to understand what your iOS device is seeing over the network, and Charles doesn’t quite have enough teeth, I hope you won’t be afraid to go deep.

References

--

--

Mike Furtak

Software Engineering for @Digits. Formerly at @Google working on @crashlytics for @Firebase