(Crossposting & backdating some content from the Neohapsis blog, which will soon be defunct)
We hope everyone found something interesting in our talk today on Multipath TCP. We’ve posted the tools and documents mentioned in the talk at:
Update (Aug 12, 2014): We’ve now also added the slides from the talk.
At the end we invited participants to explore MPTCP in a little more depth via a PCAP challenge.
Without further ado, here’s the PCAP: neohapsis_mptcp_challenge.pcapng
It’s a simple scenario: one MPTCP-capable machine sending data to another. The challenge is “simply” to reassemble and recover the original data. The data itself is not complex so you should be able to tell if you’re on the right track, but getting it exactly right will require some understanding of how MPTCP works.
If you think you have it, tweet us and follow us (@secvalve and @coffeetocode) and we’ll PM you to check your solution. You can also ask for questions/clarifications on twitter; use #BHMPTCP so others can follow along. Winner snags a $100 Amazon gift card!
- The latest version of Wireshark supports decoding mptcp options (see “tcp.options.mptcp”).
- The scapy version in the git repo is based on Nicolas Maitre’s and supports decoding mptcp options. It will help although you don’t strictly need it.
- The is an mptcp option field to tell the receiver how a tcp packet fits into the overall logical mptcp data flow (what it is and how it works is an exercise for the user )
- It’s possible to get close with techniques that don’t fully understand MPTCP (you’ll know you’re close). However the full solution should match exactly (we’ll use md5sum)
Depending on how people do and questions we get, we’ll update here with a few more hints tonight or tomorrow. Once we’ve got a winner, we’ll post the solution and code examples.
Update: Winners and Solution
The challenge was created using our fragmenter PoC tool, pushing to a netcat opened socket on an MPTCP-aware destination host:
python mptcp_fragmenter.py -n 9 --file=MPTCP.jpg --first_src_port 46548 -p 3000 192.168.1.33
The key to this exercise was to look at the mechanism that MPTCP uses to tell how a particular packet fits into the overall data flow. You can see that field in Wireshark as tcp.options.mptcp.dataseqno, or in mptcp-capable scapy as packet[TCPOption_MP].mptcp.dsn.
The mptcp-capable scapy in our mptcp-abuse git repo can easily do the reassembly across all the streams using this field.
Here’s the code (or as a Gist):
# Uses Nicolas Maitre's MPTCP-capable scapy impl, so that should be # on the python path, or run this from a directory containing that "scapy" dir from scapy.all import * packets = rdpcap("pcaps/neohapsis_mptcp_challenge.pcap") payload_packets = [p for p in packets if TCP in p and p[IP].src in ("192.168.1.26", "192.168.1.33") and TCPOption_MP in p and p[TCPOption_MP].mptcp.subtype == 2 and Raw in p] f = open("out.jpg", "w") for p in sorted(payload_packets, key=lambda p: p[TCPOption_MP].mptcp.dsn): f.write(p.load) f.close()
These reassemble to create this image:
The md5sum for the image is 4aacab314ee1a7dc5d73a030067ae0f0, so you’ll know you’ve correctly put the stream back together if your file matches that.
Thanks to everyone who took a crack at it, discussed, and asked questions!