How to protect your applications.
The perfect application protection system
by Vegard A. Larsen
I have been thinking about this for a long time, and creating a perfect protection system for my (and your) applications would seem like an impossible task. After all, cracks for your application might be available on the Internet the day after you release it. But, thinking of how Microsoft (and similar) large companies, allow users to register by simply entering a serial code, I got the idea of how to create a near-perfect protection system. What I am about to outline here are the basics of what seems to be an unbreakable protection system. Note that this article will not include any source code, so this is merely a suggestion of how to do it, and any suggestions for improvement will be greatly appreciated.
Retrieving the serial number
The first thought that hit me, was having the system web-enabled, meaning that it will connect to some sort of authentication server. At first, we will need the user to retrieve his/her serial-number. This can be done in a number of ways, but for the sake of this thought experiment, I'll specify a useable method. The user registers via an external application that sends name and organization to your server, you verify that he/she has made the payment, and sends him/her an e-mail containing this serial. Then the user will need to type this information into the main application, where the "real" registration process takes place.
Checking the serial number
Let's take the following scenario: a user enters his/her name, organization, and the serial code he/she received when he/she registered. The system connects to a authentication server, which holds all the user information (name, organization and serial code) for all the users. Our user's information is submitted (with encryption applied) to the server, where a response is returned to the application. This response will also need some sort of encryption, preventing potential crackers from intercepting the signal sent to the server (by using e.g. fake IPs) and simply supply an "220 OK" response to the application. Also, the encryption applied would have to vary from computer to computer. If we were to use the same encryption on every computer, the potential cracker could simply get hold of the name, organization and serial code of another registered user, and one would have cracked the application. So, how do we generate a key that varies from computer to computer, yet is reproducible on the same, single computer? This poses a somewhat large problem. Intel had incorporated a CPU-ID code some time ago, but this can not be reliable. Suppose the user decides to change his CPU? (There are also patches that can remove this CPU-ID code.) Then this ID value would change. Technically, there is nothing inside a computer system that will stay the exact same depending on who is using the system. If a user decides to reinstall Windows, all data
saved to the Windows folder is removed, so storing data there (such as a random-generated encryption key) would not be the best idea.
The answer might be as simple as going by the "Registered user" value stored by Windows, inside the registry. Think about it, if the user decides to reinstall Windows, he/she will most likely still enter his/her name as the registered user! Again, this poses a problem: many computers who come shrink-wrapped, with Windows and a whole bunch of applications installed out of the box, will most often have this value set to something like " user". So when our user reinstalls his/her version of Windows, this value will most likely change. This is when we will have to enforce "extras" into the license agreement, stating that if the user decides to reinstall Windows, he/she will have to notify your company about this 48 hours in advance, or he/she would loose his/her license.
Then we can do the following: set the server to within this deadline of 48 hours to allow reregistering of that specific user, if he has not done so within the deadline, reset the "Registered user" to what it was before he/she notified you. To limit this (ensuring that no user keep reinstalling Windows 3 times a week), we will have to have a counter of how many times the user has registered this year, and a limit of 12 times a year will be somewhat normal.
We then get the following result: your application sends the data encrypted with a key generated from what it found in the "Registered user" key, preferably by adding a consistency check to the the data at the end. The server receives this data, checks the consistency, and decrypts it with the key generated from the "Registered user" value (which were already present on the server).
Then the server can send it's reply, using the same encryption key, back to the program, and tell the program if the serial code was valid or not. Depending on this, the program locks/unlocks itself.
Saving data to the current system
while avoiding detection
So far, so good, but there are still several other aspects to consider. How to save that the program have been registered, on the local computer. If you do this the "normal" way, by storing values in the Registry, you can be sure that crackers will have solved how to get around it within the day. So, a simple solution might be to store the data within the application exe-file, you're most likely thinking now... Wrong, this will be the second place potential crackers look. So, I had an idea. What if we were to append our data after the EOF of a DLL file in the Windows directory? This is possible, and this way, the file will not even increase in size as you register your application. Now, this DLL file has to be a file that is very seldom used, but is present on all versions of Windows (both NT/2000 and 9x/Me), regardless of what components they chose to install with Windows. Locating such a file might be difficult, but what stops you from checking for different files on different systems? You may have it appended to one file on NT/2000 systems, and to another file on 9x/Me systems. You can even split the data on different files in the Windows folder, appending only one byte to each file (allowing you to store several bytes of data (e.g. isRegistered, RegisterRetries). Note: You will have to check that no other program has appended data after the EOF, because several programs might be using this method for storing values.
To ensure that nobody can alter the main executable, or hex edit it to find a method to remove the serial number protection, we will preferably need several layers of security, the most important being encryption and self-modifying code. Now, using these at the same time might prove difficult, especially when you need to do both at run-time. Creating self-modifying code is easy, but making it work with encryption applications will be difficult, if not impossible. Also, if possible, compression will be helpful, if simply to make a cracker's work a pain in his/her behind. I am not going to comment much more on this, as it is a subject I have limited knowledge on.
Until now, I have simply mentioned the server, not explaining what it does in detail. The basics are clear, it will be a database, containing at least the following information (may of course be extended to contain other items such as ZIP code, state, payment method, etc.):
(not to be confused with User name)
(can also be generated here)
Number of registrations the last 12 months
The server will have to have at least two other attributes, the first one being encryption. The second being that it only accepts connections from certain predefined gateways. This means that the client application connects to one system, which it thinks is the server, while this in fact only is a gateway to the server. This way, crackers would have no way of knowing what system actually is the server. The more gateways it runs through, the better protection for the server, but the slower connection. Make sure the gateways are secure, meaning they have as few ports open as possible, and that they do not print the IP-address they redirect the messages to (so
cracker's won't hack the gateway and find the route to the server).
The server will of course also have to be as secure as possible, as with any other server.
Now, creating a component such as this, will introduce another problem: If crackers manage to break one application that uses this system, they will have cracked all of them. Therefore, such a component would have to be Open Source (or at least supplied with source), so that everyone can alter their encryption algorithm to their own needs. Also, they can alter which files the local information is appended to.
Does this sound like a perfect protection system to you? If you can see any glitches, security holes or potential problems I will be glad to know. Now, the goal of this was inspiring someone to write a component that does somewhat like this model outlines. So, when someone writes this component, be sure to let me know about it...
Contact me if you have any comments whatsoever related to this article, you can mail me here. I've already shown this article to some guys on the IRC channel #delphi, EFNet, and they seemed quite eager about it. Hope this helps someone.
Updates to the article
Received this mail some days ago from Timothy Plocinski, and I can see he has
got some incredibly good points. He is right, this is something very often
overlooked, we spend days just fine-tuning small parts of our main program GUI,
but leaves this as hard work for the user.
I enjoyed your article on protection schemes very much. Its an issue I
mull over (as you have) on a theoretical level all the time. I
see one enourmous flaw in your system however, and it
seems to me that this is a problem often overlooked. The
implementation requires too much of your user, and on top
of that, treats them as if they are already guilty.
Seeing this line:
This is when we will have to enforce "extras" into the license
agreement, stating that if the user decides to reinstall
Windows, he/she will have to notify your company about
this 48 hours in advance, or he/she would loose his/her
I have to assume, that most users would simply goto a another product at
this point. And having systems that lock and unlock themselves
according to some protocol makes that system
"unstable" for any mission critical type application
you might be designing. On a theoretical level I really
enjoyed the article, on a practical level I think it
limits the user too much. After all, the majority of software users are
not criminals, so treating the majority that way, only hurts you in the long
And, I recommend all of you to read the comments, they are all worth a thorough read.