检测到Android已获取Root权限?立即卸载应用程序。

4
我正在开发一个包含敏感数据(加密密钥)的应用程序,不应该泄漏。该应用程序应能够随时离线工作,因此我不能将密钥存储在云中。
当用户拥有已root的设备时,他可以提取apk并获取密钥。我想要防止这种情况发生。
是否有一种方法可以立即强制卸载我的应用程序,而无需用户确认,一旦检测到root权限?
(或者是否有另一种方法防止密钥泄漏?)
我已经研究了三星Knox,它加密数据并使用硬件位来检测root权限,并且一旦设备被篡改,应用程序和数据将变得不可访问。它的效果非常好,但是我正在寻找适用于更广泛设备(不仅限于三星设备)的解决方案。

当用户拥有root设备时,他可以提取apk并获取密钥 -- 这不需要root权限。 "是否有任何方法可以立即强制卸载我的应用程序而无需用户确认" -- 不行。 - CommonsWare
@CommonsWare 一个没有root的设备如何提取apk文件? - Mark Buikema
APK文件在Android中是可读的。应用程序可以从设备上拉取APK文件。而且,以前至少可以使用adb pull从设备上拉取APK文件,尽管我最近几年没有这样做的需要。 - CommonsWare
谢谢,这是一个有用的链接 :) - Mark Buikema
2个回答

1

编辑:你试图实现的那些事情(为加密密钥保存存储空间等)并不容易。你应该阅读这个,它可能会对你最有帮助。

要卸载您的应用程序,您可以尝试这样做(未经测试!):

Uri packageURI = Uri.parse("package:"+MyMainActivity.class.getPackage().getName());
Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
startActivity(uninstallIntent);

当涉及到根检测时,并没有“最好”的解决方案。有多种方法,以下内容可以帮助您入门:

/** @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();
        }
    }
}

卸载部分会打开一个对话框,询问用户是否确认。如问题所述,我想强制卸载我的应用程序,而不需要用户确认。 - Mark Buikema
第三方应用程序不可能实现这一点: ( 除非你拥有根权限; D lol - jdstaerk
1
如果您的设备已经取得了 root 权限,那么您才能在不需要用户确认的情况下卸载一个应用程序。 - Nishant Pardamwar
1
是的,但用户需要授予根权限,所以对于您的目的来说这是个愚蠢的想法;D - jdstaerk

0

我认为立即卸载应用程序并不是解决方案,你必须找出根目录所在位置,并注意Magisk Manager应用程序,它可以绕过根检测。你可以尝试使用Rootbeer、roottools或创建根类进行根检测。使用Rootbeer来检测Magisk Manager

//root example you can call this class.
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/",
                "/system/app/Superuser.apk", "/sbin/su", "/sbin/su/", "/system/bin/su","/system/bin/su/",
                "/system/xbin/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", "/su/",
                "/data/local/xbin/",
                "/system/bin/.ext/",
                "/system/bin/failsafe/",
                "/system/sd/xbin/",
                "/su/xbin/",
                "/su/bin/",
                "/magisk/.core/bin/",
                "/system/usr/we-need-root/",
                "/system/xbin/",
                "/system/su","/system/bin/.ext/.su","/system/usr/we-need-root/su-backup",
                "/system/xbin/mu",
                "/system/su/","/system/bin/.ext/.su/","/system/usr/we-need-root/su-backup/",
                "/system/xbin/mu/"};
        for (String where : places) {
            if (new File(where + binaryName).exists()) {
                found = true;
                break;
            }
        }
    }
    return found;
}
private static boolean isRooted() {
    return findBinary("su");
}

使用此代码卸载应用程序(已测试)

Intent intent=new Intent(Intent.ACTION_DELETE);
String packageName = "yourpackagename";
intent.setData(Uri.parse("package:"+packageName));
startActivity(intent);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接