Making a hack proof game in Javascript [closed]

2020-02-17 01:39发布

问题:

Closed. This question needs to be more focused. It is not currently accepting answers.

Want to improve this question? Update the question so it focuses on one problem only by editing this post.

Closed 3 years ago.

Suppose you created an online game in HTML5/JavaScript. All the code would be downloaded into the user's browser, and they would run the game.

How do you stop someone from copying the game onto their computer, and injecting functions and modules to cheat? For example, they could write a function that auto-aims at the nearest enemy sprite for example.

Is there any fundamental way to protect people from doing this sort of thing by designing your game code in a certain way?

回答1:

What is stopping someone from copying the game onto their computer, and injecting functions and modules to cheat?

Nothing.

Is there any fundamental way to protect people from doing this sort of thing by designing your game code in a certain way?

Nope.



回答2:

This is why most JavaScript games rely heavily on a server state, to prevent cheats.



回答3:

In short, no. However, you can obfuscate Javascript to make it much more difficult.

For things like scores, a user could in theory POST any score to your handler script. In this case you could use a session and regularly post back to the server through AJAX.



回答4:

Some thoughts

Server side:

  • Store the games internal state sever side and check the input send by clients on the server.

  • Autoaim: Create fake sprites which are invisible to normal players, if they get hit too often you have a bot. (will not always work as the bots may be updated to check for invisibility)

  • check client reaction time to changes on the server, check for too many too fast reactions. (has to accept a large number of fast responses before reacting as a human could react fast and the time has to account for the network delay to catch anything). Give the player some sort of captcha, a regular player would never see it.

Client side:

  • use obfuscation to make it harder to interface with your code

  • check for functions defined in the hacks you know about. Has to be modified/updated often as the creators of such hacks can work around those.

  • Game design: making your game less repetitive this makes it harder to write tools/bots for it.

  • update the client to change parts of its structure from time to time. While this will not stop bots it will take work to keep them running. Either make it transparent to the user or disguise it with a new feature.

Important: make sure your server interface checks the user input, obfuscation and client side checks wont help against someone writing their own client.



回答5:

I like the question, and while there are probably better answers, here are a few off the top of my head that may (or may not) work:

  • Obfuscation. Yea, it's not guaranteed and someone can eventually get to it, but it's a pain in the butt to deal with sometimes.
  • Generate the JS with a new temporary token each time. You may be able to templatize the .js running the code and insert a server generated token that differs per each instance. The token could be temporary and it could be one way to validate the authenticity of the code
  • There's probably some way to determine the proper location of the script being run - but this could probably be faked

In general, its hard, and all of the suggestions above can be worked around. I guess the key is to make it hard for them to cheat, but given that there are cheaters for even secure online mode games, it's going to be hard to prevent JS games from being susceptible to that as well.



回答6:

Is there any fundamental way to protect people from doing this sort of thing by designing your game code in a certain way?

The only sane method is to keep critical pieces of the code on servers you control and never give it to the users' computers at all. The hard part is making this square with keeping the game fast enough to be playable.



回答7:

You're attempting to do the impossible. The best advice I can give you is that if you are plan on persisting any data like coins/money/gold, levels, whatnot you make sure you never trust the client and make as much logic server sided as a possible.



回答8:

I think the way to go would be to write the client in a way such that you dynamically alter the client code and verify the use of thusly created code on the server.

E.g. have a namespace like this

window.mynamespace = {

    foo : function(){
        // some stuff here
    },

    bar : function(){
        // some more stuff here
    } 
}

which contains all your client code and make all your server methods require a token that is the result of a previous dynamic evaluation of the code base. make this harder by redefining methods and changing method names. Here are a few sample challenges (this only makes sense if challenges are created dynamically and not predictable). All contain a task first and then a challenge that will be used to create the authorization token for the next request. (These are response objects from the ajax calls). Basically the task will be eval'd and the result of the eval'd challenge will be the next token.

{
    task: "mynamespace.baz=mynamespace.foo;mynamespace.foo=undefined;",
    challenge: "mynamespace[11].toString().substr(10,22)"
            // get part of a well-known functions source code
}

