Esempio n. 1
0
def add(args: list) -> None:
    """
        Adds a new keychain entry to the keychain

        :param args:
        :return:
    """

    if not _has_minimum_flags_to_add_item(args):
        click.secho(
            'Usage: ios keychain add --key <key name> --data <entry data>',
            bold=True)
        return

    key = _get_flag_value(args, '--key')
    value = _get_flag_value(args, '--data')

    click.secho('Adding a new entry to the iOS keychain...', dim=True)
    click.secho('Key:       {0}'.format(key), dim=True)
    click.secho('Value:     {0}'.format(value), dim=True)

    runner = FridaRunner()
    runner.set_hook_with_data(ios_hook('keychain/add'))

    api = runner.rpc_exports()

    if api.add(key, value):
        click.secho('Successfully added the keychain item', fg='green')
        return

    click.secho('Failed to add the keychain item', fg='red')
Esempio n. 2
0
def show_android_classes(args: list = None) -> None:
    """
        Show the currently loaded classes.

        :param args:
        :return:
    """

    hook = android_hook('hooking/list-classes')
    runner = FridaRunner(hook=hook)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to list classes with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return None

    # print the enumerated classes
    for class_name in sorted(response.data):
        click.secho(class_name)

    click.secho('\nFound {0} classes'.format(len(response.data)), bold=True)
Esempio n. 3
0
def show_registered_activities(args: list = None) -> None:
    """
        Enumerate all registered Activities

        :param args:
        :return:
    """

    hook = android_hook('hooking/list-activities')
    runner = FridaRunner(hook=hook)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to list activities with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return None

    if not response.data:
        click.secho('No activities were found', fg='yellow')
        return None

    for class_name in sorted(response.data):
        click.secho(class_name)

    click.secho('\nFound {0} classes'.format(len(response.data)), bold=True)
Esempio n. 4
0
def disable(args: list = None) -> None:
    """
        Attempts to disable jailbreak detection.

        :param args:
        :return:
    """

    hook = ios_hook('jailbreak/disable')

    runner = FridaRunner(hook=hook)
    runner.run_as_job(name='disable-jailbreak-detection')
Esempio n. 5
0
def simulate(args: list = None) -> None:
    """
        Attempts to simulate a Jailbroken environment

        :param args:
        :return:
    """

    hook = ios_hook('jailbreak/simulate')

    runner = FridaRunner(hook=hook)
    runner.run_as_job(name='simulate-jailbroken-environment')
Esempio n. 6
0
def dump(args: list = None) -> None:
    """
        Dump the iOS keychain

        :param args:
        :return:
    """

    if _should_output_json(args) and len(args) < 2:
        click.secho('Usage: ios keychain dump (--json <local destination>)', bold=True)
        return

    click.secho('Note: You may be asked to authenticate using the devices passcode or TouchID')

    if not _should_output_json(args):
        click.secho('Get all of the attributes by adding `--json keychain.json` to this command', dim=True)

    click.secho('Reading the iOS keychain...', dim=True)
    hook = ios_hook('keychain/dump')
    runner = FridaRunner(hook=hook)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to get keychain items with error: {0}'.format(response.error_message), fg='red')
        return

    if _should_output_json(args):
        destination = args[1]

        click.secho('Writing full keychain as json to {0}...'.format(destination), dim=True)

        with open(destination, 'w') as f:
            f.write(json.dumps(response.data, indent=2))

        click.secho('Dumped full keychain to: {0}'.format(destination), fg='green')
        return

    # refer to hooks/ios/keychain/dump.js for a key,value reference

    data = []

    if response.data:
        for entry in response.data:
            data.append([entry['item_class'], entry['account'], entry['service'], entry['generic'], entry['data'], ])

        click.secho('')
        click.secho(tabulate(data, headers=['Class', 'Account', 'Service', 'Generic', 'Data']))

    else:
        click.secho('No keychain data could be found', fg='yellow')
Esempio n. 7
0
def monitor(args: list = None) -> None:
    """
        Starts a new objection job that monitors the Android clipboard
        and reports on new strings found.

        :param args:
        :return:
    """

    hook = android_hook('clipboard/monitor')

    runner = FridaRunner(hook=hook)
    runner.run_as_job(name='clipboard-monitor')
Esempio n. 8
0
def ios_disable(args: list = None) -> None:
    """
        Starts a new objection job that hooks common classes and functions,
        applying new logic in an attempt to bypass SSL pinning.

        :param args:
        :return:
    """

    hook = ios_hook('pinning/disable')

    runner = FridaRunner(hook=hook)
    runner.run_as_job(name='pinning-disable')
