I was recently reading an article about clever ways programmers have protected their games from pirates, such as the creators of Game Dev Tycoon. This made me curious: how do they detect that the copy of the game running is in fact a pirated version on a technical level? The closest answer I was able to find through some research was how SNES cartridges can detect if they're pirated, but that tactic obviously doesn't apply to PCs.
First thing first: there is no way for a computer to know whether a file is pirated or not. Piracy is a legal/moral term, and as so, it has no meaning on a file, which is only composed of ones and zeroes.
That said, piracy prevention and countermeasures usually focus on finding out whether or not a user has something (usually an object) which can only be obtained if a copy of the game was purchased, and make that difficult to duplicate. There are tons of ways to do this, each one with advantages as well as flaws. I'll mention a few:
Early games asked users to input a word from the game manual, which you should only get if you bought a game box. A photocopier or a scanner easily defeats this technique though.
More recently, media checks are more common. The idea is that you require the game CD to be in the drive for the game to run. To implement this, you can for example access critical data files from the CD without which the game cannot run, or simply check for the existence of a file in the CD. This worked pretty well when CDs were difficult to duplicate, but CD copiers, and more recently drive emulators can be used to easily defeat these technique.
However, CD copies are not perfect, so many other techniques focus on detecting whether the CD is the original pressed CD, or a copy. To implement this, a game can check for non-standard elements that are inserted on the game disc during press time, but cannot be easily and reliably replicated by a CD burner, on a CD-R. Some common ways to do this are:
Creating dummy "ghost" files in the CD during mastering, which are not accessible from the CD filesystem, but do exist, and can be read if you know where to find them. This data is absent on file-by-file disc copies. Copying the entire disc image will copy these files though.
Another way is to intentionally insert errors in the disc. CDs contain error correction codes. By inserting errors in the data, which can be transparently corrected by a disc reader, the disc will work normally, but the errors won't be copied to the CD-R. By looking for these intentional errors, a game can consider a CD to be an original pressed copy. RAW disc image copies defeat this though.
Inserting twin sectors, with the same address but different data will yield different results when seeking data forward and backward. Checking for the existence of this is possible, and duplicating a CD with these twin sectors is very difficult.
Measuring the actual position of the pits in the CD. Once again, duplicating a CD with the pits in the same positions is very difficult.
However, many CD emulators, like Daemon Tools, or Alcohol 120% can actually emulate these features. Because of this, many publishers choose to include a CD emulator detection step, and prevent the game from running if an emulator is detected. The implementation of an emulator detector is outside of the scope of this answer though.
Instead of, or in addition to checking for a physical CD, a game can request the user to input some data, like a product key. Some ways to use product keys are:
Checking for mathematical features in the key. However, this doesn't prevent key duplication, and if the checking algorithm is discovered or reverse-engineered, a pirate may be able to create new keys at will which will appear to be legitimate to the game. Software that creates keys at will are called "keygens".
Generating a hash based on the user's hardware, send this hash and the product key (usually a combination, called the "installation key") to a server owned by the game company, and based on the hash and serial, create an activation key. Using one-way numeric methods (like modular arithmetic, or some methods with elliptic curves), a game can see if the activation key matches the hash and serial code, and only run if they match. This technique is called "activation".
With activation, a server may refuse to provide activation keys for multiple hardware hashes with the same serial code. Because of this, even if the serial code, and activation key are copied, the activation key won't match and the game won't run on other computers.
All of these measures are meant to find whether or not the user owns a purchased copy of the game. However, implementing them requires program code that checks for this. It is possible for a pirate to modify the game code to disable or bypass the checks instead of attacking the copy protection mechanisms themselves. The act of modifying game binaries to remove anti-piracy checks is called "cracking".
Cracking can simply consist of disassembling the game executable, finding the place where the relevant checks are made, modifying it to disable the checks, or ignore the results, and reassembling it. Some ways to counter cracking are:
Checking the binary with some hash. However, there must be a program that checks the hash, which can in turn be cracked as well.
Encrypting the program, or simply the check routine, and decrypting it in runtime. This makes disassembly more difficult, as it involves one or more additional decryption steps. IF the decryption key is included in the program (as it must be, because without it, the game cannot be decrypted), then the pirate can reverse engineer the decryption, find the routine, and crack the copy protection.
Because of this, as a game publisher, you want to make the key as hard to find as possible, and optionally make the decryption algorithm hard to understand. Some ways to make the key hard to find are:
Obscure it by creating it in strange ways. This simply slows the cracking process.
Create per-machine master keys similar to the serial protection mentioned above.
However, regardless of the method you use to create your keys, the keys themselves will be in memory while decryption is in progress. Memory inspectors, debuggers and emulators can help a pirate find and copy the key while it is in memory. Memory peeking can be attacked in several ways:
Having a privileged service that detects memory accesses in the specified region, and redirect the addressing somewhere else. As this requires ring 0 access, and programs that do this are more commonly used for not-so-legitimate purposes, antivirus software usually block them. (this is why many games and other software ask to turn off virus protection when running). Writing software that correctly does this is extremely difficult, and can easily compromise the stability and security of the host OS. The XCP scandal is a good example of an implementation of this method gone wrong.
Modern hardware and operating systems provide some tools, like memory curtains, secure media paths and TP modules, to make it easier to make a program that decrypts data, while being resistant to memory inspection.
There are many many more techniques to attack piracy, ranging from the trivial to the esoteric. Unfortunately, it is possible for all of these techniques to fail to recognize a genuine copy, and it's usually the more aggressive techniques that have higher false positive ratios.
As a game publisher, you usually want to choose a set of techniques whose cost of implementation, expected cracking time, and false positive ratio are in line with your expectations.
It is a common misconception that piracy protection is meant to be completely unbreakable. Most game sales happen in the first few months after release, so a piracy protection scheme is usually considered effective if breaking it consumes enough time for the game publisher to collect a large amount of profits before it gets broken.
Regarding Game Dev Tycoon, they did not use any anti-piracy technologies. They simply created a "broken" build, and distributed it over BitTorrent, as is stated in the beginning of the article you mentioned.
It is pretty easy, you just have to run a MD5 or SHA256 on your own executable, then, when you detect the signature has changed from what you hardcoded into the binary after you built the final release, then its clear somebody hacked your executable. Then most companies, don't just show a popup anymore (it was the case before) that says "broken PE" or "virus detected" and then exit the game, because this will be counter-cracked very fast be hackers. Because the game is paused on the message loop of the dialog so it is immediate to see because of what branch the dialog was poped up, and just bypass the branch by changing the code at the condition check.
Today, companies use very subtle change in gameplay, like multiply the life of monsters to make the game unplayable, or incredibly cleverly integrated in this management game, where you run a game company and you loose eventually because too many players were pirating your game. Nice mise en abyme in this case. Sometimes it just gets you a red flag uploaded on the company servers, and when you want to call them for support you get a speech, or trapped into revealing your identity.
but this is all of topic, the technique is hashing. and these checks can be run in many places in the binary so that if hackers find one and clear it, its not enough.
EDIT: If you just copy the game as-is, it may work if the game has no anti-piracy measure at all. It was working with very old games, pre CD burners era. That is why, most of the time, the game has to be installed to run, not just the installation folder copied. This involves hidden files put a bit everywhere in the system, and registry keys. The game checks the presence of these things, which can only be created by the installer. And the installer, can only be run from the CD, which is not copiable because of erratic bits that do not respect the error-correction code system at the first bytes of the disc, which kills most CD player drivers. Some copy software, like nero of alcohol, proposes you to ignore the errors but what they burn is then a corrected copy, the installer detects that and there you go again.
Q: how to hash a file then insert the hash into the file which changes the hash ?
@Byte56: Damn we are getting intelligent comments here :) Yes it is a paradox and it cannot be solved. So the hash has to be made on the part of the binary that does not contain the hash. And the check code has to know that, to exclude that zone when hashing to self check. I have seen people using tags, like ~~#### [put hash here] ####~~ to enclose their hash and do the exclusion. But it has the flaw of being easy to spot for hackers, so the hash has to be scrambled, and scattered in multiple locations. Even encrypted why not, and the same camouflaging operation goes to store the private key.