Giant Gekko's Website -- Jan 1998This 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:
RandomizationAnyone 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 VerificationSpeaking 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 RejectionImagine 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 LeadsThe 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.
|
||