android-hacker / VirtualXposed

A simple app to use Xposed without root, unlock the bootloader or modify system image, etc.
https://vxp.app
GNU General Public License v3.0
15.42k stars 2.49k forks source link

Android 11 无法读写应用ExternalCacheDir路径下的文件 #1033

Open lpcdma opened 3 years ago

lpcdma commented 3 years ago

问题描述

在Android 11上无法写入/sdcard/Android/data/package_name/cache|files/file.log文件

复现步骤

代码如下

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
Log.d(TAG, "onClick: " + getExternalCacheDir().getAbsolutePath());
                try {

                    Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                    intent.addCategory("android.intent.category.DEFAULT");
                    intent.setData(Uri.parse(String.format("package:%s",getApplicationContext().getPackageName())));
                    startActivityForResult(intent, 2296);

                    if (Environment.isExternalStorageManager()) {
                        Log.d(TAG, "onClick: " + "Environment ok");
                    } else {
                        Log.d(TAG, "onClick: " + "Environment shit");
                    }
                    String result = "##" + System.currentTimeMillis();

                    String sdPath = getExternalCacheDir().getAbsolutePath();

                    File file = new File(sdPath, System.currentTimeMillis() + "_haha.txt");
                    FileOutputStream fos = new FileOutputStream(file);

                    fos.write(result.getBytes());
                    fos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }

异常堆栈

W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Android/data/pkg_name/cache/1628742726870_haha.txt: open failed: EACCES (Permission denied)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:492)
W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:186)

环境

机型: 系统版本:Andorid 11 ROM版本:MIUI 12.5.7 Xposed 插件以及插件版本:20.0.3 VirtualXposed版本:20.0.3

补充

不知道是否有办法绕过,已经开启了系统所有文件访问权限。

参考 https://stackoverflow.com/questions/62782648/android-11-scoped-storage-permissions https://developer.android.com/about/versions/11/privacy/storage

lpcdma commented 3 years ago

类似问题 https://github.com/TeamAmaze/AmazeFileManager/issues/2015 https://github.com/termux/termux-app/issues/1952

lpcdma commented 3 years ago

支持读/Android/data的文件管理器 https://apkpure.com/x-plore-file-manager/com.lonelycatgames.Xplore https://apkpure.com/file-manager/com.alphainventor.filemanager

lpcdma commented 3 years ago

其他两款产品做了路径重定向

./Android/data/com.ludashi.dualspace/virtual/0/pkg_name/cache/1628778272764_haha.txt
./Android/data/com.ludashi.dualspace/virtual/0/pkg_name/cache/1628778283444_haha.txt
./Android/data/com.ludashi.dualspace/virtual/0/pkg_name/cache/1628778310401_haha.txt
./Android/data/com.lbe.parallel.intl.arm64/parallel_intl/0/pkg_name、cache/1628778505191_haha.txt
jbro129 commented 3 years ago

In android 11+ you cannot access android/data without the proper permissions anymore. This project shows how now restricted paths can be accessed on android 11+.

ghost commented 3 years ago

https://github.com/lianglixin/SandVXposed 试试这个

lpcdma commented 3 years ago

https://github.com/lianglixin/SandVXposed 试试这个

这个编译好的也不行。 这个只是部分开源,缺失很多东西,比如64位支持的 应该只能用目录重定位来解决,下面是解决这个bug的代码

//setupVirtualStorage
if (Build.VERSION.SDK_INT >= 30) {
            for (String storageRoot : storageRoots) {
                for (String whiteDir : whiteList) {
                    // white list, do not redirect
                    String whitePath = new File(storageRoot, whiteDir).getAbsolutePath();
                    NativeEngine.whitelist(whitePath, true);
                }
                String xPrivatePath = privatePath + "/" + info.packageName;
                File xPrivatePathFile = new File(xPrivatePath);
                if (!xPrivatePathFile.exists()) {
                    xPrivatePathFile.mkdirs();
                }
                NativeEngine.redirectDirectory(new File(storageRoot, "Android/data/" + info.packageName).getAbsolutePath(), xPrivatePathFile.getAbsolutePath());
                NativeEngine.redirectDirectory(new File(storageRoot, "Android/obb/" + info.packageName).getAbsolutePath(), xPrivatePathFile.getAbsolutePath());
            }
        }

HOOK_SYMBOL(handle, faccessat);
        HOOK_SYMBOL(handle, openat);
if (api_level >= 30) {
            findSyscalls("/apex/com.android.runtime/lib64/bionic/libc.so", on_found_syscall_aarch64);
            findSyscalls("/apex/com.android.runtime/bin/linker64", on_found_linker_syscall_arch64);
        }
tiann commented 3 years ago

需要解决两个问题:

  1. 64位的 IO 重定向目前失效,原因是 openat 在 libc 中已经没有符号。
  2. Android 11 强制开启重定向后,公共媒体目录要添加白名单。
tiann commented 3 years ago

1014