363 Stimmen

Feststellen, ob ein gerootetes Gerät verwendet wird

Meine App hat eine bestimmte Funktionalität, die nur auf einem Gerät funktioniert, auf dem Root verfügbar ist. Anstatt diese Funktion bei der Verwendung fehlschlagen zu lassen (und dem Benutzer dann eine entsprechende Fehlermeldung anzuzeigen), würde ich eine Möglichkeit bevorzugen, zuerst stillschweigend zu prüfen, ob Root verfügbar ist, und wenn nicht, die entsprechenden Optionen von vornherein auszublenden.

Gibt es eine Möglichkeit, dies zu tun?

40voto

Hitesh Sahu Punkte 37527

Update 2017

Sie können es jetzt tun mit Google Safetynet API . Die SafetyNet API bietet eine Attestation API, die Ihnen hilft, die Sicherheit und Kompatibilität der Android-Umgebungen zu bewerten, in denen Ihre Anwendungen laufen.

Mit Hilfe dieser Bescheinigung kann festgestellt werden, ob das betreffende Gerät manipuliert oder anderweitig verändert wurde.

Die Attestation API liefert eine JWS-Antwort wie diese

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

Das Parsen dieser Antwort kann Ihnen dabei helfen, festzustellen, ob das Gerät gerootet ist oder nicht

Bei verwurzelten Geräten scheint ctsProfileMatch=false zu sein.

Sie können es auf der Client-Seite tun, aber Parsing Antwort auf der Server-Seite wird empfohlen. Eine grundlegende Client-Server-Architektur mit Sicherheitsnetz-API sieht wie folgt aus:-

enter image description here

31voto

Alok Kulkarni Punkte 2133

Eine Wurzelprüfung auf Java-Ebene ist keine sichere Lösung. Wenn Ihre Anwendung Sicherheitsbedenken hat, um auf einem gerooteten Gerät zu laufen, dann verwenden Sie bitte diese Lösung.

Kevins Antwort funktioniert, es sei denn, das Telefon hat auch eine App wie RootCloak . Solche Apps haben eine Handle über Java-APIs, sobald das Telefon gerootet ist, und sie spiegeln diese APIs, um das Telefon als nicht gerootet zurückzugeben.

Ich habe einen nativen Code geschrieben, der auf Kevins Antwort basiert, er funktioniert sogar mit RootCloak! Außerdem verursacht er keine Probleme mit Speicherlecks.

#include <string.h>
#include <jni.h>
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include "android_log.h"
#include <errno.h>
#include <unistd.h>
#include <sys/system_properties.h>

JNIEXPORT int JNICALL Java_com_test_RootUtils_checkRootAccessMethod1(
        JNIEnv* env, jobject thiz) {

    //Access function checks whether a particular file can be accessed
    int result = access("/system/app/Superuser.apk",F_OK);

    ANDROID_LOGV( "File Access Result %d\n", result);

    int len;
    char build_tags[PROP_VALUE_MAX]; // PROP_VALUE_MAX from <sys/system_properties.h>.
    len = __system_property_get(ANDROID_OS_BUILD_TAGS, build_tags); // On return, len will equal (int)strlen(model_id).
    if(strcmp(build_tags,"test-keys") == 0){
        ANDROID_LOGV( "Device has test keys\n", build_tags);
        result = 0;
    }
    ANDROID_LOGV( "File Access Result %s\n", build_tags);
    return result;

}

JNIEXPORT int JNICALL Java_com_test_RootUtils_checkRootAccessMethod2(
        JNIEnv* env, jobject thiz) {
    //which command is enabled only after Busy box is installed on a rooted device
    //Outpput of which command is the path to su file. On a non rooted device , we will get a null/ empty path
    //char* cmd = const_cast<char *>"which su";
    FILE* pipe = popen("which su", "r");
    if (!pipe) return -1;
    char buffer[128];
    std::string resultCmd = "";
    while(!feof(pipe)) {
        if(fgets(buffer, 128, pipe) != NULL)
            resultCmd += buffer;
    }
    pclose(pipe);

    const char *cstr = resultCmd.c_str();
    int result = -1;
    if(cstr == NULL || (strlen(cstr) == 0)){
        ANDROID_LOGV( "Result of Which command is Null");
    }else{
        result = 0;
        ANDROID_LOGV( "Result of Which command %s\n", cstr);
        }
    return result;

}

JNIEXPORT int JNICALL Java_com_test_RootUtils_checkRootAccessMethod3(
        JNIEnv* env, jobject thiz) {

    int len;
    char build_tags[PROP_VALUE_MAX]; // PROP_VALUE_MAX from <sys/system_properties.h>.
    int result = -1;
    len = __system_property_get(ANDROID_OS_BUILD_TAGS, build_tags); // On return, len will equal (int)strlen(model_id).
    if(len >0 && strstr(build_tags,"test-keys") != NULL){
        ANDROID_LOGV( "Device has test keys\n", build_tags);
        result = 0;
    }

    return result;

}

In Ihrem Java-Code müssen Sie die Wrapper-Klasse RootUtils erstellen, um die nativen Aufrufe zu tätigen

    public boolean checkRooted() {

       if( rootUtils.checkRootAccessMethod3()  == 0 || rootUtils.checkRootAccessMethod1()  == 0 || rootUtils.checkRootAccessMethod2()  == 0 )
           return true;
      return false;
     }

23voto

noobProgrammer Punkte 1423

http://code.google.com/p/roottools/

Wenn Sie die jar-Datei nicht verwenden möchten benutzen Sie einfach den Code:

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;
    }

Das Programm wird versuchen, den Ordner su zu finden:

private static boolean isRooted() {
        return findBinary("su");
    }

Ejemplo:

if (isRooted()) {
   textView.setText("Device Rooted");

} else {
   textView.setText("Device Unrooted");
}

14voto

Android Developer Punkte 7801

RootBeer ist eine Android-Bibliothek von Scott und Matthew zur Überprüfung von Root. Sie verwendet verschiedene Prüfungen, um anzuzeigen, ob das Gerät verwurzelt ist oder nicht.

Java-Prüfungen

  • CheckRootManagementApps

  • CheckPotentiallyDangerousAppss

  • CheckRootCloakingApps

  • CheckTestKeys

  • checkForDangerousProps

  • checkForBusyBoxBinary

  • checkForSuBinary

  • checkSuExists

  • checkForRWSystem

Einheimische Kontrollen

Wir rufen unseren nativen Root-Checker auf, um einige seiner eigenen Funktionen auszuführen prüft. Native Prüfungen sind in der Regel schwieriger zu tarnen, so dass einige Root Anwendungen einfach das Laden von nativen Bibliotheken blockieren, die bestimmte bestimmte Schlüsselwörter enthalten.

  • checkForSuBinary

13voto

Pedro Andrade Punkte 4337

Anstelle von isRootAvailable() können Sie isAccessGiven() verwenden. Direkt von RootTools wiki :

if (RootTools.isAccessGiven()) {
    // your app has been granted root access
}

RootTools.isAccessGiven() prüft nicht nur, ob ein Gerät verwurzelt ist, sondern ruft auch su für Ihre Anwendung auf, bittet um Erlaubnis und gibt true zurück, wenn Ihre Anwendung erfolgreich Root-Berechtigungen erhalten hat. Dies kann verwendet werden als erste Prüfung in Ihrer App verwendet werden, um sicherzustellen, dass Sie Zugriff erhalten Zugriff erhalten, wenn Sie ihn brauchen.

Referenz

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X