Today I awoke to see a response from Tim Bray on the Android Developer's Blog regarding my previous article on circumventing the Android License Verification Library, and I almost completely agree with him. The License Verification Library is a very good start - above and beyond what, if anything, Google owes developers. Copy protection is and should be the responsibility of the developer. Google has given us a great tool, provided thorough documentation, and even open sourced the project.

However, what I don't agree with in Mr. Bray's post was his calling my article a "how-to-pirate piece," as this was not my intent at all. I wished to draw attention to the issue, so fellow developers would know that more needs to be done on top of their using the License Verification Library. The average pirate likely does not know enough to hand patch an app, and the ones that do probably figured this out before I did.

Tim Bray stated in his post,

Some developers are using this sample as-is, which makes their applications easier to attack.

The failure clearly was not Google's Licensing Service, rather, it was how developers implemented Google's License Verification Library that interacts with the service. Instead of taking Google's examples and creating a custom library and implementation of it, many developers chose to drag and drop example code into applications. Using the identical, freely available, sample code across multiple applications, developers left a clear picture of what the code was doing, and allowed the same patch methods to be used across multiple applications.

Also from Bray's post,

The attacks we’ve seen so far are also all on applications that have neglected to obfuscate their code, a practice that we strongly recommend. We’ll be publishing detailed instructions for developers on how to do this.

I looked at two popular applications, Tasker and Galcon (The only game I have played in many years! Buy a copy!), both using the License Verification Library, and both seem to have been protected with ProGuard to optimize and obfuscate their code. Sadly, like every other LVL protected app I have seen, the protection can be patched out. Automatic obfuscation does not do much to hinder a would-be cracker. Tasker seems to have the best implementation of LVL I have found so far, and the developer was kind enough to share these tips:

- don't mention validation anywhere until it's necessary

- don't allow validation till after the refund period

- allow use of all features even when unvalidated

- start trying to validate automatically in the background after the refund period

- don't start nagging till a few days have passed without a successful background check

- don't block the program until a few days more have passed

- a single positive validation answer is enough, it's never checked again (unless completely uninstalled)

Another Android Developer at Google, RomainGuy, seemingly responded to my piece yesterday with an article over at GamaSutra on copy and crack protection. If you are interested in copy protection and crack prevention please give it read - not only is it very entertaining, but it's very informative as well. The article suggests that multiple layers of protection must be used, and that it is impossible to prevent cracking - it is only possible to make it not worth the pirates time.

All in all, the developers at Google have done a fantastic job with the Android Licensing Service. I am successfully using it in a commercial application and plan to continue using an implementation of it.

I will leave you developers with a simple trick I found to help add another layer of protection to your applications. Google has made it possible for developers to check how an application was installed, using PackageManager. The following code is a quick, incomplete example. It could be written better, and it is not fool proof. Pirates may just patch it out, or change packages.xml, but every little bit makes it harder. This example will only work on devices supporting API 5 and up, and may prevent users from using app backup software.

PackageManager pm = this.getPackageManager(); if (pm.getInstallerPackageName(pname) == null) { //Not installed from Android Market } else if (pm.getInstallerPackageName(pname).equals("com.google.android.feedback")) { //Appears to be installed from the Android Market }

Join the discussion over at Droid Forums!