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

Android 12模拟器应用文件读写路径重定向(Frida反调试问题)

解决方案:Android模拟器应用路径重定向至共享文件夹

针对你的需求,以下是几种可行的实现方式,既能避开应用反调试机制,又能完成路径重定向:

一、系统级Bind Mount挂载(最稳定,无需Hook)

这个方法直接在Linux内核层面替换目录映射,完全绕开应用的反调试逻辑,是多模拟器共用文件场景的最优解。

操作步骤:

  1. 确保模拟器已获取Root权限:
    • 原生Android模拟器可通过命令emulator -avd <avd_name> -writable-system -selinux permissive启动,获取临时Root;
    • 第三方模拟器(如雷电、夜神)通常自带Root开关,直接开启即可。
  2. 准备共享目录:
    • 在Windows共享文件夹中创建两个子目录,比如app_data和app_files,分别对应应用的/data/data/<包名>和/storage/emulated/0/Android/data/<包名>路径;
    • 在模拟器中通过df命令查看共享文件夹的挂载路径,通常为/mnt/shared或/mnt/sdcard/Windows/Shared。
  3. 迁移原有文件(可选):
    如果应用已下载过文件,先将原目录内容复制到共享目录:
    cp -r /data/data/com.your.app/* /mnt/shared/app_data/com.your.app/
    cp -r /storage/emulated/0/Android/data/com.your.app/* /mnt/shared/app_files/com.your.app/
    
  4. 执行Bind Mount:
    • 先删除原应用目录(或重命名备份):
      rm -rf /data/data/com.your.app
      rm -rf /storage/emulated/0/Android/data/com.your.app
      
    • 创建空目录并完成挂载:
      mkdir -p /data/data/com.your.app
      mkdir -p /storage/emulated/0/Android/data/com.your.app
      mount --bind /mnt/shared/app_data/com.your.app /data/data/com.your.app
      mount --bind /mnt/shared/app_files/com.your.app /storage/emulated/0/Android/data/com.your.app
      
  5. 处理SELinux限制(Android 12需注意):
    Android 12的SELinux可能阻止挂载后的文件访问,可临时设置为宽容模式:
    setenforce 0
    
    若要永久生效,可修改/etc/selinux/config文件,将SELINUX=enforcing改为SELINUX=permissive,重启模拟器即可。

二、绕过反调试后Hook目标应用进程

如果Bind Mount无法满足动态路径替换需求,可先绕过应用的反检测,再Hook应用自身进程的文件操作函数。

1. 绕过Frida反检测

  • 使用--no-pause参数启动Frida,避免进程启动时被暂停检测:
    frida -U --no-pause -f com.your.app -l redirect.js
    
  • 禁用应用的ptrace反调试检测,在脚本开头添加:
    Interceptor.attach(Module.findExportByName(null, "ptrace"), {
        onEnter: function(args) {
            args[0] = ptr(0); // 阻止PT_TRACE_ME以外的ptrace调用
        },
        onLeave: function(retval) {
            retval.replace(ptr(0)); // 返回成功状态
        }
    });
    

2. Hook文件操作函数(含自定义库)

直接Hook应用进程内的open、stat以及libabc.so中的目标函数,替换路径为共享文件夹:

const SHARED_DATA_PATH = "/mnt/shared/app_data/com.your.app";
const SHARED_FILES_PATH = "/mnt/shared/app_files/com.your.app";

// Hook libc中的核心文件操作函数
function hookLibcFunctions() {
    ["open", "openat", "stat", "lstat", "fopen"].forEach(funcName => {
        const func = Module.findExportByName("libc.so", funcName);
        if (!func) return;
        
        Interceptor.attach(func, {
            onEnter: function(args) {
                let path;
                if (funcName === "openat") {
                    path = Memory.readCString(args[1]);
                } else {
                    path = Memory.readCString(args[0]);
                }
                
                // 替换/data/data路径
                if (path.includes("/data/data/com.your.app/")) {
                    const newPath = path.replace("/data/data/com.your.app", SHARED_DATA_PATH);
                    funcName === "openat" ? args[1] = ptr(Memory.allocUtf8String(newPath)) : args[0] = ptr(Memory.allocUtf8String(newPath));
                }
                // 替换外部存储路径
                else if (path.includes("/storage/emulated/0/Android/data/com.your.app/")) {
                    const newPath = path.replace("/storage/emulated/0/Android/data/com.your.app", SHARED_FILES_PATH);
                    funcName === "openat" ? args[1] = ptr(Memory.allocUtf8String(newPath)) : args[0] = ptr(Memory.allocUtf8String(newPath));
                }
            }
        });
    });
}

// Hook libabc.so中的目标函数
function hookLibabc() {
    const libabc = Module.load("libabc.so");
    // 根据崩溃日志中的地址0x5125d计算函数偏移(基址+偏移)
    const targetFunc = libabc.base.add(0x5125d);
    
    Interceptor.attach(targetFunc, {
        onEnter: function(args) {
            // 假设该函数第一个参数为路径
            const path = Memory.readCString(args[0]);
            if (path.includes("/storage/emulated/0/Android/data/com.your.app/")) {
                const newPath = path.replace("/storage/emulated/0/Android/data/com.your.app", SHARED_FILES_PATH);
                args[0] = ptr(Memory.allocUtf8String(newPath));
            }
        }
    });
}

// 初始化钩子
setImmediate(() => {
    hookLibcFunctions();
    hookLibabc();
});

三、第三方模拟器自定义存储路径

部分第三方模拟器(如雷电、逍遥)支持直接将应用存储目录绑定到Windows共享文件夹,可在模拟器设置的「存储」选项中找到相关配置,无需手动执行命令或编写Hook脚本,适合快速实现需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:26:14