Messages
In this tutorial we show how to send messages to and from a target process.
Setting up the experiment
Create a file hello.c:
#include <stdio.h>
#include <unistd.h>
void
f (int n)
{
  printf ("Number: %d\n", n);
}
int
main (int argc,
      char * argv[])
{
  int i = 0;
  printf ("f() is at %p\n", f);
  while (1)
  {
    f (i++);
    sleep (1);
  }
}Compile with:
$ gcc -Wall hello.c -o helloStart the program and make note of the address of f() (0x400544 in the
following example):
f() is at 0x400544
Number: 0
Number: 1
Number: 2
…Sending messages from a target process
The following script shows how to send a message back to the Python process. You can send any JavaScript value which is serializable to JSON.
Create a file send.py containing:
import frida
import sys
session = frida.attach("hello")
script = session.create_script("send(1337);")
def on_message(message, data):
    print(message)
script.on('message', on_message)
script.load()
sys.stdin.read()When you run this script:
$ python send.pyit should print the following message:
{'type': 'send', 'payload': 1337}This means that the JavaScript code send(1337) has been executed inside the
hello process. Terminate the script with Ctrl-D.
Handling runtime errors from JavaScript
If the JavaScript script throws an uncaught exception, this will be propagated
from the target process into the Python script. If you replace send(1337)
with send(a) (an undefined variable), the following message will be received
by Python:
{'type': 'error', 'description': 'ReferenceError: a is not defined', 'lineNumber': 1}Note the type field (error vs send).
Receiving messages in a target process
It is possible to send messages from the Python script to the JavaScript
script. Create the file pingpong.py:
import frida
import sys
session = frida.attach("hello")
script = session.create_script("""
    recv('poke', function onMessage(pokeMessage) { send('pokeBack'); });
""")
def on_message(message, data):
    print(message)
script.on('message', on_message)
script.load()
script.post({"type": "poke"})
sys.stdin.read()Running the script:
$ python pingpong.pyproduces the output:
{'type': 'send', 'payload': 'pokeBack'}The mechanics of recv()
The recv() method itself is async (non-blocking). The registered callback (onMessage) will receive exactly one message. To receive the next message, the callback must be reregistered with recv().
Blocking receives in the target process
It is possible to wait for a message to arrive (a blocking receive) inside your
JavaScript script. Create a script rpc.py:
import frida
import sys
session = frida.attach("hello")
script = session.create_script("""
Interceptor.attach(ptr("%s"), {
    onEnter(args) {
        send(args[0].toString());
        const op = recv('input', value => {
            args[0] = ptr(value.payload);
        });
        op.wait();
    }
});
""" % int(sys.argv[1], 16))
def on_message(message, data):
    print(message)
    val = int(message['payload'], 16)
    script.post({'type': 'input', 'payload': str(val * 2)})
script.on('message', on_message)
script.load()
sys.stdin.read()The program hello should be running, and you should make a note of the address
printed at its beginning (e.g. 0x400544). Run:
$ python rpc.py 0x400544then observe the change in the terminal where hello is running:
Number: 3
Number: 8
Number: 10
Number: 12
Number: 14
Number: 16
Number: 18
Number: 20
Number: 22
Number: 24
Number: 26
Number: 14The hello program should start writing “doubled” values until you stop the
Python script (Ctrl-D).