mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 16:07:39 +00:00
Build dynamic stub resource APK at runtime
Close #6013 Co-authored-by: vvb2060 <vvb2060@gmail.com>
This commit is contained in:
parent
a2495fb5fb
commit
0b26882fce
@ -21,7 +21,6 @@ import java.io.ByteArrayInputStream
|
|||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.nio.file.Files
|
|
||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -270,27 +269,20 @@ fun Project.setupStub() {
|
|||||||
commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
|
commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
|
||||||
}
|
}
|
||||||
|
|
||||||
val buffer = ByteArrayOutputStream()
|
val bos = ByteArrayOutputStream()
|
||||||
apkTmp.inputStream().use {
|
ZipFile(apkTmp).use { src ->
|
||||||
object : GZIPOutputStream(buffer) {
|
ZipOutputStream(apk.outputStream()).use {
|
||||||
init {
|
it.setLevel(Deflater.BEST_COMPRESSION)
|
||||||
def.setLevel(Deflater.BEST_COMPRESSION)
|
it.putNextEntry(ZipEntry("AndroidManifest.xml"))
|
||||||
|
src.getInputStream(src.getEntry("AndroidManifest.xml")).transferTo(it)
|
||||||
|
it.closeEntry()
|
||||||
}
|
}
|
||||||
}.use { o ->
|
DeflaterOutputStream(bos, Deflater(Deflater.BEST_COMPRESSION)).use {
|
||||||
it.transferTo(o)
|
src.getInputStream(src.getEntry("resources.arsc")).transferTo(it)
|
||||||
}
|
|
||||||
}
|
|
||||||
ZipFile(apkTmp).use { o ->
|
|
||||||
ZipOutputStream(apk.outputStream()).use { n ->
|
|
||||||
n.setLevel(Deflater.BEST_COMPRESSION)
|
|
||||||
n.putNextEntry(ZipEntry("AndroidManifest.xml"))
|
|
||||||
o.getInputStream(o.getEntry("AndroidManifest.xml")).transferTo(n)
|
|
||||||
n.closeEntry()
|
|
||||||
n.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apkTmp.delete()
|
apkTmp.delete()
|
||||||
genEncryptedResources(ByteArrayInputStream(buffer.toByteArray()), outSrcDir)
|
genEncryptedResources(ByteArrayInputStream(bos.toByteArray()), outSrcDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registerJavaGeneratingTask(genSrcTask, outSrcDir)
|
registerJavaGeneratingTask(genSrcTask, outSrcDir)
|
||||||
|
@ -34,7 +34,10 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.CipherInputStream;
|
import javax.crypto.CipherInputStream;
|
||||||
@ -76,7 +79,9 @@ public class DownloadActivity extends Activity {
|
|||||||
// Inject resources
|
// Inject resources
|
||||||
try {
|
try {
|
||||||
loadResources();
|
loadResources();
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception e) {
|
||||||
|
error(e);
|
||||||
|
}
|
||||||
|
|
||||||
ProviderInstaller.install(this);
|
ProviderInstaller.install(this);
|
||||||
|
|
||||||
@ -103,7 +108,7 @@ public class DownloadActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void error(Throwable e) {
|
private void error(Throwable e) {
|
||||||
Log.e(getClass().getSimpleName(), "", e);
|
Log.e(getClass().getSimpleName(), Log.getStackTraceString(e));
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,14 +162,26 @@ public class DownloadActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void decryptResources(OutputStream out) throws Exception {
|
private void decryptResources(OutputStream out) throws Exception {
|
||||||
|
try (var zip = new ZipOutputStream(out)) {
|
||||||
|
zip.putNextEntry(new ZipEntry("resources.arsc"));
|
||||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
SecretKey key = new SecretKeySpec(Bytes.key(), "AES");
|
SecretKey key = new SecretKeySpec(Bytes.key(), "AES");
|
||||||
IvParameterSpec iv = new IvParameterSpec(Bytes.iv());
|
IvParameterSpec iv = new IvParameterSpec(Bytes.iv());
|
||||||
cipher.init(Cipher.DECRYPT_MODE, key, iv);
|
cipher.init(Cipher.DECRYPT_MODE, key, iv);
|
||||||
var is = new GZIPInputStream(new CipherInputStream(
|
var is = new InflaterInputStream(new CipherInputStream(
|
||||||
new ByteArrayInputStream(Bytes.res()), cipher));
|
new ByteArrayInputStream(Bytes.res()), cipher));
|
||||||
try (is; out) {
|
try (is) {
|
||||||
APKInstall.transfer(is, out);
|
APKInstall.transfer(is, zip);
|
||||||
|
}
|
||||||
|
zip.closeEntry();
|
||||||
|
|
||||||
|
zip.putNextEntry(new ZipEntry("AndroidManifest.xml"));
|
||||||
|
var apk = new ZipFile(getPackageResourcePath());
|
||||||
|
var xml = apk.getInputStream(apk.getEntry("AndroidManifest.xml"));
|
||||||
|
try (apk; xml) {
|
||||||
|
APKInstall.transfer(xml, zip);
|
||||||
|
}
|
||||||
|
zip.closeEntry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user