general tips against cracking

This question is for Gerhard to answer because I asked a question about getting a unique system id to protect my program against cracking and he posted a very long article about anti-cracking tips.

Unfortunately, it did not answer my question and does not relate to its title (that's why it would be misplaced where it is). I'd like to give him some points and that's why I post an extra question. Everybody feel free to post comments, but the points will be for Gerhard.

If you see this question in the FAQ: The answer will be quite long and contain very useful tips that help protect your program against cracking - even some tips to make "low-level cracking" (i.e. disassembler) harder... well worth five points :o)) (it's "only" 50 points because he just copied the article - would/should have been 200 for writing it *g*)
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

can you post the tips back on this thread? Thanks... Zif.
Ditto what zifnab said.

BTW Zif, you still hanging out with that big green dragon?
Where can we find the article?
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

         From: Gerhard
                                                                                                               Date: Tuesday, October 06 1998 - 08:14AM PDT

         I would like to stress that this FAQ is not my work. Unfortunately I can not remember which site I d/l the original HTML file from. I left the file and all text in it exactly as I d/l'ed
         it except for converting it to TXT format.


                 Anti cracking FAQ
         How to make cracking your programs a little harder


         Finding out that the program on which you worked for months or
         years has been cracked can really hurt and demotivate.
         For me as a Shareware programmer, the reason has never been that
         I've lost a few cents (I don't want to do propability
         calculations here, it might hurt even more..), no, it was simply
         that I've always tried to hold my programs as cheap as possible
         to make them affordable for everyone, even for students or
         freeware programmers.

         Somehow I can understand the fascination of cracking programs (if
         you are absolutely intolerant about software crackers and
         hackers, please excuse, but one of my educations is
         Psychotherapy, and I'm always searching for reasons...) -
         cracking a restricted software program must be like solving a
         (sometimes very tricky) riddle, and you might get addicted to the
         feeling of solving them (I've found that when I saw my
         grandmother doing crossword puzzles all over the time for some
         months). The problem is (but at the latest, now we come to the
         undoubtedly illegal part of the "game"): it doesn't really
         satisfy the cracker if he is the the only one who knows about his
         "genius"...thus, he has to spread the news. He has to publish his
         "crack" (just see most crack packages: in most cases they just
         consist of: 1. the cracking utility 2. a short description 3. a
         big file containing claims that the producers are nothing less
         than the greatest ones on Earth and that the cracked program is
         another one which could not stop them with "its lame protection
         But now the fun is completely over: by giving out this (let's try
         to be fair: "study of feasibility") to other people, by spreading
         it via Websites, newsgroups, mailing lists, anonymous FTP, CDROM
         "abonnements" and whatever, they clearly damage the business of
         everyone who puts time and energy in their software product. Even
         if we assume that typical crackers wouldn't have bought your
         product under normal circumstances: spreading the "crack" IS
         criminal and no one could claim that none of the receivers or
         downloaders would never have bought it. It's just like if someone
         hands out copies of the key to your car on the marketplace - and
         it doesn't really matter if he does that for money or not.

         In earlier days, I have never put real energy in protecting my
         programs against cracking, but after finding several cracks for
         them around, I thought to myself: why make it too easy? As a
         programmer, of course I know that no - really: NO! - program can
         ever be crack-safe, and I know that of every interesting program
         sooner or later cracks (or at least pirated or illegally copied
         versions) will be around, but at least I could try to avoid the
         worst mistakes.

         Most of the typical 'high language' programmers don't know
         Assembler anymore, so the 'protection ideas' they use are in most
         cases quite weak.
         I don't know much about Assembler myself, so I decided to open my
         eyes and started to collect anti-crack protection tips wherever I
         found them. Also I did my best to "learn from the other side" ..
         many of the tips you can find here I've found by studying the
         typical cracking techniques, the various "cracking guides" around
         the web and by reading protection tips given even by professional
         crackers themselves (some of them generously give us tips to
         increase their challenge). Well, I hope I've learned my lessons
         well enough, but also want to share my experiences with you on
         this page.
         Some rules given here were already stated in various essays on
         other sites, but are listed here for completeness. Many of these
         apply especially to windoze, but can be "ported" to other OS'es
         or anywhere else.


            * This FAQ is brand new. If you think that I've missed some
              points or useful tips a typical Delphi programmer could
              easily add to his/her programs to improve protection, please
              let me know. If you allow it, I'll add it here, otherwise
              I'll inform you about my experiences with it.
            * Don't ask me questions - might be that I'm simply too
              overburden to answer.
              1) As mentioned, I don't have much knowledge of the
              low-level stuff.
              2) I can't send you demo sources, since I don't have
              anything ready for a publication. If I have something, you
              will read it here.
              3) Finally, I will not provide anyone with any of the URLs
              where I've found (or found out) some of these tips. Please
              understand, but this is a site dedicated to programming, but
              not to provide "step-in's" to available cracks or even to
              "Cracker hunting". Find more generic tips about
              crack-protection at my Delphi Tips page.

         But finally, here is ..
         How to make cracking your app a little bit harder:
         (tips are not sorted by importance)

            * Never use meaningful procedure names such as

                  function RegistrationOK: Boolean;

              How intelligent and complex your code inside this function
              might ever be - an experienced cracker will just take about
              10-20 seconds to remove it. Believe it or not.
              Alternatively, place some required code for your program in
              such a function. If the cracker disables the function, your
              program would produce incorrect results, for example.

            * Never use meaningful file names such as License.Dat. Why,
              you say? Please start reading here.

            * Play with asymetric encryption. Just using unusual filenames
              is often not enough. Good encryption, of course, could keep
              the cracker busy for months (if he likes).

            * Add long delays. Don't warn the user right after a violation
              is made. Wait later, maybe until the next day or two
              (crackers hate that).

            * Add short delays. Pause a second or two after a password
              entry or to your other checking routines to make brute force
              cracking unfeasible. Simple to do, but rarely done.

            * Use checksums in DLL's and in the EXE. Have them check each
              other. Far away from "safe", but it just makes it harder to

            * Self-heal your software. You know, things like the error
              correction modems and hard drives use. The technology has
              been around for years, and no one uses it on their software?
              The best thing about this is that if the cracker used a
              decompiler, they may be looking at a listing that is no
              longer valid.

            * Patch your own software! Change your code to call different
              validation routines each time. Beat them at their own game.

            * Store serial numbers in unlikely places like as a property
              of a database field. Often heard and read: "..give it a DLL
              file name and store it in the System directory." Too often
              heard, don't use it. ;-)

            * Store serial numbers in several places.

            * Don't rely on the system date. Get the date of several
              files, like SYSTEM.DAT, SYSTEM,DA0 and BOOTLOG.TXT and
              compare them to the system date. Require that the time be
              greater than the last run (but keep in mind that many users
              might do Y2K-checks these days).

            * Don't use literal strings that tell the user: "Sorry, but...
              (whatever)." These are the first things to look for. Build
              strings dynamically or encrypt them.

            * Flood the cracker with bogus calls and hard-coded strings.
              Decoys are fun.

            * Don't use a validation function. Every time you validate the
              user, write your validation code inline with the current
              process. That just makes more cracking for the cracker and
              bewares of just NUL'ing out your routine.

            * Use "reserved" names. When using hard-coded keys or
              passwords, make them look like program code or function
              calls (i.e., "73AF" or "GetWindowText"). This actually works
              very well and confuses some decompilers.

            * No "disabled" features. If your program doesn't save data in
              "crapware" edition, don't include a "grayed" menu item. No
              saving means no saving. That's it.

            * Avoid nags. The only way to tell the user that he is
              unregistered should be in the "about" dialog. This latter
              should be created dynamically for security reasons. 2
              reasons: some programmers have the philosophy that
              nagscreens are making enemies among your customers, which
              would then really be very stupid. The possibly more
              important reason is that nagscreens invite
              reverse-engineering your code and often directly leads to
              your protection code.

            * Update often. Frequent updates mean: frequently changing
              code, so the typical (simple) crack which is just patching
              hard-coded byte positions, will possibly already be outdated
              when published. Also prevent uploading them to public
              servers, so that you have better control about where your
              app sits around and people don't find older versions the
              cracks can still use. Yes, this doesn't prevent pirates from
              including the version to the crack package, but IF they do
              so, you can at least contribute to filling up their

            * Finally, take some time to think about protecting your
              software. Is it really worth the protection? Wouldn't it be
              better to improve your software, rather than improving
              protections? The problem of protecting software vanishes if
              no one will use your software. Don't overestimate your
              work's "importance to the world".

         More tips you might take into consideration:

            * Use a serial which is several KB long of arithmetical
              transforms, to drive anyone trying to crack it insane. This
              makes a keygenerator almost impossible - Also, brute force
              attacks are blocked very efficiently.

            * Caution with the Runtime libary! Use it fully when writing
              the beta versions, in the final release rewrite some
              functions at least to make crackers life harder.

            * Mangle data. Protection that mangles data is usually a good
              Example: Imagine a charting program .. e.g., just disabling
              printing and later on enabling it basing on some
              registration# is the most often committed suicide. Let your
              thingo print. When creating data structures for printing,
              mangle them in some way. Unmangle them just before printing,
              using reg# or something other for that purpose. Even more,
              make this mangling subtle. Assume that you've got a pie
              chart to print. Don't alter anything, but add some not too
              big random numbers to values of data series - this is
              mangling then. The chart will look "not that bad", but will
              be otherwise unuseable (if the changes are random and on the
              order of 20%, for example). Finding such protection, if its
              connection with reg# is not self-evident can take much time.
              One has to delve inside your data structures and find that
              dreaded mangling and unmangling code.

            * Traps. A method I'm not sure about, but I have heard some
              apps are using it: do a CRC check on your EXE. If it is
              modified then don't show the typical error message, but wait
              a day and then notify the user using some cryptic error
              code. When they contact you with the error code, you know
              that it is due to the crack. Be aware: such traps could also
              be activated due to virus infection or incorrect downloads.
              Imagine the possible aftereffects if you are blaming your
              potential customer for software piracy.
            * Don't rely on "EXE-packers". For almost any tool which
              compresses EXE files (Shrinker, WWPack32, NeoLite - to list
              the most popular ones) there's an uncompressor around, so
              compressors capable for software-protection should at least
              support configurable encryption. Unpackers for the above
              (and other) tools are not very wide-spreaded, however, don't
              rely on them as your program's one and only "protection"!

         Advanced tips ..given by assembler freaks.

            * The rcr/rcl trick
              If a rcr/rcl is performed on a value, it becomes much more
              of a pain to crack - you can't reverse it with by negating
              it's effects without knowing what the value of the carry
              flag was before the original operation. If the carry flag is
              created as a result of some other pain in the neck
              operation, you are probably onto a winner.
            * Stick conditional jumps in. Everywhere.
              Conditional jumps are not fun to reverse engineer. No loops,
              but jumps which conditionally bypass/include portions of
              your wonderful key manipulation code. There is no easy
              inverse operation to be performed here.
            * Use portions of the code as magic number tables.
              (preferably critical sections). You have no idea how
              annoying this can be, if you're like most crackers and like
              to change things around using softice (a popular cracking
            * Play with the cracker's mind.
              This one is fun :-) Stick series of nops in, as though you
              were doing self-modifying code (oh my god! what the heck!
              nops? Aha! Self-modifying code! Idiot spends next three
              years trying to find the code that should be there.). Pepper
              the code with junk instructions. Cut the code up into little
              pieces and put them all over the executable, with
              (preferably conditional) jumps between them. - Anything
              which you would find a pain in the neck.
            * Detect SoftIce. Early.
              Now crash the computer. You can crash a pentium or a pentium
              with MMX even without a vxd by the opcode: F0 0F C7 C8
              (illegal form of cmpxchg8b instruction with lock prefix).
              Beyond that, we have to resort to the tried and true
              methods. Using a vxd, take the CPU out of protected mode.
              Windows doesn't like that. Wonder why? .. On the other hand,
            * Don't loose too much time on writing anything that will kill
              disassemblers or debuggers.
              Doing it is worthless, believe me, people who made them or
              others will soon find the way around, so shift your interest
              to more important stuff. Just do things which are easily and
              fast to afford, like the above tip.

         Special on Delphi VCL cracking
         Quoted from a helpful cracking tutorial - just read and learn
         from it!

         "Let's learn something about the innards of new Borland's
         programming tools. This knowledge will allow us to speed up
         cracking sessions, as will teach shareware programmers who use
         Delphi to be more careful and not to happily expose their
         'secrets' to curious eyes B) [..]

         VCL stands for "visual component library", a library used by
         recent Borland visual languages as Delphi and BC++ Builder.
         These environments use a proprietary resource format, that appear
         as 'RCDATA' when listed by Resource Workshop. These resources
         contain 'forms'. In Delphi jargon, forms are the windows of the
         program. All the info about their design is stored there. When a
         typical Delphi app is starting, the initialisation code creates
         the forms, loading the required information from the resources.
         Sometimes this loading is deferred - forms that aren't used very
         often are created and destroyed as needed.
         This system is the best and the worst of Delphi. It allows a very
         fast way of programming but, for full-length apps, it can slow
         down the loading.

         The really interesting part of this information is that the
         address of the routines - called in response to user interactions
         with the elements of the form - are bound at run time by name. So
         knowing these names we can find the appropriate addresses!

         If you have cracked any Delphi apps, you have surely experienced
         the long chain of calls inside the library, from the breakpoints
         on the API calls to the "do something" code. I hoped that these
         addresses could help in pinpointing the relevant code."

         [..describes his installation of a quite well-known Delphi-writen
         application..] I cracked it completely and without problems, as
         you are about to see :=) After first installation the weeks
         passed and I hadn't had the time to work on it... when I started
         it, I found a nasty 'Your evaluation period has expired' message

         The first step is to gather the information about the target exe
         with a resource or form spy tool. You may be tempted to
         investigate TVALIDATORDLG, the form where the user name and
         registration key is obviously input. But all you'll find is a
         mere dialog. The real work is accomplished from its caller:
         TSPLASHFORM. This is the nag window that appears at the beginning
         of the program, as well as when it's shutting down and from the
         Help->About menu.

         You can select TSplashForm and look at the text representation of
         it. A lot of information about the buttons and labels will
         appear. Let's concentrate on the following part, near the end:

           object RegButton: TButton

             Left = 200

             Top = 176

             Width = 97

             Height = 25

             Caption = 'Register'

             TabOrder = 1

             OnClick = RegButtonClick


         What's that? This is the button with the caption "Register". You
         can see its size, position... and something with a suggestive
         name: "OnClick". "OnClick" tells us the name of the routine
         invoked when the user presses this button. Once we have the name
         (yes, "nomen est omen" :) we can search for the address of this
         routine. This is because the routine is bound to the button at
         run time by name.

         Using a hex editor, I looked for "RegButtonClick" and I found it
         twice. The second occurrence is the resource itself, the first is
         within an address table:

         000A4990 ____ ____ ____ BC57 4A00 0E52 6567 4275 ______.WJ..RegBu

         000A49A0 7474 6F6E 436C 6963 6B__ ____ ____ ____ ttonClick_______

         Now look at the magic numbers before the name. There is a byte
         ('0E') indicating the length of "RegButtonClick" (14 characters)
         and before that an address: 004ABC57.

         Some disassemblers seem to think that file is too long and it
         doesn't disassemble this portion of the exe correctly - however,
         with a special tool we can bpx on this and... right! It stops at
         the point just when we push the button.

         A couple of instructions forward you'll find a CALL. Tracing into
         it you'll find a "standard stack frame" in 44ECC8:

         0044ECC8 55     push ebp

         0044ECC9 8BEC   mov ebp, esp


         This is the kind of thing expected at the beginning of a high
         level routine, made by the application programmer. We have
         avoided the whole chain of library calls through the VCL from
         Windows notifications, and landed in the right place!
         From this point, there are some calls you can easily test by
         setting breakpoints on them - you'll find that their purpose is
         to show the dialog asking for the user name and registration key.
         Then, the key is calculated from the user name and compared with
         the one the user entered. You can enter the name you choose, and
         anything as the key, after BPXing 44ED69. Here, a call to a
         routine compares two strings. D EDX will show the fake key you
         entered and D EAX will show the correct calculated key. Easy,
         isn't it? A ten minute crack by a beginner!!

         [description about spying the key generator routine comes next.
         It's been an average routine of about 10-20 Object pascal code

         How this way of cracking can be avoided?

         Read my tips above. The basics are: don't use automatic methods
         created by double clicking on the button or the object inspector.
         Write your code somewhere else in your program, preferably in
         another module, and bind it to the button using code such as:

           RegButton.OnClick := RegButtonClick;

         Of course you'll need to enter this code after the form is
         created and before it's called. Best if it's rounded by a lot of
         unrelated stuff. This won't necessarily prevent your program from
         being cracked of course, but things will not be as easy as you
         have seen in the lines above O:)

         Notes on registration numbers
         (if you can't avoid them)

            * balance between security, feasiblity, programmability and
              end-user headaches
            * Too long, non-alphanumeric Reg#'s tend to be continuously
              entered badly. Think about requiring to enter a verification
              field (as commonly used with passwords) or, at least,
              provide a "non-persistent" Reg# entry field so that the user
              will rewrite the Reg# each time, possibly correctly at last.
              Many people will just "glance-compare" the entered Reg# and
              the one (possibly) emailed to them, arriving at the final
              thought that they did enter it correctly, whereas the font
              is too small or they are too tired to notice that this '1'
              and 'l' have been interchanged (in a reg# like
              'l83jjd_0)pH1lTe' )
            * Refrain from any user feedback. The Reg# entry box should
              accept strings of any length, without any validation. Don't
              give crackers the knowledge about the type of your Reg# - if
              you do "online-verification" which shows that it's 10 chars
              long or that is contains only uppercase chars helps - so
              don't help them!
            * Calculate the number of potential users! There's nothing bad
              like if you have to update 9,999 users because you didn't
              expect that there might be 10,000 of them and have to shoot
              out a new version which is capable for these Reg#'s...
            * If your Reg# is 10 numbers long, there are 10^10 possible
              Reg#'s. But since your app might find let's say only 10^4
              (10'000) users, you should invent an algorithm that assigns
              each one of 10^4 users one of 10^10 reg#'s, and does it
              somewhat uniformly. This prevents people and programs (some
              .vxd based "macro" players, for example) to be used for
              brute force approach. If there are only 10^4 users and you
              allow 10^9 "valid" Reg#s out of 10^10, on average each 10th
              Reg# tried brute-force will be valid, whereas on the case of
              10^4 prospective users, that many valid reg#'s and space of
              10^10 Reg#s, on average only each 10^6th Reg# tried brute
              force will be valid. Ever calculated how much time it would
              take to brute-force search 10^6 numbers, even using a fast
              machine and extremenly fast macro player (keystroke
              generator simulating Reg# entry and checking for results)?
            * the assignment operator that assigns User# to Reg# shouldn't
              be trivial, and it's implementation should be done in
              Assembler by someone experienced both in Maths and
              Assembler. Remember that Delphi still allows you to directly
              use ASM code in your source! Then, check your operator.
              create graphs of how it works. Understand your own work,
              especially its drawbacks and vulnerabilities
            * Be inventive. Don't use anything that seems simple, quick
              and effective unless you've come with something like
              Einstein's relativity theory, your approach is yes, simple,
              yes, quick, but no, not effective, and yes, easy to crack.
              I'm sorry, but we aren't geniuses and developing a good
              protection scheme takes some time.

         Just some thoughts..

             Again: please e-mail me if you have tips or suggestions !
             If you want to support my work on this page or simply say
          "thanks" for opening my treasure box to you, I'd be happy if you
                           would register one of my apps!
            Based on your support, page will be updated frequently! Last
                                 update: 29-Sep-98

                 Copyright ) 1998 by Richard Fellner. All rights reserved.
                                                          [[Image] /10'98]
         [Image]       Do not copy to other sites or include in commercial
                   compilations without the written authorization from the

Experts Exchange Solution brought to you by ConnectWise

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Richard Fellner?
Sound familiar...The author of Delphi-Box?

Yes found it at
Thanks kjteng. Now the author can get the credit he deserves.
Ronald112197Author Commented:
As you see, the "answer" was long - very long! That's why I didn't copy it and instead let Gerhard post it as an official answer.
Gerhard - the points will be yours, but I'll keep this open for another day or two to get some more comments on some questions:

1) hmmm... I always thought that the compiler translates identifiers to addresses (fixed or via lookup-tables for dynamic binding)!!! If it doesn't, that leads to a couple of questions (for me):
a) Should I use "short" identifiers to make the *.exe smaller?
b) Should I stop using "descriptive" identifiers to make hacking harder? :-(((
c) Borland JBuilder (for Java) has a "code obfuscator" which replaces all private symbols (i.e. everything that is not "exported" for derived classes) by some illegible symbols to make decompiling harder. How about that for Delphi? Using the same idea, ALL identifiers in an EXE (which doesn't "export" anything) could be replaced with something short that doesn't "make sense" to people it shouldn't make sense to *g*
d) Are there tools around that do that? "Mess up my code" before the final build? Compact all names on forms to random two-letter identifiers? ("my ressources aren't anybody's business!)

I use a very simple XOR-encoding (well, actually slightly enhanced) for all strings that shouldn't be "visible" (about-box etc.) (of course I can't use that for identifiers).

What else do I have to do? I don't really like the idea that my code should be as messy as possible (*g*) to make it harder to crack :-((
deJohn99, yes still, don't you see me flying? :-) Found a better one around? Zif?
Ronald112197Author Commented:
Hello everybody? Nobody wants to post comments because the points are already taken?

Too bad, could be an interesting discussion...might be worth writing a little tool that searches all project files and replaces identifiers by a1, a2, a3, a4, ... would probably shrink the code somewhat and make it almost impossible to understand it. Too bad I can't "rename" my event-handlers. An OnClick will always have to be an OnClick :-(
Zif:  Haven't found better yet.  Give my regards to Moneypenney.  :-)

Ronald:  It could be changed IF you also recompiled the VCL.  The Delphi documentation states that the OnXXX convention is simply that - it is not enforced by the compiler.

You would want to maintain a table of hashed <=> normal identifiers if you started playing with the VCL.   You'd also need the cooperation of Borland to the extent that you had the "magic file" they never ship.  Maybe if enough of us demand it they may start shipping it in at least a DPU form.
Ronald112197Author Commented:
So let's go and demand it!! *g* What does that "magic file" contain?

Seriously, I imagine that it would be quite a task to recompile the VCL in order to replace "all" identifiers. Shouldn't be impossible, though. About 5 years ago, I wrote a source-code lister (including syntax highlighting, counting the nesting level, automatic indent etc.).

Would be an interesting project, but I really don't have the time to do like taht right now. I think it should be included in D5! *g* - if such a program was an integral part of the IDE, you wouldn't even have to mess with the files and keep two sets of VCL (yuck!), the compiler could simply replace all "symbols" with the shortest identifier available (a..z,,, - that should make the exe significantly smaller and give hackers a really good time *ggg*
Ronald112197Author Commented:
ok, I had hoped to still get some interesting comments, but looks like this is too far down the "locked" list now... and everybody who's posted so far can continue posting anyway.

Thanks for these tips, Gerhard (and Richard *g*)
This method isnt fool proof but to help make my app that little bit trickier to crack I search for common cracking apps that might be running and then close them (I have this routine in a timer).


{ look for Registry Monitor which alerts user changes in the registry }

h:= FindWindow('RegMonClass',nil);

{ kill the monitor if it's found }

if h <> 0 then SendMessage(h,WM_CLOSE,0,0);

I know this method isnt perfect, but it is easy enough to implement and removes a few hassles.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.