Esempio n. 9
0
def search_class(args: list) -> None:
    """
        Searching for Objective-C classes in the current
        application by name.

        :param args:
        :return:
    """

    if len(clean_argument_flags(args)) < 1:
        click.secho('Usage: ios hooking search classes <name>', bold=True)
        return

    search = args[0]

    runner = FridaRunner()
    runner.set_hook_with_data(ios_hook('hooking/search-class'), search=search)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to search for classes with error: {0}'.format(response.error_reason), fg='red')
        return None

    if response.data:

        # dump the classes to screen
        for classname in response.data:
            click.secho(classname)

        click.secho('\nFound {0} classes'.format(len(response.data)), bold=True)

    else:
        click.secho('No classes found')
Esempio n. 10
0
def show_android_class_methods(args: list = None) -> None:
    """
        Shows the methods available on an Android class.

        :param args:
        :return:
    """

    if len(clean_argument_flags(args)) <= 0:
        click.secho('Usage: android hooking list class_methods <class name>',
                    bold=True)
        return

    class_name = args[0]

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('hooking/list-class-methods'),
                              class_name=class_name)

    runner.run()
    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to list class methods with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return None

    # print the enumerated classes
    for class_name in sorted(response.data):
        click.secho(class_name)

    click.secho('\nFound {0} method(s)'.format(len(response.data)), bold=True)
Esempio n. 11
0
def var_class(args: list) -> None:
    search = str(search)
    if len(search) == 0:
        click.secho('Usage: android hooking search classes <name>', bold=True)
        return

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('hooking/search-class'),
                              search=search)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to search for classes with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return None

    if response.data:

        # dump the classes to screen
        for classname in response.data:
            click.secho(classname)

        click.secho('\nFound {0} classes'.format(len(response.data)),
                    bold=True)

    else:
        click.secho('No classes found')
Esempio n. 12
0
def execute(args: list) -> None:
    """
        Runs a shell command on an Android device.

        :param args:
        :return:
    """

    command = ' '.join(args)

    click.secho('Running command: {0}\n'.format(command), dim=True)

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('command/exec'), command=command)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to run command with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return

    if response.stdout:
        click.secho(response.stdout, bold=True)

    if response.stderr:
        click.secho(response.stderr, bold=True, fg='red')
Esempio n. 13
0
def search_method(args: list) -> None:
    """
        Search for Objective-C methods by name.

        :param args:
        :return:
    """

    if len(clean_argument_flags(args)) < 1:
        click.secho('Usage: ios hooking search methods <name>', bold=True)
        return

    search = args[0]

    runner = FridaRunner()
    runner.set_hook_with_data(ios_hook('hooking/search-method'), search=search)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to search for methods with error: {0}'.format(response.error_reason), fg='red')
        return None

    if response.data:

        # dump the methods to screen
        for method in response.data:
            click.secho(method)

        click.secho('\nFound {0} methods'.format(len(response.data)), bold=True)

    else:
        click.secho('No methods found')
Esempio n. 14
0
def show_ios_class_methods(args: list) -> None:
    """
        Displays the methods available in a class.

        :param args:
        :return:
    """

    if len(args) <= 0:
        click.secho('Usage: ios hooking list class_methods <class name> (--include-parents)', bold=True)
        return

    classname = args[0]

    runner = FridaRunner()
    runner.set_hook_with_data(
        ios_hook('hooking/list-class-methods'), classname=classname,
        include_parents=_should_include_parent_methods(args))

    runner.run()
    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to list classes with error: {0}'.format(response.error_reason), fg='red')
        return None

    # dump the methods to screen
    for method in response.data:
        click.secho(method)
Esempio n. 15
0
def get(args: list) -> None:
    """
        Gets cookies using the iOS NSHTTPCookieStorage sharedHTTPCookieStorage
        and prints them to the screen.

        :param args:
        :return:
    """

    hook = ios_hook('binarycookie/get')

    runner = FridaRunner(hook=hook)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to get cookies with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return

    if not response.data:
        click.secho('No cookies found')
        return

    if _should_dump_json(args):
        print(json.dumps(response.data, indent=4))
        return

    data = []

    for cookie in response.data:
        data.append([
            cookie['name'], cookie['value'], cookie['expiresDate'],
            cookie['domain'], cookie['path'], cookie['isSecure'],
            cookie['isHTTPOnly']
        ])

    click.secho(tabulate(data,
                         headers=[
                             'Name', 'Value', 'Expires', 'Domain', 'Path',
                             'Secure', 'HTTPOnly'
                         ]),
                bold=True)
Esempio n. 16
0
def cat(args: list = None) -> None:
    """
        Parses a plist on an iOS device and echoes it in a more human
        readable way.

        :param args:
        :return:
    """

    if len(args) <= 0:
        click.secho('Usage: ios plist cat <remote_plist>', bold=True)
        return

    plist = args[0]

    if not os.path.isabs(plist):
        pwd = filemanager.pwd()
        plist = os.path.join(pwd, plist)

    runner = FridaRunner()
    runner.set_hook_with_data(ios_hook('plist/get'), plist=plist)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to get plist with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return

    click.secho(response.data, bold=True)
