diff options
Diffstat (limited to 'plugins/pychrysa/plugin.c')
-rw-r--r-- | plugins/pychrysa/plugin.c | 809 |
1 files changed, 0 insertions, 809 deletions
diff --git a/plugins/pychrysa/plugin.c b/plugins/pychrysa/plugin.c deleted file mode 100644 index fad0084..0000000 --- a/plugins/pychrysa/plugin.c +++ /dev/null @@ -1,809 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * plugin.c - interactions avec un greffon Python - * - * Copyright (C) 2012-2017 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 "plugin.h" - - -#include <pygobject.h> -#include <string.h> - - -#include <common/extstr.h> -#include "../../src/core/formats.h" -//#include <core/formats.h> -#include <plugins/plugin-int.h> - - -#include "helpers.h" - - - -/* --------------------- INTERFACE INTERNE POUR GREFFONS PYTHON --------------------- */ - - -/* Ligne de représentation de code binaire (instance) */ -struct _GPythonPlugin -{ - GPluginModule parent; /* Instance parente */ - - PyObject *module; /* Script Python chargé */ - PyObject *instance; /* Instance Python du greffon */ - -}; - - -/* Ligne de représentation de code binaire (classe) */ -struct _GPythonPluginClass -{ - GPluginModuleClass parent; /* Classe parente */ - -}; - - -/* Initialise la classe des greffons Python. */ -static void g_python_plugin_class_init(GPythonPluginClass *); - -/* Initialise l'instance d'un greffon Python. */ -static void g_python_plugin_init(GPythonPlugin *); - -/* Reconstruit la déclaration d'interface à partir de lectures. */ -static bool g_python_plugin_read_interface(GPythonPlugin *); - -/* Procède à l'initialisation du greffon. */ -static bool g_python_plugin_do_init(GPythonPlugin *); - -/* Procède à l'extinction du greffon. */ -static bool g_python_plugin_do_exit(GPythonPlugin *, GObject *); - -/* Indique si le format peut être pris en charge ici. */ -FormatMatchStatus python_plugin_is_matching(GBinContent *, GExeFormat *, GPythonPlugin *, char **); - -/* Exécute une action pendant un désassemblage de binaire. */ -static void g_python_plugin_process_disass(const GPythonPlugin *, PluginAction, GLoadedBinary *); - - - -/* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */ - - -/* Définit les constantes pour les greffons en Python. */ -static bool py_plugin_module_define_constants(PyTypeObject *); - - - -/* ---------------------------------------------------------------------------------- */ -/* INTERFACE INTERNE POUR GREFFONS PYTHON */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type définit par la GLib pour le greffon Python. */ -G_DEFINE_TYPE(GPythonPlugin, g_python_plugin, G_TYPE_PLUGIN_MODULE); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des greffons Python. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_python_plugin_class_init(GPythonPluginClass *klass) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : plugin = instance à initialiser. * -* * -* Description : Initialise l'instance d'un greffon Python. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_python_plugin_init(GPythonPlugin *plugin) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : modname = nom du module à charger. * -* filename = chemin d'accès au code Python à charger. * -* * -* Description : Crée un greffon à partir de code Python. * -* * -* Retour : Adresse de la structure mise en place ou NULL si erreur. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GPluginModule *g_python_plugin_new(const char *modname, const char *filename) -{ - GPythonPlugin *result; /* Structure à retourner */ - PyObject *name; /* Chemin d'accès pour Python */ - PyObject *module; /* Script Python chargé */ - PyObject *err_type; /* Type d'erreur Python */ - PyObject *err_value; /* Instance Python d'erreur */ - PyObject *err_traceback; /* Trace Python associée */ - PyObject *err_string; /* Description Python d'erreur */ - const char *err_msg; /* Représentation humaine */ - PyObject *dict; /* Dictionnaire associé */ - PyObject *class; /* Classe à instancier */ - PyObject *instance; /* Instance Python du greffon */ - 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 */ - - name = PyUnicode_FromString(modname); - if (name == NULL) goto gppn_bad_exit; - - module = PyImport_Import(name); - Py_DECREF(name); - - if (PyErr_Occurred()) - { - PyErr_Fetch(&err_type, &err_value, &err_traceback); - - if (err_value == NULL) - log_variadic_message(LMT_ERROR, - _("An unknown error occured when importing '%s'..."), modname); - else - { - err_string = PyObject_Str(err_value); - err_msg = PyUnicode_AsUTF8(err_string); - - log_variadic_message(LMT_ERROR, - _("An error occured when importing '%s': \"%s\""), modname, err_msg); - - Py_DECREF(err_string); - Py_DECREF(err_value); - - } - - Py_XDECREF(err_traceback); - Py_XDECREF(err_type); - - Py_XDECREF(module); - - module = NULL; - - } - - if (module == NULL) goto gppn_bad_exit; - - dict = PyModule_GetDict(module); - class = PyDict_GetItemString(dict, "AutoLoad"); - - if (class == NULL) goto gppn_no_class; - if (!PyType_Check(class->ob_type)) goto gppn_no_class; - - instance = PyObject_CallFunction(class, NULL); - if (instance == NULL) goto gppn_no_instance; - - result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL); - - G_PLUGIN_MODULE(result)->filename = strdup(filename); - - result->module = module; - result->instance = instance; - - if (!g_python_plugin_read_interface(result)) - { - printf("bad interface------------\n"); - goto gppn_interface_error; - } - - /* Localisation des différents points d'entrée déclarés */ - -#define register_python_binding(inst, sym, binding) \ - ({ \ - bool __result; \ - if (!has_python_method(inst, #sym)) \ - { \ - log_variadic_message(LMT_ERROR, \ - _("No '%s' entry in plugin candidate '%s'"), \ - #sym, G_PLUGIN_MODULE(result)->filename); \ - __result = false; \ - } \ - else \ - { \ - G_PLUGIN_MODULE(result)->sym = binding; \ - __result = true; \ - } \ - __result; \ - }) - - for (i = 0; i < G_PLUGIN_MODULE(result)->interface->actions_count; i++) - { - action = G_PLUGIN_MODULE(result)->interface->actions[i]; - category = MASK_PLUGIN_CATEGORY(action); - sub = MASK_PLUGIN_SUB_CATEGORY(action); - - switch (category) - { - case DPC_BASIC: - - switch (sub) - { - case DPS_NONE: - break; - - case PGA_PLUGIN_INIT: - if (!register_python_binding(instance, init, (pg_management_fc)g_python_plugin_do_init)) - goto gppn_bad_plugin; - break; - - case PGA_PLUGIN_EXIT: - if (!register_python_binding(instance, exit, (pg_management_fc)g_python_plugin_do_exit)) - goto gppn_bad_plugin; - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); - break; - - } - - break; - - case DPC_BINARY_PROCESSING: - - switch (sub) - { - case DPS_FORMAT: - - switch (action) - { - case PGA_FORMAT_MATCHER: - - if (!has_python_method(instance, "is_format_matching")) - { - log_variadic_message(LMT_ERROR, - _("No '%s' entry in plugin candidate '%s'"), - "is_format_matching", - G_PLUGIN_MODULE(result)->filename); - goto gppn_bad_plugin; - } - - if (!register_format_matcher((format_match_fc)python_plugin_is_matching, result)) - goto gppn_bad_plugin; - - break; - - case PGA_FORMAT_LOADER_LAST: - /* TODO */ - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown action '0x%02x' in plugin '%s'..."), - action, filename); - break; - - } - - break; - - case DPS_DISASSEMBLY: - if (!register_python_binding(instance, process_disass, - (pg_process_disassembly_fc)g_python_plugin_process_disass)) - goto gppn_bad_plugin; - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); - break; - - } - - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown category '0x%02x' in plugin '%s'..."), category, filename); - break; - - } - - } - - /* Conclusion */ - - /* - if (!g_plugin_module_load(G_PLUGIN_MODULE(result))) - goto gppn_bad_plugin; - */ - - return G_PLUGIN_MODULE(result); - - gppn_bad_plugin: - - gppn_interface_error: - - g_object_unref(G_OBJECT(result)); - - //Py_DECREF(instance); - - gppn_no_instance: - - gppn_no_class: - - //Py_DECREF(module); - - gppn_bad_exit: - - printf("bad exit :(\n"); - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : plugin = greffon à initialiser. * -* * -* Description : Reconstruit la déclaration d'interface à partir de lectures. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_python_plugin_read_interface(GPythonPlugin *plugin) -{ - bool result; /* Bilan à renvoyer */ - plugin_interface interface; /* Recueil des éléments */ - PyObject *desc; /* Tableau de description */ - PyObject *str; /* Chaîne de caractères */ - PyObject *tuple; /* Liste d'éléments à traiter */ - Py_ssize_t count; /* Nombre d'éléments présents */ - Py_ssize_t i; /* Boucle de parcours */ - PyObject *action; /* Identifiant d'une action */ - plugin_interface *final; /* Interface finale conservée */ - - result = true; - - desc = run_python_method(plugin->instance, "get_interface", NULL); - if (!PyDict_Check(desc)) - { - result = false; - goto pgpri_end; - } - - memset(&interface, 0, sizeof(interface)); - - /* Chargements des premières chaînes */ - -#define READ_STR_FIELD(name) \ - str = PyDict_GetItemString(desc, #name); \ - if ((result = PyUnicode_Check(str))) \ - interface.name = strdup(PyUnicode_DATA(str)); \ - - READ_STR_FIELD(name); - READ_STR_FIELD(desc); - READ_STR_FIELD(version); - - /* Chargement des actions supportées */ - - tuple = PyDict_GetItemString(desc, "actions"); - - if (!PyList_Check(tuple)) - { - result = false; - goto pgpri_failed; - } - - count = PyList_GET_SIZE(tuple); - - interface.actions = (plugin_action_t *)calloc(count, sizeof(plugin_action_t)); - interface.actions_count = count; - - for (i = 0; i < count; i++) - { - action = PyList_GET_ITEM(tuple, i); - - interface.actions[i] = PyLong_AsLong(action); - - } - - pgpri_failed: - - if (result) - { - final = (plugin_interface *)calloc(1, sizeof(plugin_interface)); - - memcpy(final, &interface, sizeof(interface)); - - G_PLUGIN_MODULE(plugin)->interface = final; - - } - else - { - if (interface.name != NULL) free((char *)interface.name); - if (interface.desc != NULL) free((char *)interface.desc); - if (interface.version != NULL) free((char *)interface.version); - - if (interface.actions != NULL) free(interface.actions); - - } - - pgpri_end: - - Py_XDECREF(desc); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : plugin = greffon à initialiser. * -* ref = espace de référencement global. * -* * -* Description : Procède à l'initialisation du greffon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_python_plugin_do_init(GPythonPlugin *plugin) -{ - bool result; /* Bilan à retourner */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *value; /* Valeur obtenue */ - - args = Py_None; - Py_INCREF(args); - - value = run_python_method(plugin->instance, "init", args); - - result = (value != NULL && PyObject_IsTrue(value)); - - Py_XDECREF(value); - Py_DECREF(args); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : plugin = greffon à initialiser. * -* ref = espace de référencement global. * -* * -* Description : Procède à l'extinction du greffon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_python_plugin_do_exit(GPythonPlugin *plugin, GObject *ref) -{ - bool result; /* Bilan à retourner */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *value; /* Valeur obtenue */ - - args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pygobject_new(ref)); - - value = run_python_method(plugin->instance, "exit", args); - - result = PyObject_IsTrue(value); - - Py_XDECREF(value); - Py_DECREF(args); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : content = contenu binaire à parcourir. * -* parent = éventuel format exécutable déjà chargé. * -* plugin = grefon C interne représentant le grefon Python. * -* key = identifiant de format trouvé ou NULL. [OUT] * -* * -* Description : Indique si le format peut être pris en charge ici. * -* * -* Retour : Conclusion de haut niveau sur la reconnaissance effectuée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -FormatMatchStatus python_plugin_is_matching(GBinContent *content, GExeFormat *parent, GPythonPlugin *plugin, char **key) -{ - FormatMatchStatus result; /* Bilan à renvoyer */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *value; /* Valeur obtenue */ - PyObject *arg; /* Argument en élément de tuple*/ - - result = FMS_UNKNOWN; - - args = PyTuple_New(2); - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(content))); - PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(parent))); - - value = run_python_method(plugin->instance, "is_format_matching", args); - - if (PyTuple_Check(value)) - { - if (PyTuple_Size(value) > 0) - { - arg = PyTuple_GetItem(value, 0); - - if (PyLong_Check(arg)) - { - result = PyLong_AsLong(arg); - - switch (result) - { - case FMS_MATCHED: - - if (PyTuple_Size(value) != 2) - { - g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR, - _("Expecting only a tuple [ status, key ] " \ - "as result for format matching.")); - result = FMS_UNKNOWN; - break; - } - - arg = PyTuple_GetItem(value, 1); - - if (PyUnicode_Check(arg)) - *key = strdup(PyUnicode_AsUTF8(arg)); - - else - { - g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR, - _("Expecting a key string for format matching.")); - result = FMS_UNKNOWN; - } - - break; - - case FMS_FORWARDED: - case FMS_UNKNOWN: - if (PyTuple_Size(value) != 1) - { - g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_WARNING, - _("Unused second item for format matching.")); - } - break; - - default: - g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR, - _("Unexpected result for format matching.")); - result = FMS_UNKNOWN; - break; - - } - - } - - else - { - g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR, - _("Unexpected result status for format matching.")); - result = FMS_UNKNOWN; - } - - } - else - g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_WARNING, - _("Interpreting a empty tuple as FMS_UNKNOWN " \ - "for format matching.")); - - } - else - g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR, - _("Expected a tuple containing [ status, key ] as result " \ - "for format matching.")); - - Py_XDECREF(value); - Py_DECREF(args); - - return result; - - - - -} - - -/****************************************************************************** -* * -* Paramètres : plugin = greffon à manipuler. * -* action = type d'action attendue. * -* binary = binaire dont le contenu est en cours de traitement. * -* * -* Description : Exécute une action pendant un désassemblage de binaire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAction action, GLoadedBinary *binary) -{ - PyObject *args; /* Arguments pour l'appel */ - PyObject *value; /* Valeurs obtenues */ - - args = PyTuple_New(2); - - PyTuple_SetItem(args, 0, PyLong_FromLong(action)); - PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary))); - - value = run_python_method(plugin->instance, "process_binary_disassembly", args); - - Py_XDECREF(value); - Py_DECREF(args); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* MODULE PYTHON POUR LES SCRIPTS */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* 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_AddIntMacro(obj_type, PGA_BASIC_NONE); - result &= PyDict_AddIntMacro(obj_type, PGA_PLUGIN_INIT); - result &= PyDict_AddIntMacro(obj_type, PGA_PLUGIN_EXIT); - result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_MATCHER); - result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_LOADER_LAST); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_STARTED); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_RAW); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_HOOKED_LINK); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_HOOKED_POST); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LIMITED); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LOOPS); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LINKED); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_GROUPED); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_RANKED); - result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_ENDED); - - 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_plugin_module_type(void) -{ - static PyMethodDef py_plugin_module_methods[] = { - { NULL } - }; - - static PyGetSetDef py_plugin_module_getseters[] = { - { NULL } - }; - - static PyTypeObject py_plugin_module_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.PluginModule", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = "Chrysalide plugin for Python.", - - .tp_methods = py_plugin_module_methods, - .tp_getset = py_plugin_module_getseters - - }; - - return &py_plugin_module_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide.PluginModule'. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool register_python_plugin_module(PyObject *module) -{ - PyTypeObject *py_plugin_module_type; /* Type Python 'PluginModule' */ - PyObject *dict; /* Dictionnaire du module */ - - py_plugin_module_type = get_python_plugin_module_type(); - - dict = PyModule_GetDict(module); - - if (!register_class_for_pygobject(dict, G_TYPE_PLUGIN_MODULE, py_plugin_module_type, &PyGObject_Type)) - return false; - - if (!py_plugin_module_define_constants(py_plugin_module_type)) - return false; - - return true; - -} |