{
    task: "mynamespace.bar=function(){ /* new code here */ }",
    challenge: "var xy=0;mynamespace.each(function(item){xy+=item.toString().lastIndexOf(';')}); xy"
            // accumulate the last index of a semicolon in all elements
            // of the namespace
}

To beat that and still get valid authorization tokens, the client would have to write an entire javascript emulation layer. Although that can be done, I would try to make the server code change in fundamental ways very often to make this technique almost impossible (so the emulation layer won't know what to emulate).



回答9:

they could write a function that autoaims at the nearest enemy sprite for example.

You can do this even for games were most processing happens server-side! You just need to analyse the display quickly enough.

You can even re-implement parts of the game AI to try to predict how bots will move. Not an easy task if you don't have access to the game's source code but if you log lots of gameplay time, you could apply machine learning techniques.

Is there any fundamental way to protect people from doing this sort of thing by designing your game code in a certain way?

Don't forget that you can change the game itself, not just how it is implemented. For instance, use randomly-generated levels rather than static ones, use human players rather than bots, make your art/sprites more complex, make more use of audio, put a limit on how fast the cursor can be moved, add cooldown times to weapons, add hidden hazards, and so on.



回答10:

In theory you are playing a game against hackers. You can't win this game but you make it challenging.

My suggestion would be to use as much server side logic as you can possibly use and use Javascript Obfuscation.

Javascript obfuscation will make it extremely hard to understand the code, but even better it will make it possible for you to release several thousand versions of your code while maintaining the same code base.

I have used JScrambler to do this on one occasion. Instead of having to hack the code of 1 game, hackers will have to hack several thousand versions of the code! :)



回答11:

You can put everything the code ever calls inside of a closure:

(function() {
  var cantSeeMe = function() {
    // do some game stuff!
  };

})();

Outside of the closure, it will be very difficult to get at the code for "injection hacks" (overriding a function on the console for instance). This wont stop someone from rewriting your code, but passing things through a packer, or even closure compiler can make your code pretty hard to read/modify... (take a look at jQuery min

All in all, ANY game running client side is hackable.



回答12:

travian(http://www.travian.us/) is a good example of a larger scale game that runs in DHTML and it has a ton of issues with client side abuse. Just installing grease monkey in firefox opens a rather large door to all kinds of exploitative behavior. That said, they seem to keep the game somewhat functional since most of the exploits seem to revolve around automation of common in-game tasks and not direct violations of the internal domain logic of the game. Keep in mind that this example is far from being run with only JS and relies largely on server side controls.



回答13:

Disclaimer: This is a terrible method and probably too much effort than it is worth.

Suppose that you had a method of processing the javascript code before you sent it.

First of all, every method has a ident variable which is attached to the result of every function (i.e. every function would return {ident:"special code",result:"actual useful function result"}). You also have a testIdent() function which would accept the function name to call as well as "test data" to give it (if any is needed). The purpose of testIdent() would be to send the ident returned from said function to the server for verification (the idea being that the server can request a test whenever you deem it appropriate). The ident for every function should be randomized and recorded specially for the specified user before sent.

Second, before the code is sent to the client, the function order is randomized and function names are obfuscated in some random fassion. This way there is no way for a hacker to look for some variable ident in function x() as it will be named randomly. Also, it would be another plus if every variable name is obfuscated randomly as well, just to add yet another step to the complication and headaches of... well... everyone (I told you this is a terrible method).

Now, assuming proper steps are taken to make sure the code will always function correctly, hackers are very cleaver people, and there are still ways for hackers to track this code if they are determined enough. At least one way will be to search for key code structures, such as a switch statement with a certain number of elements, or a for loop with x number of statements, etc. While each of these can be countered, say by adding dummy case statements in the switches or a couple of if(true) bits randomly throughout the code, countering hackers will always be a constant (and possibly a loosing) battle.

Hopefully this can give you some ideas. I don't know how someone would implement this exactly, but it is at least an idea.

Good luck!