Giant Gekko's Website -- Jan 1998


This is not a web page about cracking software.  It is a web page that showcases techniques and tips which make a program difficult to crack.  Its a web page for programmers who don't want their software easily cracked by the various international cracking groups roaming the internet. 

Some quick info about this webpage: 

  • My email address is [email protected] and no other.  This is an email account setup specifically for this webpage, not that I expect much positive feedback once the cracker wanna-be's get wind of this page.  BTW, no relation to any other Gekko, dead, alive, or cryogenically frozen.  Handle was randomly picked on 1/15/1998.
  • No source code.  I present written explanations of the techniques most effective in protecting software from crackers.  I choose not to make this webpage compiler specific.  Source code is not very portable between compilers or languages, but the actual techniques work everywhere.
  • No countermeasures.  I discuss only those techniques which will help make a program difficult to crack; I do not discuss debugging or reverse engineering techniques to counter the routines I present on this website.  Besides, that's a topic for another website. :)
  • Yes I am a cracker.  I'm doing this so cracking will be challenging in the future.  Cracking today's so called "protected" software is a trivial task for various reasons.  No challenge means no fun.
I should probably stick in a legal disclaimer as well.  Nah.  And now, the info you've been waitin for... 



 

Randomization

Anyone who has had the extreme displeasure of debugging a program with an intermittent bug knows the true meaning of frustration.  The amount of time required to track down each and every possible source of intermittent error is enormous with the source code to the program.  The same task without the source code is not something to be taken lightly. 

Coding copy protection routines to check for protection once in a while instead of on every single execution would make things a bit difficult for a cracker.  Randomly engaging a second check for copy protection during a file save operation or a data load operation will make things miserable for a cracker.  To be really effective, toss in twenty or so protection checks, each in a different part of the program, each activated at a random interval.  A cracker may get one, or two, or even a dozen, but the time it takes to get every single one is usually not worth their while.  And there will always be a nagging doubt that maybe one or two protection checks are still in the program... 
 

Redundant Verification

Speaking of random protection checks, do not call the same subroutine to check for copy protection.  Each check should be coded separately, the source code should be written a bit differently each time, and use different (but compatible) compiler options for each of the check routines. 

If you rely on one routine to verify the protection, I will find that routine and force it to verify each and every time.  If each of your check routines are coded the exact same way, I can search for binary code matches (taking into account memory fix ups) within your executable to locate all identical routines (hence the slightly different source code and different compiler options requirement). 

And do not use a global flag to indicate the program passed a copy protection check.  Crackers like myself will find that global memory location, set the flag, and the copy protection routines are useless.  Instead, every time it passes a protection check, increment the expiration date or execution count stored with the user's data file.   If its a valid copy, the program never expires or never zeros out the execution count. 

The real trick to being redundant is to embed the checks in the most unobtrusive locations possible.  Inside of a DLL, inside the SETUP program and activated by a special command line parameter, inside of a companion program and verified via DDE, in a DOS program with the parameter passed via the DOS environment and run from a hidden dos box, and so on. 

Between the random activation of the protection checks and the numerous redundant checks scattered through a protected program, a cracker would need several bottles of aspirin and many sleepless nights to fully unprotected the program.  While nothing is impossible to crack, the goal it to make your program take as much time and effort to crack as possible.  Crackers are not known for the patience or persistence; they'll move on to easier targets so they can have something to boast and brag about at the next IRC session. 
 

Delayed Rejection

Imagine all the people who downloaded pirated copies of Application Z.  Suppose their allegedly cracked copy of Application Z suddenly stopped working three days after they staring using it.  Bad crack they assume.  They download another copy.  Three days later, it stops working again.  Different crack, same problem.  So did the cracker's actually crack it or did they miss a copy protection check hidden somewhere in the program?  If one of the many embedded random protection checks told the program to stop running in "X" days or "N" number of executions instead of stopping the program right away, cracking such a protected software would be a real challenge. 

Crackers typically let the debugger step into a routine and see if it brings the program to a halt.  If a check fails, the program generates a message and terminates abnormally.  Obviously it won't return the the stepped in function within the debugger.  Hence the cracker is able to identify the routine where the protected is checked, compared, and a failure code exits to the OS.  Change the compare, instant crack! 

On the other hand, if the program runs fine a few dozen times (sometimes sooner, sometime longer [randomization]) before halting, locating the protection check is much more difficult.  Naturally the routine that is used to halt the program after "X" number of days needs to be redundant as well and activated at random.  As far as a cracker is concerned, this type of program would be a royal pain to crack.  That's a good thing. 

FYI, date based cracks suffer from a debugger's ability to halt the program when a date/timestamp is requested from the OS.  Get it from a file attribute field (DirGetFirst), read it from the BIOS, or read it from the CMOS.  Better yet, log the timestamp during startup using a secondary program and pass the info back to the main program via DDE or some other non-obvious means.  And use obvious means as well; if the timestamps is off by a few days, then your app knows someone is trying to crack it. 
 
 

False Leads

The programmer's equivalent of a snipe hunt is trivial to accomplish.  Create a block of data, say 4k or 8k in size, copy some program code (or a section of the EXE from the hard drive) into the data block, twiddle the bits a bit, randomly compare it and set some memory variables (global or on the stack, doesn't matter), and basically do something to the data block from each routine.  You're coding a bunch of gibberish into your program, and having the source code, you can tell the gibberish from the code.  Cracker's don't have the benefit of source code so the "gibberish" looks like some really sophisticated code CRC checking routines.  Not really, but that's what it looks when debugging without the source. 

Now really mess with the cracker's mind by searching for registry keys that you never wrote.  A typical cracker would assume that the existence of certain registry keys would deactivate the protection.  Write the code to compare the nonexistent registry values to chunks of the random data block.  Again, with the source code the misdirection is obvious, but without the benefit of the source, it looks like a registry based copy protection scheme.   

You get the idea.  Basically get a nonexistent or random chunk of data, manipulate it in some important looking way (stick in lots of XOR's and shifts), compare the result to other nonexistent data, and do nothing with the result. 

Make the false leads obvious, but don't shove it into the cracker's face.  If they're too obvious, crackers will know you've been to this page.  If its too obscure, they'll never find it and won't waste their time "cracking" the false leads.