Apktool: array parsing in resources

Created on 18 Jan 2019  ·  8Comments  ·  Source: iBotPeaches/Apktool

Information

apktool version 2.4.0-29355f-SNAPSHOT

Error with parsing resources.

I am use this apk

after decode in file res/values/arrays.xml contains the following code

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="autoteka_benefits" />
    <style name="loader_circle_colors" />
    <style name="loader_circle_sizes" />
    <style name="messenger_attachment_options" />
    <style name="messenger_attachment_options_legacy" />
    <style name="on_day_of_week" />
    <style name="pull_refresh_color_scheme" />
    <style name="rating_score_text" />
</resources>

public.xml code

<public type="array" name="autoteka_benefits" id="0x7f030000" />
    <public type="array" name="loader_circle_colors" id="0x7f030001" />
    <public type="array" name="loader_circle_sizes" id="0x7f030002" />
    <public type="array" name="messenger_attachment_options" id="0x7f030003" />
    <public type="array" name="messenger_attachment_options_legacy" id="0x7f030004" />
    <public type="array" name="on_day_of_week" id="0x7f030005" />
    <public type="array" name="pull_refresh_color_scheme" id="0x7f030006" />
    <public type="array" name="rating_score_text" id="0x7f030007" />

im try to list files of this apk via aapt.exe and fount this:

type 2 configCount=1 entryCount=8
      spec resource 0x7f030000 com.avito.android:array/autoteka_benefits: flags=0x00000000
      spec resource 0x7f030001 com.avito.android:array/loader_circle_colors: flags=0x00000000
      spec resource 0x7f030002 com.avito.android:array/loader_circle_sizes: flags=0x00000000
      spec resource 0x7f030003 com.avito.android:array/messenger_attachment_options: flags=0x00000000
      spec resource 0x7f030004 com.avito.android:array/messenger_attachment_options_legacy: flags=0x00000000
      spec resource 0x7f030005 com.avito.android:array/on_day_of_week: flags=0x00000000
      spec resource 0x7f030006 com.avito.android:array/pull_refresh_color_scheme: flags=0x00000000
      spec resource 0x7f030007 com.avito.android:array/rating_score_text: flags=0x00000000
      config (default):
        resource 0x7f030000 com.avito.android:array/autoteka_benefits: <bag>
        resource 0x7f030001 com.avito.android:array/loader_circle_colors: <bag>
        resource 0x7f030002 com.avito.android:array/loader_circle_sizes: <bag>
        resource 0x7f030003 com.avito.android:array/messenger_attachment_options: <bag>
        resource 0x7f030004 com.avito.android:array/messenger_attachment_options_legacy: <bag>
        resource 0x7f030005 com.avito.android:array/on_day_of_week: <bag>
        resource 0x7f030006 com.avito.android:array/pull_refresh_color_scheme: <bag>
        resource 0x7f030007 com.avito.android:array/rating_score_text: <bag>

And aapt2.exe(Android Asset Packaging Tool (aapt) 2:19) print this

type array id=03 entryCount=8
    resource 0x7f030000 array/autoteka_benefits
      () (array) size=10
        ["История регистраций в ГИБДД", "Нахождение в розыске", "Нахождение в залоге", "Наличие ограничений на регистрацию", 
         "Участие в ДТП", "Использование в такси", "Записи о пробеге", "Факты расчёта стоимости страхового ремонта", 
         "История обслуживания у дилеров", "История размещения на Авито"]
    resource 0x7f030001 array/loader_circle_colors
      () (array) size=4
        [@color/blue, @color/red, @color/green, @color/purple]
    resource 0x7f030002 array/loader_circle_sizes
      () (array) size=4
        [44, 34, 54, 25]
    resource 0x7f030003 array/messenger_attachment_options
      () (array) size=3
        ["Отправить фото", "Отправить объявление", "Указать место встречи"]
    resource 0x7f030004 array/messenger_attachment_options_legacy
      () (array) size=2
        ["Отправить фото", "Отправить объявление"]
    resource 0x7f030005 array/on_day_of_week
      () (array) size=7
        ["в воскресенье", "в понедельник", "во вторник", "в среду", 
         "в четверг", "в пятницу", "в субботу"]
    resource 0x7f030006 array/pull_refresh_color_scheme
      () (array) size=4
        [@color/blue, @color/purple, @color/green, @color/red]
    resource 0x7f030007 array/rating_score_text
      () (array) size=6
        ["Нажмите, чтобы оценить", "Нельзя иметь дело", "Не рекомендую", "Есть над чем работать", 
         "Почти нет вопросов", "Всё отлично"]

