January 29, 2003
Pirate-Me-Not

I promised to give some pointers for programmers on how to enhance your software so it is less vulnerable to cracker's attacks, who are trying to crack or make a serial for it.

All of these things are pretty obvious, yet a lot of software authors don't obey them. As a result, a serial number pops up on the Usenet / web boards within a few days (or even hours) after the new version release, thus hurting sales dramatically - my experience shows that if "generic pirate" people cannot find a serial number or crack for a particular software within first 3 days, they are more likely to buy it. But don't overestimate this statement, as lots of pirates will never, ever pay for your software, no matter what you do. But either way, often holding up for the initial 3 days after each release is a strategic move that might bring you more sales.

So here is a couple of tips to prevent serial numbers from being generated:


  • Strip debugging symbols. Run pbxbuild install or strip on your executable before shipping the code. Otherwise, a quick nm run will reveal a list of all of your internal symbols, such as, ugh, _CheckSerialNumber, or similar, thus giving a lot of clues to the hacker. Note that for Cocoa applications, it is not possible to completely strip off the classes and methods used in the executable - even if nm won't show it, class-dump will still do. However this adds some additional hassle as the hacker would have to set a breakpoint on a memory address rather than a symbol name in gdb.
  • Do not make bottlenecks. Never reside your serial number checking code in one routine returning true or false. This makes it an easy target for a [k] - change one byte in the code so it always returns true, and you're nailed. Use inline functions so there are many places where the serial is checked - it will introduce much more hassle for a possible cracker.
  • Base serial number on a customer name, if possible. This reduces the chances of a serial number to be distributed, as it's less likely for a person to share his/her own name with the whole 'Net as compared to a simple, faceless serial number. Base it on the email for even greater effect. There are plenty of John Smiths out there, but definitely only one john_smith@lambda.org.
  • Do not generate the full valid serial number internally. Many applications pre-generate a valid code for a given name, then compare it against the one user entered. If strings match, the serial is valid. This is probably a biggest security hole you can make -- all it takes is one run in gdb to find out the correct serial number your application nicely pre-generated for the cracker.
  • Use less obvious method names - since the hacker can easily observe all of your Objective-C classes, at least make the serial number checking routine less noticable (think orderWindowOut: instead of isSerialValid:). There's a good chance hacker will step over a routine with such an innocent name.
  • Don't check the serial number right away - there is no need to run the check right in the action invoked from the OK button on the registration sheet. Send a notification, set up a timer, do it from a sheetDidEnd: callback - just don't do it right away. This makes finding the right spot harder.
  • Banning leaked serials - never ever keep a list of banned names or serial numbers in plain text in your code. Why? Because this scenario is way too common: you ban a serial number in a new release, and hackers make a crack that will re-enable the banned serial number. How? Bloody simple. They search for a banned name in ASCII in your application binary and replace one or two letters in it, so they can still enter the "old" serial but the application will not be able to match it against a list of known leaked serials. At least ROT-13 it. Or XOR it.
  • If possible, only do partial checks - when the user enters a serial number, check only some part of it, and ignore other checks. Then check other parts of the serial for validity someplace else, and do not make a big fuzz out of the fact the second check fails. This may lead a hacker to beleive the serial they just made is valid, but it won't work.
  • Stay sane - if hackers decide to go at your software, you probably will not be able to hold out. You have other business to do, not just fight with people who are trying to outsmart you. By all means, understand that providing a sufficient protection level for your software is required to maintain acceptable sales, but the protection and the effort you spent on it should never interfere with the normal operation of your software, and shouldn't make legal users feel uncomfortable.

This about sums it up. Hopefully some of you found this useful. :)

Digg This!

 Posted by slava at January 29, 2003 04:16 PM

Trackback Pings:

TrackBack URL for this entry:
http://www.unsanity.org/mt-tb.cgi/11.

Listed below are links to weblogs that reference Pirate-Me-Not:

Software Piracy from TooMuchSexy.blog
Slava, from Unsanity, has written a relatively long post on the thoughts of Software Piracy and how to protect your software from it. Slava's post was incredibly informative, and it really interests me. I personally have been using computers since appr...[Read More]

Tracked on January 29, 2003 4:51 PM

Pirate-Me-Not from Michael Tsai's Weblog
Slava Karpenko: I promised to give some pointers for programmers on how to enhance your software so it is less vulnerable to cracker’s attacks, who are trying to crack or make a serial for it.[Read More]

Tracked on January 29, 2003 8:30 PM

