1
\$\begingroup\$

For cheating or maybe just making some trainers, it's possible for hackers to read and update variables directly in the game's memory.

Is this something that can simply be prevented, or is the answer still to "validate critical data on the server"?

As I searched, I found a tool like a cheat engine that helps hackers to find the changing value and where it changes to change some variable on memory. A very basic suggested approach is to add some offset to critical variables to keep them undiscoverable from hackers with their value. but I think there should be more robust techniques for that.

I know there are many game mechanics that cannot be authorized by servers: a well-known example is weapon recoil, which is hacked by many cheating tools.

I need to know better techniques for memory cheat prevention.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I am not an expert on this subject. But generally you can't prevent cheating on the device. You can make it more difficult, and perhaps a memory obfuscation technique could work. \$\endgroup\$
    – Almo
    Commented Dec 7, 2022 at 21:34

1 Answer 1

6
\$\begingroup\$

I've seen some folks suggest obfuscating your variables something like this:

public class ObfuscatedInt {

    int _mask;
    int _masked;

    public ObfuscatedInt() {
        _mask = GetRandomInteger();
        _masked = ~_mask;
    }

    public int Value {
         get { return _masked ^ _mask; }
         set { _masked = value ^ _mask; }
    }
}

Now any variable you store in one of these isn't written to memory in a recognizable way - its bits are randomly scrambled so a trivial search for a specific bit pattern, like the life counter changing from 3 to 2, won't find it.

The deal-breaker for any client-side security is this: the player is under no obligation to run the code you provided.

A hacker could take the game executable, decompile it, and find this ObfuscatedInt type. Then they replace _mask = GetRandomInteger(); with _mask = 0; (or a similar no-op) and recompile. Now they have a version of your game with all unmasked variables, and can go back to memory hacking just as before.

Or say you have a piece of code that watches particular variables and trips an alarm if they change values in an unsanctioned way. Again, a hacker can find the alarm code and just delete it, so this watcher code does nothing.

The same goes for code that tries to read the running executable, and trip an alarm if it detects that its own code has been tampered with. No-op the "then" case, and it's completely defanged.

So you might attempt to solve this from the server: have the server ask unpredictable questions about the client code, and if a client gives a wrong answer, block it as a cheater. But even here, a hacker can run a valid, unmodified client in a sandbox, forward the server's quizzes to it, intercept its answers, and report them as its own.

Every client-side anti-cheat on a desktop PC is just layers and flavours of these tactics, and you're just hoping the hacker will run out of motivation before you run out of layers of obfuscation. You cannot prevent memory hacks, only delay them.

Meanwhile, all those layers cause real performance impacts and an increased risk of bugs for all of your players, even if most of them are honest.

That's what folks mean when they say "validate critical data on the server" - this is not a temporary inconvenience that surely will be solved in another year or two. This is the fundamental nature of remote users running code on devices they control. You have no way in principle of verifying that the code they're running is the code you wrote, and not a forgery or hacked copy. So: the client is in the hands of the enemy. Never trust the client.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .