Respecting the Challenge
Having the experience of hacking games, gives not only a mindset but a respect for hackers that break into games. If we ignore the ethical impact it has on the industry, it seems that our species always keeps itself in check with a masochistic self destruction, greed or just social validation.
Whatever the case may be, when I approach securing my game, I make sure it is a multi-spell solution. A lot of hacking is about reversing the assembly code and tracing jump statements. “If-else” statements in code, directly translate to “jumps” (jmp command) in assembly.
Let’s look at an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// Type your code here, or load an example. int CheckProgramState() { int countHacks = 0; // Test for count hacks here.... countHacks += 12; // let's say we found hacks... if( !countHacks ) // if '0' then hacks found { return 1; } return 0; } |
so if “if-else” statements cause branching, hackers will start from the point where the program deteriorates or crashes and trace back to what caused that crash. In this minimalist example, at line 7Â Â we observe the variable “countHacks” being populated by the value 12.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
CheckProgramState(): push rbp mov rbp, rsp mov DWORD PTR [rbp-4], 0 add DWORD PTR [rbp-4], 12 cmp DWORD PTR [rbp-4], 0 jne .L2 mov eax, 1 jmp .L3 .L2: mov eax, 0 .L3: pop rbp ret |
In the assembly representation it’s in line 5. Now we know that, the key value which decides whether a program is hacked or not, “countHacks”, is stored in location (rbp-4) in the CheckProgramState()Â stack. With this information a hacker can overwrite that memory location during run time for a quick “patch” to circumvent our security checks.
Line 7 in the assembly code, with jne (Jump Not Equal or Jump Not Zero) uses the results in Line 6‘s cmp (compare). This is where our hacker will trace the decision point which we use to cause cascading degradation and eventual closure of the product.
Visualizing the Battle
Since we’re fighting a battle, it is most appropriate to map it:
The assembly code here is just a filler, the point is the code path we follow down after detecting that the product is “cracked”. The more complex these jumps, the harder it is for the hackers to undo our checks. Here’s a little animation, of a hacker’s reverse walk-through of our protection…
Of course this is the most basic form of protection, there are others like honeypot, salting, ciphers and self-policing daemons/brokers etc.. We want to overlay and make each protection inter-dependent. To hide when when we”detect” and where/when we start deteriorating the product. Ideally deterioration should be intertwined with the product’s core logic. So hackers don’t just have a single “patch” (as the “countHacks” variable) or even a few, but a multitude!
I know there are those that are against DRM and such, but just as hackers “enjoy” breaking into products, I enjoy making them dance before they get there….
You’re welcome 😉