Search in sources :

Example 1 with SuFile

use of com.topjohnwu.superuser.io.SuFile in project MagiskManager by topjohnwu.

the class HideManager method doInBackground.

@Override
protected Boolean doInBackground(Void... voids) {
    MagiskManager mm = MagiskManager.get();
    // Generate a new unhide app with random package name
    SuFile repack = new SuFile("/data/local/tmp/repack.apk", true);
    String pkg = genPackageName("com.", Const.ORIG_PKG_NAME.length());
    try {
        // Read whole APK into memory
        JarMap apk = new JarMap(new FileInputStream(mm.getPackageCodePath()));
        JarEntry je = new JarEntry(Const.ANDROID_MANIFEST);
        byte[] xml = apk.getRawData(je);
        if (!findAndPatch(xml, Const.ORIG_PKG_NAME, pkg))
            return false;
        if (!findAndPatch(xml, Const.ORIG_PKG_NAME + ".provider", pkg + ".provider"))
            return false;
        // Write in changes
        apk.getOutputStream(je).write(xml);
        // Sign the APK
        ZipUtils.signZip(apk, new SuFileOutputStream(repack));
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
    // Install the application
    if (!ShellUtils.fastCmdResult(Shell.getShell(), "pm install " + repack))
        return false;
    repack.delete();
    mm.suDB.setStrings(Const.Key.SU_REQUESTER, pkg);
    Utils.dumpPrefs();
    Utils.uninstallPkg(Const.ORIG_PKG_NAME);
    return true;
}
Also used : JarMap(com.topjohnwu.utils.JarMap) MagiskManager(com.topjohnwu.magisk.MagiskManager) SuFileOutputStream(com.topjohnwu.superuser.io.SuFileOutputStream) SuFile(com.topjohnwu.superuser.io.SuFile) JarEntry(java.util.jar.JarEntry) FileInputStream(java.io.FileInputStream)

Example 2 with SuFile

use of com.topjohnwu.superuser.io.SuFile in project MagiskManager by topjohnwu.

the class Utils method loadPrefs.

public static void loadPrefs() {
    SuFile config = new SuFile(fmt("/data/user/%d/%s", Const.USER_ID, Const.MANAGER_CONFIGS), true);
    if (config.exists()) {
        MagiskManager mm = MagiskManager.get();
        SharedPreferences.Editor editor = mm.prefs.edit();
        try {
            SuFileInputStream is = new SuFileInputStream(config);
            XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
            parser.setInput(is, "UTF-8");
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "map");
            while (parser.next() != XmlPullParser.END_TAG) {
                if (parser.getEventType() != XmlPullParser.START_TAG)
                    continue;
                String key = parser.getAttributeValue(null, "name");
                String value = parser.getAttributeValue(null, "value");
                switch(parser.getName()) {
                    case "string":
                        parser.require(XmlPullParser.START_TAG, null, "string");
                        editor.putString(key, parser.nextText());
                        parser.require(XmlPullParser.END_TAG, null, "string");
                        break;
                    case "boolean":
                        parser.require(XmlPullParser.START_TAG, null, "boolean");
                        editor.putBoolean(key, Boolean.parseBoolean(value));
                        parser.nextTag();
                        parser.require(XmlPullParser.END_TAG, null, "boolean");
                        break;
                    case "int":
                        parser.require(XmlPullParser.START_TAG, null, "int");
                        editor.putInt(key, Integer.parseInt(value));
                        parser.nextTag();
                        parser.require(XmlPullParser.END_TAG, null, "int");
                        break;
                    case "long":
                        parser.require(XmlPullParser.START_TAG, null, "long");
                        editor.putLong(key, Long.parseLong(value));
                        parser.nextTag();
                        parser.require(XmlPullParser.END_TAG, null, "long");
                        break;
                    case "float":
                        parser.require(XmlPullParser.START_TAG, null, "int");
                        editor.putFloat(key, Float.parseFloat(value));
                        parser.nextTag();
                        parser.require(XmlPullParser.END_TAG, null, "int");
                        break;
                    default:
                        parser.next();
                }
            }
        } catch (IOException | XmlPullParserException e) {
            e.printStackTrace();
        }
        editor.remove(Const.Key.ETAG_KEY);
        editor.apply();
        mm.loadConfig();
        config.delete();
    }
}
Also used : SuFileInputStream(com.topjohnwu.superuser.io.SuFileInputStream) SharedPreferences(android.content.SharedPreferences) MagiskManager(com.topjohnwu.magisk.MagiskManager) XmlPullParser(org.xmlpull.v1.XmlPullParser) SuFile(com.topjohnwu.superuser.io.SuFile) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) IOException(java.io.IOException)

