Online game file check for tampering and up to date

Started by
51 comments, last by hplus0603 12 years, 2 months ago
So making an online game. I've created a launcher/updater program that does the auto updating of game files.

My next question is about making sure the client has the most recent updated and/or not tampered with files before they play. I have an idea on this but curious about what others think.

My idea is after the client logs in, hash codes of each major file is sent to the server in one message. The server will then check these against a table of hash/filenames of the most recent update. Does that seem good enough? I suppose I should send these encrypted as well. Any other ideas around this that I haven't thought of? I'm sure there are some. :)
Advertisement
Strictly speaking, it is not possible to prevent tampering by a determined cheater.
You have to design your game rules to be enforced by the server based on packets received by the client, and you have to assume that the client might be a clone written by Chinese gold farmers, or vindictive, snotty 14-year-olds.
Checking files as you load/use them is a good idea anyway, because it will detect people who are out of date, have broken hard disks, etc.
The typical way this is done is to send a manifest of all files (file name + hash) as one of the files, and provide the hash of the manifest itself from the server. If the manifest hash mis-matches, a new manifest is downloaded. Then, each file is checked against the manifest, and if there's a mis-match, the proper version is downloaded.
Exactly how and where this is all done varies. There are many ways to skin this particular cat.
enum Bool { True, False, FileNotFound };
As hplus0603 said, make your server the authority.

In addition to hashing the entire thing, I'd hash each file differently at different levels (i.e. hash each GB of a file and the whole file). It is fairly trivial to make a modified file hash into the correct value, but if you have multiple hashes per file it becomes much more difficult.

It is fairly trivial to make a modified file hash into the correct value, but if you have multiple hashes per file it becomes much more difficult.


But that doesn't matter, because the attacker will just intercept the network send request, and make it send the hash value you want to get, no matter what was actually calculated. The only reason to hash sub-sets of a file is if you want to patch only a part of a file, that that, in turn, requires some good way of identifying subsets of files that doesn't change each time you patch the file.
enum Bool { True, False, FileNotFound };

[quote name='turch' timestamp='1327945150' post='4907711']
It is fairly trivial to make a modified file hash into the correct value, but if you have multiple hashes per file it becomes much more difficult.


But that doesn't matter, because the attacker will just intercept the network send request, and make it send the hash value you want to get, no matter what was actually calculated. The only reason to hash sub-sets of a file is if you want to patch only a part of a file, that that, in turn, requires some good way of identifying subsets of files that doesn't change each time you patch the file.
[/quote]

True, but its a little bit of extra annoyance to an attacker for about 10 minutes of extra coding. IMO worth it.

True, but its a little bit of extra annoyance to an attacker for about 10 minutes of extra coding. IMO worth it.

That particular rabbit hole goes a long way down.

You are trading days of development, weeks of QA, not insignificant server load, and potentially thousands of customer support calls, all to delay a script-kiddie by 10 minutes.

And of course, the script kiddie isn't working on salary or a clock, and it only takes a single enterprising individual to provide a crack for every single one of your customers...

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Since any of the programs (including the file validator) could be reverse engineered and tampered with (like automaticly sending the right values even when every file no longer matches the checksum/whaterver).the first thing to force a real validation on is the validator itself.

There has been discussion on these forums before and I thought that a mechanism that reloads every login (every time executable run) a new validator (recompiled daily+ with different code scrambled to result in different binary hash/checksums/exe/ size) or a .dll component so the program does not have to restart would force the hacker to constantly rebuild their hack (and redistribute it to those not cappble of doing the work themselves -- and in that case have them be personalized PER USER so that one hack doesnt work for any other user). If automated mighteven be able to be done constantly while the game runs (dll unload and reload).

Once the validator is safe the rest of the programs/files can be checked (and they too can be replaced every day/periodicly in a 'unique' hash/checksum form.)

Partial file replacement (mainly the game exe runtime) would be done constantly (every login - ive seen multimeg files dl in seconds for exist mmorpgs... so not to horrible a delay) to have something different to check (that too would be a per user variant that would make each one (at that point in time ) unique and force older copies to be invalid)
That would block direct substitution by the hacker and force more complicated insertion of hacked logic into the main process)

Next would be a communication encryption scheme -- part of the main exe (matched on a per user randomized system that is complement component on the server side) The serever would know instantly if the encryptor failed. Use could be rotated with random 'checks' against any/all files to look for tampering (even in the middle of playing) . That would deny communication intercepts/insertions as the encoding would constantly change thru too many different methods to cheat on them in a timely fashion (realtime games the data is irerlevant in mere seconds often)

