I'm using Frida to run a script on a process, and I want to wait for it to send the result back to me, as a callback.
My current code looks like this:
def check(target):
global msg
script_to_run = '''
(omitted for brevity)
'''
# callback to handle the output of the script
def on_message(message, data):
global msg
if message['type'] == 'send':
msg = message['payload']
session = device.attach(target.pid)
script = session.create_script(script_to_run)
script.on('message', on_message)
script.load()
# Wait for the script to send us a message
while msg == None:
pass
return msg == 'true'
The while
loop in particular looks a bit unoptimized, and I'm also worried about how I used that global variable... it will pollute the global scope.
EDIT: As it turns out, I was approaching this in the wrong direction. See my answer below for details.
2 Answers 2
So, as it turns out, I was approaching this problem in the wrong direction.
Instead of trying to wait on an asynchronous message, I discovered that Frida has an RPC API.
Here's how I re-wrote my code:
import frida
# --snip--
def check(target):
session = frida.attach(target.pid)
script = session.create_script('''
rpc.exports = {
check: function () {
// --snip--
return true;
}
};
''')
script.load()
return script.exports.check()
Much more succinct, doesn't use globals, and doesn't use a while
loop to block.
I am not familiar with Frida, but looking at the examples found at https://frida.re/docs/messages/ I think you should do your processing in the callback "on_message", instead of passing it to the main thread.
The Frida examples end with sys.stdin.read() which acts like a wait-forever loop. The callback is probably executing in a different thread.
So change your last lines to
# Wait for the script to send us a message
sys.stdin.read()
And change the callback to
def on_message(message, data):
if message['type'] == 'send':
print(message['payload'] == 'true')
Don't worry about poluting the global namespace. You are the only one using it :-)
-
\$\begingroup\$ Well, see the problem is that this function is going to be part of a larger program. So, I need to get the result back in the main thread, and block until then. \$\endgroup\$JJTech– JJTech2022年09月04日 19:22:04 +00:00Commented Sep 4, 2022 at 19:22
pass
for asleep(0)
: stackoverflow.com/a/790246/12735366 \$\endgroup\$check(target)
used? You're transforming an asynchronous function into a synchronous one, which defeats the entire point. \$\endgroup\$