Esempio n. 17
0
def search_class(args: list) -> None:
    """
        Searches the current Android application for instances
        of a class.

        :param args:
        :return:
    """

    if len(args) < 1:
        click.secho('Usage: android hooking search classes <name>', bold=True)
        return

    search = args[0]

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('hooking/search-class'), search=search)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to search for classes with error: {0}'.format(response.error_reason), fg='red')
        return None

    if response.data:

        # dump the classes to screen
        for classname in response.data:
            click.secho(classname)

        click.secho('\nFound {0} classes'.format(len(response.data)), bold=True)

    else:
        click.secho('No classes found')
Esempio n. 18
0
def entries(args: list = None) -> None:
    """
        Lists entries in the Android KeyStore

        :param args:
        :return:
    """

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('keystore/list'))
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to list KeyStore items with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return None

    if not response.data:
        click.secho('No keystore items were found', fg='yellow')
        return None

    output = [[x['alias'], x['is_key'], x['is_certificate']]
              for x in response.data]

    click.secho(tabulate(output, headers=['Alias', 'Is Key',
                                          'Is Certificate']))
Esempio n. 19
0
def _get_ios_classes() -> list:
    """
        Gets a list of all of the classes available in the current
        Objective-C runtime.

        :return:
    """

    hook = ios_hook('hooking/list-classes')
    runner = FridaRunner(hook=hook)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to list classes with error: {0}'.format(response.error_reason), fg='red')
        return None

    return response.data
Esempio n. 20
0
def clear(args: list = None) -> None:
    """
        Clear the iOS keychain.

        :param args:
        :return:
    """

    click.secho('Clearing the keychain...', dim=True)
    hook = ios_hook('keychain/clear')
    runner = FridaRunner(hook=hook)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to clear keychain items with error: {0}'.format(response.error_message), fg='red')
        return

    click.secho('Keychain cleared', fg='green')
Esempio n. 21
0
def set_method_return_value(args: list = None) -> None:
    """
        Sets a Java methods return value to a specified boolean.

        :param args:
        :return:
    """

    if len(clean_argument_flags(args)) < 2:
        click.secho(
            ('Usage: android hooking set return_value '
             '"<fully qualified class>" (eg: "com.example.test") '
             '"<method (with overload if needed)>" (eg: see help for details) '
             '<true/false>'),
            bold=True)
        return

    class_name = args[0]
    method_name = args[1].replace('\'', '"')  # fun!
    retval = args[2]

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('hooking/set-return'),
                              class_name=class_name,
                              method_name=method_name,
                              retval=retval)

    runner.run_as_job(name='set-return-value', args=args)
Esempio n. 22
0
def watch_class_method(args: list) -> None:
    """
        Watches for invocations of an Android Java class method.
        All overloads for the same method are also watched.

        Optionally, this method will dump the watched methods arguments,
        backtrace as well as return value.

        :param args:
        :return:
    """

    if len(clean_argument_flags(args)) < 2:
        click.secho(
            ('Usage: android hooking watch class_method <class> <method> '
             '(eg: com.example.test dologin) '
             '(optional: --dump-args) '
             '(optional: --dump-backtrace) '
             '(optional: --dump-return)'),
            bold=True)
        return

    target_class = args[0]
    target_method = args[1]

    runner = FridaRunner()

    runner.set_hook_with_data(android_hook('hooking/watch-method'),
                              target_class=target_class,
                              target_method=target_method,
                              dump_args=_should_dump_args(args),
                              dump_return=_should_dump_return_value(args),
                              dump_backtrace=_should_dump_backtrace(args))

    runner.run_as_job(name='watch-java-method', args=args)
Esempio n. 23
0
def watch_class_method(args: list) -> None:
    """
        Starts an objection jon that hooks into a specific class method
        and reports on invocations.

        :param args:
        :return:
    """

    if len(args) <= 0:
        click.secho((
            'Usage: ios hooking watch method <selector>'
            ' (eg: -[ClassName methodName:]) (optional: --include-backtrace)'),
                    bold=True)
        return

    selector = args[0]

    runner = FridaRunner()
    runner.set_hook_with_data(
        ios_hook('hooking/watch-method'),
        selector=selector,
        include_backtrace=_should_include_backtrace(args))

    runner.run_as_job(name='watch-method')
