Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for xapk files #2064

Merged
merged 11 commits into from
Dec 21, 2023
Merged

Add support for xapk files #2064

merged 11 commits into from
Dec 21, 2023

Conversation

iscle
Copy link
Contributor

@iscle iscle commented Dec 20, 2023

This PR adds support for xapk loading. It handles both: code and resources.

In order to load code, the xapk plugin makes use of the existing dex-input plugin instance by retrieving it from the plugin manager.

Some existing interfaces have been annotated with @NotNull tags for better Kotlin compatibility.

This fixes issue #1597

@skylot
Copy link
Owner

skylot commented Dec 20, 2023

@iscle thanks!
Although, I made several changes:

  • reformat code, check this
  • remove NotNull annotation, it looks awful if all types have this annotation. I usually use only @Nullable.
  • use inner apk name as a name of subdirectory instead of merging everything into root.
  • make CustomResourcesLoader closeable to handle temp file deletion
  • use DexInputPlugin directly with a new instance, it is used this way in other plugins

@iscle
Copy link
Contributor Author

iscle commented Dec 20, 2023

  • remove NotNull annotation, it looks awful if all types have this annotation. I usually use only @nullable.

Yeah I agree, Kotlin will "accept" the parameter without an explicit null check if we skip the annotation, but it complains in some situations. However, in this case, it will work just fine!

  • make CustomResourcesLoader closeable to handle temp file deletion

Your solution looks good! I wanted to discuss this in the PR comment but I completely forgot.

@skylot
Copy link
Owner

skylot commented Dec 20, 2023

@iscle can you please quick check my changes, especially resources display 🙂

@iscle
Copy link
Contributor Author

iscle commented Dec 20, 2023

Sure, I'll check them a bit later. I think there there might be an issue with string resources getting overwritten maybe. (not with your changes, but in the OG implementation)

@iscle
Copy link
Contributor Author

iscle commented Dec 20, 2023

Just checked, I see that now each APK is shown in the tree. Nice!

I only have one question, how will jadx handle the multiple AndroidManifest.xml when, for example, using the "Go to main Activity" button? Will it search through all of them until it finds the launch intent, or get the last one loaded?
With the apk I tested the last apk is the "base" one but this is coincidental and might not be the case for all xapk files.

In the xapk manifest.json we do have an unused field which indicates this, which could be used to avoid searching all the manifests. However, I think it's better not to use it so that we can also handle the case where a user drags multiple .apk files into jadx from a split apk app.

@skylot
Copy link
Owner

skylot commented Dec 20, 2023

how will jadx handle the multiple AndroidManifest.xml

Hm, now it uses first one found (code here), order same as zip entries. So this can be any other manifest. Not sure how fix this right now, because logic all over jadx didn't expect several manifests or resources.arsc files 😭

@iscle
Copy link
Contributor Author

iscle commented Dec 20, 2023

Well, since this particular issue is not part of xapk support itself, I think the PR can be merged and this fixed in another PR.

@skylot skylot merged commit f5accc8 into skylot:master Dec 21, 2023
5 checks passed
@iscle iscle deleted the xapk-support-v2 branch December 21, 2023 18:49
@nitanmarcel
Copy link

There are also .apkm files shipped by apkmirror and .apks which is the default format for Google, and the format which SAI (Split APK Installer) backups bundled applications to.

Anyway the unzipping idea is the same, and the naming I'd the apks too:

You have a base.apk which contains the base APK
You have one or multiple architecture apk which contains native libs for a specific architecture.
You have one or multiple DPI apk, containing drawables for one of the 4? available resolutions.
And lastly one or multiple locale apk, containing resources for different locales.

https://github.com/nitanmarcel/apkinjector/blob/c3b3ed2893a71863531d20dfdeaf5558b8129f22/apkinjector/bundle.py#L65

@nitanmarcel
Copy link

nitanmarcel commented Dec 28, 2023

Just checked, I see that now each APK is shown in the tree. Nice!

I only have one question, how will jadx handle the multiple AndroidManifest.xml when, for example, using the "Go to main Activity" button? Will it search through all of them until it finds the launch intent, or get the last one loaded? With the apk I tested the last apk is the "base" one but this is coincidental and might not be the case for all xapk files.

In the xapk manifest.json we do have an unused field which indicates this, which could be used to avoid searching all the manifests. However, I think it's better not to use it so that we can also handle the case where a user drags multiple .apk files into jadx from a split apk app.

The main activity is only in the base.apk AndroidManifest.xml.

And you don't need all the apks in jadx.

It doesn't do anything with the libs, so the architecture splits can be ignored.

It needs the base.apk because that contains the main code, including the activities, services, etc.

The locale split for strings, here it can load only the en one.

And if really needs, 1 of the DPI spits like contains different drawables for each DPI type

@nitanmarcel
Copy link

And this is the format of a split APK file, not base.apk

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:versionCode="112"
  package="com.my.package"
  split="config.arm64_v8a"
  splitTypes="base__abi">
  <application
    android:hasCode="false"
    android:extractNativeLibs="false">
    <meta-data
      android:name="com.android.vending.derived.apk.id"
      android:value="3">
    </meta-data>
  </application>
</manifest>

@iscle
Copy link
Contributor Author

iscle commented Dec 28, 2023

Hi @nitanmarcel,

Could you provide sample files for each case?

Thanks,
Iscle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants