Game score unhackable?

Hi There,
I am developing a game that will display your running score at all times. What approach should be taken to ensure that a trainer cannot be developed for messing with the score?
Who is Participating?
another thing to keep in mind is to:
have the score in MORE THAN ONE PLACE!... and so, if at some point the scores are different, you know they are messing up with your application...

(in addition to) you could also keep the score in something like:

if the score it 58210 (supposing the highest score is 99999)



add encryption to all those variables and any cracker will get crazy trying to figure it out!!
Nothing cannot be hacked, you know. If a cleaver enough hacker will set himself on your app, it'll be hacked/cracked in no time.

However, using some encryption, you might be able to scare off a lot of potential hackers. Just download the excellent DCPCrypt from

Please do download and review the included Demo's as they'll explain how to use the components.

Don't be discouraged if you can't get it right right away. It are very powerful components, and once you get the hang of it, you'll use them all the time...

Kind regards,
maxbAuthor Commented:
What does DPCrypt allow me to do? I think i am looking more for like best practices as in "never keep the actual score in memory, decrypt it, change it, and encrypt it back up" or something...
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

Wim ten BrinkSelf-employed developerCommented:
You don't need encryption to prevent people from messing up the score. All you need to do is calculate a hash over the score. A SHA or MD5 hash would be more than enough. Then you can just store the score any way you like, but you also store the hash. If someone messes around with the scores, your game would notice this immediately since the hash would be invalid.
If someone wants to cheat, they would also need to know how to calculate that hash. And that's often a bit more difficult than cracking some encryption scheme. (Especially if you calculate a hash over only a part of the things you store in the scoreboard.

This piece of code will calculate a very simple hash over a string value. It should be enough for simple purposes:

function PJWHash( const Value: shortstring ): Integer;
  I, G: Integer;
  Len: Integer;
  Len := Length( Value );
  // Initialize the hash value.
  Result := 0;
  // Now add every character to the hash, in a very randomized way.
  for I := 1 to Len do begin
    Result := ( Result shl 4 ) + Ord( Value[ I ] );
    G := Result and $F0000000;
    if ( G <> 0 ) then Result := Result xor ( G shr 24 ) xor G;

This hash function works best if the strings you're using are at least 7 characters. You could use it like this:
PJWHash( 'Piece of salt' + Score.PlayerName + IntToStr(Score.Total) );

The "Piece of salt" in front of it is just some fixed text that is used to make the string a bit longer, and the result less predictable. And this hash function is pretty fast.

Can people still mess with the score? Sure, but now they also have to deal with the hash. And it will take them brute force to guess the right hash value for an altered score.

If you want to make things even a bit more difficult, you don't just calculate a hash over each score in your system, you also calculate a hash over all the hashes and make sure that doesn't change either. So if this is the scorelist:
Name           Score
kretzschmar    1003474
Madshi         599986
inthe              514794
geobul              381648
Ferruccio68        366296
Slick812            364557
rllibby            344898
mnasman            340396
Epsylon            324729
DragonSlayer        300794
rwilson            293576
simonet            222423
Workshop_Alex  215226
Lischke            205638
Lee_Nover          192042

Then you first calculate a hash for each line:
Name           Score       Hash
kretzschmar    1003474     1A2B3C4D
Madshi         599986      5A6B7C8D

And then a sum of all hashes:
Lischke            205638      9F8E7C6D
Lee_Nover          192042      1F2E3F4E

