This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.
Oh Look, It's the Terminator...
The first type of cheat is reflex augmentation, which is when a computer program replaces human reaction to produce superior results. This type of cheating is really only applicable to games where reflexes and reaction times matter, and thus is most applicable to action games.
During my FPS obsession, I believe that I encountered a form of reflex augmentation known as an aiming proxy. An FPS aiming proxy works like this: The proxy program is run on a networked computer and the player configures it with the address of the server they are going to play on. They then run the FPS game on another machine and connect to the proxy machine, which in turn connects the game to the server, acting just like an Internet packet router.
The only hitch is that the proxy monitors and attempts to decode all of the packets it is routing. The program keeps track of the movements and locations of all the players the server is reporting to the game, building a simple model. When the proxy sees a Fire Weapon command packet issued by the cheating player, it checks the locations and directions of all the players it is currently tracking and picks a target from them. It then inserts a Move/Rotate command packet into the stream going to the server in front of (or into) the Fire Weapon command packet that points the player straight at the selected target. And there you have it: perfect aim without all the mouse twisting.
When aiming proxies for Quake first appeared a couple of years ago, their targeting wasn't too sophisticated and didn't take into account things such as the player's field-of-view (FOV) or lag. Giveaways, such as players shooting weapons out of their backs, tipped people off that something foul was afoot. One of the first countermeasures to be developed was a server add-on that statistically identified players whose aim was too good to be true, then kicked out and banned the perpetrators. This naturally proved controversial, since some people really are "railgun gods," and the issue of possibly falsely identifying a person as a cheater was raised (and has yet to go away). And of course, the aiming proxies evolved with time. Later versions were improved to consider only the player's current FOV and compensate for lag, and added just enough randomness in their aim to stay below a server's "too good to be legit" identification threshold.
This big vulnerability is summed up in rule number six. Since the proxy is not running on the same computer as the game client, definitive detection can be next to impossible. Making the development of the proxy extremely difficult then becomes a priority.
Rule #6: Any communication over an open line is vulnerable to interception, analysis, and modification.
One way to inhibit this form of cheating is to encrypt the command packets so that the proxies can't decode them. But there are limits to the extent that encryption can be used on communications. Most FPS games can send and receive a couple of kilobytes of data or more per player per second, and have to allow for lost and out-of-order packets. The encryption therefore has to be fast enough not to impact frame rate, and a given packet's encryption can not be dependent on any other packet unless guaranteed delivery is used. And once the encryption is cracked, the game is vulnerable until the encryption is revised, which usually involves issuing a patch. Then the hacking starts over.
Another way to make life more difficult for the proxy creator is to make the command syntax dynamic. Using something as simple as a seed number that's given to the game when it connects and a custom random number function, the actual opcodes used in the communication packets can be changed from game to game, or even more often. The seed itself doesn't have to be transmitted; it could be derived from some aspect of the current game itself. The idea here is that since a proxy sees all the communications, but only the communications, the random seed is derived from something not explicitly communicated. Foolproof? No. But it's far more difficult to hack, forcing the hackers to start from scratch.
If guaranteed delivery is used, another communications protection technique is to serialize each packet. Taking it a bit further, you could make a portion of the next serial number dependent on a checksum of the last packet. While there are speed issues with the delivery, it's an excellent way to make it difficult to insert or modify packets.
Though reflex augmentation seems to be exclusive to FPS games, the vulnerability extends to any game where quick reflexes can make a difference and game communications can be sniffed.
The Client Is Always Right
The next major class of cheats is exploiting authoritative clients. This is when one player's modified copy of an online game tells all the other players that a definitive game event has occurred. Examples of the communications would be "player 1 hit player 2 with the death-look spell for 200 points of damage," "player 2 has 10,000 hit points," and so on. The other players' games accept these as fact without challenging them and update their copy of the game simulation accordingly.
In this case, a hacked client can be created in many ways: The executables can be patched to behave differently, the game data files can be modified to change the game properties on the hacked client, or the network communication packets can be compromised. In any case, the result is the same - the game sends modified commands to the other players who blindly accept them. Games are especially vulnerable to this type of exploit when they are based on a single-player game engine that has been extended to support online multiplay in the most direct (read: quickest to develop) manner.
Fortunately there are several steps that a game developer can take to eliminate most problems with authoritative clients. A first step is to install a mechanism in the game that verifies that each player is using the same program and data files. This means going out and computing a CRC or similar identifier for all the data in question, not just relying on a value stored in the file or the file size. A nice side benefit is that this method also detects out-of-date files during the development process.
For peer-to-peer games, cheating can be made difficult by changing from a game engine that issues commands to one that issues command requests. It's a subtle distinction but one that requires engineering changes throughout the game. It also requires that each player's machine run a full copy of the game simulation, operating in lockstep with the other players.
Command processing in a single-player game typically works in the manner shown in Figure 1. The player issues some sort of command via the game's user interface. The game then performs a validation check on the command to see if the player has the resource, the move is legal, and so on. The game then performs the command and updates its internal game simulation. Figure 2 shows game engine command processing extended to support multiple players in the most direct way possible. The process stays the same except for the addition of a communications packet that's sent out to inform the other players of what has taken place. The receiving players integrate the data directly into their world simulation.
Figure 1. Single-player-game command processing steps.
Figure 2. Single-player-game command processing extended to support multiplayer operation.
With the shift to command requests, the order of events changes a bit, which is shown in Figure 3. After determining that the command is a legal one, a command request describing the command is sent out to other players and is also placed into the player's own internal command queue, which contains command requests from other players as well as his own requests. Then the game engine pulls command requests from the queue and performs another validation check, rejecting the request if it fails. The fundamental difference is that every player has a chance to reject every action in the game based solely on the information on that player's machine. No other machine provides the information to make the determination on what is right and wrong. A hacked game cannot reach out and alter what's on an honest player's machine with this approach. Note that such an architecture works equally well for a single-player game.
Figure 3. Command processing steps when using command requests.
Preventing a dishonest command from being accepted on an honest player's machine is only half the task. The game also has to be able to determine whether someone is playing the same game and if not, it must do something about it. For instance, when a received command request is rejected for reasons that should have prevented it from being issued in the first place (remember, the issuer is supposed to have checked it for validity before passing it to the other players), all other players should assume that a cheater is in their midst, and take some sort of action.
Often though, due to design issues (such as posting command requests to a future turn), it is not possible to thoroughly ensure that all command requests passed to other players won't be rejected if a player is being honest. A good way to deal with this is to add synchronization checking to the game. At various points during the game, each player's machine creates a status summary of the entire game simulation on that computer. The status, in the form of a series of flags, CRCs, and checksums, is then sent to all the other players for comparison. All the status summaries should be the same, provided the game program and data files are the same for each machine. If it turns out that one player has a different status from all the rest, the game can take action (like drop the player from the game). The idea is that a hacked game should cause that player's game simulation to produce different results.
Alternatively, you can make life even more difficult for the hacker by easing up on the received command request evaluations. By allowing command requests to bypass the verification check only on the machine that issued it, you're deliberately allowing the game to go out of synch if the initial verification check or data has been hacked. Combine this with a synchronization check that occurs somewhat infrequently and you've presented the hacker with something of a mystery - on his machine the cheat worked, but then a while later the other players booted him out of the game.
This status synchronization has a huge benefit for the development process as well. Getting a complicated game engine to produce the same game simulations results while having different player views, inputs, and settings is a very difficult task. It's difficult to keep the simulation-independent code from accidentally impacting the simulation. For example, a compare against the current player number variable in the simulation code, or randomly playing a background sound based on an object in the player's view using the same random function used by the simulation, could cause future executions to produce different results on different machines. Judicious use of status synchronization allows a developer to quickly narrow down the portion of the game that isn't executing the same for all players.
Client-server games unfortunately can't benefit as much from these techniques, as they lack full game information and by design must rely on the authority of the server. We will look at this more a bit later.