Exemplo n.º 1
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')
Exemplo n.º 2
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)
Exemplo n.º 3
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)
Exemplo n.º 4
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']))
Exemplo n.º 5
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')
Exemplo n.º 6
0
    def test_finds_and_compiles_android_hooks_without_an_exception_handler(
            self):
        hook = android_hook('filesystem/pwd', skip_trycatch=True)

        expected_output = """// Determines the current working directory, based
// on the applications filesDir

var ActivityThread = Java.use('android.app.ActivityThread');

var currentApplication = ActivityThread.currentApplication();
var context = currentApplication.getApplicationContext();

var response = {
    status: 'success',
    error_reason: NaN,
    type: 'current-working-directory',
    data: {
        cwd: context.getFilesDir().getAbsolutePath().toString()
    }
};

send(response);

// -- Sample Java
//
// getApplicationContext().getFilesDir().getAbsolutePath()
"""

        self.assertEqual(hook, expected_output)
Exemplo n.º 7
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')
Exemplo n.º 8
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)
Exemplo n.º 9
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)
Exemplo n.º 10
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)
Exemplo 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')
Exemplo n.º 12
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)
Exemplo n.º 13
0
def disable(args: list = None) -> None:
    """
        Performs a generic anti root detection.

        :param args:
        :return:
    """

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('root/disable'))

    runner.run_as_job(name='root-disable')
Exemplo n.º 14
0
def simulate(args: list = None) -> None:
    """
        Simulate a rooted environment.

        :param args:
        :return:
    """

    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('root/simulate'))

    runner.run_as_job(name='root-simulate')
Exemplo n.º 15
0
def android_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 = android_hook('pinning/disable')

    runner = FridaRunner(hook=hook)
    runner.run_as_job(name='pinning-disable')
Exemplo n.º 16
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')
Exemplo n.º 17
0
def launch_service(args: list) -> None:
    """
        Launches an exported service using an Android Intent
        
        :param args:
        :return:
        """

    if len(args) < 1:
        click.secho('Usage: android intent launch_service <service_class>',
                    bold=True)
        return

    intent_class = args[0]

    click.secho('Launching Service: {0}...'.format(intent_class), dim=True)
    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('intent/start-service'),
                              intent_class=intent_class)
    runner.run()
Exemplo n.º 18
0
def launch_activity(args: list) -> None:
    """
        Launces an activity class using an Android Intent

        :param args:
        :return:
    """

    if len(args) < 1:
        click.secho('Usage: android intent launch_activity <activity_class>',
                    bold=True)
        return

    intent_class = args[0]

    click.secho('Launching Activity: {0}...'.format(intent_class), dim=True)
    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('intent/start-activity'),
                              intent_class=intent_class)
    runner.run()
Exemplo n.º 19
0
def clear(args: list = None) -> None:
    """
        Clears out an Android KeyStore

        :param args:
        :return:
    """

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

    response = runner.get_last_message()

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

    click.secho('Cleared the KeyStore', fg='green')
Exemplo n.º 20
0
def var_class(args: list) -> None:

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

    search_class = args[0]
    search_var = args[1]
    runner = FridaRunner()

    runner.set_hook_with_data(android_hook('hooking/var-class'),
                              search_class=search_class,
                              search_var=search_var,
                              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-var', args=args)
Exemplo n.º 21
0
def dump_android_method_args(args: list) -> None:
    """
        Starts an objection job that hooks into a class method and
        dumps the argument values as the method is invoked.

        :param args:
        :return:
    """

    if len(args) < 2:
        click.secho('Usage: android hooking dump_args <class> <method>',
                    bold=True)
        return

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

    # prepare a runner for the arg dump hook
    runner = FridaRunner()
    runner.set_hook_with_data(android_hook('hooking/dump-arguments'),
                              target_class=target_class,
                              target_method=target_method)

    runner.run_as_job(name='dump-arguments')
Exemplo n.º 22
0
    def test_finds_and_compiles_android_hooks_with_an_exception_handler(self):
        hook = android_hook('filesystem/pwd')

        expected_output = """if (Java.available) {

    try {

        // From Frida documentation:
        //  "ensure that the current thread is attached to the VM and call fn"
        //
        // We also handle the exception that could happen within the callback as
        // it does not seem to bubble outside of it.
        Java.perform(function () {

            try {

                // Determines the current working directory, based
// on the applications filesDir

var ActivityThread = Java.use('android.app.ActivityThread');

var currentApplication = ActivityThread.currentApplication();
var context = currentApplication.getApplicationContext();

var response = {
    status: 'success',
    error_reason: NaN,
    type: 'current-working-directory',
    data: {
        cwd: context.getFilesDir().getAbsolutePath().toString()
    }
};

send(response);

// -- Sample Java
//
// getApplicationContext().getFilesDir().getAbsolutePath()


            } catch (err) {

                var response = {
                    status: 'error',
                    error_reason: err.message,
                    type: 'java-perform-exception',
                    data: {}
                };

                send(response);
            }
        });

    } catch (err) {

        var response = {
            status: 'error',
            error_reason: err.message,
            type: 'global-exception',
            data: {}
        };

        send(response);
    }

} else {

    var response = {
        status: 'error',
        error_reason: 'Java runtime is not available.',
        type: 'global-exception',
        data: {}
    };

    send(response);
}
"""
        self.assertEqual(hook, expected_output)