frida / frida-tools

Frida CLI tools
Other
348 stars 97 forks source link

`frida-apk` fails to make apk debuggable #96

Closed mhils closed 2 years ago

mhils commented 2 years ago

I tried to use the very cool frida-apk tool with a simple pinning demo app, but for some reason the APK did not end up as debuggable on my Pixel 3. This led me down a terrible rabbit hole into binary XML. To cut a long story short, I have discovered that I can "fix" the generated APK by moving the debuggable attribute to an earlier position in the same tag. I'm not sure why this makes things work, but maybe someone has any ideas.

Here's a minimal repro script that creates two variants of a demo apk. Variant A exhibits the same behavior as if I'm just running frida-apk, variant B is "fixed" by reordering the attributes (see patch below).

#!/usr/bin/sh
# get dependencies
wget -nc -q \
    https://github.com/httptoolkit/android-ssl-pinning-demo/releases/download/v1.2.1/pinning-demo.apk \
    https://github.com/hzw1199/xml2axml/releases/download/1.1.0/xml2axml-1.1.0-SNAPSHOT.jar

# add android:debuggable attribute
frida-apk pinning-demo.apk

# the generated pinning-demo.d.apk already exhibits the same problem as the A variant below.
# The point of the A variant is to make sure that none of the conversion steps we now do fixes it somehow.

# extract manifest from new apk
unzip -p pinning-demo.d.apk AndroidManifest.xml > AndroidManifest.orig.xml

# binary xml -> plaintext xml, create copy for variant B.
java -jar xml2axml-1.1.0-SNAPSHOT.jar d AndroidManifest.orig.xml AndroidManifest.a.xml
cp AndroidManifest.a.xml AndroidManifest.b.xml

# Patch variant B. We only move the debuggable attribute up.
patch << EOM
--- AndroidManifest.b.xml   2022-03-06 02:02:30.940230800 +0100
+++ AndroidManifest.b.xml   2022-03-06 02:02:55.030781200 +0100
@@ -22,13 +22,13 @@
        android:theme="@7F1001EF"
        android:label="@7F0F001B"
        android:icon="@7F0C0000"
+       android:debuggable="true"
        android:allowBackup="true"
        android:supportsRtl="true"
        android:extractNativeLibs="false"
        android:networkSecurityConfig="@7F120000"
        android:roundIcon="@7F0C0001"
        android:appComponentFactory="androidx.core.app.CoreComponentFactory"
-       android:debuggable="true"
        >
        <activity
            android:name="tech.httptoolkit.pinning_demo.MainActivity"

EOM

# plaintext xml -> binary xml
java -jar xml2axml-1.1.0-SNAPSHOT.jar e AndroidManifest.a.xml AndroidManifest.bin.a.xml
java -jar xml2axml-1.1.0-SNAPSHOT.jar e AndroidManifest.b.xml AndroidManifest.bin.b.xml

# create a.apk and b.apk
cp pinning-demo.d.apk pinning-demo.d.a.apk
cp pinning-demo.d.apk pinning-demo.d.b.apk

# update both variants with the new binary manifests.
mv AndroidManifest.bin.a.xml AndroidManifest.xml
zip pinning-demo.d.a.apk AndroidManifest.xml
rm AndroidManifest.xml
mv AndroidManifest.bin.b.xml AndroidManifest.xml
zip pinning-demo.d.b.apk AndroidManifest.xml
rm AndroidManifest.xml

# zipalign and sign APKs for testing
objection signapk pinning-demo.d.a.apk
objection signapk pinning-demo.d.b.apk
rm pinning-demo.d.a.apk pinning-demo.d.b.apk

echo "You now have two apks: pinning-demo.d.a.objection.apk and pinning-demo.d.b.objection.apk, which only differ by the patch above."
echo "Curiously, only the B variant appears as debuggable on a Pixel 3"

Some more notes:

  1. I initially discovered that I can fix this by running apktool d followed by apktool build. For some reasons this also reorders the attributes, I haven't figured out yet why that is the case .
  2. I initially expected @meme's binary XML patching to have some subtle issues and spent a lot of time staring at the patched binary XML. The code looks very much correct though. Here's a Kaitai Struct definition I created to visualize it https://ide.kaitai.io/: https://gist.github.com/mhils/33590982266a3f6fc68b1fea84c2c92b. There is a small inconsistency where the debuggable string is inserted after the padding in the StringPool Chunk, but that shouldn't cause any issues. I fixed it manually once, which didn't change the overall outcome. Also, the issue persists after doing a roundtrip through xml2axml.
meme commented 2 years ago

Hi. Thank you for your interest in frida-apk.

This is a very interesting observation. I am not sure why the ordering seems to matter here, I would think that attributes could be parsed regardless of order and still add the FLAG_DEBUGGABLE to the process.

Curiously, the attrs_manifest.xml file which is used to define the "schema" for attributes declares the debuggable attribute after the name, theme, etc. as well: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/res/values/attrs_manifest.xml;l=1716?q=attrs_manifest and it appears to follow the same order. Unsure if this is a coincidence.

Regardless, I am in the process of developing a frida-core API called Frida.AXML: https://github.com/frida/frida-core/blob/main/src/droidy/axml.vala. The purpose of this module is to en/decode AXML files thus allowing you to create AXML files from scratch, or modify existing ones. The plan is also to expose this API to Python.

Once this module is complete, I will rewrite frida-apk to use the new frida-core API to modify AXML files, thus cleaning up the code considerably and allowing for more flexibility such as reordering attributes with ease. Further, other out-of-tree Python scripts that use frida-core could also develop their own transformations.

mhils commented 2 years ago

I am not sure why the ordering seems to matter here, I would think that attributes could be parsed regardless of order and still add the FLAG_DEBUGGABLE to the process.

Right. After experimenting a bit longer, I have found that attributes need to be sorted by their resource ids for my stock Pixel phone to pick them up properly (Android 12). I've spend a lot of time reading through ResourceTypes.cpp to find the relevant, code but everything there seems to just iterate through the list... I'm a bit at a loss why/where it's happening, but it's definitely something I'm seeing on my device here. 🤷

After lots of trial and error I got things to work today - #97 has the necessary changes.

Regardless, I am in the process of developing a frida-core API called Frida.AXML

Very nice. You've probably seen the kaitai definition I've posted above, but that only handles decoding. And I guess you are aware of https://justanapplication.wordpress.com/category/android/android-binary-xml/ already as well. :-)