Is Your Android Rooted? Detect With These 6 Proven Ways

Phone manufacturers and mobile network operators often implement stringent software restrictions for security reasons. However, these constraints can be circumvented by rooting your Android phone. 

Rooting is the process of gaining access to more administrative-level controls on an Android device. Despite its benefits, attackers often use rooting to target sensitive user and business data.

According to security experts, 36 out of 1000 Android devices are rooted globally. Because a rooted device is considerably more vulnerable to attack, it's critical to use tools that can detect this vulnerability. To ensure that your apps only run where, when, and how you want them to, you must first determine whether the device is rooted.

What is Rooting? 

Android is very similar to Linux in that it runs on the Linux kernel. With access control similar to Linux, regular users of Android devices have very limited permissions compared to users who have rooted their devices.

Without rooting, users cannot access or modify system files and folders. Once rooted, the user has full access to the device. Rooting allows the user to make changes to everything on the device. This allows users to do things that were previously impossible, like removing bloatware, customization, custom ROMs, etc. 

What do We Need Root Detection for?

In addition to the benefits of rooting Android devices, many security issues are also associated with it. Once you have root privileges, you have full control to make changes across the device. But this also means your device is now an open target for threat actors.

Rooted devices may contain many apps that process sensitive information, such as banking apps, payment apps, social media, and cloud storage. Malicious downloads can expose your device to hackers. For these reasons, the apps installed on a device need to make sure that the device isn't rooted. This acts as a precautionary measure to protect critical user and business information data. 

Top 6 Methods for Root Detection

To acquire access to sensitive user data and other insights housed in an app's source code, hackers frequently root devices or take advantage of devices that have been rooted by the owner. Because it is difficult to guarantee system security and other measures after the root, detecting this vulnerability is critical to keeping apps safe.

Let us take a look at some of the most commonly used root detection methods:

1) SU Binary Files And Packages

There are a lot of files and packages on android devices that can be checked in order to determine if the device is rooted or not. This might include the packages for the apps that are used to root the device such as "eu.chainfire.supersu" and "com.topjohnwu.magisk". The presence of apps with such package names shows the presence of root on the Android device.

The below piece of code detects if any of the mentioned packages is present on the device or not. 

static final String[] knownRootAppsPackages =
"com.noshufou.android.su"

 "com.noshufou.android.su.elite"

 "eu.chainfire.supersu"

 "com.koushikdutta.superuser"

 "com.thirdparty.superuser"

 "com.yellowes.su"

 "com.topjohnwu.magisk"

 "com.kingroot.kinguser"

 "com.kingo.root"

 "com.smedialink.oneclickroot"

 "com.zhiqupk.root.global"

 "com.alephzain.framaroot" 

}; 

public static boolean checkRootFilesAndPackages(Context context) { 

 boolean result = false

 for(String string1: knownRootAppsPackages) { 

    if(isPackageInstalled(string1, context)) { 

       result = true

       break;

        

 } 

 return result;  

private static boolean isPackageInstalled(String packagename, Context context){

   PackageManager pm = context.getPackageManager(); 

 try {    

    pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);  

    return true

 } catch (NameNotFoundException e) { 

    return false

 } 

}

Below piece of code tries to find SU binary in commonly found locations. 

static final String[] knownSUPaths =

 "/system/bin/su"

 "/system/xbin/su"

 "/sbin/su"

 "/system/su"

 "/system/bin/.ext/.su"

 "/system/usr/we-need-root/su-backup"

 "/system/xbin/mu" 

}; 

public static boolean checkSUPaths() { 

 boolean result = false

 for(String string1: knownSUPaths) { 

    File f = new File(string1); 

    boolean fileExists = f.exists(); 

    if (fileExists) { 

       result = true

    } 

 } 

 return result;  

}

 

2) Custom ROMs

a) Build Tags

A check can be implemented to test against custom ROMs on the Android device. We can achieve this by checking build tags. Usually, when a kernel is compiled by a third party, instead of the release-keys, we can find test-keys in the build tags. Being compiled by a third party shows the presence of custom ROM on the Android device.

The following code can be used to detect if the build has test-keys or release-keys. 

 

public boolean checkCustomOS(){ 

 String buildTags = android.os.Build.TAGS

 if (buildTags != null && buildTags.contains("test-keys")) { 

    return true

 } 

 return false

 

jasmine_sprout:/ # cat /system/build.prop | grep ro.build.tags 

ro.build.tags=release-keys 

jasmine_sprout:/

 

b) Google OTA Certificates 

