I have been meaning to write about this topic for ages due to a huge response to this article, but with four exams in two days and a few more still left, there’s been very little time. So instead of a full-fledged post / tutorial, here is my view on writing solid security measures into your shareware applications. Note that I haven’t actually written a shareware app myself, so most of this is theoretical (ie. in my crazy mind).
Before we get into the different strategies, I would like recommend this article on software piracy by Ambrosia Software (Snapz Pro X). It really shows how vulnerable Mac apps really are and the effect they can have on small and individual developers. Ambrosia now uses what I believe to be one of the strongest and most fraud-free licensing system of any developer (including Apple). However, the method they use does have drawbacks in slight annoyances for the user. There is no perfect way of protecting your application, and no matter what you do, those that want to crack your application will; Even Microsoft, Apple, and Adobe have their software cracked and pirated. It’s about finding the right balance between safety and resources. How much time are you willing to spend hack-proofing your app? Do you need to go hard core encryption and daily online checks or is storing a hidden encrypted file enough? It’s up to you to review the alternatives and decide.
Using the plist
What a lot of apps these days are doing, is storing everything (registration info, no. of launches left, etc.) unencoded in the preference file. Umm… what’s the first thing you’re told to when an application starts behaving erratically? What does Mac OS X do when an application crashes?

Clean your preferences. In the case of most shareware, you get the added joy of having to dig up your registration information and re-register the app (or worse, buy another one). If you hadn’t registered it, most of the time you discover guiltily that the demo period has restarted and you can use if for longer. So, it’s clear that storing the information in the preferences isn’t the ideal way to go, but if you have no other option, you can try to utilize the following strategies:
Have a separate hidden plist
As well as your standard preferences, you can make another hidden file where you store sensitive information. It can be a standard plist file, but it could just as well be a file with the contents of the no. of launches remaining or the registration info. Applications that do this include most WidgetMachine widgets, Snapz Pro X, …… Most users who download a shareware application will spend ten minutes seeing if they can crack it, after which they’ll give up and buy the license, or resign to the demo. Hiding a second plist file is a great way to baffle average users who don’t delve very far into their Mac.
For further security against tampering, you can encrypt the contents of the hidden plist, then decrypt it when you read it from your app. Again, if you can decrypt, chances are someone geeky could too, but remember, nothing is foolproof.
I mentioned earlier the plist file doesn’t have to be an actual plist. You could call it “.myappdata.abc” (notice the lack of the words “registration”, “hidden”, and “demo”). The period at the start saves you from having to set is as hidden. Using this method, the sequence of events could be as follows:
- Application is launched for the first time, .myappdata.abc is created with the contents of the current date.
- Application is used in demo mode, with the demo expiring 30 days from the date in myappdata.abc.
- User uses app… and loves it
- Demo expires!
- User, in his delirious state, delete the .plist file in the hope of resetting the demo period. Obviously this fails as the demo info in in the file .myappdata.abc.
- When that fails, the user deletes and reinstalls the app, first manually, then using AppZapper. Again, this fails as AppZapper doesn’t pick up our hidden file.
- User scours his hard drive, looking for a sign of something that could be the key to hacking this very difficult app, neglecting to search through the hidden files.
- Finally, giving up, the user either registers the app, or deletes it.
- Assuming registration, our application deletes the contents of “.myappdata.abc” and replaces it with the registration name and serial number.
- Life goes on.
In this example, the user neglects to check hidden files, and misses .myappdata.abc in his Preferences folder. However, what if he was clever enough and got out Tinker Tool (or Terminal) and enabled viewing hidden files? Firstly, because the hidden file is named “.myappdata.abc”, he may not bother to look in it. I mean, he’s looking for something along the lines of “H1dd3n_registration_info.plist”, right? But what if he’s desperate and goes through it? If he opens it in Textedit and the contents appear to be a date, it can be a very strong clue to the fact that we’re housing demo information. To overcome this, we can encrypt the file so it’s harder to read. Having said that, if the user decides to delete the file, the information will be lost anyway, and the demo will be reset. Now it’s time to go even further.
The timestamp is your friend
This can be a great way to battle piracy. Repeat after me: I should check the timestamp of my plist file. If your app has a 30 day demo, and the key for days remaining says 999999 and the plist was created 30 days ago, it’s probably a good idea to credit that to tampering and bring the value back down where it belongs (AppZapper and Disco are very big culprits here). If you utilize a hidden plist as well as the standard one, you can check the timestamp of both standard files, to check for tampering. If they’re not the same, one of them has been deleted. Of course, this only works for time based demos.
Catch the cheats
In Cocoa, there is a very nice class by the name of “WebView” that enables you to access the internet (an easier way would be through CURLHandle). Via a simple PHP script or similar, you can log all registration attempts in a database. It’s even possible to access Cocoa from Javascript in the WebView, then use a setXMLHttpRequest to post the data; something I may look at further in a future post. As an example, the following PHP script would store the registration name, email, serial key, date and IP address in a MySQL database, by accessing POSTed variables.
<?php
mysql_connect("localhost","user","password");
mysql_select_db("myRegoDatabase");
$reg_name = $_POST['regName'];
$reg_email = $_POST['regEmail'];
$reg_serial = $_POST['regSerial'];
$reg_timestamp = time();
$ip = $_SERVER['REMOTE_ADDR'];
$result = mysql_query("INSERT INTO regInfo (id,name,email,serial,timestamp,IP)".
"VALUES ('NULL', '$reg_name', '$reg_email', '$reg_serial', '$reg_timestamp', '$ip')");
?>
Obviously you don’t want this to be visible to the user, and you’ll need to ensure against MySQL injection, which the above script doesn’t. However, I hope you get the general idea.
And the winner is…
In truth, there is no winner; no perfect method of securing your great application against theft and piracy. You need to safeguard your property, but at the same time licensing schemes can end up being overly expensive for no real benefit. Take the time to evaluate how much you want to spend (both time and money) on developing security for your application. If it’s between $0-10 then there shouldn’t be a need to implement hard core techniques, but just enough that the average user would give up trying to crack it and decide that there’s no point wasting time on a relatively inexpensive application anyway. As shops and stores suffer from theft, so developers suffer from piracy. It’s not something we can eradicate, but a little time spent planning can go a long way in ensuring you get a daily feed.
An overview
Options available for licensing and demo management:
- Make a hidden plist
- Encrypt license information in plist file
- Encrypt license information in hidden plist file
- Always check correctness of info (for tampering)
- Make file name / extension weird to throw people off
- Don’t make information obvious (as in nice XML)
- When entering license, log in online database
- Check for fraud (multiple licenses all over the place)
- Match start demo date with date plist was created
- Use your head, think abstract!
Remember, use that big lump of grey and white matter in your cranium, and innovate. If you want the user to have only three uses of your app before registering, store uses 1, 2 and 3 as NSColors or random strings, such as the first use is blue, the second use is green, then the third is yellow. Being yellow, the app finishes the demo and asks for registration. There’s no such thing as too lame. If it works, why not. Good luck, and let me know your thoughts and views.
16 Comments so far
Leave a commentBe very careful with timestamping hidden preference files. Times can and do get screwed up on your user’s machines. You really do not want to be invalidating your customer’s license data (and thus presenting warning dialogs or the like) because of a bad file date (trust me on this one.)
Apps should, however, check for system clocks that are obviously out of synch (i.e. they’ve been switched back in time deliberately or otherwise). For example, if the system time is
determined by David on November 24, 2006 7:54 am | Permalink
[gack, cut off!]
system time is
recorded by David on November 24, 2006 7:56 am | Permalink
[ok last try, it seems that the comments system does not like certain characters]
Be very careful with timestamping hidden preference files. Times can and do get screwed up on your user’s machines. You really do not want to be invalidating your customer’s license data (and thus presenting warning dialogs or the like) because of a bad file date (trust me on this one.)
Apps should, however, check for system clocks that are obviously out of synch (i.e. they’ve been switched back in time deliberately or otherwise). For example, if the system time is less than the build date, then there’s an obvious candidate. But again, be careful, and be lenient (clocks can and do go out of whack.)
Eventually, I’d like to see some sort of OS-level integration for securing such data, so that we don’t have all these random, hidden preference files floating around. Perhaps, when we register our fourcharcodes with Apple, we also register some keys that can be used exclusively by our application, and then we use a specific API to set/get the license (or other data), and it’s up to the system to store it, verify it, etc. Just an idea…
While I’m here, how about we get a solution for the other great app issue of our times: installers! The current “drag application to your Applications folder” system doesn’t work for most users. The automatically-trashing-DMG system is a flawed one (I want to keep that DMG, and I shouldn’t have to go fishing it out of the trash).
Nobody really likes installers — there’s always the feeling that Other Stuff is being installed (however simplistic this is). Drag and drop itself is great, but look at the overall process:
This tedious process, while automatic and simple for most developers and the Mac faithful, is fraught with problems and distractions for new and casual Mac users. It is EVERY easy to overestimate the user’s ability in this regard and because these people aren’t vocal (they’re not likely to leave comments on versiontracker) the first time that you know there’s a problem is when they’ve sent an email to you explaining that your latest application update doesn’t work (most likely because they’re still using the old version, and now have several copies on their machine.)
Also remember that many (most?) Mac users don’t know what a Disk Image is! After all, it’s not a Disk and it’s not an “image” (in the sense that most of our customers would recognize the term).
I would like to see standard OS-level handling of DMG files that, possibly, pops up an installation wizard which:
tells the user what is being installed, and where it is being installed.
provides an option to keep the application in the dock.
provides an option (on by default) to launch the application immediately.
Anyways… just ideas.
recorded by David on November 24, 2006 7:57 am | Permalink
Another good resource on this subject is the O’Reilly Book, “Secure Programming Cookbook for C/C++”.
It has a whole chapter devoted to Anti-Tampering measures, including detecting Unix debuggers (GDB) and self-modifying code. Worth a look.
announced by Nick on November 24, 2006 3:50 pm | Permalink
You have to be careful with apps that phone home. You must make it clear to the user that you’re contacting a remote machine or face the wrath of blog-wielding populace.
mentioned by Scott Stevenson on November 25, 2006 10:30 am | Permalink
It depends on what the app is doing. I see no ethical problem with an app phoning home to get information such as the latest version, invalidated license info, content updates etc. Very few legitimate customers would have an issue with an app getting what it needs in an anonymous fashion.
The problem comes where information gets sent back to the server, and this is where the developer needs to up front with the customer.
reasonded by David on November 26, 2006 9:19 am | Permalink
When it comes down to it, just enough protection is the perfect amount. By layering on ‘phoning home’ and other annoyances the only people you hurt are the people who actually bought the software. People who pirate or steal shareware will ALWAYS find away around it, its that simple. So just create enough protection so that the people who felt encumbered enough to buy the software can use it without worrying its not going to activate.
determined by Matt Tavares on November 27, 2006 5:04 am | Permalink
You took the word right out of my mouth. However, I do think it’s important to discourage those who might just have a quick five minute peek to see if they can avoid a registration fee as opposed to the malicious hackers. I mean, if Apple & Microsoft stuff gets cracked, someone with the know-how and the time could easily disentangle just about anything.
composed by Ankur on November 27, 2006 4:00 pm | Permalink
Matt, as someone who has sales experience with both systems, I disagree.
Phoning home is hardly an annoyance, no more so than quietly checking for a version update. (In fact, both operations can be done at the same time.) In practical terms, grabbing information (while respecting the privacy of the customer) is no more invasive than the web page where the application was downloaded in the first place. In fact, even less so. The only people genuinely disadvantaged by a one-way look up of a html page or text file, are those people who want to pirate your app.
A developer who simply releases serial numbers out in to the wild and then never checks those serials to see if they’ve been replicated in Serial Box or Surfers Serials or some random web page, is going to see a serious loss of business. Been there, done that.
“People who pirate or steal shareware will ALWAYS find away around it, its that simple.”
Actually, it’s not. For a typical app by a small company, the majority of pirates are casual: they rely on the swapping of a serial number (often a single one) which they glean quickly from the sources mentioned above. They pirate because they can: it’s easier than purchasing.
Cracks, albeit more widespread in the Windows world, are much less used than serials and more common with big-ticket items like Adobe app. The effect of cracks can be negated somewhat if you have a planned strategy for continual improvement and updating of your products. (Such updates, of course, should also deal with known invalid serials.)
spoken by David on November 28, 2006 7:20 am | Permalink
David, you make some excellent points.
I personally find that one of the biggest problems today is because of
I can name many applications that connect to the internet for registration, and seeing a little progress view for two seconds isn’t going to either annoy the user or upset him. You can always use the old “No personally identifiable information is being sent” as some of big names with expensive lawyers do.
spoken by Ankur on November 28, 2006 3:23 pm | Permalink
Hmmm… php scripts that collect emails etc and store it in your database.
As a potential customer, it makes me think a lot of the shareware you guys are creating is really just malware. I think I’ll avoid even the demos from here on in.
posted by Simon on February 28, 2007 3:13 am | Permalink
Simon, I don’t think you understood the intent of what I said.
I’m not advocating PHP scripts that store your private information in a remote database. Quite the contrary. What I’m proposing is a method for the developer to check whether an individual license is being used multiple times. Think about it, if you bought the license using your email address, then why would the developer need to use obscure tricks to scam it from you?
An application that employed this technique would really be the opposite of malware. It helps you know that your license is authentic and gives the developer the information necessary to combat piracy. Again, its not malware. There is nothing sent that could be potentially a breach of privacy. The application would simply check the number of times a license is used.
And really, if you’re going to avoid the demos I post up, that’s your call, but you’ll be missing out on a lot of groundbreaking techniques and methods. Plus, if I release the source, how big a chance is there that I’m spreading “malware”?
Really, I’m sorry that you took it the wrong way, but I hope you see my point of view now.
disclosed by Ankur on February 28, 2007 12:53 pm | Permalink
AquaticPrime, anyone?
composed by Anonymous on January 24, 2008 12:36 pm | Permalink
This days, with Spotlight technology and free app like FSEventer shareware authors are doomed. Using FSEventer you can very easily monitor installation and first run of the program and get information about EVERY file which were touched by the installed app. Cleaning afterwards is very easy.
Not to mention more advanced technologies like dtrace and strace which gives you detailed insight about app internal work.
recorded by developer on August 10, 2008 7:14 am | Permalink
Developer, you’re right that it’s not really that hard to figure out most shareware (though I can think of a few tricks which would still prevent the ‘doom’ of shareware). Hidden files are not only easy to find, they’re also very annoying.
stated by Ankur on August 10, 2008 9:13 pm | Permalink
Leave a comment