usar the significa rooted rootcloak que play ocultar magisk hbo fox detectan cómo con aplicaciones android root

android - rootcloak - the device is rooted hbo go que significa



Determine si se ejecuta en un dispositivo rooteado (20)

Mi aplicación tiene una cierta funcionalidad que solo funcionará en un dispositivo donde esté disponible la raíz. En lugar de fallar esta función cuando se usa (y luego mostrar un mensaje de error apropiado al usuario), prefiero la capacidad de verificar en silencio si la raíz está disponible primero, y si no, ocultar las opciones respectivas en primer lugar .

¿Hay alguna forma de hacer esto?


Además de la respuesta de @Kevins, recientemente, mientras utilizaba su sistema, descubrí que el Nexus 7.1 estaba devolviendo false para los tres métodos: no había comandos, no se SuperSU instalado SuperSU en /system/app .

Agregué esto:

public static boolean checkRootMethod4(Context context) { return isPackageInstalled("eu.chainfire.supersu", context); } 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; } }

Esto es un poco menos útil en algunas situaciones (si necesita acceso root garantizado), ya que es posible instalar SuperSU en dispositivos que no tienen acceso a la SU.

Sin embargo, dado que es posible tener SuperSU instalado y funcionando pero no en el directorio /system/app , este caso adicional desarraigará (jaja) estos casos.


Algunas compilaciones modificadas utilizadas para establecer la propiedad del sistema ro.modversion para este propósito. Las cosas parecen haber avanzado; Mi compilación de TheDude hace unos meses tiene esto:

