I'm writing an application that must not run on rooted devices. I want to store some secure data and which is possible only on non-rooted devices as nobody can access files in /data/data/package-name.
Does anyone know:
1) Is it possible to prevent the installation of an application on rooted devices? I read something about the "copy-protection mechanism" of Android Market. This feature seems to be outdated and replaced by the licensing feature. However, licensing is only possible for paid application and mine is free...
2) Is it possible to check programmatically whether a device is rooted or not? If it would be possible to do so I could simply stop the application if the device is rooted.
Any help regarding this topic is appreciated!
Execute
Runtime.getRuntime().exec("su");
and check the result code.
In other words, if you can exec su, then you have root access. it doesn't matter if the user allows or denies it, you have your answer.
I think your approach is a bit flawed. First of all, the user can first install your application and data, then "root" the device (even if rooting wipes the data, one can make the backup first). Next, the general rule is that whatever is in user's hands is not yours anymore. The hacker will find a way to get to your data sooner or later.
If you care about secure data, don't put it to device. As Android is net-centric device (yes, I know, that's subjective, but it was initially developed and positioned as such), accessing the data online is not uncommon.
What I would say is to run su and then check the output. If the user allows your app to have root, then use root to uninstall your own application (one way might be to place a script into init.d and then force a reboot).
If the user DOES NOT allow your app to run as root, then:
They DENIED your app permissions.
They are not rooted.
Now, denying permissions (and rooted) means that they have some sort of SUPERUSER management app, and that's where this next part comes in.
I would then proceed to use PackageManager to retrieve a list of all packages and then check them against the handful SuperUser management apps available, namely the ones by Koush, ChainsDD, and Chainfire
The relevant package names are:
com.noshufou.android.su
eu.chainfire.supersu
com.koushikdutta.superuser
Use those methods which will help you check for root
public static boolean findBinary(String binaryName) {
boolean found = false;
if (!found) {
String[] places = { "/sbin/", "/system/bin/", "/system/xbin/",
"/data/local/xbin/", "/data/local/bin/",
"/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/" };
for (String where : places) {
if (new File(where + binaryName).exists()) {
found = true;
break;
}
}
}
return found;
}
private static boolean isRooted() {
return findBinary("su");
}
Now try to check whether the device is rooted.
if (isRooted() == true){
//Do something to prevent run this app on the device
}
else{
//Do nothing and run app normally
}
For example you can force stop the app if the device is rooted
If you are trying to protect data for the user, it's their business to worry about other apps.
If you are trying to protect data from the user, what business do you have putting it on their device?
To answer your question, they are in control of the machine so expect them to be able to trap any call to an API checking 'Is this rooted?' and lie to you. Instead, encrypt the data on the client with a key known to the client, but make it non-obvious where and how you are doing it. Generally make things annoying for whoever is looking.
Enjoy the ensuing game of whack-a-mole. Every time someone cracks into it, you'll make a better fix, they'll make a better crack, and all along the way you will be raising the barrier for cracking it.
Don't fight against freedom - why should you turn away customers with free devices anyway? - instead, if you want a particular outcome, make it so Bother To Get Data > Value Of Getting Data. Then it won't happen. If you truly must have fool-proof security, keep the data server-side.
I believe that one of the 'drawbacks' of the traditional copy protection was that it did not allow the application to be installed on rooted devices, but it also has its own share of problems and will be deprecated soon.
As for client-side checks, you simply cannot rely on a programmatic approach to detect if you're running on a rooted device or not -- anything that is in client-side code can and will be hacked and removed. You'd be surprised at how easy it is to modify even Proguard-obfuscated code. At best, you force the hacker to spend a few hours or days to edit the code and recompile. This is security through obscurity, and not a viable protection mechanism.
1) no. how would you deny installation? why would a rooted device deny installation of something the user wants to install on the fs? being the whole point of rooting that you can make the device do basically whatever.
2) no. not for your purposes. you can check if you can gain root for your application through the usual methods. so you can make a check for a positive but you cannot prove programmatically that it is not rooted, from within your app.
also, what you are asking if you can make perfect copy protection drm system - you might also be missing the point that the user can alter your application, removing your root check. if you have a checksum/crc check of some kind, the user can fake the result of that as well.
Related
I need to update multiple applications installed on many Android devices.
Is there anyway to put theirs updated apks on USB flash drive, write some script that updates them and run this script manually after I plug it to the device?
I guess the most basic question would be why? Is this something you are purposely keeping off the app store? If it is not TOS breaking just pay the 25$ for a dev account and you can even just keep it in a beta/alpha status so only people you allow to can download it.
Beyond that Android phones can install APK's from third party sources, host the APK somewhere or get it to the user in some fashion and they can download from the phone and install.
Really the app store is your best bet.
It really depends on your use case and control of the devices that you are updating. Using an OTA update tool is always the fastest option for getting upgrades out. You can use BETA distribution, or TestFairy, or even hockey app, however, if you are not choosing to use these items then you will need to do a little extra leg work. Don't worry I won't patronize you with "why are you doing this", you asked a question so I'll do my best to answer it.
1) Register a service or app who's whole goal is to update others. Maybe you call it updateService.
2) Register a Broadcast Receiver for the updateService that listens for USB connected
3) Read the contents of the USB stick to know what needs to be updated. Possibly a folder system where you check "if folder exists, then update" or you can keep a local sql db of update service ownership that keeps track of last updates or current versions.
4) Once you see what needs installed have your service run ADB Install commands. However, if you have new permissions added then user interaction would be required unless you have root access or system level privelages on your update service.
Here is a package installer thread that will give you some ideas of how to silently update. Install apps silently, with granted INSTALL_PACKAGES permission
So the short answer is, yes you can do it, but the longer answer is revolving around the type of control you have, and if you have root or system level access and how much leg work is it worth to you. If you are ok with User Interactions on install then you won't have to worry as much, but I'm guessing you want silent installations.
Hope that helps.
I understand that when you install an android app you need to accept the permissions requested by the app. When you run the app, when it comes to the point that app really about to use that permission and perform a task, the android system has to check again "whether this app is allowed to perform this task?". I need to perform some task (log the event) at this moment. How can I do this?
There is a catch. I want to identify these instances (moments) for other running apps (not for my app)
(Ex: I want to know when DropBox app is about to access the internet.)
I need to perform some task (log the event) at this moment. How can I do this?
You can download the Android source code, modify it to incorporate your desired security flaw, compile the results into a ROM mod, and install that ROM mod on your own device.
This is not possible via the Android SDK.
There is a catch. I want to identify these instances (moments) for other running apps (not for my app) (Ex: I want to know when DropBox app is about to access the internet.)
You are welcome to install and use a firewall package on your rooted Android device and perhaps hook something up that way, for this specific scenario. In general, what you seek is not possible, for blindingly obvious privacy and security reasons.
I wish to know is it possible to write an android app that when it runs at the background, it can track user activities?(Such as what other app did the user used, what phone number did user dial, the GPS location for user, etc) Cause I am not sure can a single android app react to other application, does anyone know the answer? Thanks
In the general case, no, you can't. And users would probably prefer it so.
Once this has been said, there are certain partial solutions. Sometimes the system is so helpful that it will publish Intents reflecting user actions: for example when the user uninstalls an app -- with the caveat that you don't get that intent on the app itself being uninstalled.
It used to be the case that before Jelly Bean (4.1) apps could read the log that other applications publish and try to extract info from there, but it was a cumbersome, error prone, ungrateful task. For example, the browser shows nothing when it navigates to a certain page. You may read the logs for a while with adb logcat to get a feeling of what was possible and what isn't. This action requires the relevant permission, which cannot be held by regular apps now.
Thanks to #WebnetMobile for the heads up about logs and to #CommonsWare for the link, see the comments below.
Yes you can.
You can look here for instance about phone info:
Track a phone call duration
or
http://www.anddev.org/video-tut_-_querying_and_displaying_the_calllog-t169.html
There is a way to let Android and users know you are using and accessing their data for them to determine if they will allow it.
I am unsure you can simply access any app, but in theory if you know how to read the saved files that might be possible.
For instance Runtime.getRuntime().exec("ls -l /proc"); will get you the "proc" root folder with lots of data you might need there. This might have been changed, I am not sure, and I also don't know what you need.
Perhaps to get running process try:
public static boolean getApplications(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
}
For this to work you should include this in your AndroidManifest.xml
<uses-permission android:name="android.permission.GET_TASKS" />
See more about it: http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses%28%29
You certainly could but I think reporting that data back to you, unbeknownst to the user, via the internet, would be considered spyware and almost certainly illegal in most jurisdictions.
Fortunately spying users at that level should not be possible. Certain features can be achieved with abusing bugs in android which sooner than later will be fixed. I see absolutely no reason for you to know what number I am calling and where I've been lately. It's basically none of your business.
This question already has answers here:
Is it possible to detect Android app uninstall?
(8 answers)
Perform a task on uninstall in android [duplicate]
(4 answers)
Closed 7 years ago.
I though it was not possible but I noticed that NQ Mobile Security is able to show a message after I click on Uninstall and before the PackageUninstaller is called.
I would like to replicate this behavior in my App.
I tried with an Activity listening to "android.intent.action.DELETE" Intent, as suggested here:
How to know my app is uninstalled from the device...?
But as I'm about to uninstall my app, the chooser pops up asking to pick my application or the package uninstaller. How can I avoid this?
Is there a different way to intercept your application UNINSTALL event? (before answering that it is not possible, please try to uninstall NQ Mobile Security and see what happens. On my Android 2.3.4 it shows a nice screen saying that is not safe to go without a security app).
I noticed that NQ Mobile Security is able to show a message after I click on Uninstall and before the PackageUninstaller is called
They must be exploiting some security flaw in Android. I will research it and see if I can get it fixed. Apps are not supposed to get control at uninstall time.
Thanks for pointing this out!
Is there a different way to intercept your application UNINSTALL event?
I sure hope not.
Opera Max is an app that does something similar - after being uninstalled opens a webpage.
How do they do this?
By using libevent, from native code, they watch /data/data/com.opera.max directory to be removed and then post good old action.VIEW broadcast when it happens.
Install their app, run it, and on rooted device from adb shell remove /data/data/com.opera.max directory
UPDATE: I created a sample app that shows how it works. BTW it doesn't work with recent (KitKat+ I think) Android versions: https://github.com/pelotasplus/ActionAfterUninstall
I'm pretty sure that they are monitoring the LogCat to intercept when the Activity Manager calls the PackageUninstaller. I think they kill the task and start their own Activity.
It's pretty clever but it's definitely exploiting a security hole in Android.
They are likely asking for a very critical permission that the user is granting them unknowingly. Look at the "Permissions" tab for this app (as of 6/15/2012): https://play.google.com/store/apps/details?id=com.nqmobile.antivirus20&hl=en.
The list of permissions this app gets is downright chilling. Among other things:
SYSTEM TOOLS RETRIEVE RUNNING APPS Allows the app to retrieve
information about currently and recently running tasks. Malicious apps
may discover private information about other apps.
CHANGE/INTERCEPT NETWORK SETTINGS AND TRAFFIC Allows the app to change network settings
and to intercept and inspect all network traffic, for example to
change the proxy and port of any APN. Malicious apps may monitor,
redirect, or modify network packets without your knowledge.
PREVENT TABLET FROM SLEEPING PREVENT PHONE FROM SLEEPING Allows the app to
prevent the tablet from going to sleep. Allows the app to prevent the
phone from going to sleep.
CHANGE YOUR UI SETTINGS Allows the app to
change the current configuration, such as the locale or overall font
size.
MODIFY GLOBAL SYSTEM SETTINGS Allows the app to modify the
system's settings data. Malicious apps may corrupt your system's
configuration.
DISPLAY SYSTEM-LEVEL ALERTS Allows the app to show
system alert windows. Malicious apps may take over the entire screen.
MOUNT AND UNMOUNT FILESYSTEMS Allows the app to mount and unmount
filesystems for removable storage.
CHANGE NETWORK CONNECTIVITY Allows
the app to change the state of network connectivity.
CHANGE WI-FI STATE Allows the app to connect to and disconnect from Wi-Fi access
points, and to make changes to configured Wi-Fi networks.
-- Update --
I also found that the Android Package Manager pretty much just deletes a package if it is asked to do so. The only check it performs prior to doing so is whether the package being deleted is currently registered as having an active device admin:
try {
if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}
} catch (RemoteException e) {
}
See line 6900 in PackageManagerService in the AOSP source here.
For this, the application must be explicitly registered as a device admin by the user. See notes on device administration here: http://developer.android.com/training/enterprise/device-management-policy.html.
As per https://stackoverflow.com/a/26829978/1317564, here is some example code that does it: https://github.com/zzljob/android-uninstall-feedback/blob/master/library/jni/feedback-uninstall.c. This won't actually stop the uninstall from taking place, but does provide a way to catch it and take some action. I'm honestly surprised that this works in Android and the team may have plugged the gap in recent releases.
I notice that (too) many applications on my Android phone require full internet access. In some cases, it seems like they just want to connect to some service. In other cases, it is clear they are phoning home. However, it seems like users have no easy way of checking which one is the case.
I realize that in the manifest permissions for Android there is a "android.permission.INTERNET", but is there a way to say "this application will only access some.domain.org", and maybe specify which protocols will be used, or something like that? Could the Android system enforce that somehow?
As far as I know, android.permission.INTERNET is the most specific you can get. I agree that it would be nice to be able to specify that my app only talked to an individual server, but in the end it wouldn't tell the user anything meaningful, since most protocols can be tunneled and proxied over most other ones with sufficient ingenuity.
The android UI devs decided to go with the broader permission rather than confusing regular users by displaying information that would not be functionally meaningful. As an alternative, you might consider including a note in either your application description or a popup immediately after installation that explains precisely how and why your application accesses the internet.
Edit:
You might be able to circumvent that permission altogether if you only wanted one-way messaging to the phone and did something excessively clever with C2DM. This would be a bad thing to do, however, and I haven't verified that it would actually work without that permission.