mirror of
https://github.com/frida/frida-python
synced 2026-06-08 14:16:17 +00:00
Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dbe7868509 | |||
| a0867d30b9 | |||
| 0666e8d33c | |||
| 60c30102bf | |||
| d50d5cc6d0 | |||
| ddeaad5254 | |||
| c68cd908d3 | |||
| 5b6d9f378a | |||
| 0839e57d3b | |||
| 5215b5b2c8 | |||
| 54dca1d5da | |||
| 8eafeb24d9 | |||
| 1b75d93858 | |||
| c2145f3589 | |||
| 0a9995df51 | |||
| 0f3ffd4032 | |||
| 2da64cb7ca | |||
| f81c3183a1 | |||
| d2861db65b | |||
| 06210bec40 | |||
| 4934e18a0e | |||
| fe987827e9 | |||
| 0ef38236e8 | |||
| 0fab765f91 | |||
| a6c02cb7ee | |||
| 6033dd0904 | |||
| 77e94e24a1 | |||
| c97343dc83 | |||
| e1ffe5fd50 | |||
| c7314098c6 | |||
| 41d769fa4d | |||
| 044d23eef7 | |||
| 1641af6ca3 | |||
| e513eca572 | |||
| 15260bfa4a | |||
| dec8aca9ae | |||
| 8c69b9d032 | |||
| f57b0c1cfa | |||
| fd2c1f2424 | |||
| a9caf62a0c | |||
| 8bc4415f34 | |||
| e3eca3179c | |||
| ef190d9957 | |||
| 1e06ebe9a3 | |||
| 925378439c | |||
| 7ae323a3cd | |||
| 9c5985c254 | |||
| b469134be4 | |||
| 9933d916ae | |||
| 09cac4e2a5 | |||
| 6b49e14ce1 | |||
| 7711fa12ac | |||
| d468dc038c | |||
| 58ff000596 | |||
| 3652e985d8 | |||
| 210c56e1b2 | |||
| b3d6aa8ffe | |||
| 16eb645844 | |||
| b7b1fcf0ff | |||
| 978b756134 | |||
| 7b1fc43a42 | |||
| 244cf6926b | |||
| 24b941fb8a | |||
| e2b340eda1 | |||
| 2b306c6d30 | |||
| 57cee13b43 | |||
| 23aa442826 | |||
| 65236f3b05 | |||
| e52e7a95bd | |||
| 3b57222cfa | |||
| 319ac9e699 | |||
| 2e842a4e44 | |||
| f9bf571497 | |||
| 8f50f743e1 | |||
| 6da337df6f | |||
| e29d41806c | |||
| 8faf01dc2e | |||
| 4286667bc6 | |||
| 86d4b4b4bf | |||
| b5808d7b27 | |||
| 5466050755 | |||
| 4db854a02c | |||
| cc9a78ef19 | |||
| 22ed1fac3c | |||
| 9b15bde24e | |||
| a613d87b08 | |||
| 9ef240eff4 | |||
| 43a443f582 | |||
| dcc95216fd | |||
| 69e7c6c0ce | |||
| 3278173be8 | |||
| d8fa422062 | |||
| 3943d2eed2 | |||
| 8030b5aa68 | |||
| fa5f378176 | |||
| a814a4aa9b | |||
| a48ff22b6f | |||
| eb4f8d37f3 | |||
| 60a4a032d6 | |||
| 9f46dfaa80 | |||
| e57ca181f8 | |||
| 0fccd75bc7 | |||
| dea4ffb1c9 | |||
| da17d3badb | |||
| 33922241fc | |||
| fb8fdbb231 | |||
| 0f50b58a04 | |||
| f63ea5903f | |||
| a99767e501 | |||
| 07bbd3d488 | |||
| 81403cf383 | |||
| 2ea0b944a2 | |||
| 35c412c6cf | |||
| ec4524d155 | |||
| d9d53a89cc | |||
| dfb002de49 | |||
| 0f56e44abd | |||
| d28a2a4988 | |||
| 1fc39289ef | |||
| 2c757a08f3 | |||
| fc735c048f | |||
| 4d84536160 | |||
| 9e51c78c5c | |||
| a6d51e8384 | |||
| 3e80ed726d | |||
| 985410b6ff | |||
| 21c7b9ee6a | |||
| 7fba1cdc67 | |||
| a709856e2a | |||
| c3afe6089d | |||
| 6435a78d13 | |||
| 09175036ea | |||
| e0c90c5203 | |||
| 9f463fb602 | |||
| 9fdee2270f | |||
| 6e536a56b1 |
@@ -42,18 +42,16 @@ class Application:
|
|||||||
print("✔ enable_child_gating()")
|
print("✔ enable_child_gating()")
|
||||||
session.enable_child_gating()
|
session.enable_child_gating()
|
||||||
print("✔ create_script()")
|
print("✔ create_script()")
|
||||||
script = session.create_script(
|
script = session.create_script("""\
|
||||||
"""\
|
Interceptor.attach(Module.getGlobalExportByName('open'), {
|
||||||
Interceptor.attach(Module.getExportByName(null, 'open'), {
|
onEnter(args) {
|
||||||
onEnter: function (args) {
|
|
||||||
send({
|
send({
|
||||||
type: 'open',
|
type: 'open',
|
||||||
path: Memory.readUtf8String(args[0])
|
path: args[0].readUtf8String()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
script.on("message", lambda message, data: self._reactor.schedule(lambda: self._on_message(pid, message)))
|
script.on("message", lambda message, data: self._reactor.schedule(lambda: self._on_message(pid, message)))
|
||||||
print("✔ load()")
|
print("✔ load()")
|
||||||
script.load()
|
script.load()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ def on_uninjected(id):
|
|||||||
print("on_uninjected id=%u" % id)
|
print("on_uninjected id=%u" % id)
|
||||||
|
|
||||||
|
|
||||||
(target, library_path) = sys.argv[1:]
|
target, library_path = sys.argv[1:]
|
||||||
|
|
||||||
device = frida.get_local_device()
|
device = frida.get_local_device()
|
||||||
device.on("uninjected", on_uninjected)
|
device.on("uninjected", on_uninjected)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ def on_uninjected(id):
|
|||||||
print("on_uninjected id=%u" % id)
|
print("on_uninjected id=%u" % id)
|
||||||
|
|
||||||
|
|
||||||
(target, library_path) = sys.argv[1:]
|
target, library_path = sys.argv[1:]
|
||||||
|
|
||||||
device = frida.get_local_device()
|
device = frida.get_local_device()
|
||||||
device.on("uninjected", on_uninjected)
|
device.on("uninjected", on_uninjected)
|
||||||
|
|||||||
+2
-4
@@ -1,8 +1,7 @@
|
|||||||
import frida
|
import frida
|
||||||
|
|
||||||
session = frida.attach("Twitter")
|
session = frida.attach("Twitter")
|
||||||
script = session.create_script(
|
script = session.create_script("""\
|
||||||
"""\
|
|
||||||
rpc.exports = {
|
rpc.exports = {
|
||||||
hello: function () {
|
hello: function () {
|
||||||
return 'Hello';
|
return 'Hello';
|
||||||
@@ -11,8 +10,7 @@ rpc.exports = {
|
|||||||
oops;
|
oops;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
script.load()
|
script.load()
|
||||||
api = script.exports_sync
|
api = script.exports_sync
|
||||||
print("api.hello() =>", api.hello())
|
print("api.hello() =>", api.hello())
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ class Application:
|
|||||||
self._session = session
|
self._session = session
|
||||||
session.on("detached", lambda *args: self._reactor.schedule(lambda: self._on_detached(*args)))
|
session.on("detached", lambda *args: self._reactor.schedule(lambda: self._on_detached(*args)))
|
||||||
|
|
||||||
script = session.create_script(
|
script = session.create_script("""
|
||||||
"""
|
|
||||||
let _puts = null;
|
let _puts = null;
|
||||||
|
|
||||||
Interceptor.attach(DebugSymbol.getFunctionByName('f'), {
|
Interceptor.attach(DebugSymbol.getFunctionByName('f'), {
|
||||||
@@ -48,8 +47,7 @@ function puts(s) {
|
|||||||
}
|
}
|
||||||
_puts(Memory.allocUtf8String(s));
|
_puts(Memory.allocUtf8String(s));
|
||||||
}
|
}
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
self._script = script
|
self._script = script
|
||||||
script.on("message", lambda *args: self._reactor.schedule(lambda: self._on_message(*args)))
|
script.on("message", lambda *args: self._reactor.schedule(lambda: self._on_message(*args)))
|
||||||
script.load()
|
script.load()
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import threading
|
||||||
|
|
||||||
|
from frida_tools.application import Reactor
|
||||||
|
|
||||||
|
import frida
|
||||||
|
|
||||||
|
|
||||||
|
class Application:
|
||||||
|
def __init__(self):
|
||||||
|
self._stop_requested = threading.Event()
|
||||||
|
self._reactor = Reactor(run_until_return=lambda reactor: self._stop_requested.wait())
|
||||||
|
|
||||||
|
self._device = frida.get_usb_device()
|
||||||
|
self._sessions = set()
|
||||||
|
self._sessions_lock = threading.Lock()
|
||||||
|
|
||||||
|
self._device.on("spawn-added", lambda spawn: self._reactor.schedule(lambda: self._on_spawn_added(spawn)))
|
||||||
|
self._device.on("spawn-removed", lambda spawn: self._reactor.schedule(lambda: self._on_spawn_removed(spawn)))
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self._reactor.schedule(lambda: self._start())
|
||||||
|
self._reactor.run()
|
||||||
|
|
||||||
|
def _start(self):
|
||||||
|
self._device.enable_spawn_gating()
|
||||||
|
|
||||||
|
def _instrument(self, pid):
|
||||||
|
print(f"✔ attach(pid={pid})")
|
||||||
|
session = self._device.attach(pid)
|
||||||
|
session.on("detached", lambda reason: self._reactor.schedule(lambda: self._on_detached(pid, session, reason)))
|
||||||
|
print("✔ create_script()")
|
||||||
|
script = session.create_script("""\
|
||||||
|
const puts = new NativeFunction(Module.getGlobalExportByName('puts'), 'int', ['pointer']);
|
||||||
|
puts(Memory.allocUtf8String('Hello from Frida agent'));
|
||||||
|
Interceptor.attach(Module.getGlobalExportByName('open'), {
|
||||||
|
onEnter(args) {
|
||||||
|
send({
|
||||||
|
type: 'open',
|
||||||
|
path: args[0].readUtf8String()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
""")
|
||||||
|
script.on("message", lambda message, data: self._reactor.schedule(lambda: self._on_message(pid, message)))
|
||||||
|
print("✔ load()")
|
||||||
|
script.load()
|
||||||
|
print(f"✔ resume(pid={pid})")
|
||||||
|
self._device.resume(pid)
|
||||||
|
with self._sessions_lock:
|
||||||
|
self._sessions.add(session)
|
||||||
|
|
||||||
|
def _on_spawn_added(self, spawn):
|
||||||
|
print(f"⚡ spawn_added: {spawn}")
|
||||||
|
t = threading.Thread(target=self._handle_spawn, args=(spawn,))
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def _handle_spawn(self, spawn):
|
||||||
|
if "/bin/ls" in spawn.identifier:
|
||||||
|
self._instrument(spawn.pid)
|
||||||
|
else:
|
||||||
|
pid = spawn.pid
|
||||||
|
print(f"✔ resume(pid={pid})")
|
||||||
|
self._device.resume(pid)
|
||||||
|
|
||||||
|
def _on_spawn_removed(self, spawn):
|
||||||
|
print(f"⚡ spawn_removed: {spawn}")
|
||||||
|
|
||||||
|
def _on_detached(self, pid, session, reason):
|
||||||
|
print(f"⚡ detached: pid={pid}, reason='{reason}'")
|
||||||
|
with self._sessions_lock:
|
||||||
|
self._sessions.remove(session)
|
||||||
|
|
||||||
|
def _on_message(self, pid, message):
|
||||||
|
print(f"⚡ message: pid={pid}, payload={message['payload']}")
|
||||||
|
|
||||||
|
|
||||||
|
app = Application()
|
||||||
|
app.run()
|
||||||
+19
-3
@@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from . import _frida
|
from . import _frida
|
||||||
@@ -86,14 +86,30 @@ def kill(target: core.ProcessTarget) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def attach(
|
def attach(
|
||||||
target: core.ProcessTarget, realm: Optional[str] = None, persist_timeout: Optional[int] = None
|
target: core.ProcessTarget,
|
||||||
|
realm: Optional[str] = None,
|
||||||
|
persist_timeout: Optional[int] = None,
|
||||||
|
exceptor: Optional[str] = None,
|
||||||
|
unwind_broker: Optional[bool] = None,
|
||||||
|
exit_monitor: Optional[bool] = None,
|
||||||
|
thread_suspend_monitor: Optional[bool] = None,
|
||||||
|
linker_notifier_offsets: Optional[Sequence[int]] = None,
|
||||||
) -> core.Session:
|
) -> core.Session:
|
||||||
"""
|
"""
|
||||||
Attach to a process
|
Attach to a process
|
||||||
:param target: the PID or name of the process
|
:param target: the PID or name of the process
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return get_local_device().attach(target, realm=realm, persist_timeout=persist_timeout)
|
return get_local_device().attach(
|
||||||
|
target,
|
||||||
|
realm=realm,
|
||||||
|
persist_timeout=persist_timeout,
|
||||||
|
exceptor=exceptor,
|
||||||
|
unwind_broker=unwind_broker,
|
||||||
|
exit_monitor=exit_monitor,
|
||||||
|
thread_suspend_monitor=thread_suspend_monitor,
|
||||||
|
linker_notifier_offsets=linker_notifier_offsets,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def inject_library_file(target: core.ProcessTarget, path: str, entrypoint: str, data: str) -> int:
|
def inject_library_file(target: core.ProcessTarget, path: str, entrypoint: str, data: str) -> int:
|
||||||
|
|||||||
@@ -256,7 +256,17 @@ class Device(Object):
|
|||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def attach(self, pid: int, realm: Optional[str] = None, persist_timeout: Optional[int] = None) -> "Session":
|
def attach(
|
||||||
|
self,
|
||||||
|
pid: int,
|
||||||
|
realm: Optional[str] = None,
|
||||||
|
persist_timeout: Optional[int] = None,
|
||||||
|
exceptor: Optional[str] = None,
|
||||||
|
unwind_broker: Optional[bool] = None,
|
||||||
|
exit_monitor: Optional[bool] = None,
|
||||||
|
thread_suspend_monitor: Optional[bool] = None,
|
||||||
|
linker_notifier_offsets: Optional[Sequence[int]] = None,
|
||||||
|
) -> "Session":
|
||||||
"""
|
"""
|
||||||
Attach to a PID.
|
Attach to a PID.
|
||||||
"""
|
"""
|
||||||
|
|||||||
+190
-23
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2023 Ole André Vadla Ravnås <oleavr@nowsecure.com>
|
* Copyright (C) 2013-2026 Ole André Vadla Ravnås <oleavr@nowsecure.com>
|
||||||
* Copyright (C) 2024 Håvard Sørbø <havard@hsorbo.no>
|
* Copyright (C) 2024 Håvard Sørbø <havard@hsorbo.no>
|
||||||
*
|
*
|
||||||
* Licence: wxWindows Library Licence, Version 3.1
|
* Licence: wxWindows Library Licence, Version 3.1
|
||||||
@@ -378,6 +378,7 @@ static PyObject * PyGObject_marshal_variant (GVariant * variant);
|
|||||||
static PyObject * PyGObject_marshal_variant_byte_array (GVariant * variant);
|
static PyObject * PyGObject_marshal_variant_byte_array (GVariant * variant);
|
||||||
static PyObject * PyGObject_marshal_variant_dict (GVariant * variant);
|
static PyObject * PyGObject_marshal_variant_dict (GVariant * variant);
|
||||||
static PyObject * PyGObject_marshal_variant_array (GVariant * variant);
|
static PyObject * PyGObject_marshal_variant_array (GVariant * variant);
|
||||||
|
static PyObject * PyGObject_marshal_variant_tuple (GVariant * variant);
|
||||||
static gboolean PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant);
|
static gboolean PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant);
|
||||||
static gboolean PyGObject_unmarshal_variant_from_mapping (PyObject * mapping, GVariant ** variant);
|
static gboolean PyGObject_unmarshal_variant_from_mapping (PyObject * mapping, GVariant ** variant);
|
||||||
static gboolean PyGObject_unmarshal_variant_from_sequence (PyObject * sequence, GVariant ** variant);
|
static gboolean PyGObject_unmarshal_variant_from_sequence (PyObject * sequence, GVariant ** variant);
|
||||||
@@ -403,6 +404,7 @@ static void PyDevice_init_from_handle (PyDevice * self, FridaDevice * handle);
|
|||||||
static void PyDevice_dealloc (PyDevice * self);
|
static void PyDevice_dealloc (PyDevice * self);
|
||||||
static PyObject * PyDevice_repr (PyDevice * self);
|
static PyObject * PyDevice_repr (PyDevice * self);
|
||||||
static PyObject * PyDevice_is_lost (PyDevice * self);
|
static PyObject * PyDevice_is_lost (PyDevice * self);
|
||||||
|
static PyObject * PyDevice_override_option (PyDevice * self, PyObject * args, PyObject * kw);
|
||||||
static PyObject * PyDevice_query_system_parameters (PyDevice * self);
|
static PyObject * PyDevice_query_system_parameters (PyDevice * self);
|
||||||
static PyObject * PyDevice_get_frontmost_application (PyDevice * self, PyObject * args, PyObject * kw);
|
static PyObject * PyDevice_get_frontmost_application (PyDevice * self, PyObject * args, PyObject * kw);
|
||||||
static PyObject * PyDevice_enumerate_applications (PyDevice * self, PyObject * args, PyObject * kw);
|
static PyObject * PyDevice_enumerate_applications (PyDevice * self, PyObject * args, PyObject * kw);
|
||||||
@@ -418,7 +420,7 @@ static PyObject * PyDevice_input (PyDevice * self, PyObject * args);
|
|||||||
static PyObject * PyDevice_resume (PyDevice * self, PyObject * args);
|
static PyObject * PyDevice_resume (PyDevice * self, PyObject * args);
|
||||||
static PyObject * PyDevice_kill (PyDevice * self, PyObject * args);
|
static PyObject * PyDevice_kill (PyDevice * self, PyObject * args);
|
||||||
static PyObject * PyDevice_attach (PyDevice * self, PyObject * args, PyObject * kw);
|
static PyObject * PyDevice_attach (PyDevice * self, PyObject * args, PyObject * kw);
|
||||||
static FridaSessionOptions * PyDevice_parse_session_options (const gchar * realm_value, guint persist_timeout);
|
static FridaSessionOptions * PyDevice_parse_session_options (const gchar * realm_value, guint persist_timeout, const gchar * exceptor_value, gint unwind_broker, gint exit_monitor, gint thread_suspend_monitor, PyObject * linker_notifier_offsets_value);
|
||||||
static PyObject * PyDevice_inject_library_file (PyDevice * self, PyObject * args);
|
static PyObject * PyDevice_inject_library_file (PyDevice * self, PyObject * args);
|
||||||
static PyObject * PyDevice_inject_library_blob (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_channel (PyDevice * self, PyObject * args);
|
||||||
@@ -619,6 +621,7 @@ static PyMethodDef PyDeviceManager_methods[] =
|
|||||||
static PyMethodDef PyDevice_methods[] =
|
static PyMethodDef PyDevice_methods[] =
|
||||||
{
|
{
|
||||||
{ "is_lost", (PyCFunction) PyDevice_is_lost, METH_NOARGS, "Query whether the device has been lost." },
|
{ "is_lost", (PyCFunction) PyDevice_is_lost, METH_NOARGS, "Query whether the device has been lost." },
|
||||||
|
{ "override_option", (PyCFunction) PyDevice_override_option, METH_VARARGS | METH_KEYWORDS, "Override a backend-specific option." },
|
||||||
{ "query_system_parameters", (PyCFunction) PyDevice_query_system_parameters, METH_NOARGS, "Returns a dictionary of information about the host system." },
|
{ "query_system_parameters", (PyCFunction) PyDevice_query_system_parameters, METH_NOARGS, "Returns a dictionary of information about the host system." },
|
||||||
{ "get_frontmost_application", (PyCFunction) PyDevice_get_frontmost_application, METH_VARARGS | METH_KEYWORDS, "Get details about the frontmost application." },
|
{ "get_frontmost_application", (PyCFunction) PyDevice_get_frontmost_application, METH_VARARGS | METH_KEYWORDS, "Get details about the frontmost application." },
|
||||||
{ "enumerate_applications", (PyCFunction) PyDevice_enumerate_applications, METH_VARARGS | METH_KEYWORDS, "Enumerate applications." },
|
{ "enumerate_applications", (PyCFunction) PyDevice_enumerate_applications, METH_VARARGS | METH_KEYWORDS, "Enumerate applications." },
|
||||||
@@ -1749,10 +1752,20 @@ PyGObject_marshal_variant (GVariant * variant)
|
|||||||
{
|
{
|
||||||
case G_VARIANT_CLASS_STRING:
|
case G_VARIANT_CLASS_STRING:
|
||||||
return PyGObject_marshal_string (g_variant_get_string (variant, NULL));
|
return PyGObject_marshal_string (g_variant_get_string (variant, NULL));
|
||||||
|
case G_VARIANT_CLASS_BYTE:
|
||||||
|
return PyLong_FromLong (g_variant_get_byte (variant));
|
||||||
|
case G_VARIANT_CLASS_INT16:
|
||||||
|
return PyLong_FromLong (g_variant_get_int16 (variant));
|
||||||
|
case G_VARIANT_CLASS_UINT16:
|
||||||
|
return PyLong_FromUnsignedLong (g_variant_get_uint16 (variant));
|
||||||
|
case G_VARIANT_CLASS_INT32:
|
||||||
|
return PyLong_FromLong (g_variant_get_int32 (variant));
|
||||||
|
case G_VARIANT_CLASS_UINT32:
|
||||||
|
return PyLong_FromUnsignedLong (g_variant_get_uint32 (variant));
|
||||||
case G_VARIANT_CLASS_INT64:
|
case G_VARIANT_CLASS_INT64:
|
||||||
return PyLong_FromLongLong (g_variant_get_int64 (variant));
|
return PyLong_FromLongLong (g_variant_get_int64 (variant));
|
||||||
case G_VARIANT_CLASS_UINT64:
|
case G_VARIANT_CLASS_UINT64:
|
||||||
return PyLong_FromLongLong (g_variant_get_uint64 (variant));
|
return PyLong_FromUnsignedLongLong (g_variant_get_uint64 (variant));
|
||||||
case G_VARIANT_CLASS_DOUBLE:
|
case G_VARIANT_CLASS_DOUBLE:
|
||||||
return PyFloat_FromDouble (g_variant_get_double (variant));
|
return PyFloat_FromDouble (g_variant_get_double (variant));
|
||||||
case G_VARIANT_CLASS_BOOLEAN:
|
case G_VARIANT_CLASS_BOOLEAN:
|
||||||
@@ -1765,6 +1778,19 @@ PyGObject_marshal_variant (GVariant * variant)
|
|||||||
return PyGObject_marshal_variant_dict (variant);
|
return PyGObject_marshal_variant_dict (variant);
|
||||||
|
|
||||||
return PyGObject_marshal_variant_array (variant);
|
return PyGObject_marshal_variant_array (variant);
|
||||||
|
case G_VARIANT_CLASS_TUPLE:
|
||||||
|
return PyGObject_marshal_variant_tuple (variant);
|
||||||
|
case G_VARIANT_CLASS_VARIANT:
|
||||||
|
{
|
||||||
|
GVariant * inner;
|
||||||
|
PyObject * result;
|
||||||
|
|
||||||
|
inner = g_variant_get_variant (variant);
|
||||||
|
result = PyGObject_marshal_variant (inner);
|
||||||
|
g_variant_unref (inner);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1823,13 +1849,6 @@ PyGObject_marshal_variant_array (GVariant * variant)
|
|||||||
|
|
||||||
for (i = 0; (child = g_variant_iter_next_value (&iter)) != NULL; i++)
|
for (i = 0; (child = g_variant_iter_next_value (&iter)) != NULL; i++)
|
||||||
{
|
{
|
||||||
if (g_variant_is_of_type (child, G_VARIANT_TYPE_VARIANT))
|
|
||||||
{
|
|
||||||
GVariant * inner = g_variant_get_variant (child);
|
|
||||||
g_variant_unref (child);
|
|
||||||
child = inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyList_SetItem (list, i, PyGObject_marshal_variant (child));
|
PyList_SetItem (list, i, PyGObject_marshal_variant (child));
|
||||||
|
|
||||||
g_variant_unref (child);
|
g_variant_unref (child);
|
||||||
@@ -1838,6 +1857,28 @@ PyGObject_marshal_variant_array (GVariant * variant)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
PyGObject_marshal_variant_tuple (GVariant * variant)
|
||||||
|
{
|
||||||
|
GVariantIter iter;
|
||||||
|
PyObject * tuple;
|
||||||
|
guint i;
|
||||||
|
GVariant * child;
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, variant);
|
||||||
|
|
||||||
|
tuple = PyTuple_New (g_variant_iter_n_children (&iter));
|
||||||
|
|
||||||
|
for (i = 0; (child = g_variant_iter_next_value (&iter)) != NULL; i++)
|
||||||
|
{
|
||||||
|
PyTuple_SetItem (tuple, i, PyGObject_marshal_variant (child));
|
||||||
|
|
||||||
|
g_variant_unref (child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tuple;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant)
|
PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant)
|
||||||
{
|
{
|
||||||
@@ -1847,14 +1888,14 @@ PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant)
|
|||||||
|
|
||||||
PyGObject_unmarshal_string (value, &str);
|
PyGObject_unmarshal_string (value, &str);
|
||||||
|
|
||||||
*variant = g_variant_new_take_string (str);
|
*variant = g_variant_ref_sink (g_variant_new_take_string (str));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyBool_Check (value))
|
if (PyBool_Check (value))
|
||||||
{
|
{
|
||||||
*variant = g_variant_new_boolean (value == Py_True);
|
*variant = g_variant_ref_sink (g_variant_new_boolean (value == Py_True));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1867,14 +1908,14 @@ PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant)
|
|||||||
if (l == -1 && PyErr_Occurred ())
|
if (l == -1 && PyErr_Occurred ())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
*variant = g_variant_new_int64 (l);
|
*variant = g_variant_ref_sink (g_variant_new_int64 (l));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyFloat_Check (value))
|
if (PyFloat_Check (value))
|
||||||
{
|
{
|
||||||
*variant = g_variant_new_double (PyFloat_AsDouble (value));
|
*variant = g_variant_ref_sink (g_variant_new_double (PyFloat_AsDouble (value)));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1888,7 +1929,7 @@ PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant)
|
|||||||
PyBytes_AsStringAndSize (value, &buffer, &length);
|
PyBytes_AsStringAndSize (value, &buffer, &length);
|
||||||
|
|
||||||
copy = g_memdup2 (buffer, length);
|
copy = g_memdup2 (buffer, length);
|
||||||
*variant = g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING, copy, length, TRUE, g_free, copy);
|
*variant = g_variant_ref_sink (g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING, copy, length, TRUE, g_free, copy));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1934,12 +1975,13 @@ PyGObject_unmarshal_variant_from_mapping (PyObject * mapping, GVariant ** varian
|
|||||||
|
|
||||||
g_variant_builder_add (&builder, "{sv}", PyBytes_AsString (key_bytes), raw_value);
|
g_variant_builder_add (&builder, "{sv}", PyBytes_AsString (key_bytes), raw_value);
|
||||||
|
|
||||||
|
g_variant_unref (raw_value);
|
||||||
Py_DecRef (key_bytes);
|
Py_DecRef (key_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_DecRef (items);
|
Py_DecRef (items);
|
||||||
|
|
||||||
*variant = g_variant_builder_end (&builder);
|
*variant = g_variant_ref_sink (g_variant_builder_end (&builder));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@@ -1962,6 +2004,31 @@ PyGObject_unmarshal_variant_from_sequence (PyObject * sequence, GVariant ** vari
|
|||||||
|
|
||||||
is_tuple = PyTuple_Check (sequence);
|
is_tuple = PyTuple_Check (sequence);
|
||||||
|
|
||||||
|
if (is_tuple && PyTuple_Size (sequence) == 2)
|
||||||
|
{
|
||||||
|
gchar * type;
|
||||||
|
gboolean is_uint64_cast;
|
||||||
|
|
||||||
|
if (!PyGObject_unmarshal_string (PyTuple_GetItem (sequence, 0), &type))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
is_uint64_cast = strcmp (type, "uint64") == 0;
|
||||||
|
|
||||||
|
g_free (type);
|
||||||
|
|
||||||
|
if (is_uint64_cast)
|
||||||
|
{
|
||||||
|
unsigned PY_LONG_LONG l;
|
||||||
|
|
||||||
|
l = PyLong_AsUnsignedLongLong (PyTuple_GetItem (sequence, 1));
|
||||||
|
if (l == (unsigned PY_LONG_LONG) -1 && PyErr_Occurred ())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*variant = g_variant_ref_sink (g_variant_new_uint64 (l));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_variant_builder_init (&builder, is_tuple ? G_VARIANT_TYPE_TUPLE : G_VARIANT_TYPE ("av"));
|
g_variant_builder_init (&builder, is_tuple ? G_VARIANT_TYPE_TUPLE : G_VARIANT_TYPE ("av"));
|
||||||
|
|
||||||
n = PySequence_Length (sequence);
|
n = PySequence_Length (sequence);
|
||||||
@@ -1984,10 +2051,11 @@ PyGObject_unmarshal_variant_from_sequence (PyObject * sequence, GVariant ** vari
|
|||||||
else
|
else
|
||||||
g_variant_builder_add (&builder, "v", raw_value);
|
g_variant_builder_add (&builder, "v", raw_value);
|
||||||
|
|
||||||
|
g_variant_unref (raw_value);
|
||||||
Py_DecRef (val);
|
Py_DecRef (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
*variant = g_variant_builder_end (&builder);
|
*variant = g_variant_ref_sink (g_variant_builder_end (&builder));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@@ -2455,6 +2523,33 @@ PyDevice_is_lost (PyDevice * self)
|
|||||||
return PyBool_FromLong (is_lost);
|
return PyBool_FromLong (is_lost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
PyDevice_override_option (PyDevice * self, PyObject * args, PyObject * kw)
|
||||||
|
{
|
||||||
|
static char * keywords[] = { "name", "value", NULL };
|
||||||
|
const char * name;
|
||||||
|
PyObject * value;
|
||||||
|
GVariant * raw_value;
|
||||||
|
GError * error = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords (args, kw, "sO", keywords, &name, &value))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!PyGObject_unmarshal_variant (value, &raw_value))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
frida_device_override_option (PY_GOBJECT_HANDLE (self), name, raw_value, &error);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
g_variant_unref (raw_value);
|
||||||
|
|
||||||
|
if (error != NULL)
|
||||||
|
return PyFrida_raise (error);
|
||||||
|
|
||||||
|
PyFrida_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PyDevice_query_system_parameters (PyDevice * self)
|
PyDevice_query_system_parameters (PyDevice * self)
|
||||||
{
|
{
|
||||||
@@ -2887,7 +2982,7 @@ PyDevice_spawn (PyDevice * self, PyObject * args, PyObject * kw)
|
|||||||
goto invalid_dict_value;
|
goto invalid_dict_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_insert (aux, raw_key, g_variant_ref_sink (raw_value));
|
g_hash_table_insert (aux, raw_key, raw_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2986,21 +3081,43 @@ static PyObject *
|
|||||||
PyDevice_attach (PyDevice * self, PyObject * args, PyObject * kw)
|
PyDevice_attach (PyDevice * self, PyObject * args, PyObject * kw)
|
||||||
{
|
{
|
||||||
PyObject * result = NULL;
|
PyObject * result = NULL;
|
||||||
static char * keywords[] = { "pid", "realm", "persist_timeout", NULL };
|
static char * keywords[] = {
|
||||||
|
"pid",
|
||||||
|
"realm",
|
||||||
|
"persist_timeout",
|
||||||
|
"exceptor",
|
||||||
|
"unwind_broker",
|
||||||
|
"exit_monitor",
|
||||||
|
"thread_suspend_monitor",
|
||||||
|
"linker_notifier_offsets",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
long pid;
|
long pid;
|
||||||
char * realm_value = NULL;
|
char * realm_value = NULL;
|
||||||
unsigned int persist_timeout = 0;
|
unsigned int persist_timeout = 0;
|
||||||
|
char * exceptor_value = NULL;
|
||||||
|
int unwind_broker = -1;
|
||||||
|
int exit_monitor = -1;
|
||||||
|
int thread_suspend_monitor = -1;
|
||||||
|
PyObject * linker_notifier_offsets_value = NULL;
|
||||||
FridaSessionOptions * options = NULL;
|
FridaSessionOptions * options = NULL;
|
||||||
GError * error = NULL;
|
GError * error = NULL;
|
||||||
FridaSession * handle;
|
FridaSession * handle;
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords (args, kw, "l|esI", keywords,
|
if (!PyArg_ParseTupleAndKeywords (args, kw, "l|esIespppO", keywords,
|
||||||
&pid,
|
&pid,
|
||||||
"utf-8", &realm_value,
|
"utf-8", &realm_value,
|
||||||
&persist_timeout))
|
&persist_timeout,
|
||||||
|
"utf-8", &exceptor_value,
|
||||||
|
&unwind_broker,
|
||||||
|
&exit_monitor,
|
||||||
|
&thread_suspend_monitor,
|
||||||
|
&linker_notifier_offsets_value))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
options = PyDevice_parse_session_options (realm_value, persist_timeout);
|
options = PyDevice_parse_session_options (realm_value, persist_timeout,
|
||||||
|
exceptor_value, unwind_broker, exit_monitor, thread_suspend_monitor,
|
||||||
|
linker_notifier_offsets_value);
|
||||||
if (options == NULL)
|
if (options == NULL)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
@@ -3015,6 +3132,7 @@ PyDevice_attach (PyDevice * self, PyObject * args, PyObject * kw)
|
|||||||
beach:
|
beach:
|
||||||
g_clear_object (&options);
|
g_clear_object (&options);
|
||||||
|
|
||||||
|
PyMem_Free (exceptor_value);
|
||||||
PyMem_Free (realm_value);
|
PyMem_Free (realm_value);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -3022,7 +3140,12 @@ beach:
|
|||||||
|
|
||||||
static FridaSessionOptions *
|
static FridaSessionOptions *
|
||||||
PyDevice_parse_session_options (const gchar * realm_value,
|
PyDevice_parse_session_options (const gchar * realm_value,
|
||||||
guint persist_timeout)
|
guint persist_timeout,
|
||||||
|
const gchar * exceptor_value,
|
||||||
|
gint unwind_broker,
|
||||||
|
gint exit_monitor,
|
||||||
|
gint thread_suspend_monitor,
|
||||||
|
PyObject * linker_notifier_offsets_value)
|
||||||
{
|
{
|
||||||
FridaSessionOptions * options;
|
FridaSessionOptions * options;
|
||||||
|
|
||||||
@@ -3040,6 +3163,50 @@ PyDevice_parse_session_options (const gchar * realm_value,
|
|||||||
|
|
||||||
frida_session_options_set_persist_timeout (options, persist_timeout);
|
frida_session_options_set_persist_timeout (options, persist_timeout);
|
||||||
|
|
||||||
|
if (exceptor_value != NULL)
|
||||||
|
{
|
||||||
|
FridaExceptor exceptor;
|
||||||
|
|
||||||
|
if (!PyGObject_unmarshal_enum (exceptor_value, FRIDA_TYPE_EXCEPTOR, &exceptor))
|
||||||
|
goto propagate_error;
|
||||||
|
|
||||||
|
frida_session_options_set_exceptor (options, exceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unwind_broker != -1)
|
||||||
|
frida_session_options_set_unwind_broker (options, unwind_broker);
|
||||||
|
|
||||||
|
if (exit_monitor != -1)
|
||||||
|
frida_session_options_set_exit_monitor (options, exit_monitor);
|
||||||
|
|
||||||
|
if (thread_suspend_monitor != -1)
|
||||||
|
frida_session_options_set_thread_suspend_monitor (options, thread_suspend_monitor);
|
||||||
|
|
||||||
|
if (linker_notifier_offsets_value != NULL)
|
||||||
|
{
|
||||||
|
gint n, i;
|
||||||
|
|
||||||
|
n = PySequence_Size (linker_notifier_offsets_value);
|
||||||
|
if (n == -1)
|
||||||
|
goto propagate_error;
|
||||||
|
|
||||||
|
for (i = 0; i != n; i++)
|
||||||
|
{
|
||||||
|
PyObject * element;
|
||||||
|
unsigned long offset;
|
||||||
|
|
||||||
|
element = PySequence_GetItem (linker_notifier_offsets_value, i);
|
||||||
|
if (element == NULL)
|
||||||
|
goto propagate_error;
|
||||||
|
offset = PyLong_AsUnsignedLong (element);
|
||||||
|
Py_DecRef (element);
|
||||||
|
if (offset == (unsigned long) -1 && PyErr_Occurred () != NULL)
|
||||||
|
goto propagate_error;
|
||||||
|
|
||||||
|
frida_session_options_add_linker_notifier_offset (options, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
|
|
||||||
propagate_error:
|
propagate_error:
|
||||||
|
|||||||
+26
-4
@@ -883,6 +883,14 @@ class Device:
|
|||||||
|
|
||||||
return self._impl.is_lost()
|
return self._impl.is_lost()
|
||||||
|
|
||||||
|
@cancellable
|
||||||
|
def override_option(self, name: str, value: Any) -> None:
|
||||||
|
"""
|
||||||
|
Override a backend-specific option
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._impl.override_option(name, value)
|
||||||
|
|
||||||
@cancellable
|
@cancellable
|
||||||
def query_system_parameters(self) -> Dict[str, Any]:
|
def query_system_parameters(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
@@ -1038,13 +1046,26 @@ class Device:
|
|||||||
target: ProcessTarget,
|
target: ProcessTarget,
|
||||||
realm: Optional[str] = None,
|
realm: Optional[str] = None,
|
||||||
persist_timeout: Optional[int] = None,
|
persist_timeout: Optional[int] = None,
|
||||||
|
exceptor: Optional[str] = None,
|
||||||
|
unwind_broker: Optional[bool] = None,
|
||||||
|
exit_monitor: Optional[bool] = None,
|
||||||
|
thread_suspend_monitor: Optional[bool] = None,
|
||||||
|
linker_notifier_offsets: Optional[Sequence[int]] = None,
|
||||||
) -> Session:
|
) -> Session:
|
||||||
"""
|
"""
|
||||||
Attach to a process
|
Attach to a process
|
||||||
:param target: the PID or name of the process
|
:param target: the PID or name of the process
|
||||||
"""
|
"""
|
||||||
|
|
||||||
kwargs = {"realm": realm, "persist_timeout": persist_timeout}
|
kwargs = {
|
||||||
|
"realm": realm,
|
||||||
|
"persist_timeout": persist_timeout,
|
||||||
|
"exceptor": exceptor,
|
||||||
|
"unwind_broker": unwind_broker,
|
||||||
|
"exit_monitor": exit_monitor,
|
||||||
|
"thread_suspend_monitor": thread_suspend_monitor,
|
||||||
|
"linker_notifier_offsets": linker_notifier_offsets,
|
||||||
|
}
|
||||||
_filter_missing_kwargs(kwargs)
|
_filter_missing_kwargs(kwargs)
|
||||||
return Session(self._impl.attach(self._pid_of(target), **kwargs)) # type: ignore
|
return Session(self._impl.attach(self._pid_of(target), **kwargs)) # type: ignore
|
||||||
|
|
||||||
@@ -1310,7 +1331,7 @@ class EndpointParameters:
|
|||||||
_filter_missing_kwargs(kwargs)
|
_filter_missing_kwargs(kwargs)
|
||||||
|
|
||||||
if authentication is not None:
|
if authentication is not None:
|
||||||
(auth_scheme, auth_data) = authentication
|
auth_scheme, auth_data = authentication
|
||||||
if auth_scheme == "token":
|
if auth_scheme == "token":
|
||||||
kwargs["auth_token"] = auth_data
|
kwargs["auth_token"] = auth_data
|
||||||
elif auth_scheme == "callback":
|
elif auth_scheme == "callback":
|
||||||
@@ -1524,6 +1545,7 @@ CompilerSourceMaps = Literal["included", "omitted"]
|
|||||||
CompilerCompression = Literal["none", "terser"]
|
CompilerCompression = Literal["none", "terser"]
|
||||||
CompilerPlatform = Literal["neutral", "gum", "browser"]
|
CompilerPlatform = Literal["neutral", "gum", "browser"]
|
||||||
|
|
||||||
|
|
||||||
class Compiler:
|
class Compiler:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._impl = _frida.Compiler()
|
self._impl = _frida.Compiler()
|
||||||
@@ -1544,7 +1566,7 @@ class Compiler:
|
|||||||
platform: Optional[CompilerPlatform] = None,
|
platform: Optional[CompilerPlatform] = None,
|
||||||
externals: Optional[Sequence[str]] = None,
|
externals: Optional[Sequence[str]] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
kwargs = {
|
kwargs: dict[str, Any] = {
|
||||||
"project_root": project_root,
|
"project_root": project_root,
|
||||||
"output_format": output_format,
|
"output_format": output_format,
|
||||||
"bundle_format": bundle_format,
|
"bundle_format": bundle_format,
|
||||||
@@ -1570,7 +1592,7 @@ class Compiler:
|
|||||||
platform: Optional[CompilerPlatform] = None,
|
platform: Optional[CompilerPlatform] = None,
|
||||||
externals: Optional[Sequence[str]] = None,
|
externals: Optional[Sequence[str]] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
kwargs = {
|
kwargs: dict[str, Any] = {
|
||||||
"project_root": project_root,
|
"project_root": project_root,
|
||||||
"output_format": output_format,
|
"output_format": output_format,
|
||||||
"bundle_format": bundle_format,
|
"bundle_format": bundle_format,
|
||||||
|
|||||||
+1
-1
Submodule releng updated: c144673b9d...1442ae5a7a
@@ -1,6 +1,6 @@
|
|||||||
[wrap-git]
|
[wrap-git]
|
||||||
url = https://github.com/frida/frida-core.git
|
url = https://github.com/frida/frida-core.git
|
||||||
revision = 17.5.2
|
revision = 17.11.0
|
||||||
depth = 1
|
depth = 1
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
|
|||||||
Reference in New Issue
Block a user