3
\$\begingroup\$

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.

asked Sep 4, 2022 at 17:15
\$\endgroup\$
3
  • \$\begingroup\$ At the very least, I found I should change the pass for a sleep(0): stackoverflow.com/a/790246/12735366 \$\endgroup\$ Commented Sep 4, 2022 at 19:41
  • \$\begingroup\$ This feels too vague to really answer. How is check(target) used? You're transforming an asynchronous function into a synchronous one, which defeats the entire point. \$\endgroup\$ Commented Sep 4, 2022 at 21:46
  • \$\begingroup\$ Yes, sorry, I realize now that messages aren’t the proper way to go about it, I should use the RPC api. I’ll elaborate both question and answer when I get home \$\endgroup\$ Commented Sep 4, 2022 at 21:47

2 Answers 2

4
\$\begingroup\$

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.

answered Sep 4, 2022 at 20:04
\$\endgroup\$
1
\$\begingroup\$

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 :-)

answered Sep 4, 2022 at 18:02
\$\endgroup\$
1
  • \$\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\$ Commented Sep 4, 2022 at 19:22

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.