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 小时前
Android系统架构模式分析
android·java·架构·系统架构
每次的天空7 小时前
Kotlin 内联函数深度解析:从源码到实践优化
android·开发语言·kotlin
练习本7 小时前
Android MVC架构的现代化改造:构建清晰单向数据流
android·架构·mvc
早上好啊! 树哥8 小时前
android studio开发:设置屏幕朝向为竖屏,强制应用的包体始终以竖屏(纵向)展示
android·ide·android studio
YY_pdd9 小时前
使用go开发安卓程序
android·golang
Android 小码峰啊10 小时前
Android Compose 框架物理动画之捕捉动画深入剖析(29)
android·spring
bubiyoushang88810 小时前
深入探索Laravel框架中的Blade模板引擎
android·android studio·laravel
cyy29810 小时前
android 记录应用内存
android·linux·运维
CYRUS STUDIO11 小时前
adb 实用命令汇总
android·adb·命令模式·工具
这儿有一堆花11 小时前
安卓应用卡顿、性能低下的背后原因
android·安卓