From 0a3c7595eb9bfe4ff96ed1c8b806d33d38aa5e3d Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Sat, 21 Jan 2023 13:30:13 -0500 Subject: [PATCH] feat: support config flags as low as 8 bytes (#2982) --- .../androlib/res/decoder/ARSCDecoder.java | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index 351470a8..659bf1d0 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -103,10 +103,10 @@ public class ARSCDecoder { } String name = mIn.readNullEndedString(128, true); - /* typeStrings */mIn.skipInt(); - /* lastPublicType */mIn.skipInt(); - /* keyStrings */mIn.skipInt(); - /* lastPublicKey */mIn.skipInt(); + mIn.skipInt(); // typeStrings + mIn.skipInt(); // lastPublicType + mIn.skipInt(); // keyStrings + mIn.skipInt(); // lastPublicKey // TypeIdOffset was added platform_frameworks_base/@f90f2f8dc36e7243b85e0b6a7fd5a590893c827e // which is only in split/new applications. @@ -191,7 +191,7 @@ public class ARSCDecoder { private void readOverlayPolicySpec() throws AndrolibException, IOException { checkChunkType(Header.XML_TYPE_OVERLAY_POLICY); - /* policyFlags */mIn.skipInt(); + mIn.skipInt(); // policyFlags int count = mIn.readInt(); for (int i = 0; i < count; i++) { @@ -245,7 +245,7 @@ public class ARSCDecoder { mFlagsOffsets.add(new FlagsOffset(mCountIn.getCount(), entryCount)); } - /* flags */mIn.skipBytes(entryCount * 4); + mIn.skipBytes(entryCount * 4); // flags mTypeSpec = new ResTypeSpec(mTypeNames.getString(id - 1), mResTable, mPkg, id, entryCount); mPkg.addType(mTypeSpec); return mTypeSpec; @@ -260,7 +260,7 @@ public class ARSCDecoder { } int typeFlags = mIn.readByte(); - /* reserved */mIn.skipBytes(2); + mIn.skipBytes(2); // reserved int entryCount = mIn.readInt(); int entriesStart = mIn.readInt(); mMissingResSpecMap = new LinkedHashMap(); @@ -396,8 +396,8 @@ public class ARSCDecoder { } private ResIntBasedValue readValue() throws IOException, AndrolibException { - /* size */mIn.skipCheckShort((short) 8); - /* zero */mIn.skipCheckByte((byte) 0); + mIn.skipCheckShort((short) 8); // size + mIn.skipCheckByte((byte) 0); // zero byte type = mIn.readByte(); int data = mIn.readInt(); @@ -408,10 +408,10 @@ public class ARSCDecoder { private ResConfigFlags readConfigFlags() throws IOException, AndrolibException { int size = mIn.readInt(); - int read = 28; + int read = 8; - if (size < 28) { - throw new AndrolibException("Config size < 28"); + if (size < 8) { + throw new AndrolibException("Config size < 8"); } boolean isInvalid = false; @@ -419,24 +419,50 @@ public class ARSCDecoder { short mcc = mIn.readShort(); short mnc = mIn.readShort(); - char[] language = this.unpackLanguageOrRegion(mIn.readByte(), mIn.readByte(), 'a'); - char[] country = this.unpackLanguageOrRegion(mIn.readByte(), mIn.readByte(), '0'); + char[] language = new char[0]; + char[] country = new char[0]; + if (size >= 12) { + language = this.unpackLanguageOrRegion(mIn.readByte(), mIn.readByte(), 'a'); + country = this.unpackLanguageOrRegion(mIn.readByte(), mIn.readByte(), '0'); + read = 12; + } - byte orientation = mIn.readByte(); - byte touchscreen = mIn.readByte(); + byte orientation = 0; + byte touchscreen = 0; + if (size >= 14) { + orientation = mIn.readByte(); + touchscreen = mIn.readByte(); + read = 14; + } - int density = mIn.readUnsignedShort(); + int density = 0; + if (size >= 16) { + density = mIn.readUnsignedShort(); + read = 16; + } - byte keyboard = mIn.readByte(); - byte navigation = mIn.readByte(); - byte inputFlags = mIn.readByte(); - /* inputPad0 */mIn.skipBytes(1); + byte keyboard = 0; + byte navigation = 0; + byte inputFlags = 0; + if (size >= 20) { + keyboard = mIn.readByte(); + navigation = mIn.readByte(); + inputFlags = mIn.readByte(); + mIn.skipBytes(1); // inputPad0 + read = 20; + } - short screenWidth = mIn.readShort(); - short screenHeight = mIn.readShort(); + short screenWidth = 0; + short screenHeight = 0; + short sdkVersion = 0; + if (size >= 28) { + screenWidth = mIn.readShort(); + screenHeight = mIn.readShort(); - short sdkVersion = mIn.readShort(); - /* minorVersion, now must always be 0 */mIn.skipBytes(2); + sdkVersion = mIn.readShort(); + mIn.skipBytes(2); // minorVersion + read = 28; + } byte screenLayout = 0; byte uiMode = 0;