iBotPeaches / Apktool

A tool for reverse engineering Android apk files
https://apktool.org/
Apache License 2.0
20.09k stars 3.57k forks source link

APKTool 2.0.0 Loses Data #934

Closed IgorEisberg closed 9 years ago

IgorEisberg commented 9 years ago

APKTool 2.0.0 just throws away a lot of data - properties and style attributes, missing folders... Just compare the 2 folders with WinMerge and you'll see how much mess there is. "original" folder is the original APK decompiled, while "recompiled" folder is the recompiled APK which was decompiled again.

https://mega.co.nz/#!qVgSlKSL!vXRPIO8G12v6Q48-sNMCSQnzaHcSyq43I4Hj5Z5GVCI

IgorEisberg commented 9 years ago

The problem also appears with APKTool 2.0.0 RC4 but it's much less serious. Only attributes such as "android:paddingMode" in "layer-list" tag and "android:touchscreenBlocksFocus" in "android.support.v7.internal.widget.ActionBarContainer" tag are lost. This is an image from 2.0.0 RC4: http://oi62.tinypic.com/343s18m.jpg This is from 2.0.0: http://oi62.tinypic.com/zk6btl.jpg

iBotPeaches commented 9 years ago

Attributes going missing is usually an indication of a framework problem. This apk has a dependency on resources with pkgId 1 and pkgId 2. I don't think the framework I have installed as pkgId 2 is what this application wants, which would explain the missing attributes.

According to aapt. This application requires

Package Group 0 id=0x7f packageCount=1 name=com.sonyericsson.usbux
  DynamicRefTable entryCount=1:
    0x02 -> com.sonyericsson.uxp

Application com.sonyericsoon.uxp with pkgId of 2.

However, I follow this method for testing.

apktool d orig.apk apktool b orig -o new.apk apktool d new.apk

Then I compare the decoded folders of orig.apk and new.apk. However, decoding new.apk left me with this.

I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
Exception in thread "main" java.lang.ClassCastException: brut.androlib.res.data.value.ResStyleValue cannot be cast to brut.androlib.res.data.value.ResAttr
    at brut.androlib.res.data.value.ResStyleValue.serializeToResValuesXml(ResStyleValue.java:65)
    at brut.androlib.res.AndrolibResources.generateValuesFile(AndrolibResources.java:496)
    at brut.androlib.res.AndrolibResources.decode(AndrolibResources.java:252)
    at brut.androlib.Androlib.decodeResourcesFull(Androlib.java:134)
    at brut.androlib.ApkDecoder.decode(ApkDecoder.java:104)
    at brut.apktool.Main.cmdDecode(Main.java:165)
    at brut.apktool.Main.main(Main.java:81)

Apktool does currently ignore no extension files. This is a regression from a previous fix confirmed in bug #921.

So yes there is a problem here somewhere, or its a side effect of the above problem. If you can find that framework file and upload it. That'll be great!

IgorEisberg commented 9 years ago

Yeah, sorry I forgot to add the framework files, here they are: https://mega.co.nz/#!jER11RKL!3pQcCCO5KqJV9OlGweZpvKHG1BDttY6lUhHag6Rlbtk SemcGenericUxpRes.apk = com.sonyericsson.usbux

IgorEisberg commented 9 years ago

So, how is it going?

iBotPeaches commented 9 years ago

So after fixing #913 and #921, I took a look at this.

I see the missing extensions, but there is no problem here.

Take the first example we encounter.

res/color/abc_background_cache_hint_selector_material_dark.xml is apparently missing the android:state_accelerated="false" value. We scan the platform_frameworks_base repo, looking for this attribute, then git blame it to see when it was added.

We get this commit: https://github.com/android/platform_frameworks_base/commit/7eec10e6c99c30d5ee061fec08ac89ad4254ac32, on Nov. 12, 2010. So the next public version to use this branch was Honeycomb (API 11).

This means any API less than 11, has no idea what that attribute (state_accelerated) does. It will simply ignore it. So the new aapt removes all those attributes from the base folder, in this case color).

Here is the color file.

<?xml version="1.0" encoding="utf-8"?>
<selector
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/background_material_dark" />
    <item android:color="@android:color/transparent" />
</selector>

Then we have a new folder color-v11, which will load for any API 11+, then fall-back to color for any other resources it needs.

If we peek at the file in color-v11, we see this.

<?xml version="1.0" encoding="utf-8"?>
<selector
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/background_material_dark" android:state_accelerated="false" />
    <item android:color="@android:color/transparent" />
</selector>

Boom. There is our android:state_accelerated value.

If the OEM, didn't screw up the basic AOSP qualifier system then this should work fine as resources have simply been organized to allow a more optimized loading system.

This is what is happening in the application for all API breakpoints at 11, 13, 17, 21. Older apktool's didn't have this newer aapt, thus it wasn't apparent. Apktool cannot continue to use old aapts as that prevents it from working with new applications.

I believe aapt refers to this as synthesizing resources. I'm not sure how it works technically, but you may explore aapt and change this, if your use-case requires this.