diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2020-05-17 18:05:48 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2020-05-17 18:05:48 (GMT) | 
| commit | d110791309783e6e30df837a81cf8e14e1ac9641 (patch) | |
| tree | 75e65909e080cc3ace578c7beb6f0bdae6dc18c1 | |
| parent | f3e136eab9fd6adcb51988c9f70ca7f35552abc4 (diff) | |
Updated the plugin system and its Python documentation.
| -rw-r--r-- | plugins/devdbg/speed.c | 2 | ||||
| -rw-r--r-- | plugins/devdbg/speed.h | 2 | ||||
| -rw-r--r-- | plugins/libcsem/semantic.c | 2 | ||||
| -rw-r--r-- | plugins/libcsem/semantic.h | 2 | ||||
| -rw-r--r-- | plugins/lnxsyscalls/core.c | 2 | ||||
| -rw-r--r-- | plugins/lnxsyscalls/core.h | 2 | ||||
| -rw-r--r-- | plugins/pychrysalide/Makefile.am | 1 | ||||
| -rw-r--r-- | plugins/pychrysalide/analysis/constants.c | 2 | ||||
| -rw-r--r-- | plugins/pychrysalide/constants.c | 95 | ||||
| -rw-r--r-- | plugins/pychrysalide/constants.h | 38 | ||||
| -rw-r--r-- | plugins/pychrysalide/core/constants.c | 56 | ||||
| -rw-r--r-- | plugins/pychrysalide/core/constants.h | 3 | ||||
| -rw-r--r-- | plugins/pychrysalide/core/logs.c | 32 | ||||
| -rw-r--r-- | plugins/pychrysalide/format/symbol.c | 20 | ||||
| -rw-r--r-- | plugins/pychrysalide/plugin.c | 790 | ||||
| -rw-r--r-- | plugins/pychrysalide/pychrysa.c | 2 | ||||
| -rw-r--r-- | plugins/python/abackup/plugin.py | 23 | ||||
| -rw-r--r-- | plugins/python/apkfiles/apkfiles.py | 23 | ||||
| -rw-r--r-- | plugins/python/checksec/plugin.py | 21 | ||||
| -rw-r--r-- | plugins/python/liveconv/plugin.py | 19 | ||||
| -rw-r--r-- | src/plugins/plugin.c | 10 | 
21 files changed, 734 insertions, 413 deletions
diff --git a/plugins/devdbg/speed.c b/plugins/devdbg/speed.c index 1378c66..c8416d1 100644 --- a/plugins/devdbg/speed.c +++ b/plugins/devdbg/speed.c @@ -218,7 +218,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_handle_binary_format_analysis(const GPlug  *                                                                             *  ******************************************************************************/ -G_MODULE_EXPORT void chrysalide_plugin_process_binary_disassembly(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context) +G_MODULE_EXPORT void chrysalide_plugin_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)  {      speed_measure *measure;                 /* Suivi des progressions      */      struct timeval point;                   /* Point de mesure courant     */ diff --git a/plugins/devdbg/speed.h b/plugins/devdbg/speed.h index 7d591fb..2347706 100644 --- a/plugins/devdbg/speed.h +++ b/plugins/devdbg/speed.h @@ -34,7 +34,7 @@  G_MODULE_EXPORT bool chrysalide_plugin_handle_binary_format_analysis(const GPluginModule *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);  /* Exécute une action pendant un désassemblage de binaire. */ -G_MODULE_EXPORT void chrysalide_plugin_process_binary_disassembly(const GPluginModule *, PluginAction , GLoadedBinary *, GtkStatusStack *, GProcContext *); +G_MODULE_EXPORT void chrysalide_plugin_process_disassembly_event(const GPluginModule *, PluginAction , GLoadedBinary *, GtkStatusStack *, GProcContext *); diff --git a/plugins/libcsem/semantic.c b/plugins/libcsem/semantic.c index 00e174f..6786894 100644 --- a/plugins/libcsem/semantic.c +++ b/plugins/libcsem/semantic.c @@ -54,7 +54,7 @@ DEFINE_CHRYSALIDE_PLUGIN("CSem", "Semantic information relative to the libc",  *                                                                             *  ******************************************************************************/ -G_MODULE_EXPORT void chrysalide_plugin_process_binary_disassembly(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context) +G_MODULE_EXPORT void chrysalide_plugin_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)  {      if (action == PGA_DISASSEMBLY_HOOKED_POST)      { diff --git a/plugins/libcsem/semantic.h b/plugins/libcsem/semantic.h index 58c14ef..016b85d 100644 --- a/plugins/libcsem/semantic.h +++ b/plugins/libcsem/semantic.h @@ -31,7 +31,7 @@  /* Exécute une action pendant un désassemblage de binaire. */ -G_MODULE_EXPORT void chrysalide_plugin_process_binary_disassembly(const GPluginModule *, PluginAction, GLoadedBinary *, GtkStatusStack *, GProcContext *); +G_MODULE_EXPORT void chrysalide_plugin_process_disassembly_event(const GPluginModule *, PluginAction, GLoadedBinary *, GtkStatusStack *, GProcContext *); diff --git a/plugins/lnxsyscalls/core.c b/plugins/lnxsyscalls/core.c index 314f89f..bee11db 100644 --- a/plugins/lnxsyscalls/core.c +++ b/plugins/lnxsyscalls/core.c @@ -96,7 +96,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)  *                                                                             *  ******************************************************************************/ -G_MODULE_EXPORT void chrysalide_plugin_process_binary_disassembly(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context) +G_MODULE_EXPORT void chrysalide_plugin_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)  {      GBinFormat *format;                     /* Format du binaire chargé    */      const char *arch;                       /* Architecture d'exécution    */ diff --git a/plugins/lnxsyscalls/core.h b/plugins/lnxsyscalls/core.h index dcf5c11..50b8ef0 100644 --- a/plugins/lnxsyscalls/core.h +++ b/plugins/lnxsyscalls/core.h @@ -34,7 +34,7 @@  G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *);  /* Exécute une action pendant un désassemblage de binaire. */ -G_MODULE_EXPORT void chrysalide_plugin_process_binary_disassembly(const GPluginModule *, PluginAction , GLoadedBinary *, GtkStatusStack *, GProcContext *); +G_MODULE_EXPORT void chrysalide_plugin_process_disassembly_event(const GPluginModule *, PluginAction , GLoadedBinary *, GtkStatusStack *, GProcContext *); diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am index 6bcaef4..5d6c3e6 100644 --- a/plugins/pychrysalide/Makefile.am +++ b/plugins/pychrysalide/Makefile.am @@ -6,6 +6,7 @@ libdir = $(pluginslibdir)  pychrysalide_la_SOURCES =				\  	access.h access.c					\ +	constants.h constants.c				\  	constval.h constval.c				\  	helpers.h helpers.c					\  	plugin.h plugin.c					\ diff --git a/plugins/pychrysalide/analysis/constants.c b/plugins/pychrysalide/analysis/constants.c index 87f91a3..a162ac7 100644 --- a/plugins/pychrysalide/analysis/constants.c +++ b/plugins/pychrysalide/analysis/constants.c @@ -36,7 +36,7 @@  *                                                                             *  *  Paramètres  : type = type dont le dictionnaire est à compléter.            *  *                                                                             * -*  Description : Définit les constantes relatives au contenus binaires.       * +*  Description : Définit les constantes relatives aux contenus binaires.      *  *                                                                             *  *  Retour      : true en cas de succès de l'opération, false sinon.           *  *                                                                             * diff --git a/plugins/pychrysalide/constants.c b/plugins/pychrysalide/constants.c new file mode 100644 index 0000000..e31a8fe --- /dev/null +++ b/plugins/pychrysalide/constants.c @@ -0,0 +1,95 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.c - ajout des constantes principales + * + * 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 <plugins/plugin-def.h> + + +#include "helpers.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : type = type dont le dictionnaire est à compléter.            * +*                                                                             * +*  Description : Définit les constantes relatives aux greffons Python.        * +*                                                                             * +*  Retour      : true en cas de succès de l'opération, false sinon.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool define_plugin_module_constants(PyTypeObject *type) +{ +    bool result;                            /* Bilan à retourner           */ +    PyObject *values;                       /* Groupe de valeurs à établir */ + +    result = true; + +    values = PyDict_New(); + +    if (result) result = add_const_to_group(values, "BASIC_NONE", PGA_BASIC_NONE); +    if (result) result = add_const_to_group(values, "PLUGIN_INIT", PGA_PLUGIN_INIT); +    if (result) result = add_const_to_group(values, "PLUGIN_EXIT", PGA_PLUGIN_EXIT); +    if (result) result = add_const_to_group(values, "NATIVE_LOADED", PGA_NATIVE_LOADED); +    if (result) result = add_const_to_group(values, "GUI_THEME", PGA_GUI_THEME); +    if (result) result = add_const_to_group(values, "CONTENT_EXPLORER", PGA_CONTENT_EXPLORER); +    if (result) result = add_const_to_group(values, "CONTENT_RESOLVER", PGA_CONTENT_RESOLVER); +    if (result) result = add_const_to_group(values, "CONTENT_ANALYZED", PGA_CONTENT_ANALYZED); +    if (result) result = add_const_to_group(values, "FORMAT_ANALYSIS_STARTED", PGA_FORMAT_ANALYSIS_STARTED); +    if (result) result = add_const_to_group(values, "FORMAT_PRELOAD", PGA_FORMAT_PRELOAD); +    if (result) result = add_const_to_group(values, "FORMAT_ATTACH_DEBUG", PGA_FORMAT_ATTACH_DEBUG); +    if (result) result = add_const_to_group(values, "FORMAT_ANALYSIS_ENDED", PGA_FORMAT_ANALYSIS_ENDED); +    if (result) result = add_const_to_group(values, "FORMAT_POST_ANALYSIS_STARTED", PGA_FORMAT_POST_ANALYSIS_STARTED); +    if (result) result = add_const_to_group(values, "FORMAT_POST_ANALYSIS_ENDED", PGA_FORMAT_POST_ANALYSIS_ENDED); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_STARTED", PGA_DISASSEMBLY_STARTED); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_RAW", PGA_DISASSEMBLY_RAW); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_HOOKED_LINK", PGA_DISASSEMBLY_HOOKED_LINK); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_HOOKED_POST", PGA_DISASSEMBLY_HOOKED_POST); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_LIMITED", PGA_DISASSEMBLY_LIMITED); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_LOOPS", PGA_DISASSEMBLY_LOOPS); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_LINKED", PGA_DISASSEMBLY_LINKED); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_GROUPED", PGA_DISASSEMBLY_GROUPED); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_RANKED", PGA_DISASSEMBLY_RANKED); +    if (result) result = add_const_to_group(values, "DISASSEMBLY_ENDED", PGA_DISASSEMBLY_ENDED); +    if (result) result = add_const_to_group(values, "DETECTION_OBFUSCATORS", PGA_DETECTION_OBFUSCATORS); + +    if (!result) +    { +        Py_DECREF(values); +        goto exit; +    } + +    result = attach_constants_group_to_type(type, false, "PluginAction", values, +                                            "Features with which plugins can extend the core of Chrysalide."); + + exit: + +    return result; + +} diff --git a/plugins/pychrysalide/constants.h b/plugins/pychrysalide/constants.h new file mode 100644 index 0000000..21f9d0e --- /dev/null +++ b/plugins/pychrysalide/constants.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.h - prototypes pour l'ajout des constantes principales + * + * 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_CONSTANTS_H +#define _PLUGINS_PYCHRYSALIDE_CONSTANTS_H + + +#include <Python.h> +#include <stdbool.h> + + +/* Définit les constantes relatives aux greffons Python. */ +bool define_plugin_module_constants(PyTypeObject *); + + + +#endif  /* _PLUGINS_PYCHRYSALIDE_CONSTANTS_H */ diff --git a/plugins/pychrysalide/core/constants.c b/plugins/pychrysalide/core/constants.c index e61f451..f3ec530 100644 --- a/plugins/pychrysalide/core/constants.c +++ b/plugins/pychrysalide/core/constants.c @@ -73,3 +73,59 @@ bool define_core_logs_constants(PyObject *module)      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 LogMessageType.              * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_log_message_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 LogMessageType"); +            break; + +        case 1: +            value = PyLong_AsUnsignedLong(arg); + +            if (value > LMT_COUNT) +            { +                PyErr_SetString(PyExc_TypeError, "invalid value for LogMessageType"); +                result = 0; +            } + +            else +                *((LogMessageType *)dst) = value; + +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/pychrysalide/core/constants.h b/plugins/pychrysalide/core/constants.h index 38a8ebc..6ed6fbb 100644 --- a/plugins/pychrysalide/core/constants.h +++ b/plugins/pychrysalide/core/constants.h @@ -34,6 +34,9 @@  /* Définit les constantes pour les types de messages. */  bool define_core_logs_constants(PyObject *); +/* Tente de convertir en constante LogMessageType. */ +int convert_to_log_message_type(PyObject *, void *); +  #endif  /* _PLUGINS_PYCHRYSALIDE_CORE_CONSTANTS_H */ diff --git a/plugins/pychrysalide/core/logs.c b/plugins/pychrysalide/core/logs.c index 0965b4b..4e0bc7b 100644 --- a/plugins/pychrysalide/core/logs.c +++ b/plugins/pychrysalide/core/logs.c @@ -103,7 +103,7 @@ static PyObject *py_logs_get_verbosity(PyObject *self, PyObject *args)  static PyObject *py_logs_set_verbosity(PyObject *self, PyObject *args)  {      PyObject *result;                       /* Bilan à retourner           */ -    unsigned long verbosity;                /* Niveau de filtre de message */ +    LogMessageType verbosity;               /* Niveau de filtre de message */  #define LOGS_SET_VERBOSITY_METHOD PYTHON_METHOD_DEF                         \  (                                                                           \ @@ -116,7 +116,7 @@ static PyObject *py_logs_set_verbosity(PyObject *self, PyObject *args)      " all kinds of logs get printed."                                       \  ) -    if (!PyArg_ParseTuple(args, "k", &verbosity)) +    if (!PyArg_ParseTuple(args, "O&", convert_to_log_message_type, &verbosity))          return NULL;      set_log_verbosity(verbosity); @@ -145,7 +145,7 @@ static PyObject *py_logs_set_verbosity(PyObject *self, PyObject *args)  static PyObject *py_logs_log_message(PyObject *self, PyObject *args)  {      PyObject *result;                       /* Bilan à retourner           */ -    unsigned long type;                     /* Espèce du message           */ +    LogMessageType type;                    /* Espèce du message           */      const char *msg;                        /* Contenu du message          */  #define LOGS_LOG_MESSAGE_METHOD PYTHON_METHOD_DEF                           \ @@ -159,29 +159,13 @@ static PyObject *py_logs_log_message(PyObject *self, PyObject *args)      " value."                                                               \  ) -    if (!PyArg_ParseTuple(args, "ks", &type, &msg)) +    if (!PyArg_ParseTuple(args, "O&s", convert_to_log_message_type, &type, &msg))          return NULL; -    switch (type) -    { -        case LMT_INFO: -        case LMT_PROCESS: -        case LMT_WARNING: -        case LMT_BAD_BINARY: -        case LMT_ERROR: -        case LMT_EXT_ERROR: -            log_plugin_simple_message(type, msg); -            result = Py_None; -            Py_INCREF(result); -            break; - -        default: -            PyErr_SetString(PyExc_ValueError, -                            _("Invalid type of message")); -            result = NULL; -            break; - -    } +    log_plugin_simple_message(type, msg); + +    result = Py_None; +    Py_INCREF(result);      return result; diff --git a/plugins/pychrysalide/format/symbol.c b/plugins/pychrysalide/format/symbol.c index c86b453..7ecc576 100644 --- a/plugins/pychrysalide/format/symbol.c +++ b/plugins/pychrysalide/format/symbol.c @@ -59,7 +59,7 @@ static PyObject *py_binary_symbol_new(PyTypeObject *, PyObject *, PyObject *);  static void py_binary_symbol_init_gclass(GBinSymbolClass *, gpointer);  /* Fournit une étiquette pour viser un symbole. */ -static char *g_binary_symbol_get_label_wrapper(const GBinSymbol *); +static char *py_binary_symbol_get_label_wrapper(const GBinSymbol *);  /* Initialise une instance sur la base du dérivé de GObject. */  static int py_binary_symbol_init(PyObject *, PyObject *, PyObject *); @@ -194,7 +194,7 @@ static PyObject *py_binary_symbol_new(PyTypeObject *type, PyObject *args, PyObje  static void py_binary_symbol_init_gclass(GBinSymbolClass *class, gpointer unused)  { -    class->get_label = g_binary_symbol_get_label_wrapper; +    class->get_label = py_binary_symbol_get_label_wrapper;  } @@ -211,12 +211,21 @@ static void py_binary_symbol_init_gclass(GBinSymbolClass *class, gpointer unused  *                                                                             *  ******************************************************************************/ -static char *g_binary_symbol_get_label_wrapper(const GBinSymbol *symbol) +static char *py_binary_symbol_get_label_wrapper(const GBinSymbol *symbol)  {      char *result;                           /* Etiquette à retourner       */      PyObject *pyobj;                        /* Objet Python concerné       */      PyObject *pyret;                        /* Bilan de consultation       */ +#define BINARY_SYMBOL_GET_LABEL_WRAPPER PYTHON_WRAPPER_DEF              \ +(                                                                       \ +    _get_label, "$self, /",                                             \ +    METH_VARARGS,                                                       \ +    "Abstract method used to provide the default label for a symbol.\n" \ +    "\n"                                                                \ +    "The returned value has to be a string."                            \ +) +      result = NULL;      pyobj = pygobject_new(G_OBJECT(symbol)); @@ -275,8 +284,8 @@ static int py_binary_symbol_init(PyObject *self, PyObject *args, PyObject *kwds)      "Where range is a memory space defined by pychrysalide.arch.mrange and"     \      " stype a pychrysalide.format.BinSymbol.SymbolType value."                  \      "\n"                                                                        \ -    "The following special method can be overridden:\n"                         \ -    "* _get_label(self): provides a default label for the symbol." +    "The following methods have to be defined for new classes:\n"               \ +    "* pychrysalide.format.BinSymbol._get_label()."      /* Récupération des paramètres */ @@ -892,6 +901,7 @@ static int py_binary_symbol_set_label(PyObject *self, PyObject *value, void *clo  PyTypeObject *get_python_binary_symbol_type(void)  {      static PyMethodDef binary_symbol_methods[] = { +        BINARY_SYMBOL_GET_LABEL_WRAPPER,          BINARY_SYMBOL_SET_FLAG_METHOD,          BINARY_SYMBOL_UNSET_FLAG_METHOD,          BINARY_SYMBOL_HAS_FLAG_METHOD, diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c index 1736826..0d24f8c 100644 --- a/plugins/pychrysalide/plugin.c +++ b/plugins/pychrysalide/plugin.c @@ -37,8 +37,10 @@  #include "access.h" +#include "constants.h"  #include "helpers.h"  #include "pychrysa.h" +#include "core/constants.h" @@ -54,9 +56,6 @@ static void py_plugin_module_init_gclass(GPluginModuleClass *, gpointer);  /* Initialise une instance sur la base du dérivé de GObject. */  static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds); -/* Valide les fonctionnalités déclarées en actions. */ -static bool py_plugin_module_check_interface(PyObject *); -  /* Accompagne la fin du chargement des modules natifs. */  static void py_plugin_module_notify_native_loaded_wrapper(GPluginModule *, PluginAction); @@ -125,9 +124,6 @@ static void g_python_plugin_finalize(GPythonPlugin *);  /* Affiche un message dans le journal des messages système. */  static PyObject *py_plugin_module_log_message(PyObject *, PyObject *); -/* Définit les constantes pour les greffons en Python. */ -static bool py_plugin_module_define_constants(PyTypeObject *); -  /* ---------------------------------------------------------------------------------- */ @@ -250,24 +246,42 @@ static void py_plugin_module_init_gclass(GPluginModuleClass *class, gpointer unu  static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)  { -    const char *name;                       /* Désignation humaine courte  */ -    const char *desc;                       /* Description plus loquace    */ -    const char *version;                    /* Version du greffon          */ -    PyObject *actions_obj;                  /* Liste des actions offertes  */ -    int ret;                                /* Bilan de lecture des args.  */      PyObject *new_kwds;                     /* Nouveau dictionnaire épuré  */ +    int ret;                                /* Bilan d'un appel            */      GPluginModule *plugin;                  /* Greffon à manipuler         */      plugin_interface *iface;                /* Interface à constituer      */ +    PyObject *value;                        /* Valeur à présence imposée   */      size_t i;                               /* Boucle de parcours          */      PyObject *action;                       /* Identifiant d'une action    */ -    static char *kwlist[] = { "name", "desc", "version", "actions", NULL }; - -    /* Récupération des paramètres */ - -    ret = PyArg_ParseTupleAndKeywords(args, kwds, "sssO!", kwlist, -                                      &name, &desc, &version, &PyTuple_Type, &actions_obj); -    if (!ret) return -1; +#define PLUGIN_MODULE_DOC                                                   \ +    "PythonModule is the class allowing the creation of Chrysalide plugins" \ +    " for Python."                                                          \ +    "\n"                                                                    \ +    "Calls to the *__init__* constructor of this abstract object expect"    \ +    " no particular argument.\n"                                            \ +    "\n"                                                                    \ +    "Several items have to be defined as class attributes in the final"     \ +    " class:\n"                                                             \ +    "* *_name*: a string providing a small name for the plugin;\n"          \ +    "* *_desc*: a string for a human readable description of the plugin;\n" \ +    "* *_version*: a string providing the version of the plugin;\n"         \ +    "* *_url*: a string for the homepage describing the plugin;\n"          \ +    "* *_actions*: a tuple of pychrysalide.PluginModule.PluginAction"       \ +    " defining the features the plugin is bringing; this list can be"       \ +    " empty.\n"                                                             \ +    "\n"                                                                    \ +    "Depending on the implemented actions, some of the following methods"   \ +    " have to be defined for new classes:\n"                                \ +    "* pychrysalide.PluginModule._notify_native_loaded();\n"                \ +    "* pychrysalide.PluginModule._include_theme();\n"                       \ +    "* pychrysalide.PluginModule._handle_binary_content();\n"               \ +    "* pychrysalide.PluginModule._handle_loaded_content();\n"               \ +    "* pychrysalide.PluginModule._handle_format_analysis();\n"              \ +    "* pychrysalide.PluginModule._preload_format();\n"                      \ +    "* pychrysalide.PluginModule._attach_debug_format();\n"                 \ +    "* pychrysalide.PluginModule._process_disassembly_event();\n"           \ +    "* pychrysalide.PluginModule._detect_external_tools()."      /* Initialisation d'un objet GLib */ @@ -283,12 +297,34 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)      plugin = G_PLUGIN_MODULE(pygobject_get(self)); -    iface = malloc(sizeof(plugin_interface)); +    iface = calloc(1, sizeof(plugin_interface));      plugin->interface = iface; -    iface->name = strdup(name); -    iface->desc = strdup(desc); -    iface->version = strdup(version); +#define LOAD_PYTHON_IFACE(attr)                                                                 \ +    do                                                                                          \ +    {                                                                                           \ +        if (PyObject_HasAttrString(self, "_" #attr))                                            \ +        {                                                                                       \ +            value = PyObject_GetAttrString(self, "_" #attr);                                    \ +            if (value != NULL)                                                                  \ +            {                                                                                   \ +                if (PyUnicode_Check(value))                                                     \ +                    iface->attr = strdup(PyUnicode_AsUTF8(value));                              \ +                Py_DECREF(value);                                                               \ +            }                                                                                   \ +        }                                                                                       \ +        if (iface->attr == NULL)                                                                \ +        {                                                                                       \ +            PyErr_SetString(PyExc_TypeError, _("A '_" #attr "' class attributes is missing.")); \ +            return -1;                                                                          \ +        }                                                                                       \ +    }                                                                                           \ +    while (0); + +    LOAD_PYTHON_IFACE(name); +    LOAD_PYTHON_IFACE(desc); +    LOAD_PYTHON_IFACE(version); +    LOAD_PYTHON_IFACE(url);      iface->container = false; @@ -296,12 +332,21 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)      iface->required[0] = "PyChrysalide";      iface->required_count = 1; -    iface->actions_count = PyTuple_Size(actions_obj); +    if (PyObject_HasAttrString(self, "_actions")) +        value = PyObject_GetAttrString(self, "_actions"); + +    else +    { +        PyErr_SetString(PyExc_TypeError, _("A '_actions' class attributes is missing.")); +        return -1; +    } + +    iface->actions_count = PyTuple_Size(value);      iface->actions = malloc(iface->actions_count * sizeof(plugin_action_t));      for (i = 0; i < iface->actions_count; i++)      { -        action = PyTuple_GetItem(actions_obj, i); +        action = PyTuple_GetItem(value, i);          if (!PyLong_Check(action))          { @@ -313,12 +358,6 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)      } -    if (!py_plugin_module_check_interface(self)) -    { -        PyErr_SetString(PyExc_TypeError, _("missing features for the declared actions.")); -        return -1; -    } -      return 0;  } @@ -326,184 +365,158 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)  /******************************************************************************  *                                                                             * -*  Paramètres  : self = greffon Python en cours d'initialisation.             * +*  Paramètres  : plugin = greffon à manipuler.                                * +*                action = type d'action attendue.                             * +*                unused = variable non utilisé pour l'usage de __VA_ARGS__.   *  *                                                                             * -*  Description : Valide les fonctionnalités déclarées en actions.             * +*  Description : Accompagne la fin du chargement des modules natifs.          *  *                                                                             * -*  Retour      : true si le greffon Python est à priori utilisable.           * +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static bool py_plugin_module_check_interface(PyObject *self) +static void py_plugin_module_notify_native_loaded_wrapper(GPluginModule *plugin, PluginAction action)  { -    bool result;                            /* Bilan à retourner           */ -    GPluginModule *plugin;                  /* Greffon à manipuler         */ -    size_t i;                               /* Boucle de parcours          */ -    uint32_t action;                        /* Identifiant d'une action    */ -    uint32_t category;                      /* Catégorie principale        */ -    uint32_t sub;                           /* Sous-catégorie visée        */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan d'exécution           */ + +#define PLUGIN_MODULE_NOTIFY_NATIVE_LOADED_WRAPPER PYTHON_WRAPPER_DEF   \ +(                                                                       \ +    _notify_native_loaded, "$self, action, /",                          \ +    METH_VARARGS,                                                       \ +    "Abstract method called once all the native plugins are loaded.\n"  \ +    "\n"                                                                \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"   \ +    " value.\n"                                                         \ +    "\n"                                                                \ +    "This method has to be defined in order to handle action such as"   \ +    " *NATIVE_LOADED*."                                                 \ +) -    result = true; +    gstate = PyGILState_Ensure(); -    plugin = G_PLUGIN_MODULE(pygobject_get(self)); +    pyobj = pygobject_new(G_OBJECT(plugin)); -    for (i = 0; i < plugin->interface->actions_count && result; i++) +    if (has_python_method(pyobj, "_notify_native_loaded"))      { -        action = plugin->interface->actions[i]; -        category = MASK_PLUGIN_CATEGORY(action); -        sub = MASK_PLUGIN_SUB_CATEGORY(action); - -        switch (category) -        { -            case DPC_BASIC: +        args = PyTuple_New(1); -                switch (sub) -                { -                    case DPS_NONE: -                        break; - -                    case PGA_PLUGIN_INIT: -                        result = has_python_method(self, "init"); -                        break; - -                    case PGA_PLUGIN_EXIT: -                        result = has_python_method(self, "exit"); -                        break; +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); -                    default: -                        log_variadic_message(LMT_WARNING, -                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."), -                                             sub, self->ob_type->tp_name); -                        break; +        pyret = run_python_method(pyobj, "_notify_native_loaded", args); -                } +        Py_XDECREF(pyret); +        Py_DECREF(args); -                break; +    } -            case DPC_BINARY_PROCESSING: +    Py_DECREF(pyobj); -                switch (sub) -                { -                    case DPS_CONTENT: +    PyGILState_Release(gstate); -                        switch (action) -                        { -                            case PGA_CONTENT_EXPLORER: -                                result = has_python_method(self, "handle_binary_content"); -                                break; +} -                            case PGA_CONTENT_RESOLVER: -                                result = has_python_method(self, "handle_loaded_content"); -                                break; -                            default: -                                log_variadic_message(LMT_WARNING, -                                                     _("Unknown action '0x%02x' in plugin '%s'..."), -                                                     action, self->ob_type->tp_name); -                                break; +/****************************************************************************** +*                                                                             * +*  Paramètres  : plugin    = greffon à manipuler.                             * +*                action    = type d'action attendue.                          * +*                dark      = indique une préférence pour la variante foncée.  * +*                resources = liste de ressources à constituer. [OUT]          * +*                count     = taille de cette liste. [OUT]                     * +*                                                                             * +*  Description : Complète une liste de resources pour thème.                  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ -                        } +static void py_plugin_module_include_theme_wrapper(const GPluginModule *plugin, PluginAction action, gboolean dark, char ***resources, size_t *count) +{ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *darkness;                     /* Valeur booléenne à joindre  */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan d'exécution           */ +    Py_ssize_t length;                      /* Nombre d'éléments collectés */ +    Py_ssize_t i;                           /* Boucle de parcours          */ +    PyObject *res;                          /* Ressource à ajouter         */ + +#define PLUGIN_MODULE_INCLUDE_THEME_WRAPPER PYTHON_WRAPPER_DEF          \ +(                                                                       \ +    _include_theme, "$self, action, dark, /",                           \ +    METH_VARARGS,                                                       \ +    "Abstract method called once all the native plugins are loaded.\n"  \ +    "\n"                                                                \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"   \ +    " value and the *dark* parameter indicates if a dark theme is"      \ +    " being to get loaded.\n"                                           \ +    "\n"                                                                \ +    "The expected result is a list of CSS definition resource URIs,"    \ +    " provided as strings such as 'resource:///org/xxx/extra.css'"      \ +    " for instance.\n"                                                  \ +    "\n"                                                                \ +    "This method has to be defined in order to handle action such as"   \ +    " *GUI_THEME*."                                                     \ +) -                        break; +    gstate = PyGILState_Ensure(); -                    case DPS_FORMAT: +    pyobj = pygobject_new(G_OBJECT(plugin)); -                        switch (action) -                        { -                            case PGA_FORMAT_ANALYSIS_STARTED: -                            case PGA_FORMAT_ANALYSIS_ENDED: -                            case PGA_FORMAT_POST_ANALYSIS_STARTED: -                            case PGA_FORMAT_POST_ANALYSIS_ENDED: -                                result = has_python_method(self, "handle_format_analysis"); -                                break; +    if (has_python_method(pyobj, "_include_theme")) +    { +        args = PyTuple_New(2); -                            case PGA_FORMAT_PRELOAD: -                                result = has_python_method(self, "preload_format"); -                                break; +        darkness = (dark ? Py_True : Py_False); +        Py_INCREF(darkness); -                            case PGA_FORMAT_ATTACH_DEBUG: -                                result = has_python_method(self, "attach_debug_format"); -                                break; +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); +        PyTuple_SetItem(args, 1, darkness); -                            default: -                                log_variadic_message(LMT_WARNING, -                                                     _("Unknown action '0x%02x' in plugin '%s'..."), -                                                     action, self->ob_type->tp_name); -                                break; +        pyret = run_python_method(pyobj, "_include_theme", args); -                        } +        if (!PySequence_Check(pyret)) +            g_plugin_module_log_simple_message(plugin, LMT_ERROR, _("The returned value must be a string list")); -                        break; +        else +        { +            length = PySequence_Length(pyret); -                    case DPS_DISASSEMBLY: -                        result = has_python_method(self, "process_disassembly"); -                        break; +            for (i = 0; i < length; i++) +            { +                res = PySequence_GetItem(pyret, i); -                    default: -                        log_variadic_message(LMT_WARNING, -                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."), -                                             sub, self->ob_type->tp_name); -                        break; +                if (!PyUnicode_Check(res)) +                    g_plugin_module_log_variadic_message(plugin, LMT_ERROR, +                                                         _("The returned #%zd value must be a string")); +                else +                { +                    *resources = realloc(*resources, ++(*count) * sizeof(char **)); +                    *resources[*count - 1] = strdup(PyUnicode_DATA(res));                  } -                break; +                Py_DECREF(res); -            default: -                log_variadic_message(LMT_WARNING, -                                     _("Unknown category '0x%02x' in plugin '%s'..."), -                                     category, self->ob_type->tp_name); -                break; +            }          } -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : plugin = greffon à manipuler.                                * -*                action = type d'action attendue.                             * -*                unused = variable non utilisé pour l'usage de __VA_ARGS__.   * -*                                                                             * -*  Description : Accompagne la fin du chargement des modules natifs.          * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void py_plugin_module_notify_native_loaded_wrapper(GPluginModule *plugin, PluginAction action) -{ - -} +        Py_XDECREF(pyret); +        Py_DECREF(args); +    } -/****************************************************************************** -*                                                                             * -*  Paramètres  : plugin    = greffon à manipuler.                             * -*                action    = type d'action attendue.                          * -*                dark      = indique une préférence pour la variante foncée.  * -*                resources = liste de ressources à constituer. [OUT]          * -*                count     = taille de cette liste. [OUT]                     * -*                                                                             * -*  Description : Complète une liste de resources pour thème.                  * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ +    Py_DECREF(pyobj); -static void py_plugin_module_include_theme_wrapper(const GPluginModule *plugin, PluginAction action, gboolean dark, char ***resources, size_t *count) -{ +    PyGILState_Release(gstate);  } @@ -529,25 +542,47 @@ static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *      PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */      PyObject *pyobj;                        /* Objet Python concerné       */      PyObject *args;                         /* Arguments pour l'appel      */ -    PyObject *value;                        /* Valeurs obtenues            */ +    PyObject *pyret;                        /* Bilan d'exécution           */ + +#define PLUGIN_MODULE_HANDLE_BINARY_CONTENT_WRAPPER PYTHON_WRAPPER_DEF              \ +(                                                                                   \ +    _handle_binary_content, "$self, action, content, wid, status, /",               \ +    METH_VARARGS,                                                                   \ +    "Abstract method used to explore a binary content (and possibly to add new"     \ +    " contents to explore) or to load a recognized binary content into a"           \ +    " pychrysalide.analysis.LoadedContent instance.\n"                              \ +    "\n"                                                                            \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"               \ +    " value and the initial binary content is a pychrysalide.analysis.BinContent"   \ +    " instance. A tracking identifier is provided and is aimed to be"               \ +    " used with methods from pychrysalide.analysis.ContentExplorer and"             \ +    " pychrysalide.analysis.ContentResolver. A reference to the main status bar"    \ +    " may also be provided, as a pychrysalide.gtkext.StatusStack instance if"       \ +    " running in graphical mode or None otherwise.\n"                               \ +    "\n"                                                                            \ +    "This method has to be defined in order to handle actions such as"              \ +    " *CONTENT_EXPLORER* or *CONTENT_RESOLVER*."                                    \ +)      gstate = PyGILState_Ensure();      pyobj = pygobject_new(G_OBJECT(plugin)); -    assert(has_python_method(pyobj, "handle_binary_content")); +    if (has_python_method(pyobj, "_handle_binary_content")) +    { +        args = PyTuple_New(4); -    args = PyTuple_New(4); +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content))); +        PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(wid)); +        PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); -    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); -    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content))); -    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(wid)); -    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); +        pyret = run_python_method(pyobj, "_handle_binary_content", args); -    value = run_python_method(pyobj, "handle_binary_content", args); +        Py_XDECREF(pyret); +        Py_DECREF(args); -    Py_XDECREF(value); -    Py_DECREF(args); +    }      Py_DECREF(pyobj); @@ -561,7 +596,7 @@ static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *  *  Paramètres  : plugin  = greffon à manipuler.                               *  *                action  = type d'action attendue.                            *  *                content = contenu chargé à traiter.                          * -*                wid     = identifiant du groupe de traitement.               * +*                gid     = identifiant du groupe de traitement.               *  *                status  = barre de statut à tenir informée.                  *  *                                                                             *  *  Description : Procède à une opération liée à un contenu chargé.            * @@ -572,30 +607,49 @@ static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *  *                                                                             *  ******************************************************************************/ -static void py_plugin_module_handle_loaded_content_wrapper(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t wid, GtkStatusStack *status) +static void py_plugin_module_handle_loaded_content_wrapper(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t gid, GtkStatusStack *status)  {      PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */      PyObject *pyobj;                        /* Objet Python concerné       */      PyObject *args;                         /* Arguments pour l'appel      */ -    PyObject *value;                        /* Valeurs obtenues            */ +    PyObject *pyret;                        /* Bilan d'exécution           */ + +#define PLUGIN_MODULE_HANDLE_LOADED_CONTENT_WRAPPER PYTHON_WRAPPER_DEF              \ +(                                                                                   \ +    _handle_loaded_content, "$self, action, content, gid, status, /",               \ +    METH_VARARGS,                                                                   \ +    "Abstract method run once a loaded binary has been analyzed with success.\n"    \ +    "\n"                                                                            \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"               \ +    " value and the analyzed content is a pychrysalide.analysis.LoadedContent"      \ +    " instance. The identifier refers to the working queue used to process the"     \ +    " analysis. A reference to the main status bar may also be provided, as a"      \ +    " pychrysalide.gtkext.StatusStack instance if running in graphical mode or"     \ +    " None otherwise.\n"                                                            \ +    "\n"                                                                            \ +    "This method has to be defined in order to handle action such as"               \ +    " *CONTENT_ANALYZED*."                                                          \ +)      gstate = PyGILState_Ensure();      pyobj = pygobject_new(G_OBJECT(plugin)); -    assert(has_python_method(pyobj, "handle_loaded_content")); +    if (has_python_method(pyobj, "_handle_loaded_content")) +    { +        args = PyTuple_New(4); -    args = PyTuple_New(4); +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content))); +        PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid)); +        PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); -    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); -    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content))); -    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(wid)); -    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); +        pyret = run_python_method(pyobj, "_handle_loaded_content", args); -    value = run_python_method(pyobj, "handle_loaded_content", args); +        Py_XDECREF(pyret); +        Py_DECREF(args); -    Py_XDECREF(value); -    Py_DECREF(args); +    }      Py_DECREF(pyobj); @@ -625,25 +679,47 @@ static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPlugin      PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */      PyObject *pyobj;                        /* Objet Python concerné       */      PyObject *args;                         /* Arguments pour l'appel      */ -    PyObject *value;                        /* Valeurs obtenues            */ +    PyObject *pyret;                        /* Bilan d'exécution           */ + +#define PLUGIN_MODULE_HANDLE_BINARY_FORMAT_ANALYSIS_WRAPPER PYTHON_WRAPPER_DEF      \ +(                                                                                   \ +    _handle_binary_format_analysis, "$self, action, format, gid, status, /",        \ +    METH_VARARGS,                                                                   \ +    "Abstract method run at several different steps of a binary format analysis:\n" \ +    "* at the beginning and at the end of the main analysis pass;\n"                \ +    "* at the beginning and at the end of the extra final pass.\n"                  \ +    "\n"                                                                            \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"               \ +    " value and the provided format is a pychrysalide.format.BinFormat"      \ +    " instance. The identifier refers to the working queue used to process the"     \ +    " analysis. A reference to the main status bar may also be provided, as a"      \ +    " pychrysalide.gtkext.StatusStack instance if running in graphical mode or"     \ +    " None otherwise.\n"                                                            \ +    "\n"                                                                            \ +    "This method has to be defined in order to handle actions such as"              \ +    " *FORMAT_ANALYSIS_STARTED*, *FORMAT_ANALYSIS_ENDED*,"                          \ +    " *FORMAT_POST_ANALYSIS_STARTED* or *FORMAT_POST_ANALYSIS_ENDED*."              \ +)      gstate = PyGILState_Ensure();      pyobj = pygobject_new(G_OBJECT(plugin)); -    assert(has_python_method(pyobj, "handle_format_analysis")); +    if (has_python_method(pyobj, "_handle_format_analysis")) +    { +        args = PyTuple_New(4); -    args = PyTuple_New(4); +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); +        PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid)); +        PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); -    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); -    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); -    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid)); -    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); +        pyret = run_python_method(pyobj, "_handle_format_analysis", args); -    value = run_python_method(pyobj, "handle_format_analysis", args); +        Py_XDECREF(pyret); +        Py_DECREF(args); -    Py_XDECREF(value); -    Py_DECREF(args); +    }      Py_DECREF(pyobj); @@ -675,25 +751,48 @@ static bool py_plugin_module_preload_binary_format_wrapper(const GPluginModule *      PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */      PyObject *pyobj;                        /* Objet Python concerné       */      PyObject *args;                         /* Arguments pour l'appel      */ -    PyObject *value;                        /* Valeurs obtenues            */ +    PyObject *pyret;                        /* Bilan d'exécution           */ + +#define PLUGIN_MODULE_PRELOAD_BINARY_FORMAT_WRAPPER PYTHON_WRAPPER_DEF              \ +(                                                                                   \ +    _preload_binary_format, "$self, action, format, info, status, /",               \ +    METH_VARARGS,                                                                   \ +    "Abstract method which is an opportunity to setup instructions or comments"     \ +    " ahead of the disassembling process.\n"                                        \ +    "\n"                                                                            \ +    "Format fields do not need to get disassembled and may be annotated for"        \ +    " instance.\n"                                                                  \ +    "\n"                                                                            \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"               \ +    " value and the provided format is a pychrysalide.format.BinFormat"             \ +    " instance. The information holder to fill is a pychrysalide.format.PreloadInfo"\ +    " instance. A reference to the main status bar may also be provided, as a"      \ +    " pychrysalide.gtkext.StatusStack instance if running in graphical mode or"     \ +    " None otherwise.\n"                                                            \ +    "\n"                                                                            \ +    "This method has to be defined in order to handle action such as"               \ +    " *FORMAT_PRELOAD*."                                                            \ +)      gstate = PyGILState_Ensure();      pyobj = pygobject_new(G_OBJECT(plugin)); -    assert(has_python_method(pyobj, "preload_format")); +    if (has_python_method(pyobj, "_preload_format")) +    { +        args = PyTuple_New(4); -    args = PyTuple_New(4); +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); +        PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(info))); +        PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); -    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); -    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); -    PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(info))); -    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); +        pyret = run_python_method(pyobj, "_preload_format", args); -    value = run_python_method(pyobj, "preload_format", args); +        Py_XDECREF(pyret); +        Py_DECREF(args); -    Py_XDECREF(value); -    Py_DECREF(args); +    }      Py_DECREF(pyobj); @@ -723,23 +822,38 @@ static void py_plugin_module_attach_debug_format_wrapper(const GPluginModule *pl      PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */      PyObject *pyobj;                        /* Objet Python concerné       */      PyObject *args;                         /* Arguments pour l'appel      */ -    PyObject *value;                        /* Valeurs obtenues            */ +    PyObject *pyret;                        /* Bilan d'exécution           */ + +#define PLUGIN_MODULE_ATTACH_DEBUG_FORMAT_WRAPPER PYTHON_WRAPPER_DEF                \ +(                                                                                   \ +    _attach_debug_format, "$self, action, format, /",                               \ +    METH_VARARGS,                                                                   \ +    "Abstract method called when a debugger is attached to a binary format.\n"      \ +    "\n"                                                                            \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"               \ +    " value and the provided format is a pychrysalide.format.ExeFormat instance.\n" \ +    "\n"                                                                            \ +    "This method has to be defined in order to handle action such as"               \ +    " *FORMAT_ATTACH_DEBUG*."                                                       \ +)      gstate = PyGILState_Ensure();      pyobj = pygobject_new(G_OBJECT(plugin)); -    assert(has_python_method(pyobj, "attach_debug_format")); +    if (has_python_method(pyobj, "_attach_debug_format")) +    { +        args = PyTuple_New(2); -    args = PyTuple_New(2); +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); -    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); -    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); +        pyret = run_python_method(pyobj, "_attach_debug_format", args); -    value = run_python_method(pyobj, "attach_debug_format", args); +        Py_XDECREF(pyret); +        Py_DECREF(args); -    Py_XDECREF(value); -    Py_DECREF(args); +    }      Py_DECREF(pyobj); @@ -769,25 +883,43 @@ static void py_plugin_module_process_disassembly_event_wrapper(const GPluginModu      PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */      PyObject *pyobj;                        /* Objet Python concerné       */      PyObject *args;                         /* Arguments pour l'appel      */ -    PyObject *value;                        /* Valeurs obtenues            */ +    PyObject *pyret;                        /* Bilan d'exécution           */ + +#define PLUGIN_MODULE_PROCESS_DISASSEMBLY_EVENT_WRAPPER PYTHON_WRAPPER_DEF          \ +(                                                                                   \ +    _process_disassembly_event, "$self, action, format, /",                         \ +    METH_VARARGS,                                                                   \ +    "Abstract method run at several different steps of a binary analysis.\n"        \ +    "\n"                                                                            \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"               \ +    " value and the provided format is a pychrysalide.format.ExeFormat instance.\n" \ +    "\n"                                                                            \ +    "This method has to be defined in order to handle actions such as"              \ +    " *DISASSEMBLY_STARTED*, *DISASSEMBLY_RAW*, *DISASSEMBLY_HOOKED_LINK*,"         \ +    " *DISASSEMBLY_HOOKED_POST*, *DISASSEMBLY_LIMITED*, *DISASSEMBLY_LOOPS*,"       \ +    " *DISASSEMBLY_LINKED*, *DISASSEMBLY_GROUPED*, *DISASSEMBLY_RANKED*,"           \ +    " *DISASSEMBLY_ENDED*."                                                         \ +)      gstate = PyGILState_Ensure();      pyobj = pygobject_new(G_OBJECT(plugin)); -    assert(has_python_method(pyobj, "process_disassembly")); +    if (has_python_method(pyobj, "_process_disassembly_event")) +    { +        args = PyTuple_New(4); -    args = PyTuple_New(4); +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary))); +        PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(status))); +        PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(context))); -    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); -    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary))); -    PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(status))); -    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(context))); +        pyret = run_python_method(pyobj, "_process_disassembly_event", args); -    value = run_python_method(pyobj, "process_disassembly", args); +        Py_XDECREF(pyret); +        Py_DECREF(args); -    Py_XDECREF(value); -    Py_DECREF(args); +    }      Py_DECREF(pyobj); @@ -815,6 +947,85 @@ static void py_plugin_module_process_disassembly_event_wrapper(const GPluginModu  static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *plugin, PluginAction action, const GLoadedContent *content, bool version, char ***names, size_t *count)  { +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *details;                      /* Valeur booléenne à joindre  */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan d'exécution           */ +    Py_ssize_t length;                      /* Nombre d'éléments collectés */ +    Py_ssize_t i;                           /* Boucle de parcours          */ +    PyObject *res;                          /* Ressource à ajouter         */ + +#define PLUGIN_MODULE_DETECT_EXTERNAL_TOOLS_WRAPPER PYTHON_WRAPPER_DEF  \ +(                                                                       \ +    _detect_external_tools, "$self, action, content, version, /",       \ +    METH_VARARGS,                                                       \ +    "Abstract method called when a detection of tools used the build"   \ +    " the analyzed content is required.\n"                              \ +    "\n"                                                                \ +    "The expected action is a pychrysalide.PluginModule.PluginAction"   \ +    " value and the content is a pychrysalide.analysis.LoadedContent"   \ +    " instance. The *version* parameter is a boolean value indicating"  \ +    " if some extra details about the tools version are wished.\n"      \ +    "\n"                                                                \ +    "The expected result is a list of strings.\n"                       \ +    "\n"                                                                \ +    "This method has to be defined in order to handle action such as"   \ +    " *DETECTION_OBFUSCATORS*."                                         \ +) + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(plugin)); + +    if (has_python_method(pyobj, "_detect_external_tools")) +    { +        args = PyTuple_New(3); + +        details = (version ? Py_True : Py_False); +        Py_INCREF(details); + +        PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); +        PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content))); +        PyTuple_SetItem(args, 2, details); + +        pyret = run_python_method(pyobj, "_detect_external_tools", args); + +        if (!PySequence_Check(pyret)) +            g_plugin_module_log_simple_message(plugin, LMT_ERROR, _("The returned value must be a string list")); + +        else +        { +            length = PySequence_Length(pyret); + +            for (i = 0; i < length; i++) +            { +                res = PySequence_GetItem(pyret, i); + +                if (!PyUnicode_Check(res)) +                    g_plugin_module_log_variadic_message(plugin, LMT_ERROR, +                                                         _("The returned #%zd value must be a string")); + +                else +                { +                    *names = realloc(*names, ++(*count) * sizeof(char **)); +                    *names[*count - 1] = strdup(PyUnicode_DATA(res)); +                } + +                Py_DECREF(res); + +            } + +        } + +        Py_XDECREF(pyret); +        Py_DECREF(args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate);  } @@ -941,12 +1152,15 @@ static void g_python_plugin_finalize(GPythonPlugin *plugin)      if (final != NULL)      { -        free(final->name); -        free(final->desc); -        free(final->version); +        if (final->name != NULL) free(final->name); +        if (final->desc != NULL) free(final->desc); +        if (final->version != NULL) free(final->version); +        if (final->url != NULL) free(final->url); + +        assert(final->required_count <= 1); -        assert(final->required_count == 1); -        free(final->required); +        if (final->required != NULL) +            free(final->required);          if (final->actions != NULL)              free(final->actions); @@ -1059,86 +1273,31 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)  static PyObject *py_plugin_module_log_message(PyObject *self, PyObject *args)  {      PyObject *result;                       /* Bilan à retourner           */ -    unsigned long type;                     /* Espèce du message           */ +    LogMessageType type;                    /* Espèce du message           */      const char *msg;                        /* Contenu du message          */ -    if (!PyArg_ParseTuple(args, "ks", &type, &msg)) +#define PLUGIN_MODULE_LOG_MESSAGE_METHOD PYTHON_METHOD_DEF                  \ +(                                                                           \ +    log_message, "type, msg, /",                                            \ +    METH_VARARGS, py_plugin_module,                                         \ +    "Display a message in the log window, in graphical mode, or in the"     \ +    " console output if none.\n"                                            \ +    "\n"                                                                    \ +    "The type of the message has to be a pychrysalide.core.LogMessageType"  \ +    " value."                                                               \ +    "\n"                                                                    \ +    "The only difference with the main pychrysalide.core.log_message()"     \ +    " function is that messages are automatically prefixed with the plugin" \ +    " name here."                                                           \ +) + +    if (!PyArg_ParseTuple(args, "O&s", convert_to_log_message_type, &type, &msg))          return NULL; -    switch (type) -    { -        case LMT_INFO: -        case LMT_PROCESS: -        case LMT_WARNING: -        case LMT_BAD_BINARY: -        case LMT_ERROR: -        case LMT_EXT_ERROR: -            g_plugin_module_log_simple_message(G_PLUGIN_MODULE(pygobject_get(self)), type, msg); -            result = Py_None; -            Py_INCREF(result); -            break; - -        default: -            PyErr_SetString(PyExc_ValueError, -                            _("Invalid type of message")); -            result = NULL; -            break; +    g_plugin_module_log_simple_message(G_PLUGIN_MODULE(pygobject_get(self)), type, msg); -    } - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        * -*                                                                             * -*  Description : Définit les constantes pour les greffons en Python.          * -*                                                                             * -*  Retour      : true en cas de succès de l'opération, false sinon.           * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool py_plugin_module_define_constants(PyTypeObject *obj_type) -{ -    bool result;                            /* Bilan à retourner           */ - -    result = true; - -    result &= PyDict_AddULongMacro(obj_type, PGA_BASIC_NONE); - -    result &= PyDict_AddULongMacro(obj_type, PGA_PLUGIN_INIT); -    result &= PyDict_AddULongMacro(obj_type, PGA_PLUGIN_EXIT); - -    result &= PyDict_AddULongMacro(obj_type, PGA_NATIVE_LOADED); - -    result &= PyDict_AddULongMacro(obj_type, PGA_CONTENT_EXPLORER); -    result &= PyDict_AddULongMacro(obj_type, PGA_CONTENT_RESOLVER); -    result &= PyDict_AddULongMacro(obj_type, PGA_CONTENT_ANALYZED); - -    result &= PyDict_AddULongMacro(obj_type, PGA_FORMAT_ANALYSIS_STARTED); -    result &= PyDict_AddULongMacro(obj_type, PGA_FORMAT_PRELOAD); -    result &= PyDict_AddULongMacro(obj_type, PGA_FORMAT_ATTACH_DEBUG); -    result &= PyDict_AddULongMacro(obj_type, PGA_FORMAT_ANALYSIS_ENDED); -    result &= PyDict_AddULongMacro(obj_type, PGA_FORMAT_POST_ANALYSIS_STARTED); -    result &= PyDict_AddULongMacro(obj_type, PGA_FORMAT_POST_ANALYSIS_ENDED); - -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_STARTED); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_RAW); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_HOOKED_LINK); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_HOOKED_POST); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_LIMITED); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_LOOPS); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_LINKED); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_GROUPED); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_RANKED); -    result &= PyDict_AddULongMacro(obj_type, PGA_DISASSEMBLY_ENDED); - -    result &= PyDict_AddULongMacro(obj_type, PGA_DETECTION_OBFUSCATORS); +    result = Py_None; +    Py_INCREF(result);      return result; @@ -1160,11 +1319,16 @@ static bool py_plugin_module_define_constants(PyTypeObject *obj_type)  PyTypeObject *get_python_plugin_module_type(void)  {      static PyMethodDef py_plugin_module_methods[] = { -        { -            "log_message", py_plugin_module_log_message, -            METH_VARARGS, -            "log_message(type, msg, /)\n--\n\nDisplay a message in the log window, if any." -        }, +        PLUGIN_MODULE_NOTIFY_NATIVE_LOADED_WRAPPER, +        PLUGIN_MODULE_INCLUDE_THEME_WRAPPER, +        PLUGIN_MODULE_HANDLE_BINARY_CONTENT_WRAPPER, +        PLUGIN_MODULE_HANDLE_LOADED_CONTENT_WRAPPER, +        PLUGIN_MODULE_HANDLE_BINARY_FORMAT_ANALYSIS_WRAPPER, +        PLUGIN_MODULE_PRELOAD_BINARY_FORMAT_WRAPPER, +        PLUGIN_MODULE_ATTACH_DEBUG_FORMAT_WRAPPER, +        PLUGIN_MODULE_PROCESS_DISASSEMBLY_EVENT_WRAPPER, +        PLUGIN_MODULE_DETECT_EXTERNAL_TOOLS_WRAPPER, +        PLUGIN_MODULE_LOG_MESSAGE_METHOD,          { NULL }      }; @@ -1181,7 +1345,7 @@ PyTypeObject *get_python_plugin_module_type(void)          .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, -        .tp_doc         = "Chrysalide plugin for Python.", +        .tp_doc         = PLUGIN_MODULE_DOC,          .tp_methods     = py_plugin_module_methods,          .tp_getset      = py_plugin_module_getseters, @@ -1225,7 +1389,7 @@ bool ensure_python_plugin_module_is_registered(void)          if (!register_class_for_pygobject(dict, G_TYPE_PYTHON_PLUGIN, type, &PyGObject_Type))              return false; -        if (!py_plugin_module_define_constants(type)) +        if (!define_plugin_module_constants(type))              return false;      } diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c index 333544a..df6cc9a 100644 --- a/plugins/pychrysalide/pychrysa.c +++ b/plugins/pychrysalide/pychrysa.c @@ -428,7 +428,7 @@ static bool add_plugin_module_to_python_module(PyObject *super)      "PyChrysalide is a module containing Chrysalide's features and designed for Python users.\n"                \      "\n"                                                                                                        \      "The whole API is defined in a single library named 'pychrysalide.so' and can be used in two ways:\n"       \ -    "* either from the Chrysalide's GUI, by registering hooks or GLib signals,\n"                               \ +    "* either from the Chrysalide's GUI, by registering hooks or GLib signals;\n"                               \      "* or from a shell command line, by setting PYTHONPATH to point to the directory containing the library.\n" \      "\n"                                                                                                        \      "In both cases, this is a good start point to have a look at already existing plugins to quickly learn "    \ diff --git a/plugins/python/abackup/plugin.py b/plugins/python/abackup/plugin.py index d8f52b1..aea9a9c 100644 --- a/plugins/python/abackup/plugin.py +++ b/plugins/python/abackup/plugin.py @@ -34,27 +34,18 @@ from .password import PasswordReader  class AndroidBackupPlugin(PluginModule):      """Open and process Android backup files.""" +    _name = 'AndroidBackup' +    _desc = 'Add suppport for the Android backup file format' +    _version = '0.1' +    _url = 'https://www.chrysalide.re/' -    def __init__(self): -        """Initialize the plugin for Chrysalide.""" +    _actions = ( PluginModule.PluginAction.CONTENT_EXPLORER, ) -        interface = { -            'name' : 'AndroidBackup', -            'desc' : 'Add suppport for the Android backup file format', -            'version' : '0.1', - -            'actions' : ( PluginModule.PGA_CONTENT_EXPLORER, ) - -        } - -        super(AndroidBackupPlugin, self).__init__(**interface) - - -    def handle_binary_content(self, action, content, wid, status): +    def _handle_binary_content(self, action, content, wid, status):          """Process an operation on a binary content.""" -        assert(action == PluginModule.PGA_CONTENT_EXPLORER) +        assert(action == PluginModule.PluginAction.CONTENT_EXPLORER)          try:              backup = AndroidBackup(content) diff --git a/plugins/python/apkfiles/apkfiles.py b/plugins/python/apkfiles/apkfiles.py index 47dfac4..98d31c7 100644 --- a/plugins/python/apkfiles/apkfiles.py +++ b/plugins/python/apkfiles/apkfiles.py @@ -12,27 +12,18 @@ import zipfile  class ApkFiles(PluginModule):      """Open and process APK files.""" +    _name = 'ApkFiles' +    _desc = 'Add suppport for the APK file format' +    _version = '0.1' +    _url = 'https://www.chrysalide.re/' -    def __init__(self): -        """Initialize the plugin for Chrysalide.""" +    _actions = ( PluginModule.PluginAction.CONTENT_EXPLORER, ) -        interface = { -            'name' : 'ApkFiles', -            'desc' : 'Add suppport for the APK file format', -            'version' : '0.1', - -            'actions' : ( PluginModule.PGA_CONTENT_EXPLORER, ) - -        } - -        super(ApkFiles, self).__init__(**interface) - - -    def handle_binary_content(self, action, content, wid, status): +    def _handle_binary_content(self, action, content, wid, status):          """Process an operation on a binary content.""" -        assert(action == PluginModule.PGA_CONTENT_EXPLORER) +        assert(action == PluginModule.PluginAction.CONTENT_EXPLORER)          pseudo_file = io.BytesIO(content.data) diff --git a/plugins/python/checksec/plugin.py b/plugins/python/checksec/plugin.py index f1229bb..6ab213f 100644 --- a/plugins/python/checksec/plugin.py +++ b/plugins/python/checksec/plugin.py @@ -10,24 +10,15 @@ from pychrysalide.format.elf import ElfFormat  class CheckSec(PluginModule):      """Check for Elf mititgations.""" +    _name = 'CheckSec' +    _desc = 'Output the exploit mitigations compiled with a loaded binary' +    _version = '0.1' +    _url = 'https://www.chrysalide.re/' -    def __init__(self): -        """Initialize the plugin for Chrysalide.""" +    _actions = ( PluginModule.PluginAction.FORMAT_POST_ANALYSIS_ENDED, ) -        interface = { -            'name' : 'CheckSec', -            'desc' : 'Output the exploit mitigations compiled with a loaded binary', -            'version' : '0.1', - -            'actions' : ( PluginModule.PGA_FORMAT_POST_ANALYSIS_ENDED, ) - -        } - -        super(CheckSec, self).__init__(**interface) - - -    def handle_format_analysis(self, action, format, gid, status): +    def _handle_format_analysis(self, action, format, gid, status):          """Get notified at the end of format analysis."""          if type(format) == ElfFormat: diff --git a/plugins/python/liveconv/plugin.py b/plugins/python/liveconv/plugin.py index a1a182e..eadbea0 100644 --- a/plugins/python/liveconv/plugin.py +++ b/plugins/python/liveconv/plugin.py @@ -8,21 +8,18 @@ from .panel import ConvPanel  class LiveConverter(PluginModule):      """Convert raw values into interpreted values.""" +    _name = 'LiveConverter' +    _desc = 'Convert raw values into interprered values' +    _version = '0.1' +    _url = 'https://www.chrysalide.re/' -    def __init__(self): -        """Initialize the plugin for Chrysalide.""" - -        interface = { +    _actions = ( ) -            'name' : 'LiveConverter', -            'desc' : 'Convert raw values into interprered values', -            'version' : '0.1', -            'actions' : ( ) - -        } +    def __init__(self): +        """Initialize the plugin for Chrysalide.""" -        super(LiveConverter, self).__init__(**interface) +        super(LiveConverter, self).__init__()          p = ConvPanel() diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 674b1a8..dc8fc59 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -424,7 +424,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename)                          break;                      case DPS_DISASSEMBLY: -                        valid = check_plugin_symbol(module, "chrysalide_plugin_process_binary_disassembly"); +                        valid = check_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event");                          break;                      case DPS_DETECTION: @@ -684,7 +684,7 @@ static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *modu                          break;                      case DPS_DISASSEMBLY: -                        load_plugin_symbol(module, "chrysalide_plugin_process_binary_disassembly", &class->process_disass); +                        load_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event", &class->process_disass);                          break;                      case DPS_DETECTION: @@ -1130,7 +1130,7 @@ void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAc  *  Paramètres  : plugin  = greffon à manipuler.                               *  *                action  = type d'action attendue.                            *  *                content = contenu chargé à traiter.                          * -*                wid     = identifiant du groupe de traitement.               * +*                gid     = identifiant du groupe de traitement.               *  *                status  = barre de statut à tenir informée.                  *  *                                                                             *  *  Description : Procède à une opération liée à un contenu chargé.            * @@ -1141,13 +1141,13 @@ void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAc  *                                                                             *  ******************************************************************************/ -void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t wid, GtkStatusStack *status) +void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t gid, GtkStatusStack *status)  {      GPluginModuleClass *class;              /* Classe de l'instance active */      class = G_PLUGIN_MODULE_GET_CLASS(plugin); -    return class->handle_loaded(plugin, action, content, wid, status); +    return class->handle_loaded(plugin, action, content, gid, status);  }  | 