Example 3 with SuFile

use of com.topjohnwu.superuser.io.SuFile in project MagiskManager by topjohnwu.

the class InstallMagisk method doInBackground.

@Override
protected Boolean doInBackground(Void... voids) {
    MagiskManager mm = MagiskManager.get();
    install = new File((Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? mm.createDeviceProtectedStorageContext() : mm).getFilesDir().getParent(), "install");
    Shell.Sync.sh("rm -rf " + install);
    List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
    String arch;
    if (abis.contains("x86_64"))
        arch = "x64";
    else if (abis.contains("arm64-v8a"))
        arch = "arm64";
    else if (abis.contains("x86"))
        arch = "x86";
    else
        arch = "arm";
    console.add("- Device platform: " + arch);
    try {
        // Unzip files
        console.add("- Extracting files");
        try (InputStream in = mm.getContentResolver().openInputStream(mZip)) {
            if (in == null)
                throw new FileNotFoundException();
            BufferedInputStream buf = new BufferedInputStream(in);
            buf.mark(Integer.MAX_VALUE);
            ZipUtils.unzip(buf, install, arch + "/", true);
            buf.reset();
            ZipUtils.unzip(buf, install, "common/", true);
            buf.reset();
            ZipUtils.unzip(buf, install, "chromeos/", false);
            buf.reset();
            ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true);
            buf.close();
        } catch (FileNotFoundException e) {
            console.add("! Invalid Uri");
            throw e;
        } catch (Exception e) {
            console.add("! Cannot unzip zip");
            throw e;
        }
        Shell.Sync.sh("chmod 755 " + install + "/*");
        File boot = new File(install, "boot.img");
        boolean highCompression = false;
        switch(mode) {
            case PATCH_MODE:
                // Copy boot image to local
                try (InputStream in = mm.getContentResolver().openInputStream(mBootImg);
                    OutputStream out = new FileOutputStream(boot)) {
                    InputStream source;
                    if (in == null)
                        throw new FileNotFoundException();
                    if (Utils.getNameFromUri(mm, mBootImg).endsWith(".tar")) {
                        // Extract boot.img from tar
                        TarInputStream tar = new TarInputStream(new BufferedInputStream(in));
                        org.kamranzafar.jtar.TarEntry entry;
                        while ((entry = tar.getNextEntry()) != null) {
                            if (entry.getName().equals("boot.img"))
                                break;
                        }
                        source = tar;
                    } else {
                        // Direct copy raw image
                        source = new BufferedInputStream(in);
                    }
                    ShellUtils.pump(source, out);
                } catch (FileNotFoundException e) {
                    console.add("! Invalid Uri");
                    throw e;
                } catch (IOException e) {
                    console.add("! Copy failed");
                    throw e;
                }
                break;
            case DIRECT_MODE:
                console.add("- Patch boot/ramdisk image: " + mBootLocation);
                if (mm.remoteMagiskVersionCode >= 1463) {
                    highCompression = Integer.parseInt(Utils.cmd(Utils.fmt("%s/magiskboot --parse %s; echo $?", install, mBootLocation))) == 2;
                    if (highCompression)
                        console.add("! Insufficient boot partition size detected");
                }
                if (boot.createNewFile()) {
                    Shell.Sync.su("cat " + mBootLocation + " > " + boot);
                } else {
                    console.add("! Dump boot image failed");
                    return false;
                }
                break;
            default:
                return false;
        }
        boolean isSigned;
        try (InputStream in = new FileInputStream(boot)) {
            isSigned = SignBoot.verifySignature(in, null);
            if (isSigned) {
                console.add("- Boot image is signed with AVB 1.0");
            }
        } catch (Exception e) {
            console.add("! Unable to check signature");
            throw e;
        }
        // Patch boot image
        Shell.Sync.sh(console, logs, "cd " + install, Utils.fmt("KEEPFORCEENCRYPT=%b KEEPVERITY=%b HIGHCOMP=%b " + "sh update-binary indep boot_patch.sh %s || echo 'Failed!'", mm.keepEnc, mm.keepVerity, highCompression, boot));
        if (TextUtils.equals(console.get(console.size() - 1), "Failed!"))
            return false;
        Shell.Sync.sh("mv -f new-boot.img ../", "mv bin/busybox busybox", "rm -rf bin *.img update-binary", "cd /");
        SuFile patched_boot = new SuFile(install.getParent(), "new-boot.img");
        if (isSigned) {
            console.add("- Signing boot image with test keys");
            File signed = new File(install.getParent(), "signed.img");
            try (InputStream in = new SuFileInputStream(patched_boot);
                OutputStream out = new BufferedOutputStream(new FileOutputStream(signed))) {
                SignBoot.doSignature("/boot", in, out, null, null);
            }
            Shell.Sync.sh("mv -f " + signed + " " + patched_boot);
        }
        switch(mode) {
            case PATCH_MODE:
                File dest = new File(Const.EXTERNAL_PATH, "patched_boot" + mm.bootFormat);
                dest.getParentFile().mkdirs();
                OutputStream out;
                switch(mm.bootFormat) {
                    case ".img.tar":
                        out = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
                        ((TarOutputStream) out).putNextEntry(new TarEntry(patched_boot, "boot.img"));
                        break;
                    default:
                    case ".img":
                        out = new BufferedOutputStream(new FileOutputStream(dest));
                        break;
                }
                try (InputStream in = new SuFileInputStream(patched_boot)) {
                    ShellUtils.pump(in, out);
                    out.close();
                }
                console.add("");
                console.add("*********************************");
                console.add(" Patched Boot Image is placed in ");
                console.add(" " + dest + " ");
                console.add("*********************************");
                break;
            case DIRECT_MODE:
                String binPath = mm.remoteMagiskVersionCode >= 1464 ? "/data/adb/magisk" : "/data/magisk";
                Shell.Sync.su(console, logs, Utils.fmt("rm -rf %s/*; mkdir -p %s; chmod 700 /data/adb", binPath, binPath), Utils.fmt("cp -af %s/* %s; rm -rf %s", install, binPath, install), Utils.fmt("flash_boot_image %s %s", patched_boot, mBootLocation), mm.remoteMagiskVersionCode >= 1464 ? "[ -L /data/magisk.img ] || cp /data/magisk.img /data/adb/magisk.img" : "", mm.keepVerity ? "" : "patch_dtbo_image");
                break;
            default:
                return false;
        }
        patched_boot.delete();
        console.add("- All done!");
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
    return true;
}
Also used : TarOutputStream(org.kamranzafar.jtar.TarOutputStream) MagiskManager(com.topjohnwu.magisk.MagiskManager) BufferedInputStream(java.io.BufferedInputStream) FileInputStream(java.io.FileInputStream) TarInputStream(org.kamranzafar.jtar.TarInputStream) SuFileInputStream(com.topjohnwu.superuser.io.SuFileInputStream) InputStream(java.io.InputStream) BufferedOutputStream(java.io.BufferedOutputStream) OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) TarOutputStream(org.kamranzafar.jtar.TarOutputStream) FileNotFoundException(java.io.FileNotFoundException) SuFile(com.topjohnwu.superuser.io.SuFile) TarEntry(com.topjohnwu.magisk.container.TarEntry) IOException(java.io.IOException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) FileInputStream(java.io.FileInputStream) SuFileInputStream(com.topjohnwu.superuser.io.SuFileInputStream) SuFileInputStream(com.topjohnwu.superuser.io.SuFileInputStream) BufferedInputStream(java.io.BufferedInputStream) TarInputStream(org.kamranzafar.jtar.TarInputStream) FileOutputStream(java.io.FileOutputStream) SuFile(com.topjohnwu.superuser.io.SuFile) File(java.io.File) BufferedOutputStream(java.io.BufferedOutputStream)

