diff --git a/app/src/full/java/com/topjohnwu/magisk/asyncs/PatchAPK.java b/app/src/full/java/com/topjohnwu/magisk/asyncs/PatchAPK.java index a3b3c818c..7fa140bc3 100644 --- a/app/src/full/java/com/topjohnwu/magisk/asyncs/PatchAPK.java +++ b/app/src/full/java/com/topjohnwu/magisk/asyncs/PatchAPK.java @@ -17,25 +17,32 @@ import com.topjohnwu.superuser.io.SuFileOutputStream; import com.topjohnwu.utils.JarMap; import com.topjohnwu.utils.SignAPK; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.CharBuffer; import java.security.SecureRandom; import java.util.jar.JarEntry; public class PatchAPK { + public static final String LOWERALPHA = "abcdefghijklmnopqrstuvwxyz"; + public static final String UPPERALPHA = LOWERALPHA.toUpperCase(); + public static final String ALPHA = LOWERALPHA + UPPERALPHA; + public static final String DIGITS = "0123456789"; + public static final String ALPHANUM = ALPHA + DIGITS; + public static final String ALPHANUMDOTS = ALPHANUM + "............"; + private static String genPackageName(String prefix, int length) { StringBuilder builder = new StringBuilder(length); builder.append(prefix); length -= prefix.length(); SecureRandom random = new SecureRandom(); - String base = "abcdefghijklmnopqrstuvwxyz"; - String alpha = base + base.toUpperCase(); - String full = alpha + "0123456789.........."; - char next, prev = '\0'; + char next, prev = '.'; for (int i = 0; i < length; ++i) { - if (prev == '.' || i == length - 1 || i == 0) { - next = alpha.charAt(random.nextInt(alpha.length())); + if (prev == '.' || i == length - 1) { + next = ALPHA.charAt(random.nextInt(ALPHA.length())); } else { - next = full.charAt(random.nextInt(full.length())); + next = ALPHANUMDOTS.charAt(random.nextInt(ALPHANUMDOTS.length())); } builder.append(next); prev = next; @@ -43,48 +50,30 @@ public class PatchAPK { return builder.toString(); } - private static int findOffset(byte buf[], byte pattern[]) { + private static boolean findAndPatch(byte xml[], String a, String b) { + if (a.length() != b.length()) + return false; + char[] from = a.toCharArray(), to = b.toCharArray(); + CharBuffer buf = ByteBuffer.wrap(xml).order(ByteOrder.LITTLE_ENDIAN).asCharBuffer(); int offset = -1; - for (int i = 0; i < buf.length - pattern.length; ++i) { + for (int i = 0; i < buf.length() - from.length; ++i) { boolean match = true; - for (int j = 0; j < pattern.length; ++j) { - if (buf[i + j] != pattern[j]) { + for (int j = 0; j < from.length; ++j) { + if (buf.get(i + j) != from[j]) { match = false; break; } } - if (match) { + // Make sure it is null terminated + if (match && buf.get(i + from.length) == '\0') { offset = i; break; } } - return offset; - } - - /* It seems that AAPT sometimes generate another type of string format */ - private static boolean fallbackPatch(byte xml[], String from, String to) { - - byte[] target = new byte[from.length() * 2 + 2]; - for (int i = 0; i < from.length(); ++i) { - target[i * 2] = (byte) from.charAt(i); - } - int offset = findOffset(xml, target); if (offset < 0) return false; - byte[] dest = new byte[target.length - 2]; - for (int i = 0; i < to.length(); ++i) { - dest[i * 2] = (byte) to.charAt(i); - } - System.arraycopy(dest, 0, xml, offset, dest.length); - return true; - } - - private static boolean findAndPatch(byte xml[], String from, String to) { - byte target[] = (from + '\0').getBytes(); - int offset = findOffset(xml, target); - if (offset < 0) - return fallbackPatch(xml, from, to); - System.arraycopy(to.getBytes(), 0, xml, offset, to.length()); + buf.position(offset); + buf.put(to); return true; } @@ -123,9 +112,8 @@ public class PatchAPK { JarEntry je = apk.getJarEntry(Const.ANDROID_MANIFEST); byte xml[] = apk.getRawData(je); - if (!findAndPatch(xml, from, to)) - return false; - if (!findAndPatch(xml, from + ".provider", to + ".provider")) + if (!findAndPatch(xml, from, to) || + !findAndPatch(xml, from + ".provider", to + ".provider")) return false; // Write in changes