cmb@apollo:~$ adb -d shell getprop |grep build [ro.build.id]: [CUPCAKE] [ro.build.display.id]: [htc_dream-eng 1.5 CUPCAKE eng.TheDudeAbides.20090427.235325 test-keys] [ro.build.version.incremental]: [eng.TheDude.2009027.235325] [ro.build.version.sdk]: [3] [ro.build.version.release]: [1.5] [ro.build.date]: [Mon Apr 20 01:42:32 CDT 2009] [ro.build.date.utc]: [1240209752] [ro.build.type]: [eng] [ro.build.user]: [TheDude] [ro.build.host]: [ender] [ro.build.tags]: [test-keys] [ro.build.product]: [dream] [ro.build.description]: [kila-user 1.1 PLAT-RC33 126986 ota-rel-keys,release-keys] [ro.build.fingerprint]: [tmobile/kila/dream/trout:1.1/PLAT-RC33/126986:user/ota-rel-keys,release-keys] [ro.build.changelist]: [17615# end build properties]

Por otro lado, el emulador del 1.5 SDK, que ejecuta la imagen 1.5, también tiene una raíz, es probablemente similar al Android Dev Phone 1 (que probablemente desee permitir) y tiene esto:

cmb@apollo:~$ adb -e shell getprop |grep build [ro.build.id]: [CUPCAKE] [ro.build.display.id]: [sdk-eng 1.5 CUPCAKE 148875 test-keys] [ro.build.version.incremental]: [148875] [ro.build.version.sdk]: [3] [ro.build.version.release]: [1.5] [ro.build.date]: [Thu May 14 18:09:10 PDT 2009] [ro.build.date.utc]: [1242349750] [ro.build.type]: [eng] [ro.build.user]: [android-build] [ro.build.host]: [undroid16.mtv.corp.google.com] [ro.build.tags]: [test-keys] [ro.build.product]: [generic] [ro.build.description]: [sdk-eng 1.5 CUPCAKE 148875 test-keys] [ro.build.fingerprint]: [generic/sdk/generic/:1.5/CUPCAKE/148875:eng/test-keys]

En cuanto a las compilaciones minoristas, no tengo una a mano, pero varias búsquedas en el site:xda-developers.com son informativas. Aquí hay un G1 en los Países Bajos , puedes ver que ro.build.tags no tiene test-keys , y creo que esa es probablemente la propiedad más confiable para usar.


Aquí está mi código basado en algunas respuestas aquí:

/** * Checks if the phone is rooted. * * @return <code>true</code> if the phone is rooted, <code>false</code> * otherwise. */ public static boolean isPhoneRooted() { // get from build info String buildTags = android.os.Build.TAGS; if (buildTags != null && buildTags.contains("test-keys")) { return true; } // check if /system/app/Superuser.apk is present try { File file = new File("/system/app/Superuser.apk"); if (file.exists()) { return true; } } catch (Throwable e1) { // ignore } return false; }


Aquí hay una clase que buscará la raíz de una de tres maneras.

/** @author Kevin Kowalewski */ public class RootUtil { public static boolean isDeviceRooted() { return checkRootMethod1() || checkRootMethod2() || checkRootMethod3(); } private static boolean checkRootMethod1() { String buildTags = android.os.Build.TAGS; return buildTags != null && buildTags.contains("test-keys"); } private static boolean checkRootMethod2() { String[] paths = { "/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su"}; for (String path : paths) { if (new File(path).exists()) return true; } return false; } private static boolean checkRootMethod3() { Process process = null; try { process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" }); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); if (in.readLine() != null) return true; return false; } catch (Throwable t) { return false; } finally { if (process != null) process.destroy(); } } }


De hecho, es una pregunta interesante y hasta ahora nadie ha merecido un premio. Yo uso el siguiente código:

boolean isRooted() { try { ServerSocket ss = new ServerSocket(81); ss.close(); return true; } catch (Exception e) { // not sure } return false; }

El código no es a prueba de balas, ya que la red no puede estar disponible, por lo que se obtiene una excepción. Si este método devuelve verdadero, entonces el 99% puede estar seguro, de lo contrario solo el 50% no. Permiso de red también puede estropear la solución.


Dos ideas adicionales, si desea comprobar si un dispositivo es compatible con root desde su aplicación:

  1. Compruebe si existe el binario ''su'': ejecute "which su" desde Runtime.getRuntime().exec()
  2. Busque el /system/app/Superuser.apk SuperUser.apk en /system/app/Superuser.apk

En lugar de usar isRootAvailable () puede usar isAccessGiven (). Directo desde la wiki RootTools:

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

RootTools.isAccessGiven () no solo comprueba que un dispositivo está rooteado, sino que también llama a su aplicación, solicita permiso y devuelve true si la aplicación recibió permisos de root. Esto se puede usar como la primera comprobación en su aplicación para asegurarse de que se le otorgará acceso cuando lo necesite.

wiki


En mi aplicación, estaba comprobando si el dispositivo está rooteado o no ejecutando el comando "su". Pero hoy he eliminado esta parte de mi código. ¿Por qué?

Porque mi aplicación se convirtió en un asesino de memoria. ¿Cómo? Déjame contarte mi historia.

Hubo algunas quejas de que mi aplicación estaba ralentizando los dispositivos (Por supuesto, pensé que eso no puede ser cierto). Traté de averiguar por qué. Así que utilicé MAT para obtener vertederos y analizar, y todo parecía perfecto. Pero después de relanzar mi aplicación muchas veces, me di cuenta de que el dispositivo se está volviendo más lento y al detener mi aplicación no lo hacía más rápido (a menos que reiniciara el dispositivo). Volví a analizar los archivos de volcado mientras el dispositivo es muy lento. Pero todo seguía siendo perfecto para el archivo de volcado. Entonces hice lo que debía hacerse al principio. Enumeré los procesos.

$ adb shell ps

Sorprender hubo muchos procesos para mi aplicación (con la etiqueta de proceso de mi aplicación en el manifiesto). Algunos de ellos eran zombies, otros no.

Con una aplicación de muestra que tiene una sola Actividad y ejecuta solo el comando "su", me di cuenta de que se está creando un proceso zombie en cada lanzamiento de la aplicación. Al principio, estos zombies asignan 0KB, pero luego sucede algo y los procesos zombie tienen casi los mismos KB que el proceso principal de mi aplicación y se convirtieron en procesos estándar.

Hay un informe de errores para el mismo problema en bugs.sun.com: http://bugs.sun.com/view_bug.do?bug_id=6474073 esto explica si no se encuentra el comando. Se crearán zombies con el método exec () . Pero aún no entiendo por qué y cómo pueden convertirse en procesos estándar y tener KB importantes. (Esto no está sucediendo todo el tiempo)

Puedes probar si quieres con el ejemplo de código de abajo;

String commandToExecute = "su"; executeShellCommand(commandToExecute);

Método de ejecución de comando simple;

private boolean executeShellCommand(String command){ Process process = null; try{ process = Runtime.getRuntime().exec(command); return true; } catch (Exception e) { return false; } finally{ if(process != null){ try{ process.destroy(); }catch (Exception e) { } } } }

Para resumir; No tengo ningún consejo para que usted determine si el dispositivo está enraizado o no. Pero si fuera tú, no usaría Runtime.getRuntime (). Exec ().

Por cierto; RootTools.isRootAvailable () causa el mismo problema.


La biblioteca RootTools ofrece métodos simples para verificar la raíz:

RootTools.isRootAvailable()

Reference


Muchas de las respuestas enumeradas aquí tienen problemas inherentes:

  • La comprobación de las claves de prueba está correlacionada con el acceso raíz, pero no necesariamente lo garantiza
  • Los directorios "PATH" deben derivarse de la variable de entorno real "PATH" en lugar de estar codificados
  • La existencia del ejecutable "su" no significa necesariamente que el dispositivo haya sido rooteado
  • El ejecutable "which" puede estar instalado o no, y debe dejar que el sistema resuelva su ruta si es posible
  • El hecho de que la aplicación SuperUser esté instalada en el dispositivo no significa que el dispositivo aún tenga acceso a la raíz

La biblioteca Reference de Stericson parece estar comprobando la raíz de forma más legítima. También tiene muchas herramientas y utilidades adicionales, así que lo recomiendo altamente. Sin embargo, no hay una explicación de cómo comprueba específicamente la raíz, y puede ser un poco más pesado de lo que la mayoría de las aplicaciones realmente necesitan.

He creado un par de métodos de utilidad que se basan libremente en la biblioteca RootTools. Si simplemente desea comprobar si el ejecutable "su" está en el dispositivo, puede usar el siguiente método:

public static boolean isRootAvailable(){ for(String pathDir : System.getenv("PATH").split(":")){ if(new File(pathDir, "su").exists()) { return true; } } return false; }

Este método simplemente recorre los directorios enumerados en la variable de entorno "PATH" y comprueba si existe uno de ellos en el archivo "su".

Para verificar realmente el acceso a la raíz, el comando "su" debe ejecutarse realmente. Si se instala una aplicación como SuperUser, en este punto puede solicitar acceso a la raíz, o si ya se ha otorgado / denegado, se puede mostrar un brindis que indica si se otorgó o denegó el acceso. Un buen comando para ejecutar es "id" para que pueda verificar que la identificación del usuario es de hecho 0 (raíz).

Aquí hay un método de muestra para determinar si se ha otorgado acceso de root:

public static boolean isRootGiven(){ if (isRootAvailable()) { Process process = null; try { process = Runtime.getRuntime().exec(new String[]{"su", "-c", "id"}); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); String output = in.readLine(); if (output != null && output.toLowerCase().contains("uid=0")) return true; } catch (Exception e) { e.printStackTrace(); } finally { if (process != null) process.destroy(); } } return false; }

Es importante probar realmente ejecutar el comando "su" porque algunos emuladores tienen el ejecutable "su" preinstalado, pero solo permiten que ciertos usuarios accedan a él como el shell adb.

También es importante verificar la existencia del ejecutable "su" antes de intentar ejecutarlo, ya que se sabe que Android no dispone correctamente de los procesos que intentan ejecutar los comandos que faltan. Estos procesos fantasmas pueden aumentar el consumo de memoria a lo largo del tiempo.


Si ya está utilizando Fabric / Crashlytics puede llamar

CommonUtils.isRooted(context)

Esta es la implementación actual de ese método:

public static boolean isRooted(Context context) { boolean isEmulator = isEmulator(context); String buildTags = Build.TAGS; if(!isEmulator && buildTags != null && buildTags.contains("test-keys")) { return true; } else { File file = new File("/system/app/Superuser.apk"); if(file.exists()) { return true; } else { file = new File("/system/xbin/su"); return !isEmulator && file.exists(); } } }



Usar C ++ con el ndk es el mejor método para detectar la raíz, incluso si el usuario está utilizando aplicaciones que ocultan su raíz, como RootCloak. Probé este código con RootCloak y pude detectar la raíz incluso si el usuario está tratando de ocultarlo. Así que tu archivo cpp quisiera:

#include <jni.h> #include <string> /** * * function that checks for the su binary files and operates even if * root cloak is installed * @return integer 1: device is rooted, 0: device is not *rooted */ extern "C" JNIEXPORT int JNICALL Java_com_example_user_root_1native_rootFunction(JNIEnv *env,jobject thiz){ const char *paths[] ={"/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su"}; int counter =0; while (counter<9){ if(FILE *file = fopen(paths[counter],"r")){ fclose(file); return 1; } counter++; } return 0; }

Y llamarás a la función desde tu código Java de la siguiente manera

public class Root_detect { /** * * function that calls a native function to check if the device is *rooted or not * @return boolean: true if the device is rooted, false if the *device is not rooted */ public boolean check_rooted(){ int checker = rootFunction(); if(checker==1){ return true; }else { return false; } } static { System.loadLibrary("cpp-root-lib");//name of your cpp file } public native int rootFunction(); }


Usar mi biblioteca en rootbox , es bastante fácil. Compruebe el código requerido a continuación:

//Pass true to <Shell>.start(...) call to run as superuser Shell shell = null; try { shell = Shell.start(true); } catch (IOException exception) { exception.printStackTrace(); } if (shell == null) // We failed to execute su binary return; if (shell.isRoot()) { // Verified running as uid 0 (root), can continue with commands ... } else throw Exception("Unable to gain root access. Make sure you pressed Allow/Grant in superuser prompt.");


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

Si no desea usar el archivo jar, solo use el código:

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

El programa intentará encontrar su carpeta:

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

Ejemplo:

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


RootBeer es una biblioteca de Android que comprueba la raíz de Scott y Matthew. Utiliza varias comprobaciones para indicar si el dispositivo está enraizado o no.

Cheques de java

  • CheckRootManagementApps

  • CheckPotentiallyDangerousAppss

  • CheckRootCoakingApps

  • CheckTestKeys

  • checkForDangerousProps

  • checkForBusyBoxBinary

  • checkForSuBinary

  • checkSuExists

  • checkForRWSystem

Cheques nativos

Llamamos a nuestro verificador de raíz nativo para ejecutar algunas de sus propias comprobaciones. Los controles nativos suelen ser más difíciles de ocultar, por lo que algunas aplicaciones de manto raíz simplemente bloquean la carga de bibliotecas nativas que contienen ciertas palabras clave.

  • checkForSuBinary

Actualización 2017

Puedes hacerlo ahora con la API de Google Safetynet . La API de SafetyNet proporciona la API de certificación que le ayuda a evaluar la seguridad y la compatibilidad de los entornos Android en los que se ejecutan sus aplicaciones.

Esta declaración puede ayudar a determinar si un dispositivo en particular ha sido manipulado o modificado.

La API de certificación devuelve una respuesta de JWS como esta

{ "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, }

El análisis de esta respuesta puede ayudarlo a determinar si el dispositivo está enraizado o no.

Los dispositivos rooteados parecen causar ctsProfileMatch = false.

Puede hacerlo en el lado del cliente, pero se recomienda analizar la respuesta en el lado del servidor. Una arquitectura básica del servidor cliente con la red de seguridad API se verá así:


La comprobación de raíz a nivel de Java no es una solución segura. Si su aplicación tiene problemas de seguridad para ejecutar en un dispositivo rooteado, utilice esta solución.

La respuesta de Kevin funciona a menos que el teléfono también tenga una aplicación como RootCloak. Estas aplicaciones tienen un Handle over Java APIs una vez que el teléfono está rooteado y se burlan de estas API para devolver el teléfono no está rooteado.

He escrito un código de nivel nativo basado en la respuesta de Kevin, ¡funciona incluso con RootCloak! Además, no causa ningún problema de pérdida de memoria.

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

En su código Java, debe crear RootUtils de clase contenedora para realizar las llamadas nativas

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


public static boolean isRootAvailable(){ Process p = null; try{ p = Runtime.getRuntime().exec(new String[] {"su"}); writeCommandToConsole(p,"exit 0"); int result = p.waitFor(); if(result != 0) throw new Exception("Root check result with exit command " + result); return true; } catch (IOException e) { Log.e(LOG_TAG, "Su executable is not available ", e); } catch (Exception e) { Log.e(LOG_TAG, "Root is unavailable ", e); }finally { if(p != null) p.destroy(); } return false; } private static String writeCommandToConsole(Process proc, String command, boolean ignoreError) throws Exception{ byte[] tmpArray = new byte[1024]; proc.getOutputStream().write((command + "/n").getBytes()); proc.getOutputStream().flush(); int bytesRead = 0; if(proc.getErrorStream().available() > 0){ if((bytesRead = proc.getErrorStream().read(tmpArray)) > 1){ Log.e(LOG_TAG,new String(tmpArray,0,bytesRead)); if(!ignoreError) throw new Exception(new String(tmpArray,0,bytesRead)); } } if(proc.getInputStream().available() > 0){ bytesRead = proc.getInputStream().read(tmpArray); Log.i(LOG_TAG, new String(tmpArray,0,bytesRead)); } return new String(tmpArray); }


if [[ "`adb shell which su | grep -io "permission denied"`" != "permission denied" ]]; then echo "Yes. Rooted device." else echo "No. Device not rooted. Only limited tasks can be performed. Done." zenity --warning --title="Device Not Rooted" --text="The connected Android Device is <b>NOT ROOTED</b>. Only limited tasks can be performed." --no-wrap fi