Search code examples
androidpythonfrida

How to get the return value of a Java method using Frida


TLDR i am looking to use Frida to call an unused method in an Android app and get back its value. Currently, I am not getting any return in my scripts output.

Code for the Android app:

package securisec.com.methods;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public static String strings(){
        return "This is a string method";
    }

}

As you can see, the strings method is never used. I want to be able to call this method using Frida and get the return value back.

Here is my python script that is not working.

import frida
from time import sleep

call_back_message = ''

def on_message(message, payload):
    global call_back_message
    if message['type'] == 'send':
        call_back_message = message['payload']
        return call_back_message

def object_hooking(comName, className, method):
    process = frida.get_usb_device()
    pid = process.spawn([comName])
    process.resume(pid)
    sleep(1)
    js = """
            Java.perform(function()
            {
                var getVal = Java.use('%s.%s');
                console.log(getVal)
                var cons = getVal.$new();
                console.log(cons)
                var solution = cons.%s;
                var send_it = solution.toString();
                send(send_it);
            });""" % (comName, className, method)
    session = process.attach(pid)
    script = session.create_script(js)
    script.on('message', on_message)
    script.load()
    return call_back_message

print(object_hooking(
    comName='securisec.com.methods', 
    className='MainActivity',
    method='strings()'
))

Solution

  • You do not need to create new instance, you got couple of typo's but overall it seems you get the point.

    If the method exists in

    Object.getOwnPropertyNames(Java.use('securisec.com.methods.MainActivity').__proto__).join('\n\t')
    

    and the compiler did not exclude it, the following code should do the work

    def main():
        device = frida.get_usb_device()
        script = device.attach(device.spawn([APP])).create_script("""
            Java.perform(function(){
                console.log( 
                    Java.use('securisec.com.methods.MainActivity')['strings']() 
                );
            });
        """)
        script.load()
        device.resume(APP)
        sys.stdin.read()
    
    if __name__ == "__main__":
        main()
    

    I prefer to keep clean style :)

    function Main() {
        var retVal = Java.use("securisec.com.methods.MainActivity")["strings"]();
        console.log("retVal", retVal);
    }
    Java.perform(Main);
    

    You can also test w/ REPL

    $ frida -U com.app -e 'console.log(Java.use("securisec.com.methods.MainActivity")["strings"]())' --no-pause