From 0954bae7df3e72d12978d1dddb112f44e84446e0 Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Sat, 12 Nov 2022 11:30:00 +0100 Subject: [PATCH 01/11] Make it clearer which flags are enabled by default --- objection/commands/mobile_packages.py | 1 - objection/console/cli.py | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/objection/commands/mobile_packages.py b/objection/commands/mobile_packages.py index 59efd6d5..32d638b6 100644 --- a/objection/commands/mobile_packages.py +++ b/objection/commands/mobile_packages.py @@ -122,7 +122,6 @@ def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: :return: """ - github = Github(gadget_version=gadget_version) android_gadget = AndroidGadget(github) diff --git a/objection/console/cli.py b/objection/console/cli.py index 14e6c701..be7b74c6 100644 --- a/objection/console/cli.py +++ b/objection/console/cli.py @@ -54,7 +54,7 @@ def get_agent() -> Agent: @click.option('--debugger', required=False, default=False, is_flag=True, help='Enable the Chrome debug port.') @click.option('--uid', required=False, default=None, help='Specify the uid to run as (Android only).') def cli(network: bool, host: str, port: int, api_host: str, api_port: int, - name: str, serial: str, debug: bool, spawn: bool, no_pause: bool, + name: str, serial: str, debug: bool, spawn: bool, no_pause: bool, foremost: bool, debugger: bool, uid: int) -> None: """ \b @@ -255,20 +255,21 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio 'specified, the latest version will be used.'), default=None) @click.option('--pause', '-p', is_flag=True, help='Pause the patcher before rebuilding the APK.', show_default=True) -@click.option('--skip-cleanup', '-k', is_flag=True, +@click.option('--skip-cleanup', '-k', is_flag=True, default=True, help='Do not clean temporary files once finished.', show_default=True) -@click.option('--enable-debug', '-d', is_flag=True, +@click.option('--enable-debug', '-d', is_flag=True, default=True, help='Set the android:debuggable flag to true in the application manifest.', show_default=True) @click.option('--network-security-config', '-N', is_flag=True, default=False, help='Include a network_security_config.xml file allowing for user added CA\'s to be trusted on ' - 'Android 7 and up. This option can not be used with the --skip-resources flag.') + 'Android 7 and up. This option can not be used with the --skip-resources flag.', + show_default=True) @click.option('--skip-resources', '-D', is_flag=True, default=False, help='Skip resource decoding as part of the apktool processing.', show_default=False) @click.option('--skip-signing', '-C', is_flag=True, default=False, help='Skip signing the apk file.', show_default=False) @click.option('--target-class', '-t', help='The target class to patch.', default=None) @click.option('--use-aapt2', '-2', is_flag=True, default=False, - help='Use the aapt2 binary instead of aapt as part of the apktool processing.', show_default=False) + help='Use the aapt2 binary instead of aapt as part of the apktool processing.', show_default=True) @click.option('--gadget-config', '-c', default=None, help=( 'The gadget configuration file to use. ' 'Refer to https://frida.re/docs/gadget/ for more information.'), show_default=False) From 6994adaffc8d13f59f701b3ea195da70b7f81e09 Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Sat, 12 Nov 2022 11:30:22 +0100 Subject: [PATCH 02/11] Inject through shared library whenever possible --- objection/utils/patchers/android.py | 24 +++++++++++++++++++++++- requirements.txt | 1 + 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index a843a9d3..8ba46755 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -8,6 +8,7 @@ import click import delegator +import lief import requests import semver @@ -211,6 +212,8 @@ def __init__(self, skip_cleanup: bool = False, skip_resources: bool = False, man self.skip_resources = skip_resources self.manifest = manifest + self.architecture = None + self.keystore = os.path.join(os.path.abspath(os.path.dirname(__file__)), '../assets', 'objection.jks') self.netsec_config = os.path.join(os.path.abspath(os.path.dirname(__file__)), '../assets', 'network_security_config.xml') @@ -822,8 +825,26 @@ def inject_load_library(self, target_class: str = None): if target_class: click.secho('Using target class: {0} for patch'.format(target_class), fg='green', bold=True) else: - click.secho('Target class not specified, searching for launchable activity instead...', fg='green', + click.secho('Target class not specified, injecting through existing native libraries...', fg='green', bold=True) + # Inspired by https://fadeevab.com/frida-gadget-injection-on-android-no-root-2-methods/ + if not self.architecture: + raise Exception('Frida-gadget should have been copied prior to injecting!') + libs_path = os.path.join(self.apk_temp_directory, 'lib', self.architecture) + existing_libs_in_apk = [ + lib + for lib in os.listdir(libs_path) + if lib not in ['libfrida-gadget.so', self.libfridagadgetconfig_name] + ] + if existing_libs_in_apk: + for lib in existing_libs_in_apk: + libnative = lief.parse(os.path.join(libs_path, lib)) + libnative.add_library('libfrida-gadget.so') # Injection! + libnative.write(os.path.join(libs_path, lib)) + return + else: + click.secho('No native libraries found in APK, searching for launchable activity instead...', fg='green', + bold=True) activity_path = self._determine_smali_path_for_class( target_class if target_class else self._get_launchable_activity()) @@ -863,6 +884,7 @@ def add_gadget_to_apk(self, architecture: str, gadget_source: str, gadget_config :param gadget_config: :return: """ + self.architecture = architecture libs_path = os.path.join(self.apk_temp_directory, 'lib', architecture) diff --git a/requirements.txt b/requirements.txt index 1f678cfa..4bac5e88 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ requests Flask>=3.0.0 Pygments>=2.0.0 litecli>=1.3.0 +lief From 8b4f12231c26eb192ff18227ccdebfd3668bc5b5 Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Sat, 12 Nov 2022 11:39:55 +0100 Subject: [PATCH 03/11] Let user specify an alternative name for the Frida gadget library --- objection/commands/mobile_packages.py | 12 +++++++++--- objection/console/cli.py | 13 ++++++++++++- objection/utils/patchers/android.py | 17 +++++++++++------ 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/objection/commands/mobile_packages.py b/objection/commands/mobile_packages.py index 32d638b6..7cb83cbb 100644 --- a/objection/commands/mobile_packages.py +++ b/objection/commands/mobile_packages.py @@ -99,8 +99,9 @@ def patch_ios_ipa(source: str, codesign_signature: str, provision_file: str, bin def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: bool = True, enable_debug: bool = True, gadget_version: str = None, skip_resources: bool = False, network_security_config: bool = False, target_class: str = None, - use_aapt2: bool = False, gadget_config: str = None, script_source: str = None, - ignore_nativelibs: bool = True, manifest: str = None, skip_signing: bool = False, only_main_classes: bool = False) -> None: + use_aapt2: bool = False, gadget_name: str = 'libfrida-gadget.so', + gadget_config: str = None, script_source: str = None, + ignore_nativelibs: bool = True, manifest: str = None, skip_signing: bool = False) -> None: """ Patches an Android APK by extracting, patching SMALI, repackaging and signing a new APK. @@ -115,6 +116,7 @@ def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: :param network_security_config: :param target_class: :param use_aapt2: + :param gadget_name: :param gadget_config: :param script_source: :param manifest: @@ -200,8 +202,12 @@ def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: if network_security_config: patcher.add_network_security_config() + patcher.add_gadget_to_apk( + architecture, + android_gadget.get_frida_library_path(), gadget_config, + gadget_name + ) patcher.inject_load_library(target_class=target_class) - patcher.add_gadget_to_apk(architecture, android_gadget.get_frida_library_path(), gadget_config) if script_source: click.secho('Copying over a custom script to use with the gadget config.', fg='green') diff --git a/objection/console/cli.py b/objection/console/cli.py index be7b74c6..8725d6a4 100644 --- a/objection/console/cli.py +++ b/objection/console/cli.py @@ -270,6 +270,12 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio @click.option('--target-class', '-t', help='The target class to patch.', default=None) @click.option('--use-aapt2', '-2', is_flag=True, default=False, help='Use the aapt2 binary instead of aapt as part of the apktool processing.', show_default=True) +@click.option('--gadget-name', '-g', default='libfrida-gadget.so', + help=( + 'Name of the gadget library. Can be named whatever you want to dodge anti-frida ' + 'detection schemes looking for loaded libraries with frida in the name.' + 'Refer to https://frida.re/docs/gadget/ for more information.'), + show_default=True) @click.option('--gadget-config', '-c', default=None, help=( 'The gadget configuration file to use. ' 'Refer to https://frida.re/docs/gadget/ for more information.'), show_default=False) @@ -282,7 +288,7 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio @click.option('--only-main-classes', help="Only patch classes that are in the main dex file.", is_flag=True, default=False) def patchapk(source: str, architecture: str, gadget_version: str, pause: bool, skip_cleanup: bool, enable_debug: bool, skip_resources: bool, network_security_config: bool, target_class: str, - use_aapt2: bool, gadget_config: str, script_source: str, ignore_nativelibs: bool, manifest: str, skip_signing: bool, only_main_classes:bool = False) -> None: + use_aapt2: bool, gadget_name: str, gadget_config: str, script_source: str, ignore_nativelibs: bool, manifest: str, skip_signing: bool, only_main_classes:bool = False) -> None: """ Patch an APK with the frida-gadget.so. """ @@ -302,6 +308,11 @@ def patchapk(source: str, architecture: str, gadget_version: str, pause: bool, s click.secho('The --ignore-nativelibs flag is required with the --skip-resources flag.', fg='red') return + # ensure provided gadget name is a valid android lib name + if not gadget_name.startswith('lib') or not gadget_name.endswith('.so'): + click.secho("Gadget name should start with 'lib' and end in '.so'", fg='red') + return + patch_android_apk(**locals()) diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index 8ba46755..186a96b1 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -828,18 +828,18 @@ def inject_load_library(self, target_class: str = None): click.secho('Target class not specified, injecting through existing native libraries...', fg='green', bold=True) # Inspired by https://fadeevab.com/frida-gadget-injection-on-android-no-root-2-methods/ - if not self.architecture: + if not self.architecture or not self.libfridagadget_name: raise Exception('Frida-gadget should have been copied prior to injecting!') libs_path = os.path.join(self.apk_temp_directory, 'lib', self.architecture) existing_libs_in_apk = [ lib for lib in os.listdir(libs_path) - if lib not in ['libfrida-gadget.so', self.libfridagadgetconfig_name] + if lib not in [self.libfridagadget_name, self.libfridagadgetconfig_name] ] if existing_libs_in_apk: for lib in existing_libs_in_apk: libnative = lief.parse(os.path.join(libs_path, lib)) - libnative.add_library('libfrida-gadget.so') # Injection! + libnative.add_library(self.libfridagadget_name) # Injection! libnative.write(os.path.join(libs_path, lib)) return else: @@ -874,7 +874,9 @@ def inject_load_library(self, target_class: str = None): with open(activity_path, 'w') as f: f.write(''.join(patched_smali)) - def add_gadget_to_apk(self, architecture: str, gadget_source: str, gadget_config: str): + def add_gadget_to_apk(self, architecture: str, + gadget_source: str, gadget_config: str, + libfridagadget_name: str = 'libfrida-gadget.so'): """ Copies a frida gadget for a specific architecture to an extracted APK's lib path. @@ -882,9 +884,12 @@ def add_gadget_to_apk(self, architecture: str, gadget_source: str, gadget_config :param architecture: :param gadget_source: :param gadget_config: + :param libfridagadget_name: :return: """ self.architecture = architecture + self.libfridagadget_name = libfridagadget_name + self.libfridagadgetconfig_name = libfridagadget_name.replace('.so', '.config.so') libs_path = os.path.join(self.apk_temp_directory, 'lib', architecture) @@ -894,11 +899,11 @@ def add_gadget_to_apk(self, architecture: str, gadget_source: str, gadget_config os.makedirs(libs_path) click.secho('Copying Frida gadget to libs path...', fg='green', dim=True) - shutil.copyfile(gadget_source, os.path.join(libs_path, 'libfrida-gadget.so')) + shutil.copyfile(gadget_source, os.path.join(libs_path, self.libfridagadget_name)) if gadget_config: click.secho('Adding a gadget configuration file...', fg='green') - shutil.copyfile(gadget_config, os.path.join(libs_path, 'libfrida-gadget.config.so')) + shutil.copyfile(gadget_config, os.path.join(libs_path, self.libfridagadgetconfig_name)) def build_new_apk(self, use_aapt2: bool = False): """ From 7a678f8dd2269bcb66d6939820dc5e7d9c2325ae Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Sat, 12 Nov 2022 12:10:46 +0100 Subject: [PATCH 04/11] Fuzzy match of architectures in APK tree --- objection/utils/patchers/android.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index 186a96b1..bbf1b2ae 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -1,4 +1,5 @@ import contextlib +import functools import lzma import os import re @@ -805,6 +806,30 @@ def _h(): return patched_smali + @functools.cache + def _find_libs_path(self): + """ + Find the libraries path for the target architecture within the APK. + """ + base_libs_path = os.path.join(self.apk_temp_directory, 'lib') + available_libs_arch = os.listdir(base_libs_path) + if self.architecture in available_libs_arch: + # Exact match with arch + return os.path.join(base_libs_path, self.architecture) + else: + # Try to use prefix search + try: + matching_arch = next( + item for item in available_libs_arch if item.startswith(self.architecture) + ) + click.secho('Using matching architecture {0} from provided architecture {1}.'.format( + matching_arch, self.architecture + ), dim=True) + return os.path.join(base_libs_path, matching_arch) + except StopIteration: + # Might create the arch folder inside the APK tree + return os.path.join(base_libs_path, self.architecture) + def inject_load_library(self, target_class: str = None): """ Injects a loadLibrary call into a class. @@ -830,7 +855,7 @@ def inject_load_library(self, target_class: str = None): # Inspired by https://fadeevab.com/frida-gadget-injection-on-android-no-root-2-methods/ if not self.architecture or not self.libfridagadget_name: raise Exception('Frida-gadget should have been copied prior to injecting!') - libs_path = os.path.join(self.apk_temp_directory, 'lib', self.architecture) + libs_path = self._find_libs_path() existing_libs_in_apk = [ lib for lib in os.listdir(libs_path) @@ -891,7 +916,7 @@ def add_gadget_to_apk(self, architecture: str, self.libfridagadget_name = libfridagadget_name self.libfridagadgetconfig_name = libfridagadget_name.replace('.so', '.config.so') - libs_path = os.path.join(self.apk_temp_directory, 'lib', architecture) + libs_path = self._find_libs_path() # check if the libs path exists if not os.path.exists(libs_path): From 3d6161ba9cb77bfa788c23cc8288c8d33c75fcdf Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Sat, 12 Nov 2022 12:12:44 +0100 Subject: [PATCH 05/11] Use aapt2 by default From https://developer.android.com/studio/command-line/aapt2 > Prior to AAPT2, AAPT was the default version of Android Asset Packaging Tool and it has now been deprecated. Although AAPT2 should immediately work with older projects, this section describes some behavior changes that you should be aware of. --- objection/commands/mobile_packages.py | 2 +- objection/console/cli.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/objection/commands/mobile_packages.py b/objection/commands/mobile_packages.py index 7cb83cbb..d979795b 100644 --- a/objection/commands/mobile_packages.py +++ b/objection/commands/mobile_packages.py @@ -99,7 +99,7 @@ def patch_ios_ipa(source: str, codesign_signature: str, provision_file: str, bin def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: bool = True, enable_debug: bool = True, gadget_version: str = None, skip_resources: bool = False, network_security_config: bool = False, target_class: str = None, - use_aapt2: bool = False, gadget_name: str = 'libfrida-gadget.so', + use_aapt2: bool = True, gadget_name: str = 'libfrida-gadget.so', gadget_config: str = None, script_source: str = None, ignore_nativelibs: bool = True, manifest: str = None, skip_signing: bool = False) -> None: """ diff --git a/objection/console/cli.py b/objection/console/cli.py index 8725d6a4..2d7ca6d4 100644 --- a/objection/console/cli.py +++ b/objection/console/cli.py @@ -268,8 +268,8 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio @click.option('--skip-signing', '-C', is_flag=True, default=False, help='Skip signing the apk file.', show_default=False) @click.option('--target-class', '-t', help='The target class to patch.', default=None) -@click.option('--use-aapt2', '-2', is_flag=True, default=False, - help='Use the aapt2 binary instead of aapt as part of the apktool processing.', show_default=True) +@click.option('--use-aapt2', '-2', is_flag=True, default=True, + help='Use the aapt2 binary instead of aapt au part of the apktool processing.', show_default=True) @click.option('--gadget-name', '-g', default='libfrida-gadget.so', help=( 'Name of the gadget library. Can be named whatever you want to dodge anti-frida ' From 77b9b3502f257d82436a68e9a0efbfddd0848f75 Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Thu, 13 Jun 2024 12:05:10 +0200 Subject: [PATCH 06/11] Revert default value for --enable-debug --- objection/console/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objection/console/cli.py b/objection/console/cli.py index 2d7ca6d4..0d7b956f 100644 --- a/objection/console/cli.py +++ b/objection/console/cli.py @@ -257,7 +257,7 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio show_default=True) @click.option('--skip-cleanup', '-k', is_flag=True, default=True, help='Do not clean temporary files once finished.', show_default=True) -@click.option('--enable-debug', '-d', is_flag=True, default=True, +@click.option('--enable-debug', '-d', is_flag=True, help='Set the android:debuggable flag to true in the application manifest.', show_default=True) @click.option('--network-security-config', '-N', is_flag=True, default=False, help='Include a network_security_config.xml file allowing for user added CA\'s to be trusted on ' From 6669696a99017cac202488a6fee31a340ecc17ac Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Thu, 13 Jun 2024 12:05:45 +0200 Subject: [PATCH 07/11] Revert change on skip-cleanup --- objection/console/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objection/console/cli.py b/objection/console/cli.py index 0d7b956f..db1409aa 100644 --- a/objection/console/cli.py +++ b/objection/console/cli.py @@ -255,7 +255,7 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio 'specified, the latest version will be used.'), default=None) @click.option('--pause', '-p', is_flag=True, help='Pause the patcher before rebuilding the APK.', show_default=True) -@click.option('--skip-cleanup', '-k', is_flag=True, default=True, +@click.option('--skip-cleanup', '-k', is_flag=True, help='Do not clean temporary files once finished.', show_default=True) @click.option('--enable-debug', '-d', is_flag=True, help='Set the android:debuggable flag to true in the application manifest.', show_default=True) From c58766edb3077018d6e0fa1b02d86ec40b2aced7 Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Thu, 13 Jun 2024 12:13:37 +0200 Subject: [PATCH 08/11] Pin lief minimum version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4bac5e88..5cc95715 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,4 @@ requests Flask>=3.0.0 Pygments>=2.0.0 litecli>=1.3.0 -lief +lief>=0.14.0 From a93855c1de1714d65699c53065da86ba52e47166 Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Thu, 13 Jun 2024 12:18:15 +0200 Subject: [PATCH 09/11] review --- objection/commands/mobile_packages.py | 7 ++++--- objection/console/cli.py | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/objection/commands/mobile_packages.py b/objection/commands/mobile_packages.py index d979795b..3e3a375c 100644 --- a/objection/commands/mobile_packages.py +++ b/objection/commands/mobile_packages.py @@ -99,9 +99,9 @@ def patch_ios_ipa(source: str, codesign_signature: str, provision_file: str, bin def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: bool = True, enable_debug: bool = True, gadget_version: str = None, skip_resources: bool = False, network_security_config: bool = False, target_class: str = None, - use_aapt2: bool = True, gadget_name: str = 'libfrida-gadget.so', + use_aapt2: bool = False, gadget_name: str = 'libfrida-gadget.so', gadget_config: str = None, script_source: str = None, - ignore_nativelibs: bool = True, manifest: str = None, skip_signing: bool = False) -> None: + ignore_nativelibs: bool = True, manifest: str = None, skip_signing: bool = False, only_main_classes: bool = False) -> None: """ Patches an Android APK by extracting, patching SMALI, repackaging and signing a new APK. @@ -204,7 +204,8 @@ def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: patcher.add_gadget_to_apk( architecture, - android_gadget.get_frida_library_path(), gadget_config, + android_gadget.get_frida_library_path(), + gadget_config, gadget_name ) patcher.inject_load_library(target_class=target_class) diff --git a/objection/console/cli.py b/objection/console/cli.py index db1409aa..f5e258f7 100644 --- a/objection/console/cli.py +++ b/objection/console/cli.py @@ -261,8 +261,7 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio help='Set the android:debuggable flag to true in the application manifest.', show_default=True) @click.option('--network-security-config', '-N', is_flag=True, default=False, help='Include a network_security_config.xml file allowing for user added CA\'s to be trusted on ' - 'Android 7 and up. This option can not be used with the --skip-resources flag.', - show_default=True) + 'Android 7 and up. This option can not be used with the --skip-resources flag.') @click.option('--skip-resources', '-D', is_flag=True, default=False, help='Skip resource decoding as part of the apktool processing.', show_default=False) @click.option('--skip-signing', '-C', is_flag=True, default=False, From 21e282dad912eea14b0473064c9a25276d6ec5d7 Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Thu, 13 Jun 2024 12:23:29 +0200 Subject: [PATCH 10/11] Move from --skpi-resources to --decode-resources flag --- objection/commands/mobile_packages.py | 6 +++--- objection/console/cli.py | 20 ++++++++++---------- objection/utils/patchers/android.py | 16 ++++++++-------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/objection/commands/mobile_packages.py b/objection/commands/mobile_packages.py index 3e3a375c..e32dbc89 100644 --- a/objection/commands/mobile_packages.py +++ b/objection/commands/mobile_packages.py @@ -97,7 +97,7 @@ def patch_ios_ipa(source: str, codesign_signature: str, provision_file: str, bin def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: bool = True, - enable_debug: bool = True, gadget_version: str = None, skip_resources: bool = False, + enable_debug: bool = True, gadget_version: str = None, decode_resources: bool = False, network_security_config: bool = False, target_class: str = None, use_aapt2: bool = False, gadget_name: str = 'libfrida-gadget.so', gadget_config: str = None, script_source: str = None, @@ -112,7 +112,7 @@ def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: :param skip_cleanup: :param enable_debug: :param gadget_version: - :param skip_resources: + :param decode_resources: :param network_security_config: :param target_class: :param use_aapt2: @@ -177,7 +177,7 @@ def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: click.secho('Patcher will be using Gadget version: {0}'.format(github_version), fg='green') - patcher = AndroidPatcher(skip_cleanup=skip_cleanup, skip_resources=skip_resources, manifest=manifest, only_main_classes=only_main_classes) + patcher = AndroidPatcher(skip_cleanup=skip_cleanup, decode_resources=decode_resources, manifest=manifest, only_main_classes=only_main_classes) # ensure that we have all of the commandline requirements if not patcher.are_requirements_met(): diff --git a/objection/console/cli.py b/objection/console/cli.py index f5e258f7..89cd9db4 100644 --- a/objection/console/cli.py +++ b/objection/console/cli.py @@ -261,9 +261,9 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio help='Set the android:debuggable flag to true in the application manifest.', show_default=True) @click.option('--network-security-config', '-N', is_flag=True, default=False, help='Include a network_security_config.xml file allowing for user added CA\'s to be trusted on ' - 'Android 7 and up. This option can not be used with the --skip-resources flag.') -@click.option('--skip-resources', '-D', is_flag=True, default=False, - help='Skip resource decoding as part of the apktool processing.', show_default=False) + 'Android 7 and up. This option requires the --decode-resources flag.') +@click.option('--decode-resources', '-D', is_flag=True, default=False, + help='Decode resource as part of the apktool processing.', show_default=False) @click.option('--skip-signing', '-C', is_flag=True, default=False, help='Skip signing the apk file.', show_default=False) @click.option('--target-class', '-t', help='The target class to patch.', default=None) @@ -286,25 +286,25 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio @click.option('--manifest', '-m', help='A decoded AndroidManifest.xml file to read.', default=None) @click.option('--only-main-classes', help="Only patch classes that are in the main dex file.", is_flag=True, default=False) def patchapk(source: str, architecture: str, gadget_version: str, pause: bool, skip_cleanup: bool, - enable_debug: bool, skip_resources: bool, network_security_config: bool, target_class: str, + enable_debug: bool, decode_resources: bool, network_security_config: bool, target_class: str, use_aapt2: bool, gadget_name: str, gadget_config: str, script_source: str, ignore_nativelibs: bool, manifest: str, skip_signing: bool, only_main_classes:bool = False) -> None: """ Patch an APK with the frida-gadget.so. """ # ensure we decode resources if we have the network-security-config flag. - if network_security_config and skip_resources: - click.secho('The --network-security-config flag is incompatible with the --skip-resources flag.', fg='red') + if network_security_config and not decode_resources: + click.secho('The --network-security-config flag requires the --decode-resources flag.', fg='red') return # ensure we decode resources if we have the enable-debug flag. - if enable_debug and skip_resources: - click.secho('The --enable-debug flag is incompatible with the --skip-resources flag.', fg='red') + if enable_debug and not decode_resources: + click.secho('The --enable-debug flag is incompatible with the --decode-resources flag.', fg='red') return # ensure we decode resources if we do not have the --ignore-nativelibs flag. - if not ignore_nativelibs and skip_resources: - click.secho('The --ignore-nativelibs flag is required with the --skip-resources flag.', fg='red') + if not ignore_nativelibs and not decode_resources: + click.secho('The --ignore-nativelibs flag is required with the --decode-resources flag.', fg='red') return # ensure provided gadget name is a valid android lib name diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index bbf1b2ae..8f485187 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -201,7 +201,7 @@ class AndroidPatcher(BasePlatformPatcher): } } - def __init__(self, skip_cleanup: bool = False, skip_resources: bool = False, manifest: str = None, only_main_classes: bool = False): + def __init__(self, skip_cleanup: bool = False, decode_resources: bool = False, manifest: str = None, only_main_classes: bool = False): super(AndroidPatcher, self).__init__() self.apk_source = None @@ -210,7 +210,7 @@ def __init__(self, skip_cleanup: bool = False, skip_resources: bool = False, man self.apk_temp_frida_patched_aligned = self.apk_temp_directory + '.aligned.objection.apk' self.aapt = None self.skip_cleanup = skip_cleanup - self.skip_resources = skip_resources + self.decode_resources = decode_resources self.manifest = manifest self.architecture = None @@ -287,11 +287,11 @@ def _get_android_manifest(self) -> ElementTree: :return: """ - # error if --skip-resources was used because the manifest is encoded - if self.skip_resources is True and self.manifest is None: - click.secho('Cannot manually parse the AndroidManifest.xml when --skip-resources ' - 'is set, remove this and try again, or manually specify a manifest with --manifest.', fg='red') - raise Exception('Cannot --skip-resources when trying to manually parse the AndroidManifest.xml') + # error if --decode-resources was not used because the manifest is encoded + if not self.decode_resources is True and self.manifest is None: + click.secho('Cannot manually parse the AndroidManifest.xml when --decoode-resources ' + 'is not set, add this and try again, or manually specify a manifest with --manifest.', fg='red') + raise Exception('Cannot --decode-resources when trying to manually parse the AndroidManifest.xml') # use the android namespace ElementTree.register_namespace('android', 'http://schemas.android.com/apk/res/android') @@ -408,7 +408,7 @@ def unpack_apk(self): self.required_commands['apktool']['location'], 'decode', '-f', - '-r' if self.skip_resources else '', + '-r' if not self.decode_resources else '', '--only-main-classes' if self.only_main_classes else '', '-o', self.apk_temp_directory, From c3aef7f5119f6a187f6e307518653def4e1c4c5f Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Thu, 13 Jun 2024 12:26:09 +0200 Subject: [PATCH 11/11] Switch --use-aapt2 to --use-aapt1 --- objection/commands/mobile_packages.py | 6 +++--- objection/console/cli.py | 6 +++--- objection/utils/patchers/android.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/objection/commands/mobile_packages.py b/objection/commands/mobile_packages.py index e32dbc89..65d90734 100644 --- a/objection/commands/mobile_packages.py +++ b/objection/commands/mobile_packages.py @@ -99,7 +99,7 @@ def patch_ios_ipa(source: str, codesign_signature: str, provision_file: str, bin def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: bool = True, enable_debug: bool = True, gadget_version: str = None, decode_resources: bool = False, network_security_config: bool = False, target_class: str = None, - use_aapt2: bool = False, gadget_name: str = 'libfrida-gadget.so', + use_aapt1: bool = False, gadget_name: str = 'libfrida-gadget.so', gadget_config: str = None, script_source: str = None, ignore_nativelibs: bool = True, manifest: str = None, skip_signing: bool = False, only_main_classes: bool = False) -> None: """ @@ -115,7 +115,7 @@ def patch_android_apk(source: str, architecture: str, pause: bool, skip_cleanup: :param decode_resources: :param network_security_config: :param target_class: - :param use_aapt2: + :param use_aapt1: :param gadget_name: :param gadget_config: :param script_source: @@ -225,7 +225,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) + patcher.build_new_apk(use_aapt1=use_aapt1) patcher.zipalign_apk() if not skip_signing: patcher.sign_apk() diff --git a/objection/console/cli.py b/objection/console/cli.py index 89cd9db4..38dd12bf 100644 --- a/objection/console/cli.py +++ b/objection/console/cli.py @@ -267,8 +267,8 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio @click.option('--skip-signing', '-C', is_flag=True, default=False, help='Skip signing the apk file.', show_default=False) @click.option('--target-class', '-t', help='The target class to patch.', default=None) -@click.option('--use-aapt2', '-2', is_flag=True, default=True, - help='Use the aapt2 binary instead of aapt au part of the apktool processing.', show_default=True) +@click.option('--use-aapt1', '-1', is_flag=True, default=False, + help='Use the aapt binary instead of aapt2 as part of the apktool processing.', show_default=True) @click.option('--gadget-name', '-g', default='libfrida-gadget.so', help=( 'Name of the gadget library. Can be named whatever you want to dodge anti-frida ' @@ -287,7 +287,7 @@ def patchipa(source: str, gadget_version: str, codesign_signature: str, provisio @click.option('--only-main-classes', help="Only patch classes that are in the main dex file.", is_flag=True, default=False) def patchapk(source: str, architecture: str, gadget_version: str, pause: bool, skip_cleanup: bool, enable_debug: bool, decode_resources: bool, network_security_config: bool, target_class: str, - use_aapt2: bool, gadget_name: str, gadget_config: str, script_source: str, ignore_nativelibs: bool, manifest: str, skip_signing: bool, only_main_classes:bool = False) -> None: + use_aapt1: bool, gadget_name: str, gadget_config: str, script_source: str, ignore_nativelibs: bool, manifest: str, skip_signing: bool, only_main_classes:bool = False) -> None: """ Patch an APK with the frida-gadget.so. """ diff --git a/objection/utils/patchers/android.py b/objection/utils/patchers/android.py index 8f485187..71a8825f 100644 --- a/objection/utils/patchers/android.py +++ b/objection/utils/patchers/android.py @@ -930,7 +930,7 @@ def add_gadget_to_apk(self, architecture: str, click.secho('Adding a gadget configuration file...', fg='green') shutil.copyfile(gadget_config, os.path.join(libs_path, self.libfridagadgetconfig_name)) - def build_new_apk(self, use_aapt2: bool = False): + def build_new_apk(self, use_aapt1: bool = False): """ Build a new .apk with the frida-gadget patched in. @@ -942,7 +942,7 @@ def build_new_apk(self, use_aapt2: bool = False): self.list2cmdline([self.required_commands['apktool']['location'], 'build', self.apk_temp_directory, - ] + (['--use-aapt2'] if use_aapt2 else []) + [ + ] + (['--use-aapt2'] if not use_aapt1 else []) + [ '-o', self.apk_temp_frida_patched ]), timeout=self.command_run_timeout)