Move patching logic out of AXML

This commit is contained in:
topjohnwu 2022-08-26 02:54:27 -07:00
parent e9af773901
commit cdc66c1ac8
2 changed files with 23 additions and 22 deletions

View File

@ -71,14 +71,24 @@ object HideAPK {
pkg: String, label: CharSequence
): Boolean {
val info = context.packageManager.getPackageArchiveInfo(apk.path, 0) ?: return false
val name = info.applicationInfo.nonLocalizedLabel.toString()
val origLabel = info.applicationInfo.nonLocalizedLabel.toString()
try {
JarMap.open(apk, true).use { jar ->
val je = jar.getJarEntry(ANDROID_MANIFEST)
val xml = AXML(jar.getRawData(je))
if (!xml.findAndPatch(APPLICATION_ID to pkg, name to label.toString()))
if (!xml.patchStrings {
for (i in it.indices) {
val s = it[i]
if (s.contains(APPLICATION_ID)) {
it[i] = s.replace(APPLICATION_ID, pkg)
} else if (s == origLabel) {
it[i] = label.toString()
}
}
}) {
return false
}
// Write apk changes
jar.getOutputStream(je).use { it.write(xml.bytes) }

View File

@ -29,7 +29,7 @@ class AXML(b: ByteArray) {
* Followed by an array of uint32_t with size = number of strings
* Each entry points to an offset into the string data
*/
fun findAndPatch(vararg patterns: Pair<String, String>): Boolean {
fun patchStrings(patchFn: (Array<String>) -> Unit): Boolean {
val buffer = ByteBuffer.wrap(bytes).order(LITTLE_ENDIAN)
fun findStringPool(): Int {
@ -42,7 +42,6 @@ class AXML(b: ByteArray) {
return -1
}
var patch = false
val start = findStringPool()
if (start < 0)
return false
@ -57,34 +56,26 @@ class AXML(b: ByteArray) {
val dataOff = start + intBuf.get()
intBuf.get()
val strings = ArrayList<String>(count)
// Read and patch all strings
loop@ for (i in 0 until count) {
val strList = ArrayList<String>(count)
// Collect all strings in the pool
for (i in 0 until count) {
val off = dataOff + intBuf.get()
val len = buffer.getShort(off)
val str = String(bytes, off + 2, len * 2, UTF_16LE)
for ((from, to) in patterns) {
if (str.contains(from)) {
strings.add(str.replace(from, to))
patch = true
continue@loop
}
}
strings.add(str)
strList.add(String(bytes, off + 2, len * 2, UTF_16LE))
}
if (!patch)
return false
val strArr = strList.toTypedArray()
patchFn(strArr)
// Write everything before string data, will patch values later
val baos = RawByteStream()
baos.write(bytes, 0, dataOff)
// Write string data
val strList = IntArray(count)
val offList = IntArray(count)
for (i in 0 until count) {
strList[i] = baos.size() - dataOff
val str = strings[i]
offList[i] = baos.size() - dataOff
val str = strArr[i]
baos.write(str.length.toShortBytes())
baos.write(str.toByteArray(UTF_16LE))
// Null terminate
@ -103,7 +94,7 @@ class AXML(b: ByteArray) {
// Patch index table
newBuffer.position(start + STRING_INDICES_OFF)
val newIntBuf = newBuffer.asIntBuffer()
strList.forEach { newIntBuf.put(it) }
offList.forEach { newIntBuf.put(it) }
// Write the rest of the chunks
val nextOff = start + size