Game developers are often times not experienced in hacking games, or how reverse engineers, modders and server emulator developers analyze the games while working on their respective projects. For the hackers this is good news, because it makes their life easier. For the game developers less so, because they don’t understand how to protect their products.
Backstory
A few months ago, I got acquainted with the developer of an indie (M)MORPG, and being a server developer, the first thought that popped into my head was to write a server for their game, just for fun. Luckily they hadn’t protected their game at all yet, so I whipped together a simple packet logger, got the information I needed, and a few hours later I had a basic server going. It was a fun afternoon, and I probably would’ve stopped there, but while looking through the packets, I noticed some rather glaring security issues and potential exploits. That’s when I decided to have some more fun and explore the game and what I could do with it.
Spawning items, flying around, killing entire maps full of monsters in seconds; it’s always interesting to see how far you can go with a simple packet editor. But after I’d had my fun, I reported the issues I had found to the developer. They fixed most everything I had found rather quickly, and then they figured they would give protecting their game a try, by encrypting their packets.
As I talked with this developer, I realized they had no idea how I did what I did. They figured if the packets are encrypted, I can’t read them anymore, I can’t modify them anymore, and I wouldn’t be able to send my own packets, because I don’t know how to encrypt them. But since I simply read the client’s code, I did know the encryption. After they had published that update it took me just a few minutes to open up the client, reverse engineer their custom encryption algorithm, and then I was back up and running.
This was their first encryption algorithm ever and it was fairly simple. It was basically a Vigenère cipher, with a password that was a) stored in plain text inside the client, and b) could be inferred from the packets, because the 0 bytes in the packets made it obvious by how much the byte had been shifted. This way I immediately knew what they had done and understanding and reverse engineering their code became even easier.
After this failed attempt they figured their custom algorithm had just been too simple, and they rewrote the encryption. This time it wasn’t immediately clear to me what the encryption was from the packets, but once I had opened up the client I was greeted by references to AES. That made it simple once again. Download an AES library, plug it in, look up how the keys are generated and shared in the client, and I was done once more.
They made an effort, but in the end they failed to keep me out because they weren’t familiar with my methods. They even ported AES to their engine because they figured that’s an industry standard, it must be secure, but this all stemmed from the incorrect assumption that you need to protect your packet data.
Annoyances
The thing is, you can never, ever, prevent users from hacking your client. Assume that they can literally read your code, that they know everything you’re doing on the client side. Well, how are you supposed to protect anything from hackers then? The trick is to annoy them. Annoy them to the point where they don’t want to work on your game anymore. Until they figure it’s not worth it.
An encryption is actually a good first step, because that keeps out everybody who is not able to reverse engineer your code. Without an encryption they could just read the raw packets and that’s that. Getting through the encryption requires at least some effort.
However, it is my believe that you shouldn’t use a well established encryption algorithm. AES is most definitely difficult to crack, but don’t forget that I’m not trying to crack the packets. I just read the code, see that it’s AES, and then I basically know how to en- and decrypt everything. Even modifying the algorithm slightly is relatively pointless because I can just compare your code to the original and find the differences when I notice that I’m not getting the correct results.
A custom algorithm on the other hand forces me to actually understand and reverse engineer it. And even though I said that you should assume users can literally read your code, that’s still an actual hurdle. And the more creative you get, the more time and effort it takes to reverse it. I realize this sounds kind of counter intuitive, but the crude, custom algorithm the developer had written was actually a better idea than using AES. They would’ve just have to tweak it a little.
If you have a popular game on your hands though, someone will eventually break your encryption or find a way around it. It’s just a matter of time. They’ll figure it out, they’ll start doing things you don’t want them to, and that’s that. Well, unless you simply change the encryption. For you it’s fairly simple to make some quick changes or even swap out the entire encryption, but every time you do, someone has to go back in there and reverse everything once again. They might do this for fun a few times, but nobody will do it consistently without getting annoyed by it. “Another week, another update, another new encryption… Ugh, here we go again.” And it doesn’t have to stop at the encryption.
Another underutilized method of annoying hackers is to simply randomize a few things on a regular basis. For example, opcodes. Opcodes are used to identify packets, and a hacker might be using packet 0xEA28
to, say, kill NPCs. For some reason you might be unable to change/fix this behavior, but if you randomized your opcodes regularly, hackers would need to look them back up every time. “Another week, another update, 496 random opcodes… Ugh, here we go again.” And while hackers might only be interested in a handful of specific packets that they can use for their purposes, server developers actually need all packets, and by randomizing your opcodes you essentially stop them in their tracks. Very, very few people will ever go to the trouble of updating hundreds of opcodes on a regular basis.
Or how about something really nasty, randomizing the fields inside the packets, so even if a hacker has the encryption and the opcodes, they have to rewrite the entire reading and writing of every packet every week? There’s so many little things you can do, with very little effort, that could even be automated, that would annoy me personally so much that I would probably drop any project related to your game in two weeks or less.
Conclusion
Essentially, you should never think about how to encrypt your packets even more, but about how to slow down and annoy reverse engineers. The keyword is obfuscation. Remember that most of them are doing it for fun, and if it stops being fun, they’ll stop doing it. I might have fun developing a server emulator or a packet editor, but I definitely don’t want to get the new opcodes every week, or reverse engineer another encryption algorithm. No, thank you.
I find it fascinating that, to my knowledge, there are very few examples of companies employing such strategies, despite of how simple they would be to implement. Only two explanations come to my mind. A) They don’t care. It’s possible, but since companies usually do at least try to get rid of hackers, I doubt that. Or B) Just like the game developer I talked to, they just don’t know better. They see their encryption as their barrier, and once it’s breached they either lie down and give up, or, at most, put up a new wall. Very few ever come up with the idea of putting an ever changing labyrinth in front of their castle. Then again, I suppose I’m kind of thankful for that 😊