diff options
Diffstat (limited to 'plugins/pychrysalide/analysis/loaded.c')
-rw-r--r-- | plugins/pychrysalide/analysis/loaded.c | 266 |
1 files changed, 204 insertions, 62 deletions
diff --git a/plugins/pychrysalide/analysis/loaded.c b/plugins/pychrysalide/analysis/loaded.c index 3ed51d5..a2bf13f 100644 --- a/plugins/pychrysalide/analysis/loaded.c +++ b/plugins/pychrysalide/analysis/loaded.c @@ -35,6 +35,7 @@ #include <analysis/loaded-int.h> #include <core/global.h> +#include <plugins/dt.h> #include "content.h" @@ -47,14 +48,17 @@ /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Procède à l'initialisation de l'interface de génération. */ -static void py_loaded_content_interface_init(GLoadedContentIface *, gpointer *); +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_loaded_content_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise la classe générique des contenus chargés. */ +static void py_loaded_content_init_gclass(GLoadedContentClass *, gpointer); /* Fournit le contenu représenté de l'élément chargé. */ static GBinContent *py_loaded_content_get_content_wrapper(const GLoadedContent *); -/* Fournit le format associé à l'élément chargé. */ -static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *); +/* Décrit la nature du contenu reconnu pour l'élément chargé. */ +static char *py_loaded_content_get_content_class_wrapper(const GLoadedContent *, bool); /* Lance l'analyse propre à l'élément chargé. */ static bool py_loaded_content_analyze_wrapper(GLoadedContent *, bool, bool, wgroup_id_t, GtkStatusStack *); @@ -62,6 +66,8 @@ static bool py_loaded_content_analyze_wrapper(GLoadedContent *, bool, bool, wgro /* Fournit le désignation associée à l'élément chargé. */ static char *py_loaded_content_describe_wrapper(const GLoadedContent *, bool); +#ifdef INCLUDE_GTK_SUPPORT + /* Détermine le nombre de vues disponibles pour un contenu. */ static unsigned int py_loaded_content_count_views_wrapper(const GLoadedContent *); @@ -77,6 +83,8 @@ static GtkWidget *py_loaded_content_build_view_wrapper(GLoadedContent *, unsigne /* Retrouve l'indice correspondant à la vue donnée d'un contenu. */ static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *, GtkWidget *); +#endif + /* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ @@ -94,6 +102,8 @@ static PyObject *py_loaded_content_describe(PyObject *, PyObject *); /* Etablit une liste d'obscurcissements présents. */ static PyObject *py_loaded_content_detect_obfuscators(PyObject *, PyObject *); +#ifdef INCLUDE_GTK_SUPPORT + /* Détermine le nombre de vues disponibles pour un contenu. */ static PyObject *py_loaded_content_count_views(PyObject *, PyObject *); @@ -106,11 +116,16 @@ static PyObject *py_loaded_content_build_default_view(PyObject *, PyObject *); /* Met en place la vue initiale pour un contenu chargé. */ static PyObject *py_loaded_content_build_view(PyObject *, PyObject *); +#endif + /* Fournit le contenu représenté de l'élément chargé. */ static PyObject *py_loaded_content_get_content(PyObject *, void *); -/* Fournit le format associé à l'élément chargé. */ -static PyObject *py_loaded_content_get_format_name(PyObject *, void *); +/* Décrit la nature du contenu reconnu pour l'élément chargé. */ +static PyObject *py_loaded_content_get_content_class(PyObject *, void *); + +/* Décrit la nature du contenu reconnu pour l'élément chargé. */ +static PyObject *py_loaded_content_get_content_class_for_human(PyObject *, void *); @@ -121,21 +136,28 @@ static PyObject *py_loaded_content_get_format_name(PyObject *, void *); /****************************************************************************** * * -* Paramètres : iface = interface GLib à initialiser. * -* unused = adresse non utilisée ici. * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * * * -* Description : Procède à l'initialisation de l'interface de génération. * +* Description : Accompagne la création d'une instance dérivée en Python. * * * -* Retour : - * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -static void py_loaded_content_interface_init(GLoadedContentIface *iface, gpointer *unused) +static PyObject *py_loaded_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + #define LOADED_CONTENT_DOC \ - "The LoadedContent interface is an intermediary level of abstraction" \ + "The LoadedContent object is an intermediary level of abstraction" \ " for all loaded binary contents to analyze." \ "\n" \ "No matter if the loaded content comes from an ELF file or XML data," \ @@ -148,7 +170,7 @@ static void py_loaded_content_interface_init(GLoadedContentIface *iface, gpointe "\n" \ "The following methods have to be defined for new implementations:\n" \ "* pychrysalide.analysis.storage.LoadedContent._get_content();\n" \ - "* pychrysalide.analysis.storage.LoadedContent._get_format_name();\n" \ + "* pychrysalide.analysis.storage.LoadedContent._get_content_class();\n" \ "* pychrysalide.analysis.storage.LoadedContent._analyze();\n" \ "* pychrysalide.analysis.storage.LoadedContent._describe();\n" \ "* pychrysalide.analysis.storage.LoadedContent._count_views();\n" \ @@ -157,18 +179,76 @@ static void py_loaded_content_interface_init(GLoadedContentIface *iface, gpointe "* pychrysalide.analysis.storage.LoadedContent._build_view();\n" \ "* pychrysalide.analysis.storage.LoadedContent._get_view_index();\n" - iface->get_content = py_loaded_content_get_content_wrapper; - iface->get_format_name = py_loaded_content_get_format_name_wrapper; + /* Validations diverses */ + + base = get_python_loaded_content_type(); + + if (type == base) + { + result = NULL; + PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name); + goto exit; + } - iface->analyze = py_loaded_content_analyze_wrapper; + /* Mise en place d'un type dédié */ - iface->describe = py_loaded_content_describe_wrapper; + first_time = (g_type_from_name(type->tp_name) == 0); - iface->count_views = py_loaded_content_count_views_wrapper; - iface->get_view_name = py_loaded_content_get_view_name_wrapper; - iface->build_def_view = py_loaded_content_build_default_view_wrapper; - iface->build_view = py_loaded_content_build_view_wrapper; - iface->get_view_index = py_loaded_content_get_view_index_wrapper; + gtype = build_dynamic_type(G_TYPE_LOADED_CONTENT, type->tp_name, + (GClassInitFunc)py_loaded_content_init_gclass, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* unused = données non utilisées ici. * +* * +* Description : Initialise la classe générique des contenus chargés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_loaded_content_init_gclass(GLoadedContentClass *class, gpointer unused) +{ + class->get_content = py_loaded_content_get_content_wrapper; + class->get_content_class = py_loaded_content_get_content_class_wrapper; + + class->analyze = py_loaded_content_analyze_wrapper; + + class->describe = py_loaded_content_describe_wrapper; + +#ifdef INCLUDE_GTK_SUPPORT + class->count_views = py_loaded_content_count_views_wrapper; + class->get_view_name = py_loaded_content_get_view_name_wrapper; + class->build_def_view = py_loaded_content_build_default_view_wrapper; + class->build_view = py_loaded_content_build_view_wrapper; + class->get_view_index = py_loaded_content_get_view_index_wrapper; +#endif } @@ -234,31 +314,34 @@ static GBinContent *py_loaded_content_get_content_wrapper(const GLoadedContent * /****************************************************************************** * * * Paramètres : content = élément chargé à manipuler. * +* human = description humaine attendue ? * * * -* Description : Fournit le format associé à l'élément chargé. * +* Description : Décrit la nature du contenu reconnu pour l'élément chargé. * * * -* Retour : Format associé à l'élément chargé. * +* Retour : Classe de contenu associée à l'élément chargé. * * * * Remarques : - * * * ******************************************************************************/ -static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *content) +static char *py_loaded_content_get_content_class_wrapper(const GLoadedContent *content, bool human) { char *result; /* Contenu interne à renvoyer */ PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *hobj; /* Argument pour Python */ PyObject *pyret; /* Bilan de consultation */ int ret; /* Validité d'une conversion */ -#define LOADED_CONTENT_GET_FORMAT_NAME_WRAPPER PYTHON_WRAPPER_DEF \ +#define LOADED_CONTENT_GET_CONTENT_CLASS_WRAPPER PYTHON_WRAPPER_DEF \ ( \ - _get_format_name, "$self", \ + _get_content_class, "$self, human", \ METH_VARARGS, \ - "Abstract method used to provide the aw name of the format connected" \ - " to the loaded content.\n" \ + "Abstract method used to provide the nature of the loaded content.\n" \ "\n" \ - "The name associated to a loaded Elf binary is for instance 'elf'." \ + "The description associated to a loaded ARM Elf binary is for instance" \ + " 'elf-armv7', or 'Elf, ARMv7' for the human version." \ ) result = NULL; @@ -267,9 +350,16 @@ static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *con pyobj = pygobject_new(G_OBJECT(content)); - if (has_python_method(pyobj, "_get_format_name")) + if (has_python_method(pyobj, "_get_content_class")) { - pyret = run_python_method(pyobj, "_get_format_name", NULL); + args = PyTuple_New(1); + + hobj = (human ? Py_True : Py_False); + Py_INCREF(hobj); + + PyTuple_SetItem(args, 0, hobj); + + pyret = run_python_method(pyobj, "_get_content_class", args); if (pyret != NULL) { @@ -282,6 +372,8 @@ static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *con } + Py_DECREF(args); + } Py_DECREF(pyobj); @@ -456,6 +548,9 @@ static char *py_loaded_content_describe_wrapper(const GLoadedContent *content, b } +#ifdef INCLUDE_GTK_SUPPORT + + /****************************************************************************** * * * Paramètres : content = contenu chargé à consulter. * @@ -792,6 +887,9 @@ static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *con } +#endif + + /* ---------------------------------------------------------------------------------- */ /* CONNEXION AVEC L'API DE PYTHON */ @@ -876,7 +974,6 @@ static PyObject *py_loaded_content_analyze_and_wait(PyObject *self, PyObject *ar int connect; /* Connexion à la base ? */ int cache; /* Préparation de rendu ? */ int ret; /* Bilan de lecture des args. */ - PyThreadState *_save; /* Sauvegarde de contexte */ GLoadedContent *content; /* Version GLib de l'élément */ bool status; /* Bilan de l'opération */ @@ -911,12 +1008,8 @@ static PyObject *py_loaded_content_analyze_and_wait(PyObject *self, PyObject *ar content = G_LOADED_CONTENT(pygobject_get(self)); - Py_UNBLOCK_THREADS; - status = g_loaded_content_analyze_and_wait(content, connect, cache); - Py_BLOCK_THREADS; - result = status ? Py_True : Py_False; Py_INCREF(result); @@ -1030,6 +1123,9 @@ static PyObject *py_loaded_content_detect_obfuscators(PyObject *self, PyObject * } +#ifdef INCLUDE_GTK_SUPPORT + + /****************************************************************************** * * * Paramètres : self = contenu chargé à manipuler. * @@ -1271,6 +1367,9 @@ static PyObject *py_loaded_content_get_view_index(PyObject *self, PyObject *args } +#endif + + /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * @@ -1314,35 +1413,77 @@ static PyObject *py_loaded_content_get_content(PyObject *self, void *closure) * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * -* Description : Fournit le format associé à l'élément chargé. * +* Description : Décrit la nature du contenu reconnu pour l'élément chargé. * * * -* Retour : Format associé à l'élément chargé. * +* Retour : Classe de contenu associée à l'élément chargé. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_loaded_content_get_format_name(PyObject *self, void *closure) +static PyObject *py_loaded_content_get_content_class(PyObject *self, void *closure) { PyObject *result; /* Instance Python à retourner */ GLoadedContent *content; /* Version GLib de l'élément */ - GBinContent *bincnt; /* Contenu binaire associé */ + char *class; /* Nature du contenu binaire */ -#define LOADED_CONTENT_FORMAT_NAME_ATTRIB PYTHON_GET_DEF_FULL \ +#define LOADED_CONTENT_CONTENT_CLASS_ATTRIB PYTHON_GET_DEF_FULL \ ( \ - format_name, py_loaded_content, \ - "Raw name of the format connected to the loaded content.\n" \ + content_class, py_loaded_content, \ + "Nature of the loaded content.\n" \ "\n" \ - "The name associated to a loaded Elf binary is for instance 'elf'." \ + "The description associated to a loaded ARM Elf binary is for instance" \ + " 'elf-armv7'." \ ) content = G_LOADED_CONTENT(pygobject_get(self)); - bincnt = g_loaded_content_get_content(content); + class = g_loaded_content_get_content_class(content, false); - result = pygobject_new(G_OBJECT(bincnt)); + result = PyUnicode_FromString(class); - g_object_unref(G_OBJECT(bincnt)); + free(class); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Décrit la nature du contenu reconnu pour l'élément chargé. * +* * +* Retour : Classe de contenu associée à l'élément chargé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_loaded_content_get_content_class_for_human(PyObject *self, void *closure) +{ + PyObject *result; /* Instance Python à retourner */ + GLoadedContent *content; /* Version GLib de l'élément */ + char *class; /* Nature du contenu binaire */ + +#define LOADED_CONTENT_CONTENT_CLASS_FOR_HUMAN_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + content_class_for_human, py_loaded_content, \ + "Humain version of the nature of the loaded content.\n" \ + "\n" \ + "The description associated to a loaded ARM Elf binary is for instance" \ + " ''Elf, ARMv7'." \ +) + + content = G_LOADED_CONTENT(pygobject_get(self)); + + class = g_loaded_content_get_content_class(content, true); + + result = PyUnicode_FromString(class); + + free(class); return result; @@ -1365,29 +1506,34 @@ PyTypeObject *get_python_loaded_content_type(void) { static PyMethodDef py_loaded_content_methods[] = { LOADED_CONTENT_GET_CONTENT_WRAPPER, - LOADED_CONTENT_GET_FORMAT_NAME_WRAPPER, + LOADED_CONTENT_GET_CONTENT_CLASS_WRAPPER, LOADED_CONTENT_ANALYZE_WRAPPER, LOADED_CONTENT_DESCRIBE_WRAPPER, +#ifdef INCLUDE_GTK_SUPPORT LOADED_CONTENT_COUNT_VIEWS_WRAPPER, LOADED_CONTENT_GET_VIEW_NAME_WRAPPER, LOADED_CONTENT_BUILD_DEFAULT_VIEW_WRAPPER, LOADED_CONTENT_BUILD_VIEW_WRAPPER, LOADED_CONTENT_GET_VIEW_INDEX_WRAPPER, +#endif LOADED_CONTENT_ANALYZE_METHOD, LOADED_CONTENT_ANALYZE_AND_WAIT_METHOD, LOADED_CONTENT_DESCRIBE_METHOD, LOADED_CONTENT_DETECT_OBFUSCATORS_METHOD, +#ifdef INCLUDE_GTK_SUPPORT LOADED_CONTENT_COUNT_VIEWS_METHOD, LOADED_CONTENT_GET_VIEW_NAME_METHOD, LOADED_CONTENT_BUILD_DEFAULT_VIEW_METHOD, LOADED_CONTENT_BUILD_VIEW_METHOD, LOADED_CONTENT_GET_VIEW_INDEX_METHOD, +#endif { NULL } }; static PyGetSetDef py_loaded_content_getseters[] = { LOADED_CONTENT_CONTENT_ATTRIB, - LOADED_CONTENT_FORMAT_NAME_ATTRIB, + LOADED_CONTENT_CONTENT_CLASS_ATTRIB, + LOADED_CONTENT_CONTENT_CLASS_FOR_HUMAN_ATTRIB, { NULL } }; @@ -1396,14 +1542,16 @@ PyTypeObject *get_python_loaded_content_type(void) PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.analysis.LoadedContent", - .tp_basicsize = sizeof(PyObject), + .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, .tp_doc = LOADED_CONTENT_DOC, .tp_methods = py_loaded_content_methods, - .tp_getset = py_loaded_content_getseters + .tp_getset = py_loaded_content_getseters, + + .tp_new = py_loaded_content_new, }; @@ -1430,14 +1578,6 @@ bool ensure_python_loaded_content_is_registered(void) PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ - static GInterfaceInfo info = { /* Paramètres d'inscription */ - - .interface_init = (GInterfaceInitFunc)py_loaded_content_interface_init, - .interface_finalize = NULL, - .interface_data = NULL, - - }; - type = get_python_loaded_content_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) @@ -1446,10 +1586,12 @@ bool ensure_python_loaded_content_is_registered(void) dict = PyModule_GetDict(module); +#ifdef INCLUDE_GTK_SUPPORT if (!ensure_python_named_widget_is_registered()) return false; +#endif - if (!register_interface_for_pygobject(dict, G_TYPE_LOADED_CONTENT, type, &info)) + if (!register_class_for_pygobject(dict, G_TYPE_LOADED_CONTENT, type)) return false; } |