Skip to content
This repository was archived by the owner on Jan 16, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6571b66
Various updates
TheDauntless Jun 23, 2021
2a7e557
Fix issue #30 with build function
jseigelis Nov 25, 2021
4c7cd49
Add regex file patching and fix issue #31
jseigelis Nov 25, 2021
99c40d5
Fix untracked apktool xml strings escape bug
jseigelis Nov 25, 2021
dd61e39
Add apksigner to deps
jseigelis Nov 25, 2021
fc905a0
disclaimer
jseigelis Nov 25, 2021
2e4cb1f
Fix aapt dependency
jseigelis Nov 25, 2021
96a8c82
small cosmetic changes
jseigelis Nov 25, 2021
5270b31
Add subprocess run helper and remove some prints
jseigelis Nov 25, 2021
406fc53
signAndZipAlign, jarsigner -> apksigner, prints
jseigelis Nov 25, 2021
238ef47
Fix last of the prints
jseigelis Nov 25, 2021
8b97d54
Move zip align to front and rename result
jseigelis Nov 25, 2021
9179af6
Remove extra unnecessary move
jseigelis Nov 25, 2021
0e1636e
Add DS_Store to gitignore
jseigelis Nov 29, 2021
89d6c4d
Use xmlPath var in fixPublicResourceIDs
jseigelis Dec 3, 2021
6dc2040
Fix null drawables
jseigelis Dec 3, 2021
6832bff
Forgot alpha
jseigelis Dec 3, 2021
81d4ad3
Tabs to spaces
jseigelis Dec 29, 2021
176a6d9
Update comment to include tracked issue
jseigelis Feb 9, 2022
04bbd7e
Fix private resources blocking builds
jseigelis Aug 11, 2022
0ce0970
Extra logging
jseigelis Aug 11, 2022
8ebb923
Use `NULL_DECODED_DRAWABLE_COLOR` const
jseigelis Aug 11, 2022
7d30047
Smarter `rawREReplace`
jseigelis Aug 11, 2022
bdc9afc
Supported version check disclaimer for this fork
jseigelis Aug 11, 2022
03e857b
this was bothering me today
jseigelis Nov 1, 2022
e8553b8
style
jseigelis Dec 12, 2022
1baa928
Merge pull request #1 from jseigelis/master
TheDauntless Feb 22, 2023
3536a06
Some refactoring
Feb 22, 2023
3c7d234
Bunch of improvements and refactoring
Feb 22, 2023
be384ba
Update documentation
Feb 22, 2023
f52baec
It's 2023
Feb 22, 2023
0458b8b
Remove apktool warning
Aug 23, 2023
1eddebe
Remove split properties from <manifest> tag
TheDauntless Oct 10, 2024
cba9cd5
Add multi-user support
TheDauntless Oct 10, 2024
d6519d9
Update changelog
TheDauntless Oct 15, 2024
baa948a
Replace deprecated pkg_resources usage with packaging.version
lsellens Apr 8, 2025
418f32f
Merge pull request #8 from lsellens/packaging
TheDauntless Apr 16, 2025
3051718
Fixes No module named packaging TheDauntless/patch-apk#9
TheDauntless Jul 7, 2025
2529f48
apktool has changed the version command. Fixes Invalid version: Apkto…
TheDauntless Jul 7, 2025
4579bbe
Fixes Unrecognized command: --use-aapt2 TheDauntless/patch-apk#11
TheDauntless Jul 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
patch-apk-dbg.py
.DS_Store
186 changes: 113 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# :warning: Active fork for NickstaDB/patch-apk

As the original projects has been set to read-only, I've created an active fork which combines most interesting modifications. If you identify any issues, please open a ticket.

Original credit goes to @NickstaDB and significant modifications were made by myself and @jseigelis

