Securing an MMO game against cheaters

Posted on 2009-04-08
Last Modified: 2013-12-21
I'm writing an MMO game in VB.NET and C#, and am researching anti-cheat methods. Here's what I've got so far in terms of actual code and ideas:

1) Active detection of cheat applications.
I can detect Cheat Engine, ArtMoney, etc. through process monitoring (process name, process directory and file hash) and FindWindow'ing application-unique classes (e.g. Cheat Engine's window is easily detected by looking for the TMemoryBrowser class). The definitions of such applications can be updated within the source code for each version.

2) Self-hashing of executables.
The SHA1 hash of the executable is calculated post-build and is signed using RSA with a key pair stored on my development machine. The signed hash is appended to the executable file and the application checks it upon run. The public key is stored inside the executable as a CSP blob in bytes. Without the correct hash, the application just crashes.

3) Server side code handles all operations.
The game application itself simply serves as a frontend to the server. Each operation performed in the GUI by the user causes a message to be sent to the server. This means that no operations are actually performed on the client side - instead the client requests that the operation is performed by the server on its behalf. The server runs Apache and the backend is simply coded in PHP. Communication is over SSL and the game application checks that the URL of the certificate and the issuer information is correct. Each message sent has a handshake protocol in which the client's request sends a random number, which the server joins with another random number and an unchanging string and hashes it. The response is sent back with the server's random number and the resulting hash. The application checks the hash and if it is correct the message is authenticated.

4) Encryption on stored sensitive data.
Certain bits of sensitive information that must be stored within the game executable are encrypted using a simple algorithm. This is intended more as a deterrant than a security measure.

5) Security violation logs.
If unexpected requests are made by a client, the server records them in a table. If an account or IP address makes too many violations within a set period of time, they are temporaraly banned. Repeat offenders get permenantly banned (accounts that are permabanned get deleted after 7 days if an admin doesn't intervene). Certain violations result in an instant permaban.

6) Purposeful crashes.
If a user attempts to circumvent security measures, the application can crash itself. Unconventional crash methods are used (calling APIs with bad signatures, invalid casting, division by 0, etc)  along with the usual Throw New Exception to make preventing the crash more difficult. These methods are not all called from a single method, but rather are hard coded separately to different cases, In most cases, more than one method is used and may be called from a separate thread or sequentially in the method code.

7) Dual session IDs
Not only is the usual PHPSESSID used, but a second session ID is used to track a client to a specific user account.

8) Secure variables
To make memory searching/editing harder, some values are stored in a secure variable class that encrypts them and decrypts them for use.

As far as all of this go, most of it can be circumvented by a talented cheater. I'd like to know if there are any specific extra security measures I can take to help secure my game from cheaters, without resorting to shelling out a million pounds to get PunkBuster or VAC on my game. I had a look at DMW and it's interesting but not really what I had in mind. What to games like Dawn of War and Command and Conquer do to stop people from cheating?
Question by:burningmace
LVL 11

Assisted Solution

jgordos earned 70 total points
ID: 24172261
Hi Burning...

The question you're asking is far more complicated than it really looks.  I don't have a ton of time at the moment, but I would like to give you some feedback.

1) you've got the right idea.. but generally, if the game becomes popular enough, you'll get somebody that will load a custom built version, and your symbol names will change... it's very hard to do this and ever finish (by definition, you're always at least one move behind the hacker), but it's a good 'step one'

2) if i can't attack the hash.. then i'll null out the code behind the if/then/else test in the executable.  The hash for my executable will be wrong, but it won't matter, because my patch will remove the "crash" code behavior.  NO-OPS are the hacker's friend.

3) Generally, a good concept; in practice, bad bad bad... if everything goes to the server, you won't scale well.

4) Don't bother.  Do it right or don't do it.

5) not a bad idea.. what traffic, though, would you not expect?

6) again, no-ops are the hacker's friend

7) Agreed. Not a horrible idea.

