[Vigilance on Talos V: Now Shipping!]

Pirate's Paradise- by Allan Mertner


Most protections built into shareware programs do not fulfill their purpose of preventing nonpaying customers from using the full feature set of the programs. Allan Mertner, author of the SecureIt Shareware Protection package, looks into the issues involved.

The three main concerns

Publishing a shareware program is a complicated matter, where several factors need to be taken into account. First and foremost, the freely distributable version of the software must provide enough functionality to convince potential customers of its usefulness. Secondly, there should be an incentive for users to register the software. And finally, the process of registering the software must be both simple and secure to prevent unauthorised access to the full set of features in the software.

The first point is what programmers spend the most time on: Writing a program that is hopefully useful to a lot of people, in order to make the software widely used and to sell as many copies as possible.

The second point, providing an incentive for buying it, is more difficult. A number of standard techniques employed in this area are listed below, with examples of OS/2 shareware programs using the particular technique in brackets:

The above mentioned methods can, of course, be combined, with the ever present danger of annoying users so much that they cannot be bothered to use the program and so, of course, do not register it either.

The third point, protecting the software from unauthorised tampering, is typically the area where the least effort is invested. Since most shareware programs are written by busy people in their spare time, it is hardly surprising that the available time is spent on extending the feature set and not on improving a part of the software that does not add value to it for the customer.

This has the downside that most shareware protections are easily circumvented by software pirates ("crackers"), which in turn may result in fewer copies of the software being sold. The ultimate consequence of widespread use of unauthorised shareware is that the products in question are discontinued because the authors do not sell enough copies to pay for the effort of updating and maintaining them. This is certainly not a desirable situation, but probably a quite common one nonetheless.

Defining the term "secure"

In this article, I will be talking about secure software protection. By this, I mean protection that can not be circumvented by any amount of clever debugging or changing of executable code (code "patching"). If either of these pirating techniques works on a particular protection system, it is not considered to be secure.

Building a lock vs. Buying one

Probably the main obstacle the typical developer is faced with is that he is not really qualified to write a good protection algorithm, because he has never tried to break one himself!

Consider the parallel where a nonprofessional attempts to design and build a secure lock for his front door. He probably has some idea about how a good lock works, knowledge which enables him to make a lock that keeps the door from opening by itself, but is probably not capable of keeping even a relatively unskilled burglar out. On the other hand, anyone capable of operating a screwdriver can buy a very safe lock and install it without necessarily knowing how it works internally -- it just does.

Similarly, to build a really secure software protection mechanism a rare combination of skills is required. The person should obviously be a skilled developer, capable of writing a solid piece of software. He should also have tried (successfully, mind you) to break a large number of different software protection schemes in order to know what constitutes a difficult system and what does not. And lastly, he must be convinced to use this knowledge to create a protection system that is sound and can not be broken.

Software protection

Out of the list of commonly used protection methods given in the first section of this article, only the first, crippling the unregistered version of the software in some way, can ever be totally secure. The other methods of protecting the software can always be circumvented, although obviously with varying degrees of effort required on the part of the software pirate, depending on the skill and effort of the programmer who developed the system.

In all the other cases listed, special code is executed when the program is not registered, and it is usually not a problem for a pirate to prevent these certain bits of code from being executed.

What makes crippled software potentially secure is that certain bits of code are only executed when the program is registered. The fact that a core part of the software is not executed in the unregistered version is the key to building a really secure protection system, since this means that information required to execute those portions of code can be stored elsewhere or be supplied when the program is registered.

In spite of this, you may still want to implement a system that relies on an expiry date, well aware that the system is not secure. The reason why it never can be secure is that there must be a date/time check somewhere in the code, which does not add information and so can be removed by a pirate.

The usual protection algorithm

In two thirds of all shareware programs, the protection algorithm used is a variation on the following piece of pseudocode:
  ...
  GetNameAndPassword;
  if VeryComplicatedRoutine(Name) <> Password then
    Registered = False;
    DisplayNagScreen;
  else
    Registered = True;
    DisplayRegisteredScreen;
  ...
  if Registered = True then
    EnableRegisteredFeatures;
    DisableNagScreens;
The code inside the "VeryComplicatedRoutine" is probably very complex indeed, and a software pirate is unlikely to be able to find out what it does. Quite likely, the developer himself is not entirely sure anymore.

