Gotta catch the root!

For security reasons, some applications block users who’ve made modifications to the system. Let’s explore how those applications do this.

Florian Le Ficher
Nov 20, 2018 · 8 min read

I am root

The root on Android is like jailbreak ☠️ on iOS but far more powerful. Usually, iOS users jailbreak their devices to install unofficial applications. On Android, it’s feasible without root by checking an option in the security parameters 🔐.

The root is a modification of the system that allows the user to execute commands with root privileges, same as on Linux systems.

On Android, the root brings a lot of possibilities by giving all the rights on the device to the user. With it you can:

  • Uninstall preinstalled bloatware apps
  • Install a custom version of Android (or custom ROM) like LineageOs to get the latest version of Android if the manufacturer doesn’t provide updates anymore. Paradoxically, it improves the security by allowing you to install the last security patches
  • Install another Operating System
  • Apply some system tweaks, overcloking the CPU or advanced theming
  • Cheat on mobile games 🎮

But with great power comes great responsibility, and the root can damage your device if you don’t know what you’re doing. Most of the time, rooting a device is a complex operation so it should be reserved for advanced users.

You may understand why some developers don’t want users to have access or to alter their applications data and for user security reasons. Indeed, the root can bring about security breaches if used improperly.

Use case: Pokemon GO

The Pokemon Go game on mobile was quite a success. It has been developed by Niantic, the same who developed Ingress (another great non-battery friendly game).

A few weeks after it was released, some devices indicated an error, saying the device was not compatible with the game:

I hoped i could have been the very best…

I was one of those who rooted my device, so I could no longer play on my new phone. Such a disappointment.

Why this restriction? There were a lot of people cheating on this game to fake their location or using scripts to get the positions of pokemons everywhere (even without being on the game) which caused the game to go down because of an overload, and preventing other users from playing.

Other applications also take such precautions as a security measure, like Google Pay or some other bank apps.

How to dodge it?

I was not about to give up. And in my search for a way to play again, I found a magic solution.

Magisk Manager is an app that can be used to make a rooted device undetectable by applications. It changes the way the root works by completing the root process “systemless-ly”, which means that it doesn’t alter the system partition anymore.

The Magisk Manager app

You can choose which apps you want to hide the root from the Magisk Hide item in the burger menu. If you try to enable this option on an app that blocks root such as Google Pay, it works.

Let’s try on Pokemon Go now:

Root is now hidden for this app

And then, launch the app:

why ?

Damn, why? There’s a simple reason: This app and many others make a SafetyNet check to detect if the device has been modified. You can check if your device passes this test by downloading one of those apps on the Playstore.

To simplify, SafetyNet is a solution made by Google to check if the device can be trusted or not. This includes detecting root and other kinds of system modifications (eg: having your bootloader unlocked or when using an emulator). If your device passes the certification you’re good to go.

Ok but why Pokemon Go is still blocking me?

Well, the app is doing a simple trick to do it. First, let’s see how we can reproduce the root detection.

Capture techniques

In this part, we will try to find a way to reproduce how the Pokemon GO app detects the device modifications.

First try: looking for a library

  • SuperUser 💀

Let’s start with a simple solution by using the superuser library from Chainfire.

This library allow us to run commands with superuser privileges but also to check for the su binary availability. This is done by calling a simple static method: Shell.SU.available()

As it’s a blocking call, don’t do it on the UI thread! Instead, why not use Kotlin coroutines?

launch {
val isRooted = async(Dispatchers.IO) {
Shell.SU.available()
}.await()
if (isRooted) {
// You are a pirate !
}
}

It works by running a command as root and checking if the result is available or not. This is quite brutal because, on rooted devices, it will prompt a dialog to ask for root privileges to your app.

The trick is to call the Shell.SU.version method:

if (Shell.SU.version(false) != null) {
// su not available or retrieving the version isn't supported
}
  • RootBeer 🍻

I’ve also found another library on Github called RootBeer which is simpler to use than the SuperUser library:

RootBeer rootBeer = new RootBeer(context);
if (rootBeer.isRooted()) {
//we found indication of root
} else {
//we didn't find indication of root
}