The Piracty and Protection Problem from Laterus
Unsanity: Software Protection and Piracy is an interesting article I ran across while reading through Tuesday's NetNewsWire's feeds. The article[Read More]

Tracked on January 30, 2003 10:04 PM

The Piracty and Protection Problem from Laterus
Unsanity: Software Protection and Piracy is an interesting article I ran across while reading through Tuesday's NetNewsWire's feeds. The article[Read More]

Tracked on January 30, 2003 10:04 PM

Cracking Software from MINISTRY OF INFORMATION
I just read a nice article over at unsanity.org. There are some good guys working there who have helped me out in the past with my development work. The article covers protecting your software registration code system from being cracked by pirates. I a...[Read More]

Tracked on May 16, 2003 11:55 AM




Related:
Comments

What the hell are you giving out my e-mail for man?

Posted by: John Smith on January 29, 2003 7:27 PM

Yeah... riiight.. LOL

Oh, and I like the "Welcome Safari User" badge. Much nicer than Apple's.

Posted by: Jason Anderson on January 29, 2003 8:25 PM

Don't say hacker when you mean cracker.

Posted by: nit picker on January 30, 2003 11:07 PM

I just wanted to thank you for being so informative.

Posted by: Etan on January 31, 2003 6:35 PM

I think the most effective way is used by Blizzard Entertainment on their Battle.net games. They require a serial code at activation, and every time you go on Battle.net the network checks if you're the only one on with that code. If someone else is on the server rejects your connection, and Blizzard will eventually look at how much that happens for the specific code and may ban it or make it so you cannot talk over Battle.net just game.

Posted by: Musics4Me on February 2, 2003 5:17 AM

Indeed I am thankful for this article. Too many developers are ignorant of the weaknesses in their programs and then complain when a kracker comes along and [k]s the app within 5 mins... kracking is similar to the way that hacking exposes system vulnerabilities to the programmers/admins of that system. kracking reveals program weaknesses to their developers.

Posted by: =FireSt0rM= on February 3, 2003 9:57 AM

There is one more (obvious?) point I'd like to mention: When displaying a serial number to the user (in the about box or a splash screen for example) don't display the complete number! Just display a unique part of it so that someone copying the number will be missing essential information for registering his "borrowed" copy. This not only makes it harder for the thieves, it also helps honest people from inadvertently sharing their serial number while still enabling them to keep track of the license used for the particular install.

Posted by: Mike on February 12, 2003 2:06 PM

Is it just me or what .. information like this should be better left in developer connection groups. By explaining stuff like this publicly only promotes more crackers to figure you out. The great LOKI has spoken oooooo..

Posted by: LOKI on March 10, 2003 3:40 PM

Hey, pop! Security through obscurity is not the way to go. The smarter "crackers" will find a way at the information anyways. Only by publicly distributed information will enough legitamate users have the information to make it valuable. If no one has the data it doesn't matter that you said it.

Posted by: Fenris on March 14, 2003 2:09 AM

Loki wrote:

"Is it just me or what .. information like this should be better left in developer connection groups. By explaining stuff like this publicly only promotes more crackers to figure you out. The great LOKI has spoken oooooo."

As someone who cracked a few wares in my day, I don't think there is any reason not to post this information. It is all glaringly obvious, and there are plenty of programmers out there (developers) who should pay attention to these things. Most of the time, cracking software (mac and commodore 64) was WAY pathetically easy, with none of the above security measures taken.

There will be no benefit to crackers in posting the above, because it's pretty damn glaringly obvious, and knowing that developers might do the above doesn't help in cracking it anyway.

Posted by: humphries on April 13, 2003 4:19 PM

First of all, I'd like to thank Slava for posting this list on securing registration codes. Hopefully this will help other software makers from stumbling through a tricky topic.

On the topic of disclosure, there is nothing really to fear from posting this information in a general sense. You'll notice that Slava did not post the locations in memory of their registration functions. There is considerable work in reverse engineering a well constructed application and breaking its registration system. Knowing the ways that some developers make it more difficult is not "new" knowledge to people who crack software.

Most importantly, I'd like to add to the body of knowledge here from lessons that I have learned.

I recommend putting a failure counter inside of your registration code checker. If someone uses the function a certain number of times with incorrect codes, then it should trip a static variable that tells it to silently fail every code after that. This helps prevent brute force attacks against your checking code.

Make registration code checking slow. This is code that does not need to be optimized. You want anyone linking in against your code and running a brute force attempt to find codes to take a very very very long time. Obviously, you want to be a little more subtle than sleep(2) as something like this is easily circumvented.

I'd like to re-iterate that you should not build your registration code checking system inside of cocoa objects. They export far too much information and aid potential crackers.

Statically link against any registration code system. Do not place your registration code system inside of dynamic libraries or frameworks.

Do not use boolean values as returns for any registration code checking. You should dynamically assign some variables that define success or failure during the run time of your application. These assignments should be random values that are unique to every running instance of your application.

You can keep a list of codes to ban inside of your application, but you should use encryption to hide them. This is trivial on Mac OS X as crypto libraries are included on the system.

I also recommend doing checksum verifications against any critical hard-coded data (such as codes to block) and cause a silent failing of the registration code system anytime one of these chunks of static data are found to be modified.

Well I hope some of these other ideas aid folks in protecting their software better. I can be reached at the listed email address, or through my personal web site for questions.

Cheers!

Jeff

Jeff Thompson
http://www.everythingmacosx.com/

Posted by: Jeff Thompson on May 16, 2003 11:50 AM

I'm currently working on a serial algorithm; which I believe would be quite safe, currently there's somethings to work out though,the algorithm takes adventage of MacOS X memory protection and the fact that a process runs in it's own virtual memory space, in short it works like this, the user gets a code that's generated specially for this user, his serial is generated using a public key algorithm, when decrypted it will reveal an 32 bit integer that's an secret address defined by the developer (the application checks this address for a checksum) if the address is invalid it will most likely not contain this particular checksum; the great thing about public key algorithms such as RSA is that you can check if it's signed, if it's not signed we assume it's an invalid serial number, if it's checked we assume it's valid and decrypts it, if it's a "generated" serial it will most likely result in the wrong address. That allows us to be quite sure about wheneither the sn# is spoofed or not, that's how it works in short, I might have missed explaining a part or so, the point isn't to explain exactly how this algorithm works, just to give you a hint about it. and either way this is just an idea I've evolved from, I just want to share the base idea, if you find it interesting feel free to implement it, (personally I use a variation of it that's slightly more complex) also note this algorithm has not been tested in any product yet, it's just on the "research" stage, but I believe it's fairly secure. currently it goes under the code name "SoftDongle" ;)

Posted by: Fredrik Andersson on May 23, 2003 5:43 PM

I don't know how it will work out but I plan on distributing my app with a licensing scheme that requires a license file that is encrypted, and tied to the HW ethernet address of the machine. You can pass the file around, but it won't decrypt unless the app registration info in the app is the same as that used to request the license, and it won't run unless the machine ethernet address is the same as in the license. (I will be happy to generate new licenses for registered people who change machines or use a powerbook in addition to a desktop for example).

Posted by: Chad Leigh on June 5, 2003 3:42 PM

don't say cracker when you mean kracker :P

hacker: takes apart things for fun, sometimes wanders into the less legal side, but usually doesn't do anything malicious based on the information gained.

cracker: takes down/modifies web pages without consent of author. creates viruses and trojans. other malicious web based attacks.

kracker: takes apart software to determine how it works, and then creates a work around. sometimes tells others how he/she did it, sometimes releases a krack. will, on occasion purchase software/shareware, sometimes to aid in the kracking of the application, sometimes to support the author of the software that they are kracking. usually understands that if no one pays for the software, it will no longer exist, but also knows that information wants to be free.

01011011010111010001110001101011

Posted by: 0110 1011 on August 28, 2003 3:33 PM

Hate to break it to you, but even after after you've done all of that, and even with the sha1 technique that haxies have been using, it's still relatively easy to generate serials for any haxie. You might want to consider using a different technique for each haxie.

The advice I can give to developers is that you can only stop the casual pirate. If someone really wants to use your app without paying, they will.

Posted by: peter pumpkin eater on December 30, 2003 8:06 PM

peter pumpkin eater: any protection can be cracked, as I said before. It's a matter of time and will, and if somebody really wants to get something, they will.

Posted by: slava on December 31, 2003 1:30 AM

pray your software does not end up on fosi's web page that is one way. The other sell the shit at retail stores.

Meshue

Posted by: Meshue on June 12, 2004 2:02 PM

You're suggesting ROT13? Sheesh! We upgraded to double-ROT13 years ago.

Posted by: Security Advisor on March 13, 2006 6:50 PM

One good tip: Use #define for changing function names. That way, you can write the code with lines like if [self checkPartOneOfSN] ... but the #define will make sure it gets compiled into if [self doSomethingUninteresting].

Posted by: Uli Kusterer on May 11, 2007 4:17 PM
Post a comment
Keep comments on topic. If a comment is unrelated to this post, it may be removed or moderated.





Remember Me?

(you may use HTML tags for style)