GKLBB

当你经历了暴风雨,你也就成为了暴风雨

导航

应用安全 --- app加固 之 root检测

下面我将详细列举 Android 平台上的 Root 检测方法及其对抗方案。

Root 检测与对抗全景图

Root 检测的核心思路是寻找设备被 Root 后留下的 “痕迹”。对抗的核心思路则是 “隐藏痕迹” 或 “欺骗检测API”。


一、常规路径与文件检测

这是最基础、最常见的检测方法,检查通常只有 Root 后才会存在的特殊文件、路径和二进制工具。

检测方法检测目标示例对抗方法
检查 Superuser APK /system/app/Superuser.apk
/system/app/SuperSU.apk
重命名/隐藏APK:使用 Magisk Hide 或类似功能隐藏管理应用。
检查 SU 二进制文件 /system/bin/su
/system/xbin/su
/sbin/su
/vendor/bin/su
移除默认SU路径:Magisk 将其 magisk 二进制文件放在随机化的路径下,并通过 su 符号链接调用。隐藏符号链接是关键。
检查其他Root工具 busyboxsqlite3 等常用工具 避免安装:不要安装不必要的、可能暴露环境的工具。
检查测试密钥 ro.build.tags=test-keys 修改Build属性:使用 MagiskHide Props Config 模块,将指纹 (fingerprint) 和标签 (tags) 模拟为官方发布密钥 (release-keys)。

对抗代码示例 (Hook java.io.File.exists()):

javascript
 
Java.perform(function() {
    var suspiciousPaths = [
        "/system/bin/su", "/system/xbin/su", "/sbin/su",
        "/system/app/Superuser.apk", "/system/app/SuperSU"
    ];

    var File = Java.use("java.io.File");
    File.exists.implementation = function() {
        var path = this.getAbsolutePath();
        for (var i = 0; i < suspiciousPaths.length; i++) {
            if (path.startsWith(suspiciousPaths[i])) {
                console.log("[Bypass] Blocking access to: " + path);
                return false; // 告诉调用者文件不存在
            }
        }
        return this.exists(); // 正常调用原方法
    };
});

二、环境属性检测

检查系统的各种属性,寻找与官方系统不一致的“非正常”值。

检测方法检测目标示例对抗方法
检查 ro.debuggable getprop ro.debuggable != 0 动态修改属性值:使用 Magisk Hide 或通过 Hook 在应用读取时临时返回 0
检查 ro.secure getprop ro.secure != 1 同上,动态修改返回值。
检查 ro.build.type getprop ro.build.type != user 修改为 user
检查特定Magisk属性 ro.boot.vbmeta.device_state
ro.boot.veritymode
使用 Magisk 本身:Magisk 会主动隐藏这些痕迹。

对抗代码示例 (Hook android.os.SystemProperties.get()):

javascript
 
Java.perform(function() {
    var SystemProperties = Java.use("android.os.SystemProperties");
    SystemProperties.get.overload('java.lang.String').implementation = function(key) {
        if (key === "ro.debuggable") {
            return "0";
        } else if (key === "ro.secure") {
            return "1";
        } else if (key === "ro.build.type") {
            return "user";
        } else if (key === "ro.build.tags") {
            return "release-keys";
        }
        return this.get(key); // 其他属性正常返回
    };

    // 另一个重载方法也需要Hook
    SystemProperties.get.overload('java.lang.String', 'java.lang.String').implementation = function(key, def) {
        var origResult = this.get(key, def);
        if (key === "ro.debuggable") {
            return "0";
        }
        // ... 其他属性同上
        return origResult;
    };
});

三、运行命令检测

尝试执行 which su 或 pm list packages 等命令,查看输出结果。

检测方法检测目标示例对抗方法
which su 检查命令返回值或输出 隐藏 su 命令:Magisk 通过修改 PATH 环境变量或挂钩子 (hook) 系统调用来实现。
pm list packages 检查包列表中是否存在 magisksupersu 等 隐藏管理包名:使用 Magisk Hide 功能隐藏特定的应用程序。

对抗代码示例 (Hook java.lang.Runtime.exec()):

javascript
 
Java.perform(function() {
    var Runtime = Java.use("java.lang.Runtime");
    var execOverloads = ['java.lang.String', '[Ljava.lang.String;'];
    
    for (var i = 0; i < execOverloads.length; i++) {
        Runtime.exec.overload(execOverloads[i]).implementation = function() {
            var cmd = arguments[0];
            if (typeof cmd === 'string') {
                if (cmd.includes("which su") || cmd.includes("/system/bin/which su")) {
                    console.log("[Bypass] Blocking command: " + cmd);
                    // 可以返回一个空的Process对象或抛异常,但更安全的是返回一个“未找到”的模拟输出
                    // 这里需要更复杂的实现来模拟一个空的InputStream
                    return null; // 简单示例,实际处理更复杂
                }
            }
            return this.exec.apply(this, arguments);
        };
    }
});

