Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

Commit

Permalink
fix: libziprs, new zipalign, manifest patching
Browse files Browse the repository at this point in the history
  • Loading branch information
rushiiMachine committed Mar 28, 2022
1 parent e0d380e commit e76e132
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 94 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ dependencies {
implementation 'com.gitlab.AuroraOSS:gplayapi:0e224071f3'
implementation "com.google.protobuf:protobuf-java:3.19.4"

implementation "com.github.Aliucord:libzip:1.0.1"
implementation "com.github.diamondminer88:zip-android:1.0.0@aar"
implementation "org.bouncycastle:bcpkix-jdk15on:1.65"
implementation "com.android.tools.build:apksig:7.1.2"
implementation "de.upb.cs.swt:axml:2.1.1"
Expand Down
93 changes: 28 additions & 65 deletions app/src/main/java/com/github/redditvanced/installer/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import com.aliucord.libzip.Zip
import com.android.apksig.ApkSigner
import com.aurora.gplayapi.exceptions.ApiException
import com.aurora.gplayapi.helpers.AuthHelper
import com.aurora.gplayapi.helpers.PurchaseHelper
import com.github.diamondminer88.zip.ZipReader
import com.github.diamondminer88.zip.ZipWriter
import com.github.kittinunf.fuel.gson.responseObject
import com.github.kittinunf.fuel.httpGet
import com.github.kittinunf.result.Result
Expand Down Expand Up @@ -74,7 +75,6 @@ fun install(activity: Activity) {
Build.SUPPORTED_ABIS.first { it in supportedABIs }
?: throw Error("Unsupported ABI!")

Log.i("Installer", "Extracting zipalign binary")
val zipalignBinary = File(activity.applicationInfo.nativeLibraryDir, "libzipalign.so")

// TODO: check if already installed but keystore gone
Expand Down Expand Up @@ -198,88 +198,51 @@ fun install(activity: Activity) {
Log.i("Installer", "Downloaded APKs in ${time}ms")

Log.i("Installer", "Patching main apk")
var mainApkZip = Zip(mainApkFile.absolutePath, 6, 'r')
val mainReader = ZipReader(mainApkFile)

var dexCount = 0
val entryDexRegex = "classes(\\d).dex".toRegex()
for (i in 0 until mainApkZip.totalEntries) {
mainApkZip.openEntryByIndex(i)
val name = mainApkZip.entryName
mainApkZip.closeEntry()

val index = entryDexRegex.find(name)
?.groupValues
?.get(1)
?.toIntOrNull()
?: continue
if (dexCount < index) dexCount = index
mainReader.entryNames.forEach {
if (it.startsWith("classes"))
dexCount++
}

// Read original AndroidManifest.xml
mainApkZip.openEntry("AndroidManifest.xml")
val originalManifest = mainApkZip.readEntry()
mainApkZip.closeEntry()
val originalManifest = mainReader.openEntry("AndroidManifest.xml")!!.read()
val originalClassesDex = mainReader.openEntry("classes.dex")!!.read()
mainReader.close()

// Read original classes.dex
mainApkZip.openEntry("classes.dex")
val originalClassesDex = mainApkZip.readEntry()
mainApkZip.closeEntry()

// Reopen APK with append (writing) flag
mainApkZip.close()
mainApkZip = Zip(mainApkFile.absolutePath, 6, 'a')

// Delete original AndroidManifest.xml
mainApkZip.deleteEntry("AndroidManifest.xml")

// Write original classes.dex to the end of the classesN.dex list
mainApkZip.deleteEntry("classes.dex")
mainApkZip.openEntry("classes${dexCount + 1}.dex")
mainApkZip.writeEntry(originalClassesDex, originalClassesDex.size.toLong())
mainApkZip.closeEntry()

// libzip will corrupt apk if I write more stuff without reloading
mainApkZip.close()
mainApkZip = Zip(mainApkFile.absolutePath, 6, 'a')
val mainWriter = ZipWriter(mainApkFile, true)
mainWriter.deleteEntries("AndroidManifest.xml", "classes.dex")
mainWriter.writeEntry("classes${dexCount + 1}.dex", originalClassesDex)

// Copy injector zip contents into apk
val injectorZip = Zip(getInjector(activity).absolutePath, 6, 'r')
for (i in 0 until injectorZip.totalEntries) {
injectorZip.openEntryByIndex(i)
if (injectorZip.isEntryDir) continue

val bytes = injectorZip.readEntry()
mainApkZip.openEntry(injectorZip.entryName)
mainApkZip.writeEntry(bytes, bytes.size.toLong())
mainApkZip.closeEntry()

injectorZip.closeEntry()
ZipReader(getInjector(activity)).use { injector ->
injector.forEach {
if (!it.isDir)
mainWriter.writeEntryUncompressed(it.name, it.read())
}
}
injectorZip.close()

// Change AndroidManifest targetSdkVersion to 29 (Credit to Juby)
val newManifest = ManifestUtils.editManifest(originalManifest)
mainApkZip.openEntry("AndroidManifest.xml")
mainApkZip.writeEntry(newManifest, newManifest.size.toLong())
mainApkZip.closeEntry()
mainApkZip.close()

Log.i("Installer", "Signing apks")
val apkFiles = requireNotNull(buildDir.listFiles { f -> f.extension == "apk" })
mainWriter.writeEntry("AndroidManifest.xml", newManifest)
mainWriter.close()

Log.i("Installer", "zipalign-ing apk")
val mainAligned = File(buildDir, "main.apk.aligned")
ProcessBuilder()
.command(
zipalignBinary.absolutePath,
"-i ${mainApkFile.absolutePath}",
"-o ${mainAligned.absolutePath}",
"-a 4",
"-f true"
"-p",
"-f",
"4",
mainApkFile.absolutePath,
mainAligned.absolutePath,
)
.start()
.waitFor()
.start().waitFor()
mainAligned.renameTo(mainApkFile)

Log.i("Installer", "Signing apks")
val apkFiles = requireNotNull(buildDir.listFiles { f -> f.extension == "apk" })
val keySet = KeystoreUtils.loadKeyStore(keystoreFile)
val signingConfig = ApkSigner.SignerConfig.Builder(
"RedditVanced Signer",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,28 @@ object ManifestUtils {
val writer = AxmlWriter()
reader.accept(object : AxmlVisitor(writer) {
override fun child(ns: String?, name: String) =
object : NodeVisitor(super.child(ns, name)) {
object : ReplaceAttrsVisitor(super.child(ns, name), mapOf()) {

override fun child(ns: String?, name: String): NodeVisitor {
val visitor = super.child(ns, name)
return if (name != "uses-sdk") visitor
else object : NodeVisitor(visitor) {
override fun attr(
ns: String?,
name: String,
resourceId: Int,
type: Int,
value: Any
) {
var obj = value
if ("targetSdkVersion" == name)
obj = 29
super.attr(ns, name, resourceId, type, obj)
val nv = super.child(ns, name)
return when (name) {
"application" -> object :
ReplaceAttrsVisitor(
nv,
mapOf("label" to "Aliucord", "extractNativeLibs" to false)
) {
override fun child(ns: String?, name: String): NodeVisitor {
val nv = super.child(ns, name)
return when (name) {
"activity" -> ReplaceAttrsVisitor(
nv,
mapOf("label" to "Amulet")
)
else -> nv
}
}
}
else -> nv
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2021 Juby210
* Licensed under the Open Software License version 3.0
*/
package com.github.redditvanced.installer

import pxb.android.axml.NodeVisitor

open class ReplaceAttrsVisitor(
nv: NodeVisitor,
private val attrs: Map<String, Any>
) : NodeVisitor(nv) {
override fun attr(ns: String?, name: String, resourceId: Int, type: Int, value: Any?) {
val replace = attrs.containsKey(name)
val newValue = attrs[name]
super.attr(
ns,
name,
resourceId,
if (newValue is String) TYPE_STRING else type,
if (replace) newValue else value
)
}
}
Binary file modified app/src/main/jniLibs/arm64-v8a/libzipalign.so
Binary file not shown.
Binary file modified app/src/main/jniLibs/armeabi-v7a/libzipalign.so
Binary file not shown.
Binary file removed app/src/main/jniLibs/x86-64/libzipalign.so
Binary file not shown.
Binary file added app/src/main/jniLibs/x86/libzipalign.so
Binary file not shown.
Binary file added app/src/main/jniLibs/x86_64/libzipalign.so
Binary file not shown.
13 changes: 0 additions & 13 deletions build_zipalign.sh

This file was deleted.

3 changes: 3 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ dependencyResolutionManagement {
maven {
url "https://jitpack.io"
}
maven {
url "https://redditvanced.ddns.net/maven/releases"
}
}
}
rootProject.name = "Installer"
Expand Down

0 comments on commit e76e132

Please sign in to comment.