I’ve been seeing posts lately in the wake of the LVL anti-piracy code being broken, with different methods on how to keep your Android package safe. Anti-piracy measures have always been fascinating to me, so I love diving into them and taking a look at what developers think are good and why. One of the latest crazes is using the PackageManager‘s “getInstallerPackageName” to verify whether or not the Market actually installed the apk file or not.
There are a few issues with this, though they are only minor issues depending on how you look at them;
- API call is a of the API Level 5, meaning it won’t reach all android users (Android 2.0 and up) – and “may not always work”
- It’s only a viable method if protecting for the Android Market
- It’s simply just something else for a pirate to patch, nothing too hard
- This prevents legitimate people from backing up the application, installing from without use of the Market, adb, etc.
It’s pretty self explanatory for the API level issue. If you want to target people below Android 2.0, then your can’t use this method to verify the installer source. It’s not going to be available, which may or may not be an issue depending on what other API’s you are targeting. On top of this though, it apparently doesn’t always work;
In a late edit, we removed a suggestion that you use a check that relies on GetInstallerPackageName when our of our senior engineers pointed out that this is undocumented, unsupported, and only happens to work by accident. –Tim (Securing Android LVL Applications – Android-Developers/Blogspot
Another issue that arrises from this method, is that it’s actually only set when being installed by the Android Market. If an application is not installed via the Market, attempting to retrieve this value will just return null. That’s ok right? Well, if you’d like to lock out customers who want to use this on multiple devices, or keep older versions of your application – then no it’s not. While this could be a small base of users, people may be purchasing your application and attempting to run it on a second Android device that doesn’t have access to the Market. Or possibly just using Astro File Manager to keep separate versions of your application – these would all be broken if you use this method, as once installing from anything but the Market happens, it will not return the correct value.
Ok, well if you don’t care about the rest of the cases so far and are willing to risk it, why bother? It may seem like your locking out a few legitimate users, but at this point you’ll probably lock out more legitimate users than you will pirates. Using any of the numerous tools out there, or even the ones bundling within the Android SDK can find you the function call to getInstallerPackageName, and quickly circumvent the check to see if what was returned was null or com.google.android.feedback.
So how can legitimate rooted users get around this annoyance? Well, I wouldn’t recommend it, but an easy way to get around this is simply editing your /data/system/packages.xml – inside this you will see the information for all the packages you have on your system. The actual important part you want to look at is the package header tag;
<package name=”com.package.example.name” codePath=”/data/app/com.package.example.name.apk” flags=”0″ ts=”1283990162000″ version=”25″ userId=”10066″ installer=”com.google.android.feedback”>
The tag in bold is only apparent when it is installed via the Market. If you don’t have this in something that needs it… You could add it. If you want to change it to turn a different value, well here is where you can add it. Oh – and obviously this would require root.
After looking a little bit deeper into this, I remember the trusty old “pm” command – which actually works around almost all these issues. By doing the following simple command via ADB you can set the installer to anything;
pm install -i installername com.example.package
This will perform an install setting the “installer” to whatever you’ve chosen it to be. No reboot required, or root privileges needed – just access via ADB.
Vending Assets Database; /data/data/com.android.vending/databases/assets.db
CREATE TABLE assets(
_id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id INTEGER UNIQUE,
Here is an example entry:
type: 1 (1 = app, 4 = game?)
Didn’t have much time as of lately to post, so I figured I’d drop this schema and an example entry on the blog. It shows how the Vending application stores “assets”. I’m still doing more research, but it looks like the previous “DRM” that we’ve mentioned isn’t the only security measure that will be in place. As you can see “is_forward_locked” is a field, though all applications I’ve run across have this disabled (both protected and unprotected). The “version_code” and “refund_timeout” also seem to not be used.
Well paid applications have officially rolled out, or rather – reached my phone through the android market. The first thing I wanted to find out, is what is the protection scheme used?! My first assumption is that it might be something tied to your account, or android id – something sort of like SlideLOCK which I previously mentioned. So after looking around the market I downloaded a few applications and I also decided to download some “protected” free applications. Mainly I wanted free applications to toy with, so I didn’t feel bad possibly violating paid ones
The programs I’ve started with where Inaugural Address 2009 and Phandroid News. Both are “protected” applications. What does this mean exactly? After a little digging it was clear exactly what “protected” actually meant;
So first I checked as you can tell, the SD card. Originally I was checking posts at xda-devs and someone posted that they where located on the SD card and where .zip files. This is false, the packages are .apk and located in the /data/app-private folder as you can see from the screen shot above. Well, what does this mean exactly? This means a non protected app, which is stored in /data/app can be pulled using adb, while a protected app is located in /data/app-private is not allowed to be pulled by adb.
Though… with a rooted phone – this isn’t exactly a problem since it can pull any file!
Alright, so what? Isn’t there some more protection involved in this?!
Sadly, that’s what I (wrongly) assumed too. What I assumed was that there would be some more protection other than just things being “protected” in a folder. Possibly, it being linked to the android id? Maybe it not being able to be installed on another device or through a “non-market” source. Or maybe the market would track it, since it does for updates on market installed applications… Well, sadly, no – no other protection seems to be present.
All “protected” applications can be dexdumped like a normal one, can be pulled (as long as you have a rooted phone), then reinstalled. The even worse part, is that protectd applications don’t stay in the protected folder when installed via a web download or adb install. They simply get pushed into the normal /data/app folder… Some protection huh? Oh, and my first assumption that the market might look for these also appears to be false. The market does not check any applications installed from an “unknown source” – so that idea for protection is a complete bust.
C:\Documents and Settings\tstrazze\Desktop\eclipse\android-sdk-windows-1.0_r1\t
ols>adb install phandroidnews.apk
374 KB/s (0 bytes in 1286982.003s)
C:\Documents and Settings\tstrazze\Desktop\eclipse\android-sdk-windows-1.0_r1\t
# cd data
# cd app-private
# cd ..
# cd app
What sort of makes this whole ironic deal even odder, is the refund policy. Within twenty-four hours of a download, you are allowed to uninstall and get a full refund of the product you purchased. So you could theoretically just rip all the applications you want, not that I am suggesting this at all.
Want to try this process? Well I’ve uploaded inaugural address to my site for testing. This is the protected application that is free on the market. As you notice it will install to the /data/app directory, not the /data/app-private directory. I’ve tested this process with multiple application on my rooted G1, and a friend also verified that installed “protected” applications through an unknown source also works on thier stock G1 (non-rooted). (If the author wants me to remove this, I will gladly do so – I just wanted an example and figured a free application/free service would not mind the attention)
So what are developers to do? Well, recently I bashed on the SlideLOCK in a previous post… Though – the more I looked at it, this seems like the best option for developers to protect their applications. Though, hopefully google will remedy this solution and fast. Until then though, strike-one google market.
Edit: The author of phandroid news asked me to remove his application, so I have. In it’s place I’ve uploaded the inaugural address 2009 application unless that author would like me to remove it.
Edit2: To clarify, I’ve tested this with a free PROTECTED application. This is NOT the same as a free non-protected application, at phandroid he shows what the step looks like to have a “protected” application opposed to a “non-protected” one. Also the protected applications appear to be identical to the paid applications, which are also protected.