Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm assuming we're talking about desktop games -- something the player downloads and runs on their local computer. Many are the memory editors that allow you to detect and freeze values, like your player's health.

How do you prevent cheating via memory-modifiation? What strategies are effective to combat this kind of cheating?

For reference, I know that players can: - Search for something by value or range - Search for something that changed value - Set memory values - Freeze memory values

I'm looking for some good ones. Two I use that are mediocre are:

  • Displaying values as a percentage instead of the number (eg. 46/50 = 92% health)
  • A low-level class that holds values in an array and moves them with each change. (For example, instead of an int, I have a class that's an array of ints, and whenever the value changes, I use a different, randomly-chosen array item to hold the value)
share|improve this question
25  
Why do you want to prevent that? If the player wants to cheat, why shouldn't he? He paid for the game after all. (we're talking about single player / offline games, aren't we?) –  CeeJay Mar 16 '11 at 12:41
6  
You like putting extra effort in for pretty much no reason? –  The Communist Duck Mar 16 '11 at 17:09
4  
-1 for spending extra effort to make games that are quantifiably less fun. –  AttackingHobo Mar 16 '11 at 17:57
15  
Regardless of whether or not you think a single player game should have cheat prevention, the question has merit as it applies to more than just his game. +1 –  James Mar 16 '11 at 20:01
2  
@ashes99 Ok then, I didn't see that point originally. And there's no point saying 'helpful comments only please' because everything I see is constructive criticism. –  The Communist Duck Mar 16 '11 at 21:41
show 8 more comments

10 Answers

up vote 15 down vote accepted

Another possibility (for integer values) is to have a second member-variable which holds a bitwise complement of an existing variable.

So imagine you got health, you would also have healthComplement. Your implementation could look like this:

// setter sets value and complement
void setHealth(int value){
    health = value;
    healthComplement = ~value;
}

// getter checks if value was changed outside of the setter
int getHealth(){
    if(value != ~healthComplement){
        // launch some cheat-counter-measure, like crashing the game?
        exit;
    }
    return health;
}

Somebody who wants to cheat would have to set health and healthComplement correctly, otherwise the game would crash.

I think it's kinda pointless to try to prevent stuff like this. People have successfully created hacks/cheats for much more complex stuff and it just needlessly obfuscates your code or makes your game perform worse.

share|improve this answer
2  
Pointless? Maybe. Fun? Aw yeah. –  ashes999 Mar 16 '11 at 16:41
    
My normal procedure of locating memory addresses which hold game stats would detect both health and healthComplement. –  Dave O. Mar 16 '11 at 19:58
    
@DaveO even if Complement was a random integer which was XOR'ed with the health value? You could probably find the changing memory addresses, but making sense of them without knowing what's going on would be difficult, I think. –  Vilx- Mar 17 '11 at 15:14
    
@Vilx: You could find out exactly what's going on by decompiling the program or reading the assembly - skills I think would be common for the kind of hacker we're talking about. –  Jonathan Hobbs Mar 18 '11 at 11:17
7  
@Jonathan Hobbs - Yes, but we're talking about memory editors here, which are used by people of lot less skill. Also, although theoretically nothing can stand against reading the disassembly, in practice it is possible to provide enough obfuscation that only the most skilled of skilled can hack through it. Reading disassembly isn't exactly easy. –  Vilx- Mar 18 '11 at 11:36
show 1 more comment

Here's one scheme I came up with when someone was asking for it on some board long ago. Using percentages or doubled variables doesn't really work, as you can search for "any" values and freeze them.

Instead, make a monster of a data type.

Basically, store your important values as a structure with:

  • 32 pointers to bits
  • For quick reading, have the struct include the current value as a plain int too

For manipulation, collect the current value from the separately-allocated bits (which can be true/false ints), change the value, and then store them back.

Here's the nasty bit: every time you manipulate the value, free and allocate the bits again. Allocation should happen in random order, so the data jumps around in memory and can't be easily frozen.

Additional safeguards would be to store checksums of the values (as well as the "plain" int) and compare these during the manipulation calls too. If mismatch is found, do something subtle, like remove a random key needed to unlock doors to progress in the game.

Edit: For further memory movement, make sure you allocate the new "bits" before freeing the old ones.

Edit: For multiplayer games, it's also possible to serialize the data structure, compress it, and send it over the network. Not the most efficient use of the network, but definitely harder to figure out through packet sniffing.

share|improve this answer
2  
+1 for removing random keys! Best way to beat cheaters, detect when it happens, and subtly make their life hard. –  Nate Mar 16 '11 at 16:05
    
@Nate this is precisely what I'm trying to do; make it harder to cheat. People find it fun to cheat. Well, I find it fun to throw wrenches in their cheating! +1 for checksumming. –  ashes999 Mar 16 '11 at 16:39
    
It's a game of walls and ladders, but I find it fun on both sides. :) Never played it though. :P –  Vilx- Mar 18 '11 at 11:40
add comment

How about you store the health complemented with a random value generated each time you store it. This would at least defeat the simple mechanism of searching for increasing/decreasing values in memory to find the health.

class Player
{
  int m_Health;
  int m_RandomHealth;
  Random m_Rnd = new Random();

  public int Health {
    get
    {
      return m_Health ^ m_RandomHealth;
    }

    set
    {
      m_RandomHealth = m_Rnd.Next();
      m_Health = value ^ m_RandomHealth;
    }
  }
}
share|improve this answer
1  
This is very easy to find with, for example, "artmoney" memory hack tool. –  Jari Komppa Mar 16 '11 at 20:14
    
I like your creativity. –  ashes999 Mar 16 '11 at 20:20
add comment

One possible option I think might work (I'm not too familiar with these cheating tools): don't hide it. Perform your operations and expect certain results. After the operation (possibly next frame), check to ensure that the results are as you expect them to be. If you subtract health and then verify it, only to find health never changed, you can be pretty sure (provided you don't have some obscure bug) that it was locked.

If you detect cheating, you are now free to change the rules of the game as you see fit for maximum griefing, if that is your intent. If your intent is to ignore the cheating and have the game continue to work, reallocate the health elsewhere in memory and change your pointers so that the new value gets used and the old is ignored. Repeat ad infinitum.

share|improve this answer
add comment

Although I made the first comment questioning the point of degrading the experience of a portion of your audience for no apparent gain, I still find it an interesting question from a technical point of view.

I just had this idea: What cheaters do is find values that change and freeze them. The search would then happen only between deaths or events that changed the player's health. Moreover, the cheater could be refining the search by filtering out what changed when he was "not dying".

What if the "health" counter is changing the whole time? Make it a pointer and reallocate it every frame or every N frames if the performance hit is too big. Or XOR it with a random value that changes every frame (XORing again against the same value for decrypting before encrypting with a new random value).

If you have other in-game data also changing the whole time (including x and y positions of the player character, or the time counter), that might make it harder to find out which of all the changing data is the health. And freezing the whole game state is a no-go for the cheater.

For further mislead, you can actually store the health in a plain write-only variable meant as a honey pot.

Edit:

Still, the cheater might try to find which of the variables that is changing the whole time is the one to freeze through trial and error. A possible solution would be to couple the variables together.

An example:

Instead of storing health (h) and position (x), you store them in two variables a and b, from which you can retrieve the values later:

a = x+h; b = x-h
x = (a+b)/2; h = (a-b)/2

This way, if the cheater freezes only one of them and then moves the character, the position is affected and, depending on which one was frozen, h goes negative (instant death). You can switch between the above formulas and:

a = x-h; b = x+h
x = (a+b)/2; h = (b-a)/2

In consecutive frames, and you guarantee that in at most 2 frames after either one of the variables have been frozen health will turn 0 the moment x changes. Remember that you are storing only a and b. Combine this with the continuous XOR as mentioned above. The result is a collection of variables that are changing every frame to seemingly random values, and freezing any single one or a subset of them only produces undesired side effects in the game, instant death being one of them.

share|improve this answer
add comment

Any attempts at mere obfuscation are bound to fail in theory, but in practice you just need to make it hard enough to break that the challenge becomes less fun than succeeding at the game. I don’t know what your game is, so I won’t risk suggesting data obfuscation methods, even less as I believe they’re pointless.

That said, and you will probably not be fond of it, I believe you are looking for memory curtaining, which is a Trusted Computing concept.

share|improve this answer
4  
Trusted Computing? <Stallman> You mean, Treacherous Computing! </Stallman> –  James Mar 18 '11 at 15:44
add comment

Write a ring 0 driver that hooks SSDT and logs / blocks when ReadProcessMemory / WriteProcessMemory is called on your application. It'd be better to just log so you can slowly change their game behavior over time rather than just crash.

share|improve this answer
add comment

Why would you prevent players from cheating themselves (which cheating in a single player game amounts to)? In a multiplayer environment, it's the server's task to detect unnatural changes and counter them (typically by either ignoring the input or blocking the culprit out from the server completely), but in a single player environment there's nothing happening except the cheater is doing himself a disservice.

IOW, unless you're creating a multiplayer game it's a waste of money, and if you are you're thinking of hardening the wrong place.

share|improve this answer
add comment

One very effective technique used by some roguelikes (DoomRL, Brogue) is to mask the actual variables. What this means is that instead of showing health as "2/10," show it as "20%."

Remember, most memory editors work well with specific value searching/filtering. If you don't know the specific value, you can still track it down (eg. search for changed/decreased values after the player health drops), albeit it takes much longer to do it that way.

I also suggest an anti-cheat backlash. For example, if you have a game where the player takes non-positive damage and their health didn't drop, you can easily and accurately check this and know that the player cheats. Do something interesting, like spawning some uber enemies around him :)

share|improve this answer
add comment

Research the known cheating tools - and frequently check whether any of the most common ones are detected running (check process names?)

If any are detected, let the player cheat (if offline, it's harmless), but make sure no scores/acheivements will be posted to any online leaderboard/acheivement system - just make it silently fail?

Won't stop more determined hackers, but will reduce the chance of more casual cheats messing up your leaderboards.

(Might annoy coders that have dev tools open and minimized for legit purposes and are taking a gaming break, though...)

share|improve this answer
4  
I was a big fan of Steam as a distribution platform, and played a lot of Team Fortress II a couple of years ago. One evening, I took a break from a long coding session and left open Visual Studio and a debugger while I played. I found myself banned from TF2 for "cheating." No appeal, no framework in place to have a ban lifted. One "offense" and it is permanent for the account. I'd still have no idea why -- and believe me, I was fuming -- except that I saw buried deep in a FAQ that having a "memory editor" open while playing the game constituted cheating and was ban-able. Wow. –  user16782 Jun 3 '12 at 3:03
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.