diff options
Diffstat (limited to 'plugins/pychrysalide/analysis')
97 files changed, 7816 insertions, 270 deletions
| diff --git a/plugins/pychrysalide/analysis/Makefile.am b/plugins/pychrysalide/analysis/Makefile.am index 66a2524..43e8ed2 100644 --- a/plugins/pychrysalide/analysis/Makefile.am +++ b/plugins/pychrysalide/analysis/Makefile.am @@ -1,28 +1,30 @@  noinst_LTLIBRARIES = libpychrysaanalysis.la -libpychrysaanalysis_la_SOURCES =		\ -	binary.h binary.c					\ -	block.h block.c						\ -	cattribs.h cattribs.c				\ -	constants.h constants.c				\ -	content.h content.c					\ -	loaded.h loaded.c					\ -	loading.h loading.c					\ -	module.h module.c					\ -	project.h project.c					\ -	routine.h routine.c					\ -	type.h type.c						\ +libpychrysaanalysis_la_SOURCES =			\ +	binary.h binary.c						\ +	block.h block.c							\ +	cattribs.h cattribs.c					\ +	constants.h constants.c					\ +	content.h content.c						\ +	loaded.h loaded.c						\ +	loading.h loading.c						\ +	module.h module.c						\ +	project.h project.c						\ +	routine.h routine.c						\ +	type.h type.c							\  	variable.h variable.c  libpychrysaanalysis_la_LIBADD =				\  	contents/libpychrysaanalysiscontents.la	\  	db/libpychrysaanalysisdb.la				\  	disass/libpychrysaanalysisdisass.la		\ +	scan/libpychrysaanalysisscan.la			\  	storage/libpychrysaanalysisstorage.la	\  	types/libpychrysaanalysistypes.la -libpychrysaanalysis_la_LDFLAGS =  +libpychrysaanalysis_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT  devdir = $(includedir)/chrysalide/$(subdir) @@ -30,9 +32,4 @@ devdir = $(includedir)/chrysalide/$(subdir)  dev_HEADERS = $(libpychrysaanalysis_la_SOURCES:%c=) -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - -SUBDIRS = contents db disass storage types +SUBDIRS = contents db disass scan storage types diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c index d8f01e5..6599ecc 100644 --- a/plugins/pychrysalide/analysis/binary.c +++ b/plugins/pychrysalide/analysis/binary.c @@ -562,7 +562,7 @@ bool ensure_python_loaded_binary_is_registered(void)          if (!ensure_python_loaded_content_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_LOADED_BINARY, type, get_python_loaded_content_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_LOADED_BINARY, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/block.c b/plugins/pychrysalide/analysis/block.c index 0b09eb7..7f74c2f 100644 --- a/plugins/pychrysalide/analysis/block.c +++ b/plugins/pychrysalide/analysis/block.c @@ -353,7 +353,7 @@ bool ensure_python_code_block_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_CODE_BLOCK, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_CODE_BLOCK, type))              return false;      } @@ -612,7 +612,7 @@ bool ensure_python_block_list_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_BLOCK_LIST, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_BLOCK_LIST, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/cattribs.c b/plugins/pychrysalide/analysis/cattribs.c index 895fed8..84a5e1d 100644 --- a/plugins/pychrysalide/analysis/cattribs.c +++ b/plugins/pychrysalide/analysis/cattribs.c @@ -294,7 +294,7 @@ bool ensure_python_content_attributes_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_ATTRIBUTES, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_ATTRIBUTES, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/content.c b/plugins/pychrysalide/analysis/content.c index f94e3f7..c30cdd8 100644 --- a/plugins/pychrysalide/analysis/content.c +++ b/plugins/pychrysalide/analysis/content.c @@ -40,6 +40,7 @@  #include "cattribs.h"  #include "constants.h" +#include "storage/serialize.h"  #include "../access.h"  #include "../helpers.h"  #include "../arch/vmpa.h" @@ -49,8 +50,13 @@  /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Procède à l'initialisation de l'interface de génération. */ -static void py_binary_content_interface_init(GBinContentIface *, gpointer *); +/* Initialise la classe générique des contenus de binaire. */ +static void py_binary_content_init_gclass(GBinContentClass *, gpointer); + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(binary_content, G_TYPE_BIN_CONTENT, py_binary_content_init_gclass); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_binary_content_init(PyObject *, PyObject *, PyObject *);  /* Fournit le nom associé au contenu binaire. */  static char *py_binary_content_describe_wrapper(const GBinContent *, bool); @@ -126,10 +132,10 @@ static PyObject *py_binary_content_get_data(PyObject *, void *);  /******************************************************************************  *                                                                             * -*  Paramètres  : iface  = interface GLib à initialiser.                       * -*                unused = adresse non utilisée ici.                           * +*  Paramètres  : class  = classe à initialiser.                               * +*                unused = données non utilisées ici.                          *  *                                                                             * -*  Description : Procède à l'initialisation de l'interface de génération.     * +*  Description : Initialise la classe générique des contenus de binaire.      *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -137,21 +143,45 @@ static PyObject *py_binary_content_get_data(PyObject *, void *);  *                                                                             *  ******************************************************************************/ -static void py_binary_content_interface_init(GBinContentIface *iface, gpointer *unused) +static void py_binary_content_init_gclass(GBinContentClass *class, gpointer unused)  { +    class->describe = py_binary_content_describe_wrapper; + +    class->read_raw = py_binary_content_read_raw_wrapper; +    class->read_u8 = py_binary_content_read_u8_wrapper; +    class->read_u16 = py_binary_content_read_u16_wrapper; +    class->read_u32 = py_binary_content_read_u32_wrapper; +    class->read_u64 = py_binary_content_read_u64_wrapper; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_binary_content_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ +  #define BINARY_CONTENT_DOC                                                  \ -    "The BinContent is an interface which handles access to a given binary" \ -    " content.\n"                                                           \ +    "A BinContent is an abstract object which handles access to a given"    \ +    " binary content.\n"                                                    \      "\n"                                                                    \      "All of its implementations are located in the"                         \      " pychrysalide.analysis.contents module. The main implemantation is"    \      " the pychrysalide.analysis.contents.FileContent class.\n"              \      "\n"                                                                    \ -    "A typical class declaration for a new implementation looks like:\n"    \ -    "\n"                                                                    \ -    "    class NewImplem(GObject.Object, BinContent):\n"                    \ -    "        ...\n"                                                         \ -    "\n"                                                                    \      "The following methods have to be defined for new implementations:\n"   \      "* pychrysalide.analysis.BinContent._describe();\n"                     \      "* pychrysalide.analysis.BinContent._read_raw();\n"                     \ @@ -161,13 +191,12 @@ static void py_binary_content_interface_init(GBinContentIface *iface, gpointer *      "* pychrysalide.analysis.BinContent._read_u32();\n"                     \      "* pychrysalide.analysis.BinContent._read_u64();\n" -    iface->describe = py_binary_content_describe_wrapper; +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; -    iface->read_raw = py_binary_content_read_raw_wrapper; -    iface->read_u8 = py_binary_content_read_u8_wrapper; -    iface->read_u16 = py_binary_content_read_u16_wrapper; -    iface->read_u32 = py_binary_content_read_u32_wrapper; -    iface->read_u64 = py_binary_content_read_u64_wrapper; +    return 0;  } @@ -1406,14 +1435,17 @@ PyTypeObject *get_python_binary_content_type(void)          PyVarObject_HEAD_INIT(NULL, 0)          .tp_name        = "pychrysalide.analysis.BinContent", -        .tp_basicsize   = sizeof(PyObject), +        .tp_basicsize   = sizeof(PyGObject),          .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,          .tp_doc         = BINARY_CONTENT_DOC,          .tp_methods     = py_binary_content_methods, -        .tp_getset      = py_binary_content_getseters +        .tp_getset      = py_binary_content_getseters, + +        .tp_init        = py_binary_content_init, +        .tp_new         = py_binary_content_new,      }; @@ -1440,23 +1472,18 @@ bool ensure_python_binary_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_binary_content_interface_init, -        .interface_finalize = NULL, -        .interface_data = NULL, - -    }; -      type = get_python_binary_content_type();      if (!PyType_HasFeature(type, Py_TPFLAGS_READY))      { +        if (!ensure_python_serializable_object_is_registered()) +            return false; +          module = get_access_to_python_module("pychrysalide.analysis");          dict = PyModule_GetDict(module); -        if (!register_interface_for_pygobject(dict, G_TYPE_BIN_CONTENT, type, &info)) +        if (!register_class_for_pygobject(dict, G_TYPE_BIN_CONTENT, type))              return false;          if (!define_analysis_content_constants(type)) diff --git a/plugins/pychrysalide/analysis/contents/Makefile.am b/plugins/pychrysalide/analysis/contents/Makefile.am index 5014d47..9238a58 100644 --- a/plugins/pychrysalide/analysis/contents/Makefile.am +++ b/plugins/pychrysalide/analysis/contents/Makefile.am @@ -1,22 +1,17 @@  noinst_LTLIBRARIES = libpychrysaanalysiscontents.la -libpychrysaanalysiscontents_la_SOURCES = \ -	encapsulated.h encapsulated.c		\ -	file.h file.c						\ -	memory.h memory.c					\ -	module.h module.c					\ +libpychrysaanalysiscontents_la_SOURCES = 	\ +	encapsulated.h encapsulated.c			\ +	file.h file.c							\ +	memory.h memory.c						\ +	module.h module.c						\  	restricted.h restricted.c -libpychrysaanalysiscontents_la_LDFLAGS =  +libpychrysaanalysiscontents_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT  devdir = $(includedir)/chrysalide/$(subdir)  dev_HEADERS = $(libpychrysaanalysiscontents_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/pychrysalide/analysis/contents/encapsulated.c b/plugins/pychrysalide/analysis/contents/encapsulated.c index 0e09f81..e9583e6 100644 --- a/plugins/pychrysalide/analysis/contents/encapsulated.c +++ b/plugins/pychrysalide/analysis/contents/encapsulated.c @@ -28,18 +28,20 @@  #include <pygobject.h> -#include <analysis/contents/encapsulated.h> +#include <i18n.h> +#include <analysis/contents/encapsulated-int.h>  #include "../content.h" -#include "../storage/serialize.h"  #include "../../access.h"  #include "../../helpers.h" -/* Crée un nouvel objet Python de type 'BinContent'. */ -static PyObject *py_encaps_content_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(encaps_content, G_TYPE_ENCAPS_CONTENT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_encaps_content_init(PyObject *, PyObject *, PyObject *);  /* Indique la base d'un contenu binaire encapsulé. */  static PyObject *py_encaps_content_get_base(PyObject *, void *); @@ -54,26 +56,25 @@ static PyObject *py_encaps_content_get_endpoint(PyObject *, void *);  /******************************************************************************  *                                                                             * -*  Paramètres  : type = type de l'objet à instancier.                         * +*  Paramètres  : self = objet à initialiser (théoriquement).                  *  *                args = arguments fournis à l'appel.                          *  *                kwds = arguments de type key=val fournis.                    *  *                                                                             * -*  Description : Crée un nouvel objet Python de type 'BinContent'.            * +*  Description : Initialise une instance sur la base du dérivé de GObject.    *  *                                                                             * -*  Retour      : Instance Python mise en place.                               * +*  Retour      : 0.                                                           *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_encaps_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_encaps_content_init(PyObject *self, PyObject *args, PyObject *kwds)  { -    PyObject *result;                       /* Instance à retourner        */      GBinContent *base;                      /* Base de l'extraction        */      const char *path;                       /* Chemin vers le contenu final*/      GBinContent *endpoint;                  /* Contenu accessible au final */      int ret;                                /* Bilan de lecture des args.  */ -    GBinContent *content;                   /* Version GLib du contenu     */ +    GEncapsContent *content;                /* Version GLib du contenu     */  #define ENCAPS_CONTENT_DOC                                                  \      "EncapsulatedContent gathers items relative to a binary encapsulated"   \ @@ -94,20 +95,30 @@ static PyObject *py_encaps_content_new(PyTypeObject *type, PyObject *args, PyObj      " pychrysalide.analysis.BinContent instances and the access path must"  \      " be provided as a string." +    /* Récupération des paramètres */ +      ret = PyArg_ParseTuple(args, "O&sO&",                             convert_to_binary_content, &base,                             &path,                             convert_to_binary_content, &endpoint); -    if (!ret) return NULL; +    if (!ret) return -1; -    content = g_encaps_content_new(base, path, endpoint); +    /* Initialisation d'un objet GLib */ -    result = pygobject_new(G_OBJECT(content)); +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; -    if (content != NULL) -        g_object_unref(content); +    /* Eléments de base */ -    return result; +    content = G_ENCAPS_CONTENT(pygobject_get(self)); + +    if (!g_encaps_content_create(content, base, path, endpoint)) +    { +        PyErr_SetString(PyExc_ValueError, _("Unable to create encapsulated content.")); +        return -1; +    } + +    return 0;  } @@ -276,7 +287,9 @@ PyTypeObject *get_python_encaps_content_type(void)          .tp_methods     = py_encaps_content_methods,          .tp_getset      = py_encaps_content_getseters, -        .tp_new         = py_encaps_content_new + +        .tp_init        = py_encaps_content_init, +        .tp_new         = py_encaps_content_new,      }; @@ -311,13 +324,10 @@ bool ensure_python_encaps_content_is_registered(void)          dict = PyModule_GetDict(module); -        if (!ensure_python_serializable_object_is_registered()) -            return false; -          if (!ensure_python_binary_content_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_ENCAPS_CONTENT, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_ENCAPS_CONTENT, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/contents/file.c b/plugins/pychrysalide/analysis/contents/file.c index 4786cdb..5bef069 100644 --- a/plugins/pychrysalide/analysis/contents/file.c +++ b/plugins/pychrysalide/analysis/contents/file.c @@ -28,18 +28,20 @@  #include <pygobject.h> -#include <analysis/contents/file.h> +#include <i18n.h> +#include <analysis/contents/file-int.h>  #include "memory.h" -#include "../storage/serialize.h"  #include "../../access.h"  #include "../../helpers.h" -/* Crée un nouvel objet Python de type 'BinContent'. */ -static PyObject *py_file_content_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(file_content, G_TYPE_FILE_CONTENT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_file_content_init(PyObject *, PyObject *, PyObject *);  /* Fournit le nom de fichier associé au contenu binaire. */  static PyObject *py_file_content_get_filename(PyObject *, void *); @@ -48,24 +50,23 @@ static PyObject *py_file_content_get_filename(PyObject *, void *);  /******************************************************************************  *                                                                             * -*  Paramètres  : type = type de l'objet à instancier.                         * +*  Paramètres  : self = objet à initialiser (théoriquement).                  *  *                args = arguments fournis à l'appel.                          *  *                kwds = arguments de type key=val fournis.                    *  *                                                                             * -*  Description : Crée un nouvel objet Python de type 'BinContent'.            * +*  Description : Initialise une instance sur la base du dérivé de GObject.    *  *                                                                             * -*  Retour      : Instance Python mise en place.                               * +*  Retour      : 0.                                                           *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_file_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_file_content_init(PyObject *self, PyObject *args, PyObject *kwds)  { -    PyObject *result;                       /* Instance à retourner        */      const char *filename;                   /* Nom du fichier à charger    */      int ret;                                /* Bilan de lecture des args.  */ -    GBinContent *content;                   /* Version GLib du contenu     */ +    GFileContent *content;                  /* Version GLib du contenu     */  #define FILE_CONTENT_DOC                                                    \      "FileContent handles binary content loaded from a file.\n"              \ @@ -76,17 +77,27 @@ static PyObject *py_file_content_new(PyTypeObject *type, PyObject *args, PyObjec      "\n"                                                                    \      "Where filename is a path to an existing file." +    /* Récupération des paramètres */ +      ret = PyArg_ParseTuple(args, "s", &filename); -    if (!ret) return NULL; +    if (!ret) return -1; -    content = g_file_content_new(filename); +    /* Initialisation d'un objet GLib */ -    result = pygobject_new(G_OBJECT(content)); +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; -    if (content != NULL) -        g_object_unref(content); +    /* Eléments de base */ -    return result; +    content = G_FILE_CONTENT(pygobject_get(self)); + +    if (!g_file_content_create(content, filename)) +    { +        PyErr_SetString(PyExc_ValueError, _("Unable to create file content.")); +        return -1; +    } + +    return 0;  } @@ -163,7 +174,9 @@ PyTypeObject *get_python_file_content_type(void)          .tp_methods     = py_file_content_methods,          .tp_getset      = py_file_content_getseters, -        .tp_new         = py_file_content_new + +        .tp_init        = py_file_content_init, +        .tp_new         = py_file_content_new,      }; @@ -201,10 +214,7 @@ bool ensure_python_file_content_is_registered(void)          if (!ensure_python_memory_content_is_registered())              return false; -        if (!ensure_python_serializable_object_is_registered()) -            return false; - -        if (!register_class_for_pygobject(dict, G_TYPE_FILE_CONTENT, type, get_python_memory_content_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_FILE_CONTENT, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/contents/memory.c b/plugins/pychrysalide/analysis/contents/memory.c index 4782445..7464779 100644 --- a/plugins/pychrysalide/analysis/contents/memory.c +++ b/plugins/pychrysalide/analysis/contents/memory.c @@ -28,42 +28,43 @@  #include <pygobject.h> -#include <analysis/contents/memory.h> +#include <i18n.h> +#include <analysis/contents/memory-int.h>  #include "../content.h" -#include "../storage/serialize.h"  #include "../../access.h"  #include "../../helpers.h" -/* Crée un nouvel objet Python de type 'BinContent'. */ -static PyObject *py_memory_content_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(memory_content, G_TYPE_MEMORY_CONTENT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_memory_content_init(PyObject *, PyObject *, PyObject *);  /******************************************************************************  *                                                                             * -*  Paramètres  : type = type de l'objet à instancier.                         * +*  Paramètres  : self = objet à initialiser (théoriquement).                  *  *                args = arguments fournis à l'appel.                          *  *                kwds = arguments de type key=val fournis.                    *  *                                                                             * -*  Description : Crée un nouvel objet Python de type 'BinContent'.            * +*  Description : Initialise une instance sur la base du dérivé de GObject.    *  *                                                                             * -*  Retour      : Instance Python mise en place.                               * +*  Retour      : 0.                                                           *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_memory_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_memory_content_init(PyObject *self, PyObject *args, PyObject *kwds)  { -    PyObject *result;                       /* Instance à retourner        */      const char *data;                       /* Tampon interne de Python    */ -    int length;                             /* Taille utilisé de ce tampon */ +    Py_ssize_t length;                      /* Taille utilisé de ce tampon */      int ret;                                /* Bilan de lecture des args.  */ -    GBinContent *content;                   /* Version GLib du contenu     */ +    GMemoryContent *content;                /* Version GLib du contenu     */  #define MEMORY_CONTENT_DOC                                                  \      "MemoryContent builds a binary content from memory data only."          \ @@ -76,22 +77,32 @@ static PyObject *py_memory_content_new(PyTypeObject *type, PyObject *args, PyObj      "Where data is provided as string or read-only bytes-like object."      \      " The string may contain embedded null bytes." +    /* Récupération des paramètres */ +      /**       * La taille doit être de type 'int' et non 'Py_ssize_t', sinon les 32 bits       * de poids fort ne sont pas initialisés !       */      ret = PyArg_ParseTuple(args, "s#", &data, &length); -    if (!ret) return NULL; +    if (!ret) return -1; + +    /* Initialisation d'un objet GLib */ -    content = g_memory_content_new((const bin_t *)data, length); +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; -    result = pygobject_new(G_OBJECT(content)); +    /* Eléments de base */ -    if (content != NULL) -        g_object_unref(content); +    content = G_MEMORY_CONTENT(pygobject_get(self)); -    return result; +    if (!g_memory_content_create(content, (const bin_t *)data, length)) +    { +        PyErr_SetString(PyExc_ValueError, _("Unable to create memory content.")); +        return -1; +    } + +    return 0;  } @@ -131,7 +142,9 @@ PyTypeObject *get_python_memory_content_type(void)          .tp_methods     = py_memory_content_methods,          .tp_getset      = py_memory_content_getseters, -        .tp_new         = py_memory_content_new + +        .tp_init        = py_memory_content_init, +        .tp_new         = py_memory_content_new,      }; @@ -166,13 +179,10 @@ bool ensure_python_memory_content_is_registered(void)          dict = PyModule_GetDict(module); -        if (!ensure_python_serializable_object_is_registered()) -            return false; -          if (!ensure_python_binary_content_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_MEMORY_CONTENT, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_MEMORY_CONTENT, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/contents/restricted.c b/plugins/pychrysalide/analysis/contents/restricted.c index 47df8c5..4521578 100644 --- a/plugins/pychrysalide/analysis/contents/restricted.c +++ b/plugins/pychrysalide/analysis/contents/restricted.c @@ -31,19 +31,21 @@  #include <i18n.h> -#include <analysis/contents/restricted.h> +#include <i18n.h> +#include <analysis/contents/restricted-int.h>  #include "../content.h" -#include "../storage/serialize.h"  #include "../../access.h"  #include "../../helpers.h"  #include "../../arch/vmpa.h" -/* Crée un nouvel objet Python de type 'BinContent'. */ -static PyObject *py_restricted_content_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(restricted_content, G_TYPE_RESTRICTED_CONTENT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_restricted_content_init(PyObject *, PyObject *, PyObject *);  /* Indique l'espace de restriction appliqué à un contenu. */  static PyObject *py_restricted_content_get_range(PyObject *, void *); @@ -52,25 +54,24 @@ static PyObject *py_restricted_content_get_range(PyObject *, void *);  /******************************************************************************  *                                                                             * -*  Paramètres  : type = type de l'objet à instancier.                         * +*  Paramètres  : self = objet à initialiser (théoriquement).                  *  *                args = arguments fournis à l'appel.                          *  *                kwds = arguments de type key=val fournis.                    *  *                                                                             * -*  Description : Crée un nouvel objet Python de type 'BinContent'.            * +*  Description : Initialise une instance sur la base du dérivé de GObject.    *  *                                                                             * -*  Retour      : Instance Python mise en place.                               * +*  Retour      : 0.                                                           *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_restricted_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_restricted_content_init(PyObject *self, PyObject *args, PyObject *kwds)  { -    PyObject *result;                       /* Instance à retourner        */ -    GBinContent *content;                   /* Instance GLib correspondante*/ +    GBinContent *internal;                  /* Instance GLib correspondante*/      mrange_t range;                         /* Restriction à appliquer     */      int ret;                                /* Bilan de lecture des args.  */ -    GBinContent *restricted;                /* Création GLib à transmettre */ +    GRestrictedContent *content;            /* Version GLib du contenu     */  #define RESTRICTED_CONTENT_DOC                                                  \      "RestrictedContent restricts access to a given area for a binary content."  \ @@ -82,14 +83,27 @@ static PyObject *py_restricted_content_new(PyTypeObject *type, PyObject *args, P      "Where content is a pychrysalide.analysis.BinContent instance and range"    \      " a Python object which can be converted into pychrysalide.arch.mrange." -    ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &content, convert_any_to_mrange, &range); -    if (!ret) return NULL; +    /* Récupération des paramètres */ -    restricted = g_restricted_content_new(content, &range); +    ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &internal, convert_any_to_mrange, &range); +    if (!ret) return -1; -    result = pygobject_new(G_OBJECT(restricted)); +    /* Initialisation d'un objet GLib */ -    return result; +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    /* Eléments de base */ + +    content = G_RESTRICTED_CONTENT(pygobject_get(self)); + +    if (!g_restricted_content_create(content, internal, &range)) +    { +        PyErr_SetString(PyExc_ValueError, _("Unable to create restricted content.")); +        return -1; +    } + +    return 0;  } @@ -166,7 +180,9 @@ PyTypeObject *get_python_restricted_content_type(void)          .tp_methods     = py_restricted_content_methods,          .tp_getset      = py_restricted_content_getseters, -        .tp_new         = py_restricted_content_new + +        .tp_init        = py_restricted_content_init, +        .tp_new         = py_restricted_content_new,      }; @@ -201,13 +217,10 @@ bool ensure_python_restricted_content_is_registered(void)          dict = PyModule_GetDict(module); -        if (!ensure_python_serializable_object_is_registered()) -            return false; -          if (!ensure_python_binary_content_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_RESTRICTED_CONTENT, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_RESTRICTED_CONTENT, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/db/Makefile.am b/plugins/pychrysalide/analysis/db/Makefile.am index 94d4c43..a0dcc0d 100644 --- a/plugins/pychrysalide/analysis/db/Makefile.am +++ b/plugins/pychrysalide/analysis/db/Makefile.am @@ -1,21 +1,22 @@  noinst_LTLIBRARIES = libpychrysaanalysisdb.la -libpychrysaanalysisdb_la_SOURCES =		\ -	admin.h admin.c						\ -	analyst.h analyst.c					\ -	certs.h certs.c						\ -	client.h client.c					\ -	collection.h collection.c			\ -	constants.h constants.c				\ -	item.h item.c						\ -	module.h module.c					\ +libpychrysaanalysisdb_la_SOURCES =			\ +	admin.h admin.c							\ +	analyst.h analyst.c						\ +	certs.h certs.c							\ +	client.h client.c						\ +	collection.h collection.c				\ +	constants.h constants.c					\ +	item.h item.c							\ +	module.h module.c						\  	server.h server.c -libpychrysaanalysisdb_la_LIBADD = 		\ +libpychrysaanalysisdb_la_LIBADD = 			\  	items/libpychrysaanalysisdbitems.la -libpychrysaanalysisdb_la_LDFLAGS =  +libpychrysaanalysisdb_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT  devdir = $(includedir)/chrysalide/$(subdir) @@ -23,9 +24,4 @@ devdir = $(includedir)/chrysalide/$(subdir)  dev_HEADERS = $(libpychrysaanalysisdb_la_SOURCES:%c=) -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -  SUBDIRS = items diff --git a/plugins/pychrysalide/analysis/db/admin.c b/plugins/pychrysalide/analysis/db/admin.c index a4694e6..10a150e 100644 --- a/plugins/pychrysalide/analysis/db/admin.c +++ b/plugins/pychrysalide/analysis/db/admin.c @@ -237,7 +237,7 @@ PyTypeObject *get_python_admin_client_type(void)  *                                                                             *  *  Paramètres  : module = module dont la définition est à compléter.          *  *                                                                             * -*  Description : Prend en charge l'objet 'pychrysalide....db.AdminClient'.  * +*  Description : Prend en charge l'objet 'pychrysalide....db.AdminClient'.    *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        *  *                                                                             * @@ -255,14 +255,14 @@ bool ensure_python_admin_client_is_registered(void)      if (!PyType_HasFeature(type, Py_TPFLAGS_READY))      { -        if (!ensure_python_hub_client_is_registered()) -            return false; -          module = get_access_to_python_module("pychrysalide.analysis.db");          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_ADMIN_CLIENT, type, get_python_hub_client_type())) +        if (!ensure_python_hub_client_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_ADMIN_CLIENT, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/db/analyst.c b/plugins/pychrysalide/analysis/db/analyst.c index 3cb77d1..f2860ed 100644 --- a/plugins/pychrysalide/analysis/db/analyst.c +++ b/plugins/pychrysalide/analysis/db/analyst.c @@ -900,14 +900,14 @@ bool ensure_python_analyst_client_is_registered(void)      if (!PyType_HasFeature(type, Py_TPFLAGS_READY))      { -        if (!ensure_python_hub_client_is_registered()) -            return false; -          module = get_access_to_python_module("pychrysalide.analysis.db");          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_ANALYST_CLIENT, type, get_python_hub_client_type())) +        if (!ensure_python_hub_client_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_ANALYST_CLIENT, type))              return false;          if (!define_loading_status_hint_constants(type)) diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c index 0cd9704..7ef658e 100644 --- a/plugins/pychrysalide/analysis/db/client.c +++ b/plugins/pychrysalide/analysis/db/client.c @@ -235,7 +235,7 @@ bool ensure_python_hub_client_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_HUB_CLIENT, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_HUB_CLIENT, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/db/collection.c b/plugins/pychrysalide/analysis/db/collection.c index ca4151c..5970d15 100644 --- a/plugins/pychrysalide/analysis/db/collection.c +++ b/plugins/pychrysalide/analysis/db/collection.c @@ -165,7 +165,7 @@ bool ensure_python_db_collection_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_DB_COLLECTION, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_DB_COLLECTION, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/db/item.c b/plugins/pychrysalide/analysis/db/item.c index 836f902..cc9bdf4 100644 --- a/plugins/pychrysalide/analysis/db/item.c +++ b/plugins/pychrysalide/analysis/db/item.c @@ -369,7 +369,7 @@ bool ensure_python_db_item_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_DB_ITEM, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_DB_ITEM, type))              return false;          if (!define_db_protocol_constants(type)) diff --git a/plugins/pychrysalide/analysis/db/items/Makefile.am b/plugins/pychrysalide/analysis/db/items/Makefile.am index 2bac8ba..201aed7 100644 --- a/plugins/pychrysalide/analysis/db/items/Makefile.am +++ b/plugins/pychrysalide/analysis/db/items/Makefile.am @@ -1,22 +1,17 @@  noinst_LTLIBRARIES = libpychrysaanalysisdbitems.la -libpychrysaanalysisdbitems_la_SOURCES =	\ -	bookmark.h bookmark.c				\ -	comment.h comment.c					\ -	constants.h constants.c				\ -	module.h module.c					\ +libpychrysaanalysisdbitems_la_SOURCES =		\ +	bookmark.h bookmark.c					\ +	comment.h comment.c						\ +	constants.h constants.c					\ +	module.h module.c						\  	switcher.h switcher.c -libpychrysaanalysisdbitems_la_LDFLAGS =  +libpychrysaanalysisdbitems_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT  devdir = $(includedir)/chrysalide/$(subdir)  dev_HEADERS = $(libpychrysaanalysisdbitems_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/pychrysalide/analysis/db/items/bookmark.c b/plugins/pychrysalide/analysis/db/items/bookmark.c index af649e3..d2bc0f0 100644 --- a/plugins/pychrysalide/analysis/db/items/bookmark.c +++ b/plugins/pychrysalide/analysis/db/items/bookmark.c @@ -108,7 +108,7 @@ static PyObject *py_db_bookmark_new(PyTypeObject *type, PyObject *args, PyObject      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -366,7 +366,7 @@ bool ensure_python_db_bookmark_is_registered(void)          if (!ensure_python_db_item_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_DB_BOOKMARK, type, get_python_db_item_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_DB_BOOKMARK, type))              return false;      } @@ -473,7 +473,7 @@ static PyObject *py_bookmark_collection_new(PyTypeObject *type, PyObject *args,      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -570,7 +570,7 @@ bool ensure_python_bookmark_collection_is_registered(void)          if (!ensure_python_db_collection_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_BM_COLLECTION, type, get_python_db_collection_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_BM_COLLECTION, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/db/items/comment.c b/plugins/pychrysalide/analysis/db/items/comment.c index 78d4902..1358f1d 100644 --- a/plugins/pychrysalide/analysis/db/items/comment.c +++ b/plugins/pychrysalide/analysis/db/items/comment.c @@ -117,7 +117,7 @@ static PyObject *py_db_comment_new(PyTypeObject *type, PyObject *args, PyObject      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -464,7 +464,7 @@ bool ensure_python_db_comment_is_registered(void)          if (!ensure_python_db_item_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_DB_COMMENT, type, get_python_db_item_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_DB_COMMENT, type))              return false;          if (!define_db_comment_constants(type)) @@ -574,7 +574,7 @@ static PyObject *py_comment_collection_new(PyTypeObject *type, PyObject *args, P      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -671,7 +671,7 @@ bool ensure_python_comment_collection_is_registered(void)          if (!ensure_python_db_collection_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_COMMENT_COLLECTION, type, get_python_db_collection_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_COMMENT_COLLECTION, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/db/items/switcher.c b/plugins/pychrysalide/analysis/db/items/switcher.c index 6ac5cdf..5766fe1 100644 --- a/plugins/pychrysalide/analysis/db/items/switcher.c +++ b/plugins/pychrysalide/analysis/db/items/switcher.c @@ -114,7 +114,7 @@ static PyObject *py_db_switcher_new(PyTypeObject *type, PyObject *args, PyObject      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -398,7 +398,7 @@ bool ensure_python_db_switcher_is_registered(void)          if (!ensure_python_db_item_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_DB_SWITCHER, type, get_python_db_item_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_DB_SWITCHER, type))              return false;      } @@ -506,7 +506,7 @@ static PyObject *py_switcher_collection_new(PyTypeObject *type, PyObject *args,      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -603,7 +603,7 @@ bool ensure_python_switcher_collection_is_registered(void)          if (!ensure_python_db_collection_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_SWITCHER_COLLECTION, type, get_python_db_collection_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_SWITCHER_COLLECTION, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/db/server.c b/plugins/pychrysalide/analysis/db/server.c index 9e4ee61..dae7b29 100644 --- a/plugins/pychrysalide/analysis/db/server.c +++ b/plugins/pychrysalide/analysis/db/server.c @@ -274,7 +274,7 @@ bool ensure_python_hub_server_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_HUB_SERVER, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_HUB_SERVER, type))              return false;          if (!define_hub_server_constants(type)) diff --git a/plugins/pychrysalide/analysis/disass/Makefile.am b/plugins/pychrysalide/analysis/disass/Makefile.am index 1aa34ea..0daa930 100644 --- a/plugins/pychrysalide/analysis/disass/Makefile.am +++ b/plugins/pychrysalide/analysis/disass/Makefile.am @@ -1,21 +1,14 @@  noinst_LTLIBRARIES = libpychrysaanalysisdisass.la -libpychrysaanalysisdisass_la_SOURCES =	\ -	block.h block.c						\ +libpychrysaanalysisdisass_la_SOURCES =		\ +	block.h block.c							\  	module.h module.c -libpychrysaanalysisdisass_la_LDFLAGS =  +libpychrysaanalysisdisass_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT  devdir = $(includedir)/chrysalide/$(subdir)  dev_HEADERS = $(libpychrysaanalysisdisass_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - -SUBDIRS =  diff --git a/plugins/pychrysalide/analysis/disass/block.c b/plugins/pychrysalide/analysis/disass/block.c index 38e65a1..d82e3e2 100644 --- a/plugins/pychrysalide/analysis/disass/block.c +++ b/plugins/pychrysalide/analysis/disass/block.c @@ -159,7 +159,10 @@ bool ensure_python_basic_block_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_BASIC_BLOCK, type, get_python_code_block_type())) +        if (!ensure_python_code_block_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_BASIC_BLOCK, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/loaded.c b/plugins/pychrysalide/analysis/loaded.c index c8674a5..a2bf13f 100644 --- a/plugins/pychrysalide/analysis/loaded.c +++ b/plugins/pychrysalide/analysis/loaded.c @@ -66,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 *); @@ -81,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 ------------------------- */ @@ -98,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 *); @@ -110,6 +116,8 @@ 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 *); @@ -191,7 +199,7 @@ static PyObject *py_loaded_content_new(PyTypeObject *type, PyObject *args, PyObj      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -234,11 +242,13 @@ static void py_loaded_content_init_gclass(GLoadedContentClass *class, gpointer u      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  } @@ -538,6 +548,9 @@ static char *py_loaded_content_describe_wrapper(const GLoadedContent *content, b  } +#ifdef INCLUDE_GTK_SUPPORT + +  /******************************************************************************  *                                                                             *  *  Paramètres  : content = contenu chargé à consulter.                        * @@ -874,6 +887,9 @@ static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *con  } +#endif + +  /* ---------------------------------------------------------------------------------- */  /*                           CONNEXION AVEC L'API DE PYTHON                           */ @@ -1107,6 +1123,9 @@ static PyObject *py_loaded_content_detect_obfuscators(PyObject *self, PyObject *  } +#ifdef INCLUDE_GTK_SUPPORT + +  /******************************************************************************  *                                                                             *  *  Paramètres  : self = contenu chargé à manipuler.                           * @@ -1348,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.                 * @@ -1487,20 +1509,24 @@ PyTypeObject *get_python_loaded_content_type(void)          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 }      }; @@ -1560,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_class_for_pygobject(dict, G_TYPE_LOADED_CONTENT, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_LOADED_CONTENT, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/loading.c b/plugins/pychrysalide/analysis/loading.c index dea4e31..8a60d8a 100644 --- a/plugins/pychrysalide/analysis/loading.c +++ b/plugins/pychrysalide/analysis/loading.c @@ -168,7 +168,7 @@ bool ensure_python_content_explorer_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_EXPLORER, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_EXPLORER, type))              return false;      } @@ -294,7 +294,7 @@ bool ensure_python_content_resolver_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_RESOLVER, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_RESOLVER, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/module.c b/plugins/pychrysalide/analysis/module.c index 9632956..6b8e441 100644 --- a/plugins/pychrysalide/analysis/module.c +++ b/plugins/pychrysalide/analysis/module.c @@ -41,6 +41,7 @@  #include "contents/module.h"  #include "db/module.h"  #include "disass/module.h" +#include "scan/module.h"  #include "storage/module.h"  #include "types/module.h"  #include "../helpers.h" @@ -86,6 +87,7 @@ bool add_analysis_module(PyObject *super)      if (result) result = add_analysis_contents_module(module);      if (result) result = add_analysis_db_module(module);      if (result) result = add_analysis_disass_module(module); +    if (result) result = add_analysis_scan_module(module);      if (result) result = add_analysis_storage_module(module);      if (result) result = add_analysis_types_module(module); @@ -131,6 +133,7 @@ bool populate_analysis_module(void)      if (result) result = populate_analysis_contents_module();      if (result) result = populate_analysis_db_module();      if (result) result = populate_analysis_disass_module(); +    if (result) result = populate_analysis_scan_module();      if (result) result = populate_analysis_storage_module();      if (result) result = populate_analysis_types_module(); diff --git a/plugins/pychrysalide/analysis/project.c b/plugins/pychrysalide/analysis/project.c index e66119c..b00259a 100644 --- a/plugins/pychrysalide/analysis/project.c +++ b/plugins/pychrysalide/analysis/project.c @@ -402,7 +402,7 @@ bool ensure_python_study_project_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_STUDY_PROJECT, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_STUDY_PROJECT, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/routine.c b/plugins/pychrysalide/analysis/routine.c index e33ca90..535ba84 100644 --- a/plugins/pychrysalide/analysis/routine.c +++ b/plugins/pychrysalide/analysis/routine.c @@ -757,7 +757,7 @@ bool ensure_python_binary_routine_is_registered(void)          if (!ensure_python_binary_symbol_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_BIN_ROUTINE, type, get_python_binary_symbol_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_BIN_ROUTINE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/scan/Makefile.am b/plugins/pychrysalide/analysis/scan/Makefile.am new file mode 100644 index 0000000..8c9fb77 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/Makefile.am @@ -0,0 +1,28 @@ + +noinst_LTLIBRARIES = libpychrysaanalysisscan.la + +libpychrysaanalysisscan_la_SOURCES =		\ +	constants.h constants.c					\ +	context.h context.c						\ +	core.h core.c							\ +	expr.h expr.c							\ +	item.h item.c							\ +	module.h module.c						\ +	options.h options.c						\ +	scanner.h scanner.c						\ +	space.h space.c + +libpychrysaanalysisscan_la_LIBADD =			\ +	exprs/libpychrysaanalysisscanexprs.la	\ +	patterns/libpychrysaanalysisscanpatterns.la + +libpychrysaanalysisscan_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libpychrysaanalysisscan_la_SOURCES:%c=) + + +SUBDIRS = exprs patterns diff --git a/plugins/pychrysalide/analysis/scan/constants.c b/plugins/pychrysalide/analysis/scan/constants.c new file mode 100644 index 0000000..d030df2 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/constants.c @@ -0,0 +1,128 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.c - ajout des constantes de base pour les types + * + * Copyright (C) 2020 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "constants.h" + + +#include <analysis/scan/expr.h> + + +#include "../../helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : type = type dont le dictionnaire est à compléter.            * +*                                                                             * +*  Description : Définit les constantes relatives aux expressions de scan.    * +*                                                                             * +*  Retour      : true en cas de succès de l'opération, false sinon.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool define_expression_value_type_constants(PyTypeObject *type) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *values;                       /* Groupe de valeurs à établir */ + +    values = PyDict_New(); + +    result = add_const_to_group(values, "PENDING", SRS_PENDING); +    if (result) result = add_const_to_group(values, "REDUCED", SRS_REDUCED); +    if (result) result = add_const_to_group(values, "WAIT_FOR_SCAN", SRS_WAIT_FOR_SCAN); +    if (result) result = add_const_to_group(values, "UNRESOLVABLE", SRS_UNRESOLVABLE); + +    if (!result) +    { +        Py_DECREF(values); +        goto exit; +    } + +    result = attach_constants_group_to_type(type, false, "ScanReductionState", values, +                                            "State of a scanexpression during the reduction process."); + + exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en constante ScanReductionState.          * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_reduction_state(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ +    unsigned long value;                    /* Valeur transcrite           */ + +    result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ScanReductionState"); +            break; + +        case 1: +            value = PyLong_AsUnsignedLong(arg); + +            if (value > SRS_UNRESOLVABLE) +            { +                PyErr_SetString(PyExc_TypeError, "invalid value for ScanReductionState"); +                result = 0; +            } + +            else +                *((ScanReductionState *)dst) = value; + +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/constants.h b/plugins/pychrysalide/analysis/scan/constants.h new file mode 100644 index 0000000..aa6c571 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/constants.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.h - prototypes pour l'ajout des constantes de base pour les types + * + * Copyright (C) 2020 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Définit les constantes relatives aux expressions de scan. */ +bool define_expression_value_type_constants(PyTypeObject *); + +/* Tente de convertir en constante ScanReductionState. */ +int convert_to_scan_reduction_state(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H */ diff --git a/plugins/pychrysalide/analysis/scan/context.c b/plugins/pychrysalide/analysis/scan/context.c new file mode 100644 index 0000000..9becaf7 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/context.c @@ -0,0 +1,432 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.c - équivalent Python du fichier "analysis/scan/context.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "context.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/content.h> +#include <analysis/scan/context-int.h> +#include <analysis/scan/expr.h> + +#include "expr.h" +#include "../content.h"  +#include "../../access.h" +#include "../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_context, G_TYPE_SCAN_CONTEXT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_context_init(PyObject *, PyObject *, PyObject *); + +/* Note que la phase d'analyse de contenu est terminée. */ +static PyObject *py_scan_context_mark_scan_as_done(PyObject *, PyObject *); + +/* Indique si une correspondance globale a pu être établie. */ +static PyObject *py_scan_context_has_match_for_rule(PyObject *, PyObject *); + +/* Fournit une référence au contenu principal analysé. */ +static PyObject *py_scan_context_get_content(PyObject *, void *); + +/* Définit le contenu principal à analyser. */ +static int py_scan_context_set_content(PyObject *, PyObject *, void *); + +/* Indique si la phase d'analyse de contenu est terminée. */ +static PyObject *py_scan_context_is_scan_done(PyObject *, void *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_context_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_CONTEXT_DOC                                            \ +    "A ScanContext object tracks results of a run analysis process" \ +    " against binary contents.\n"                                   \ +    "\n"                                                            \ +    "Instances can be created using the following constructor:\n"   \ +    "\n"                                                            \ +    "    ScanContext()" + +    /* Récupération des paramètres */ + +    ret = PyArg_ParseTuple(args, ""); +    if (!ret) return -1; + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = classe représentant un format.                        * +*                args = arguments fournis à l'appel.                          * +*                                                                             * +*  Description : Note que la phase d'analyse de contenu est terminée.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_context_mark_scan_as_done(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Contexte de suivi à renvoyer*/ +    GScanContext *context;                  /* Contexte de suivi d'analyse */ + +#define SCAN_CONTEXT_MARK_SCAN_AS_DONE_METHOD PYTHON_METHOD_DEF \ +(                                                               \ +    mark_scan_as_done, "$self",                                 \ +    METH_NOARGS, py_scan_context,                               \ +    "Note that the analysis operations are finished."           \ +) + +    context = G_SCAN_CONTEXT(pygobject_get(self)); + +    g_scan_context_mark_scan_as_done(context); + +    result = Py_None; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = classe représentant un format.                        * +*                args = arguments fournis à l'appel.                          * +*                                                                             * +*  Description : Indique si une correspondance globale a pu être établie.     * +*                                                                             * +*  Retour      : Bilan final d'une analyse (False par défaut).                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_context_has_match_for_rule(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Contexte de suivi à renvoyer*/ +    const char *name;                       /* Désignation de règle        */ +    int ret;                                /* Bilan de lecture des args.  */ +    GScanContext *context;                  /* Contexte de suivi d'analyse */ +    bool matched;                           /* Bilan d'analyse à renvoyer  */ + +#define SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD PYTHON_METHOD_DEF    \ +(                                                                   \ +    has_match_for_rule, "$self, name, /",                           \ +    METH_VARARGS, py_scan_context,                                  \ +    "Provide the match status for a given scan rule.\n"             \ +    "\n"                                                            \ +    "The *name* argument points to the registered rule to query.\n" \ +    "\n"                                                            \ +    "The method returns the scan final status as a boolean: *True*" \ +    " in case of match, *False* otherwise."                         \ +) + +    ret = PyArg_ParseTuple(args, "s", &name); +    if (!ret) return NULL; + +    context = G_SCAN_CONTEXT(pygobject_get(self)); + +    matched = g_scan_context_has_match_for_rule(context, name); + +    result = matched ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = classe représentant une routine binaire.           * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Fournit une référence au contenu principal analysé.          * +*                                                                             * +*  Retour      : Content binaire associé au context.                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_context_get_content(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Eléments à retourner        */ +    GScanContext *context;                  /* Version native              */ +    GBinContent *content;                   /* Contenu binaire à référencer*/ + +#define SCAN_CONTEXT_CONTENT_ATTRIB PYTHON_GETSET_DEF_FULL  \ +(                                                           \ +    content, py_scan_context,                               \ +    "Link to the scanned binary content.\n"                 \ +    "\n"                                                    \ +    "The result is a pychrysalide.analysis.BinContent for"  \ +    " fully initialized context."                           \ +) + +    context = G_SCAN_CONTEXT(pygobject_get(self)); +    content = g_scan_context_get_content(context); + +    result = pygobject_new(G_OBJECT(content)); + +    g_object_unref(G_OBJECT(content)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                value   = valeur fournie à intégrer ou prendre en compte.    * +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Définit le contenu principal à analyser.                     * +*                                                                             * +*  Retour      : Content binaire associé au context.                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_context_set_content(PyObject *self, PyObject *value, void *closure) +{ +    GScanContext *context;                  /* Elément à consulter         */ +    int ret;                                /* Bilan de lecture des args.  */ +    GBinContent *content;                   /* Contenu binaire à référencer*/ + +    ret = PyObject_IsInstance(value, (PyObject *)get_python_binary_content_type()); +    if (!ret) return -1; + +    context = G_SCAN_CONTEXT(pygobject_get(self)); +    content = G_BIN_CONTENT(pygobject_get(value)); + +    // FIXME g_scan_context_set_content(context, content); + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Indique si la phase d'analyse de contenu est terminée.       * +*                                                                             * +*  Retour      : True si la phase de scan est terminée, False sinon.          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_context_is_scan_done(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Instance Python à retourner */ +    GScanContext *context;                  /* Contexte de suivi d'analyse */ +    bool status;                            /* Bilan de consultation       */ + +#define SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB PYTHON_IS_DEF_FULL     \ +(                                                               \ +    scan_done, py_scan_context,                                 \ +    "Tell if the analysis operations are finished.\n"           \ +    "\n"                                                        \ +    "The result is a boolean: *True* if the scan is marked as"  \ +    " done, *False* otherwise."                                 \ +) + +    context = G_SCAN_CONTEXT(pygobject_get(self)); + +    status = g_scan_context_is_scan_done(context); + +    result = status ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_context_type(void) +{ +    static PyMethodDef py_scan_context_methods[] = { +        SCAN_CONTEXT_MARK_SCAN_AS_DONE_METHOD, +        SCAN_CONTEXT_HAS_MATCH_FOR_RULE_METHOD, +        { NULL } +    }; + +    static PyGetSetDef py_scan_context_getseters[] = { +        SCAN_CONTEXT_CONTENT_ATTRIB, +        SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB, +        { NULL } +    }; + +    static PyTypeObject py_scan_context_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.ScanContext", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_CONTEXT_DOC, + +        .tp_methods     = py_scan_context_methods, +        .tp_getset      = py_scan_context_getseters, + +        .tp_init        = py_scan_context_init, +        .tp_new         = py_scan_context_new, + +    }; + +    return &py_scan_context_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide.....scan.ScanContext.  * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_context_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'ScanContext'   */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_context_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan"); + +        dict = PyModule_GetDict(module); + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_CONTEXT, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en contexte de suivi d'analyse.           * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_context(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_context_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan context"); +            break; + +        case 1: +            *((GScanContext **)dst) = G_SCAN_CONTEXT(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/context.h b/plugins/pychrysalide/analysis/scan/context.h new file mode 100644 index 0000000..477205b --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/context.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.h - prototypes pour l'équivalent Python du fichier "analysis/scan/context.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_context_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanContext'. */ +bool ensure_python_scan_context_is_registered(void); + +/* Tente de convertir en contexte de suivi d'analyse. */ +int convert_to_scan_context(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_CONTEXT_H */ diff --git a/plugins/pychrysalide/analysis/scan/core.c b/plugins/pychrysalide/analysis/scan/core.c new file mode 100644 index 0000000..16df9a9 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/core.c @@ -0,0 +1,179 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.c - équivalent Python du fichier "analysis/scan/core.c" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "core.h" + + +#include <pygobject.h> + + +#include <analysis/scan/core.h> + + +#include "patterns/modifier.h" +#include "../../access.h" +#include "../../helpers.h" + + + +/* Inscrit un modificateur dans la liste des disponibles. */ +static PyObject *py_scan_register_token_modifier(PyObject *, PyObject *); + +/* Fournit le modificateur correspondant à un nom. */ +static PyObject *py_scan_find_token_modifiers_for_name(PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet Python concerné par l'appel.                    * +*                args = arguments fournis à l'appel.                          * +*                                                                             * +*  Description : Inscrit un modificateur dans la liste des disponibles.       * +*                                                                             * +*  Retour      : Bilan des enregistrements effectués : True si nouveauté.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_register_token_modifier(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Bilan à retourner           */ +    PyObject *instance;                     /* Instance Python fournie     */ +    GScanTokenModifier *modifier;           /* Version native              */ +    int ret;                                /* Bilan de lecture des args.  */ +    bool status;                            /* Bilan d'un enregistrement   */ + +#define SCAN_REGISTER_TOKEN_MODIFIER_METHOD PYTHON_METHOD_DEF           \ +(                                                                       \ +    register_token_modifier, "inst, /",                                 \ +    METH_VARARGS, py_scan,                                              \ +    "Register a token modifier for byte patterns to scan.\n"            \ +    "\n"                                                                \ +    "This instance will be used as singleton and has to be a"           \ +    " subclass of pychrysalide.analysis.scan.patterns.TokenModifier."   \ +) + +    ret = PyArg_ParseTuple(args, "O!", get_python_scan_token_modifier_type(), &instance); +    if (!ret) return NULL; + +    modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(instance)); + +    status = register_scan_token_modifier(modifier); + +    result = status ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet Python concerné par l'appel.                    * +*                args = arguments fournis à l'appel.                          * +*                                                                             * +*  Description : Fournit le modificateur correspondant à un nom.              * +*                                                                             * +*  Retour      : Instance du modificateur identifié ou None.                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_find_token_modifiers_for_name(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Bilan à retourner           */ +    sized_string_t name;                    /* Nom d'appel à rechercher    */ +    Py_ssize_t len;                         /* Taille de ce nom            */ +    int ret;                                /* Bilan de lecture des args.  */ +    GScanTokenModifier *modifier;           /* Instance mise en place      */ + +#define SCAN_FIND_TOKEN_MODIFIERS_FOR_NAME_METHOD PYTHON_METHOD_DEF \ +(                                                                   \ +    find_token_modifiers_for_name, "name, /",                       \ +    METH_VARARGS, py_scan,                                          \ +    "Provide the registered instance of a pattern modifier linked"  \ +    " to a given *name* provided as a key string.\n"                \ +    "\n"                                                            \ +    "The returned instance is an object inherited from"             \ +    " pychrysalide.analysis.scan.patterns.TokenModifier or *None*"  \ +    " if no instance was found for the provided name."              \ +) + +    ret = PyArg_ParseTuple(args, "s#", &name.static_data, &len); +    if (!ret) return NULL; + +    name.len = len; + +    modifier = find_scan_token_modifiers_for_name(&name); + +    if (modifier != NULL) +    { +        result = pygobject_new(G_OBJECT(modifier)); +        g_object_unref(G_OBJECT(modifier)); +    } +    else +    { +        result = Py_None; +        Py_INCREF(result); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Définit une extension du module 'scan' à compléter.          * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool populate_scan_module_with_core_methods(void) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *module;                       /* Module à recompléter        */ + +    static PyMethodDef py_core_methods[] = { +        SCAN_REGISTER_TOKEN_MODIFIER_METHOD, +        SCAN_FIND_TOKEN_MODIFIERS_FOR_NAME_METHOD, +        { NULL } +    }; + +    module = get_access_to_python_module("pychrysalide.analysis.scan"); + +    result = register_python_module_methods(module, py_core_methods); + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/core.h b/plugins/pychrysalide/analysis/scan/core.h new file mode 100644 index 0000000..e283f91 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/core.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.h - prototypes pour l'équivalent Python du fichier "analysis/scan/core.h" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_CORE_CORE_H +#define _PLUGINS_PYCHRYSALIDE_CORE_CORE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Définit une extension du module 'scan' à compléter. */ +bool populate_scan_module_with_core_methods(void); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_CORE_CORE_H */ diff --git a/plugins/pychrysalide/analysis/scan/expr.c b/plugins/pychrysalide/analysis/scan/expr.c new file mode 100644 index 0000000..2d8245a --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/expr.c @@ -0,0 +1,393 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * expr.c - équivalent Python du fichier "analysis/scan/expr.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "expr.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/content.h> +#include <analysis/scan/expr-int.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/content.h> +#include <plugins/pychrysalide/glibext/comparison.h> + + +#include "constants.h" + + + +/* Initialise la classe générique des expressions d'évaluation. */ +static void py_scan_expression_init_gclass(GScanExpressionClass *, gpointer); + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_expression, G_TYPE_SCAN_EXPRESSION, py_scan_expression_init_gclass); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_expression_init(PyObject *, PyObject *, PyObject *); + +/* Réalise une comparaison entre objets selon un critère précis. */ +static bool py_scan_expression_compare_rich_wrapper(const GScanExpression *, const GScanExpression *, RichCmpOperation, bool *); + +/* Indique l'état de réduction d'une expression. */ +static PyObject *py_scan_expression_get_state(PyObject *, void *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : class  = classe à initialiser.                               * +*                unused = données non utilisées ici.                          * +*                                                                             * +*  Description : Initialise la classe générique des expressions d'évaluation. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void py_scan_expression_init_gclass(GScanExpressionClass *class, gpointer unused) +{ +    class->cmp_rich = py_scan_expression_compare_rich_wrapper; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_expression_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    ScanReductionState state;               /* Etat de réduction initial   */ +    int ret;                                /* Bilan de lecture des args.  */ +    GScanExpression *expr;                  /* Création GLib à transmettre */ + +    static char *kwlist[] = { "state", NULL }; + +#define SCAN_EXPRESSION_DOC                                             \ +    "A ScanExpression is an abstract object which defines an expression"\ +    " involved in data matching when running a scan.\n"                 \ +    "\n"                                                                \ +    "Calls to the *__init__* constructor of this abstract object expect"\ +    " the following arguments as keyword parameters:\n"                 \ +    "* *state*: initial state of reduction for the expression, as a"    \ +    " pychrysalide.analysis.scan.ScanExpression.ScanReductionState"     \ +    " value."                                                           \ +    "\n"                                                                \ +    "The following methods have to be defined for new classes:\n"       \ +    "* pychrysalide.analysis.scan.ScanExpression._cmp_rich().\n" + +    /* Récupération des paramètres */ + +    ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist, convert_to_scan_reduction_state, &state); +    if (!ret) return -1; + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    /* Eléments de base */ + +    expr = G_SCAN_EXPRESSION(pygobject_get(self)); + +    if (!g_scan_expression_create(expr, state)) +    { +        PyErr_SetString(PyExc_ValueError, _("Unable to create scan expression.")); +        return -1; +    } + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item   = premier objet à cnsulter pour une comparaison.      * +*                other  = second objet à cnsulter pour une comparaison.       * +*                op     = opération de comparaison à réaliser.                * +*                status = bilan des opérations de comparaison. [OUT]          * +*                                                                             * +*  Description : Réalise une comparaison entre objets selon un critère précis.* +*                                                                             * +*  Retour      : true si la comparaison a pu être effectuée, false sinon.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_scan_expression_compare_rich_wrapper(const GScanExpression *item, const GScanExpression *other, RichCmpOperation op, bool *status) +{ +    bool result;                            /* Etat à retourner            */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    int ret;                                /* Bilan d'une conversion      */ + +#define SCAN_EXPRESSION_CMP_RICH_WRAPPER PYTHON_WRAPPER_DEF             \ +(                                                                       \ +    _cmp_rich, "$self, other, op, /",                                   \ +    METH_VARARGS,                                                       \ +    "Abstract method used to compare the expression against another"    \ +    " one.\n"                                                           \ +    "\n"                                                                \ +    "The second *other* instance is built from the same type as *self*."\ +    " The *op* argument points to a"                                    \ +    " pychrysalide.glibext.ComparableItem.RichCmpOperation mode"        \ +    " describing the expected comparison.\n"                            \ +    "\n"                                                                \ +    "The result is a boolean status or *None* if the comparison"        \ +    " process is undefined."                                            \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(item)); + +    if (has_python_method(pyobj, "_cmp_rich")) +    { +        args = PyTuple_New(2); +        PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(other))); +        PyTuple_SetItem(args, 1, cast_with_constants_group_from_type(get_python_comparable_item_type(), +                                                                     "RichCmpOperation", op)); + +        pyret = run_python_method(pyobj, "_cmp_rich", args); + +        if (pyret != NULL) +        { +            ret = PyBool_Check(pyret); + +            if (ret) +            { +                *status = (pyret == Py_True); +                result = true; +            } + +            Py_DECREF(pyret); + +        } + +        Py_DECREF(args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Indique l'état de réduction d'une expression.                * +*                                                                             * +*  Retour      : Etat courant associé à l'expression.                         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_expression_get_state(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Instance Python à retourner */ +    GScanExpression *expr;                  /* Version GLib de l'opérande  */ +    ScanReductionState state;               /* Etat courant de l'expression*/ + +#define SCAN_EXPRESSION_STATE_ATTRIB PYTHON_GET_DEF_FULL            \ +(                                                                   \ +    state, py_scan_expression,                                      \ +    "Current state of the expression, relative to the reduction"    \ +    " process, as a"                                                \ +    " pychrysalide.analysis.scan.ScanExpression.ScanReductionState" \ +    " value."                                                       \ +) + +    expr = G_SCAN_EXPRESSION(pygobject_get(self)); + +    state = g_scan_expression_get_state(expr); + +    result = cast_with_constants_group_from_type(get_python_scan_expression_type(), "ScanReductionState", state); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_expression_type(void) +{ +    static PyMethodDef py_scan_expression_methods[] = { +        SCAN_EXPRESSION_CMP_RICH_WRAPPER, +        { NULL } +    }; + +    static PyGetSetDef py_scan_expression_getseters[] = { +        SCAN_EXPRESSION_STATE_ATTRIB, +        { NULL } +    }; + +    static PyTypeObject py_scan_expression_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.ScanExpression", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_EXPRESSION_DOC, + +        .tp_methods     = py_scan_expression_methods, +        .tp_getset      = py_scan_expression_getseters, + +        .tp_init        = py_scan_expression_init, +        .tp_new         = py_scan_expression_new, + +    }; + +    return &py_scan_expression_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide...scan.ScanExpression'.* +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_expression_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'ScanExpression'*/ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_expression_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_comparable_item_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_EXPRESSION, type)) +            return false; + +        if (!define_expression_value_type_constants(type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en expression d'évaluation généraliste.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_expression(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_expression_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to match expression"); +            break; + +        case 1: +            *((GScanExpression **)dst) = G_SCAN_EXPRESSION(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/expr.h b/plugins/pychrysalide/analysis/scan/expr.h new file mode 100644 index 0000000..42f5350 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/expr.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * expr.h - prototypes pour l'équivalent Python du fichier "analysis/scan/expr.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_expression_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanExpression'. */ +bool ensure_python_scan_expression_is_registered(void); + +/* Tente de convertir en expression d'évaluation généraliste. */ +int convert_to_scan_expression(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPR_H */ diff --git a/plugins/pychrysalide/analysis/scan/exprs/Makefile.am b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am new file mode 100644 index 0000000..e40d4de --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libpychrysaanalysisscanexprs.la + +libpychrysaanalysisscanexprs_la_SOURCES = 	\ +	constants.h constants.c					\ +	literal.h literal.c						\ +	module.h module.c + +libpychrysaanalysisscanexprs_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +    $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libpychrysaanalysisscanexprs_la_SOURCES:%c=) diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.c b/plugins/pychrysalide/analysis/scan/exprs/constants.c new file mode 100644 index 0000000..b11ac4c --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/constants.c @@ -0,0 +1,128 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.c - ajout des constantes de base pour les expressions + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "constants.h" + + +#include <analysis/scan/exprs/literal.h> + + +#include "../../../helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : type = type dont le dictionnaire est à compléter.            * +*                                                                             * +*  Description : Définit les constantes relatives aux expressions de scan.    * +*                                                                             * +*  Retour      : true en cas de succès de l'opération, false sinon.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool define_literal_expression_value_type_constants(PyTypeObject *type) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *values;                       /* Groupe de valeurs à établir */ + +    values = PyDict_New(); + +    result = add_const_to_group(values, "LVT_BOOLEAN", LVT_BOOLEAN); +    if (result) result = add_const_to_group(values, "SIGNED_INTEGER", LVT_SIGNED_INTEGER); +    if (result) result = add_const_to_group(values, "UNSIGNED_INTEGER", LVT_UNSIGNED_INTEGER); +    if (result) result = add_const_to_group(values, "STRING", LVT_STRING); + +    if (!result) +    { +        Py_DECREF(values); +        goto exit; +    } + +    result = attach_constants_group_to_type(type, false, "LiteralValueType", values, +                                            "Type of value carried by a literal scan expression."); + + exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en constante LiteralValueType.          * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_literal_expression_value_type(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ +    unsigned long value;                    /* Valeur transcrite           */ + +    result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to LiteralValueType"); +            break; + +        case 1: +            value = PyLong_AsUnsignedLong(arg); + +            if (value > LVT_REG_EXPR) +            { +                PyErr_SetString(PyExc_TypeError, "invalid value for LiteralValueType"); +                result = 0; +            } + +            else +                *((LiteralValueType *)dst) = value; + +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.h b/plugins/pychrysalide/analysis/scan/exprs/constants.h new file mode 100644 index 0000000..e5b8e8c --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/constants.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.h - prototypes pour l'ajout des constantes de base pour les expressions + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Définit les constantes relatives aux expressions litérales. */ +bool define_literal_expression_value_type_constants(PyTypeObject *); + +/* Tente de convertir en constante LiteralValueType. */ +int convert_to_literal_expression_value_type(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H */ diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.c b/plugins/pychrysalide/analysis/scan/exprs/literal.c new file mode 100644 index 0000000..d7ae002 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/literal.c @@ -0,0 +1,281 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * literal.c - équivalent Python du fichier "analysis/scan/exprs/literal.c" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "literal.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/exprs/literal-int.h> + + +#include "constants.h" +#include "../expr.h" +#include "../../../access.h" +#include "../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_literal_expression, G_TYPE_SCAN_LITERAL_EXPRESSION); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_literal_expression_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_literal_expression_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    PyObject *py_value;                     /* Valeur en version Python    */ +    int ret;                                /* Bilan de lecture des args.  */ +    LiteralValueType vtype;                 /* Valeur à porter             */ +    bool arg_boolean;                       /* Argument natif booléen      */ +    unsigned long long arg_uinteger;        /* Argument natif entier       */ +    sized_string_t arg_string;              /* Argument natif textuel      */ +    Py_ssize_t arg_str_length;              /* Taille de ce texte          */ +    void *arg_ptr;                          /* Pointeur vers un argument   */ +    GScanLiteralExpression *expr;           /* Création GLib à transmettre */ + +#define SCAN_LITERAL_EXPRESSION_DOC                                 \ +    "A ScanLiteralExpression object defines expression carrying"    \ +    " literal values available for scan match conditions.\n"        \ +    "\n"                                                            \ +    "Instances can be created using one of the following"           \ +    " constructors:\n"                                              \ +    "\n"                                                            \ +    "    ScanLiteralExpression(value)"                              \ +    "\n"                                                            \ +    "\n"                                                            \ +    "Where *value* is either a boolean, an integer or bytes." + +    /* Récupération des paramètres */ + +    ret = PyArg_ParseTuple(args, "O", &py_value); +    if (!ret) return -1; + +    if (PyBool_Check(py_value)) +    { +        vtype = LVT_BOOLEAN; + +        arg_boolean = (py_value == Py_True); +        arg_ptr = &arg_boolean; + +    } + +    else if (PyLong_Check(py_value)) +    { +        if (1 /* sign - TODO */) +            ; + +        vtype = LVT_UNSIGNED_INTEGER; + +        arg_uinteger = PyLong_AsUnsignedLongLong(py_value); +        arg_ptr = &arg_uinteger; + +    } + +    else if (PyBytes_Check(py_value)) +    { +        vtype = LVT_STRING; + +        ret = PyBytes_AsStringAndSize(py_value, &arg_string.data, &arg_str_length); +        if (ret == -1) return -1; + +        arg_string.len = arg_str_length; +        arg_ptr = &arg_string; + +    } + +    else +    { +        PyErr_SetString(PyExc_ValueError, _("Unsupported Python value for a literal scan expression.")); +        return -1; +    } + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    /* Eléments de base */ + +    expr = G_SCAN_LITERAL_EXPRESSION(pygobject_get(self)); + +    if (!g_scan_literal_expression_create(expr, vtype, arg_ptr)) +    { +        PyErr_SetString(PyExc_ValueError, _("Unable to create literal expression.")); +        return -1; +    } + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_literal_expression_type(void) +{ +    static PyMethodDef py_scan_literal_expression_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_scan_literal_expression_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_scan_literal_expression_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.exprs.ScanLiteralExpression", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_LITERAL_EXPRESSION_DOC, + +        .tp_methods     = py_scan_literal_expression_methods, +        .tp_getset      = py_scan_literal_expression_getseters, + +        .tp_init        = py_scan_literal_expression_init, +        .tp_new         = py_scan_literal_expression_new, + +    }; + +    return &py_scan_literal_expression_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....PlainModifier'.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_literal_expression_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'PlainModifier' */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_literal_expression_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan.exprs"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_scan_expression_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_LITERAL_EXPRESSION, type)) +            return false; + +        if (!define_literal_expression_value_type_constants(type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en transmission d'octets à l'identique.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_literal_expression(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_literal_expression_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan literal expression"); +            break; + +        case 1: +            *((GScanLiteralExpression **)dst) = G_SCAN_LITERAL_EXPRESSION(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.h b/plugins/pychrysalide/analysis/scan/exprs/literal.h new file mode 100644 index 0000000..8e7ea70 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/literal.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * literal.h - équivalent Python du fichier "analysis/scan/exprs/literal.h" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_literal_expression_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.exprs.ScanLiteralExpression'. */ +bool ensure_python_scan_literal_expression_is_registered(void); + +/* Tente de convertir en transmission d'octets à l'identique. */ +int convert_to_scan_literal_expression(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H */ diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.c b/plugins/pychrysalide/analysis/scan/exprs/module.c new file mode 100644 index 0000000..4f38430 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/module.c @@ -0,0 +1,103 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire exprs en tant que module + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "module.h" + + +#include <assert.h> + + +#include "literal.h" +#include "../../../helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : super = module dont la définition est à compléter.           * +*                                                                             * +*  Description : Ajoute le module 'analysis....modifiers' à un module Python. * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool add_analysis_scan_exprs_module(PyObject *super) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *module;                       /* Sous-module mis en place    */ + +#define PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC \ +    "This module provide expressions used to build a match condition." + +    static PyModuleDef py_chrysalide_analysis_scan_exprs_module = { + +        .m_base = PyModuleDef_HEAD_INIT, + +        .m_name = "pychrysalide.analysis.scan.exprs", +        .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC, + +        .m_size = -1, + +    }; + +    module = build_python_module(super, &py_chrysalide_analysis_scan_exprs_module); + +    result = (module != NULL); + +    if (!result) +        Py_XDECREF(module); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Intègre les objets du module 'analysis...patterns.modifiers'.* +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool populate_analysis_scan_exprs_module(void) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    if (result) result = ensure_python_scan_literal_expression_is_registered(); + +    assert(result); + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.h b/plugins/pychrysalide/analysis/scan/exprs/module.h new file mode 100644 index 0000000..ee4b8ab --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/module.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire exprs en tant que module + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'analysis.scan.exprs' à un module Python. */ +bool add_analysis_scan_exprs_module(PyObject *); + +/* Intègre les objets du module 'analysis.scan.exprs'. */ +bool populate_analysis_scan_exprs_module(void); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H */ diff --git a/plugins/pychrysalide/analysis/scan/item.c b/plugins/pychrysalide/analysis/scan/item.c new file mode 100644 index 0000000..014ae24 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/item.c @@ -0,0 +1,740 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * item.c - équivalent Python du fichier "analysis/scan/item.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "item.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/item-int.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "context.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Initialise la classe des éléments appelables enregistrés. */ +static void py_scan_registered_item_init_gclass(GScanRegisteredItemClass *, gpointer); + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_registered_item, G_TYPE_SCAN_REGISTERED_ITEM, py_scan_registered_item_init_gclass); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_registered_item_init(PyObject *, PyObject *, PyObject *); + +/* Indique le nom associé à une expression d'évaluation. */ +static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *); + +/* Lance une résolution d'élément à solliciter. */ +static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + +/* Réduit une expression à une forme plus simple. */ +static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **); + +/* Effectue un appel à une fonction enregistrée. */ +static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ + + +/* Lance une résolution d'élément à appeler. */ +static PyObject *py_scan_registered_item_resolve(PyObject *, PyObject *); + +/* Fournit le désignation associée à un composant nommé. */ +static PyObject *py_scan_registered_item_get_name(PyObject *, void *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                          GLUE POUR CREATION DEPUIS PYTHON                          */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : class  = classe à initialiser.                               * +*                unused = données non utilisées ici.                          * +*                                                                             * +*  Description : Initialise la classe des éléments appelables enregistrés.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void py_scan_registered_item_init_gclass(GScanRegisteredItemClass *class, gpointer unused) +{ +    class->get_name = py_scan_registered_item_get_name_wrapper; +    class->resolve = py_scan_registered_item_resolve_wrapper; +    class->reduce = py_scan_registered_item_reduce_wrapper; +    class->run_call = py_scan_registered_item_run_call_wrapper; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_registered_item_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_REGISTERED_ITEM_DOC                                    \ +    "The *RegisteredItem* class is an abstract definition which is" \ +    " the base for all keywords involved in a match condition"      \ +    " expression.\n"                                                \ +    "\n"                                                            \ +    "Calls to the *__init__* constructor of this abstract object"   \ +    " expect no particular argument.\n"                             \ +    "\n"                                                            \ +    "The following methods have to be defined for new classes:\n"   \ +    "* pychrysalide.analysis.scan.RegisteredItem._resolve();\n"     \ +    "* pychrysalide.analysis.scan.RegisteredItem._reduce();\n"      \ +    "* pychrysalide.analysis.scan.RegisteredItem._call().\n"        \ +    "\n"                                                            \ +    "One item has to be defined as class attributes in the final"   \ +    " class:\n"                                                     \ +    "* pychrysalide.analysis.scan.RegisteredItem._name.\n" + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *item) +{ +    char *result;                           /* Désignation à retourner     */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *pyname;                       /* Nom en objet Python         */ +    int ret;                                /* Bilan d'une conversion      */ + +#define SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER PYTHON_GETTER_WRAPPER_DEF  \ +(                                                                           \ +    _name,                                                                  \ +    "Provide the keyword of the expression item to be evaluated.\n"         \ +    "\n"                                                                    \ +    "The result has to be a string."                                        \ +) + +    result = NULL; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(item)); + +    if (PyObject_HasAttrString(pyobj, "_name")) +    { +        pyname = PyObject_GetAttrString(pyobj, "_name"); + +        if (pyname != NULL) +        { +            ret = PyUnicode_Check(pyname); + +            if (ret) +                result = strdup(PyUnicode_AsUTF8(pyname)); + +            Py_DECREF(pyname); + +        } + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item   = élément d'appel à consulter.                        * +*                target = désignation de l'objet d'appel à identifier.        * +*                ctx    = contexte de suivi de l'analyse courante.            * +*                scope  = portée courante des variables locales.              * +*                out    = zone d'enregistrement de la résolution opérée. [OUT]* +*                                                                             * +*  Description : Lance une résolution d'élément à solliciter.                 * +*                                                                             * +*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ +    bool result;                            /* Bilan à retourner           */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    GObject *gobj_ret;                      /* Bilan natif de consultation */ + +#define SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER PYTHON_WRAPPER_DEF         \ +(                                                                       \ +    _cmp_rich, "$self, target, ctx, scope, /",                          \ +    METH_VARARGS,                                                       \ +    "Abstract method used to resolve an item by name.\n"                \ +    "\n"                                                                \ +    "The *target* argument provide the name of the searched item;"      \ +    " *ctx* is a pychrysalide.analysis.scan.ScanContext instance"       \ +    " providing information about the current state; *scope* is a"      \ +    " pychrysalide.analysis.scan.ScanScope offering a view on the"      \ +    " current namespace for variables.\n"                               \ +    "\n"                                                                \ +    "The result has to be a pychrysalide.analysis.scan.RegisteredItem"  \ +    " instance on success, or *None* in case of failure."               \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(item)); + +    if (has_python_method(pyobj, "_resolve")) +    { +        args = PyTuple_New(3); +        PyTuple_SetItem(args, 0, PyUnicode_FromString(target)); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(ctx))); +        PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(scope))); + +        pyret = run_python_method(pyobj, "_resolve", args); + +        if (pyret != NULL) +        { +            gobj_ret = pygobject_get(pyret); + +            if (G_IS_SCAN_REGISTERED_ITEM(gobj_ret)) +            { +                *out = G_SCAN_REGISTERED_ITEM(gobj_ret); + +                g_object_ref(G_OBJECT(*out)); +                result = true; + +            } + +            Py_DECREF(pyret); + +        } + +        Py_DECREF(args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la réduction opérée. [OUT]  * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ +    bool result;                            /* Bilan à retourner           */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    GObject *gobj_ret;                      /* Bilan natif de consultation */ + +#define SCAN_REGISTERED_ITEM_REDUCE_WRAPPER PYTHON_WRAPPER_DEF          \ +(                                                                       \ +    _cmp_rich, "$self, ctx, scope, /",                                  \ +    METH_VARARGS,                                                       \ +    "Abstract method used to replace the item by an equivalent reduced" \ +    " value.\n"                                                         \ +    "\n"                                                                \ +    "The *ctx* argument is a pychrysalide.analysis.scan.ScanContext"    \ +    " instance providing information about the current state; *scope*"  \ +    " is a pychrysalide.analysis.scan.ScanScope offering a view on the" \ +    " current namespace for variables.\n"                               \ +    "\n"                                                                \ +    "The result has to be a pychrysalide.analysis.scan.ScanExpression"  \ +    " instance on success, or *None* in case of failure."               \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(item)); + +    if (has_python_method(pyobj, "_reduce")) +    { +        args = PyTuple_New(2); +        PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(ctx))); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(scope))); + +        pyret = run_python_method(pyobj, "_reduce", args); + +        if (pyret != NULL) +        { +            gobj_ret = pygobject_get(pyret); + +            if (G_IS_SCAN_EXPRESSION(gobj_ret)) +            { +                *out = G_SCAN_EXPRESSION(gobj_ret); + +                g_object_ref(G_OBJECT(*out)); +                result = true; + +            } + +            Py_DECREF(pyret); + +        } + +        Py_DECREF(args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Effectue un appel à une fonction enregistrée.                * +*                                                                             * +*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *sub_args;                     /* Sous-arguments pour l'appel */ +    size_t i;                               /* Boucle de parcours          */ +    PyObject *py_args;                      /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    GObject *gobj_ret;                      /* Bilan natif de consultation */ + +#define SCAN_REGISTERED_ITEM_CALL_WRAPPER PYTHON_WRAPPER_DEF            \ +(                                                                       \ +    _cmp_rich, "$self, args, ctx, scope, /",                            \ +    METH_VARARGS,                                                       \ +    "Abstract method used to replace the item and its arguments by an"  \ +    " equivalent reduced value.\n"                                      \ +    "\n"                                                                \ +    "The *args* argument is a tuple of already reduced"                 \ +    " pychrysalide.analysis.scan.ScanExpression objects; ctx* argument" \ +    " is a pychrysalide.analysis.scan.ScanContext instance providing"   \ +    " information about the current state; *scope* is a"                \ +    " pychrysalide.analysis.scan.ScanScope offering a view on the"      \ +    " current namespace for variables.\n"                               \ +    "\n"                                                                \ +    "The result has to be a pychrysalide.analysis.scan.ScanExpression"  \ +    " instance on success, or *None* in case of failure."               \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(item)); + +    if (has_python_method(pyobj, "_call")) +    { +        sub_args = PyTuple_New(count); + +        for (i = 0; i < count; i++) +            PyTuple_SetItem(sub_args, 1, pygobject_new(G_OBJECT(args[i]))); + +        py_args = PyTuple_New(3); +        PyTuple_SetItem(py_args, 0, sub_args); +        PyTuple_SetItem(py_args, 1, pygobject_new(G_OBJECT(ctx))); +        PyTuple_SetItem(py_args, 2, pygobject_new(G_OBJECT(scope))); + +        pyret = run_python_method(pyobj, "_call", py_args); + +        if (pyret != NULL) +        { +            gobj_ret = pygobject_get(pyret); + +            if (G_IS_OBJECT(gobj_ret)) +            { +                *out = gobj_ret; + +                g_object_ref(G_OBJECT(*out)); +                result = true; + +            } + +            Py_DECREF(pyret); + +        } + +        Py_DECREF(py_args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                           CONNEXION AVEC L'API DE PYTHON                           */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = élément d'appel à consulter.                          * +*                args = arguments fournis pour l'opération.                   * +*                                                                             * +*  Description : Lance une résolution d'élément à appeler.                    * +*                                                                             * +*  Retour      : Nouvel élément d'appel identifié ou None.                    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_registered_item_resolve(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Bilan à retourner           */ +    const char *target;                     /* Désignation de la cible     */ +    GScanContext *ctx;                      /* Contexte d'analyse          */ +    GScanScope *scope;                      /* Portée de variables locales */ +    int ret;                                /* Bilan de lecture des args.  */ +    GScanRegisteredItem *item;              /* Version native              */ +    bool status;                            /* Bilan d'exécution           */ +    GScanRegisteredItem *resolved;          /* Elément trouvé              */ + +#define SCAN_REGISTERED_ITEM_RESOLVE_METHOD PYTHON_METHOD_DEF           \ +(                                                                       \ +    resolve, "$self, target, /, ctx=None, scope=None",                  \ +    METH_VARARGS, py_scan_registered_item,                              \ +    "Resolve a name into a scan item."                                  \ +    "\n"                                                                \ +    "The *target* name is the only mandatory parameter and has to point"\ +    " to only one item. The *ctx* argument points to an optional useful"\ +    " storage for resolution lookup, as a"                              \ +    " pychrysalide.analysis.scan.ScanContext instance. The *args* list" \ +    " defines an optional list of arguments, as"                        \ +    " pychrysalide.analysis.scan.ScanExpression instances, to use for"  \ +    " building the resolved item. The *final* flag states if the"       \ +    " scanning process is about to conclude or not."                    \ +    "\n"                                                                \ +    "The result is an object inheriting from"                           \ +    " pychrysalide.analysis.scan.RegisteredItem or *None* if the"       \ +    " resolution operation failed."                                     \ +) + +    ctx = NULL; +    scope = NULL; + +    ret = PyArg_ParseTuple(args, "s|O&", &target, +                           convert_to_scan_context, &ctx); +    if (!ret) return NULL; + +    item = G_SCAN_REGISTERED_ITEM(pygobject_get(self)); + +    status = g_scan_registered_item_resolve(item, target, ctx, scope, &resolved); + +    if (!status) +    { +        result = NULL; +        PyErr_Format(PyExc_RuntimeError, _("Unable to resolve any target from the item")); +    } +    else +    { +        if (resolved != NULL) +        { +            result = pygobject_new(G_OBJECT(resolved)); +            g_object_unref(G_OBJECT(resolved)); +        } +        else +        { +            result = Py_None; +            Py_INCREF(result); +        } +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = classe représentant un composant nommé à manipuler.* +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Fournit le désignation associée à un composant nommé.        * +*                                                                             * +*  Retour      : Description courante.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_registered_item_get_name(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Décompte à retourner        */ +    GScanRegisteredItem *item;              /* Version native              */ +    char *name;                             /* Désignation à convertir     */ + +#define SCAN_REGISTERED_ITEM_NAME_ATTRIB PYTHON_GET_DEF_FULL            \ +(                                                                       \ +    name, py_scan_registered_item,                                      \ +    "Name linked to the registered item.\n"                             \ +    "\n"                                                                \ +    "The result should be a string, or *None* for the root namespace."  \ +) + +    item = G_SCAN_REGISTERED_ITEM(pygobject_get(self)); + +    name = g_scan_registered_item_get_name(item); + +    if (name == NULL) +    { +        result = Py_None; +        Py_INCREF(result); +    } +    else +    { +        result = PyUnicode_FromString(name); +        free(name); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_registered_item_type(void) +{ +    static PyMethodDef py_scan_registered_item_methods[] = { +        SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER, +        SCAN_REGISTERED_ITEM_REDUCE_WRAPPER, +        SCAN_REGISTERED_ITEM_CALL_WRAPPER, +        SCAN_REGISTERED_ITEM_RESOLVE_METHOD, +        { NULL } +    }; + +    static PyGetSetDef py_scan_registered_item_getseters[] = { +        SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER, +        SCAN_REGISTERED_ITEM_NAME_ATTRIB, +        { NULL } +    }; + +    static PyTypeObject py_scan_registered_item_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.ScanRegisteredItem", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_REGISTERED_ITEM_DOC, + +        .tp_methods     = py_scan_registered_item_methods, +        .tp_getset      = py_scan_registered_item_getseters, + +        .tp_init        = py_scan_registered_item_init, +        .tp_new         = py_scan_registered_item_new, + +    }; + +    return &py_scan_registered_item_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide...ScanRegisteredItem'. * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_registered_item_is_registered(void) +{ +    PyTypeObject *type;                     /* Type 'ScanRegisteredItem'   */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_registered_item_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan"); + +        dict = PyModule_GetDict(module); + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REGISTERED_ITEM, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en expression d'évaluation généraliste.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_registered_item(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_registered_item_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to generic scan expression"); +            break; + +        case 1: +            *((GScanRegisteredItem **)dst) = G_SCAN_REGISTERED_ITEM(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/item.h b/plugins/pychrysalide/analysis/scan/item.h new file mode 100644 index 0000000..773908c --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/item.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * item.h - prototypes pour l'équivalent Python du fichier "analysis/scan/item.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_registered_item_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanRegisteredItem'. */ +bool ensure_python_scan_registered_item_is_registered(void); + +/* Tente de convertir en expression d'évaluation généraliste. */ +int convert_to_scan_registered_item(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_ITEM_H */ diff --git a/plugins/pychrysalide/analysis/scan/module.c b/plugins/pychrysalide/analysis/scan/module.c new file mode 100644 index 0000000..9ae0e52 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/module.c @@ -0,0 +1,125 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire scan en tant que module + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "module.h" + + +#include <assert.h> + + +#include "context.h" +#include "core.h" +#include "expr.h" +#include "item.h" +#include "options.h" +#include "scanner.h" +#include "space.h" +#include "exprs/module.h" +#include "patterns/module.h" +#include "../../helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : super = module dont la définition est à compléter.           * +*                                                                             * +*  Description : Ajoute le module 'analysis.scan' à un module Python.         * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool add_analysis_scan_module(PyObject *super) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *module;                       /* Sous-module mis en place    */ + +#define PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_DOC                   \ +    "This module provide all the features useful for scanning"  \ +    " binary contents." + +    static PyModuleDef py_chrysalide_analysis_scan_module = { + +        .m_base = PyModuleDef_HEAD_INIT, + +        .m_name = "pychrysalide.analysis.scan", +        .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_DOC, + +        .m_size = -1, + +    }; + +    module = build_python_module(super, &py_chrysalide_analysis_scan_module); + +    result = (module != NULL); + +    if (result) result = add_analysis_scan_exprs_module(module); +    if (result) result = add_analysis_scan_patterns_module(module); + +    if (!result) +        Py_XDECREF(module); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Intègre les objets du module 'analysis.scan'.                * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool populate_analysis_scan_module(void) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    if (result) result = ensure_python_content_scanner_is_registered(); +    if (result) result = ensure_python_scan_context_is_registered(); +    if (result) result = ensure_python_scan_expression_is_registered(); +    if (result) result = ensure_python_scan_registered_item_is_registered(); +    if (result) result = ensure_python_scan_options_is_registered(); +    if (result) result = ensure_python_scan_namespace_is_registered(); + +    if (result) result = populate_scan_module_with_core_methods(); + +    if (result) result = populate_analysis_scan_exprs_module(); +    if (result) result = populate_analysis_scan_patterns_module(); + +    assert(result); + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/module.h b/plugins/pychrysalide/analysis/scan/module.h new file mode 100644 index 0000000..a5e84b5 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/module.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire scan en tant que module + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'analysis.scan' à un module Python. */ +bool add_analysis_scan_module(PyObject *); + +/* Intègre les objets du module 'analysis.scan'. */ +bool populate_analysis_scan_module(void); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODULE_H */ diff --git a/plugins/pychrysalide/analysis/scan/options.c b/plugins/pychrysalide/analysis/scan/options.c new file mode 100644 index 0000000..84c1784 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/options.c @@ -0,0 +1,511 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * options.c - équivalent Python du fichier "analysis/scan/options.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "options.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/options-int.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + + +CREATE_DYN_CONSTRUCTOR(scan_options, G_TYPE_SCAN_OPTIONS); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_options_init(PyObject *, PyObject *, PyObject *); + +/* Indique le type d'un moteur d'analyse de données sélectionné. */ +static PyObject *py_scan_options_get_backend_for_data(PyObject *, void *); + +/* Sélectionne un type de moteur d'analyse pour données brutes. */ +static int py_scan_options_set_backend_for_data(PyObject *, PyObject *, void *); + +/* Impose le format JSON comme type de sortie. */ +static PyObject *py_scan_options_get_print_json(PyObject *, void *); + +/* Mémorise le format JSON comme type de sortie. */ +static int py_scan_options_set_print_json(PyObject *, PyObject *, void *); + +/* Indique un besoin d'affichage des correspondances finales. */ +static PyObject *py_scan_options_get_print_strings(PyObject *, void *); + +/* Mémorise un besoin d'affichage des correspondances finales. */ +static int py_scan_options_set_print_strings(PyObject *, PyObject *, void *); + +/* Indique un besoin de statistiques en fin de compilation. */ +static PyObject *py_scan_options_get_print_stats(PyObject *, void *); + +/* Mémorise un besoin de statistiques en fin de compilation. */ +static int py_scan_options_set_print_stats(PyObject *, PyObject *, void *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_options_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_OPTIONS_DOC                                            \ +    "The *ScanOptions* class stores all parameters used to tune"    \ +    " a scanning process.\n"                                        \ +    "\n"                                                            \ +    "Instances can be created using the following constructor:\n"   \ +    "\n"                                                            \ +    "    ScanOptions()" + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = classe représentant un format Axml.                * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Indique le type d'un moteur d'analyse de données sélectionné.* +*                                                                             * +*  Retour      : Type d'objet, idéalement valide.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_options_get_backend_for_data(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Liste éventuelle à renvoyer */ +    GScanOptions *options;                  /* Version native              */ +    GType type;                             /* Type à transcrire           */ + +#define SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB PYTHON_GETSET_DEF_FULL \ +(                                                                   \ +    backend_for_data, py_scan_options,                              \ +    "Type of the selected scan algorithm."                          \ +) + +    options = G_SCAN_OPTIONS(pygobject_get(self)); + +    type = g_scan_options_get_backend_for_data(options); + +    result = pyg_type_wrapper_new(type); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                value   = valeur fournie à intégrer ou prendre en compte.    * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Sélectionne un type de moteur d'analyse pour données brutes. * +*                                                                             * +*  Retour      : Bilan de l'opération pour Python.                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_options_set_backend_for_data(PyObject *self, PyObject *value, void *closure) +{ +    GType type;                             /* Type à transcrit            */ +    GScanOptions *options;                  /* Version native              */ + +    type = pyg_type_from_object(value); + +    options = G_SCAN_OPTIONS(pygobject_get(self)); + +    g_scan_options_set_backend_for_data(options, type); + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = classe représentant un format Axml.                * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Impose le format JSON comme type de sortie.                  * +*                                                                             * +*  Retour      : Etat de l'option visée à conservé.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_options_get_print_json(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Liste éventuelle à renvoyer */ +    GScanOptions *options;                  /* Version native              */ +    bool state;                             /* Etat courant à consulter    */ + +#define SCAN_OPTIONS_PRINT_JSON_ATTRIB PYTHON_GETSET_DEF_FULL   \ +(                                                               \ +    print_json, py_scan_options,                                \ +    "Define if the process summary is output into a JSON"       \ +    " format at the end of the scan or not."                    \ +) + +    options = G_SCAN_OPTIONS(pygobject_get(self)); + +    state = g_scan_options_get_print_json(options); + +    result = state ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                value   = valeur fournie à intégrer ou prendre en compte.    * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Mémorise le format JSON comme type de sortie.                * +*                                                                             * +*  Retour      : Bilan de l'opération pour Python.                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_options_set_print_json(PyObject *self, PyObject *value, void *closure) +{ +    bool state;                             /* Nouvel état à définir       */ +    GScanOptions *options;                  /* Version native              */ + +    if (value != Py_True && value != Py_False) +        return -1; + +    state = (value == Py_True); + +    options = G_SCAN_OPTIONS(pygobject_get(self)); + +    g_scan_options_set_print_json(options, state); + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = classe représentant un format Axml.                * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Indique un besoin d'affichage des correspondances finales.   * +*                                                                             * +*  Retour      : Etat de l'option visée à conservé.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_options_get_print_strings(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Liste éventuelle à renvoyer */ +    GScanOptions *options;                  /* Version native              */ +    bool state;                             /* Etat courant à consulter    */ + +#define SCAN_OPTIONS_PRINT_STRINGS_ATTRIB PYTHON_GETSET_DEF_FULL    \ +(                                                                   \ +    print_strings, py_scan_options,                                 \ +    "Define if the matching patterns are printed with found"        \ +    " offset at the end of the scan or not."                        \ +) + +    options = G_SCAN_OPTIONS(pygobject_get(self)); + +    state = g_scan_options_get_print_strings(options); + +    result = state ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                value   = valeur fournie à intégrer ou prendre en compte.    * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Mémorise un besoin d'affichage des correspondances finales.  * +*                                                                             * +*  Retour      : Bilan de l'opération pour Python.                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_options_set_print_strings(PyObject *self, PyObject *value, void *closure) +{ +    bool state;                             /* Nouvel état à définir       */ +    GScanOptions *options;                  /* Version native              */ + +    if (value != Py_True && value != Py_False) +        return -1; + +    state = (value == Py_True); + +    options = G_SCAN_OPTIONS(pygobject_get(self)); + +    g_scan_options_set_print_strings(options, state); + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = classe représentant un format Axml.                * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Indique un besoin de statistiques en fin de compilation.     * +*                                                                             * +*  Retour      : Etat de l'option visée à conservé.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_options_get_print_stats(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Liste éventuelle à renvoyer */ +    GScanOptions *options;                  /* Version native              */ +    bool state;                             /* Etat courant à consulter    */ + +#define SCAN_OPTIONS_PRINT_STATS_ATTRIB PYTHON_GETSET_DEF_FULL  \ +(                                                               \ +    print_stats, py_scan_options,                               \ +    "Control the output of final statistics afer a scan."       \ +) + +    options = G_SCAN_OPTIONS(pygobject_get(self)); + +    state = g_scan_options_get_print_stats(options); + +    result = state ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                value   = valeur fournie à intégrer ou prendre en compte.    * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Mémorise un besoin de statistiques en fin de compilation.    * +*                                                                             * +*  Retour      : Bilan de l'opération pour Python.                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_options_set_print_stats(PyObject *self, PyObject *value, void *closure) +{ +    bool state;                             /* Nouvel état à définir       */ +    GScanOptions *options;                  /* Version native              */ + +    if (value != Py_True && value != Py_False) +        return -1; + +    state = (value == Py_True); + +    options = G_SCAN_OPTIONS(pygobject_get(self)); + +    g_scan_options_set_print_stats(options, state); + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_options_type(void) +{ +    static PyMethodDef py_scan_options_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_scan_options_getseters[] = { +        SCAN_OPTIONS_BACKEND_FOR_DATA_ATTRIB, +        SCAN_OPTIONS_PRINT_JSON_ATTRIB, +        SCAN_OPTIONS_PRINT_STRINGS_ATTRIB, +        SCAN_OPTIONS_PRINT_STATS_ATTRIB, +        { NULL } +    }; + +    static PyTypeObject py_scan_options_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.ScanOptions", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT, + +        .tp_doc         = SCAN_OPTIONS_DOC, + +        .tp_methods     = py_scan_options_methods, +        .tp_getset      = py_scan_options_getseters, + +        .tp_init        = py_scan_options_init, +        .tp_new         = py_scan_options_new, + +    }; + +    return &py_scan_options_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide...scan.ScanOptions'.   * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_options_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'ScanOptions' */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_options_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan"); + +        dict = PyModule_GetDict(module); + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_OPTIONS, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en ensemble d'options d'analyses.         * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_options(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_options_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan options"); +            break; + +        case 1: +            *((GScanOptions **)dst) = G_SCAN_OPTIONS(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/options.h b/plugins/pychrysalide/analysis/scan/options.h new file mode 100644 index 0000000..3e83880 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/options.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * options.h - prototypes pour l'équivalent Python du fichier "analysis/scan/options.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_options_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanOptions'. */ +bool ensure_python_scan_options_is_registered(void); + +/* Tente de convertir en ensemble d'options d'analyses. */ +int convert_to_scan_options(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_OPTIONS_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am new file mode 100644 index 0000000..dd26fa5 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/Makefile.am @@ -0,0 +1,22 @@ + +noinst_LTLIBRARIES = libpychrysaanalysisscanpatterns.la + +libpychrysaanalysisscanpatterns_la_SOURCES = \ +	backend.h backend.c						\ +	modifier.h modifier.c					\ +	module.h module.c + +libpychrysaanalysisscanpatterns_la_LIBADD = \ +	backends/libpychrysaanalysisscanpatternsbackends.la \ +	modifiers/libpychrysaanalysisscanpatternsmodifiers.la + +libpychrysaanalysisscanpatterns_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +    $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libpychrysaanalysisscanpatterns_la_SOURCES:%c=) + + +SUBDIRS = backends modifiers diff --git a/plugins/pychrysalide/analysis/scan/patterns/backend.c b/plugins/pychrysalide/analysis/scan/patterns/backend.c new file mode 100644 index 0000000..03db143 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backend.c @@ -0,0 +1,202 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * backend.c - équivalent Python du fichier "analysis/scan/backend.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "backend.h" + + +#include <pygobject.h> + + +#include <analysis/scan/patterns/backend-int.h> + + +#include "../../../access.h" +#include "../../../helpers.h" + + + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(engine_backend, G_TYPE_ENGINE_BACKEND, NULL); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_engine_backend_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_engine_backend_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define ENGINE_BACKEND_DOC                                              \ +    "An *EngineBackend* object is the root class of all scan algorithm" \ +    " looking for data patterns." + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_engine_backend_type(void) +{ +    static PyMethodDef py_engine_backend_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_engine_backend_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_engine_backend_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.EngineBackend", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT, + +        .tp_doc         = ENGINE_BACKEND_DOC, + +        .tp_methods     = py_engine_backend_methods, +        .tp_getset      = py_engine_backend_getseters, + +        .tp_init        = py_engine_backend_init, +        .tp_new         = py_engine_backend_new, + +    }; + +    return &py_engine_backend_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....EngineBackend'.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_engine_backend_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'ScanNamespace' */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_engine_backend_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan"); + +        dict = PyModule_GetDict(module); + +        if (!register_class_for_pygobject(dict, G_TYPE_ENGINE_BACKEND, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en méthode de recherches.                 * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_engine_backend(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_engine_backend_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to engine backend"); +            break; + +        case 1: +            *((GEngineBackend **)dst) = G_ENGINE_BACKEND(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/backend.h b/plugins/pychrysalide/analysis/scan/patterns/backend.h new file mode 100644 index 0000000..6b1f4cd --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backend.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * backend.h - prototypes pour l'équivalent Python du fichier "analysis/scan/backend.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_engine_backend_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.EngineBackend'. */ +bool ensure_python_engine_backend_is_registered(void); + +/* Tente de convertir en méthode de recherches. */ +int convert_to_engine_backend(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_BACKEND_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am new file mode 100644 index 0000000..cccfc2d --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backends/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libpychrysaanalysisscanpatternsbackends.la + +libpychrysaanalysisscanpatternsbackends_la_SOURCES =		\ +	acism.h acism.c							\ +	bitap.h bitap.c							\ +	module.h module.c + +libpychrysaanalysisscanpatternsbackends_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libpychrysaanalysisscanpatternsbackends_la_SOURCES:%c=) diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c new file mode 100644 index 0000000..56d0b55 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.c @@ -0,0 +1,214 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * acism.c - équivalent Python du fichier "analysis/scan/patterns/backends/acism.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "acism.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/patterns/backends/acism-int.h> + + +#include "../backend.h" +#include "../../../../access.h" +#include "../../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(acism_backend, G_TYPE_ACISM_BACKEND); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_acism_backend_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_acism_backend_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define ACISM_BACKEND_DOC                                                   \ +    "A *AcismBackend* class provide an implementation of the Aho-Corasick"  \ +    " search algorithm with Interleaved State-transition Matrix (ACISM)."   \ +    "\n"                                                                    \ +    "Instances can be created using the following constructor:\n"           \ +    "\n"                                                                    \ +    "    AcismBackend()"                                                    \ +    "\n"                                                                    \ +    "See the relative white paper for more information:"                    \ +    " https://docs.google.com/document/d/1e9Qbn22__togYgQ7PNyCz3YzIIVPKvrf8PCrFa74IFM" + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_acism_backend_type(void) +{ +    static PyMethodDef py_acism_backend_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_acism_backend_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_acism_backend_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.backends.AcismBackend", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = ACISM_BACKEND_DOC, + +        .tp_methods     = py_acism_backend_methods, +        .tp_getset      = py_acism_backend_getseters, + +        .tp_init        = py_acism_backend_init, +        .tp_new         = py_acism_backend_new, + +    }; + +    return &py_acism_backend_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....AcismBackend'.      * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_acism_backend_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'AcismBackend'*/ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_acism_backend_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.backends"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_engine_backend_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_ACISM_BACKEND, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en méthode de recherche ACISM.            * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_acism_backend(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_acism_backend_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ACISM backend"); +            break; + +        case 1: +            *((GAcismBackend **)dst) = G_ACISM_BACKEND(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h new file mode 100644 index 0000000..9ed61fa --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backends/acism.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * acism.h - prototypes pour l'équivalent Python du fichier "analysis/scan/patterns/backends/acism.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_acism_backend_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.backends.AcismBackend'. */ +bool ensure_python_acism_backend_is_registered(void); + +/* Tente de convertir en méthode de recherche ACISM. */ +int convert_to_acism_backend(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_ACISM_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c new file mode 100644 index 0000000..c910f26 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.c @@ -0,0 +1,214 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bitap.c - équivalent Python du fichier "analysis/scan/patterns/backends/bitap.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "bitap.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/patterns/backends/bitap-int.h> + + +#include "../backend.h" +#include "../../../../access.h" +#include "../../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(bitap_backend, G_TYPE_BITAP_BACKEND); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_bitap_backend_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_bitap_backend_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define BITAP_BACKEND_DOC                                           \ +    "A *BitapBackend* class provide an implementation of the Bitap" \ +    " search algorithm."                                            \ +    "\n"                                                            \ +    "Instances can be created using the following constructor:\n"   \ +    "\n"                                                            \ +    "    BitapBackend()"                                            \ +    "\n"                                                            \ +    "See the relative white paper for more information:"            \ +    " https://en.wikipedia.org/wiki/Bitap_algorithm" + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_bitap_backend_type(void) +{ +    static PyMethodDef py_bitap_backend_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_bitap_backend_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_bitap_backend_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.backends.BitapBackend", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = BITAP_BACKEND_DOC, + +        .tp_methods     = py_bitap_backend_methods, +        .tp_getset      = py_bitap_backend_getseters, + +        .tp_init        = py_bitap_backend_init, +        .tp_new         = py_bitap_backend_new, + +    }; + +    return &py_bitap_backend_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....BitapBackend'.      * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_bitap_backend_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'BitapBackend'*/ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_bitap_backend_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.backends"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_engine_backend_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_BITAP_BACKEND, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en méthode de recherche BITAP.            * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_bitap_backend(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_bitap_backend_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Bitap backend"); +            break; + +        case 1: +            *((GBitapBackend **)dst) = G_BITAP_BACKEND(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h new file mode 100644 index 0000000..f7853d4 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backends/bitap.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bitap.h - prototypes pour l'équivalent Python du fichier "analysis/scan/patterns/backends/bitap.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_bitap_backend_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.backends.BitapBackend'. */ +bool ensure_python_bitap_backend_is_registered(void); + +/* Tente de convertir en méthode de recherche Bitap. */ +int convert_to_bitap_backend(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_BITAP_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/module.c b/plugins/pychrysalide/analysis/scan/patterns/backends/module.c new file mode 100644 index 0000000..f4a0293 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backends/module.c @@ -0,0 +1,106 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire backends en tant que module + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "module.h" + + +#include <assert.h> + + +#include "acism.h" +#include "bitap.h" +#include "../../../../helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : super = module dont la définition est à compléter.           * +*                                                                             * +*  Description : Ajoute le module 'analysis.....backends' à un module Python. * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool add_analysis_scan_patterns_backends_module(PyObject *super) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *module;                       /* Sous-module mis en place    */ + +#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_DOC                   \ +    "This module provide all the features useful for scanning"  \ +    " binary contents." + +    static PyModuleDef py_chrysalide_analysis_scan_patterns_backends_module = { + +        .m_base = PyModuleDef_HEAD_INIT, + +        .m_name = "pychrysalide.analysis.scan.patterns.backends", +        .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_DOC, + +        .m_size = -1, + +    }; + +    module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_backends_module); + +    result = (module != NULL); + +    if (!result) +        Py_XDECREF(module); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Intègre les objets du module 'analysis....patterns.backends'.* +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool populate_analysis_scan_patterns_backends_module(void) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    if (result) result = ensure_python_acism_backend_is_registered(); +    if (result) result = ensure_python_bitap_backend_is_registered(); + +    assert(result); + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/backends/module.h b/plugins/pychrysalide/analysis/scan/patterns/backends/module.h new file mode 100644 index 0000000..ab1aad5 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/backends/module.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire backends en tant que module + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'analysis.scan.patterns.backends' à un module Python. */ +bool add_analysis_scan_patterns_backends_module(PyObject *); + +/* Intègre les objets du module 'analysis.scan.patterns.backends'. */ +bool populate_analysis_scan_patterns_backends_module(void); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_BACKENDS_MODULE_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.c b/plugins/pychrysalide/analysis/scan/patterns/modifier.c new file mode 100644 index 0000000..6547d91 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.c @@ -0,0 +1,416 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * modifier.c - équivalent Python du fichier "analysis/scan/modifier.c" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "modifier.h" + + +#include <pygobject.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + +#include "../../../access.h" +#include "../../../helpers.h" + + + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_token_modifier, G_TYPE_SCAN_TOKEN_MODIFIER, NULL); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_token_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_token_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_TOKEN_MODIFIER_DOC                                     \ +    "An *TokenModifier* object is the root class of all modifiers"  \ +    " for byte patterns." + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = tampon de données à consulter.                        * +*                args = arguments fournis pour la conduite de l'opération.    * +*                                                                             * +*  Description : Transforme une séquence d'octets pour motif de recherche.    * +*                                                                             * +*  Retour      : Liste des nouvelle(s) séquence(s) d'octets obtenue(s).       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_token_modifier_transform(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Bilan à faire remonter      */ +    PyObject *py_src;                       /* Motifs Python en entrée     */ +    PyObject *py_arg;                       /* Eventuel paramètre de config*/ +    sized_binary_t src;                     /* Entrée au format adapté     */ +    Py_ssize_t len;                         /* Quantité de ces données     */ +    int ret;                                /* Bilan de lecture des args.  */ +    sized_binary_t *src_list;               /* Entrées au format adapté    */ +    size_t scount;                          /* Taille de cette liste       */ +    bool dyn_src;                           /* Allocation dynamique ?      */ +    Py_ssize_t size;                        /* Taille d'une séquence       */ +    Py_ssize_t k;                           /* Boucle de parcours #1       */ +    PyObject *item;                         /* Elément de liste de motifs  */ +    modifier_arg_t arg;                     /* Eventuelle précision        */ +    GScanTokenModifier *modifier;           /* Version native de l'instance*/ +    sized_binary_t *dest;                   /* Liste des nouvelles chaînes */ +    size_t dcount;                          /* Taille de cette liste       */ +    bool status;                            /* Bilan de l'opération        */ +    size_t i;                               /* Boucle de parcours #2       */ + +#define SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD PYTHON_METHOD_DEF      \ +(                                                                   \ +    transform, "$self, data, /, arg",                               \ +    METH_VARARGS, py_scan_token_modifier,                           \ +    "Transform data from a byte pattern for an incoming scan.\n"    \ +    "\n"                                                            \ +    "The data has to be provided as bytes.\n"                       \ +    "\n"                                                            \ +    "The method returns a tuple of transformed data as bytes, or"   \ +    " *None* in case of error."                                     \ +) + +    py_arg = NULL; + +    ret = PyArg_ParseTuple(args, "O|O", &py_src, &py_arg); +    if (!ret) return NULL; + +    /* Constitution des motifs d'entrée */ + +    if (PyBytes_Check(py_src)) +    { +        ret = PyBytes_AsStringAndSize(py_src, &src.data, &len); +        if (ret == -1) return NULL; + +        src.len = len; + +        src_list = &src; +        scount = 1; + +        dyn_src = false; + +    } + +    else if (PySequence_Check(py_src)) +    { +        size = PySequence_Size(py_src); + +        src_list = malloc(size * sizeof(sized_binary_t)); +        scount = size; + +        dyn_src = true; + +        for (k = 0; k < size; k++) +        { +            item = PySequence_ITEM(py_src, k); + +            if (PyBytes_Check(item)) +            { +                ret = PyBytes_AsStringAndSize(item, &src_list[k].data, &len); +                if (ret == -1) return NULL; + +                src_list[k].len = len; + +            } +            else +            { +                free(src_list); + +                PyErr_SetString(PyExc_TypeError, "lists of items other than bytes are not supported"); +                return NULL; +            } + +        } + +    } + +    else +    { +        PyErr_SetString(PyExc_TypeError, "only bytes and lists of bytes are expected as input for modifiers"); +        return NULL; +    } + +    /* Récupération d'une éventuelle précision opérationnelle */ + +    if (py_arg != NULL) +    { +        if (PyLong_Check(py_arg)) +        { +            arg.type = MAT_UNSIGNED_INTEGER; +            arg.value.u_integer = PyLong_AsUnsignedLongLong(py_arg); +        } + +        else +        { +            if (dyn_src) +                free(src_list); + +            PyErr_SetString(PyExc_TypeError, "unable to handle the argument type for calling a modifier"); +            return NULL; + +        } + +    } + +    /* Création des nouveaux motifs */ + +    modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self)); + +    if (py_arg == NULL) +        status = g_scan_token_modifier_transform(modifier, src_list, scount, &dest, &dcount); +    else +        status = g_scan_token_modifier_transform_with_arg(modifier, src_list, scount, &arg, &dest, &dcount); + +    if (dyn_src) +        free(src_list); + +    if (status) +    { +        result = PyTuple_New(dcount); + +        for (i = 0; i < dcount; i++) +        { +            PyTuple_SetItem(result, i, PyBytes_FromStringAndSize(dest[i].data, dest[i].len)); +            exit_szstr(&dest[i]); +        } + +        free(dest); + +    } + +    else +    { +        result = Py_None; +        Py_INCREF(result); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = classe représentant un composant nommé à manipuler.* +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Fournit le désignation associée à un composant nommé.        * +*                                                                             * +*  Retour      : Description courante.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_token_modifier_get_name(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Décompte à retourner        */ +    GScanTokenModifier *modifier;           /* Version native              */ +    char *name;                             /* Désignation à convertir     */ + +#define SCAN_TOKEN_MODIFIER_NAME_ATTRIB PYTHON_GET_DEF_FULL \ +(                                                           \ +    name, py_scan_token_modifier,                           \ +    "Call name for the modifier.\n"                         \ +    "\n"                                                    \ +    "The result is a string."                               \ +) + +    modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self)); + +    name = g_scan_token_modifier_get_name(modifier); + +    if (name == NULL) +    { +        result = Py_None; +        Py_INCREF(result); +    } +    else +    { +        result = PyUnicode_FromString(name); +        free(name); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_token_modifier_type(void) +{ +    static PyMethodDef py_scan_token_modifier_methods[] = { +        SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD, +        { NULL } +    }; + +    static PyGetSetDef py_scan_token_modifier_getseters[] = { +        SCAN_TOKEN_MODIFIER_NAME_ATTRIB, +        { NULL } +    }; + +    static PyTypeObject py_scan_token_modifier_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.TokenModifier", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_TOKEN_MODIFIER_DOC, + +        .tp_methods     = py_scan_token_modifier_methods, +        .tp_getset      = py_scan_token_modifier_getseters, + +        .tp_init        = py_scan_token_modifier_init, +        .tp_new         = py_scan_token_modifier_new, + +    }; + +    return &py_scan_token_modifier_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....TokenModifier'.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_token_modifier_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'TokenModifier' */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_token_modifier_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan"); + +        dict = PyModule_GetDict(module); + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_TOKEN_MODIFIER, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en transformation de séquence d'octets.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_token_modifier(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_token_modifier_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to token modifier"); +            break; + +        case 1: +            *((GScanTokenModifier **)dst) = G_SCAN_TOKEN_MODIFIER(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.h b/plugins/pychrysalide/analysis/scan/patterns/modifier.h new file mode 100644 index 0000000..770b2c1 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * modifier.h - prototypes pour l'équivalent Python du fichier "analysis/scan/modifier.h" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_token_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.TokenModifier'. */ +bool ensure_python_scan_token_modifier_is_registered(void); + +/* Tente de convertir en transformation de séquence d'octets. */ +int convert_to_scan_token_modifier(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_MODIFIER_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am new file mode 100644 index 0000000..ae53e45 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am @@ -0,0 +1,18 @@ + +noinst_LTLIBRARIES = libpychrysaanalysisscanpatternsmodifiers.la + +libpychrysaanalysisscanpatternsmodifiers_la_SOURCES = \ +	hex.h hex.c								\ +	list.h list.c							\ +	module.h module.c						\ +	plain.h plain.c							\ +	rev.h rev.c								\ +	xor.h xor.c + +libpychrysaanalysisscanpatternsmodifiers_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libpychrysaanalysisscanpatternsmodifiers_la_SOURCES:%c=) diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c new file mode 100644 index 0000000..503580d --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.c" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "hex.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/patterns/modifiers/hex.h> + + +#include "../modifier.h" +#include "../../../../access.h" +#include "../../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_hex_modifier, G_TYPE_SCAN_HEX_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_hex_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_hex_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_HEX_MODIFIER_DOC                                               \ +    "The *HexModifier* class transforms a byte pattern into its"            \ +    " corresponding byte sequence in lower case."                           \ +    "\n"                                                                    \ +    "Instances can be created using the following constructor:\n"           \ +    "\n"                                                                    \ +    "    HexModifier()" + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_hex_modifier_type(void) +{ +    static PyMethodDef py_scan_hex_modifier_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_scan_hex_modifier_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_scan_hex_modifier_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.HexModifier", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_HEX_MODIFIER_DOC, + +        .tp_methods     = py_scan_hex_modifier_methods, +        .tp_getset      = py_scan_hex_modifier_getseters, + +        .tp_init        = py_scan_hex_modifier_init, +        .tp_new         = py_scan_hex_modifier_new, + +    }; + +    return &py_scan_hex_modifier_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....HexModifier'.       * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_hex_modifier_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'HexModifier'   */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_hex_modifier_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_scan_token_modifier_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_HEX_MODIFIER, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en transmission d'octets à l'identique.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_hex_modifier(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_hex_modifier_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to hex modifier"); +            break; + +        case 1: +            *((GScanHexModifier **)dst) = G_SCAN_HEX_MODIFIER(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h new file mode 100644 index 0000000..5d70a01 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * hex.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.h" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_hex_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.HexModifier'. */ +bool ensure_python_scan_hex_modifier_is_registered(void); + +/* Tente de convertir en transmission d'octets à l'identique. */ +int convert_to_scan_hex_modifier(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c new file mode 100644 index 0000000..7c77d63 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.c @@ -0,0 +1,320 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * list.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/list.c" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "list.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/patterns/modifiers/list.h> + + +#include "../modifier.h" +#include "../../../../access.h" +#include "../../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_modifier_list, G_TYPE_SCAN_MODIFIER_LIST); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_modifier_list_init(PyObject *, PyObject *, PyObject *); + +/* Intègre un nouveau transformateur dans une liste. */ +static PyObject *py_scan_modifier_list_add(PyObject *, PyObject *); + +/* Fournit les transformateurs associés à la liste. */ +static PyObject *py_scan_modifier_list_get_modifiers(PyObject *, void *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_modifier_list_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_MODIFIER_LIST_DOC                                              \ +    "The *ModifierList* class is a special modifier which groups a list of" \ +    " modifiers for byte patterns."                                         \ +    "\n"                                                                    \ +    "Instances can be created using the following constructor:\n"           \ +    "\n"                                                                    \ +    "    ModifierList()"                                                    \ +    "\n"                                                                    \ +    "The keyword for such a modifier is *(list)*." + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = projet d'étude à manipuler.                           * +*                args = arguments accompagnant l'appel.                       * +*                                                                             * +*  Description : Intègre un nouveau transformateur dans une liste.            * +*                                                                             * +*  Retour      : Bilan de l'ajout : False si un élément similaire est déjà là.* +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_modifier_list_add(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Absence de retour Python    */ +    GScanTokenModifier *modifier;           /* Modificateur à intégrer     */ +    int ret;                                /* Bilan de lecture des args.  */ +    GScanModifierList *list;                /* Version GLib du type        */ +    bool status;                            /* Bilan de l'opération        */ + +#define SCAN_MODIFIER_LIST_ADD_METHOD PYTHON_METHOD_DEF                     \ +(                                                                           \ +    add, "$self, modifier, /",                                              \ +    METH_VARARGS, py_scan_modifier_list,                                    \ +    "Add an extra modifier to the list.\n"                                  \ +    "\n"                                                                    \ +    "This *modifier* parameter has to be a"                                 \ +    " pychrysalide.analysis.scan.patterns.TokenModifier instance."          \ +    "\n"                                                                    \ +    "The function returns *True* if the provided modifier did not already"  \ +    " exist in the list, *False* otherwise."                                \ +) + +    ret = PyArg_ParseTuple(args, "O&", convert_to_scan_token_modifier, &modifier); +    if (!ret) return NULL; + +    list = G_SCAN_MODIFIER_LIST(pygobject_get(self)); + +    status = g_scan_modifier_list_add(list, modifier); + +    result = status ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Fournit les transformateurs associés à la liste.             * +*                                                                             * +*  Retour      : Liste de modificateurs de séquence d'octets.                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_modifier_list_get_modifiers(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Résultat à retourner        */ +    GScanModifierList *list;                /* Version GLib du type        */ +    size_t count;                           /* Nombre de transformateurs   */ +    size_t i;                               /* Boucle de parcours          */ +    GScanTokenModifier *modifier;           /* Modificateur de la liste    */ + +#define SCAN_MODIFIER_LIST_MODIFIERS_ATTRIB PYTHON_GET_DEF_FULL                             \ +(                                                                                           \ +    modifiers, py_scan_modifier_list,                                                       \ +    "List of all modifiers contained in a list.\n"                                          \ +    "\n"                                                                                    \ +    "The returned value is a tuple of pychrysalide.analysis.scan.patterns.TokenModifier"    \ +    " instances."                                                                           \ +) + +    list = G_SCAN_MODIFIER_LIST(pygobject_get(self)); + +    count = g_scan_modifier_list_count(list); + +    result = PyTuple_New(count); + +    for (i = 0; i < count; i++) +    { +        modifier = g_scan_modifier_list_get(list, i); + +        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(modifier))); + +        g_object_unref(modifier); + +    } + +    return result; + +} + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_modifier_list_type(void) +{ +    static PyMethodDef py_scan_modifier_list_methods[] = { +        SCAN_MODIFIER_LIST_ADD_METHOD, +        { NULL } +    }; + +    static PyGetSetDef py_scan_modifier_list_getseters[] = { +        SCAN_MODIFIER_LIST_MODIFIERS_ATTRIB, +        { NULL } +    }; + +    static PyTypeObject py_scan_modifier_list_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.ModifierList", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_MODIFIER_LIST_DOC, + +        .tp_methods     = py_scan_modifier_list_methods, +        .tp_getset      = py_scan_modifier_list_getseters, + +        .tp_init        = py_scan_modifier_list_init, +        .tp_new         = py_scan_modifier_list_new, + +    }; + +    return &py_scan_modifier_list_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....ModifierList'.      * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_modifier_list_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'ModifierList'  */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_modifier_list_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_scan_token_modifier_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_MODIFIER_LIST, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en liste de transormations d'octets.      * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_modifier_list(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_modifier_list_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to modifier list"); +            break; + +        case 1: +            *((GScanModifierList **)dst) = G_SCAN_MODIFIER_LIST(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h new file mode 100644 index 0000000..133de8d --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/list.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * list.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/list.h" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_modifier_list_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.ModifierList'. */ +bool ensure_python_scan_modifier_list_is_registered(void); + +/* Tente de convertir en liste de transormations d'octets. */ +int convert_to_scan_modifier_list(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_LIST_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c new file mode 100644 index 0000000..ae450dc --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c @@ -0,0 +1,112 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire modifiers en tant que module + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "module.h" + + +#include <assert.h> + + +#include "hex.h" +#include "list.h" +#include "plain.h" +#include "rev.h" +#include "xor.h" +#include "../../../../helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : super = module dont la définition est à compléter.           * +*                                                                             * +*  Description : Ajoute le module 'analysis....modifiers' à un module Python. * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool add_analysis_scan_patterns_modifiers_module(PyObject *super) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *module;                       /* Sous-module mis en place    */ + +#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_DOC    \ +    "This module provide all the features useful for scanning"      \ +    " binary contents." + +    static PyModuleDef py_chrysalide_analysis_scan_patterns_modifiers_module = { + +        .m_base = PyModuleDef_HEAD_INIT, + +        .m_name = "pychrysalide.analysis.scan.patterns.modifiers", +        .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_DOC, + +        .m_size = -1, + +    }; + +    module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_modifiers_module); + +    result = (module != NULL); + +    if (!result) +        Py_XDECREF(module); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Intègre les objets du module 'analysis...patterns.modifiers'.* +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool populate_analysis_scan_patterns_modifiers_module(void) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    if (result) result = ensure_python_scan_hex_modifier_is_registered(); +    if (result) result = ensure_python_scan_modifier_list_is_registered(); +    if (result) result = ensure_python_scan_plain_modifier_is_registered(); +    if (result) result = ensure_python_scan_reverse_modifier_is_registered(); +    if (result) result = ensure_python_scan_xor_modifier_is_registered(); + +    assert(result); + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h new file mode 100644 index 0000000..8094efc --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire modifiers en tant que module + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'analysis.scan.patterns.modifiers' à un module Python. */ +bool add_analysis_scan_patterns_modifiers_module(PyObject *); + +/* Intègre les objets du module 'analysis.scan.patterns.modifiers'. */ +bool populate_analysis_scan_patterns_modifiers_module(void); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_MODULE_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c new file mode 100644 index 0000000..7a260c1 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * plain.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/plain.c" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "plain.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/patterns/modifiers/plain.h> + + +#include "../modifier.h" +#include "../../../../access.h" +#include "../../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_plain_modifier, G_TYPE_SCAN_PLAIN_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_plain_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_plain_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_PLAIN_MODIFIER_DOC                                             \ +    "The *PlainModifier* class provide an transmision of a byte pattern"    \ +    " without any modification."                                            \ +    "\n"                                                                    \ +    "Instances can be created using the following constructor:\n"           \ +    "\n"                                                                    \ +    "    PlainModifier()" + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_plain_modifier_type(void) +{ +    static PyMethodDef py_scan_plain_modifier_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_scan_plain_modifier_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_scan_plain_modifier_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.PlainModifier", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_PLAIN_MODIFIER_DOC, + +        .tp_methods     = py_scan_plain_modifier_methods, +        .tp_getset      = py_scan_plain_modifier_getseters, + +        .tp_init        = py_scan_plain_modifier_init, +        .tp_new         = py_scan_plain_modifier_new, + +    }; + +    return &py_scan_plain_modifier_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....PlainModifier'.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_plain_modifier_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'PlainModifier' */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_plain_modifier_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_scan_token_modifier_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_PLAIN_MODIFIER, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en transmission d'octets à l'identique.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_plain_modifier(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_plain_modifier_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to plain modifier"); +            break; + +        case 1: +            *((GScanPlainModifier **)dst) = G_SCAN_PLAIN_MODIFIER(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h new file mode 100644 index 0000000..03949d8 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/plain.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * plain.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/plain.h" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_plain_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.PlainModifier'. */ +bool ensure_python_scan_plain_modifier_is_registered(void); + +/* Tente de convertir en transmission d'octets à l'identique. */ +int convert_to_scan_plain_modifier(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c new file mode 100644 index 0000000..841e929 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.c" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "rev.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/patterns/modifiers/rev.h> + + +#include "../modifier.h" +#include "../../../../access.h" +#include "../../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_reverse_modifier, G_TYPE_SCAN_REVERSE_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_reverse_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_reverse_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_HEX_MODIFIER_DOC                                               \ +    "The *ReverseModifier* class transforms a byte pattern by reversing"    \ +    " the order of each bytes."                                             \ +    "\n"                                                                    \ +    "Instances can be created using the following constructor:\n"           \ +    "\n"                                                                    \ +    "    ReverseModifier()" + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_reverse_modifier_type(void) +{ +    static PyMethodDef py_scan_reverse_modifier_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_scan_reverse_modifier_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_scan_reverse_modifier_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.ReverseModifier", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_HEX_MODIFIER_DOC, + +        .tp_methods     = py_scan_reverse_modifier_methods, +        .tp_getset      = py_scan_reverse_modifier_getseters, + +        .tp_init        = py_scan_reverse_modifier_init, +        .tp_new         = py_scan_reverse_modifier_new, + +    }; + +    return &py_scan_reverse_modifier_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....ReverseModifier'.   * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_reverse_modifier_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python ReverseModifier */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_reverse_modifier_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_scan_token_modifier_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REVERSE_MODIFIER, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en transformation d'octets par inverse.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_reverse_modifier(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_reverse_modifier_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to reverse modifier"); +            break; + +        case 1: +            *((GScanReverseModifier **)dst) = G_SCAN_REVERSE_MODIFIER(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h new file mode 100644 index 0000000..fe10e1e --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * rev.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/rev.h" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_reverse_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.ReverseModifier'. */ +bool ensure_python_scan_reverse_modifier_is_registered(void); + +/* Tente de convertir en transformation d'octets par inverse. */ +int convert_to_scan_reverse_modifier(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c new file mode 100644 index 0000000..17a32f4 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c @@ -0,0 +1,210 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * xor.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/xor.c" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "xor.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/patterns/modifiers/xor.h> + + +#include "../modifier.h" +#include "../../../../access.h" +#include "../../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_xor_modifier, G_TYPE_SCAN_XOR_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_xor_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_xor_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    int ret;                                /* Bilan de lecture des args.  */ + +#define SCAN_XOR_MODIFIER_DOC                                               \ +    "The *XorModifier* class transforms a byte pattern by XORing bytes.\n"  \ +    "\n"                                                                    \ +    "Instances can be created using the following constructor:\n"           \ +    "\n"                                                                    \ +    "    XorModifier()" + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_xor_modifier_type(void) +{ +    static PyMethodDef py_scan_xor_modifier_methods[] = { +        { NULL } +    }; + +    static PyGetSetDef py_scan_xor_modifier_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_scan_xor_modifier_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.patterns.modifiers.XorModifier", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_XOR_MODIFIER_DOC, + +        .tp_methods     = py_scan_xor_modifier_methods, +        .tp_getset      = py_scan_xor_modifier_getseters, + +        .tp_init        = py_scan_xor_modifier_init, +        .tp_new         = py_scan_xor_modifier_new, + +    }; + +    return &py_scan_xor_modifier_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide....XorModifier'.   * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_xor_modifier_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python XorModifier */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_xor_modifier_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + +        dict = PyModule_GetDict(module); + +        if (!ensure_python_scan_token_modifier_is_registered()) +            return false; + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_XOR_MODIFIER, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en transformation d'octets par inverse.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_xor_modifier(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_xor_modifier_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to XOR modifier"); +            break; + +        case 1: +            *((GScanXorModifier **)dst) = G_SCAN_XOR_MODIFIER(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h new file mode 100644 index 0000000..7b9bb69 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * xor.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/xor.h" + * + * Copyright (C) 2023 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_xor_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.XorModifier'. */ +bool ensure_python_scan_xor_modifier_is_registered(void); + +/* Tente de convertir en transformation d'octets par inverse. */ +int convert_to_scan_xor_modifier(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.c b/plugins/pychrysalide/analysis/scan/patterns/module.c new file mode 100644 index 0000000..123b23a --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/module.c @@ -0,0 +1,114 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire patterns en tant que module + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "module.h" + + +#include <assert.h> + + +#include "backend.h" +#include "modifier.h" +#include "backends/module.h" +#include "modifiers/module.h" +#include "../../../helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : super = module dont la définition est à compléter.           * +*                                                                             * +*  Description : Ajoute le module 'analysis.scan.patterns' à un module Python.* +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool add_analysis_scan_patterns_module(PyObject *super) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *module;                       /* Sous-module mis en place    */ + +#define PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_DOC                   \ +    "This module provide all the features useful for scanning"  \ +    " binary contents." + +    static PyModuleDef py_chrysalide_analysis_scan_patterns_module = { + +        .m_base = PyModuleDef_HEAD_INIT, + +        .m_name = "pychrysalide.analysis.scan.patterns", +        .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_DOC, + +        .m_size = -1, + +    }; + +    module = build_python_module(super, &py_chrysalide_analysis_scan_patterns_module); + +    result = (module != NULL); + +    if (result) result = add_analysis_scan_patterns_backends_module(module); +    if (result) result = add_analysis_scan_patterns_modifiers_module(module); + +    if (!result) +        Py_XDECREF(module); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Intègre les objets du module 'analysis.scan.patterns'.       * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool populate_analysis_scan_patterns_module(void) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    if (result) result = ensure_python_engine_backend_is_registered(); +    if (result) result = ensure_python_scan_token_modifier_is_registered(); + +    if (result) result = populate_analysis_scan_patterns_backends_module(); +    if (result) result = populate_analysis_scan_patterns_modifiers_module(); + +    assert(result); + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/module.h b/plugins/pychrysalide/analysis/scan/patterns/module.h new file mode 100644 index 0000000..bc25129 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/module.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire patterns en tant que module + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'analysis.scan.patterns' à un module Python. */ +bool add_analysis_scan_patterns_module(PyObject *); + +/* Intègre les objets du module 'analysis.scan.patterns'. */ +bool populate_analysis_scan_patterns_module(void); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODULE_H */ diff --git a/plugins/pychrysalide/analysis/scan/scanner.c b/plugins/pychrysalide/analysis/scan/scanner.c new file mode 100644 index 0000000..bc58c9a --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/scanner.c @@ -0,0 +1,487 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * scanner.c - équivalent Python du fichier "analysis/scan/scanner.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "scanner.h" + + +#include <malloc.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/content.h> +#include <analysis/scan/context.h> +#include <analysis/scan/scanner-int.h> + + +#include "context.h" +#include "options.h" +#include "../content.h" +#include "../../access.h" +#include "../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(content_scanner, G_TYPE_CONTENT_SCANNER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_content_scanner_init(PyObject *, PyObject *, PyObject *); + +/* Lance une analyse d'un contenu binaire. */ +static PyObject *py_content_scanner_analyze(PyObject *, PyObject *); + +/* Convertit un gestionnaire de recherches en JSON. */ +static PyObject *py_content_scanner_convert_to_json(PyObject *, PyObject *); + +/* Indique le chemin d'un éventuel fichier de source. */ +static PyObject *py_content_scanner_get_filename(PyObject *, void *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_content_scanner_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    const char *text;                       /* Contenu de règles à traiter */ +    Py_ssize_t len;                         /* Taille de ce nom            */ +    const char *filename;                   /* Fichier de définitions      */ +    int ret;                                /* Bilan de lecture des args.  */ +    GContentScanner *scanner;               /* Création GLib à transmettre */ + +    static char *kwlist[] = { "text", "filename", NULL }; + +#define CONTENT_SCANNER_DOC                                         \ +    "A ContentScanner object provides support for rules processing" \ +    " against binary contents.\n"                                   \ +    "\n"                                                            \ +    "Instances can be created using one of the following"           \ +    " constructors:\n"                                              \ +    "\n"                                                            \ +    "    ContentScanner(text=str)"                                  \ +    "\n"                                                            \ +    "    ContentScanner(filename=str)"                              \ +    "\n"                                                            \ +    "Where *text* is a string for the rules definitions and"        \ +    " *filename* an alternative string for a path pointing to a"    \ +    " definition file." + +    /* Récupération des paramètres */ + +    text = NULL; +    len = 0; +    filename = NULL; + +    ret = PyArg_ParseTupleAndKeywords(args, kwds, "|s#s", kwlist, &text, &len, &filename); +    if (!ret) return -1; + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    /* Eléments de base */ + +    scanner = G_CONTENT_SCANNER(pygobject_get(self)); + +    if (text != NULL) +    { +        if (!g_content_scanner_create_from_text(scanner, text, len)) +        { +            PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner.")); +            return -1; +        } + +    } + +    else if (filename != NULL) +    { +        if (!g_content_scanner_create_from_file(scanner, filename)) +        { +            PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner.")); +            return -1; +        } + +    } + +    else +    { +        PyErr_SetString(PyExc_ValueError, _("Unable to create empty content scanner.")); +        return -1; +    } + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = classe représentant un format.                        * +*                args = arguments fournis à l'appel.                          * +*                                                                             * +*  Description : Lance une analyse d'un contenu binaire.                      * +*                                                                             * +*  Retour      : Contexte de suivi pour l'analyse menée.                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_content_scanner_analyze(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Contexte de suivi à renvoyer*/ +    GScanOptions *options;                  /* Paramètres d'analyse        */ +    GBinContent *content;                   /* Contenu binaire à traiter   */ +    int ret;                                /* Bilan de lecture des args.  */ +    GContentScanner *scanner;               /* Encadrement de recherche    */ +    GScanContext *context;                  /* Contexte de suivi           */ + +#define CONTENT_SCANNER_ANALYZE_METHOD PYTHON_METHOD_DEF            \ +(                                                                   \ +    analyze, "$self, options, content, /",                          \ +    METH_VARARGS, py_content_scanner,                               \ +    "Run a scan against a binary content.\n"                        \ +    "\n"                                                            \ +    "The *content* argument is a pychrysalide.analysis.BinContent"  \ +    " object pointing to data to analyze.\n"                        \ +    "\n"                                                            \ +    "The method returns a pychrysalide.analysis.scan.ScanContext"   \ +    " object tracking all the scan results."                        \ +) + +    ret = PyArg_ParseTuple(args, "O&O&", convert_to_scan_options, &options, convert_to_binary_content, &content); +    if (!ret) return NULL; + +    scanner = G_CONTENT_SCANNER(pygobject_get(self)); + +    context = g_content_scanner_analyze(scanner, options, content); + +    result = pygobject_new(G_OBJECT(context)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = classe représentant un format.                        * +*                args = arguments fournis à l'appel.                          * +*                                                                             * +*  Description : Convertit un gestionnaire de recherches en texte.            * +*                                                                             * +*  Retour      : Données textuelles ou None en cas d'erreur.                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_content_scanner_convert_to_text(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Contexte de suivi à renvoyer*/ +    GScanContext *context;                  /* Contexte d'analyse          */ +    int ret;                                /* Bilan de lecture des args.  */ +    GContentScanner *scanner;               /* Encadrement de recherche    */ +    char *out;                              /* Données en sortie           */ + +#define CONTENT_SCANNER_CONVERT_TO_TEXT_METHOD PYTHON_METHOD_DEF            \ +(                                                                           \ +    convert_to_text, "$self, context, /",                                   \ +    METH_VARARGS, py_content_scanner,                                       \ +    "Output a scan results as text.\n"                                      \ +    "\n"                                                                    \ +    "The *context* argument is a pychrysalide.analysis.scan.ScanContext"    \ +    " instance provided by a previous call to *self.analyze()*. This"       \ +    " context stores all the scan results.\n"                               \ +    "\n"                                                                    \ +    "The method returns a string value, or *None* in case of failure."      \ +) + +    ret = PyArg_ParseTuple(args, "O&", convert_to_scan_context, &context); +    if (!ret) return NULL; + +    scanner = G_CONTENT_SCANNER(pygobject_get(self)); + +    out = g_content_scanner_convert_to_text(scanner, context); + +    if (out != NULL) +    { +        result = PyUnicode_FromString(out); +        free(out); +    } +    else +    { +        result = Py_None; +        Py_INCREF(result); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = classe représentant un format.                        * +*                args = arguments fournis à l'appel.                          * +*                                                                             * +*  Description : Convertit un gestionnaire de recherches en JSON.             * +*                                                                             * +*  Retour      : Données textuelles au format JSON ou None en cas d'erreur.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_content_scanner_convert_to_json(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Contexte de suivi à renvoyer*/ +    GScanContext *context;                  /* Contexte d'analyse          */ +    int ret;                                /* Bilan de lecture des args.  */ +    GContentScanner *scanner;               /* Encadrement de recherche    */ +    char *out;                              /* Données en sortie           */ + +#define CONTENT_SCANNER_CONVERT_TO_JSON_METHOD PYTHON_METHOD_DEF            \ +(                                                                           \ +    convert_to_json, "$self, context, /",                                   \ +    METH_VARARGS, py_content_scanner,                                       \ +    "Output a scan results as JSON data.\n"                                 \ +    "\n"                                                                    \ +    "The *context* argument is a pychrysalide.analysis.scan.ScanContext"    \ +    " instance provided by a previous call to *self.analyze()*. This"       \ +    " context stores all the scan results.\n"                               \ +    "\n"                                                                    \ +    "The method returns JSON data as a string value, or *None* in case"     \ +    " of failure."                                                          \ +) + +    ret = PyArg_ParseTuple(args, "O&", convert_to_scan_context, &context); +    if (!ret) return NULL; + +    scanner = G_CONTENT_SCANNER(pygobject_get(self)); + +    out = g_content_scanner_convert_to_json(scanner, context); + +    if (out != NULL) +    { +        result = PyUnicode_FromString(out); +        free(out); +    } +    else +    { +        result = Py_None; +        Py_INCREF(result); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Indique le chemin d'un éventuel fichier de source.           * +*                                                                             * +*  Retour      : Chemin d'un éventuel fichier de définitions ou NULL.         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_content_scanner_get_filename(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Valeur à retourner          */ +    GContentScanner *scanner;               /* Analyseur à consulter       */ +    const char *filename;                   /* Chemin d'accès à transmettre*/ + +#define CONTENT_SCANNER_FILENAME_ATTRIB PYTHON_GET_DEF_FULL     \ +(                                                               \ +    filename, py_content_scanner,                               \ +    "Provide the access path to the source file of the rules'"  \ +    " definition, or *None* if these rules have not been loaded"\ +    " from memory."                                             \ +) + +    scanner = G_CONTENT_SCANNER(pygobject_get(self)); + +    filename = g_content_scanner_get_filename(scanner); + +    if (filename != NULL) +        result = PyUnicode_FromString(filename); + +    else +    { +        result = Py_None; +        Py_INCREF(result); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_content_scanner_type(void) +{ +    static PyMethodDef py_content_scanner_methods[] = { +        CONTENT_SCANNER_ANALYZE_METHOD, +        CONTENT_SCANNER_CONVERT_TO_TEXT_METHOD, +        CONTENT_SCANNER_CONVERT_TO_JSON_METHOD, +        { NULL } +    }; + +    static PyGetSetDef py_content_scanner_getseters[] = { +        CONTENT_SCANNER_FILENAME_ATTRIB, +        { NULL } +    }; + +    static PyTypeObject py_content_scanner_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.ContentScanner", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = CONTENT_SCANNER_DOC, + +        .tp_methods     = py_content_scanner_methods, +        .tp_getset      = py_content_scanner_getseters, + +        .tp_init        = py_content_scanner_init, +        .tp_new         = py_content_scanner_new, + +    }; + +    return &py_content_scanner_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide...scan.ContentScanner. * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_content_scanner_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'ContentScanner'*/ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_content_scanner_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan"); + +        dict = PyModule_GetDict(module); + +        if (!register_class_for_pygobject(dict, G_TYPE_CONTENT_SCANNER, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en scanner de contenus binaires.          * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_content_scanner(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_content_scanner_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to content scanner"); +            break; + +        case 1: +            *((GContentScanner **)dst) = G_CONTENT_SCANNER(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/scanner.h b/plugins/pychrysalide/analysis/scan/scanner.h new file mode 100644 index 0000000..b3b1baf --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/scanner.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * scanner.h - prototypes pour l'équivalent Python du fichier "analysis/scan/scanner.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_content_scanner_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.ContentScanner'. */ +bool ensure_python_content_scanner_is_registered(void); + +/* Tente de convertir en scanner de contenus binaires. */ +int convert_to_content_scanner(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SCANNER_H */ diff --git a/plugins/pychrysalide/analysis/scan/space.c b/plugins/pychrysalide/analysis/scan/space.c new file mode 100644 index 0000000..6ea87b8 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/space.c @@ -0,0 +1,283 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * space.c - équivalent Python du fichier "analysis/scan/space.c" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "space.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/content.h> +#include <analysis/scan/item.h> +#include <analysis/scan/space-int.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/content.h> + + +#include "item.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_namespace, G_TYPE_SCAN_NAMESPACE); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_namespace_init(PyObject *, PyObject *, PyObject *); + +/* Intègre un nouvel élément dans l'esapce de noms. */ +static PyObject *py_scan_namespace_register_item(PyObject *, PyObject *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet à initialiser (théoriquement).                  * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Initialise une instance sur la base du dérivé de GObject.    * +*                                                                             * +*  Retour      : 0.                                                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_scan_namespace_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +    const char *name;                       /* Désignation de l'espace     */ +    int ret;                                /* Bilan de lecture des args.  */ +    GScanNamespace *space;                  /* Création GLib à transmettre */ + +#define SCAN_NAMESPACE_DOC                                              \ +    "ScanNamespace defines a group of properties and functions for a"   \ +    " given scan theme.\n"                                              \ +    "\n"                                                                \ +    "Instances can be created using the following constructor:\n"       \ +    "\n"                                                                \ +    "    ScanNamespace(name)"                                           \ +    "\n"                                                                \ +    "Where *name* is a string providing the name of the new namespace." + +    /* Récupération des paramètres */ + +    ret = PyArg_ParseTuple(args, "s", &name); +    if (!ret) return -1; + +    /* Initialisation d'un objet GLib */ + +    ret = forward_pygobjet_init(self); +    if (ret == -1) return -1; + +    /* Elément de base */ + +    space = G_SCAN_NAMESPACE(pygobject_get(self)); + +    if (!g_scan_namespace_create(space, name)) +    { +        PyErr_SetString(PyExc_ValueError, _("Unable to create scan namespace.")); +        return -1; +    } + +    return 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = objet représentant une table de chaînes.              * +*                args = arguments fournis pour l'opération.                   * +*                                                                             * +*  Description : Intègre un nouvel élément dans l'esapce de noms.             * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_scan_namespace_register_item(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Bilan à retourner           */ +    GScanRegisteredItem *item;              /* Elément d'évaluation à lier */ +    int ret;                                /* Bilan de lecture des args.  */ +    GScanNamespace *space;                  /* Version native              */ +    bool status;                            /* Bilan de l'opération        */ + +#define SCAN_NAMESPACE_REGISTER_ITEM_METHOD PYTHON_METHOD_DEF                   \ +(                                                                               \ +    register_item, "$self, item, /",                                            \ +    METH_VARARGS, py_scan_namespace,                                            \ +    "Include an item into a namespace.\n"                                       \ +    "\n"                                                                        \ +    "The *item* argument has to be a pychrysalide.analysis.scan.RegisteredItem" \ +    " instance.\n"                                                              \ +    "\n"                                                                        \ +    "The function returns a boolean value translating the operation status:"    \ +    " *True* in case of success, *False* for a failure.\n"                      \ +) + +    ret = PyArg_ParseTuple(args, "O&", convert_to_scan_registered_item, &item); +    if (!ret) return NULL; + +    space = G_SCAN_NAMESPACE(pygobject_get(self)); + +    status = g_scan_namespace_register_item(space, item); + +    result = status ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_scan_namespace_type(void) +{ +    static PyMethodDef py_scan_namespace_methods[] = { +        SCAN_NAMESPACE_REGISTER_ITEM_METHOD, +        { NULL } +    }; + +    static PyGetSetDef py_scan_namespace_getseters[] = { +        { NULL } +    }; + +    static PyTypeObject py_scan_namespace_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.analysis.scan.ScanNamespace", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + +        .tp_doc         = SCAN_NAMESPACE_DOC, + +        .tp_methods     = py_scan_namespace_methods, +        .tp_getset      = py_scan_namespace_getseters, + +        .tp_init        = py_scan_namespace_init, +        .tp_new         = py_scan_namespace_new, + +    }; + +    return &py_scan_namespace_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide...scan.ScanNamespace'. * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool ensure_python_scan_namespace_is_registered(void) +{ +    PyTypeObject *type;                     /* Type Python 'ScanNamespace' */ +    PyObject *module;                       /* Module à recompléter        */ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_scan_namespace_type(); + +    if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) +    { +        module = get_access_to_python_module("pychrysalide.analysis.scan"); + +        dict = PyModule_GetDict(module); + +        if (!register_class_for_pygobject(dict, G_TYPE_SCAN_NAMESPACE, type)) +            return false; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en espace de noms pour scan.              * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_scan_namespace(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_namespace_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan namespace"); +            break; + +        case 1: +            *((GScanNamespace **)dst) = G_SCAN_NAMESPACE(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/space.h b/plugins/pychrysalide/analysis/scan/space.h new file mode 100644 index 0000000..0166c04 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/space.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * space.h - prototypes pour l'équivalent Python du fichier "analysis/scan/space.h" + * + * Copyright (C) 2022 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_namespace_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanNamespace'. */ +bool ensure_python_scan_namespace_is_registered(void); + +/* Tente de convertir en espace de noms pour scan. */ +int convert_to_scan_namespace(PyObject *, void *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_SPACE_H */ diff --git a/plugins/pychrysalide/analysis/storage/Makefile.am b/plugins/pychrysalide/analysis/storage/Makefile.am index fdf2666..d0a4df4 100644 --- a/plugins/pychrysalide/analysis/storage/Makefile.am +++ b/plugins/pychrysalide/analysis/storage/Makefile.am @@ -9,19 +9,10 @@ libpychrysaanalysisstorage_la_SOURCES =		\  	storage.h storage.c						\  	tpmem.h tpmem.c -libpychrysaanalysisstorage_la_LIBADD =  - -libpychrysaanalysisstorage_la_LDFLAGS =  +libpychrysaanalysisstorage_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT  devdir = $(includedir)/chrysalide/$(subdir)  dev_HEADERS = $(libpychrysaanalysisstorage_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - -SUBDIRS =  diff --git a/plugins/pychrysalide/analysis/storage/cache.c b/plugins/pychrysalide/analysis/storage/cache.c index 9859623..8cd5bac 100644 --- a/plugins/pychrysalide/analysis/storage/cache.c +++ b/plugins/pychrysalide/analysis/storage/cache.c @@ -100,7 +100,7 @@ static PyObject *py_object_cache_new(PyTypeObject *type, PyObject *args, PyObjec      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -304,7 +304,7 @@ bool ensure_python_object_cache_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_CACHE, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_CACHE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/storage/storage.c b/plugins/pychrysalide/analysis/storage/storage.c index 7c03be0..c54fe0f 100644 --- a/plugins/pychrysalide/analysis/storage/storage.c +++ b/plugins/pychrysalide/analysis/storage/storage.c @@ -115,7 +115,7 @@ static PyObject *py_object_storage_new(PyTypeObject *type, PyObject *args, PyObj      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -601,7 +601,7 @@ bool ensure_python_object_storage_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_STORAGE, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_STORAGE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/storage/tpmem.c b/plugins/pychrysalide/analysis/storage/tpmem.c index 491ee68..ae07008 100644 --- a/plugins/pychrysalide/analysis/storage/tpmem.c +++ b/plugins/pychrysalide/analysis/storage/tpmem.c @@ -108,7 +108,7 @@ static PyObject *py_type_memory_new(PyTypeObject *type, PyObject *args, PyObject      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -453,7 +453,7 @@ bool ensure_python_type_memory_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_TYPE_MEMORY, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_TYPE_MEMORY, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/type.c b/plugins/pychrysalide/analysis/type.c index 357d381..ea8affd 100644 --- a/plugins/pychrysalide/analysis/type.c +++ b/plugins/pychrysalide/analysis/type.c @@ -158,7 +158,7 @@ static PyObject *py_data_type_new(PyTypeObject *type, PyObject *args, PyObject *      if (first_time)      { -        status = register_class_for_dynamic_pygobject(gtype, type, base); +        status = register_class_for_dynamic_pygobject(gtype, type);          if (!status)          { @@ -1125,7 +1125,7 @@ bool ensure_python_data_type_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_DATA_TYPE, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_DATA_TYPE, type))              return false;          if (!define_analysis_data_type_constants(type)) diff --git a/plugins/pychrysalide/analysis/types/Makefile.am b/plugins/pychrysalide/analysis/types/Makefile.am index d13fe0c..697c998 100644 --- a/plugins/pychrysalide/analysis/types/Makefile.am +++ b/plugins/pychrysalide/analysis/types/Makefile.am @@ -1,30 +1,23 @@  noinst_LTLIBRARIES = libpychrysaanalysistypes.la -libpychrysaanalysistypes_la_SOURCES =	\ -	array.h array.c						\ -	basic.h basic.c						\ -	constants.h constants.c				\ -	cse.h cse.c							\ -	encaps.h encaps.c					\ -	expr.h expr.c						\ -	literal.h literal.c					\ -	module.h module.c					\ -	override.h override.c				\ -	proto.h proto.c						\ +libpychrysaanalysistypes_la_SOURCES =		\ +	array.h array.c							\ +	basic.h basic.c							\ +	constants.h constants.c					\ +	cse.h cse.c								\ +	encaps.h encaps.c						\ +	expr.h expr.c							\ +	literal.h literal.c						\ +	module.h module.c						\ +	override.h override.c					\ +	proto.h proto.c							\  	template.h template.c -libpychrysaanalysistypes_la_LDFLAGS =  +libpychrysaanalysistypes_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT  devdir = $(includedir)/chrysalide/$(subdir)  dev_HEADERS = $(libpychrysaanalysistypes_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - -SUBDIRS =  diff --git a/plugins/pychrysalide/analysis/types/array.c b/plugins/pychrysalide/analysis/types/array.c index 8055316..88b773e 100644 --- a/plugins/pychrysalide/analysis/types/array.c +++ b/plugins/pychrysalide/analysis/types/array.c @@ -423,7 +423,7 @@ bool ensure_python_array_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_ARRAY_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_ARRAY_TYPE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/types/basic.c b/plugins/pychrysalide/analysis/types/basic.c index 9ae4f8f..19fb9d1 100644 --- a/plugins/pychrysalide/analysis/types/basic.c +++ b/plugins/pychrysalide/analysis/types/basic.c @@ -210,7 +210,7 @@ bool ensure_python_basic_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_BASIC_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_BASIC_TYPE, type))              return false;          if (!define_basic_type_constants(type)) diff --git a/plugins/pychrysalide/analysis/types/cse.c b/plugins/pychrysalide/analysis/types/cse.c index 7701d48..0aab4d9 100644 --- a/plugins/pychrysalide/analysis/types/cse.c +++ b/plugins/pychrysalide/analysis/types/cse.c @@ -262,7 +262,7 @@ bool ensure_python_class_enum_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_CLASS_ENUM_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_CLASS_ENUM_TYPE, type))              return false;          if (!define_class_enum_type_constants(type)) diff --git a/plugins/pychrysalide/analysis/types/encaps.c b/plugins/pychrysalide/analysis/types/encaps.c index 3a5acb5..bc9f4db 100644 --- a/plugins/pychrysalide/analysis/types/encaps.c +++ b/plugins/pychrysalide/analysis/types/encaps.c @@ -223,7 +223,7 @@ bool ensure_python_encapsulated_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_ENCAPSULATED_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_ENCAPSULATED_TYPE, type))              return false;          if (!define_encapsulated_type_constants(type)) diff --git a/plugins/pychrysalide/analysis/types/expr.c b/plugins/pychrysalide/analysis/types/expr.c index 02cb02f..e3b2b0a 100644 --- a/plugins/pychrysalide/analysis/types/expr.c +++ b/plugins/pychrysalide/analysis/types/expr.c @@ -201,7 +201,7 @@ bool ensure_python_expr_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_EXPR_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_EXPR_TYPE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/types/literal.c b/plugins/pychrysalide/analysis/types/literal.c index e00104f..3d9d5e3 100644 --- a/plugins/pychrysalide/analysis/types/literal.c +++ b/plugins/pychrysalide/analysis/types/literal.c @@ -136,7 +136,7 @@ bool ensure_python_literal_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_LITERAL_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_LITERAL_TYPE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/types/override.c b/plugins/pychrysalide/analysis/types/override.c index 896163f..236a34c 100644 --- a/plugins/pychrysalide/analysis/types/override.c +++ b/plugins/pychrysalide/analysis/types/override.c @@ -247,7 +247,7 @@ bool ensure_python_override_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_OVERRIDE_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_OVERRIDE_TYPE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/types/proto.c b/plugins/pychrysalide/analysis/types/proto.c index 7c3ebed..1da3119 100644 --- a/plugins/pychrysalide/analysis/types/proto.c +++ b/plugins/pychrysalide/analysis/types/proto.c @@ -349,7 +349,7 @@ bool ensure_python_proto_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_PROTO_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_PROTO_TYPE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/types/template.c b/plugins/pychrysalide/analysis/types/template.c index 6fc50e4..68f390a 100644 --- a/plugins/pychrysalide/analysis/types/template.c +++ b/plugins/pychrysalide/analysis/types/template.c @@ -345,7 +345,7 @@ bool ensure_python_template_type_is_registered(void)          if (!ensure_python_data_type_is_registered())              return false; -        if (!register_class_for_pygobject(dict, G_TYPE_TEMPLATE_TYPE, type, get_python_data_type_type())) +        if (!register_class_for_pygobject(dict, G_TYPE_TEMPLATE_TYPE, type))              return false;      } diff --git a/plugins/pychrysalide/analysis/variable.c b/plugins/pychrysalide/analysis/variable.c index 3aeddf4..5f8d490 100644 --- a/plugins/pychrysalide/analysis/variable.c +++ b/plugins/pychrysalide/analysis/variable.c @@ -266,7 +266,7 @@ bool ensure_python_binary_variable_is_registered(void)          dict = PyModule_GetDict(module); -        if (!register_class_for_pygobject(dict, G_TYPE_BIN_VARIABLE, type, &PyGObject_Type)) +        if (!register_class_for_pygobject(dict, G_TYPE_BIN_VARIABLE, type))              return false;      } | 
