

Author: “No Bugs” Hare Follow: Job Title: Sarcastic Architect Hobbies: Thinking Aloud, Arguing with Managers, Annoying HRs,

Calling a Spade a Spade, Keeping Tongue in Cheek

[rabbit_ddmog vol=”8″ chap=”Chapter 29(b) from “beta” Volume VIII”]

If you know the enemy and know yourself you need not fear the results of a thousand battles. — Sun Tzu, The Art of War, circa 5th century B.C. —

Before we even start devising how to protect from a certain threat, we have to realize what (and who) exactly we’re facing; this is especially true when dealing with hackers. Otherwise, we’re risking to fall prey to oversimplified-solutions-which-don’t-really-work such as “hey, let’s ‘encrypt’ our code, that’s all we’ll ever need to do”.

These days, our primary adversary is somebody who has already hacked a dozen of competitor’s games, and he is keen to add our game to the ever-increasing roster of his wins. For the time being, we can ignore whether he is doing it for money, or just for fun; this, while being important in the Grand Scheme of Things™ (especially if we’re speaking about “when he decides to give up” and “how it is possible to get his hack to defend against it”), doesn’t change technical means for the attacks too much.

“we (as MOG developers) do NOT care about hacks by government agencies and antivirus companiesWhat is clear though is that we (as MOG developers) do NOT care about hacks by government agencies and antivirus companies;1 while, strictly speaking, the latter folks are indirectly in the picture (as in the course of their work against malware they can produce methods and tools which defeat anti-reverse-engineering protections), they rarely share their methods with sufficient-to-use-in-practice-details publicly (because of the inherent danger of their published methods being analyzed and counter-acted by malware writers) <phew />.

A Bit of History

Back in early 2000s, the whole thing was in its infancy; moreover – pretty simple techniques were sufficient to throw attackers off the scent. In [Dodd], they describe how they managed to do it by adding a checksum to their game, so they can be sure that the game is not modified. Yes –

back in early 2000s even such simple solutions were enough to delay hackers for 2 months.

Since then, attacker tools improved greatly. In particular, an advent of the concept of “interactive disassembling”, represented by IDA Pro hacking suite, has helped attackers a Damn Lot™. While the attackers did improve their attacks, changes on defending side are left much more modest, and are mostly still trying to deal only with a DRM-inspired question of “how to hide the real code from the prying eyes” – and with only very limited success too.

This, in turn, has lead to a situation that as of 2017,

All the popular protection methods lag well-behind capabilities of the dedicated attacker <sad-face />

Still, the hope is not lost – it is just we shall look beyond what-is-popular (looking for weaker spots within the attacks).

Hackers: Tools of the Trade

These days, a serious attacker comes to break our C/C++ game2 armed with the following set of tools:

IDA Pro. IDA Pro can be seen as a comprehensive suite designed exactly to hack executables. It provides both static analyzer, and debugger; while different attackers MAY prefer to use an alternative debugger, for static analysis IDA Pro is the tool of the hacker’s trade. Basic stuff such as flow graphs, custom loaders to deal with “encrypted” executables, support for structs/unions, etc. etc. is already there. It is interactive too – after it has done its job, you can say “hey, I identified this function (structure, union, you-name-it)” – and it will use information-you-found, for all the code. This, in turn, improves readability and allows to identify things further. “ One of the nastier-for-us features of IDA Pro is so-called F.L.I.R.T. If you’re about to do bot fighting yourself – make sure to read [Eagle]; feeling the ways hackers think is of extreme importance to write efficient defences.

As for hacking-oriented debuggers, the choice is wider than just IDA; among those which are seen to be used in the wild, besides IDA, there are OllyDbg, Cheat Engine, and of course, WinDbg. What we can rely on, is that whatever-debugger-is-in-use, on each step/breakpoint, it will provide the attacker at least with the following information: Stack frames of the functions which are currently on the stack. RTTI information (if present). This includes no less than those-class-names-right-from-the-source-code(!). VMT A virtual method table (VMT), virtual function table, virtual call table, dispatch table, vtable, or vftable is a mechanism used in a programming language to support dynamic dispatch (or run-time method binding). — Wikipedia — Let’s note that while this information is highly compiler-dependent, any decent debugger will report it for any popular-enough compiler.



