Tuesday, February 14, 2012

How not to protect your software

I wrote my first (completed) software package 14 years ago. It was an animation program for creating 2.5D cut-out animation. Once it was ready for distribution, I needed a way to keep users from copying the software. Naively I opted for a simple key registration mechanism which was defeated not long after its release, and a crack was out in no time.

Don't use comparisons.

In university we had many courses ranging from low level network protocols, databases, artificial intelligence, many languages including Pascal, C++ and assembler, but nothing about how to secure your applications. So what I did was just using the user's personal information to create a hash, which was truncated and became a key. The user would fill in their personal information and key, and this key was checked against the key computed from the filled-in information. Of course this was very easy to defeat. One just had to locate the if test (JMP instruction) and replace it with a no operation (NOP instruction), which would make it skip the test. (A program that is tailored to do such specific change in the binary code is often called a crack). Another way to defeat it was just looking at the instructions, and copying what it did into a new program where a user can fill in his own credentials (such program would be called a keygen or key generator).

Don’t think they can’t read your code.

Many developers create extensive copy protection mechanisms without realizing that potential crackers can read their code. It is not because you ship a binary, that your program becomes unreadable. I told a colleague this a few years ago. He was working on an application which was still in private testing, and to avoid having guest users spread it, he built in some simple protection. The protection in this case was to compare the MAC addresses of the network cards inside the computer it was running on with a list of addresses compiled into the program. I told him several ways how people would circumvent it. As stated previously, they could simply remove the comparison. But they could also make it work without ever modifying the program. Since the list was inside the exe, they could read it, and they could just clone one of the MAC addresses from the list to their network card, or even use a virtual card with the correct MAC address. This list was easy to find, since the comparisons referred to the memory address the list resided at.

Encryption is not the magical answer.
A later version of our software was a lot harder to crack, as we put more thought into it. What we did was to encrypt program critical information, together with user information into a key file. The file was needed to unlock the program, since it contained part of the logic, and wouldn't be distributed because we would know who did it. This seemed to work well, and as far as I know was never circumvented. Most likely because more experienced crackers spent their time on bigger software suites or games. I say this because it is in fact easy to crack. The files were encrypted using a private key, which only we have, but the files are decrypted with a public key, inside the program. At first you would think this is safe, since a cracker can not create the file without getting hold of the private key, so a crack seems impossible. However he can extract and replace the public key inside the program. Using the original public key, an existing key file can be decrypted, changed and re-encrypted with the cracker's private key. The modified program than uses the cracker's public key to read the modified key file as if it was one we provided.

You can stall them, but you can't win.

Instead of using comparisons and exit the program when they fail, it is better to continue, and having the program test at a random intervals, and exit at a random time afterwards. The test might instead of setting a value to true, leave data uninitialized which is later caught in an exception where the program can exit. This makes it harder to find the actual test. Also having an application check for MAC addresses or hard drive serial numbers really of gives away that you are in a copy protection routine. These calls are easy to find and attract the cracker to the correct position in your code. To make the code less readable, there are various obfuscation tactics, but it should be taken as fact that whatever you do, they will circumvent it eventually. The puzzle becomes harder, but every puzzle has a solution.

Do not anger your users.

Since whatever method you use to protect your content will eventually be cracked, it is important to know where and when to stop. Some go too far and try to keep users connected to the internet, to have the software communicate with their servers at intervals, others calculate fingerprints made from hardware information in order to restrict users from installing the software on too many devices (and thus also restricting them from hardware upgrades). From the moment that cracked software becomes more desirable to legitimate users than the software they bought, you create a bigger problem than just piracy. A person pirating your software is seldom a potential client, since he doesn't value your software anyway. But turning a potential client into a pirate is not such a good business plan.

No comments:

Post a Comment