Packet visualization with Python
A long-time pet project of mine is decoding the network protocol of Valve Software’s “Source” game engine, used in Half-Life 2, Counter-Strike: Source, Team Fortress 2, and Left 4 Dead. I’ve never made it very far, but it has led me down some interesting paths in reverse engineering, debugging, and visualization. One example of the latter is this Python script I wrote to analyze a series of packets. It creates an image in which each row represents a packet, and each pixel represents one byte of the packet. The pixels range from black (for a value of 0×00) to bright green (0xFF). I got the idea from Greg Conti in his interview on the Network Security Podcast. Here’s what I did:
1) Start Counter-Strike: Source and connect to my server.
2) Use Wireshark to capture packets going from my machine to the server. Filter out any extra packets captured, and save the capture to a file called “capture.pcap”.
from scapy import * from PIL import Image capture = rdpcap('./capture.pcap') imgHeight = len(capture) imgWidth = 0 for pkt in capture: if(len(pkt.load) > imgWidth): imgWidth = len(pkt.load) imgSize = imgWidth, imgHeight print 'Image Size: ', imgSize img = Image.new('RGB', imgSize, (255,255,255)) putpixel = img.im.putpixel for i in range(0, imgHeight): for j in range(0, len(capture[i].load)): color = ord(capture[i].load[j]) print 'Writing pixel', (j,i), 'with value:', color putpixel((j,i), (0, color, 0)) img.save('./result.png')
(This could be done more quickly in newer versions of the PIL, but for now I don’t care.)
The resulting image, saved as “result.png”:
As you can see, you have to zoom in to really see what’s going on. Once you do, you can easily see some patterns. For example, here’s the first 100 or so lines:
I put red rectangles around a couple of columns that correspond to 4-byte counters incrementing by 1. You can see it by the long, steady gradient. Orange rectangles highlight some columns that mostly stay constant. The yellow box highlights two cycling values.
It’s interesting to see that a few of the rows seem out of place, going by the alignment of those constant values. I have no idea why this is, but it’s interesting.
Going back to the original image, I can look for the things I was doing in-game during the packet capture. During this portion, my character was running straight across the map:
The packets started carrying more data when I started running (in the image, the fat part corresponds to my running). Since the data seems to be constant, I would venture to guess that the game transmits deltas in each packet (the equivalent of “I’ve moved a foot forward from my last position” in each packet).
The noisy part at the bottom was when I rotated my character 360 degrees (using the “+left” command in-game so as not to pollute the data with rotation around the other two axes):
This is really interesting. I have no idea what to make of it, yet.
So that’s all I’ve got for now. Hopefully this sort of thing will help me continue my quest to conquer the Source multiplayer network protocol.