四、Native层检测

在 C/C++ 层进行更底层、更隐蔽的检测。

检测方法检测目标示例对抗方法
直接使用 access() 系统调用 access("/system/bin/su", F_OK) Hook Native 函数:使用 Frida 或 Xposed (Whale) 来 Hook libc 中的 accessfopenstat 等函数。
检查进程列表 读取 /proc/self/mounts 查找 magisk 路径 隐藏Magisk路径:Magisk 会使用 mount 命名空间来隔离其修改,使其对目标应用不可见。
检测加载的库 检查 maps 中是否加载了 libsu.so 等 隐藏库:避免使用会注入so库的Root管理App,或Hook读取 /proc/self/maps 的函数。

对抗代码示例 (Hook Native access()):

javascript
 
// Frida JS 代码
var libc = Module.findBaseName('libc.so');
var accessAddr = Module.findExportByName(libc, 'access');

Interceptor.attach(accessAddr, {
    onEnter: function(args) {
        this.path = args[0].readCString();
        if (this.path && this.path.includes("su")) {
            console.log("[Bypass] Blocking access to: " + this.path);
            // 让 access 调用返回 -1 (表示文件不存在),并设置 errno 为 ENOENT
            this.errno = 0x20000002; // 根据系统定义,通常为 2
        }
    },
    onLeave: function(retval) {
        if (this.errno) {
            retval.replace(-1); // 返回 -1
            // 在某些架构上,还需要通过 __errno  location 来设置 errno
        }
    }
});

五、综合与高阶检测

检测方法检测目标示例对抗方法
SafetyNet API Google 官方的完整性检验 API。 Magisk 的核心功能:Magisk 的 Universal SafetyNet Fix 模块通过模拟硬件 attestation 来通过验证。
执行结果差异性 对比 stat("/system/bin/su") 和 stat("/system/bin/ls") 的权限、用户组等。 完善的隐藏方案:需要完整的Root解决方案(如Magisk)在系统层面进行全局隐藏,而不是局部Hook。
内核特征检测 检测 syscall 表是否被修改(挂钩子)。 KernelSU:另一种Root方案,修改内核但力求隐藏得更好。对抗难度极大。

总结与最佳实践

对于普通用户/测试人员:

  1. 首选 Magisk:它是目前隐藏能力最强、更新最活跃的Root方案。

  2. 开启 Magisk Hide:在设置中启用,并勾选需要隐藏Root的目标应用(如银行App、游戏等)。

  3. 安装模块:安装 Universal SafetyNet Fix 和 MagiskHide Props Config 等模块来通过更严格的检测。

  4. 隐藏 Magisk 应用:在 Magisk 设置中,有一个选项可以将其自身应用包名随机化。

对于安全研究人员(需要对抗更强检测):

  1. 组合使用工具:Magisk + Frida

  2. 定制化Hook:分析目标App的检测逻辑,使用上述 Frida 脚本示例,编写针对性的Hook代码。

  3. 环境隔离:使用基于内核的隔离方案(如 KernelSU),或者直接在定制ROM中实现隐藏。

  4. 动态分析:如果Hook失败,可能是因为检测在Native层或使用了反调试。需要逆向App的so库,找到检测函数并下断点分析,然后制定更底层的Hook方案。

记住:这是一场持续的攻防战。新的检测方法不断出现,而隐藏技术也在不断进化。没有一劳永逸的方案,关键在于理解原理,灵活运用各种工具。

 

过检工具

firda脚本绕过

https://github.com/AshenOneYe/FridaAntiRootDetection

Shamiko模块绕过

https://github.com/LSPosed/LSPosed.github.io/releases/tag/shamiko-344

狐狸面具绕过(推荐这种方法,一劳永逸)

 

 对抗

 const-string ([vp]\d+), “*.su”

替换

 const-string $1, "/no_su"

 

最终效果

修改前:

smali
const-string v0, "/system/xbin/su" # 加载一个真实存在的Root路径
# file.exists() -> true (检测到Root)

修改后:

smali
const-string v0, "/no su" # 加载一个绝对不存在的假路径
# file.exists() -> false (未检测到Root)

通过将检测Root的关键字符串(su的路径)替换为一个无意义的、不存在的字符串,应用程序的Root检查逻辑就会被绕过,认为设备没有Root权限,从而允许应用继续正常运行。

 

 

 

posted on 2025-08-24 08:03  GKLBB  阅读(86)  评论(0)    收藏  举报