mirror of
https://github.com/frida/frida-python
synced 2026-06-08 14:16:17 +00:00
device: Add open_service() and Service API
Co-authored-by: Håvard Sørbø <havard@hsorbo.no>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
import frida
|
||||
import pprint
|
||||
|
||||
device = frida.get_usb_device()
|
||||
|
||||
deviceinfo = device.open_service("dtx:com.apple.instruments.server.services.deviceinfo")
|
||||
response = deviceinfo.request({"method": "runningProcesses"})
|
||||
pprint.pp(response)
|
||||
@@ -0,0 +1,26 @@
|
||||
import frida
|
||||
import sys
|
||||
|
||||
|
||||
def on_message(message):
|
||||
print("on_message:", message)
|
||||
|
||||
|
||||
device = frida.get_usb_device()
|
||||
|
||||
opengl = device.open_service("dtx:com.apple.instruments.server.services.graphics.opengl")
|
||||
opengl.on("message", on_message)
|
||||
opengl.request(
|
||||
{
|
||||
"method": "setSamplingRate:",
|
||||
"args": [5.0],
|
||||
}
|
||||
)
|
||||
opengl.request(
|
||||
{
|
||||
"method": "startSamplingAtTimeInterval:",
|
||||
"args": [0.0],
|
||||
}
|
||||
)
|
||||
|
||||
sys.stdin.read()
|
||||
@@ -0,0 +1,30 @@
|
||||
import frida
|
||||
import sys
|
||||
|
||||
|
||||
def on_message(message):
|
||||
print("on_message:", message)
|
||||
|
||||
|
||||
device = frida.get_usb_device()
|
||||
|
||||
control = device.open_service("dtx:com.apple.instruments.server.services.processcontrol")
|
||||
control.on("message", on_message)
|
||||
pid = control.request(
|
||||
{
|
||||
"method": "launchSuspendedProcessWithDevicePath:bundleIdentifier:environment:arguments:options:",
|
||||
"args": [
|
||||
"",
|
||||
"no.oleavr.HelloIOS",
|
||||
{},
|
||||
[],
|
||||
{
|
||||
"StartSuspendedKey": False,
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
control.request({"method": "startObservingPid:", "args": [pid]})
|
||||
|
||||
print(f"App spawned, PID: {pid}. Kill it to see an example message being emitted.")
|
||||
sys.stdin.read()
|
||||
@@ -0,0 +1,14 @@
|
||||
import frida
|
||||
import sys
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print(f"Usage: {sys.argv[0]} outfile.png", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
outfile = sys.argv[1]
|
||||
|
||||
device = frida.get_usb_device()
|
||||
|
||||
screenshot = device.open_service("dtx:com.apple.instruments.server.services.screenshot")
|
||||
png = screenshot.request({"method": "takeScreenshot"})
|
||||
with open(outfile, "wb") as f:
|
||||
f.write(png)
|
||||
@@ -0,0 +1,28 @@
|
||||
import frida
|
||||
import time
|
||||
|
||||
|
||||
def on_message(message):
|
||||
print("on_message:", message)
|
||||
|
||||
|
||||
device = frida.get_usb_device()
|
||||
|
||||
sysmon = device.open_service("dtx:com.apple.instruments.server.services.sysmontap")
|
||||
sysmon.on("message", on_message)
|
||||
sysmon.request(
|
||||
{
|
||||
"method": "setConfig:",
|
||||
"args": [
|
||||
{
|
||||
"ur": 1000,
|
||||
"cpuUsage": True,
|
||||
"sampleInterval": 1000000000,
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
sysmon.request({"method": "start"})
|
||||
time.sleep(5)
|
||||
sysmon.request({"method": "stop"})
|
||||
time.sleep(1)
|
||||
@@ -0,0 +1,9 @@
|
||||
import frida
|
||||
|
||||
device = frida.get_usb_device()
|
||||
|
||||
diag = device.open_service("plist:com.apple.mobile.diagnostics_relay")
|
||||
diag.request({"type": "query", "payload": {"Request": "RSDCheckin", "ProtocolVersion": "2", "Label": "Frida"}})
|
||||
diag.request({"type": "read"})
|
||||
diag.request({"type": "query", "payload": {"Request": "Sleep", "WaitForDisconnect": True}})
|
||||
diag.request({"type": "query", "payload": {"Request": "Goodbye"}})
|
||||
@@ -0,0 +1,14 @@
|
||||
import frida
|
||||
import pprint
|
||||
|
||||
device = frida.get_usb_device()
|
||||
|
||||
appservice = device.open_service("xpc:com.apple.coredevice.appservice")
|
||||
response = appservice.request(
|
||||
{
|
||||
"CoreDevice.featureIdentifier": "com.apple.coredevice.feature.listprocesses",
|
||||
"CoreDevice.action": {},
|
||||
"CoreDevice.input": {},
|
||||
}
|
||||
)
|
||||
pprint.pp(response)
|
||||
@@ -149,6 +149,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;
|
||||
@@ -256,6 +257,11 @@ struct _PyBus
|
||||
PyGObject parent;
|
||||
};
|
||||
|
||||
struct _PyService
|
||||
{
|
||||
PyGObject parent;
|
||||
};
|
||||
|
||||
struct _PySession
|
||||
{
|
||||
PyGObject parent;
|
||||
@@ -397,6 +403,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);
|
||||
@@ -434,6 +441,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);
|
||||
@@ -574,6 +586,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 }
|
||||
};
|
||||
@@ -641,6 +654,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." },
|
||||
@@ -818,6 +839,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 },
|
||||
@@ -2966,6 +2992,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)
|
||||
{
|
||||
@@ -3465,6 +3510,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", ¶ms))
|
||||
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)
|
||||
{
|
||||
@@ -5334,6 +5442,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);
|
||||
|
||||
@@ -792,6 +792,70 @@ class Bus:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
ServiceCloseCallback = Callable[[], None]
|
||||
ServiceMessageCallback = Callable[[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: Any) -> Any:
|
||||
"""
|
||||
Perform a request
|
||||
"""
|
||||
|
||||
return self._impl.request(parameters)
|
||||
|
||||
@overload
|
||||
def on(self, signal: Literal["close"], callback: ServiceCloseCallback) -> None: ...
|
||||
|
||||
@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["close"], callback: ServiceCloseCallback) -> None: ...
|
||||
|
||||
@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]
|
||||
@@ -1019,6 +1083,14 @@ class Device:
|
||||
|
||||
return IOStream(self._impl.open_channel(address))
|
||||
|
||||
@cancellable
|
||||
def open_service(self, address: str) -> Service:
|
||||
"""
|
||||
Open a device-specific service
|
||||
"""
|
||||
|
||||
return Service(self._impl.open_service(address))
|
||||
|
||||
@cancellable
|
||||
def unpair(self) -> None:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user