(Too bad EE doesn't use a fixed-size font.)
All you have to do is calculate the hashes and the total hash and any hacker will have a hard time trying to crack it.
maxbAuthor Commented:
That sounds good. Can you help me understand the actual implementation? Obviously the score needs to be altered and displayed during the course of the game. Can you walk me through the exact steps on doing that?
 I'm looking for something like:
1. hash score
2. check if current score hash equals old hash
3. increment score and rehash

Wim ten BrinkSelf-employed developerCommented:
Well, I assume you store the score in some way, e.g. a record. Something like:

  TScore = record
    Name: string;
    TotalScore: Integer;
    // Add this:
    ScoreHash: Integer;
  TScoreList = array[0..9] od TScore;
  ScoreList: TScoreList;

So, whenever you change thename or score of a record, recalculate the hash like this:

  ScoreList[0].Name := 'Workshop Alex';
  ScoreList[0].TotalScore := 96460;
  ScoreList[0].ScoreHash := PJWHash( 'Piece of salt' + ScoreList[0].Name + IntToStr(ScoreList[0].TotalScore) );

Or when you need to check it, use:
  if (ScoreList[0].ScoreHash = PJWHash( 'Piece of salt' + ScoreList[0].Name + IntToStr(ScoreList[0].TotalScore) )) then begin
    // Score is okay.
  end else begin
    // Some hacker messed around with it all.

And to calculate the total hash:

  Temp: string;
  TotalHash: Integer;
  Temp:= '';
  for I := Low(ScoreList) to High(ScoreList) do Temp := Temp + '/' + IntToStr(ScoreList[I].ScoreHash;
  TotalHash := PJWHash( Temp ); // No need for this one to be salted.

Or if you just want to check if the whole list is unaltered, then change the last line into:
  if (TotalHash = PJWHash( Temp ) ) then begin
    // Score is okay.
  end else begin
    // Some hacker messed around with it all.

All you have to do is store both the scorelist and the total hash in some way. But that's up to you. There are too many ways to do such a thing. But a good way would be to use a class for the TScore and a second class for the TScoreList. That way, you could automatically recalculate the hash values if needed.
In general, you would only have to check the hashes when you read the list from file, or calculate the hashes when you write it to a file.

The chance of someone cracking this system is pretty low, since they have to guess two proper hash values. They could do this if they know the hash algorithm that you've used and also know the grain of salt (the extra string constant) that you used to pollute the hash a bit. Otherwise, they need to use brute force to guess the two proper hash values. Since both have about 4 billion possible values, they have 4 billion * 4 billion different possibilities. That's quite a lot... :-)
maxbAuthor Commented:
Well, the score is basically just one number stored in an Integer variable.

You're saying that its fine to check the hash just when its read from a file, however, that doesnt prevent people from changing the value in memory as the app is running... I'm trying to prevent people from using trainers- something that changes the actual system memory values. Still confused
Wim ten BrinkSelf-employed developerCommented:
Well, if you want to prevent people from changing the value of the high score while your game is running, you would have to create get/set methods to assign the score to the scorefield. The get will have to check the score and the set would adjust both the score as the hash. This is best done if the score is part of a class.
However, it isn't that easy to hack values that are stored in-memory. Besides, if some hacker manages to do this, then no protection scheme would be save for this hacker.

But, a trainer must be loaded in the process space of your application and you could perhaps come up with a way to detect that a user is loading such a trainer in your application.
Hi this is a nice site to read all about creatingn unhackable stuff in delphi, its not specificaly about this form of encrytion but I am certain it will give you some ideas

Have a look at this thread also

Wim ten BrinkSelf-employed developerCommented:
I just don't get it... Why did you accept BlackTigerX his answer?
I'll let him answer that, but just a comment on this:

if (ScoreList[0].ScoreHash = PJWHash( 'Piece of salt' + ScoreList[0].Name + IntToStr(ScoreList[0].TotalScore) )) then ...

and that PJWHash XOR "encryption", is just completly discouraged, XOR encryption is one of the oldest and wickest methods for encrypting
in this example of "protection" you show, a hacker would just have to encrypt whatever he wanted the score to be and is done (since you are providing the simple little function)

you can read about cracking XOR encryption here:

there are many methods around for good encryption methods, "home made" encryption methods are COMPLETLY DISCOURAGED by anyone that knows about encryption-decryption techniques, standard methods are preferred (MD5, etc)
Wim ten BrinkSelf-employed developerCommented:
BlackTigerX, this is not encrypting we're talking about, but hashing. Two completely different techniques. And the hash method selected by me in this case just is an example. For more security, use a more complicated hash!
You are confusing encryption with hashing. A hash is just like a digital signature, making it harder to tamper with the signed data. All you do is read the value, calculate the hash and compare what you've calculated with what you've stored. If it's the same, it's not tampered with.

And for both encryption and hashing, if the hacker knows the algorithm, then it's not protected. All the user then needs is the key to encrypt and decrypt the data, if there is a key in the first place. The two of you should definitely learn the difference between hashing and encryption. A HASH CANNOT BE DECRYPTED! Thus, hashing is just as good as a solution as encryption.

If you use a hash instead of encryption, you will keep the hacker off-guard for quite a while. He sees where the score is stored but if he alters it, the program crashes. With encryption, once he knows how to decrypt it, he just encrypts his preferred score. Besides, no matter what you try, the encryption routine or hash routine is always provided to the hacker. It's there, in your code, stored as binary code. He can easily call those routines to use for his own needs.

What you suggested:
> if the score it 58210 (supposing the highest score is 99999)
> a=5
> b=8
> c=2
> d=1
> e=0
> x=58210
is even weaker than encryption or hashing since the average hacker will just use a disassembler to study the sourcecode. Looking for the place where the score is updated and from there he just looks how it is stored. If a hacker already has this much access to the application, no protection scheme is safe. Because no matter what you do, at one point the score has to be updated. All the hacker has to do is debug the whole thing. The weak spot is the one routine that is used to update the score anyway. No matter how you encrypt the data, no matter in how many variables you store the score, no matter how much hashing you do, at one point there's one single function that will assign a value to the score. All the hacker has to do is find this point and pass his own values instead.
If you encrypt it, all he has to do is discover where you encrypt the value.
If you split it, all he has to do is find where you split it.
If you hash it, all he has to do is find the call to the hash routine.

No, this is just the big problem with security. If the hacker has access to the binary code, then he can crack it. It might take a day or two but it will happen.

Now, the reason why I'm so suprised that he accepted your answer, BlackTigerX, is because all you suggest is to split up the score over multiple locations. And that's just a very weak protection. A hacker would easily discover this by keeping an eye on all memory writes. First you write to a, then to b, then to c, then to d... All he has to do is check what you've written. And if you encrypt it before splitting it, he just has to alter the score right before you start encrypting it... Piece of cake, actually.
The same is true for the hashing solution, though. But as I said, no solution is foolproof.
maxbAuthor Commented:
Hi Alex, I'm very sorry but I didnt even realize that it wasn't you who posted the splitting suggestion. I sincerely apologize, I realize I actually should have split the points because BTX actually did provide another idea that I have not thought of.

Since all encryption can be broken, how are all these online casinos still in business? I don't get why there isnt a trainer or something out by now.... any ideas?
Wim ten BrinkSelf-employed developerCommented:
I'm not worried about not getting the points, maxb. It's just that I thought it was weird that you accepted some other answer.

And why are online casinos still in business? Simple. Too many people are just losing money with their games, so that makes up some of the losses. The additional advertisements on their sites add more revenue. The price money is also limited to some maximum amount in many cases. Furthermore, they might not just keep track of the score but also the time it took the player to reach that score. If you can score about 500 points per minute then it's suspicious if someone scores 10.000 points within a minute. And of course, these are online games. They could send an in-between score to the server quite regular.
Also, since these are online games, it is a bit difficult for hackers to hack the system. Their actions are tracked by the server, thus by analysing the server logs you can check if there was some foul play going on.

It is still possible to hack online casino's, though. But it just requires quite a few good resources and keeping track of the network traffic. But guess what? An online casino can make it harder by changing the protocol slightly every week. Like with the hash I suggested, by changing the seed every two weeks in your application and then sending an updated game version to the users, they don't give hackers much time to crack the current system. Especially if it's a Flash/MacroMedia application that's reloaded every time the player visits the site.
I am afraid you don't know much about code protection Workshop Alex, I recommend you read from guys that know more about it, they will recommend you to keep different variables with same values but hashed different and so that is what I suggested

and hashing or encrypting using XOR method is not good anyway

however I do agree that there is no such thing as security, if a good hacker wants to tamper it, he will no matter what you do
actually the casinos is another whole story, they use laws of probabilities (randomness), and EVERY turn has the same (1 in a billionth or whatever) probability of winning the big price

that randomness can be adjusted

can it be hacked? sure... but you would actually have to hack into their servers first and whatever database they use, not only the screen (Flash or whatever) that you see... as you can see, the complexity of that is very high
maxbAuthor Commented:
So the casino software actually does no calculations? You're saying that you need to hack their servers... why? if the software is on your PC (why not just hack your PC's memory?). Any idea how its actually setup?
if it was only in your computer it would be way too easy...

