Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to find the rooted device programmatically?

Tags:

android

Before installing my application,i want it to check whether the device is rooted or not.I have used the following code

private static boolean isRooted()

                 return findBinary("su");
        }
    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;
    } 

It is working properly.But i have heard that the filename "su" can be changed and also a file with the name "su" can be created in the nonrooted devices.In that cases,this source is not dependable.so i want to know some other way to find the rooted device other than searching for "su". I have used the following code

   Public static boolean checkRootMethod1()

     {
        String buildTags = android.os.Build.TAGS;

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

            return true;
        }

        return false;
    }

It is not working properly.For rooted devices it works as expected.But for SOME unrooted devices also it shows as rooted.Since the output is variying for differnt devices,i cannot find a solution..any help would be appreciated

like image 321
Arun Inbasekaran Avatar asked Jul 02 '14 05:07

Arun Inbasekaran


2 Answers

If you want to restrict usage of your app in the rooted device then you have to think of 2 points:
1) Restrict downloading of the app in the rooted device.
2) Restrict sideloading of the app in the rooted device.

Follow below steps to restrict downloading from the play store:
1) Go to play store console.
2) On the left side menu, go to release management.
3) In that, go to device catalog.
4) Then you will get 3 tab options, go to Excluded devices.
5) You will get an option to specify exclusion rules. click on manage exclusion rules.
6) You can see a chooser for SafetyNet exclusion. choose the option: exclude devices that don't pass basic integrity, as well as devices that are uncertified by google.

Follow below steps to restrict the sideloading of the app:
1) Obtain an API key using: https://developer.android.com/training/safetynet/attestation.html#obtain-api-key

2) Add safetynet dependency in your gradle file.
implementation 'com.google.android.gms:play-services-safetynet:17.0.0'

3) I have put below code in my BaseActivity which my other activities extend, so If a hacker with the rooted device tries to sideload and tries to enter at any activity then below code executes.

    private void ifGooglePlayServicesValid() {
        if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(getApplicationContext())
                == ConnectionResult.SUCCESS) {
            // The SafetyNet Attestation API is available.
            callSafetyNetAttentationApi();

        } else {
            // Prompt user to update Google Play services.
        }
    }

    private void callSafetyNetAttentationApi() {
        SafetyNet.getClient(this).attest(generateNonce(), SAFETY_NET_CHECK_API_KEY)
            .addOnSuccessListener(this,
                response -> {
                    // Use response.getJwsResult() to get the result data.
                    String jwsResponse = decodeJws(response.getJwsResult());
                    try {
                        JSONObject attestationResponse = new JSONObject(jwsResponse);
                        boolean ctsProfileMatch = attestationResponse.getBoolean("ctsProfileMatch");
                        boolean basicIntegrity = attestationResponse.getBoolean("basicIntegrity");
                        if (!ctsProfileMatch || !basicIntegrity) {
                            // this indicates it's rooted/tampered device
                        }
                    } catch (JSONException e) {
                        // json exception
                    }
                })
            .addOnFailureListener(this, e -> {
                // An error occurred while communicating with the service.
            });
    }

    public String decodeJws(String jwsResult) {
        if (jwsResult == null) {
            return null;
        }
        final String[] jwtParts = jwsResult.split("\\.");
        if (jwtParts.length == 3) {
            return new String(Base64.decode(jwtParts[1], Base64.DEFAULT));
        } else {
            return null;
        }
    }

    private byte[] generateNonce() {
        byte[] nonce = new byte[16];
        new SecureRandom().nextBytes(nonce);
        return nonce;
    }

SAFETY_NET_CHECK_API_KEY is the key obtained in the 1st step.

The Attestation API returns a JWS response which looks like:

{
  "timestampMs": 9860437986543,
  "nonce": "R2Rra24fVm5xa2Mg",
  "apkPackageName": "com.package.name.of.requesting.app",
  "apkCertificateDigestSha256": ["base64 encoded, SHA-256 hash of the
                                  certificate used to sign requesting app"],
  "ctsProfileMatch": true,
  "basicIntegrity": true,
}

The JWS response contains ctsProfileMatch and basicIntegrity that indicate the device status.

enter image description here
Reference: https://developer.android.com/training/safetynet/attestation.html

like image 161
Kalpesh Wadekar Avatar answered Nov 20 '22 02:11

Kalpesh Wadekar


public static boolean checkRooted()
{
    try
    {
        Process p = Runtime.getRuntime().exec("su", null, new File("/"));
        DataOutputStream os = new DataOutputStream( p.getOutputStream());
        os.writeBytes("pwd\n");
        os.writeBytes("exit\n");
        os.flush();
        p.waitFor();
        p.destroy();
    }
    catch (Exception e)
    {
        return false;
    }

    return true;
}
like image 20
Ali Bagheri Avatar answered Nov 20 '22 02:11

Ali Bagheri