frida / frida-python

Frida Python bindings
Other
785 stars 147 forks source link

Early hooking on Android #108

Open nioncode opened 7 years ago

nioncode commented 7 years ago

I'm trying to spawn an Android process and hook all calls to early executing methods like System.loadLibrary and Activity.onResume. However, either my hooks don't get applied at all, or they get applied too late.

What is the correct way to do this?

My android-hook.py:

import frida
import sys

scriptname = sys.argv[1]
procname = sys.argv[2]
with open(scriptname, "r") as f:
    script_content = f.read()

# define callback function to receive and output messages
# received from server
def on_message(message, data):
    print(message)

device = frida.get_usb_device(1)  # Parameter '1' adds a timeout. Otherwise, frida often raises a frida.TimedOutError
pid = device.spawn([procname])
session = device.attach(pid)
script = session.create_script(script_content)
# setup callback using function defined above
script.on('message', on_message)
# load script into the process
script.load()
# resume process, otherwise nothing will happen
device.resume(pid)
# read from stdin to keep script running
sys.stdin.read()

My injected script:

'use strict';
setImmediate(function() {
    console.log('init')
    Java.perform(function () {
        console.log("hooking");
        var activity = Java.use('de.nioncode.fridasample.MainActivity');
        activity.onResume.implementation = function () {
            send("onResume");
            this.onResume();
        };
        console.log("hooking done");
        send("initialized");
    });
    console.log('init done')
});

This variation performs the hooks too late, thus missing the first 'onResume' call. I tried to use the rpc mechanism in combination with a Promise to defer the continuation until I call resolve on the Promise. However, this resulted in an frida.InvalidOperationError: script is destroyed error. This was my attempt with the Promise script:

rpc.exports = {
    init: function() {
        console.log('init')
        return new Promise(function(resolve, reject) {
            console.log('init2')
            Java.perform(function () {
                console.log("hooking");
                var activity = Java.use('de.nioncode.antidebug.MainActivity');
                activity.onResume.implementation = function () {
                    send("onResume");
                    this.onResume();
                };
                console.log("hooking done");
                // resolve the Promise, telling Frida to continue executing
                resolve();
            });
            console.log('init2 done')
        });
    }
};

Related to: https://github.com/frida/frida-python/issues/50 https://github.com/frida/frida/issues/13

yotamN commented 1 year ago

Current version of Frida pause the application by default and will only continue with a call to resume, is it still relevant?