Your program does not correctly identify the array and its contents.

Bug

Most helpful comment

Confirmed.

All 8 comments

Can you please give me a quick link to the location where the Snapshot builds can be obtained from @azt59?

I had recently lost the link and had just remembered about asking around for it again.

Thanks a bunch! :-)

~Ibuprophen

I build it by this instructions https://ibotpeaches.github.io/Apktool/build/

This case is present too in 2.3.4 version, arrays is parsed as styles tags

Confirmed.

Hi! I have just ran into the same issue, I spent some times trying to implement a fix and found this solution:

diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java
index 0c2de96d..df07f7c8 100644
--- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java
+++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java
@@ -24,6 +24,11 @@ import java.util.*;
  * @author Ryszard Wiśniewski <[email protected]>
  */
 public final class ResTypeSpec {
+
+    public static final String RES_TYPE_NAME_ARRAY = "array";
+    public static final String RES_TYPE_NAME_PLURALS = "plurals";
+    public static final String RES_TYPE_NAME_STYLES = "style";
+
     private final String mName;
     private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<String, ResResSpec>();

diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java
index ee21befd..fae59dbc 100644
--- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java
+++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java
@@ -19,6 +19,7 @@ package brut.androlib.res.data.value;
 import android.util.TypedValue;
 import brut.androlib.AndrolibException;
 import brut.androlib.res.data.ResPackage;
+import brut.androlib.res.data.ResTypeSpec;
 import brut.util.Duo;

 /**
@@ -83,7 +84,7 @@ public class ResValueFactory {
         return new ResStringValue(value, rawValue);
     }

-    public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items) throws AndrolibException {
+    public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items, ResTypeSpec resTypeSpec) throws AndrolibException {
         ResReferenceValue parentVal = newReference(parent, null);

         if (items.length == 0) {
@@ -93,14 +94,25 @@ public class ResValueFactory {
         if (key == ResAttr.BAG_KEY_ATTR_TYPE) {
             return ResAttr.factory(parentVal, items, this, mPackage);
         }
-        // Android O Preview added an unknown enum for ResTable_map. This is hardcoded as 0 for now.
-        if (key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) {
+
+        String resTypeName = resTypeSpec.getName();
+
+        // Android O Preview added an unknown enum for c. This is hardcoded as 0 for now.
+        if (ResTypeSpec.RES_TYPE_NAME_ARRAY.equals(resTypeName)
+                || key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) {
             return new ResArrayValue(parentVal, items);
         }
-        if (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END) {
+
+        if (ResTypeSpec.RES_TYPE_NAME_PLURALS.equals(resTypeName) ||
+                (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END)) {
             return new ResPluralsValue(parentVal, items);
         }
-        return new ResStyleValue(parentVal, items, this);
+
+        if (ResTypeSpec.RES_TYPE_NAME_STYLES.equals(resTypeName)) {
+            return new ResStyleValue(parentVal, items, this);
+        }
+
+        throw new AndrolibException("unsupported res type name for bags. Found: " + resTypeName);
     }

     public ResReferenceValue newReference(int resID, String rawValue) {
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 290a6615..86efecff 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
@@ -347,7 +347,7 @@ public class ARSCDecoder {
             }
         }

-        return factory.bagFactory(parent, items);
+        return factory.bagFactory(parent, items, mTypeSpec);
     }

     private ResIntBasedValue readValue() throws IOException, AndrolibException {

Instead of using the id of the first item within the bag, I use the name of the res type spec to choose the res bag value to create. The "names" have been found from the aapt2 source code:

https://github.com/aosp-mirror/platform_frameworks_base/blob/e80b45506501815061b079dcb10bf87443bd385d/tools/aapt2/Resources.proto#L84-L94

https://github.com/aosp-mirror/platform_frameworks_base/blob/e80b45506501815061b079dcb10bf87443bd385d/tools/aapt2/Resource.cpp#L105-L132

I kept the previous checks, but we might remove them and use only the check on the names.

Please, feel free to tell me what you think of the solution :) I might submit an MR in the coming days if it's OK for you!

@vbarthel-fr That sounds excellent! Thanks for digging into that. I always knew trusting the first value inside the bag was a bad idea. Your solution looks good. Feel free to put it up for review

@iBotPeaches Thanks :) Before I submit a pull request, have you any preferences regarding keeping the previous checks? I might not have enough hindsight and experience with the arsc format to fully understand the consequences of those changes!

Here is my first attempt: https://github.com/iBotPeaches/Apktool/pull/2000 :)

Was this page helpful?
0 / 5 - 0 ratings