Esempio n. 24
0
def watch_class_method(args: list) -> None:
    """
        Starts an objection jon that hooks into a specific class method
        and reports on invocations.

        :param args:
        :return:
    """

    if len(clean_argument_flags(args)) <= 0:
        click.secho(('Usage: ios hooking watch method <selector> (eg: -[ClassName methodName:]) '
                     '(optional: --dump-backtrace) '
                     '(optional: --dump-args) '
                     '(optional: --dump-return)'), bold=True)
        return

    selector = args[0]
    argument_count = selector.count(':')

    runner = FridaRunner()
    runner.set_hook_with_data(ios_hook('hooking/watch-method'), selector=selector,
                              argument_count=argument_count,
                              dump_backtrace=_should_dump_backtrace(args),
                              dump_args=_should_dump_args(args),
                              dump_return=_should_dump_return_value(args))

    runner.run_as_job(name='watch-method', args=args)
Esempio n. 25
0
def watch_class_methods_var_returns(args: list) -> None:
    """
        Starts an objection jon that hooks into a specific all classes
        and methods and reports on invocations when specifi
        args and return values reached.

        :param args:
        :return:
    """

    if len(clean_argument_flags(args)) <= 0:
        click.secho(('Usage: ios hooking watch var_and_returns <classPattern> <methodPattern> <argsPattern> <returnPattern> (eg: Controller login [email protected] false) '
                     '(optional: --dump-backtrace) '
                     '(optional: --dump-args) '
                     '(optional: --dump-return)'), bold=True)
        return

    classes_Pattern = args[0]
    methods_Pattern = args[1]
    args_Pattern = args[2]
    returns_Pattern = args[3]

    runner = FridaRunner()
    runner.set_hook_with_data(ios_hook('hooking/watch-class-methods-var-returns'),
                              classes_Pattern=classes_Pattern,
                              methods_Pattern=methods_Pattern,
                              args_Pattern=args_Pattern,
                              returns_Pattern=returns_Pattern,
                              dump_backtrace=_should_dump_backtrace(args),
                              dump_args=_should_dump_args(args),
                              dump_return=_should_dump_return_value(args))

    runner.run_as_job(name='watch-class-methods-var-returns', args=args)
Esempio n. 26
0
def watch_class_method(args: list) -> None:
    """
        Watches for invocations of an Android Java class method.
        All overloads are watched.

        :param args:
        :return:
    """

    if len(args) < 2:
        click.secho(
            ('Usage: android hooking watch class_method <class> <method>'
             ' (eg: com.example.test dologin)'),
            bold=True)
        return

    target_class = args[0]
    target_method = args[1]

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('hooking/watch-method'),
                              target_class=target_class,
                              target_method=target_method)

    runner.run_as_job(name='watch-java-method')
Esempio n. 27
0
def watch_class(args: list) -> None:
    """
        Watches for invocations of all methods in an Android
        Java class. All overloads for methods found are also watched.

        :param args:
        :return:
    """

    if len(clean_argument_flags(args)) < 1:
        click.secho(
            'Usage: android hooking watch class <class> '
            '(eg: com.example.test) '
            '(optional: --dump-args) '
            '(optional: --dump-backtrace) '
            '(optional: --dump-return)',
            bold=True)
        return

    target_class = args[0]

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('hooking/watch-class-methods'),
                              target_class=target_class,
                              dump_args=_should_dump_args(args),
                              dump_return=_should_dump_return_value(args),
                              dump_backtrace=_should_dump_backtrace(args))

    runner.run_as_job(name='watch-java-class', args=args)
Esempio n. 28
0
    def setUp(self):
        self.runner = FridaRunner()

        self.successful_message = {
            'payload': {
                'type': 'send',
                'status': 'success',
                'error_reason': None,
                'data': 'data for unittest'
            }
        }

        self.error_message = {
            'payload': {
                'type': 'send',
                'status': 'error',
                'error_reason': 'error_message',
                'data': 'error data for unittest'
            }
        }

        self.sample_hook = """// this is a comment
Esempio n. 29
0
def get(args: list = None) -> None:
    """
        Gets all of the values stored in NSUserDefaults and prints
        them to screen.

        :param args:
        :return:
    """

    hook = ios_hook('nsuserdefaults/get')

    runner = FridaRunner(hook=hook)
    runner.run()

    response = runner.get_last_message()

    if not response.is_successful():
        click.secho('Failed to get nsuserdefaults with error: {0}'.format(
            response.error_reason),
                    fg='red')
        return

    click.secho(response.data, bold=True)
Esempio n. 30
0
def dump(args: list = None) -> None:
    """
        Dumps credentials stored in NSURLCredentialStorage

        :param args:
        :return:
    """

    hook = ios_hook('nsurlcredentialstorage/dump')

    runner = FridaRunner(hook=hook)
    api = runner.rpc_exports()

    data = api.dump()

    runner.unload_script()

    if not data:
        click.secho('No credentials found using NSURLCredentialStorage')

    click.secho('')
    click.secho(tabulate(data, headers="keys"))
    click.secho('')
    click.secho('Found {count} credentials'.format(count=len(data)), bold=True)