With small .dll modules constantly shifting each with different encoding scemes and cyphers the data load (renewal overhead) across the connection might be fairly minimal. The server could have a dictionary of thousands of encryption substitutions (matching parts for client/server sides) and more could be programaticly generated for freshness constantly. The hacker could never keep up. Modules would be algorythmic variants as well as cypher data so that the hacker could never predict what might be loaded 'on the fly' and too difficult for automatic code breaking/adapter building for his hack. Turn them over constantly and use more than one at once and anything outside of the games iown exe cant keep up with the changes.


It eventually comes down to 'making it much harder' and if the hacker cannot automate his hack reenginerring system and it takes too long to redo it by hand (and cant redistribute to script kiddees if he CAN somehow break it) then the hacker will spend all their time rehacking and have no time to cheat (and the greater number who are reliant on getting hack from others are totally screwed)

Add a server side system to report incidents when the system detects a hack attempt and identifies repeaters (more than just the odd mistake such a complex system might cause -- a pattern of trying to hack) for human review and banning the perp (with evidence)

ALL or part of a system like this would make the hackers work significantly harder and past a certain point unrewarding for most but the dedicated/fanatics.


Hmm this sounds like an interesting project to actually do for a demo -- who knows if its good enough sell it to the MMORPG companies for a cool million...

----------------------------

This all of course is in ADDITION TOO easy server side validation.

-----

!!!!! I now just remembered that much of this what looks like OVERKILL was actually origianlly to figure out how to offload servers logic with PEER (P2P) execution of some of the servers load ---- like heavyweight AI (one of my interests) which can take ALOT of CPU processing and making use of the numerous user's client machines could significantly increase the games AI resources.

Think sanitized/genericised/encrypted (all in-memory) process jobs that constantly shift amongs the peers (so a user never knows what it is his machine is working on minute to minute and even if he did it wouldnt be there for long). The above security stuff would make it safe to run on the peers without compromising the game data. Of course you would have to VET the available peers as some are just not reliable or are underpowered or try to hack. Some reward would be made to players willing to have some of their computer resources used to help the server.

-----
--------------------------------------------[size="1"]Ratings are Opinion, not Fact

[quote name='turch' timestamp='1327961887' post='4907789']
True, but its a little bit of extra annoyance to an attacker for about 10 minutes of extra coding. IMO worth it.

That particular rabbit hole goes a long way down.

You are trading days of development, weeks of QA, not insignificant server load, and potentially thousands of customer support calls, all to delay a script-kiddie by 10 minutes.

And of course, the script kiddie isn't working on salary or a clock, and it only takes a single enterprising individual to provide a crack for every single one of your customers...
[/quote]

But if you're hashing at all, you're already way down the rabbit hole. If you're only trying to make sure files are up to date, there is no point in hashing, it would be way simpler to send file size info + each file's version number.
@turch: Hashing helps for users who have hard disks that don't read back whatever you initially wrote. Such things exist -- I'd expect 1 out of every 10,000 users to be affected by this.

@wodinoneeye: All your fancy mechanisms don't mean nothing. Your server will receive packets from the greater internet, and has to make decisions based on those packets. I can form packets any way I want. Perhaps I patch your client. Perhaps I write my own client. Perhaps I point my Windows box at a Linux box for its gateway, and modify the packets in flight. Perhaps I run your game in a virtual machine inside my Windows box and use the virtual network redirect to patch the packet stream. There is no way you can detect this and separate "touched" packets from "untouched" packets, because I can just inspect your client and inspect your packet stream and figure out how to generate correct packets. And once one person has figured this out, every person can download it on the internet.
The *only* defense against cheating is to not trust the client, and enforce all game state and rules on the server.
This is assuming your game is popular enough that anyone cares to cheat, of course. If you have no players, you have no cheater problem :-)
enum Bool { True, False, FileNotFound };
So for file validation this looks like the way to go. Step 1 is to make sure users are all running the correct version. I get the server side ruling all, but if someone goes into the character models file and replaces it with a model that has giant arrows pointing in all 6 directions and your game is a FPS how would you avoid that? It clearly gives him an advantage because he can see you coming from anywhere. Hash checks would stop that for the people who don't know how to redirect network traffic but know how to model and replace a file, but even server side validation can't detect that's happening if they are able to intercept the network traffic and send the right hash code. Is there really any way to handle that? My game won't have that specific problem but I know I've seen cheats like that in counter-strike before.

Like some are saying you could make it harder on a hacker by doing all sorts of crazy stuff, but it does add time to your development and will introduce bugs.

This topic is closed to new replies.

Advertisement