Example 4 with SuFile

use of com.topjohnwu.superuser.io.SuFile in project MagiskManager by topjohnwu.

the class SuDatabaseHelper method openDatabase.

private SQLiteDatabase openDatabase(MagiskManager mm) {
    final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db", true);
    DB_FILE = new File(Utils.fmt("/sbin/.core/db-%d/magisk.db", Const.USER_ID));
    Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? mm.createDeviceProtectedStorageContext() : mm;
    if (!DB_FILE.canWrite()) {
        if (!Shell.rootAccess()) {
            // We don't want the app to crash, create a db and return
            DB_FILE = mm.getDatabasePath("su.db");
            return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
        }
        mm.loadMagiskInfo();
        // Cleanup
        Shell.Sync.su("sudb_clean " + Const.USER_ID);
        if (mm.magiskVersionCode < 1410) {
            // Super old legacy mode
            DB_FILE = mm.getDatabasePath("su.db");
            return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
        } else if (mm.magiskVersionCode < 1450) {
            // Legacy mode with FBE aware
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                de.moveDatabaseFrom(mm, "su.db");
            }
            DB_FILE = de.getDatabasePath("su.db");
            return de.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
        } else {
            mm.deleteDatabase("su.db");
            de.deleteDatabase("su.db");
            if (mm.magiskVersionCode < 1460) {
                // Link to new path
                File oldDB = new File(de.getFilesDir().getParentFile().getParentFile(), "magisk.db");
                Shell.Sync.su(Utils.fmt("mv -f %s %s; ln -s %s %s", oldDB, GLOBAL_DB, GLOBAL_DB, oldDB));
            }
            if (mm.magiskVersionCode < 1550) {
                // We need some additional policies on old versions
                Shell.Sync.su("magiskpolicy --live " + "'create su_file' 'allow * su_file file *' 'allow * su_file dir *'");
            }
            if (!GLOBAL_DB.exists()) {
                Shell.Sync.su("sudb_init");
                SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close();
                Shell.Sync.su("sudb_restore");
            }
            Shell.Sync.su("sudb_setup " + Process.myUid());
        }
    }
    // Not using legacy mode, open the mounted global DB
    return SQLiteDatabase.openOrCreateDatabase(DB_FILE, null);
}
Also used : Context(android.content.Context) SuFile(com.topjohnwu.superuser.io.SuFile) File(java.io.File) SuFile(com.topjohnwu.superuser.io.SuFile)

Aggregations

SuFile (com.topjohnwu.superuser.io.SuFile)4 MagiskManager (com.topjohnwu.magisk.MagiskManager)3 SuFileInputStream (com.topjohnwu.superuser.io.SuFileInputStream)2 File (java.io.File)2 FileInputStream (java.io.FileInputStream)2 IOException (java.io.IOException)2 Context (android.content.Context)1 SharedPreferences (android.content.SharedPreferences)1 TarEntry (com.topjohnwu.magisk.container.TarEntry)1 SuFileOutputStream (com.topjohnwu.superuser.io.SuFileOutputStream)1 JarMap (com.topjohnwu.utils.JarMap)1 BufferedInputStream (java.io.BufferedInputStream)1 BufferedOutputStream (java.io.BufferedOutputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 FileOutputStream (java.io.FileOutputStream)1 InputStream (java.io.InputStream)1 OutputStream (java.io.OutputStream)1 JarEntry (java.util.jar.JarEntry)1 TarInputStream (org.kamranzafar.jtar.TarInputStream)1 TarOutputStream (org.kamranzafar.jtar.TarOutputStream)1