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
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.
Reference: https://developer.android.com/training/safetynet/attestation.html
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With