It works by checking the presence of some apps/files on the device:

RootBeer.isRooted method
  • Fabric 🚀

Fabric is a platform that offers the ability to reports crashes to a dashboard. For the developers who have used Fabric, you may have noticed on the crash reports an attribute showing if the device is rooted or not.

You can retrieve the code used to detect the root in the CommandUtils file:

Fabric root detection method

It checks if the device where the app runs is an emulator, how the kernel is signed, checking the presence of the Superuser app and if the su binary file exists.

Those solutions are easy to use but they have several CONs:

  • They can’t bypass the Magisk Hide feature
  • They don’t check for any other system modifications
  • The code is not maintained or the checks are based on old binary names or that can be renamed/moved
  • They may have false positives

Let’s check for another solution in our bag.

Second try: SafetyNet

This time we’re going to use the SafetyNet Attestation library from Google.

We’ve spoken about SafetyNet in the Magisk Manager presentation part. We’re going to use this API here and figure out what’s happening.

SafetyNet examines software and hardware information on the device where your app is installed to create a profile of that device. The service then attempts to find this same profile within a list of device models that have passed Android compatibility testing. The API also uses this software and hardware information to help you assess the basic integrity of the device, as well as the APK information of the calling app. This attestation helps you to determine whether or not the particular device has been tampered with or otherwise modified

Looks promising. Let’s take a look at this one!

First, you have to retrieve an API Key and enable the Android Device Verification API from your developer console. This is a similar step as for using Google Maps on an Android app.

The implementation is more complex than the 1st solution. You can check the sample on the Google Github repository. I’ve made another sample using Kotlin and Coroutines on my Github repository.

Here is how SafetyNet works according to the documentation:

SafetyNet Attestation API protocol
  1. Your app makes a call to the SafetyNet Attestation API.
  2. The API requests a signed response using its backend.
  3. The backend sends the response to Google Play services.
  4. The signed response is returned to your app.
  5. Your app should forwards the signed response to a server that you trust.
  6. The server verifies the response and sends the result of the verification process back to your app

Here’s what the API request response looks like:

SafetyNet API response

The most important fields we want to check first are ctsProfileMatch and basicIntegrity. These values have different meanings depending on device status.

ctsProfileMatch & basicIntegrity interpretations

To resume, if the fields are true, then the device pass the SafetyNet certification. Otherwise, that means some modifications have been made on the device.

The 5th and 6th steps should be done on an external sever to verify the compatibility check response. This can be done directly by the app but there is no guarantee that the verification logic itself hasn’t been modified.

To simplify things, in our repository sample, the logic is done on the app side.

root captured !

Pros:

  • Detects root & many more modifications
  • Provided by Google & maintained

Cons:

  • It cannot bypass the Magisk Hide feature
  • Implementation is complex if you want to do the server check
  • There is a quota of 10,000 requests per day. The pricing plan is not clear, you have to fill a form to request more
  • It depends on Play Services. If they are not installed, SafetyNet will not work

Root captured?

As we’ve seen, there is no perfect solution to detect root in all cases, there will always be a way around its detection.

Ok but that doesn’t explains how Pokemon Go detects the root whereas the SafetyNet attestation is fine

Indeed, it doesn’t explain everything.

In fact, Pokemon GO does other verifications to enforce the root check:

  1. Detects if Magisk Manager is installed on the device by searching with its package name (but there is an option to change it in the app, so it wouldn’t work in that case)
  2. Detects if a folder “MagiskManager” exists. This directory is created after the installation of the app

By deleting this folder on the phone storage, the game should work again! Yep, that’s all 😅 Sometimes, the simplest solution is the best.

Another mystery solved !

I hope you’ve liked this post. Don’t hesitate to leave a comment and clap 👏 if you loved it 😍

We’re also hiring a Senior Android Engineer and a Senior iOS Engineer too! Don’t hesitate to apply if you want to make the world greener 🌎

From BoT, with love 💚

Back Market Engineering

Creative engineers building a less wasteful world …

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store