if you were the one programming it, would you relay only in the client side program? I wouldn't, is just like any other web application, you can NEVER trust the data coming from the client side, you always validate it

Macromedia files (all versions) have been cracked really easy

I don't know how is actually setup
Wim ten BrinkSelf-employed developerCommented:
@BlackTigerX, let's just say that opinions differ on this. I still wonder how you could crack a one-way hash anyways. All you end up with is 4 bytes of data securing whatever amount of data there is. Even if a XOR method is used, it's still a one-way method. Trying to calculate the correct score back from the hash is just impossible, no matter what kind of method you use. Now, if the hacker happens to know the hash method and seed used to hash the score then he has mostly cracked it already. But again, this is true for whatever hashing method you use. No matter if you use XOR or e.g. the more complex SHA hash. OR a DES or Triple-DES. MD5 would do fine too.
Of course, for encrypting a XOR hash won't do, but again... I'm NOT encrypting here. And a XOR hash is weaker than a SHA hash since the final result set is a lot smaller.
Furthermore, there is a hashing algorithm that is very popular which is based on the XOR principle... Ever heard of BLOWFISH? Go check it.

One other reason why I chose this simple XOR algorithm is just because it's simple. Simple, fast and already very effective. And if you read my first post, I already said this was just one of the simplest hashing methods. The only weakness of my XOR method is that the result is a 32-bit value. Most other hashes start with a 64-bit result set and could even be as big as 512 or 1024 bytes. (And bigger.)
About those online casino's, they could be using a simple webservice system. The client application would be connecting to the server through the webserver, calling methods on the server that will do most of the calculations and the random drawing of cards or whatever. In Delphi, this is called SOAP, although webservices have grown a bit beyond this. So if they have a poker game, the client asks for 5 cards to be drawn. The server then sets up a new game, draws 5 cards and remembers that this player just started a game with the cards chosen randomly for the player. The client shows them to the player, the player can start bidding and/or discarding cards and ask new ones from the server. The client tells the server which cards have been discared and the server remembers this and draws more random cards for the player. Determining if the player has won and if so, how much, is also done on the server.
The biggest drawback is of course that a player needs to be connected to the Internet and you should be aware that a player could just quit the game while it's still playing. (E.g. because he has very bad cards, but also because of a power failure that ends in a connection loss.) Thus, the server will just have to remember where the player was the last time so the player can continue the game at a later time, or assume the player just forfeited the game. Player loses, thus loses his cash too. However, players should be warned about this before they start playing! (If during a game the connection is broken, the player might get 48 hours to reconnect or else he loses the game and bet.)
For multiplayer casino games this would be even more difficult, though. Just imagine someone is about to win and his connection is broken off for whatever reason. That would cost him a lot of money but the other players just continue to play. Thus, with multiplayer games it becomes even more complex.

