Anti Cracking FAQ
Letters and Contributions
Back to the FAQ..
I was very interested to read the Anti-Cracking FAQ on your site. I myself am a
cracker, and am always interested in encouraging software authors to produce higher
quality and more secure protections. In addition to BuLLeT and the LAXiTY members
comments, I'd like to elaborate on a few things I think they didn't cover.
BuLLeT correctly states that dongle's are expensive for authors to use. But he also dismisses dongles as being essentially worthless protection and advises authors not to use them. Dongle's have huge potential among the upper end area of the software market, where low volume sales are compensated by high prices. However, time and time again we see a very expensive piece of software which requires a dongle, but the author has just lazily applied the dongle vendors default protection wrapper and left it at that. Lousy.
If you can afford to use a dongle to protect your app, you should spend significant time making sure that the dongle is used to its full potential. You generally have a reasonable amount of dongle memory at your disposal. Make sure its ingeniously used..
It is not enough to store hard coded values scattered around the dongle, (and if a check for these values passes, then you assume the dongle is valid). This is bad, and can easily be faked. Just by using non-adjacent cells of dongle memory provides absolutely ZERO more protection than using contiguous bytes. I've been on both ends of cracking and development with dongles, and I've seen how easily false assumptions are made when you dont think like a cracker. If you have decided on using a dongle, make sure you do just that. USE it !!
Store vital parts of the programs code encrypted into the dongle. Have jump tables stored in the dongle which hold a selection of code addresses. When the app loads, you can decrypt these addresses and use them to control the program flow. This means you have to compile your app, and then rip out the jump table values for each build. So escape from your RAD environment for just a while. I't wont kill you and it may just save you a lot of potentially lost revenue.
Whats the use of this of this technique, you might ask ? Well, believe it or not, the vast majority of dongle protected apps do NOT require the original dongle to be cracked. This is because the author has put all his trust in the dongle vendors security claims, and has not spent time making sure the dongle is well used. It is generally not exceptionally difficult to fake or bypass vendors dongle API. If you store vital functionality in the dongle, then even when the cracker unwraps the dongle software wrapper, he is faced with a set of data which he cannot recover unless he has an actual dongle for your app. If the cracker does have a dongle for your app, then he can proceed to crack it, but notice how using a dongle in this way instantly restricts the set of crackers able to produce the fatal crack.
The best ways to protect your app are using advanced encryption, and *obfuscation*. Encryption is often heavily maths based and time consuming to implement properly. This sadly puts a lot of programmers off, yet ironically, they are so bitter when their app gets cracked. I affectionately think of this as the "You had your chance. You didnt take it." syndrome ;)
The dongle manufacturers HASP produce an excellent FAQ which should be read by programmers and crackers alike. Grab it from www.hasp.com.
Obfuscation in your protection can involve many things. First of all you should make the flow of execution as confusing and unpredictable as possible. The cracker is only human, and as such, his confusion is generally proportional to the amount of conditional valid states the protection can be in. Work extra hard to scatter your app with red herrings for the cracker to chew over. Encrypt serials in various ways and store them into memory, as if they will all be used for the protection. Take the encrypted username and a selection of these crypted serials and combine them to produce your valid serial. Avoid putting all of your protection in one place. You can implement all the complex protection in the world, but if its all wrapped in a function which returns true or false depending on the security check, then the cracker will gleefully chuckle at your stupidity. Make sure the security check is carried out many times at various parts of the app. After the initial check, if the security fails, set some subtle flag somewhere in the app which even more subtlely breaks the apps functionality. You can write self modifying code to do this.
Remember that only the most confident and persistant crackers will continue trying to crack your app when faced with a screen of utter confusion. The vast majority of crackers will give up and try something else. Group scene crackers, in particular, usually attempt to churn out as many cracks as they can in a given time, in a form of sick competetion. Rather than spend hours or days cracking your app, most are more likely to move onto an easier app in order to boost their crack quota and make themselves look even more elite ;)
It is vital that you make your encryption a one way, algo. As the encryption progresses in turning the username into a serial, make sure the serial undergoes a lot of one way transformation. For example, bitwise AND a small section of the serial with a value, round other small sections and truncate others. This makes it a lot more difficult for the cracker to generate a serial for a given username, since there are far more unknowns. Don't generate a valid serial in your app and then compare it to the serial the user entered. It is TRIVIAL for the cracker to rip out the very same code you use to do your generation, and spread it in his keygen for all to use.
The cracker is able to trace each instruction as it occurs. No surprise there. But if your code executes linearly and in a set condition, then it is easier to crack than if it is 'event driven'. For example, use timers to your advantage. Maybe even have a string of timers interacting with each other, or triggering each other off, with each timer performing a set step in the validation. Threads can also be used effectively. Programming with threads can often be difficult to debug; Cracking when you have multiple threads all 'simulataneously' working on a seperate part of the validation, can be a nightmare :)
As for using threads and timers together, well, I'll leave you to ponder on that one ;)
These are usually the easiest of 'protections' to dispose of. Many newbie crackers will start off cracking a nag screen or two. Most nag screens are implemented in a seperate function such as ShowStartUpScreen or whatever. Im sure you realise that this compiles to:
So if all your function does is show the nag screen, the cracker (even the newbie one), will quite happily NOP or JMP over these instructions, and the nag is history. If you use a nag, make sure you place vital initialisation code deep inside the nag routine itself. So if the nag function is bypassed, then the app is not fully initialised. You could introduce subtle defects by choosing this initialisation procedure correctly. Make sure you dont crash the app as this will immediately alert the cracker that he's done a duff job. A good place to put this initialisation routine might be in the OnActivate.
A lot of the techniques which apply to using dongles for protection, can be used in keyfiles. Pad your keyfile out with a lot of spurious data, making reconstructing a valid keyfile more confusing. Keyfiles should invariably contain a crc value which is intelligently checked (avoid producing a yes/no result). You can use your keyfile to contain jump locations, or even vital program code.
Packers and PE_Cryptors.
Whilst these are generally not difficult for an experienced cracker to unwrap, it slows him down one step further, and even possibly cuts off a set of less experienced crackers. Commercial packers and cryptors are available, along with freeware ones. Its shocking how many developers dont even attempt to make use of them.
Use the very well documented tricks to detect debuggers, and specifically SoftICE. Modify your protection so it is less restrictive if a debugger is found. This may have the humourous effect that a cracker believes he has figured out how your protection works, only for his crack to fail on all users machines which dont have a debugger running.
I hope you find this of interest.
I have read your papers on anti-cracking, and found it a good read on all subjects, much appreciated knowledge,
but got me thinking on why I crack programs, not for the reason of distributing cracks,patches,keygens, oh no!,
but for the challenge of getting the functions working (or the Reg code).
As far as my programming knowledge is concerned: I have none, only what I have learned trying to crack encryption
or algo's and getting reg #, but as 1 guy Eminence said to me "you're a NEWBIE, and a lot to learn" , yet I find
the harder protections like PACE Interlock, VBox, VB Progs easy, yet fail on easy programs from small companies
like Techfacts'95 (I could never get that until I read a TUT) - strange isn't it!. That multi-million £ companies
charge so much for products which are good, don't get me wrong, but are wrapped up in Christmas paper, so to speak.
Why small authors think about protection? Because I think 90% of them have been crackers or have cracked something
in their programming lives!
Well - I just wanted to get that of my chest after reading your VGood papers. :))
I'll still crack though ;P (only for knowledge and a challenge)..
Back to the Anti Cracking FAQ..
Do not copy to other sites or include in commercial
compilations without the written authorization from the author.