# patch-apk - App Bundle/Split APK Aware Patcher for Objection #
An APK patcher, for use with [objection](https://github.com/sensepost/objection), that supports Android app bundles/split APKs. It automates the following:

Expand All @@ -11,6 +17,19 @@ An APK patcher, for use with [objection](https://github.com/sensepost/objection)

### Changelog ###

* **10th October 2024:**
* Added mult-user support. If the apk file path can't be found for the default user, it will try other users
* Remove split-apk tags from <manifest>. Doesn't seem to be documented, but Android verifies these too.

* **22nd February 2023:** Took over project and added various features:
* Merged modifications from @jseigelis's fork
* Removed support for outdated objection versions
* Fixed bug for `--debug-output`
* Added `--verbose` flag
* Fixed bug with objection AndroidManifest extraction
* Updated output format
* Remove dependency on apksigner by using objection's signapk command

* **29th April 2021:** Implemented a fix for an issue with `apktool` where the handling of some resource XML elements changed and the `--use-aapt2` flag is required ([https://github.com/iBotPeaches/Apktool/issues/2462](https://github.com/iBotPeaches/Apktool/issues/2462)).
* **28th April 2021:** Fixed a bug with `objection` version detection when the `objection version` command output an update notice.
* **1st August 2020:** Updated for compatibility with `objection` version 1.9.3 and above and fixed a bug with line endings when retrieving package names from the Android device/emulator.
Expand Down Expand Up @@ -56,104 +75,125 @@ When `patch-apk.py` is done, the installed app should be patched with objection
**Partial Package Name Matching:** Pass a partial package name to `patch-apk.py` and it'll automatically grab the correct package name or ask you to confirm from available options.

```
$ python3 patch-apk.py ovid
Multiple matching packages installed, select the package to patch.
[1] com.android.providers.telephony
[2] com.android.providers.calendar
[3] com.android.providers.media
[4] com.android.providers.downloads
[5] com.android.providers.downloads.ui
[6] com.android.providers.settings
[7] com.android.providers.partnerbookmarks
[8] com.android.bookmarkprovider
[9] com.android.providers.blockednumber
[10] com.android.providers.userdictionary
[11] com.joinzoe.covid_zoe
[12] com.android.providers.contacts
Choice:
$ python3 patch-apk.py proxy

[!] Multiple matching packages installed, select the package to patch.

[1] org.proxydroid
[2] com.android.proxyhandler
Choice:

```

**Patching Split APKs:** Split APKs are automatically detected and combined into a single APK before patching. Split APKs can be identified by multiple APK paths being returned by the `adb shell pm path` command as shown below.

```
$ adb shell pm path com.joinzoe.covid_zoe
package:/data/app/com.joinzoe.covid_zoe-vck7Y7NlVGutCaaAbonakw==/base.apk
package:/data/app/com.joinzoe.covid_zoe-vck7Y7NlVGutCaaAbonakw==/split_config.arm64_v8a.apk
package:/data/app/com.joinzoe.covid_zoe-vck7Y7NlVGutCaaAbonakw==/split_config.en.apk
package:/data/app/com.joinzoe.covid_zoe-vck7Y7NlVGutCaaAbonakw==/split_config.xxhdpi.apk
$ adb shell pm path org.proxydroid
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/base.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.arm64_v8a.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.en.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.fr.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.nl.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.xxhdpi.apk
```

The following shows `patch-apk.py` detecting, rebuilding, and patching a split APK. Some output has been snipped for brevity.
The following shows `patch-apk.py` detecting, rebuilding, and patching a split APK. Some output has been snipped for brevity. The `-v` flag has been set to show additional info.

```
$ python3 patch-apk.py covid
Getting APK path(s) for package: com.joinzoe.covid_zoe
[+] APK path: /data/app/com.joinzoe.covid_zoe-vck7Y7NlVGutCaaAbonakw==/base.apk
[+] APK path: /data/app/com.joinzoe.covid_zoe-vck7Y7NlVGutCaaAbonakw==/split_config.arm64_v8a.apk
[+] APK path: /data/app/com.joinzoe.covid_zoe-vck7Y7NlVGutCaaAbonakw==/split_config.en.apk
[+] APK path: /data/app/com.joinzoe.covid_zoe-vck7Y7NlVGutCaaAbonakw==/split_config.xxhdpi.apk

Pulling APK file(s) from device.
[+] Pulling: com.joinzoe.covid_zoe-base.apk
[+] Pulling: com.joinzoe.covid_zoe-split_config.arm64_v8a.apk
[+] Pulling: com.joinzoe.covid_zoe-split_config.en.apk
[+] Pulling: com.joinzoe.covid_zoe-split_config.xxhdpi.apk

App bundle/split APK detected, rebuilding as a single APK.

Extracting individual APKs with apktool.
[+] Extracting: /tmp/tmp1kir74u_/com.joinzoe.covid_zoe-base.apk
[+] Extracting: /tmp/tmp1kir74u_/com.joinzoe.covid_zoe-split_config.arm64_v8a.apk
[+] Extracting: /tmp/tmp1kir74u_/com.joinzoe.covid_zoe-split_config.en.apk
[+] Extracting: /tmp/tmp1kir74u_/com.joinzoe.covid_zoe-split_config.xxhdpi.apk

Copying files and directories from split APKs into base APK.
[+] Creating directory in base APK: /lib
[+] Creating directory in base APK: /lib/arm64-v8a
[+] Moving file to base APK: /lib/arm64-v8a/libfb.so
...
[+] Moving file to base APK: /res/drawable-xxxhdpi/shell_launch_background_image.png
$ python3 patch-apk.py org.proxydroid -v

[+] Retrieving APK path(s) for package: org.proxydroid
[+] APK path: /data/app/~~FTVBmscrJiLerJdXIEa5tw==/org.proxydroid-KMq91nU1y9Qz8ZZAGM--RA==/base.apk
[+] APK path: /data/app/~~FTVBmscrJiLerJdXIEa5tw==/org.proxydroid-KMq91nU1y9Qz8ZZAGM--RA==/split_config.arm64_v8a.apk
[+] APK path: /data/app/~~FTVBmscrJiLerJdXIEa5tw==/org.proxydroid-KMq91nU1y9Qz8ZZAGM--RA==/split_config.en.apk
[+] APK path: /data/app/~~FTVBmscrJiLerJdXIEa5tw==/org.proxydroid-KMq91nU1y9Qz8ZZAGM--RA==/split_config.fr.apk
[+] APK path: /data/app/~~FTVBmscrJiLerJdXIEa5tw==/org.proxydroid-KMq91nU1y9Qz8ZZAGM--RA==/split_config.nl.apk
[+] APK path: /data/app/~~FTVBmscrJiLerJdXIEa5tw==/org.proxydroid-KMq91nU1y9Qz8ZZAGM--RA==/split_config.xxhdpi.apk

[+] Pulling APK file(s) from device |################################| 6/6
[+] Pulled: org.proxydroid-base.apk
[+] Pulled: org.proxydroid-split_config.arm64_v8a.apk
[+] Pulled: org.proxydroid-split_config.en.apk
[+] Pulled: org.proxydroid-split_config.fr.apk
[+] Pulled: org.proxydroid-split_config.nl.apk
[+] Pulled: org.proxydroid-split_config.xxhdpi.apk

[!] App bundle/split APK detected, rebuilding as a single APK.

[+] Disassembling split APKs |################################| 6/6

Extracted: /var/folders/t3/vz305z151ng8y2rwvpkx28xw0000gn/T/tmpyw7wl64i/org.proxydroid-base.apk
Extracted: /var/folders/t3/vz305z151ng8y2rwvpkx28xw0000gn/T/tmpyw7wl64i/org.proxydroid-split_config.arm64_v8a.apk
Extracted: /var/folders/t3/vz305z151ng8y2rwvpkx28xw0000gn/T/tmpyw7wl64i/org.proxydroid-split_config.en.apk
Extracted: /var/folders/t3/vz305z151ng8y2rwvpkx28xw0000gn/T/tmpyw7wl64i/org.proxydroid-split_config.fr.apk
Extracted: /var/folders/t3/vz305z151ng8y2rwvpkx28xw0000gn/T/tmpyw7wl64i/org.proxydroid-split_config.nl.apk
Extracted: /var/folders/t3/vz305z151ng8y2rwvpkx28xw0000gn/T/tmpyw7wl64i/org.proxydroid-split_config.xxhdpi.apk

[+] Rebuilding as a single APK

[+] Found public.xml in the base APK, fixing resource identifiers across split APKs.
[+] Resolving 21 resource identifiers.
[+] Located 21 true resource names.
[+] Updated 21 dummy resource names with true names in the base APK.
[+] Updated 47 references to dummy resource names in the base APK.
[+] Disabling APK splitting in AndroidManifest.xml of base APK.
[+] Fixing any improperly escaped ampersands.
[+] Forcing all private resources to be public
[+] Updated 350 private resources before building APK.
[+] Rebuilding with 'apktool --use-aapt2'.

[+] Patching org.proxydroid-base.apk with objection.

[+] Patching APK to enable support for user-installed CA certificates.
[+] Forcing all private resources to be public
[+] Updated 351 private resources before building APK.
[+] Rebuilding with 'apktool --use-aapt2'.
[+] Zip aligning new APK.
[+] Signing new APK.

[+] Uninstalling the original package from the device.

[+] Installing the patched APK to the device.

[+] Done
```

Found public.xml in the base APK, fixing resource identifiers across split APKs.
[+] Resolving 83 resource identifiers.
[+] Located 83 true resource names.
[+] Updated 83 dummy resource names with true names in the base APK.
[+] Updated 164 references to dummy resource names in the base APK.
After `patch-apk.py` completes, we can run `adb shell pm path` again to verify that there is now a single patched APK installed on the device.

Disabling APK splitting in AndroidManifest.xml of base APK.
```
$ adb shell pm path org.proxydroid
package:/data/app/org.proxydroid-9NuZnT-lK3qM_IZQEHhTgA==/base.apk
```

Rebuilding as a single APK.
[+] Building APK with apktool.
[+] Signing new APK.
[+] Zip aligning new APK.
By default, patch-apk will inject the frida gadget and modify the network security config. It is also possible to only perform an extraction by providing the `--extract-only` flag. Any split apks will still be merged and a local copy of the APK will be produced:

Patching com.joinzoe.covid_zoe-base.apk with objection.
```
$ python3 patch-apk.py org.proxydroid --extract-only

Patching APK to enable support for user-installed CA certificates.
[+] Retrieving APK path(s) for package: org.proxydroid

Uninstalling the original package from the device.
[+] Pulling APK file(s) from device |################################| 6/6

Installing the patched APK to the device.
[!] App bundle/split APK detected, rebuilding as a single APK.

Done, cleaning up temporary files.
```
[+] Disassembling split APKs |################################| 6/6

After `patch-apk.py` completes, we can run `adb shell pm path` again to verify that there is now a single patched APK installed on the device.
[+] Rebuilding as a single APK

```
$ adb shell pm path com.joinzoe.covid_zoe
package:/data/app/com.joinzoe.covid_zoe-9NuZnT-lK3qM_IZQEHhTgA==/base.apk
[+] Saving a copy of the APK to org.proxydroid.apk
```

## Combining Split APKs ##
Split APKs have been supported since Android 5/Lollipop (June 2014, API level 21). Essentially this allows an app to be split across multiple APK files, for example one might contain the main code and another might contain image resources for a given screen resolution. We can identify whether an app uses split APKs with the `adb shell pm path` command like so:

```
$ adb shell pm path com.joinzoe.covid_zoe
package:/data/app/com.joinzoe.covid_zoe-NW8ZbgI5VPzvSZ1NgMa4CQ==/base.apk
package:/data/app/com.joinzoe.covid_zoe-NW8ZbgI5VPzvSZ1NgMa4CQ==/split_config.arm64_v8a.apk
package:/data/app/com.joinzoe.covid_zoe-NW8ZbgI5VPzvSZ1NgMa4CQ==/split_config.en.apk
package:/data/app/com.joinzoe.covid_zoe-NW8ZbgI5VPzvSZ1NgMa4CQ==/split_config.xxhdpi.apk
$ adb shell pm path org.proxydroid
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/base.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.arm64_v8a.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.en.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.fr.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.nl.apk
package:/data/app/~~TP7sglBuEoDc3yH0wpZdiA==/org.proxydroid-PCy1JxTMVJT3KmxVqaagGQ==/split_config.xxhdpi.apk
```

These can be combined into a single APK for use with other tools such as `objection patchapk`. This is done by `patch-apk.py` as follows:
Expand Down
Loading