In addition, there are lots of OS-level tricks which attacker may use to gather information about our program and/or modify its behavior in desired-for-them ways. In addition to static analysis and debugging, such tricks include:

DLL injections

Hooks

Blue Pill Blue Pill is the codename for a rootkit based on x86 virtualization. — Wikipedia —

BTW, we can (and often should) try to detect such intrusions and take counter-measures; however, as a Big Fat Rule of Thumb™, it will stop only relatively-novice attackers (which still has its merits, but is far from being a comprehensive protection).

As a side note: for Wirth’s sake, please don’t implement your protection as a single call to IsDebuggerPresent() and think that you already protected your executable from debugging; such “protections” are disabled way too simply, and anywhere-reasonable protection is much more sophisticated than that. Overall, the only valid reason I know to have IsDebuggerPresent() in your code – is to show a dialog box notifying the hacker that he violates your ToC (which might have positive implications from legal point of view – though make sure to discuss it with your legal department). Still, it doesn’t count as protection; the point where you wrote it, is not the end of writing protection, but rather the very beginning. For real protection stuff – keep reading, as we’ll see, there are LOTS of different things to do in this regard.

Most Popular Attack Vectors

Now, after we described the tools hackers are armed with, we can discuss the most popular attack vectors on the game Clients. There is a long list of such attacks, so to put them into some kind of perspective I’ll try to categorize them; on the other hand – please keep in mind that this categorization is neither strict nor wide-accepted, and should be taken with even a larger pinch of salt than usual.

Attacks on Silly Deficiencies

There are quite a few attack vectors which exist only because we (as developers) allow them to exist; still, if we’re silly enough to allow them – we’ll be hacked (and I won’t even blame hackers for doing it). Out of these, the most popular rather-silly-from-anti-bot-perspective things which game developers happen to be very prone of doing, are the following:

“ The worst thing about proxy bots is that they can be made fundamentally undetectable. Unfortunately, just encrypting our traffic (as we’d do it for a web browser or any other app) is not sufficient for games. The next silly thing in this regard, is using DLL for encryption (it can be standard APIs such as sspi.dll or 3 rd -party DLLs such as openssl.dll). Very briefly – there is no chance to hide DLL calls, which means that we’re giving the attacker our unencrypted protocol (and therefore, an ability to write a proxy bot) on the plate. Moreover, such attacks can be mounted even in real-time easily (see, for example, [Aiko]) After we eliminate DLLs from the picture – we’ll still be potentially vulnerable to F.L.I.R.T., but fighting it goes beyond simple removal of the silly stuff (more on it in [[TODO]] section below). MITM In cryptography and computer security, a man-in-the-middle attack (MITM) is an attack where the attacker secretly relays and possibly alters the communication between two parties who believe they are directly communicating with each other. — Wikipedia — 3 – attacker can mount a classical MITM attack, setting up a crypto-proxy which essentially pretends to be a Server to the Client (this connection will use the attacker’s own pair of public-private keys, which will work because of the lack of certificate checks on the Client-Side). At the same time, crypto-proxy will pretend to be a Client to the Server; this will allow crypto-proxy to forward all the traffic in both directions. As a result – attacker will be able to get his hands on our unencrypted protocol, allowing him to sniff/modify it to his heart’s content.

Using standard APIs to draw important text. The worst thing I’ve seen in this regard, was a bunch of poker apps using standard Windows controls to show the chat window. For poker Clients, chat window includes information such as cards dealt, player actions, and so on, so using standard controls for this sensitive information automatically enables both bot writing and data mining, obtaining the current state of the game as simple as by a call to GetWindowText().

Having one point where our protection can be disabled. This is especially silly when using obviously-visible standard API functions such as IsDebuggerPresent(); this combination enables very simple mountable-in-5-minutes attacks such as the one shown in [DutchTechChannel].

Specific Attacks

In addition to exploiting silly things, there is a bunch of the attacks which go after one very-specific aspect of the game; such attacks are rather game-specific, but there are still some common attacks, including the following ones:

Texture replacement, which is used to make walls transparent, make opponents better visible against the background, etc. etc. To deal with it – keeping track of texture checksums would do the trick (but we still need to make LOTS of efforts discussed below to make sure that these texture checksums are protected and checks are not disabled).

“ Even if we didn’t make any of the silly crypto-related mistakes discussed above, attackers can still try getting their hands on our unencrypted protocol, mounting a self-MITM attack. Self-MITM is a variation of a classical man-in-the-middle (MITM) attack which was briefly discussed above; as a rule of thumb, self-MITM goes along the following lines: Just as for a classical MITM, attacker generates his own pair of private-public keys for TLS encryption. 4 Attacker finds our certificate-stored-in-Client which is normally used to prevent classical MITM. Then, within the Client, he replaces our certificate (or public key) with his own one (the one generated above). Bingo! From this point on, he can make a crypto-proxy and mount MITM attack (even as our Client checks the certificate, it will check against an attacker’s certificate, enabling MITM). BTW, using OS-installed certificates to validate TLS connection is usually even worse than having a certificate embedded into our Client (because it is usually trivial to add a root certificate to the list of OS-recognized ones). To protect from self-MITM, we (after avoiding doing all the silly things discussed above) have to hide our certificate better, and to check its checksum too (again, hiding the checksum and checks well). As for “how to hide things” – this is going to be a huuuge subject, discussed in sections starting from [[TODO]] below.



Mother of All Hacks – “Brute Force” Reverse-Engineering

And last but certainly not least, we should mention “the mother of all hacks” – which is what hackers will usually do when none of the simpler ways (discussed above or otherwise), work. In a sense – it is a full-scale reverse engineering (of that-stuff-which-hacker-needs-at-the-moment). This class of attacks applies to any program, but on the other hand requires lots of effort; that’s the reason why I tend to name this family of techniques “brute-force reverse engineering”.

One common attack scenario which is next-to-impossible to prevent completely (but is still possible to delay quite a bit), goes along the following lines:

“ As we’re writing an MOG, we have to call system-level socket functions (such as WinSock functions), there is no way around it. Alternatively, the attack can start not from a system call, but from a standard library function identified by F.L.I.R.T. (with whatever-SSL-library-you’re-using, being one of the nastier targets).

Attacker gets call stack at the point where WinSock (or F.L.I.R.T.-ed) function is called.

Then, he traces the stack all the way up to the interesting part which causes the call. In the process, to identify “what is interesting”, he has to use whatever structure/VMT/RTTI data he has access to, to understand the data we’re dealing with in those-functions-currently-on-the-stack. This happens to be of paramount importance for the attackers; in fact, I don’t know of any successful attack which doesn’t use any of such data-related information to hack the program via brute-force. In particular, message formats are of special interest to the hackers. I lost count of how many games were hacked using “the first 2 bytes of the message represent message type” convention. BTW, having the first field in your class Message as int type is also very popular – and is very vulnerable too <sigh />. Then, attacker dissects that function-of-interest, and modifies it (or gets protocol information out of it) to get the desired result. Once again, data analysis (such as structures, VMT pointers, RTTI) happens to be of paramount importance in this process.



In a sense, brute-force is the “ultimate” form of attack which can be tried regardless of whatever-we-do. Moreover, given time – any code will give up to the persistent and proficient attacker. However, as we already mentioned above – for MOGs, there is a way to deny this time to the attacker (so that by the time when he’s past our defences, the time is up and he has to start anew); how to do it – will be discussed over the course of the rest of this chapter.

[[To Be Continued…

This concludes beta Chapter 29(b) from the upcoming book “Development and Deployment of Multiplayer Online Games (from social games to MMOFPS, with social games in between)”.

Stay tuned for Chapter 29(c), where we’ll start discussing practicalities of anti-reverse engineering protection]]

Acknowledgement

Cartoons by Sergey Gordeev from Gordeev Animation Graphics, Prague.