2016-03-02

Privacy: Programmatically Identifying Developer Devices

It's due to the fact that app developers usually install their app many times. And, it's possible to watch for those app installs in Android.

Implementing an app that takes advantage of this requires ZERO permissions.

So, I've created two working proof-of-concept apps: One to programmatically identify developer devices, and one to identify those kinds of apps and stop them. Both are open source and can be found on GitHub, and the later one can be found on Google Play.

I'll explain shortly how this is done.

Imagine, if you are an app developer, then your device(s) can be programmatically identified and have special code ran for them and nobody else will experience the same issue or app changes.

TLDR: Notes for why this app might be useful (but still shouldn't be used):

Learn something new: More approaches to breaching privacy and protecting from that

Show resume to app developer(s) at a specific company

Run different app code (maybe crashes) for other developers, or for non-developer devices

The app works by listening for app installs in a `BroadcastReceiver`. The receiver can either be defined in the manifest or dynamically created and ran in a `Service`.

Both have their pros and cons.

The manifest method is reliable and doesn't require a running process, but it is easily detectable by reading the manifest.

The service method would require decompiling the app (doable, but a bit harder than just the manifest) in order to be identifiable, but it requires a running process and developers may not be running any other apps when developing, so it wouldn't be as reliable.

For this proof-of-concept version of IDD (identify-dev-device) app, with people only testing on their own devices, it shows a `Toast` when an app is installed, and it show a notification when an app is installed four times in one day. I felt this was enough times to catch mostly developers and not regular users. And, the count threshold and other configs can be easily updated for other ideas on how to best identify likely developer devices. Something else to also consider may be devices for CI (Continuous Integration), which may get 100s of app installs a day, and those CI devices may either be shared (and likely no other running apps) or personally-used devices.

Another method (thanks to Kevin) is to check the APK signature to see if it is for debug or release. Apps distributed through Google Play require a release signature.

AIDD: Anti Identify Developer Deviceapp

The AIDD app identifies apps like IDD, including itself, as being capable of identifying developer devices because it has the `BroadcastReceiver` watching for the app installs.

The AIDD app works in two different ways. You can either open the app and press the "Scan all apps" button or you can just let its receiver do the work and provide a notification anytime an app is installed (or updated) that can also watch app installs.

A notification will occur if one of the following intent actions is found in a receiver in the AndroidManifest:

When you click on the notification (or app after scanning), there will be a detail page showing a brief summary and the ability to view the manifest and open the system app info page to "force stop" the app. Once an app is stopped like this, then it won't be able to receive broadcasts. Screenshot:

But, currently this app does have a limitation. It only checks the manifest for the BroadcastReceiver declaring actions in the format of Intent.ACTION_PACKAGE_*. It doesn't address if an IDD app dynamically creates the receiver. So, nothing related to seeing the intent has to be added to the Manifest and the app won't be identified by AIDD. This may require decompiling the apps further and grepping for the string (dex to smali might be enough and quicker to scan).

Though, having said that, typically when I'm working on an app, I don't have any other apps running so that wouldn't be a problem. (Caveat: launcher and Google/Android systems)

Because of that limitation, it would be useful to require a declared permission in the manifest to make those apps easier to identify. For some reason there is a Manifest.permission.GET_PACKAGE_SIZE (can anybody answer why? I haven't used it before, but APK size would seem easy to get or not as consequential). So, there could be one for Manifest.permission.RECEIVE_PACKAGE_CHANGE or similar that encompasses the Intent.ACTION_PACKAGE_* group.

One way to make it harder to identify dev devices would be to send fake app install broadcasts from every app. Then, it may seem that every device is a dev device. Unfortunately, each of those `Intent.ACTION_PACKAGE_*` say "This is a protected intent that can only be sent by the system." (documentation). A SecurityException is thrown when it is tried: `java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.PACKAGE_REPLACED`

Going Forward

From experimenting with my own device, I found that many Google and system apps watch for app installations/changes. Probably too many, but AIDD doesn't provide the reasons why any apps are doing that.

There's probably a reason why 23 different apps on my device watch for app installs and updates. But, I only expected one because a file explorer app recently introduced a new feature to identify if an installed app has "dangerous" permissions.

All of this is just scratching the surface. There are still more possibilities that I haven't had time to check yet, and would possibly be even harder to detect, like having a FileObserver, checking APK signature, checking running processes, or checking for what's on the recent tasks. And, Android API 23 introduced Manifest.permission.PACKAGE_USAGE_STATS, which could also potentially be used for some apps. Though, for one of my apps, I know many people are running it 24/7, and for another older app, many people use it much more than I develop for it. So, usage of that permission to identify dev devices would depend more on the app type and update speed.

So to abruptly conclude.. I hope no apps are actively trying to identify developer devices, and now we have an app that can check (mostly). I'm happy to hear more ideas.

You can safely experiment with this yourself by running the sample identify-dev-device app, which the APK is in the repo or you can build it from the code. It doesn't have any internet permission, nor tries to circumvent that by using Intents.