With online casino's, the only client-side calculations are the ones that don't affect the game. With poker, for example, the client application could display what kind of card the player has (2 pairs, full house, royal flush, whatever.) And the client application might tell the player which odds he has on getting a better card if he discards some cards. Also keep in mind that with a game like Blackjack, you should "shuffle the cards" before the first game starts and them remember the whole deck until it's emptied. With blackjack, the cards are only shuffled after they've all been drawn. Thus, the client application could even keep track of all cards that have already been drawn and thus help the player even more in predicting which cards are in the deck.

Keep in mind that online casino's have to invest heavily in a secure server park. Not only do they have to serve hundreds of players at the same time, they also have to do lots of calculations and store the data of every game.
the only part that we disagree is that you say that having the value split across multiple places (different variables in different places) is weaker than having a simple "if"
"What you suggested:
> if the score it 58210 (supposing the highest score is 99999)
> a=5
> b=8
> c=2
> d=1
> e=0
> x=58210
is even weaker than encryption or hashing since the average hacker will just use a disassembler to study the sourcecode"

maybe you didn't read my initial post, I also said:
"add encryption to all those variables and any cracker will get crazy trying to figure it out!!" (meaning hashing each separate variable, even using different methods for each)

and when I used the "encryption" word, I was meaning "one way encryption", also known as hashing, I put MD5 as an example of this, so that was just a misunderstanding

anyway, the question is closed

best regards
Wim ten BrinkSelf-employed developerCommented:
BlackTigerX, you just keep mixing up the words encryption and hashing. If you don't even know the difference between these two terms, then you're only confusing matters. And if you suggested to hash the score then your answer is not so different from mine. And if you only hash those values then you can't ever get the original score back so you have to score the original score in one place and the hash in some other place.
well, The questioner understood what I meant and he knows is a good idea, if you are confused about the terms I used, I'm sorry for you
Wim ten BrinkSelf-employed developerCommented:
No, the questioner already said he made a mistake because he didn't realise that the answer you gave wasn't from me. As he says:

> Hi Alex, I'm very sorry but I didnt even realize that it wasn't you who posted the splitting
> suggestion. I sincerely apologize, I realize I actually should have split the points because
> BTX actually did provide another idea that I have not thought of.

Apologies accepted and for only 50 points I'm not going to start a lot of trouble. Basically, he would have split the points if he realised that your answer didn't come from me.

The only good suggestion you apparantly made was splitting the score in multiple fields...
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.