Search code examples
javascriptpythonpython-3.xrpcfrida

How to get all functions from frida javascript rpc.exports to python?


I have a js file with some rpc.exports

rpc.exports = {
    callfunctionsecret: callSecretFun,
    callfunctionsomethingelse: callSomethingElse,
}

I want to list ALL these functions in python, but I couldn't find a way to do it

device = frida.get_usb_device()
pid = device.spawn([package_name])
device.resume(pid)
time.sleep(1)
session = device.attach(pid)
with open(sys.argv[1]) as jsfile:
        script = session.create_script(jsfile.read())
print(dir(script.exports))
# output
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_script']
# output doesn't contain "callfunctionsecret" and "callfunctionsomethingelse"

Is there a way to get the function names in some kind of list?

# e.g.
['callfunctionsecret','callfunctionsomethingelse']

So far I've only gotten to the point where I can access the function object with

print(script.exports.__getattrs__(callfunctionsecret))

but that requires us to know the function name first which defeats the purpose of listing all the function names


Solution

  • From what I've seen, this is not documented and there isn't an explicit method for this. ScriptExports as class does not contain any useful information or methods for this purpose. However, if you search frida-gum's code there is such an operation serving this purpose, list. One could trigger this operation and get all rpc exports like this:

    agent.js

    function callSecretFun(n) {
            return n*100
    }
    
    rpc.exports = {
            callfunctionsecret: callSecretFun,
            fun1: function() {send("fun1"); return 1000},
            fun2: function() {send("fun2")}
    }
    

    agent.py

    import sys
    import frida
    
    session = frida.attach("hello")
    with open("agent.js", "r") as f:
        script = session.create_script(f.read())
    script.load()
    rpc_exports = script._rpc_request('list') # send an rpc request to list rpc exports
    print(rpc_exports)
    sys.stdin.read()
    

    Output:

    $ python3 agent.py
    ['callfunctionsecret', 'fun1', 'fun2']