But the pirate does not want to know what it does! The code above will, after all, not be included with source code, but just as an executable file and will translate to something like the following (the addresses used are, of course, just examples; if you are not proficient in assembly language programming, just read the comments and the explanation):

  call   00010404              ; Call GetNameAndPassword
  push   dword ptr [00219F3]   ; Push the Name parameter on stack
  call   0CF9921B              ; Call VeryComplicatedRoutine
  cmp    eax,[00219F7]         ; Compare the value returned with the
                               ; ...value entered as password
  je     00012004              ; Equal -> Jump to Program registered
                               ; Not Equal: Unregistered code
  mov    byte ptr [0023991],0  ; Set Registered to False
  call   00013D22              ; Display nag-screen
  jmp    0001201D              ; Continue after Registered code
@12004:
  mov    byte ptr [0023991],1  ; Set Registered to True
  call   00013F18              ; Display registered screen
@1201D:
  ...
To the uninitiated, the above is probably pure gibberish, but to the pirate it is "yet another 1-byte crack". By changing the code to read:
  cmp    eax,[00219F7]         ; Compare password with correct value
  JMP    00012004              ; Program registered!
i.e. by changing the conditional "je" instruction to an unconditional "JMP", the program will always consider itself to be registered, irrespective of the password entered. This involves changing just one byte in the executable.

A slightly more experienced pirate will recognise the call to the VeryComplicatedRoutine for what it is, and read the valid password for the name entered by simply checking the value of the eax register. Having done this, all he has to do is enter this password, and the program is registered without even changing the executable file.

Pirate's Hell: Good protection

In spite of the difficulties involved, it is possible to write a generic protection system that is secure. A system of this sort must adhere to the Software Protection Check List below, and at the same time make it easy for the programmer to use it:
  1. The data to be delivered to a paying customer should be a small piece of plain text that can be easily transmitted via telephone, fax or e-mail. Keyfiles, extra DLLs, etc. are clumsy and not desirable.

  2. A valid password must have no obvious correlation with the name for which it works.

  3. Many different products must be able to use the package, and the passwords for one product must not be valid for any other product.

  4. If a pirate knows one valid name/password combination, he must not be able to guess or deduce another one. However, in this situation he does have access to everything required to run the full version of the program and it is possible to crack it with this knowledge. The job of the protection system is to make it very, very difficult to crack the protection even with this knowledge (this is the primary reason for including the next three points: 5, 6 and 7).

  5. It should be difficult for the pirate to locate the routines central to the protection mechanism. Make the pirate spend as much time as possible simply locating the checking routines.

  6. Once the critical routines are located, it should be difficult to determine what they do and how they do it.

  7. A pirate should be dissuaded from debugging the code in the first place. This should preferably be done by including code that behaves differently when the program is being run from inside a debugger, and that may even cause the system to hang if pirating is attempted.

  8. It must not be possible to make a "generic" patch, which will allow all programs protected with the system to be pirated if one is pirated.

  9. At its core, the system should be inherently safe and virtually impossible to crack, even if the above mentioned defenses are penetrated.

The Check List may look very complicated and long-winded, but each item is actually important. In order for you to write your own secure shareware protection mechanism, you must read (and understand!) the Check List, spice it with some common sense, a bit of Assembler programming and some hands-on debugging experience, and you're halfway there.

Note, that by "debugging experience" I mean experience in debugging programs at machine level, not at source code level. Get a good debugger capable of debugging any executable and have a play with breaking your current protection routine before doing anything else -- you may discover that it falls into the "usual" category outlined above, in which case you will probably want to do something about it...

If you don't want to go to the trouble of building a protection system yourself, a good alternative already exists in the shareware package SecureIt. It implements all the functions required for you to build really secure protection into your software with very little effort. And SecureIt does fall into the category of "Good protection": I can not crack a program that properly uses SecureIt for protection -- and I wrote it!

More information?

If you are interested in more information on the subject of software protection, I might consider writing a follow-up to this article. Write me an e-mail (the address can be found below) if you would find this worthwhile.
Allan Mertner is 30 years old and works as development manager for software publisher fPrint (UK) Ltd., which develops and markets the acclaimed Virtual Pascal for OS/2 product. In his spare time, he sometimes writes software, and used to remove copy protections from software just for the fun of it.

[Index]  [® Previous] - [Feedback] - [Next ¯]

[Our Sponsor: MR/2 ICE Internet Email Client - Delivering the Email features of the future, today.]


This page is maintained by Falcon Networking. We welcome your suggestions.

Copyright © 1997 - Falcon Networking