Along with the build tags, looking for Google Over-The-Air certificates is another way of detecting if it is a stock Android build or a custom ROM. The following command can detect if the OTA certificates are present on the device or not. 

 

public static boolean checkOTACerts() { 

 String OTAPath = "/etc/security/otacerts.zip"

 File f = new File(OTAPath); 

 boolean fileExists = f.exists(); 

 if (fileExists) { 

    return true

 } else

    return false

 }  

 

jasmine_sprout:/ # ls -l /etc/security/otacerts.zip 

-rw-r--r-- 1 root root 1536 2009-01-01 05:30 /etc/security/otacerts.zip

jasmine_sprout:/

3) Checking for Dangerous Props 

The build.prop file on an Android device contains system properties and build information that are applied throughout the operating device. Properties are stored in key-value pairs. The file is stored in the /system folder and it is loaded every time the device is booted.

Some custom builds/rooting apps modify the build.prop on the Android device and modify some of the properties that can only be done by a root user.

We can use the following code in our app to detect if the properties are modified or not. Some of the properties that are usually modified are ro.debuggable and ro.secure.

private String[] propsReader() { 

 try

    InputStream inputstream

Runtime.getRuntime().exec("getprop").getInputStream(); 

    if (inputstream == null) return null

    String propVal = new Scanner(inputstream).useDelimiter("\\A").next();   

    return propVal.split("\n"); 

   } catch (IOException | NoSuchElementException e) { 

    QLog.e(e); 

    return null;  

 } 

public boolean checkForDangerousProps() { 

 final Map<String, String> dangerousProps = new HashMap<>();   

 dangerousProps.put("ro.debuggable", "1"); 

 dangerousProps.put("ro.secure", "0"); 

 boolean result = false

 String[] lines = propsReader(); 

 if (lines == null){ 

    return false

 } 

 for (String line : lines) { 

    for (String key : dangerousProps.keySet()) { 

       if (line.contains(key)) { 

          String badValue = dangerousProps.get(key); 

          badValue = "[" + badValue + "]"

          if (line.contains(badValue)) { 

             QLog.v(key + " = " + badValue + " detected!");            

             result = true

          } 

      } 

   } 

return result

}

We can also use the following command to check the same from a shell. 

adb -e shell getprop | grep -E "secure|dashboard" 

4) Common Apps Found On Rooted Device 

Another common way used by security experts for root detection is to search for applications that are commonly found on a rooted device. Some of such examples are Busyboy, Titanium Backup, Xposed Manager, Luckypatcher. 

public static final String[] knownDangerousAppsPackages =

 "com.koushikdutta.rommanager"

 "com.koushikdutta.rommanager.license"

 "com.dimonvideo.luckypatcher"

 "com.chelpus.lackypatch"

 "com.ramdroid.appquarantine"

 "com.ramdroid.appquarantinepro"

 "com.android.vending.billing.InAppBillingService.COIN"

 "com.android.vending.billing.InAppBillingService.LUCK"

 "com.chelpus.luckypatcher"

 "com.blackmartalpha"

 "org.blackmart.market"

 "com.allinone.free"

 "com.repodroid.app"

 "org.creeplays.hack"

 "com.baseappfull.fwd"

 "com.zmapp"

 "com.dv.marketmod.installer"

 "org.mobilism.android"

 "com.android.wp.net.log"

 "com.android.camera.update"

 "cc.madkite.freedom"

 "com.solohsu.android.edxp.manager"

 "org.meowcat.edxposed.manager"

 "com.xmodgame"

 "com.cih.game_cih"

 "com.charles.lpoqasert"

 "catch_.me_.if_.you_.can_" 

}; 

public boolean detectPotentiallyDangerousApps(String[] additionalDangerousApps) {

 ArrayList<String> packages = new ArrayList<>(); 

 packages.addAll(Arrays.asList(Const.knownDangerousAppsPackages));

 if (additionalDangerousApps!=null && additionalDangerousApps.length>0){

     packages.addAll(Arrays.asList(additionalDangerousApps)); 

 }

 return isAnyPackageFromListInstalled(packages); 

Similarly, we can also use the shell to confirm some of the apps too. For example, the command below can be run to see if Busybox is present or not. 

busybox pwd 

5) Unusual Permissions For Partitions And System Directories 

Sometimes when a device is rooted, the permissions on some of the system directories change. By default, the system files and folders on Android devices are mounted as read only. Once the device is rooted, we can find some files and folders with read-write permissions. We can check the permissions on the system directories to figure out if the device might have been rooted.

