Last weekend I participated in Ghost in the Shellcode, a capture the flag competition (ie. hacker contest) which included several unique challenges that involved hacking (cheating) at an MMORPG style game. The game was built using the Unreal 4 Engine, so it's possible that this protocol is same across other games with the same engine, but I have yet to confirm that.
As someone who loves huffing ethernet and inspired by talks such as "DEFCON 19: Hacking MMORPGs for Fun and Mostly Profit", I immediately went for reverse engineering the protocol so that I could build a proxy to perform all sorts of cheats. Sadly, I didn't have enough time to build a proxy, but I was able to write a Wireshark plug-in that parses most of the protocol (available here).
There is a lot to cover in this protocol, so this post will only cover some highlights.
For starters, this is a TCP based protocol that hops around on port 3000 through 3016. This is typical of MMORPGs that spread what looks like a unified map and environment over multiple servers and instances.
Note that once you add your plug-in registers the ports the target protocol runs on with the DissectorTable, you can now filter based on the name you've given the protocol. In this example, I can filter on gits.
Another thing to note is that the packets from the server are much larger than the packets from the client. The game client will typically only need to send the server updates of the player's location and abilities used, while the game server needs to update the client on numerous surroundings, including other players and dynamic content. This makes packet data a wealth of information.
In this scenario, I have control of one part of the communications, namely the client. This gives me an advantage as I can capture packets while performing various actions and then correlate changes in packet data to those actions.
The first file I dig into is "moving in a circle and jumping.pcapng". A boring name, but it tells me I should expect the x and y coordinates move in a predictable fashion, with the direction turning constantly one way or the other, followed with a rise and fall of the z coordinate.
I start in reverse and dump the hex from a series packets that show low entropy (few bytes value changes).
From this I can see that the packets contain dynamic content. In two of the packets there was another data chunk prefixed to the data chunk I was interested in, and so I had to manually align the packets. I note that the lead bytes (marked in green) for both of these data chunks have similar values, and guess that they identify the data that follows.
Looking at the entropy bytes (marked in yellow), I notice that third bytes change much less than the first two bytes. This provides an important hint of wither the data is big-endian or little-endian (little-endian in this instance). For a 32bit integer, we should expect a 4 byte value, so the next byte that hasn't changed is the most significant byte. Now we have byte alignment, which is confirmed by the x and y fields when I examine the running in a circle, and the 4 bytes following the z coordinate (not indicated on the scratch sheet) is the direction of the player.
This leaves a very constant field of zeros, and a unknown byte after the id marker. Looking at the preceding data field with a very similar value, I come to suspect that the id markers are two bytes. Thus the client traffic has been parsed, while not fully interpreted (very difficult to interpret the meaning of zeros).
This is pretty much the process I used to parse much of the protocol. I did have another trick for finding new id markers & data. The game generates a lot of traffic, of which 80% is the same (especially if you're standing). In order to quickly search through the packets for new activities to document, I sorted the packets by length, and ignored the packets that had the same length as the ones I've already documented.
From there I repeated the process for a dozen files, until I stopped seeing unknown data chunks. Perhaps in the future I'll post on how I write Wireshark plug-ins, as there are a lot of tricks I use in writing them that help in speeding along the reversing process.
What I want to showcase though, is the reward from parsing out the protocol (other than reward of the act itself). First, this game did not have a map, mini-map, or display coordinates. By checking my packets I was able to tell where I was. More importantly though, I was able to figure out where to go.
When you install the game, it comes with all the static resources such as the map, object models, and textures. When the game connects to the server, the server needs to communicate to the game all of the dynamic information, namely the locations of objects that are either dynamic, or that the developers wanted to hide from the client for whatever reason.
Here's an example of that communication. Specifically details on the location of various eggs the player was suppose to find.
Now that we have this information, we can easily graph it in any spreadsheet program to get a basic map.