Skip to content

Commit

Permalink
device: Add open_service() and Service API
Browse files Browse the repository at this point in the history
Co-authored-by: Håvard Sørbø <[email protected]>
  • Loading branch information
oleavr and hsorbo committed May 15, 2024
1 parent 9d21327 commit e7231b1
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 0 deletions.
109 changes: 109 additions & 0 deletions frida/_frida/extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ typedef struct _PySpawn PySpawn;
typedef struct _PyChild PyChild;
typedef struct _PyCrash PyCrash;
typedef struct _PyBus PyBus;
typedef struct _PyService PyService;
typedef struct _PySession PySession;
typedef struct _PyScript PyScript;
typedef struct _PyRelay PyRelay;
Expand Down Expand Up @@ -255,6 +256,11 @@ struct _PyBus
PyGObject parent;
};

struct _PyService
{
PyGObject parent;
};

struct _PySession
{
PyGObject parent;
Expand Down Expand Up @@ -391,6 +397,7 @@ static FridaSessionOptions * PyDevice_parse_session_options (const gchar * realm
static PyObject * PyDevice_inject_library_file (PyDevice * self, PyObject * args);
static PyObject * PyDevice_inject_library_blob (PyDevice * self, PyObject * args);
static PyObject * PyDevice_open_channel (PyDevice * self, PyObject * args);
static PyObject * PyDevice_open_service (PyDevice * self, PyObject * args);
static PyObject * PyDevice_unpair (PyDevice * self);

static PyObject * PyApplication_new_take_handle (FridaApplication * handle);
Expand Down Expand Up @@ -428,6 +435,11 @@ static PyObject * PyBus_new_take_handle (FridaBus * handle);
static PyObject * PyBus_attach (PySession * self);
static PyObject * PyBus_post (PyScript * self, PyObject * args, PyObject * kw);

static PyObject * PyService_new_take_handle (FridaService * handle);
static PyObject * PyService_activate (PyService * self);
static PyObject * PyService_cancel (PyService * self);
static PyObject * PyService_request (PyService * self, PyObject * args);

static PyObject * PySession_new_take_handle (FridaSession * handle);
static int PySession_init (PySession * self, PyObject * args, PyObject * kw);
static void PySession_init_from_handle (PySession * self, FridaSession * handle);
Expand Down Expand Up @@ -568,6 +580,7 @@ static PyMethodDef PyDevice_methods[] =
{ "inject_library_file", (PyCFunction) PyDevice_inject_library_file, METH_VARARGS, "Inject a library file to a PID." },
{ "inject_library_blob", (PyCFunction) PyDevice_inject_library_blob, METH_VARARGS, "Inject a library blob to a PID." },
{ "open_channel", (PyCFunction) PyDevice_open_channel, METH_VARARGS, "Open a device-specific communication channel." },
{ "open_service", (PyCFunction) PyDevice_open_service, METH_VARARGS, "Open a device-specific service." },
{ "unpair", (PyCFunction) PyDevice_unpair, METH_NOARGS, "Unpair device." },
{ NULL }
};
Expand Down Expand Up @@ -635,6 +648,14 @@ static PyMethodDef PyBus_methods[] =
{ NULL }
};

static PyMethodDef PyService_methods[] =
{
{ "activate", (PyCFunction) PyService_activate, METH_NOARGS, "Activate the service." },
{ "cancel", (PyCFunction) PyService_cancel, METH_NOARGS, "Cancel the service." },
{ "request", (PyCFunction) PyService_request, METH_VARARGS, "Perform a request." },
{ NULL }
};

