Over a million developers have joined DZone.

Android LVL Obfuscation Pitfalls

DZone's Guide to

Android LVL Obfuscation Pitfalls

· Mobile Zone
Free Resource

Discover how to focus on operators for Reactive Programming and how they are essential to react to data in your application.  Brought to you in partnership with Wakanda

The recently-introduced Android License Verification Library (LVL) survived a disappointingly short time in the wild before somebody figured out how to circumvent its protection. Google responded to this development by stating that it was the lack of obfuscation that had made the crack so straightforward and then followed up with further advice on achieving security through obscurity, effectively acknowledging that there is no robust way of doing licence verification that can’t be bypassed.

Unfortunately, the LVL is pretty much the only option for protecting apps sold via the Android Market (other app stores have their own protection mechanisms). The choice for Android developers is mediocre protection or no protection at all (Google apparently intends to withdraw its previous copy protection mechanism).  You can thwart the most casual Android pirates and make things harder for the determined but that’s about as good as it gets.

Obfuscating LVL-protected Apps with Proguard

Assuming that you choose to add the LVL to your app, you’ll no doubt want to follow Google’s advice and obfuscate your code, probably using Proguard. If you do, you might hit a couple of problems that prevent the LVL from working properly.

I added the LVL source to my application and built it as a single entity but it is also possible to incorporate the LVL as a library project.

Disable Aggressive Overloading

The first problem I encountered was a limitation in the Dalvik VM. Unlike the JVM, it does not (did not?) permit static fields of different types to have the same name.  In normal Java development this situation never arises but Proguard has an option to aggressively overload names to make decompilation more difficult. For Android development this option should not be used otherwise you will get VerifyErrors.

Avoid Renaming the ILicensingService Intent

The checkAccess method of the LVL’s LicenseChecker class binds to the licensing service as follows:

boolean bindResult = mContext.bindService(
    new Intent(ILicensingService.class.getName()),
    this,  // ServiceConnection.

The problem with calling ILicensingService.class.getName() is that, after obfuscation, the class has a different name and therefore the wrong intent is created. This will show up in the log as an error with the message “Could not bind to service” and the licence check will always fail.

You could fix this by modifying the Proguard configuration to avoid renaming the ILicensingService interface or, even more straightforwardly, you could just modify the code in LicenseChecker and hard-code the appropriate action:

boolean bindResult = mContext.bindService(
    new Intent("com.android.vending.licensing.ILicensingService",
    this,  // ServiceConnection.

Learn how divergent branches can appear in your repository and how to better understand why they are called “branches".  Brought to you in partnership with Wakanda


Published at DZone with permission of Dan Dyer. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}