15

Thanks to the recent browsers enhancements, developing games with canvas and javascript has become a good option, but now that the code is easily accessible, just writing

javascript:score=99999

or

javascript:lives=99

Will spoil the game objectives.

I know that with some server-side checking something can be done, but I would prefer to access the server just to store player stats at the end, or even have it client only in most cases.

I wonder if at least the are some best pratices to start with.

(using not so obvious variables names is a start, but not enough)

-Added-

Thanks for the replies, I was looking to improve the client-side code, enough to stop "casual hackers", but still leaving the code as clean as possible. Anyone that really wants to hack it will succeed anyway, even with server-side checks, as I've seen it in many flash games.

Omiod
  • 11,285
  • 11
  • 53
  • 59
  • 1
    Theoretically it's impossible, but the way I prefer is `(function(){/*insert your code here*/}());`. – JiminP Jun 12 '11 at 08:42
  • 1
    Better questions to ask: Who and what are you really trying to prevent? Who is your audience, and why is preventing cheating important to your goal? And in the end, you may want to ask, does it really matter if they cheat (if they really want to); it may end up that allowing modifications may even improve your product for your audience. – user120242 Jun 12 '11 at 10:41
  • eg: There are entire web sites with modified Flash games for cheating with ad supported revenue. There is a market there. Why bother trying to stop it, when you could even benefit off it, or prevent others from benefiting from your customer's lack of technical knowledge? – user120242 Jun 12 '11 at 10:43
  • You are right, in most cases this is not an issue at all, but just think to a simple on-line scoreboard. Cheating would make it useless. – Omiod Jun 12 '11 at 17:58

3 Answers3

11

One way is to send a record of every move to the server as well, then to verify that those moves would have got that score.

That's easy for games like solitaire or chess, but not really for more complex games.

A simpler version of that is to work out the max points that could be obtained per second, or per move, then to verify that the score isn't higher than your theoretical maximum.

Another way is for each move to be recorded on the server, and to total up the score there. That means there is no send at the end of the game, and that those variables are only for display, not the real score.

Offline games could be starred on the highscore table or something to show they aren't verified.

It's worth pointing out that with any javascript debugger, such as the Inspector in Webkit, Firebug for Firefox or Dragonfly on Opera it's trivial to change the value of variables on the client side, even if your code is in a closure. Any form of obfuscation is pointless, as again it's easy to watch which variable corresponds to the score as the game is played, and any encoding or whatever can simply be read out of the code.

Rich Bradshaw
  • 71,795
  • 44
  • 182
  • 241
  • That may be true, but the OP specifically states not wanting to put calculations on the server, as well as implicit indication that he just wants to make it more difficult. Making values change in non-obvious ways (such as encoding values in alternate bit order and encoding strings) and obfuscated code will make it more difficult. – user120242 Jun 12 '11 at 10:27
  • Also worth noting, is that arguably even server based anti-cheating has limits. It may be the best solution, but will not necessarily be the best efficacy/cost ratio, depending on situation. I could very confidently tell you that anything you implement I could circumvent within a day. Such as just by faking valid moves. Even server side checks, at some level, can be seen as "obfuscation". – user120242 Jun 12 '11 at 10:34
  • 2
    True, it's required that you eventually have to trust something, but you can attempt to discard impossible scores. At the end of the day, it's usually easy to tell the difference between real and fake scores, so even manually pruning them would work. – Rich Bradshaw Jun 12 '11 at 11:28
11

I'll say what I said at my comment: put every source code in (function(){ }());. Then, the variables and functions can't be accessed from outside.

Example:

(function(){
    var a = 'Foo';
    var b = 42;
    function helloWorld(a,b){
        for(i=0;i<b;i++)console.log(a);
    }
    helloWorld(a,b);
});
//Can't access to a, b, or helloWorld using javascript: or default console of Google Chrome,
//but people still can see by looking source code and may be modified by other tools
//(see comments of Tom & user120242)

I 'learned' this technique this when I dig into Les Paul Google Doodle.

To be more secure (not completely secure, but it'll annoy some hackers), compress and obfuscate your script by tools something like YUI compressor or packer.

JiminP
  • 2,136
  • 19
  • 26
  • Thats the right way to do it. Cause its an unnamed self invoke function you cant access them later. And all variables are stored in the function context that cant access from outside. – Andreas Köberle Jun 12 '11 at 09:38
  • 6
    This post implies that these variables and functions can never be accessed from the outside, which is obviously false since the code is available on the client side meaning that anything can be accessed if desired. One needs a server with authority to make anything near secure. – Tom Jun 12 '11 at 09:42
  • 11
    @eskimoblood @JiminiP @Tom I can give you an example of changing those values _without_ modifying the code. Pull up the Javascript dev console and set a breakpoint on "var b=42;", then when the breakpoint occurs, type in the JS console "a=b=999999999". Pretty trivial for anyone to do with ease. – user120242 Jun 12 '11 at 18:41
2

In order of preference:

  1. Send player moves or statistics to server. Prevent strange behavior. eg: Score too high, invalid actions, actions that cannot be replayed, etc
  2. Prevent strange behavior on client-side. Same as above but not on server. eg: sudden lives changed, moving too fast, etc
  3. Create obfuscated JS output (which you should be doing to reduce JS size anyways) eg: GWT (Java to JS compiler), Google Closure Compiler (ADVANCED_OPTIMIZATIONS will obfuscate more, --output-wrapper (function(){%output%})() to wrap in closure), Yahoo Compressor
  4. Obfuscate variable values eg: Encode strings (xor, substitution, BASE64), don't use normal variable increments
  5. Use a closure to encapsulate variable names: (function(){code here})()

EDIT: I want to make clear that the best solution is still to move calculations to the server, as Rich Bradshaw had said. These things can only do so much, even after you obfuscate the code.

Here's a link that also applies to your Javascript game, and I think is probably the best possible answer to your question: What is the best way to stop people hacking the PHP-based highscore table of a Flash game

The most important idea to get from that link is:

The objective isn't to stop this attack; it's to make the attack more expensive than just getting really good at the game and beating it.

Community
  • 1
  • 1
user120242
  • 14,918
  • 3
  • 38
  • 52
  • Could you explain whet you mean with "don't use normal variable increments"? What is your alternative to `score += 100;` ? – Omiod Jun 12 '11 at 18:15
  • Note: the cheater could still trace the function that effects the dispalyed score, and hook the right function call to artifically increase the score. Anyhow, here is an idea that matches much like what Brad is saying: separate the displayed score and the "effective" score. Have the "effective" score append an integer hash. And tally actions that attribute to score. You can have tallies be decremented instead of incremented to make it more confusing. You can additionally use fancy math to store values. And/or even make the score xor with other important values. – user120242 Jun 12 '11 at 19:13
  • You can also use type casting to a different base. parseInt(x,radix) Number.toString(radix). This can make it difficult for casual memory search (which is fairly common even among young children, at least that I've seen on computers). But it won't stop them. – user120242 Jun 12 '11 at 20:06