Wednesday, September 29, 2010 9:05 AM
If you develop a game which runs heavily on the browser side for example with Flash, Java or Silverlight, you risk to have some smart pants which use the well known "Cheat Engine". Cheat engine is a small but yet powerful little application which let you scan the memory of a running program. So let's say at some point you have 1000 gold, then a bit later 900, you can scan first for 1000, then change the value and ask for a rescan, and Cheat Engine will then show all the addresses which match your searches. So far it wouldn't be an issue, but Cheat engine allows to change values on the fly, that means somebody could then (once he/she found the correct address) change the value and put more or less whatever he/she want.
Well, I developed a small Silverlight application which use a self defined class called "CheckedDouble". This class contains not only the double value which is what interest us, but as well an "hidden" second value which will contain a copy of the value... with a little twist. This allows to store the same value but doesn't show it to tools like "Cheat Engine". Also this class offers a little tool which allows to check if somebody cheated or not. The smartest way to use this info is to contact the server back and flag this user as cheater and don't show the info directly to the user, such that you can delete his/her account without showing how you did it.
Full sources can be found here:
As added bonus, as we deal with objects and not with a struct (double), the memory address changes, and it makes the life yet harder for those kids.
BTW, this class you will find in the ZIP overload most if not all operators and therefore can be used as you would use any double.
Wednesday, September 29, 2010 10:33 AM
Hi. This is a nice approach. However I see some problems with that: you won't stop anyone who really wants to cheat with that kind of protection. It's true that the hidden value is not shown when you search for that exact value. However, a more sophisticated approach is to simply check for changed variables when you trigger some actions. Repeat that like 5-10 times to eliminate "false positives", and eventually a memory scan will spit out not only the address of the original value, but also the hidden value (because it also changes every time). And the fact that the relative difference of the hidden value is always the same as the original value makes it even easier to find the correlation (e.g. gold 1000 => 900, hidden value FFFC17 => FFFC7B).
Furthermore, Silverlight is not a secure platform in the first place, as it is possible to extract your application and look at the source code with most simple tools (unzip + reflector), so your algorithm to hide values lies there, open to read for everybody who knows little of C# or a similar language.
Maybe use a more complex approach, with a random seed and a non-linear mathematical function, combined with obfuscation, and you will indeed prevent most script kiddies from hacking into your highscore system. Until they find another weak link, that is :>.
Wednesday, September 29, 2010 11:01 AM
Indeed without obfuscation this approach doesn't help much. And you will never really stop true dedicated hackers if the process runs on their machine.
Yet you must define how much security you want, if avoiding just a 2 click scan is enough or not etc...
For the game I'm currently developing, I will not only obfuscate my code, but the player progression will be checked, and people which are outside a certain range will be flagged as potential cheater. For example, if you know you need to play 1 hour for 1 level gain and you suddenly see somebody which gains 10 levels in 1 hour you know there is something wrong.
However trying to avoid the cheaters is something multi player games must have, otherwise the good players will simply leave the game as there is no way you could compete against cheaters (beside cheating yourself) and soon your game will be ruined. Therefore every single bits of "security" will help even if those solutions are never perfect.
Wednesday, September 29, 2010 11:19 AM
Yes, I agree. The best solution for that problem always is to put as much control and validation logic as possible on the server side, and I like the idea of having "fuzzy" rules like that to detect cheats.
Don't get me wrong, my opinion just is that some sort of pattern matching ("look for a difference of 100") isn't really that much harder than "look for the value of 1000, now look for the value of 900", and I'd personally still count that to the '2-click-scan' category. Maybe as a cheater you need multiple attempts when you see that the first one didn't succeed, but still.
Wednesday, September 29, 2010 1:10 PM
Sure, a non linear function (like some sin or whatever), a MD5 or even some sort of string hash could be used and would be indeed much stronger than a simple math formula like in this example.
Note that it is not the same code I will use myself (as I would avoid to share too much of my own security mechanism). I was trying more to talk about the concept itself as I know that many RIA developers don't even count on such issues like a memory scanner / editor.
Wednesday, September 29, 2010 4:41 PM
Sounds like the hacked highscore problem. Obfuscating the score will make life a little harder, but the weakness is still that your Silverlight game is an untrusted client. If I were to make a multi-player game with state on the server, then the user's score would also be on the server. Players could change it with a memory scanner, but it would not have any effect. If a certain score earns you the right to for example, a new weapon, then you would also authorize this weapon on the server. The hacked highscore problem cannot be solved, it can be minimalised though.
This page is very informative, what applies to flash, applies to Silverlight.
Wednesday, September 29, 2010 5:32 PM
If I were to make a multi-player game with state on the server, then the user's score would also be on the server. Players could change it with a memory scanner, but it would not have any effect.
At some point there needs to be some actions from the client that trigger a score change. If the game score is completely tracked on the server, the next attempt would be to send the server the event notifications he wants to hear to increase the score (I'm super pac-man, I can eat a thousand dots per second...). Like you said, you cannot prevent it, you can only make it harder and harder.
Thank you for the link, sums it up quite nicely.