8) Where's the encrytped data and the decrypt routine? Client side? If so, don't bother.  it will eventually be found, decrypted, and hacked.

Self modifying code is harder under modern operating systems with the hardware enforced data/code bits... but it's still not impossible.  Determined hackers will be able to stay ahead of you.  

The problem is.. you have 1 good path to manage.  1 path of "I can trust my client software", and they have about an infinite number of ways to make your life miserable.

We can discuss further if  you have questions.


Accepted Solution

burningmace earned 0 total points
ID: 24191684
Thanks for the reply. I have some comments for each section.

1 and 2) I know attackers can simply blank out the hash check code with NOP or skip over it with JMP, so I've not made it that simple. All of my anti-cheat and hash check code is spread out across other normal game functions that are called periodically. Some of it gets its own thread. This means that the hacker has to work 50 times as hard to patch up all the checks. It'll eventually be done, but by then version n+1 will be out and their changes will be void. I plan to significantly alter the underlying client-server communications protocol every month or so to force the use of an updated client version. This is easily done with conditional compilation statements (#if(...)  #endif) within my communication class. I can switch the defined communication protocol constant (e.g. undefine COMMS_CSV and define COMMS_XML) to change the entire function of the class. It's not a particularly large amount of effort on my part, but it messes up all previous versions of the client enough for them to have to use the new one.

3) This works in the same sense of any other game. I'm not sending every click there, but rather anything that affects the player's account or any other players in game. For example, I want to buy an item. I click the buy button and the client sends a request to the server to buy that item. The server checks if the player that the client is logged in as has enough money, and if so buys the item. There should never really be a case when the client sends a request to buy something that it cannot afford, as the game application won't usually allow the request to be sent if the cost is more than the money value stored in memory.

4) It's not something I designed to be utter rubbish, it's actually on a par with WoW's packet encryption algorithm (but mathematically stronger). Funny story about that - I designed the algorithm about a year ago and posted my findings on some crypto site somewhere. Somebody came back and posted the code to WoW's packet encryption and it compared quite admirably. I'm proud I came up with something better than Blizzard did with all their money and expertise.

5) In certain cases some requests should never be sent by the client. For example, a request to start random_applet v5 when the player only has random_applet v2 can only be a case of someone attempting to hack the game. Also, badly formed messages (ones that do not fit the usual protocol) and bad handshake responses (I use challenge/response hashing) are deemed violations. Too many violations gets you an IP ban. The idea (mainly) behind this is that it's much harder to reverse engineer the game protocol if you're getting IP banned all the time when you try to test it. It also deters normal players from using hacked clients, because if they get caught they get their account permabanned.

6) Again true, but they have their work cut out. The crash code is split across the rest of the game code and resides in some really odd places. In some cases the crash code doesn't even appear to be something that should crash.

7) I always use secondary session IDs and "secret values" to prevent session ID theft and of course just in case a flaw is found with PHP's session ID code.

8) This one is a little different to #4. The reason for encrypting them is to prevent the "larger crowd" from using memory editors to find the value in memory. It uses a few tricks to make tracking the value from a static pointer a little harder, and the encryption algorithm is a combination of my own and another. On XP and Vista, depending on security settings, the value can be stored in protected LSA memory. Of course, on XP it may be possible for someone to use an auditing tool like Cain to retrieve the contents of LSA memory. Anyway, editing these values isn't a security risk as such, as the values are server side. It simply makes it easier for me to detect the real cheaters from the idiots that think their money value is ever sent from client to server and stored.

Featured Post

DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
As game developers, we quickly learn that Artificial Intelligence (AI) doesn’t need to be so tough.  To reference Space Ghost: “Moltar, I have a giant brain that is able to reduce any complex machine into a simple yes or no answer. (http://www.youtu…
This Micro Tutorial demonstrates using Microsoft Excel pivot tables, how to reverse engineer competitors' marketing strategies through backlinks.
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question