static PyMethodDef PySession_methods[] =
{
{ "is_detached", (PyCFunction) PySession_is_detached, METH_NOARGS, "Query whether the session is detached." },
Expand Down Expand Up @@ -812,6 +833,11 @@ PYFRIDA_DEFINE_TYPE ("_frida.Bus", Bus, GObject, NULL, g_object_unref,
{ Py_tp_methods, PyBus_methods },
);

PYFRIDA_DEFINE_TYPE ("_frida.Service", Service, GObject, NULL, g_object_unref,
{ Py_tp_doc, "Frida Service" },
{ Py_tp_methods, PyService_methods },
);

PYFRIDA_DEFINE_TYPE ("_frida.Session", Session, GObject, PySession_init_from_handle, frida_unref,
{ Py_tp_doc, "Frida Session" },
{ Py_tp_init, PySession_init },
Expand Down Expand Up @@ -2839,6 +2865,25 @@ PyDevice_open_channel (PyDevice * self, PyObject * args)
return PyIOStream_new_take_handle (stream);
}

static PyObject *
PyDevice_open_service (PyDevice * self, PyObject * args)
{
const char * address;
GError * error = NULL;
FridaService * service;

if (!PyArg_ParseTuple (args, "s", &address))
return NULL;

Py_BEGIN_ALLOW_THREADS
service = frida_device_open_service_sync (PY_GOBJECT_HANDLE (self), address, g_cancellable_get_current (), &error);
Py_END_ALLOW_THREADS
if (error != NULL)
return PyFrida_raise (error);

return PyService_new_take_handle (service);
}

static PyObject *
PyDevice_unpair (PyDevice * self)
{
Expand Down Expand Up @@ -3338,6 +3383,69 @@ PyBus_post (PyScript * self, PyObject * args, PyObject * kw)
}


static PyObject *
PyService_new_take_handle (FridaService * handle)
{
return PyGObject_new_take_handle (handle, PYFRIDA_TYPE (Service));
}

static PyObject *
PyService_activate (PyService * self)
{
GError * error = NULL;

Py_BEGIN_ALLOW_THREADS
frida_service_activate_sync (PY_GOBJECT_HANDLE (self), g_cancellable_get_current (), &error);
Py_END_ALLOW_THREADS
if (error != NULL)
return PyFrida_raise (error);

Py_RETURN_NONE;
}

static PyObject *
PyService_cancel (PyService * self)
{
GError * error = NULL;

Py_BEGIN_ALLOW_THREADS
frida_service_cancel_sync (PY_GOBJECT_HANDLE (self), g_cancellable_get_current (), &error);
Py_END_ALLOW_THREADS
if (error != NULL)
return PyFrida_raise (error);

Py_RETURN_NONE;
}

static PyObject *
PyService_request (PyService * self, PyObject * args)
{
PyObject * result, * params;
GVariant * raw_params, * raw_result;
GError * error = NULL;

if (!PyArg_ParseTuple (args, "O", &params))
return NULL;

if (!PyGObject_unmarshal_variant (params, &raw_params))
return NULL;

Py_BEGIN_ALLOW_THREADS
raw_result = frida_service_request_sync (PY_GOBJECT_HANDLE (self), raw_params, g_cancellable_get_current (), &error);
Py_END_ALLOW_THREADS

g_variant_unref (raw_params);

if (error != NULL)
return PyFrida_raise (error);

result = PyGObject_marshal_variant (raw_result);
g_variant_unref (raw_result);

return result;
}


static PyObject *
PySession_new_take_handle (FridaSession * handle)
{
Expand Down Expand Up @@ -5207,6 +5315,7 @@ MOD_INIT (_frida)
PYFRIDA_REGISTER_TYPE (Child, FRIDA_TYPE_CHILD);
PYFRIDA_REGISTER_TYPE (Crash, FRIDA_TYPE_CRASH);
PYFRIDA_REGISTER_TYPE (Bus, FRIDA_TYPE_BUS);
PYFRIDA_REGISTER_TYPE (Service, FRIDA_TYPE_SERVICE);
PYFRIDA_REGISTER_TYPE (Session, FRIDA_TYPE_SESSION);
PYFRIDA_REGISTER_TYPE (Script, FRIDA_TYPE_SCRIPT);
PYFRIDA_REGISTER_TYPE (Relay, FRIDA_TYPE_RELAY);
Expand Down
65 changes: 65 additions & 0 deletions frida/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,63 @@ def _on_message(self, raw_message: str, data: Any) -> None:
traceback.print_exc()


ServiceMessageCallback = Callable[[Mapping[Any, Any]], None]


class Service:
def __init__(self, impl: _frida.Service) -> None:
self._impl = impl

@cancellable
def activate(self) -> None:
"""
Activate the service
"""

self._impl.activate()

@cancellable
def cancel(self) -> None:
"""
Cancel the service
"""

self._impl.cancel()

def request(self, parameters: Mapping[Any, Any]) -> Mapping[Any, Any]:
"""
Perform a request
"""

return self._impl.request(parameters)

@overload
def on(self, signal: Literal["message"], callback: ServiceMessageCallback) -> None: ...

@overload
def on(self, signal: str, callback: Callable[..., Any]) -> None: ...

def on(self, signal: str, callback: Callable[..., Any]) -> None:
"""
Add a signal handler
"""

self._impl.on(signal, callback)

@overload
def off(self, signal: Literal["message"], callback: ServiceMessageCallback) -> None: ...

@overload
def off(self, signal: str, callback: Callable[..., Any]) -> None: ...

def off(self, signal: str, callback: Callable[..., Any]) -> None:
"""
Remove a signal handler
"""

self._impl.off(signal, callback)


DeviceSpawnAddedCallback = Callable[[_frida.Spawn], None]
DeviceSpawnRemovedCallback = Callable[[_frida.Spawn], None]
DeviceChildAddedCallback = Callable[[_frida.Child], None]
Expand Down Expand Up @@ -1019,6 +1076,14 @@ def open_channel(self, address: str) -> IOStream:

return IOStream(self._impl.open_channel(address))

@cancellable
def open_service(self, address: str) -> IOStream:
"""
Open a device-specific service
"""

return Service(self._impl.open_service(address))

@cancellable
def unpair(self) -> None:
"""
Expand Down

0 comments on commit e7231b1

Please sign in to comment.