Following are some of the directories that we can check for permissions. 

/data 

/system 

/system/bin 

/system/sbin 

/system/xbin 

/vendor/bin 

/sys 

/sbin 

/etc 

/proc 

/dev 

Below is a perfect piece of code that checks for permissions on specific folders based on the SDK version of the software. 

public boolean checkForRWPaths() {

 boolean result = false

 String[] lines = mountReader(); 

 if (lines == null){ 

     return false

 } 

 int sdkVersion = android.os.Build.VERSION.SDK_INT

 for (String line : lines) { 

     String[] args = line.split(" "); 

     if ((sdkVersion <= android.os.Build.VERSION_CODES.M && args.length < 4|| (sdkVersion > android.os.Build.VERSION_CODES.M && args.length < 6)) { 

         QLog.e("Error formatting mount line: "+line); 

         continue

     } 

     String mountPoint

     String mountOptions

     if (sdkVersion > android.os.Build.VERSION_CODES.M) { 

         mountPoint = args[2]; 

         mountOptions = args[5]; 

     } else

         mountPoint = args[1]; 

         mountOptions = args[3]; 

     } 

     for(String pathToCheck: Const.pathsThatShouldNotBeWritable) {                  

        if (mountPoint.equalsIgnoreCase(pathToCheck)) { 

            if (android.os.Build.VERSION.SDK_INT

android.os.Build.VERSION_CODES.M) { 

                mountOptions = mountOptions.replace("(", "");              

                mountOptions = mountOptions.replace(")", ""); 

            }

            for (String option : mountOptions.split(",")){ 

                if (option.equalsIgnoreCase("rw")){ 

                    QLog.v(pathToCheck+" path is mounted with rw permissions! "+line); 

                    result = true

                    break

                } 

            } 

        } 

     } 

 } 

 return result

}

6) Checking For Commonly Used Root Cloaking Apps 

There are a lot of root cloaking apps available that can hide the root status of an Android device so that other apps won't be able to detect if the device is rooted or not. We can list all the packages and search for the commonly used root cloaking apps.

Below code is an example of code that can detect root cloaking apps installed on the device. 

public static final String[] knownRootCloakingPackages =

 "com.devadvance.rootcloak"

 "com.devadvance.rootcloakplus"

 "de.robv.android.xposed.installer"

 "com.saurik.substrate"

 "com.zachspong.temprootremovejb"

 "com.amphoras.hidemyroot"

 "com.amphoras.hidemyrootadfree"

 "com.formyhm.hiderootPremium"

 "com.formyhm.hideroot" 

}; 

public boolean detectRootCloakingApps(String[] additionalRootCloakingApps){

   ArrayList<String> packages = new ArrayList<> 

(Arrays.asList(Const.knownRootCloakingPackages)); 

   if (additionalRootCloakingApps!=null && additionalRootCloakingApps.length>0){

     packages.addAll(Arrays.asList(additionalRootCloakingApps));

 } 

 return isAnyPackageFromListInstalled(packages); 

private boolean isAnyPackageFromListInstalled(List<String> packages){

    boolean result = false

 PackageManager pm = mContext.getPackageManager(); 

 for (String packageName : packages) { 

     try

         pm.getPackageInfo(packageName, 0); 

         QLog.e(packageName + " ROOT management app detected!");

         result = true

     } catch (PackageManager.NameNotFoundException e) { 

         // Exception thrown, package is not installed into the system 

     } 

 return result

}

Final Thoughts

From a security standpoint, developers that prevent users from running their apps on rooted devices may be a smart idea, but this becomes extremely inconvenient for users who are unable to execute the app only because they had rooted their device. The majority of the time, rooting techniques can be readily bypassed, hence it is highly advised that developers utilize sophisticated techniques for root detection and prevent attackers from bypassing their validation measures.

 

Published on Apr 27, 2022
Ajay Pandita
Written by Ajay Pandita
Ajay Pandita is a Penetration Tester working as a security analyst. Ajay specializes in performing pen tests on Android, iOS, and Web applications. He is OSCP certified and aims to become a Red Teamer. His journey started from web development and system administration and has 10+ years of experience in Linux. Alongside work, he spends his time doing CTFs. He also enjoys playing racing games and is a big fan of Red Bull F1 racing.

Questions?

Chat With Us

Using Other Product?

Switch to Appknox

2 Weeks Free Trial!

Get Started Now