You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Frida antiroot脚本场景下安卓App Root检测防绕过方案咨询

问题说明

在Magisk获取Root权限的设备上,攻击者使用下述Frida绕过脚本时,应用内置的、经普通代码混淆的Java层Root检测功能会失效,无法正确识别设备Root状态:

Java.perform(function() {
    var RootPackages = ["com.topjohnwu.magisk"
    ];
    var RootBinaries = ["su", "busybox", "magisk"];
    var RootProperties = {
        "ro.build.selinux": "1",
        "ro.debuggable": "0",
        "service.adb.root": "0",
        "ro.secure": "1"
    };
    var RootPropertiesKeys = [];

    for (var k in RootProperties) RootPropertiesKeys.push(k);

    var NativeFile = Java.use('java.io.File');
    var ProcessBuilder = Java.use('java.lang.ProcessBuilder');
    var useProcessManager = false;

    NativeFile.exists.implementation = function() {
        var name = NativeFile.getName.call(this);
        var shouldFakeReturn = (RootBinaries.indexOf(name) > -1);
        if (shouldFakeReturn) {
            return false;
        } else {
            return this.exists.call(this);
        }
    };

    ProcessBuilder.start.implementation = function() {
        var cmd = this.command.call(this);
        var shouldModifyCommand = false;
        for (var i = 0; i < cmd.size(); i = i + 1) {
            var tmp_cmd = cmd.get(i).toString();
            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd.indexOf("mount") != -1 || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd.indexOf("id") != -1) {
                shouldModifyCommand = true;
            }
        }
        if (shouldModifyCommand) {
            this.command.call(this, ["grep"]);
            return this.start.call(this);
        }
        if (cmd.indexOf("su") != -1) {
            this.command.call(this, ["SOMEFAKECMD"]);
            return this.start.call(this);
        }
        return this.start.call(this);
    };

    if (useProcessManager) {
        var ProcManExec = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File', 'boolean');
    
        ProcManExec.implementation = function(cmd, env, workdir, redirectstderr) {
            var fake_cmd = cmd;
            for (var i = 0; i < cmd.length; i = i + 1) {
                var tmp_cmd = cmd[i];
                if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") {
                    var fake_cmd = ["grep"];
                }
                if (tmp_cmd == "su") {
                    var fake_cmd = ["SOMEFAKECMD"];
                }
            }
            return ProcManExec.call(this, fake_cmd, env, workdir, redirectstderr);
        };
    }
});

上述为裁剪后的Frida绕过脚本,移除了原公开脚本中的无关冗余逻辑。

可落地的加固技术手段
  • 优先将核心Root检测逻辑下沉至Native层,避免依赖Java层被Hook的公开API
    这个脚本所有拦截逻辑都作用在Java框架层,仅Hook了java.io.File.exists()、java.lang.ProcessBuilder.start()两个公开Java方法,预留的ProcessManager.exec Hook逻辑默认处于关闭状态,实际拦截覆盖范围非常有限,完全没有覆盖Native层的系统调用路径。你可以在C/C++层直接通过syscall调用open/access/stat接口检查su、Magisk相关二进制、Magisk专属挂载路径(如/dev/.magisk、/sbin/.magisk)的存在性,直接调用__system_property_get读取系统属性,直接通过fork+execve执行系统命令读取结果,全程不经过Java层的File、ProcessBuilder类,脚本的伪造返回值、篡改命令逻辑完全无法生效。为了进一步提升安全性,Native层的系统调用可以通过内联汇编直接触发,避免依赖libc导出函数被后续Native层Hook拦截。
  • 在Root检测流程前增加Frida环境检测与API完整性校验
    不要等Root检测逻辑跑起来才做校验,在应用启动的最早阶段就完成两项检查:
    1. 反注入/反调试检查:扫描进程/proc/self/maps内存映射表查找frida-agent、frida-server相关内存段特征,检测Frida默认监听的27042端口,检查进程是否被ptrace附着,扫描线程名是否包含frida特征字符串,发现异常直接终止检测流程、触发风险判定。
    2. 关键API完整性校验:检查Root检测用到的Java层系统方法(如File.exists、ProcessBuilder.start)的入口地址是否和系统原生方法一致,检查自身应用的核心检测方法是否被插桩篡改,如果发现方法被替换(即被Frida Hook),直接判定环境异常。
  • 优化Java层检测逻辑,规避脚本的固定匹配规则
    如果暂时无法完全把逻辑下沉到Native层,可以针对性绕过脚本的匹配逻辑:
    1. 不要直接调用File.exists()做文件存在性判断,可以通过FileDescriptor直接打开目标文件路径,根据打开结果判断文件是否存在,绕开被Hook的exists方法。
    2. 执行系统命令时不要直接传入完整的命令字符串,将命令关键词拆分、动态拼接后传入,规避脚本里对getprop/mount/su等固定字符串的匹配;不要只依赖ProcessBuilder执行命令,可以通过反射调用Runtime.exec等其他命令执行路径,分散Hook点。
    3. 对检测逻辑做高强度混淆,包括字符串加密、控制流平坦化、类/方法名混淆,避免攻击者通过特征定位到你的Root检测代码段。
  • 扩展Root检测维度,做交叉校验
    这个脚本仅覆盖了非常有限的Root检测绕过项:仅伪造了三个Root二进制文件的exists返回值、仅篡改了四个固定系统属性的读取路径、仅拦截了四个固定关键词的命令执行。你可以补充更多脚本未覆盖的检测维度:
    1. 读取/proc/self/mountinfo检查Magisk的挂载痕迹,检查Magisk修改的SELinux规则
    2. 校验boot镜像、系统分区的完整性,检查vbmeta锁定状态
    3. 扩展系统属性检测范围,补充ro.boot.vbmeta.device_state、ro.build.type、ro.boot.verifiedbootstate等和Root、解锁状态相关的属性校验,不要只检查脚本里列的四个属性
    4. 实际执行su命令校验权限返回结果,而不是只判断su文件是否存在。
参考防护方案的适用性判断

你提到的StackOverflow相关帖子里提出的核心防护思路——包括核心逻辑下沉Native层、Frida运行环境检测、多维度Root校验、代码完整性校验——完全适用于当前场景。但需要注意,帖子里给出的示例代码仅覆盖了基础防护场景,直接照搬会存在两个问题:一是公开的固定检测代码很容易被攻击者针对性写绕过规则,二是示例代码没有针对你遇到的这个脚本的Java层Hook点做专门的API完整性校验,落地时需要对代码做混淆改造、补充Hook检测逻辑,才能有效拦截这类绕过脚本。

内容的提问来源于stack exchange,提问作者peteryun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 18:51:05