This is a problem we all have to consider at some point.
After many years and many approaches I tend to agree in general with the staterment: "For any protected software used by more than a few hundred people, you can find a cracked version. So far, every protection scheme can be tampered with." http://stackoverflow.com/questions/343017/does-your-employer-enforce-the-use-of-anti-piracy-software
Further, every time I post about this subject, some one will remind me; "First of all, no matter what kind of protection you'll employ,a truly dedicated cracker will, eventually, get through all of the protective barriers." http://stackoverflow.com/questions/71146/whats-the-best-value-for-money-c-code-protection-for-a-single-developer
So not withstanding these two broadly true disclaimers, lets talk about "protection"!
I still feel that for smaller apps that are unlikely to warrent the time and attention of a skilled cracker, protection IS a worthwhile exercise.
It seems obvious that no matter what you do, if the cracker can switch the outcome of an IF statement (jmp) by patching the application, then all the passwords and dongles in the world anre not going to help.
So My approach has been to obfuscate the code with virtualization using products like: http://www.oreans.com/codevirtualizer.php I have been very happy with this product. To my knowledge it has neve been defeated. I can even compress the executable with PEcompact Does anyone else have experience with it?
Had nothing but problems with EXEcryptor http://www.strongbit.com/news.asp Even the site is a headache to use. The compiled apps would crash when doing any WMI calls.
This approach allows you to surround smaller sections of code with the obfuscation and thus protect the security checking etc.
I Use the online authorization approach, as the application needs data from the server regularly so it makes no sense for the user to use it off line for extended periods. By definition, the app is worthless at that point, even if it is cracked.
So a simple encrypted handshake is plenty good. I just check it occasionally within the obfuscation protection. If the user installs the app on a different machine, a New ID is uploaded upon launch and the server disables the old ID and returns a new authorization.
I also use a hash of the compiled app and check it at launch to see if a single bit has changed, then open the app as a file (with a read LOCK) from within the app to prevent anyone changing it once launched.
Since all static strings are clearly visible in the .exe file, I try to be generic with error messages and so forth. You will not find the string "Authorization failed" anywhere.
To protect against memory dumps, I use a simple text obfuscation technique (like XOR every character) This makes plain text data in memory harder to distinguish from variables and so forth.
Then of course there is AES for any data that is really sensitive. I like counter mode for text as this results in no repeating sequences revealing underlying data like a sequence of white spaces.
But with all these techniques, if the Key or Initialization vector can be dumped from memory, or the IF statement bypassed, everything is wasted.
I tend to use a switch statement rather than a conditional statement. Then I create a second function that is basically a dead end instead of the function that actually performs the desired task.
Another idea is to code pointers with a variable added. The variable is the result of the authorization (usually zero). This will inevitable lead to a GPF at some point. I only use this as a last resort after a few lower level authorizations have failed otherwise real users may encounter it. Then the reputation of your software is lowered.
What techniques do you use?
(this is NOT a thread debating the merits of implementing something. It is designed for those that have decided to do SOMETHING)