Root Detection and Evasion
In this article, we will look at the techniques being used by Android developers to detect if a device on which the app is running is rooted or not. There are good number of advantages for an application in detecting if it is running on a rooted device or not. Most of the techniques we use to pentest an Android application require root permission to install various tools and hence to compromise the security of the application.
Many Android applications do not run on rooted devices for security reasons. I have seen some banking applications check for root-access and stop running if the device is rooted. In this article, I will explain the most common ways being implemented by developers to detect if the app is rooted and some of the bypassing techniques to run the app on a rooted device.
Common techniques to detect if the device is rooted
Let’s begin with the most common techniques being used in the most popular applications to detect if the device is rooted.
Once a device is rooted, some new files may be placed on the device. Checking for those files and packages installed on the device is one way of finding out if a device is rooted or not. Some developers may execute the commands which are accessible only to root users, and some may look for directories with elevated permissions. I have listed few of these techniques below.
Superuser.apk is the most common package many apps look for in root detection. This application allows other applications to run as root on the device.
Many applications look for applications with specific package names. An example is show below.
The above screenshot shows a package named “eu.chainfire.supersu”. I have seen some apps from the Android market verifying if any application by “chainfire” is running on the device.
There are some specific applications which run only on rooted devices. Checking for those applications would also be a good idea to detect if the device is rooted.
Busybox is an application which provides a way to execute the most common Linux commands on your Android device.
Executing “su” and “id” commands and looking at the UID to see if it is root.
Checking the BUILD tag for test-keys: This check is generally to see if the device is running with a custom ROM. By default, Google gives ‘release-keys’ as its tag for stock ROMs. If it is something like “test-keys”, then it is most likely built with a custom ROM.
Looking at the above figure, it is pretty clear that I am using a stock Android ROM from Google.
The above mentioned techniques are just a few examples of what a developer may look for in order to identify if a device is rooted. But there could be other ways around for root detection which are not mentioned here in this article.
Bypassing root detection — Demo
In this section, we will see how one can bypass one of the root detection mechanisms mentioned above. Before we begin, let’s understand the background.
Download the application from the download section of this article and run the app on your device and click the button “Is my device rooted?” Since I am running it on a rooted device, it says “Device Rooted”. Now, our job is to fool the application that this device is not rooted.
Now, let’s begin.
Understanding the app’s functionality
Let’s first understand how this app is checking for the root access. The code inside this application is performing a simple check for Superuser.apk file as shown in the screenshot below.
As we can see in the above figure, the app is checking if there is a file named “Superuser.apk” inside the “/system/app/” directory. If it exists, then we are displaying the message “Device Rooted”. There are various ways to bypass this detection.
Let us first reconfirm manually if the device is rooted by executing “su” and “id” commands.
Let’s see if the “Superuser.apk” file is located in the path being checked by our target app.
To bypass this check, let’s rename the application “Superuser.apk” to “Superuser0.apk” as shown in the figure below.
As we see in the above figure, we may get an error message saying it’s a read-only file system. We can change it to read-write as shown in the next step.
Changing permissions from Read-Only to Read-Write:
The following command will change the file system permissions to “Read-Write”.
Now, if we rename the file to “Superuser0.apk”, it works fine as shown in the figure below.
If we now go back to the application and click the button “Is my device rooted?”, it shows a message as shown in the figure below.
This is just an example of how one can bypass root detection if it is not properly implemented. Applications may use some complex techniques to stop attackers from bypassing root detection. The techniques will change depending on how the developer is checking for root access.
For example, if a developer uses the following code snippet to check for root, the procedure to bypass the detection is different:
In this case, we would need to make our own “su” binary and “superuser” apk.
Developers who stop users from running their apps on rooted devices could be a good idea from a security perspective, but this is really annoying to a techie user who is not able to execute the app only due to the reason that he has rooted his device. Rooting techniques can be bypassed easily most of the time, and it is highly recommended that developers should use complex techniques in order to stop attackers from bypassing their validation controls.