From d4c525509cbac8d23dec4a9935bbca7f83117aa6 Mon Sep 17 00:00:00 2001 From: Aan <6284204+aancw@users.noreply.github.com> Date: Wed, 17 Sep 2025 18:08:23 +0700 Subject: [PATCH 1/4] Update apktool command to use `v` instead of `-version` for latest support --- objection/utils/patchers/android.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index 7127bab5..78dc64ed 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -227,7 +227,7 @@ def is_apktool_ready(self) -> bool: o = delegator.run(self.list2cmdline([ self.required_commands['apktool']['location'], - '-version', + 'v', ]), timeout=self.command_run_timeout).out.strip() # On windows we get this 'Press any key to continue' thing, From f4072c0bdad0d329d27a3270225575aa0fad4c74 Mon Sep 17 00:00:00 2001 From: Aan <6284204+aancw@users.noreply.github.com> Date: Wed, 17 Sep 2025 18:16:46 +0700 Subject: [PATCH 2/4] fix: prevent empty string arguments in apktool command via filter(None) --- objection/utils/patchers/android.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index 78dc64ed..a06aab19 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -400,16 +400,21 @@ def unpack_apk(self, fix_concurrency_to = None): click.secho('Unpacking {0}'.format(self.apk_source), dim=True) - o = delegator.run(self.list2cmdline([ - self.required_commands['apktool']['location'], - 'decode', - '-f', - '-r' if self.skip_resources else '', - '--only-main-classes' if self.only_main_classes else '', - '-o', - self.apk_temp_directory, - self.apk_source - ] + ([] if fix_concurrency_to is None else ['-j', fix_concurrency_to])), timeout=self.command_run_timeout) + o = delegator.run( + self.list2cmdline(filter(None, [ + self.required_commands['apktool']['location'], + 'decode', + '-f', + '-r' if self.skip_resources else None, + '--only-main-classes' if self.only_main_classes else None, + '-o', + self.apk_temp_directory, + self.apk_source, + '-j' if fix_concurrency_to else None, + fix_concurrency_to + ])), + timeout=self.command_run_timeout + ) if len(o.err) > 0: click.secho('An error may have occurred while extracting the APK.', fg='red') From a360305809203ab2865c91cb9fd0659d28637ba8 Mon Sep 17 00:00:00 2001 From: Aan <6284204+aancw@users.noreply.github.com> Date: Wed, 17 Sep 2025 19:45:21 +0700 Subject: [PATCH 3/4] chore: remove --use-aapt2 flag as apktool now uses aapt2 by default --- objection/commands/mobile_packages.py | 2 +- objection/utils/patchers/android.py | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/objection/commands/mobile_packages.py b/objection/commands/mobile_packages.py index ad3b61ac..137338a2 100644 --- a/objection/commands/mobile_packages.py +++ b/objection/commands/mobile_packages.py @@ -223,7 +223,7 @@ def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: input('Press ENTER to continue...') - patcher.build_new_apk(use_aapt2=use_aapt2, fix_concurrency_to=fix_concurrency_to) + patcher.build_new_apk(fix_concurrency_to=fix_concurrency_to) patcher.zipalign_apk() if not skip_signing: patcher.sign_apk() diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index a06aab19..8e5ca8dc 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -883,7 +883,7 @@ def add_gadget_to_apk(self, architecture: str, gadget_source: str, gadget_config click.secho('Adding a gadget configuration file...', fg='green') shutil.copyfile(gadget_config, os.path.join(libs_path, 'libfrida-gadget.config.so')) - def build_new_apk(self, use_aapt2: bool = False, fix_concurrency_to = None): + def build_new_apk(self, fix_concurrency_to = None): """ Build a new .apk with the frida-gadget patched in. @@ -892,15 +892,17 @@ def build_new_apk(self, use_aapt2: bool = False, fix_concurrency_to = None): click.secho('Rebuilding the APK with the frida-gadget loaded...', fg='green', dim=True) o = delegator.run( - self.list2cmdline([self.required_commands['apktool']['location'], - 'build', - self.apk_temp_directory, - ] + (['--use-aapt2'] if use_aapt2 else []) + [ - '-o', - self.apk_temp_frida_patched - ]+ ([] if fix_concurrency_to is None else ['-j', fix_concurrency_to])) - , timeout=self.command_run_timeout) - + self.list2cmdline(filter(None, [ + self.required_commands['apktool']['location'], + 'b', + self.apk_temp_directory, + '-o', + self.apk_temp_frida_patched, + '-j' if fix_concurrency_to else None, + fix_concurrency_to + ])), + timeout=self.command_run_timeout + ) if len(o.err) > 0: click.secho(('Rebuilding the APK may have failed. Read the following ' From 8d72a804e8b8176573ef30a76b42dfb7ff2ac4d8 Mon Sep 17 00:00:00 2001 From: Aan <6284204+aancw@users.noreply.github.com> Date: Wed, 17 Sep 2025 19:57:51 +0700 Subject: [PATCH 4/4] feat: switch from aapt to aapt2 --- objection/utils/patchers/android.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index 8e5ca8dc..fc65575c 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -182,8 +182,8 @@ class AndroidPatcher(BasePlatformPatcher): """ Class used to patch Android APK's""" required_commands = { - 'aapt': { - 'installation': 'apt install aapt (Kali Linux)' + 'aapt2': { + 'installation': 'Install aapt2 from https://developer.android.com/build/building-cmdline#download_aapt2' }, 'adb': { 'installation': 'apt install adb (Kali Linux); brew install adb (macOS)' @@ -206,7 +206,7 @@ def __init__(self, skip_cleanup: bool = False, skip_resources: bool = False, man self.apk_temp_directory = tempfile.mkdtemp(suffix='.apktemp') self.apk_temp_frida_patched = self.apk_temp_directory + '.objection.apk' self.apk_temp_frida_patched_aligned = self.apk_temp_directory + '.aligned.objection.apk' - self.aapt = None + self.aapt2 = None self.skip_cleanup = skip_cleanup self.skip_resources = skip_resources self.manifest = manifest @@ -298,26 +298,26 @@ def _get_android_manifest(self) -> ElementTree: def _get_appt_output(self): """ - Get the output of `aapt dump badging`. + Get the output of `aapt2 dump badging`. :return: """ - if not self.aapt: + if not self.aapt2: o = delegator.run(self.list2cmdline([ - self.required_commands['aapt']['location'], + self.required_commands['aapt2']['location'], 'dump', 'badging', self.apk_source ]), timeout=self.command_run_timeout) if len(o.err) > 0: - click.secho('An error may have occurred while running aapt.', fg='red') + click.secho('An error may have occurred while running aapt2.', fg='red') click.secho(o.err, fg='red') - self.aapt = o.out + self.aapt2 = o.out - return self.aapt + return self.aapt2 def _get_launchable_activity(self) -> str: """ @@ -419,7 +419,7 @@ def unpack_apk(self, fix_concurrency_to = None): if len(o.err) > 0: click.secho('An error may have occurred while extracting the APK.', fg='red') click.secho(o.err, fg='red') - + def inject_internet_permission(self): """ Checks the status of the source APK to see if it