OddOne Trusted SF Member


Joined: 24 May 2004 Posts: 0

|
Posted: Fri Oct 15, 2004 4:17 pm Post subject: |
|
|
From an IRC conversation I had with a cracker friend of mine:
Me: Nothing says "I wub j00" to a cracker like polymorphic encryption and self-modifying program code.
Him: You are an evil, evil man.
Loads of people to quote here, so look for your name, hehehe...
Security Hobbit wrote: |
Well, I'm no good at windows app, but from my experience on 68K, with a good debugger and a bit of time to spare then it shouldn't be much of a problem. Again, the whole point is to beat the equation:
time to crack > time cracker is willing to spend on it
The second part of the equation is mostly dependant on how popular/famous the app is. |
Yep, there's no such thing as "uncrackable." The whole point is to make it take too long to be worth it to anyone but the most hardcore. So-called "production" crackers, the ones that are part of warez groups, are the ones that developers are best off targeting with their protection schemes as these folks have incentive to break the protection as quickly as possible and distribute the cracks without any concern about the developer.
Security Hobbit wrote: |
You don't need all sorts of encryption and things like that, just do the registration check in a completly different part of the application than the registration input routine (in the middle of the game for example), save the results in convoluted ways in 25 different places checked at different times in the application and that should do it in my book. You can also do checks on parts of the resitration at different places and in different ways so that the cracker doesn't know whether the rest of the registration is really checked or not. |
Encryption does help, by making it harder to see what's going on in memory. And yes, doing partial checks all over the place is great. Another good tip is to not use dialog boxes to display nags or expire notices, as any boob with a copy of SoftIce can set a breakpoint onto the MessageBox API call and backtrack your code from there.
I'm also fond of checking the checking code, and using inverse logic (a true for bad code instead of a true for good) helps by adding the sheer annoyance factor.
Security Hobbit wrote: |
PS: don't forget convoluted code checksums on small key parts of the code that do not crash the app but simply do something wicked. Make also sure that the results of the code checksums (equal or not) are not necessarily correct all the time either just to fool people. |
This has to be done carefully so as to not anger legitimate users. You don't want to crash a machine, and CERTAINLY not damage files, but crashing the app out with a special "error" code that you'll recognize as a "hey, this user tried to crack the app" flag is good. Or, have the app quietly abort whatever its main process happens to be. I was also fond of having a few threads spawn that did something difficult and time-consuming (like making SHA-512 hashes of ISAAC-generated pseudorandom data, which eats cycles like mad), so as to bog the app (and machine) down without actually hurting anything.
lepricaun wrote: |
It would be the ultimate solution to create an md5 checksum of the complete executable and let this be checked in the executable itself. meaning, as soon as something has been altered, the program won't work anymore. but it is impossible to create an md5 checksum from your program and then implement the result in your code, cause this would alter the original checksum again.... |
There is no "ultimate" solution. There are only variations in difficulty. And, tagging a file with a hash is quite easy - you simply place the hash at the end of the file and perform the hash check against all but the last X bytes of file to not rehash the hash. You'd need to perform additional trickery to the hash, though, to prevent what Troopa mentioned as a vulnerability of this method - a cracker recreating the hash after patching the file.
Security Hobbit wrote: |
One way I know of which is a bit more evolved is by creating a separate file or code resource or whatever with length, positions in code and checksum (whichever you want: md5 hash, CRC16, ...). You then have a code checksum routine in your main program which loads positions in codes, length, and correct code checksum (or incorrect code checksum if you like and want to play with the cracker a bit) and reacts accordingly. This of course is still crackable, but a lot more of a pain in the @ss to crack. Using false code checksums to thwart off the cracker is a very good way to do it. |
Yep, spotchecks work wonders, and inverse logic pwns the mind of many a cracker. Another REALLY good one is to bury a spotcheck inside a critical portion of the program's working code, interspersing one into the other as much as possible. NOOPing out the spotcheck then kills the app's working code and renders it useless. Bonus points for making the app detect this and raise a special "error" code as I mentioned earlier.
Speaking of NOOPs, a great one to mess with the mind is to have a block of NOOPs in the file and write encrypted variable contents - or just random garbage - into the block of space. Suddenly the app looks like it's self-modifying and the cracker has to go on a wild goose chase to figure out WTF your app is doing, why, and at what point in execution. Bonus points here for making it occasionally write critical data into this NOOP block so that touching it wrecks the app.
Security Hobbit wrote: |
The ultimate protection: create the code checksum or reg check routine in a programming language that disassembles into a mess of rubbish which is extremely hard to follow and incomprehensible to the cracker. This of course would make him/her spend way more time tracing routines than he/she is willing to spend. That coupled with the stuff I told you above should do it. |
Nothing says "I wub joo" to a cracker like spaghetti code with more jumps than actual instructions, and with conditionals that constantly flipflop in their logic. Even better, have parts of it encrypted and parts not, but leave no obvious indicator of which is which.
tsh33p wrote: |
Yeah, this is just basic stuff. Software developers seem to be complete gimps, half of them don't even change the protection. It's been like that since cracking started... And I think it will always be like that. Cracking is not hard, it's just like a high tech crossword puzzle and you are right, most reversers reverse because of the challenge, there are only a few who do it for the software... If your interested in cracking, reverse engineering, etc. be sure to search google for those keywords. Any way, again.. this is just *basic* stuff. |
Most developers are retarded or totally braindead when it comes to protection because they do not approach the protection with the idea of "how can I break this?" They simply don't think about how a protection scheme can be attacked, and thus, when it is, it fails.
I've been evolving my own protection schemes over time. My first took ten months to crack (measured in terms of time from release to the public emergence of the first crack/serial/keygen), my second has not been broken since 2002, and my third has only been out a few weeks but thus far has not been breached as far as I can tell. Still, they're not unbreakable (NOTHING is) but they are hard enough that I've gotten hatemail from pissed-off crackers. Someone will break them I'm sure, but I want my protection to be tough enough that only the true code poets, the elite among the cracking circles, will accomplish that feat.
oO
|
|