Android 检测设备是否 Root

为了安全起见,很多Android应用会阻止在已 Root 的设备上运行,因为Root设备可能会给恶意应用带来系统级别的权限,进而泄露数据或对系统进行破坏。

在代码层面,可以通过一些方法检测设备是否已经Root。以下是常见的几种方法:

1. 检查常见的Root文件路径

Root后的Android设备通常会包含一些文件或路径,开发者可以检查这些路径来确定设备是否被Root。常见的Root文件和路径包括:

  • /system/bin/su
  • /system/xbin/su
  • /system/app/Superuser.apk
  • /data/data/com.noshufou.android.su/
  • /system/etc/init.d/
java 复制代码
public boolean isDeviceRooted() {
    String[] paths = {"/system/bin/su", "/system/xbin/su", "/system/app/Superuser.apk", "/system/etc/init.d/"};
    for (String path : paths) {
        File file = new File(path);
        if (file.exists()) {
            return true;
        }
    }
    return false;
}

2. 检查 su 命令是否可执行

Root设备通常会包含一个名为 su 的二进制文件,它是通过超级用户权限执行命令的工具。你可以通过执行 su 命令来检查设备是否已经Root。

java 复制代码
public boolean isSuAvailable() {
    Process process = null;
    try {
        process = Runtime.getRuntime().exec("which su");
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = reader.readLine();
        if (line != null && line.contains("su")) {
            return true;
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (process != null) {
            process.destroy();
        }
    }
    return false;
}

3. 检查 Build 属性

Root设备可能会修改Android的 Build 属性。例如,ro.build.tags 属性可以指示设备是否是开发者版本或Root版本。

java 复制代码
public boolean isDeviceRootedByBuildTags() {
    String buildTags = android.os.Build.TAGS;
    return buildTags != null && buildTags.contains("test-keys");
}

4. 尝试执行具有Root权限的命令

你可以尝试通过Shell执行一些需要Root权限的命令(例如 idls)来判断是否能够获取Root权限。如果能成功执行命令,则表示设备已经Root。

java 复制代码
public boolean canExecuteRootCommands() {
    try {
        Process process = Runtime.getRuntime().exec("su");
        DataOutputStream os = new DataOutputStream(process.getOutputStream());
        os.writeBytes("id\n");
        os.flush();
        os.close();
        process.waitFor();
        return process.exitValue() == 0;
    } catch (IOException | InterruptedException e) {
        return false;
    }
}

5. 使用 SafetyNet API

Google提供了 SafetyNet API,它可以检测设备的安全状态,包括是否被Root。通过集成SafetyNet API,应用可以获得更准确的Root检测,尤其是在Google Play环境下。

java 复制代码
SafetyNet.getClient(this).attest(nonce, apiKey)
    .addOnSuccessListener(this, response -> {
        if (response.getJwsResult() != null) {
            // 根据 response 判断是否为安全设备
        }
    })
    .addOnFailureListener(this, e -> {
        // 处理失败情况
    });

6. 检查系统属性

一些系统属性在Root后的设备上可能会发生变化,比如 ro.debuggablero.secure

java 复制代码
public boolean isDeviceRootedBySystemProperties() {
    return checkProperty("ro.debuggable") || checkProperty("ro.secure");
}

private boolean checkProperty(String prop) {
    try {
        String result = getSystemProperty(prop);
        return result != null && !result.equals("1");
    } catch (Exception e) {
        return false;
    }
}

private String getSystemProperty(String prop) {
    String result = null;
    try {
        Class<?> systemProperties = Class.forName("android.os.SystemProperties");
        result = (String) systemProperties.getMethod("get", String.class).invoke(null, prop);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

7. 检查运行时是否有root权限

通过 Runtime.getRuntime().exec("su") 来判断当前进程是否能够获得Root权限。

java 复制代码
public boolean checkRootPermission() {
    try {
        Process process = Runtime.getRuntime().exec("su");
        process.waitFor();
        return process.exitValue() == 0;
    } catch (IOException | InterruptedException e) {
        return false;
    }
}

8. 检查是否能够访问敏感系统文件

Root后,应用通常能够访问一些系统文件和目录,检查是否能够访问这些文件来判断设备是否已Root。

java 复制代码
public boolean checkForRoot() {
    try {
        String[] paths = {"/system/xbin/su", "/system/bin/su"};
        for (String path : paths) {
            if (new File(path).exists()) {
                return true;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

9. 使用Root检测库

有些开源库可以帮助你检测设备是否Root,如RootBeer库。RootBeer是一个专门用来检测Android设备是否Root的开源库,它提供了较为全面的检测方法。

使用RootBeer

  1. 添加依赖:

    build.gradle中添加依赖:

    gradle 复制代码
    dependencies {
        implementation 'com.scottyab:rootbeer-lib:0.0.6'
    }
  2. 代码使用:

    使用RootBeer库检测Root设备:

    java 复制代码
    RootBeer rootBeer = new RootBeer(getApplicationContext());
    boolean isRooted = rootBeer.isRooted();
    if (isRooted) {
        // 设备已Root
    } else {
        // 设备未Root
    }

10. 通过反向工程和系统漏洞进行检测

可以通过以下方式进行进一步的安全检查,但这并不是一种常见的做法:

  • 检查是否可以调用受保护的API:有些Root工具可能会使得系统API调用变得不稳定或异常,因此可以在应用中通过调用一些不允许在非Root设备上执行的系统方法进行检测。
  • 检查是否存在安全漏洞:有些Root工具利用漏洞获得Root权限,这些漏洞可能在某些系统上存在。检测设备是否有这些漏洞可能有助于判断设备是否Root。

总结

为了准确判断设备是否已经Root,通常可以结合以上几种方法进行检测。单独依赖某一种方法可能会存在误判的风险(例如,某些Root工具会隐藏自己),因此建议使用多个方法的组合来增加检测的准确性。SafetyNet API是推荐的方式,它可以通过Google的服务器来验证设备的安全性,避免了本地Root检测的很多限制。

相关推荐
安卓理事人2 小时前
安卓LinkedBlockingQueue消息队列
android
万能的小裴同学3 小时前
Android M3U8视频播放器
android·音视频
q***57743 小时前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober4 小时前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿4 小时前
关于ObjectAnimator
android
zhangphil5 小时前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android
火柴就是我6 小时前
从头写一个自己的app
android·前端·flutter
lichong9517 小时前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端
用户69371750013848 小时前
14.Kotlin 类:类的形态(一):抽象类 (Abstract Class)
android·后端·kotlin
火柴就是我8 小时前
NekoBoxForAndroid 编译libcore.aar
android