compiler: Add Compiler API

This commit is contained in:
Ole André Vadla Ravnås
2022-07-20 01:42:20 +02:00
parent 54cd19a859
commit 77f0141d4b
3 changed files with 222 additions and 9 deletions
+2 -9
View File
@@ -27,9 +27,11 @@ from . import core
__version__ = _frida.__version__
get_device_manager = core.get_device_manager
Relay = _frida.Relay
PortalService = core.PortalService
EndpointParameters = core.EndpointParameters
Compiler = core.Compiler
FileMonitor = _frida.FileMonitor
Cancellable = core.Cancellable
@@ -104,12 +106,3 @@ def enumerate_devices(**kwargs):
@core.cancellable
def shutdown():
get_device_manager()._impl.close()
global _device_manager
_device_manager = None
def get_device_manager():
global _device_manager
if _device_manager is None:
_device_manager = core.DeviceManager(_frida.DeviceManager())
return _device_manager
+30
View File
@@ -12,9 +12,17 @@ import traceback
import _frida
_device_manager = None
_Cancellable = _frida.Cancellable
def get_device_manager():
global _device_manager
if _device_manager is None:
_device_manager = DeviceManager(_frida.DeviceManager())
return _device_manager
def cancellable(f):
@wraps(f)
def wrapper(*args, **kwargs):
@@ -591,6 +599,28 @@ class PortalService(object):
traceback.print_exc()
class Compiler(object):
def __init__(self):
self._impl = _frida.Compiler(get_device_manager()._impl)
def __repr__(self):
return repr(self._impl)
@cancellable
def build(self, *args, **kwargs):
return self._impl.build(*args, **kwargs)
@cancellable
def watch(self, *args, **kwargs):
return self._impl.watch(*args, **kwargs)
def on(self, signal, callback):
self._impl.on(signal, callback)
def off(self, signal, callback):
self._impl.off(signal, callback)
class IOStream(object):
def __init__(self, impl):
self._impl = impl
+190
View File
@@ -129,6 +129,7 @@ typedef struct _PyRelay PyRelay;
typedef struct _PyPortalMembership PyPortalMembership;
typedef struct _PyPortalService PyPortalService;
typedef struct _PyEndpointParameters PyEndpointParameters;
typedef struct _PyCompiler PyCompiler;
typedef struct _PyFileMonitor PyFileMonitor;
typedef struct _PyIOStream PyIOStream;
typedef struct _PyCancellable PyCancellable;
@@ -271,6 +272,11 @@ struct _FridaPythonAuthenticationService
GThreadPool * pool;
};
struct _PyCompiler
{
PyGObject parent;
};
struct _PyFileMonitor
{
PyGObject parent;
@@ -316,6 +322,7 @@ static PyObject * PyGObject_marshal_enum (gint value, GType type);
static gboolean PyGObject_unmarshal_enum (const gchar * str, GType type, gpointer value);
static PyObject * PyGObject_marshal_bytes (GBytes * bytes);
static PyObject * PyGObject_marshal_bytes_non_nullable (GBytes * bytes);
static PyObject * PyGObject_marshal_variant (GVariant * variant);
static gboolean PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant);
static PyObject * PyGObject_marshal_parameters_dict (GHashTable * dict);
static PyObject * PyGObject_marshal_socket_address (GSocketAddress * address);
@@ -453,6 +460,12 @@ static gchar * frida_python_authentication_service_authenticate_finish (FridaAut
GError ** error);
static void frida_python_authentication_service_do_authenticate (GTask * task, FridaPythonAuthenticationService * self);
static int PyCompiler_init (PyCompiler * self, PyObject * args, PyObject * kw);
static PyObject * PyCompiler_build (PyCompiler * self, PyObject * args, PyObject * kw);
static PyObject * PyCompiler_watch (PyCompiler * self, PyObject * args, PyObject * kw);
static gboolean PyCompiler_set_options (FridaCompilerOptions * options, const gchar * project_root_value, const gchar * source_maps_value,
const gchar * compression_value);
static int PyFileMonitor_init (PyFileMonitor * self, PyObject * args, PyObject * kw);
static PyObject * PyFileMonitor_enable (PyFileMonitor * self);
static PyObject * PyFileMonitor_disable (PyFileMonitor * self);
@@ -658,6 +671,13 @@ static PyMemberDef PyPortalService_members[] =
{ NULL }
};
static PyMethodDef PyCompiler_methods[] =
{
{ "build", (PyCFunction) PyCompiler_build, METH_VARARGS | METH_KEYWORDS, "Build an agent." },
{ "watch", (PyCFunction) PyCompiler_watch, METH_VARARGS | METH_KEYWORDS, "Continuously build an agent." },
{ NULL }
};
static PyMethodDef PyFileMonitor_methods[] =
{
{ "enable", (PyCFunction) PyFileMonitor_enable, METH_NOARGS, "Enable the file monitor." },
@@ -1321,6 +1341,48 @@ static PyTypeObject PyEndpointParametersType =
PYFRIDA_DEFINE_TYPE (EndpointParameters, NULL, g_object_unref);
static PyTypeObject PyCompilerType =
{
PyVarObject_HEAD_INIT (NULL, 0)
"_frida.Compiler", /* tp_name */
sizeof (PyCompiler), /* tp_basicsize */
0, /* tp_itemsize */
NULL, /* tp_dealloc */
PYFRIDA_NO_PRINT_FUNC_OR_VECTORCALL_OFFSET, /* tp_{print,vco} */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
NULL, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
NULL, /* tp_as_mapping */
NULL, /* tp_hash */
NULL, /* tp_call */
NULL, /* tp_str */
NULL, /* tp_getattro */
NULL, /* tp_setattro */
NULL, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"Frida File Monitor", /* tp_doc */
NULL, /* tp_traverse */
NULL, /* tp_clear */
NULL, /* tp_richcompare */
0, /* tp_weaklistoffset */
NULL, /* tp_iter */
NULL, /* tp_iternext */
PyCompiler_methods, /* tp_methods */
NULL, /* tp_members */
NULL, /* tp_getset */
&PyGObjectType, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) PyCompiler_init, /* tp_init */
};
PYFRIDA_DEFINE_TYPE (Compiler, NULL, frida_unref);
static PyTypeObject PyFileMonitorType =
{
PyVarObject_HEAD_INIT (NULL, 0)
@@ -1833,6 +1895,9 @@ PyGObject_marshal_value (const GValue * value)
case G_TYPE_STRING:
return PyGObject_marshal_string (g_value_get_string (value));
case G_TYPE_VARIANT:
return PyGObject_marshal_variant (g_value_get_variant (value));
default:
if (G_TYPE_IS_ENUM (type))
return PyGObject_marshal_enum (g_value_get_enum (value), type);
@@ -4993,6 +5058,130 @@ frida_python_authentication_service_do_authenticate (GTask * task, FridaPythonAu
}
static int
PyCompiler_init (PyCompiler * self, PyObject * args, PyObject * kw)
{
PyDeviceManager * manager;
if (PyGObjectType.tp_init ((PyObject *) self, args, kw) < 0)
return -1;
if (!PyArg_ParseTuple (args, "O!", &PYFRIDA_TYPE (DeviceManager), &manager))
return -1;
PyGObject_take_handle (&self->parent, frida_compiler_new (PY_GOBJECT_HANDLE (manager)), &PYFRIDA_TYPE_SPEC (Compiler));
return 0;
}
static PyObject *
PyCompiler_build (PyCompiler * self, PyObject * args, PyObject * kw)
{
PyObject * result;
static char * keywords[] = { "entrypoint", "project_root", "source_maps", "compression", NULL };
const char * entrypoint;
const char * project_root = NULL;
const char * source_maps = NULL;
const char * compression = NULL;
FridaBuildOptions * options;
GError * error = NULL;
gchar * bundle;
if (!PyArg_ParseTupleAndKeywords (args, kw, "s|sss", keywords, &entrypoint, &project_root, &source_maps, &compression))
return NULL;
options = frida_build_options_new ();
if (!PyCompiler_set_options (FRIDA_COMPILER_OPTIONS (options), project_root, source_maps, compression))
goto invalid_option_value;
Py_BEGIN_ALLOW_THREADS
bundle = frida_compiler_build_sync (PY_GOBJECT_HANDLE (self), entrypoint, options, g_cancellable_get_current (), &error);
Py_END_ALLOW_THREADS
g_object_unref (options);
if (error != NULL)
return PyFrida_raise (error);
result = PyUnicode_FromUTF8String (bundle);
g_free (bundle);
return result;
invalid_option_value:
{
g_object_unref (options);
return NULL;
}
}
static PyObject *
PyCompiler_watch (PyCompiler * self, PyObject * args, PyObject * kw)
{
static char * keywords[] = { "entrypoint", "project_root", "source_maps", "compression", NULL };
const char * entrypoint;
const char * project_root = NULL;
const char * source_maps = NULL;
const char * compression = NULL;
FridaWatchOptions * options;
GError * error = NULL;
if (!PyArg_ParseTupleAndKeywords (args, kw, "s|sss", keywords, &entrypoint, &project_root, &source_maps, &compression))
return NULL;
options = frida_watch_options_new ();
if (!PyCompiler_set_options (FRIDA_COMPILER_OPTIONS (options), project_root, source_maps, compression))
goto invalid_option_value;
Py_BEGIN_ALLOW_THREADS
frida_compiler_watch_sync (PY_GOBJECT_HANDLE (self), entrypoint, options, g_cancellable_get_current (), &error);
Py_END_ALLOW_THREADS
g_object_unref (options);
if (error != NULL)
return PyFrida_raise (error);
Py_RETURN_NONE;
invalid_option_value:
{
g_object_unref (options);
return NULL;
}
}
static gboolean
PyCompiler_set_options (FridaCompilerOptions * options, const gchar * project_root_value, const gchar * source_maps_value,
const gchar * compression_value)
{
if (project_root_value != NULL)
frida_compiler_options_set_project_root (options, project_root_value);
if (source_maps_value != NULL)
{
FridaSourceMaps source_maps;
if (!PyGObject_unmarshal_enum (source_maps_value, FRIDA_TYPE_SOURCE_MAPS, &source_maps))
return FALSE;
frida_compiler_options_set_source_maps (options, source_maps);
}
if (compression_value != NULL)
{
FridaJsCompression compression;
if (!PyGObject_unmarshal_enum (compression_value, FRIDA_TYPE_JS_COMPRESSION, &compression))
return FALSE;
frida_compiler_options_set_compression (options, compression);
}
return TRUE;
}
static int
PyFileMonitor_init (PyFileMonitor * self, PyObject * args, PyObject * kw)
{
@@ -5613,6 +5802,7 @@ MOD_INIT (_frida)
PYFRIDA_REGISTER_TYPE (PortalMembership, FRIDA_TYPE_PORTAL_MEMBERSHIP);
PYFRIDA_REGISTER_TYPE (PortalService, FRIDA_TYPE_PORTAL_SERVICE);
PYFRIDA_REGISTER_TYPE (EndpointParameters, FRIDA_TYPE_ENDPOINT_PARAMETERS);
PYFRIDA_REGISTER_TYPE (Compiler, FRIDA_TYPE_COMPILER);
PYFRIDA_REGISTER_TYPE (FileMonitor, FRIDA_TYPE_FILE_MONITOR);
PYFRIDA_REGISTER_TYPE (IOStream, G_TYPE_IO_STREAM);
PYFRIDA_REGISTER_TYPE (Cancellable, G_TYPE_CANCELLABLE);