From 0e3059731d9687027c913135b3b856596c49a689 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 19 Sep 2015 22:28:42 +0000 Subject: Extended the prototype for matching formats in order to get it suitable for plugins. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@577 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 72 +++++ plugins/devdbg/speed.c | 3 - plugins/mobicore/mclf.c | 14 +- plugins/mobicore/mclf.h | 3 +- plugins/mobicore/mobicore.c | 6 +- plugins/pychrysa/core/Makefile.am | 1 + plugins/pychrysa/core/module.c | 2 + plugins/pychrysa/plugin.c | 340 ++++++++--------------- plugins/python/apkfiles/__init__.py | 4 +- plugins/python/apkfiles/apkfiles.py | 27 +- plugins/ropgadgets/select.c | 12 +- src/analysis/binaries/file.c | 8 +- src/analysis/binary-int.h | 12 +- src/analysis/binary.c | 307 +++++++++++++++++++-- src/analysis/binary.h | 32 ++- src/analysis/content-int.h | 10 + src/analysis/content.c | 86 ++++++ src/analysis/content.h | 10 + src/analysis/contents/file.c | 128 +++++++++ src/analysis/contents/file.h | 3 + src/analysis/disass/disassembler.c | 2 +- src/analysis/project.c | 530 ++++++++++++++++++++++++++++++++++-- src/analysis/project.h | 52 ++++ src/common/xml.c | 108 +++++++- src/common/xml.h | 11 +- src/core/formats.c | 34 ++- src/core/formats.h | 20 +- src/format/dwarf/dwarf.c | 31 ++- src/format/dwarf/dwarf.h | 4 +- src/format/elf/elf.c | 16 +- src/format/elf/elf.h | 5 +- src/format/executable-int.h | 3 + src/format/executable.c | 78 ++++++ src/format/executable.h | 9 + src/gui/menus/project.c | 13 +- src/plugins/plugin-int.h | 29 +- src/plugins/plugin.c | 26 +- 37 files changed, 1689 insertions(+), 362 deletions(-) diff --git a/ChangeLog b/ChangeLog index 166ef5d..6b28940 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,75 @@ +15-09-19 Cyrille Bagard + + * plugins/devdbg/speed.c: + Remove debug code. + + * plugins/mobicore/mclf.c: + * plugins/mobicore/mclf.h: + * plugins/mobicore/mobicore.c: + Update code. + + * plugins/pychrysa/core/Makefile.am: + Add the missing 'formats.[ch]' files to libpychrysacore_la_SOURCES. + + * plugins/pychrysa/core/module.c: + Load formats core into Python. + + * plugins/pychrysa/plugin.c: + * plugins/python/apkfiles/apkfiles.py: + * plugins/python/apkfiles/__init__.py: + * plugins/ropgadgets/select.c: + Update code. + + * src/analysis/binaries/file.c: + Disable this specific kind of instances for loaded binaries. + + * src/analysis/binary.c: + * src/analysis/binary.h: + * src/analysis/binary-int.h: + Build a standalone generic binary. Use binary contents as external + entities. Only reference the main binary format and attach debug + info to it. + + * src/analysis/content.c: + * src/analysis/content.h: + * src/analysis/content-int.h: + * src/analysis/contents/file.c: + * src/analysis/contents/file.h: + Describe, save and restore binary contents. + + * src/analysis/disass/disassembler.c: + Update code. + + * src/analysis/project.c: + * src/analysis/project.h: + Store binary contents as well as loaded binaries. Update the storing and + restoring routines. + + * src/common/xml.c: + * src/common/xml.h: + Handle long values for nodes attributes. + + * src/core/formats.c: + * src/core/formats.h: + Extend the prototype for matching formats in order to get it suitable + for plugins. + + * src/format/dwarf/dwarf.c: + * src/format/dwarf/dwarf.h: + * src/format/elf/elf.c: + * src/format/elf/elf.h: + Update code. + + * src/format/executable.c: + * src/format/executable.h: + * src/format/executable-int.h: + Store debug information when requested. + + * src/gui/menus/project.c: + * src/plugins/plugin.c: + * src/plugins/plugin-int.h: + Update code. + 15-09-11 Cyrille Bagard * configure.ac: diff --git a/plugins/devdbg/speed.c b/plugins/devdbg/speed.c index e5042ea..538a741 100644 --- a/plugins/devdbg/speed.c +++ b/plugins/devdbg/speed.c @@ -79,7 +79,6 @@ G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *plugin, Plu } - switch (action) { case PGA_DISASSEMBLY_STARTED: @@ -115,6 +114,4 @@ G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *plugin, Plu } - printf("##########\n\nPassage 0x%08x !!!\n\n################\n", action); - } diff --git a/plugins/mobicore/mclf.c b/plugins/mobicore/mclf.c index 99ff7ed..4ff44bb 100644 --- a/plugins/mobicore/mclf.c +++ b/plugins/mobicore/mclf.c @@ -56,6 +56,8 @@ static void g_mclf_format_refine_portions(const GMCLFFormat *, GBinPortion *); * * * Paramètres : content = contenu binaire à parcourir. * * parent = éventuel format exécutable déjà chargé. * +* unused = adresse non utilisée ici. * +* key = identifiant de format trouvé ou NULL. [OUT] * * * * Description : Indique si le format peut être pris en charge ici. * * * @@ -65,9 +67,9 @@ static void g_mclf_format_refine_portions(const GMCLFFormat *, GBinPortion *); * * ******************************************************************************/ -const char *mclf_is_matching(GBinContent *content, GExeFormat *parent) +FormatMatchStatus mclf_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key) { - const char *result; /* Format détecté à renvoyer */ + FormatMatchStatus result; /* Bilan à renvoyer */ vmpa2t addr; /* Tête de lecture initiale */ bool status; /* Bilan des accès mémoire */ char magic[4]; /* Idenfiant standard */ @@ -78,7 +80,13 @@ const char *mclf_is_matching(GBinContent *content, GExeFormat *parent) status &= (memcmp(magic, MC_SERVICE_HEADER_MAGIC_STR, 4) == 0); - result = status ? "mclf" : NULL; + if (status) + { + result = FMS_MATCHED; + *key = strdup("mclf"); + } + else + result = FMS_UNKNOWN; return result; diff --git a/plugins/mobicore/mclf.h b/plugins/mobicore/mclf.h index 5ac0926..78ed57b 100644 --- a/plugins/mobicore/mclf.h +++ b/plugins/mobicore/mclf.h @@ -30,6 +30,7 @@ #include +#include #include #include @@ -51,7 +52,7 @@ typedef struct _GMCLFFormatClass GMCLFFormatClass; /* Indique si le format peut être pris en charge ici. */ -const char *mclf_is_matching(GBinContent *, GExeFormat *); +FormatMatchStatus mclf_is_matching(GBinContent *, GExeFormat *, void *, char **); /* Indique le type défini pour un format d'exécutable MCLF. */ GType g_mclf_format_get_type(void); diff --git a/plugins/mobicore/mobicore.c b/plugins/mobicore/mobicore.c index 087297b..8a28a76 100644 --- a/plugins/mobicore/mobicore.c +++ b/plugins/mobicore/mobicore.c @@ -54,9 +54,11 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref) { bool result; /* Bilan à retourner */ - result &= register_format_matcher(mclf_is_matching); + result = true; - result = register_format_loader("mclf", "MobiCore Load Format", g_mclf_format_new); + result &= register_format_matcher(mclf_is_matching, NULL); + + result &= register_format_loader("mclf", "MobiCore Load Format", g_mclf_format_new); return result; diff --git a/plugins/pychrysa/core/Makefile.am b/plugins/pychrysa/core/Makefile.am index 1ffacf4..129b5af 100644 --- a/plugins/pychrysa/core/Makefile.am +++ b/plugins/pychrysa/core/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libpychrysacore.la libpychrysacore_la_SOURCES = \ + formats.h formats.c \ module.h module.c \ params.h params.c diff --git a/plugins/pychrysa/core/module.c b/plugins/pychrysa/core/module.c index a866c05..9fcede9 100644 --- a/plugins/pychrysa/core/module.c +++ b/plugins/pychrysa/core/module.c @@ -28,6 +28,7 @@ #include +#include "formats.h" #include "params.h" @@ -78,6 +79,7 @@ bool add_core_module_to_python_module(PyObject *super) result = true; + result &= register_python_formats(module); result &= register_python_params(module); loading_failed: diff --git a/plugins/pychrysa/plugin.c b/plugins/pychrysa/plugin.c index 44cb0d8..5e968e2 100644 --- a/plugins/pychrysa/plugin.c +++ b/plugins/pychrysa/plugin.c @@ -30,6 +30,8 @@ #include +#include "../../src/core/formats.h" +//#include #include @@ -74,23 +76,11 @@ static bool g_python_plugin_do_init(GPythonPlugin *, GObject *); /* 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 **); - - - - -/* Indique l'utilité pratique du greffon. */ -static PluginAction g_python_plugin_get_action(const GPythonPlugin *); - -/* Indentifie un format à associer à un contenu binaire. */ -static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *, char **, bin_t **, off_t *); - -/* Exécute une action définie sur un binaire chargé. */ -static bool g_python_plugin_execute_on_binary(GPythonPlugin *, GLoadedBinary *, PluginAction); - - -/* Exécute une action relative à un débogueur. */ -//static bool g_python_plugin_handle_debugger(const GPythonPlugin *, GBinaryDebugger *, PluginAction); +/* Exécute une action pendant un désassemblage de binaire. */ +static void g_python_plugin_process_disass(const GPythonPlugin *, PluginAction, GLoadedBinary *); @@ -143,19 +133,10 @@ static void g_python_plugin_class_init(GPythonPluginClass *klass) static void g_python_plugin_init(GPythonPlugin *plugin) { - GPluginModule *plugin_parent; /* Instance parente */ - - plugin_parent = G_PLUGIN_MODULE(plugin); - - plugin_parent->exec_on_bin = (execute_action_on_binary_fc)g_python_plugin_execute_on_binary; - //plugin_parent->handle_debugger = (execute_on_debugger_fc)g_python_plugin_handle_debugger; } - - - /****************************************************************************** * * * Paramètres : modname = nom du module à charger. * @@ -184,6 +165,7 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO 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 */ @@ -246,17 +228,6 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO goto gppn_interface_error; } - - //G_PLUGIN_MODULE(result)->get_action = (get_plugin_action_fc)g_python_plugin_get_action; - - //G_PLUGIN_MODULE(result)->is_matching = (is_matching_fc)g_python_plugin_is_matching; - - - - - - - /* Localisation des différents points d'entrée déclarés */ #define register_python_binding(inst, sym, binding) \ @@ -279,8 +250,9 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO for (i = 0; i < G_PLUGIN_MODULE(result)->interface->actions_count; i++) { - category = MASK_PLUGIN_CATEGORY(G_PLUGIN_MODULE(result)->interface->actions[i]); - sub = MASK_PLUGIN_SUB_CATEGORY(G_PLUGIN_MODULE(result)->interface->actions[i]); + action = G_PLUGIN_MODULE(result)->interface->actions[i]; + category = MASK_PLUGIN_CATEGORY(action); + sub = MASK_PLUGIN_SUB_CATEGORY(action); switch (category) { @@ -309,26 +281,39 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO } break; -#if 0 + case DPC_BINARY_PROCESSING: switch (sub) { case DPS_FORMAT: - switch (result->interface->actions[i]) + 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: - if (!load_plugin_symbol(result->module, - "handle_binary_format", &result->handle_format)) - goto bad_plugin; + /* TODO */ break; default: log_variadic_message(LMT_WARNING, _("Unknown action '0x%02x' in plugin '%s'..."), - result->interface->actions[i], filename); + action, filename); break; } @@ -336,9 +321,9 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO break; case DPS_DISASSEMBLY: - if (!load_plugin_symbol(result->module, - "process_binary_disassembly", &result->proc_disass)) - goto bad_plugin; + if (!register_python_binding(instance, process_disass, + (pg_process_disassembly_fc)g_python_plugin_process_disass)) + goto gppn_bad_plugin; break; default: @@ -349,7 +334,7 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GO } break; -#endif + default: log_variadic_message(LMT_WARNING, _("Unknown category '0x%02x' in plugin '%s'..."), category, filename); @@ -555,234 +540,152 @@ static bool g_python_plugin_do_exit(GPythonPlugin *plugin, GObject *ref) } - - - - - - /****************************************************************************** * * -* Paramètres : plugin = greffon de prise en charge à utiliser. * +* 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 l'utilité pratique du greffon. * +* Description : Indique si le format peut être pris en charge ici. * * * -* Retour : Action(s) codifiée(s), PGA_NONE par défaut. * +* Retour : Conclusion de haut niveau sur la reconnaissance effectuée. * * * * Remarques : - * * * ******************************************************************************/ -static PluginAction g_python_plugin_get_action(const GPythonPlugin *plugin) +FormatMatchStatus python_plugin_is_matching(GBinContent *content, GExeFormat *parent, GPythonPlugin *plugin, char **key) { - PluginAction result; /* Valeur à retourner */ - PyObject *value; /* Valeur obtenue */ - - value = run_python_method(plugin->instance, "get_action", NULL); - - if (value != NULL) - { - result = PyLong_AsLong(value); - Py_DECREF(value); - } - else - result = 0;//PGA_NONE; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : plugin = greffon de prise en charge à utiliser. * -* filename = éventuel nom de fichier associé ou NULL. [OUT] * -* data = données chargées. [OUT] * -* length = quantité de ces données. [OUT] * -* * -* Description : Indentifie un format à associer à un contenu binaire. * -* * -* Retour : Bilan de la recherche de correspondances. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *plugin, char **filename, bin_t **data, off_t *length) -{ - return MFA_NONE; - -#if 0 - MatchingFormatAction result; /* Valeur à retourner */ + FormatMatchStatus result; /* Bilan à renvoyer */ PyObject *args; /* Arguments pour l'appel */ - PyObject *value; /* Valeurs obtenues */ - PyObject *action; /* Action à faire suivre */ - PyObject *new_filename; /* Nouveau fichier */ - PyObject *new_data; /* Nouvelles données */ - char *tmp; /* Stockage avant recopie */ + PyObject *value; /* Valeur obtenue */ + PyObject *arg; /* Argument en élément de tuple*/ - if (*filename == NULL) - return MFA_NONE; + 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))); - PyTuple_SetItem(args, 0, PyString_FromString(*filename)); - PyTuple_SetItem(args, 1, PyByteArray_FromStringAndSize((char *)*data, *length)); - - value = run_python_method(plugin->instance, "is_matching", args); + value = run_python_method(plugin->instance, "is_format_matching", args); - if (value != NULL && PyTuple_Check(value) && PyTuple_Size(value) == 3) + if (PyTuple_Check(value)) { - action = PyTuple_GetItem(value, 0); - new_filename = PyTuple_GetItem(value, 1); - new_data = PyTuple_GetItem(value, 2); - - if (action == NULL || new_filename == NULL || new_data == NULL) - goto is_matching_bad; - - if (!PyInt_Check(action) - || (new_filename != Py_None && !PyString_Check(new_filename)) - || (new_data != Py_None && !PyByteArray_Check(new_data))) - goto is_matching_bad; - - result = PyInt_AsLong(action); - if (result >= MFA_COUNT) goto is_matching_bad; - - if (result != MFA_NONE && new_data == Py_None) goto is_matching_bad; - - if (new_filename != Py_None) - { - free(*filename); - *filename = strdup(PyString_AsString(new_filename)); - } - - /** - * La suppression de la part du greffon n'est permise que - * si une prise en charge est assurée. - */ - else if (result != MFA_NONE) - { - free(*filename); - *filename = NULL; - } - - /** - * Pareil que précédemment. - */ - if (new_data != Py_None) + if (PyTuple_Size(value) > 0) { - tmp = PyByteArray_AsString(new_data); - *length = PyByteArray_Size(new_data); - - free(*data); - - *data = (bin_t *)calloc(*length, sizeof(bin_t)); - memcpy(*data, tmp, *length * sizeof(bin_t)); - - } + arg = PyTuple_GetItem(value, 0); - goto is_matching_ok; + if (PyLong_Check(arg)) + { + result = PyLong_AsLong(arg); - } - - is_matching_bad: - - printf("Bad result from is_matching() plugin function.\n"); + switch (result) + { + case FMS_MATCHED: - result = MFA_NONE; + 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; + } - is_matching_ok: + arg = PyTuple_GetItem(value, 1); - Py_XDECREF(value); - Py_DECREF(args); + if (PyUnicode_Check(arg)) + *key = strdup(PyUnicode_AsUTF8(arg)); - return result; -#endif -} + 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; -/****************************************************************************** -* * -* Paramètres : plugin = greffon de prise en charge à utiliser. * -* binary = représentation binaire à traiter. * -* action = action attendue. * -* * -* Description : Exécute une action définie sur un binaire chargé. * -* * -* Retour : true si une action a été menée, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ + default: + g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR, + _("Unexpected result for format matching.")); + result = FMS_UNKNOWN; + break; -static bool g_python_plugin_execute_on_binary(GPythonPlugin *plugin, GLoadedBinary *binary, PluginAction action) -{ - bool result; /* Bilan à remonter */ - PyObject *args; /* Arguments pour l'appel */ - PyObject *value; /* Valeurs obtenues */ + } - args = PyTuple_New(2); + } - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(binary))); - PyTuple_SetItem(args, 1, Py_None);//PyInt_FromLong(action)); + else + { + g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_ERROR, + _("Unexpected result status for format matching.")); + result = FMS_UNKNOWN; + } - value = run_python_method(plugin->instance, "execute_on_binary", args); + } + else + g_plugin_module_log_variadic_message(G_PLUGIN_MODULE(plugin), LMT_WARNING, + _("Interpreting a empty tuple as FMS_UNKNOWN " \ + "for format matching.")); - result = (value == Py_True); + } + 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; -} +} -#if 0 /****************************************************************************** * * -* Paramètres : plugin = greffon à consulter. * -* debugger = débogueur à l'origine de l'opération. * -* action = action attendue. * +* 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 relative à un débogueur. * +* Description : Exécute une action pendant un désassemblage de binaire. * * * -* Retour : true si une action a été menée, false sinon. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool g_python_plugin_handle_debugger(const GPythonPlugin *plugin, GBinaryDebugger *debugger, PluginAction action) +static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAction action, GLoadedBinary *binary) { - bool result; /* Bilan à remonter */ PyObject *args; /* Arguments pour l'appel */ PyObject *value; /* Valeurs obtenues */ args = PyTuple_New(2); - PyTuple_SetItem(args, 0, py_binary_debugger_from_c(debugger)); - PyTuple_SetItem(args, 1, Py_None);//PyInt_FromLong(action)); + PyTuple_SetItem(args, 0, PyLong_FromLong(action)); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary))); - value = run_python_method(plugin->instance, "handle_debugger", args); - - result = (value == Py_True); + value = run_python_method(plugin->instance, "process_binary_disassembly", args); Py_XDECREF(value); Py_DECREF(args); - return result; - } -#endif - - - - @@ -791,19 +694,6 @@ static bool g_python_plugin_handle_debugger(const GPythonPlugin *plugin, GBinary /* ---------------------------------------------------------------------------------- */ - - - - - - - - - - - - - /****************************************************************************** * * * Paramètres : obj_type = type dont le dictionnaire est à compléter. * diff --git a/plugins/python/apkfiles/__init__.py b/plugins/python/apkfiles/__init__.py index 2ebf824..7da894e 100644 --- a/plugins/python/apkfiles/__init__.py +++ b/plugins/python/apkfiles/__init__.py @@ -1,2 +1,4 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- -from apkfiles import ApkFiles as apkfiles +from apkfiles.apkfiles import ApkFiles as AutoLoad diff --git a/plugins/python/apkfiles/apkfiles.py b/plugins/python/apkfiles/apkfiles.py index 7c05ca9..b85b0c8 100644 --- a/plugins/python/apkfiles/apkfiles.py +++ b/plugins/python/apkfiles/apkfiles.py @@ -1,15 +1,36 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pychrysalide import Plugin - +from pychrysalide import PluginModule import zipfile -class ApkFiles(Plugin): +class ApkFiles(PluginModule): """Open and process APK files.""" + def get_interface(self): + """Provide the full plugin description.""" + + desc = { + + 'name' : 'Welcome', + 'desc' : 'Add suppport for the APK file format', + 'version' : '0.1', + + 'actions' : [ PluginModule.PGA_PLUGIN_INIT ] + + } + + return desc + + + def init(self, ref): + """Initialise l'extension.""" + + return True + + def get_action(self): """Register the plugin for given actions.""" diff --git a/plugins/ropgadgets/select.c b/plugins/ropgadgets/select.c index 53995e5..2497dd1 100644 --- a/plugins/ropgadgets/select.c +++ b/plugins/ropgadgets/select.c @@ -1316,7 +1316,8 @@ static GBinFormat *load_external_format_for_rop_gadgets(GObject *ref) GtkEntry *entry; /* Zone de saisie de texte */ const gchar *filename; /* Nom du fichier à charger */ GBinContent *content; /* Contenu binaire chargé */ - const char *target; /* Sous-traitance requise */ + FormatMatchStatus status; /* Statut d'une reconnaissance */ + char *target; /* Sous-traitance requise */ const char *desc; /* Description humaine associée*/ /* Récupération du nom de fichier */ @@ -1338,18 +1339,21 @@ static GBinFormat *load_external_format_for_rop_gadgets(GObject *ref) /* Récupération du format de fichier associé */ - target = find_matching_format(content, NULL); - desc = get_binary_format_name(target); + status = find_matching_format(content, NULL, &target); - if (desc == NULL) + if (status != FMS_MATCHED) { g_object_unref(G_OBJECT(content)); push_status_printing_of_rop_search_step(ref, "format", _("unknown binary format"), false); goto leffrg_error; } + desc = get_binary_format_name(target); + result = load_new_named_format(target, content, NULL); + free(target); + if (result == NULL) { push_status_printing_of_rop_search_step(ref, "format", _("error while loading the binary"), false); diff --git a/src/analysis/binaries/file.c b/src/analysis/binaries/file.c index 32cd41f..c31828c 100644 --- a/src/analysis/binaries/file.c +++ b/src/analysis/binaries/file.c @@ -116,8 +116,8 @@ static void g_file_binary_init(GFileBinary *binary) loaded = G_LOADED_BINARY(binary); - loaded->save = (save_binary_fc)g_file_binary_save; - loaded->get_name = (get_binary_name_fc)g_file_binary_get_name; + //loaded->save = (save_binary_fc)g_file_binary_save; + //loaded->get_name = (get_binary_name_fc)g_file_binary_get_name; } @@ -173,7 +173,7 @@ GLoadedBinary *g_file_binary_new_from_file(const char *filename) content = g_file_content_new(filename); if (content == NULL) goto lbf_error; - target = find_matching_format(content, NULL); + target = "";//find_matching_format(content, NULL); desc = get_binary_format_name(target); if (desc == NULL) @@ -194,7 +194,7 @@ GLoadedBinary *g_file_binary_new_from_file(const char *filename) goto lbf_error; } - target = find_matching_format(content, loaded->format); + target = "";//find_matching_format(content, loaded->format); desc = get_binary_format_name(target); if (desc != NULL) diff --git a/src/analysis/binary-int.h b/src/analysis/binary-int.h index 4bfb14e..60b9662 100644 --- a/src/analysis/binary-int.h +++ b/src/analysis/binary-int.h @@ -33,11 +33,8 @@ -/* Ecrit une sauvegarde du binaire dans un fichier XML. */ -typedef bool (* save_binary_fc) (const GLoadedBinary *, xmlDocPtr, xmlXPathContextPtr, const char *); - /* Fournit le fichier correspondant à l'élément binaire. */ -typedef const char * (* get_binary_name_fc) (const GLoadedBinary *, bool); +typedef const char * (* get_binary_name_fc) (const GLoadedBinary *, bool); //// REMME /* Description de fichier binaire (instance) */ @@ -57,11 +54,12 @@ struct _GLoadedBinary DBStorage storages[DBF_COUNT]; /* Lieux d'enregistrement */ GList *collections; /* Ensemble de modifications */ - save_binary_fc save; /* Sauvegarde au format XML */ - get_binary_name_fc get_name; /* Obtention d'une description */ + get_binary_name_fc get_name; /* Obtention d'une description */ //// REMME + + GBinContent *content; /* Contenu binaire chargé */ //// REMME GExeFormat *format; /* Format du binaire */ - GDbgFormat *debug; /* Informations de débogage */ + GDbgFormat *debug; /* Informations de débogage */ //// REMME GArchProcessor *proc; /* Architecture du binaire */ GArchInstruction *instrs; /* Instructions d'assemblage */ diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 615e72e..c94f4f6 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -24,12 +24,14 @@ #include "binary.h" +#include #include #include #include #include #include + #include @@ -41,8 +43,11 @@ #include "../common/extstr.h" #include "../common/cpp.h" #include "../core/collections.h" +#include "../core/formats.h" #include "../core/params.h" +#include "../core/processors.h" #include "../glibext/chrysamarshal.h" +#include "../gui/panels/log.h" @@ -185,8 +190,11 @@ static void g_loaded_binary_init(GLoadedBinary *binary) static void g_loaded_binary_dispose(GLoadedBinary *binary) { + g_object_unref(G_OBJECT(binary->content)); + if (binary->format != NULL) g_object_unref(G_OBJECT(binary->format)); + if (binary->proc != NULL) g_object_unref(G_OBJECT(binary->proc)); @@ -222,10 +230,103 @@ static void g_loaded_binary_finalize(GLoadedBinary *binary) /****************************************************************************** * * -* Paramètres : context = contexte pour les recherches XPath. * +* Paramètres : content = contenu binaire chargé en mémoire. * +* * +* Description : Interprète un contenu binaire chargé. * +* * +* Retour : Adresse de la représentation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GLoadedBinary *g_loaded_binary_new(GBinContent *content) +{ + GLoadedBinary *result; /* Adresse à retourner */ + FormatMatchStatus status; /* Statut d'une reconnaissance */ + char *target; /* Sous-traitance requise */ + const char *desc; /* Description humaine associée*/ + const char *arch; /* Architecture d'exécution */ + + result = g_object_new(G_TYPE_LOADED_BINARY, NULL); + + log_variadic_message(LMT_PROCESS, _("Opening binary data from '%s'..."), + g_binary_content_describe(content, true)); + + g_object_ref(G_OBJECT(content)); + result->content = content; + + /* Format d'exécutable */ + + status = find_matching_format(content, NULL, &target); + assert(status == FMS_MATCHED); + + desc = get_binary_format_name(target); + + if (desc == NULL) + { + free(target); + log_simple_message(LMT_INFO, _("Unknown binary format")); + goto lbf_error; + } + else + log_variadic_message(LMT_INFO, _("Detected format: %s"), desc); + + result->format = G_EXE_FORMAT(load_new_named_format(target, content, NULL)); + + free(target); + + if (result->format == NULL) + { + log_simple_message(LMT_ERROR, _("Error while loading the binary")); + goto lbf_error; + } + + /* Informations de débogage associées */ + + if (!g_loaded_binary_attach_debug_info(result, content)) + goto lbf_error; + + /* Architecture visée */ + + arch = g_exe_format_get_target_machine(result->format); + desc = get_arch_processor_name(arch); + + if (desc == NULL) + { + log_simple_message(LMT_INFO, _("Unknown architecture")); + goto lbf_error; + } + else + log_variadic_message(LMT_INFO, _("Detected architecture: %s"), desc); + + result->proc = get_arch_processor_for_type(arch); + + if (result->proc == NULL) + { + log_simple_message(LMT_ERROR, _("Unable to load the required processor")); + goto lbf_error; + } + + return G_LOADED_BINARY(result); + + lbf_error: + + g_object_unref(G_OBJECT(result)); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire chargé en mémoire. * +* context = contexte pour les recherches XPath. * * path = chemin d'accès au noeud XML à lire. * +* project = projet dans lequel venir rechercher les contenus. * * * -* Description : Charge en mémoire le contenu d'un fichier à partir d'XML. * +* Description : Interprète un contenu binaire chargé avec un appui XML. * * * * Retour : Adresse de la représentation ou NULL en cas d'échec. * * * @@ -233,39 +334,94 @@ static void g_loaded_binary_finalize(GLoadedBinary *binary) * * ******************************************************************************/ -GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const char *path) +GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const char *path, GStudyProject *project) { GLoadedBinary *result; /* Adresse à retourner */ - char *type; /* Type de binaire à charger */ + char *content_path; /* Partie "Contenus" */ + char *access; /* Chemin d'accès à un élément */ + char *hash; /* Empreinte à retrouver */ + GBinContent *content; /* Contenu à référencer */ + + xmlXPathObjectPtr xobject; /* Cible d'une recherche */ + unsigned int i; /* Boucle de parcours */ + + /* Contenus binaires associés */ + + content_path = strdup(path); + content_path = stradd(content_path, "/Contents"); + + access = strdup(content_path); + access = stradd(access, "/Main"); + hash = get_node_text_value(context, access); + free(access); - result = NULL; + if (hash == NULL) + { + free(content_path); + return NULL; + } - type = get_node_prop_value(context, path, "type"); + content = g_study_project_find_binary_content_by_hash(project, hash); + free(hash); - if (strcmp(type, "file") == 0) - result = g_file_binary_new_from_xml(context, path); + if (content == NULL) + { + free(content_path); + return NULL; + } - free(type); + result = g_loaded_binary_new(content); if (result == NULL) + { + free(content_path); return NULL; + } - /* --------- %< --------- TODO : à bouger pour + de générique --------- %< --------- */ + xobject = get_node_xpath_object(context, "/ChrysalideProject/Contents/Content"); + for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) + { + asprintf(&access, "%s/DebugInfo[position()=%u]", content_path, i + 1); - // -> init() - //result->collections = create_collections_list(); + hash = get_node_text_value(context, access); + free(access); - if (!g_loaded_binary_load_storage(result, context, path)) - goto glbnfx_error; + if (hash == NULL) + { + free(content_path); + goto glbnfx_error; + } + + content = g_study_project_find_binary_content_by_hash(project, hash); + free(hash); + + if (content == NULL) + { + free(content_path); + goto glbnfx_error; + } + if (!g_loaded_binary_attach_debug_info(result, content)) + { + free(content_path); + goto glbnfx_error; + } + + } + + if(xobject != NULL) + xmlXPathFreeObject(xobject); - /* --------- %< --------- TODO : à bouger pur + de générique --------- %< --------- */ + free(content_path); + /* Elément divers associés au binaire */ + if (!g_loaded_binary_load_storage(result, context, path)) + goto glbnfx_error; return result; @@ -296,15 +452,88 @@ GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const ch bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path) { bool result; /* Bilan à faire remonter */ + char *content_path; /* Partie "Contenus" */ + char *access; /* Chemin d'accès à un élément */ + GBinContent *content; /* Contenu à référencer */ + const gchar *hash; /* Empreinte à mémoriser */ + size_t debugs_count; /* Quantité de formats liés */ + size_t i; /* Boucle de parcours */ + GDbgFormat *debug; /* Informations de débogage */ + + /* Contenus binaires associés */ - result = binary->save(binary, xdoc, context, path); + content_path = strdup(path); + content_path = stradd(content_path, "/Contents"); + + access = strdup(content_path); + access = stradd(access, "/Main"); + + content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); + hash = g_binary_content_get_cheksum(content); + g_object_unref(G_OBJECT(content)); + + result = add_content_to_node(xdoc, context, access, hash); + + free(access); + + debugs_count = g_exe_format_count_debug_info(binary->format); + + for (i = 0; i < debugs_count; i++) + { + asprintf(&access, "%s/DebugInfo[position()=%zu]", content_path, i); + + debug = g_exe_format_get_debug_info(binary->format, i); + + content = g_binary_format_get_content(G_BIN_FORMAT(debug)); + hash = g_binary_content_get_cheksum(content); + g_object_unref(G_OBJECT(content)); + + g_object_unref(G_OBJECT(debug)); + + result &= add_content_to_node(xdoc, context, access, hash); + + free(access); + + } + + free(content_path); + + /* Elément divers associés au binaire */ result = g_loaded_binary_save_storage(binary, xdoc, context, path); + /* Sauvegarde côté serveur */ - //// g_db_client_save(binary->local); + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : binary = élément binaire à consulter. * +* full = précise s'il s'agit d'une version longue ou non. * +* * +* Description : Fournit le nom associé à l'élément binaire. * +* * +* Retour : Nom de fichier avec chemin absolu. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_loaded_binary_get_name(const GLoadedBinary *binary, bool full) +{ + const char *result; /* Description à retourner */ + GBinContent *content; /* Contenu binaire mannipulé */ + + content = g_binary_format_get_content(G_BIN_FORMAT(binary->format)); + + result = g_binary_content_describe(content, full); + + g_object_unref(G_OBJECT(content)); return result; @@ -961,19 +1190,53 @@ void g_loaded_binary_analyse(GLoadedBinary *binary) /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * -* full = précise s'il s'agit d'une version longue ou non. * * * -* Description : Fournit le nom associé à l'élément binaire. * +* Description : Fournit le format de fichier reconnu dans le contenu binaire.* * * -* Retour : Nom de fichier avec chemin absolu. * +* Retour : Instance du format reconnu. * * * * Remarques : - * * * ******************************************************************************/ -const char *g_loaded_binary_get_name(const GLoadedBinary *binary, bool full) +bool g_loaded_binary_attach_debug_info(GLoadedBinary *binary, GBinContent *content) { - return binary->get_name(binary, full); + bool result; /* Bilan à retourner pour info */ + FormatMatchStatus status; /* Statut d'une reconnaissance */ + char *target; /* Sous-traitance requise */ + const char *desc; /* Description humaine associée*/ + GDbgFormat *debug; /* Format de débogage trouvé */ + + result = false; + + status = find_matching_format(content, binary->format, &target); + + if (status == FMS_MATCHED) + { + desc = get_binary_format_name(target); + + if (desc != NULL) + { + log_variadic_message(LMT_INFO, _("Detected debug format: %s"), desc); + + debug = G_DBG_FORMAT(load_new_named_format(target, content, binary->format)); + + if (debug == NULL) + log_simple_message(LMT_ERROR, _("Error while loading the debug information for binary")); + + else + { + result = true; + g_exe_format_add_debug_info(binary->format, debug); + } + + } + + free(target); + + } + + return result; } diff --git a/src/analysis/binary.h b/src/analysis/binary.h index 6b7d338..4ef3a0d 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -28,6 +28,7 @@ #include #include +#include "content.h" #include "db/collection.h" #include "db/client.h" #include "db/protocol.h" @@ -39,6 +40,23 @@ +/* Redéfinition depuis project.c : projet d'étude regroupant les binaires analysés (instance) */ +typedef struct _GStudyProject GStudyProject; + + + +#define G_TYPE_LOADED_BINARY g_loaded_binary_get_type() +#define G_LOADED_BINARY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_loaded_binary_get_type(), GLoadedBinary)) +#define G_IS_LOADED_BINARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_loaded_binary_get_type())) +#define G_LOADED_BINARY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LOADED_BINARY, GLoadedBinaryClass)) +#define G_IS_LOADED_BINARY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LOADED_BINARY)) +#define G_LOADED_BINARY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LOADED_BINARY, GLoadedBinaryClass)) + + + + + + #define G_TYPE_LOADED_BINARY g_loaded_binary_get_type() #define G_LOADED_BINARY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_loaded_binary_get_type(), GLoadedBinary)) #define G_IS_LOADED_BINARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_loaded_binary_get_type())) @@ -79,12 +97,18 @@ typedef enum _BinaryView /* Indique le type défini pour une description de fichier binaire. */ GType g_loaded_binary_get_type(void); -/* Charge en mémoire le contenu d'un fichier à partir d'XML. */ -GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr, const char *); +/* Interprète un contenu binaire chargé. */ +GLoadedBinary *g_loaded_binary_new(GBinContent *); + +/* Interprète un contenu binaire chargé avec un appui XML. */ +GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr, const char *, GStudyProject *); /* Ecrit une sauvegarde du binaire dans un fichier XML. */ bool g_loaded_binary_save(const GLoadedBinary *, xmlDocPtr, xmlXPathContextPtr, const char *); +/* Fournit le nom associé à l'élément binaire. */ +const char *g_loaded_binary_get_name(const GLoadedBinary *, bool); + /* ------------------------- INFORMATIONS D'ENREGISTREMENTS ------------------------- */ @@ -155,8 +179,8 @@ bool _g_loaded_binary_remove_from_collection(GLoadedBinary *, DBFeatures, GDbIte /* Lance l'analyse d'un élément binaire chargé. */ void g_loaded_binary_analyse(GLoadedBinary *); -/* Fournit le nom associé à l'élément binaire. */ -const char *g_loaded_binary_get_name(const GLoadedBinary *, bool); +/* Fournit le format de fichier reconnu dans le contenu binaire. */ +bool g_loaded_binary_attach_debug_info(GLoadedBinary *, GBinContent *); /* Fournit le format de fichier reconnu dans le contenu binaire. */ GExeFormat *g_loaded_binary_get_format(const GLoadedBinary *); diff --git a/src/analysis/content-int.h b/src/analysis/content-int.h index 7734916..c5b1659 100644 --- a/src/analysis/content-int.h +++ b/src/analysis/content-int.h @@ -29,6 +29,12 @@ +/* Fournit le nom associé au contenu binaire. */ +typedef const char * (* describe_content_fc) (const GBinContent *, bool); + +/* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ +typedef bool (* save_content_fc) (const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *); + /* Fournit une empreinte unique (SHA256) pour les données. */ typedef const gchar * (* get_checksum_fc) (GBinContent *); @@ -62,6 +68,10 @@ struct _GBinContentIface { GTypeInterface base_iface; /* A laisser en premier */ + describe_content_fc describe; /* Fournit une description */ + + save_content_fc save; /* Sauvegarde du contenu */ + get_checksum_fc get_checksum; /* Calcul de l'empreinte */ compute_size_fc compute_size; /* Calcul de la taille totale */ diff --git a/src/analysis/content.c b/src/analysis/content.c index 5a4c899..d314d0c 100644 --- a/src/analysis/content.c +++ b/src/analysis/content.c @@ -24,7 +24,11 @@ #include "content.h" +#include + + #include "content-int.h" +#include "contents/file.h" @@ -57,6 +61,88 @@ static void g_binary_content_default_init(GBinContentInterface *iface) /****************************************************************************** * * +* Paramètres : context = contexte pour les recherches XPath. * +* path = chemin d'accès au noeud XML à lire. * +* * +* Description : Charge en mémoire un contenu binaire à partir d'XML. * +* * +* Retour : Adresse de la représentation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr context, const char *path) +{ + GBinContent *result; /* Contenu en place à renvoyer */ + char *type; /* Type de binaire à charger */ + + result = NULL; + + type = get_node_prop_value(context, path, "type"); + + if (strcmp(type, "file") == 0) + result = g_file_content_new_from_xml(context, path); + + free(type); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à consulter. * +* full = précise s'il s'agit d'une version longue ou non. * +* * +* Description : Fournit le nom associé au contenu binaire. * +* * +* Retour : Nom de fichier avec chemin absolu au besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_binary_content_describe(const GBinContent *content, bool full) +{ + GBinContentIface *iface; /* Interface utilisée */ + + iface = G_BIN_CONTENT_GET_IFACE(content); + + return iface->describe(content, full); + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à traiter. * +* xdoc = structure XML en cours d'édition. * +* context = contexte à utiliser pour les recherches. * +* path = chemin d'accès réservé au binaire. * +* * +* Description : Ecrit une sauvegarde de contenu binaire dans un fichier XML. * +* * +* Retour : true si l'opération a bien tourné, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_content_save(const GBinContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path) +{ + GBinContentIface *iface; /* Interface utilisée */ + + iface = G_BIN_CONTENT_GET_IFACE(content); + + return iface->save(content, xdoc, context, path); + +} + + +/****************************************************************************** +* * * Paramètres : content = contenu binaire à venir lire. * * * * Description : Fournit une empreinte unique (SHA256) pour les données. * diff --git a/src/analysis/content.h b/src/analysis/content.h index d422dc6..0d991b9 100644 --- a/src/analysis/content.h +++ b/src/analysis/content.h @@ -31,6 +31,7 @@ #include "../arch/vmpa.h" #include "../common/endianness.h" +#include "../common/xml.h" @@ -52,6 +53,15 @@ typedef struct _GBinContentIface GBinContentIface; /* Détermine le type d'une interface pour la lecture de binaire. */ GType g_binary_content_get_type(void) G_GNUC_CONST; +/* Charge en mémoire un contenu binaire à partir d'XML. */ +GBinContent *g_binary_content_new_from_xml(xmlXPathContextPtr, const char *); + +/* Fournit le nom associé au contenu binaire. */ +const char *g_binary_content_describe(const GBinContent *, bool); + +/* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ +bool g_binary_content_save(const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *); + /* Fournit une empreinte unique (SHA256) pour les données. */ const gchar *g_binary_content_get_cheksum(GBinContent *); diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c index eb0d488..9f1c10c 100644 --- a/src/analysis/contents/file.c +++ b/src/analysis/contents/file.c @@ -27,12 +27,14 @@ #include #include #include +#include #include #include #include #include "../content-int.h" +#include "../../common/extstr.h" @@ -41,6 +43,8 @@ struct _GFileContent { GObject parent; /* A laisser en premier */ + char *filename; /* Fichier chargé en mémoire */ + bin_t *data; /* Contenu binaire représenté */ mrange_t range; /* Couverture du binaire */ @@ -72,6 +76,12 @@ static void g_file_content_dispose(GFileContent *); /* Procède à la libération totale de la mémoire. */ static void g_file_content_finalize(GFileContent *); +/* Fournit le nom associé au contenu binaire. */ +static const char *g_file_content_describe(const GFileContent *, bool); + +/* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ +static bool g_file_content_save(const GFileContent *, xmlDocPtr, xmlXPathContextPtr, const char *); + /* Fournit une empreinte unique (SHA256) pour les données. */ static const gchar *g_file_content_get_checksum(GFileContent *); @@ -166,6 +176,10 @@ static void g_file_content_init(GFileContent *content) static void g_file_content_interface_init(GBinContentInterface *iface) { + iface->describe = (describe_content_fc)g_file_content_describe; + + iface->save = (save_content_fc)g_file_content_save; + iface->get_checksum = (get_checksum_fc)g_file_content_get_checksum; iface->compute_size = (compute_size_fc)g_file_content_compute_size; @@ -217,6 +231,8 @@ static void g_file_content_dispose(GFileContent *content) static void g_file_content_finalize(GFileContent *content) { + free(content->filename); + if (content->data != NULL) free(content->data); @@ -275,6 +291,8 @@ GBinContent *g_file_content_new(const char *filename) result = g_object_new(G_TYPE_FILE_CONTENT, NULL); + result->filename = strdup(filename); + result->data = (bin_t *)malloc(info.st_size); memcpy(result->data, content, info.st_size); @@ -295,6 +313,116 @@ GBinContent *g_file_content_new(const char *filename) /****************************************************************************** * * +* Paramètres : context = contexte pour les recherches XPath. * +* path = chemin d'accès au noeud XML à lire. * +* * +* Description : Charge en mémoire le contenu d'un fichier à partir d'XML. * +* * +* Retour : Adresse de la représentation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr context, const char *path) +{ + GBinContent *result; /* Adresse à retourner */ + char *access; /* Chemin pour une sous-config.*/ + char *filename; /* Chemin du binaire à charger */ + + result = NULL; + + /* Chemin du fichier à retrouver */ + + access = strdup(path); + access = stradd(access, "/Filename"); + + filename = get_node_text_value(context, access); + + free(access); + + /* Chargement */ + + if (filename != NULL) + { + result = g_file_content_new(filename); + free(filename); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à consulter. * +* full = précise s'il s'agit d'une version longue ou non. * +* * +* Description : Fournit le nom associé au contenu binaire. * +* * +* Retour : Nom de fichier avec chemin absolu au besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *g_file_content_describe(const GFileContent *content, bool full) +{ + const char *result; /* Description à retourner */ + + if (full) + result = content->filename; + else + result = strrchr(content->filename, G_DIR_SEPARATOR) + 1; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à traiter. * +* xdoc = structure XML en cours d'édition. * +* context = contexte à utiliser pour les recherches. * +* path = chemin d'accès réservé au binaire. * +* * +* Description : Ecrit une sauvegarde de contenu binaire dans un fichier XML. * +* * +* Retour : true si l'opération a bien tourné, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_file_content_save(const GFileContent *content, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path) +{ + bool result; /* Bilan à faire remonter */ + char *access; /* Chemin d'accès à un élément */ + + result = true; + + /* Type */ + + result &= add_string_attribute_to_node(xdoc, context, path, "type", "file"); + + /* Nom du fichier associé */ + + access = strdup(path); + access = stradd(access, "/Filename"); + + result &= add_content_to_node(xdoc, context, access, content->filename); + + free(access); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : content = contenu binaire à venir lire. * * * * Description : Fournit une empreinte unique (SHA256) pour les données. * diff --git a/src/analysis/contents/file.h b/src/analysis/contents/file.h index 2e3cfef..0985f6b 100644 --- a/src/analysis/contents/file.h +++ b/src/analysis/contents/file.h @@ -53,6 +53,9 @@ GType g_file_content_get_type(void); /* Charge en mémoire le contenu d'un fichier donné. */ GBinContent *g_file_content_new(const char *); +/* Charge en mémoire le contenu d'un fichier à partir d'XML. */ +GBinContent *g_file_content_new_from_xml(xmlXPathContextPtr, const char *); + #endif /* _ANALYSIS_CONTENTS_FILE_H */ diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index cd16429..990ab0f 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -705,7 +705,7 @@ void disassemble_binary(GLoadedBinary *binary, GArchInstruction **instrs, GCodeB checksum = g_binary_content_get_cheksum(content); g_object_unref(G_OBJECT(content)); - build_disass_prologue(*buffer, g_loaded_binary_get_name(binary, true), checksum); + build_disass_prologue(*buffer, g_binary_content_describe(content, true), checksum); disass = g_delayed_disassembly_new(binary, instrs, *buffer); g_signal_connect(disass, "work-completed", G_CALLBACK(ack), binary); diff --git a/src/analysis/project.c b/src/analysis/project.c index 5bb028f..db00f09 100644 --- a/src/analysis/project.c +++ b/src/analysis/project.c @@ -29,14 +29,20 @@ #include +#include + + #include "binaries/file.h" #include "../common/xml.h" +#include "../core/formats.h" #include "../core/params.h" #include "../glibext/signal.h" #include "../gtkext/easygtk.h" +#include "../glibext/delayed-int.h" #include "../gtkext/gtkblockview.h" #include "../gtkext/gtkgraphview.h" #include "../gtkext/gtksourceview.h" +#include "../gui/panels/log.h" #include "../gui/panels/panel.h" @@ -44,6 +50,14 @@ /* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */ +/* Conservation d'un contenu chargé */ +typedef struct _loaded_content +{ + GBinContent *content; /* Contenu binaire en place */ + ProjectContentState state; /* Renseigne le type de contenu*/ + +} loaded_content; + /* Conservation d'un binaire chargé */ typedef struct _loaded_binary { @@ -65,9 +79,13 @@ struct _GStudyProject char *filename; /* Lieu d'enregistrement */ + loaded_content *contents; /* Contenus binaires chargés */ + size_t contents_count; /* Nombre de ces contenus */ + GMutex cnt_mutex; /* Modification de la liste */ + loaded_binary **binaries; /* Fichiers binaires associés */ size_t binaries_count; /* Nombre de ces fichiers */ - GMutex mutex; /* Modification de la liste */ + GMutex bin_mutex; /* Modification de la liste */ }; @@ -91,6 +109,49 @@ static void g_study_project_hide(const GStudyProject *); + + +/* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */ + + +/* Ensembles binaires à désassembler (instance) */ +struct _GDelayedStudy +{ + GDelayedWork parent; /* A laisser en premier */ + + GStudyProject *project; /* Projet de rattachement */ + GBinContent *content; /* Contenu binaire à traiter */ + ProjectContentState state; /* Renseigne le type de contenu*/ + + bool only_preload; /* Enregistrement seulement ? */ + +}; + +/* Ensembles binaires à désassembler (classe) */ +struct _GDelayedStudyClass +{ + GDelayedWorkClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des intégrations de binaires à étudier. */ +static void g_delayed_study_class_init(GDelayedStudyClass *); + +/* Initialise une intégration de binaire à étudier. */ +static void g_delayed_study_init(GDelayedStudy *); + +/* Supprime toutes les références externes. */ +static void g_delayed_study_dispose(GDelayedStudy *); + +/* Procède à la libération totale de la mémoire. */ +static void g_delayed_study_finalize(GDelayedStudy *); + +/* Prépare une intégration de binaire au projet courant. */ +static void g_delayed_study_process(GDelayedStudy *, GtkExtStatusBar *); + + + /* ---------------------------------------------------------------------------------- */ /* DEFINITION D'UN PROJET INTERNE */ /* ---------------------------------------------------------------------------------- */ @@ -132,7 +193,9 @@ static void g_study_project_class_init(GStudyProjectClass *klass) static void g_study_project_init(GStudyProject *project) { - g_mutex_init(&project->mutex); + g_mutex_init(&project->cnt_mutex); + + g_mutex_init(&project->bin_mutex); } @@ -180,11 +243,17 @@ GStudyProject *g_study_project_open(GObject *ref, const char *filename) GStudyProject *result; /* Adresse à retourner */ xmlDocPtr xdoc; /* Structure XML chargée */ xmlXPathContextPtr context; /* Contexte pour les XPath */ + unsigned int root_contents; /* Quantité de contenus majeurs*/ + GAsyncQueue *sema; /* Sémaphore taisant son nom */ xmlXPathObjectPtr xobject; /* Cible d'une recherche */ unsigned int i; /* Boucle de parcours */ size_t access_len; /* Taille d'un chemin interne */ char *access; /* Chemin pour une sous-config.*/ - GLoadedBinary *binary; /* Représentation à intégrer */ + GBinContent *content; /* Contenu binaire retrouvé */ + long state; /* Etat de ce contenu binaire */ + bool status; /* Bilan d'une lecture */ + GDelayedStudy *dstudy; /* Etude complémentaire à mener*/ + GLoadedBinary *binary; /* Représentation à intégrer */ if (!open_xml_file(filename, &xdoc, &context)) return NULL; @@ -192,19 +261,78 @@ GStudyProject *g_study_project_open(GObject *ref, const char *filename) result->filename = strdup(filename); - /* Chargement des éléments binaires attachés */ + /* Préparations aux traitements parallèles */ + + root_contents = 0; + + sema = g_async_queue_new(); + + void ack_content_processing(GDelayedStudy *dstudy, GAsyncQueue *aqueue) + { + g_async_queue_push(aqueue, GINT_TO_POINTER(1)); + } + + /* Chargement des contenus binaires attachés */ + + xobject = get_node_xpath_object(context, "/ChrysalideProject/Contents/Content"); + + for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) + { + access_len = strlen("/ChrysalideProject/Contents/Content[position()=") + SIZE_T_MAXLEN + strlen("]") + 1; + + access = calloc(access_len, sizeof(char)); + snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%u]", i + 1); + + content = g_binary_content_new_from_xml(context, access); + status = get_node_prop_long_value(context, access, "state", &state); + + free(access); + + if (!status) + { + log_variadic_message(LMT_PROCESS, _("bad state for content '%s' ; skipping..."), + g_binary_content_describe(content, true)); + continue; + } + + /* Le contenu peut être un conteneur ? */ + if (state == PCS_ROOT) + { + dstudy = g_delayed_study_new(result, content, state); + g_signal_connect(dstudy, "work-completed", G_CALLBACK(ack_content_processing), sema); + + g_delayed_study_preload_only(dstudy); + + root_contents++; + + study_new_content(dstudy); + + } + + } + + if(xobject != NULL) + xmlXPathFreeObject(xobject); + + /* Attente pour la réception de contenus supplémentaires éventuels */ + + for (i = 0; i < root_contents; i++) + g_async_queue_pop(sema); + + g_async_queue_unref(sema); - xobject = get_node_xpath_object(context, "/OpenIDAProject/Binaries/Binary"); + /* Chargement des binaires analysés */ + + xobject = get_node_xpath_object(context, "/ChrysalideProject/Binaries/Binary"); for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) { - access_len = strlen("/OpenIDAProject/Binaries/Binary[position()=") - + strlen("4294967295" /* UINT_MAX */) + strlen("]") + 1; + access_len = strlen("/ChrysalideProject/Binaries/Binary[position()=") + SIZE_T_MAXLEN + strlen("]") + 1; access = calloc(access_len, sizeof(char)); - snprintf(access, access_len, "/OpenIDAProject/Binaries/Binary[position()=%u]", i + 1); + snprintf(access, access_len, "/ChrysalideProject/Binaries/Binary[position()=%u]", i + 1); - binary = g_loaded_binary_new_from_xml(context, access); + binary = g_loaded_binary_new_from_xml(context, access, result); free(access); @@ -254,17 +382,36 @@ bool g_study_project_save(GStudyProject *project, const char *filename) result = create_new_xml_file(&xdoc, &context); - result &= (ensure_node_exist(xdoc, context, "/OpenIDAProject") != NULL); + result &= (ensure_node_exist(xdoc, context, "/ChrysalideProject") != NULL); + + /* Enregistrement des contenus binaires attachés */ - /* Enregistrement des éléments binaires attachés */ + for (i = 0; i < project->contents_count && result; i++) + { + if (!project->contents[i].state == PCS_INTERNAL) continue; + + access_len = strlen("/ChrysalideProject/Contents/Content[position()=") + SIZE_T_MAXLEN + strlen("]") + 1; + + access = calloc(access_len, sizeof(char)); + snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%zu]", i + 1); + + result = g_binary_content_save(project->contents[i].content, xdoc, context, access); + + if (result) + result = add_long_attribute_to_node(xdoc, context, access, "state", project->contents[i].state); + + free(access); + + } + + /* Enregistrement des binaires analysés */ for (i = 0; i < project->binaries_count && result; i++) { - access_len = strlen("/OpenIDAProject/Binaries/Binary[position()=") - + strlen("4294967295" /* UINT_MAX */) + strlen("]") + 1; + access_len = strlen("/ChrysalideProject/Binaries/Binary[position()=") + SIZE_T_MAXLEN + strlen("]") + 1; access = calloc(access_len, sizeof(char)); - snprintf(access, access_len, "/OpenIDAProject/Binaries/Binary[position()=%zu]", i + 1); + snprintf(access, access_len, "/ChrysalideProject/Binaries/Binary[position()=%zu]", i + 1); result = g_loaded_binary_save(project->binaries[i]->binary, xdoc, context, access); @@ -311,6 +458,88 @@ const char *g_study_project_get_filename(const GStudyProject *project) /****************************************************************************** * * +* Paramètres : project = projet dont le contenu est à compléter. * +* content = contenu binaire à mémoriser pour le projet. * +* state = état du contenu à conserver. * +* * +* Description : Assure l'intégration d'un contenu binaire dans un projet. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_study_project_add_binary_content(GStudyProject *project, GBinContent *content, ProjectContentState state) +{ + loaded_content *new; /* Nouveau contenu à définir */ + + g_mutex_lock(&project->cnt_mutex); + + project->contents = (loaded_content *)realloc(project->contents, + ++project->contents_count * sizeof(loaded_content)); + + new = &project->contents[project->contents_count - 1]; + + g_object_ref(G_OBJECT(content)); + + new->content = content; + new->state = state; + + g_mutex_unlock(&project->cnt_mutex); + + +} + + +/****************************************************************************** +* * +* Paramètres : project = projet dont le contenu est à compléter. * +* hash = empreinte du contenu à retrouver. * +* * +* Description : Recherche un contenu binaire du projet selon son empreinte. * +* * +* Retour : Contenu avec propriété transférée ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *project, const char *hash) +{ + GBinContent *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + GBinContent *iter; /* Contenu binaire analysé */ + const gchar *other; /* Autre empreinte à comparer */ + + result = NULL; + + g_mutex_lock(&project->cnt_mutex); + + for (i = 0; i < project->contents_count && result == NULL; i++) + { + iter = project->contents[i].content; + other = g_binary_content_get_cheksum(iter); + + if (strcmp(hash, other) == 0) + { + g_object_ref(G_OBJECT(iter)); + result = iter; + } + + } + + g_mutex_unlock(&project->cnt_mutex); + + return result; + +} + + + + +/****************************************************************************** +* * * Paramètres : binary = élément binaire tout juste désassemblé. * * project = projet dont le contenu est à compléter. * * * @@ -431,7 +660,7 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina /* Enregistrement dans le projet */ - g_mutex_lock(&project->mutex); + g_mutex_lock(&project->bin_mutex); project->binaries = (loaded_binary **)realloc(project->binaries, ++project->binaries_count * sizeof(loaded_binary *)); @@ -440,7 +669,7 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina project->binaries[result] = loaded; - g_mutex_unlock(&project->mutex); + g_mutex_unlock(&project->bin_mutex); update_project_area(project); @@ -714,3 +943,272 @@ void push_project_into_recent_list(const GStudyProject *project) g_generic_config_set_value(get_main_configuration(), MPK_LAST_PROJECT, project->filename); } + + + +/* ---------------------------------------------------------------------------------- */ +/* AMORCE POUR CHARGEMENT DE CONTENUS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour les tâches de préparations d'étude. */ +G_DEFINE_TYPE(GDelayedStudy, g_delayed_study, G_TYPE_DELAYED_WORK); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des intégrations de binaires à étudier. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_study_class_init(GDelayedStudyClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_study_dispose; + object->finalize = (GObjectFinalizeFunc)g_delayed_study_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : dstudy = instance à initialiser. * +* * +* Description : Initialise une intégration de binaire à étudier. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_study_init(GDelayedStudy *dstudy) +{ + G_DELAYED_WORK(dstudy)->run = (run_task_fc)g_delayed_study_process; + + dstudy->only_preload = false; + +} + + +/****************************************************************************** +* * +* Paramètres : binary = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_study_dispose(GDelayedStudy *dstudy) +{ + g_object_unref(G_OBJECT(dstudy->project)); + g_object_unref(G_OBJECT(dstudy->content)); + + G_OBJECT_CLASS(g_delayed_study_parent_class)->dispose(G_OBJECT(dstudy)); + +} + + +/****************************************************************************** +* * +* Paramètres : binary = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_study_finalize(GDelayedStudy *dstudy) +{ + G_OBJECT_CLASS(g_delayed_study_parent_class)->finalize(G_OBJECT(dstudy)); + +} + + +/****************************************************************************** +* * +* Paramètres : project = projet dont le contenu est à compléter. * +* content = contenu binaire chargé à analyser. * +* state = état du contenu à conserver. * +* * +* Description : Crée une tâche d'intégration de contenu binaire. * +* * +* Retour : Tâche créée. * +* * +* Remarques : L'appelant perd la propriété du contenu. * +* * +******************************************************************************/ + +GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content, ProjectContentState state) +{ + GDelayedStudy *result; /* Tâche à retourner */ + + result = g_object_new(G_TYPE_DELAYED_STUDY, NULL); + + g_object_ref(G_OBJECT(project)); + result->project = project; + + g_object_ref(G_OBJECT(content)); + result->content = content; + + result->state = state; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : dstudy = intégration à mener. * +* statusbar = barre de statut à tenir informée. * +* * +* Description : Prépare une intégration de binaire au projet courant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_study_process(GDelayedStudy *dstudy, GtkExtStatusBar *statusbar) +{ + FormatMatchStatus status; /* Statut d'une reconnaissance */ + char *target; /* Sous-traitance requise */ + GLoadedBinary *binary; /* Représentation chargée */ + + status = find_matching_format(dstudy->content, NULL, &target); + + switch (status) + { + case FMS_MATCHED: + + if (dstudy->only_preload) + g_study_project_add_binary_content(dstudy->project, dstudy->content, dstudy->state); + + else + { + binary = g_loaded_binary_new(dstudy->content); + + if (binary != NULL) + { + g_study_project_add_binary_content(dstudy->project, dstudy->content, dstudy->state); + + g_signal_connect_to_main(binary, "disassembly-done", + G_CALLBACK(g_study_project_add_loaded_binary), + dstudy->project, g_cclosure_marshal_VOID__VOID); + + g_loaded_binary_analyse(binary); + + } + + } + + break; + + case FMS_FORWARDED: + /** + * L'émetteur de ce type de réponse a pour charge de + * reprogrammer lui même l'analyse de nouveaux contenus. + */ + log_variadic_message(LMT_PROCESS, _("binary '%s' contains other binaries..."), + g_binary_content_describe(dstudy->content, true)); + + if (dstudy->state == PCS_ROOT) + g_study_project_add_binary_content(dstudy->project, dstudy->content, PCS_ROOT); + + break; + + default: + /** + * Les jeux sont faits pour le contenu binaire courant. + */ + log_variadic_message(LMT_PROCESS, _("Unknown binary format for '%s'..."), + g_binary_content_describe(dstudy->content, true)); + break; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : dstudy = tâche d'analyse de contenu pour projet à mener. * +* * +* Description : Limite l'étude et l'intégration d'un contenu binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_delayed_study_preload_only(GDelayedStudy *dstudy) +{ + dstudy->only_preload = true; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire chargé à analyser. * +* state = état du contenu à conserver. * +* * +* Description : Programme l'étude et l'intégration d'un contenu binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void qck_study_new_content(GBinContent *content, ProjectContentState state) +{ + GDelayedStudy *dstudy; /* Etude à conduire */ + + dstudy = g_delayed_study_new(get_current_project(), content, state); + + study_new_content(dstudy); + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire chargé à analyser. * +* state = état du contenu à conserver. * +* * +* Description : Programme l'étude et l'intégration d'un contenu binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void study_new_content(GDelayedStudy *dstudy) +{ + GWorkQueue *queue; /* Gestionnaire de différés */ + + queue = get_work_queue(); + g_work_queue_schedule_work(queue, G_DELAYED_WORK(dstudy)); + +} diff --git a/src/analysis/project.h b/src/analysis/project.h index 05e7f12..5f5b38c 100644 --- a/src/analysis/project.h +++ b/src/analysis/project.h @@ -66,6 +66,23 @@ bool g_study_project_save(GStudyProject *, const char *); /* Indique le chemin du fichier destiné à la sauvegarde. */ const char *g_study_project_get_filename(const GStudyProject *); +/* Etat d'un contenu binaire du projet */ +typedef enum _ProjectContentState +{ + PCS_ROOT, /* Contenu principal */ + PCS_INTERNAL, /* Contenu dérivé */ + PCS_ATTACHED, /* Contenu complémentaire */ + + PCS_COUNT + +} ProjectContentState; + +/* Assure l'intégration d'un contenu binaire dans un projet. */ +void g_study_project_add_binary_content(GStudyProject *, GBinContent *, ProjectContentState); + +/* Recherche un contenu binaire du projet selon son empreinte. */ +GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *, const char *); + /* Assure l'intégration d'un élément binaire dans un projet. */ void g_study_project_add_loaded_binary(GLoadedBinary *, GStudyProject *); @@ -103,4 +120,39 @@ void push_project_into_recent_list(const GStudyProject *); +/* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */ + + +#define G_TYPE_DELAYED_STUDY g_delayed_study_get_type() +#define G_DELAYED_STUDY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_study_get_type(), GDelayedStudy)) +#define G_IS_DELAYED_STUDY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_study_get_type())) +#define G_DELAYED_STUDY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_STUDY, GDelayedStudyClass)) +#define G_IS_DELAYED_STUDY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_STUDY)) +#define G_DELAYED_STUDY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_STUDY, GDelayedStudyClass)) + + +/* Ensembles binaires à désassembler (instance) */ +typedef struct _GDelayedStudy GDelayedStudy; + +/* Ensembles binaires à désassembler (classe) */ +typedef struct _GDelayedStudyClass GDelayedStudyClass; + + +/* Indique le type défini pour les tâches de préparations d'étude. */ +GType g_delayed_study_get_type(void); + +/* Crée une tâche d'intégration de contenu binaire. */ +GDelayedStudy *g_delayed_study_new(GStudyProject *, GBinContent *, ProjectContentState); + +/* Limite l'étude et l'intégration d'un contenu binaire. */ +void g_delayed_study_preload_only(GDelayedStudy *); + +/* Programme l'étude et l'intégration d'un contenu binaire. */ +void qck_study_new_content(GBinContent *, ProjectContentState); + +/* Programme l'étude et l'intégration d'un contenu binaire. */ +void study_new_content(GDelayedStudy *); + + + #endif /* _PROJECT_H */ diff --git a/src/common/xml.c b/src/common/xml.c index 1e2871b..a9c65b5 100644 --- a/src/common/xml.c +++ b/src/common/xml.c @@ -27,6 +27,7 @@ #include #include +#include #include @@ -322,6 +323,43 @@ char *qck_get_node_prop_value(xmlNodePtr node, const char *name) /****************************************************************************** * * +* Paramètres : node = noeud dont une propriété est à lire. * +* name = nom de la propriété à lire. * +* out = valeur entière lue depuis le contenu textuel. [OUT] * +* * +* Description : Obtient la valeur entière d'une propriété d'un élément. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool qck_get_node_prop_long_value(xmlNodePtr node, const char *name, long *out) +{ + bool result; /* Bilan à retourner */ + char *value; /* Valeur brute lue */ + + value = qck_get_node_prop_value(node, name); + + if (value) + { + result = true; + + *out = strtol(value, NULL, 10); + free(value); + + } + else + result = false; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : xpathCtx = contexte à utiliser pour les recherches. * * path = chemin d'accès au noeud à traiter. * * name = nom de la propriété à lire. * @@ -356,6 +394,41 @@ char *get_node_prop_value(xmlXPathContextPtr xpathCtx, const char *path, const c /****************************************************************************** * * +* Paramètres : xpathCtx = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud à traiter. * +* name = nom de la propriété à lire. * +* out = valeur entière obtenue via contenu textuel. [OUT] * +* * +* Description : Obtient la valeur entière d'une propriété d'un élément. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_node_prop_long_value(xmlXPathContextPtr xpathCtx, const char *path, const char *name, long *out) +{ + bool result; /* Bilan à retourner */ + xmlXPathObjectPtr xpathObj; /* Point de départ XML */ + + result = NULL; + + xpathObj = get_node_xpath_object(xpathCtx, path); + if (xpathObj == NULL) return NULL; + + if (xpathObj->nodesetval->nodeNr > 0) + result = qck_get_node_prop_long_value(xpathObj->nodesetval->nodeTab[0], name, out); + + xmlXPathFreeObject(xpathObj); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : node = noeud de texte avec un lien avec le document XML. * * * * Description : Construit un chemin d'accès complet selon le fichier XML. * @@ -965,16 +1038,13 @@ bool _add_string_attribute_to_node(xmlNodePtr node, const char *name, const char bool add_string_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *name, const char *value) { xmlNodePtr node; /* Noeud à modifier */ - xmlAttrPtr attrib; /* Attribut créé et en place */ if (value == NULL) return true; node = ensure_node_exist(xdoc, context, path); if (node == NULL) return false; - attrib = xmlSetProp(node, BAD_CAST name, BAD_CAST value); - - return (attrib != NULL); + return _add_string_attribute_to_node(node, name, value); } @@ -993,7 +1063,7 @@ bool add_string_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, co * * ******************************************************************************/ -bool add_long_attribute_to_node(xmlNodePtr node, const char *name, long value) +bool _add_long_attribute_to_node(xmlNodePtr node, const char *name, long value) { char tmp[11/*strlen("2147483647")*/]; /* Stockage temporaire */ @@ -1002,3 +1072,31 @@ bool add_long_attribute_to_node(xmlNodePtr node, const char *name, long value) return _add_string_attribute_to_node(node, name, tmp); } + + +/****************************************************************************** +* * +* Paramètres : xdoc = structure XML chargée. * +* context = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud visé. * +* name = nom de la propriété à créer. * +* value = valeur numérique à placer. * +* * +* Description : Ajoute une propriété à un noeud existant donné. * +* * +* Retour : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_long_attribute_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *name, long value) +{ + xmlNodePtr node; /* Noeud à modifier */ + + node = ensure_node_exist(xdoc, context, path); + if (node == NULL) return false; + + return _add_long_attribute_to_node(node, name, value); + +} diff --git a/src/common/xml.h b/src/common/xml.h index 8cb8c0e..60891f7 100644 --- a/src/common/xml.h +++ b/src/common/xml.h @@ -68,9 +68,15 @@ char *get_node_text_value(xmlXPathContextPtr, const char *); /* Obtient la valeur d'une propriété d'un élément. */ char *qck_get_node_prop_value(xmlNodePtr, const char *); +/* Obtient la valeur entière d'une propriété d'un élément. */ +bool qck_get_node_prop_long_value(xmlNodePtr, const char *, long *); + /* Obtient la valeur d'une propriété d'un élément. */ char *get_node_prop_value(xmlXPathContextPtr, const char *, const char *); +/* Obtient la valeur entière d'une propriété d'un élément. */ +bool get_node_prop_long_value(xmlXPathContextPtr, const char *, const char *, long *); + /* Construit un chemin d'accès complet selon le fichier XML. */ char *qck_build_filename_with_doc_url(xmlNodePtr); @@ -133,7 +139,10 @@ bool _add_string_attribute_to_node(xmlNodePtr, const char *, const char *); bool add_string_attribute_to_node(xmlDocPtr, xmlXPathContextPtr, const char *, const char *, const char *); /* Ajoute une propriété à un noeud existant donné. */ -bool add_long_attribute_to_node(xmlNodePtr, const char *, long); +bool _add_long_attribute_to_node(xmlNodePtr, const char *, long); + +/* Ajoute une propriété à un noeud existant donné. */ +bool add_long_attribute_to_node(xmlDocPtr, xmlXPathContextPtr, const char *, const char *, long); diff --git a/src/core/formats.c b/src/core/formats.c index 891fc12..1326fc4 100644 --- a/src/core/formats.c +++ b/src/core/formats.c @@ -41,6 +41,7 @@ typedef struct _format_matcher_t { format_match_fc func; /* Recherche de correspondance */ + void *data; /* Eventuelle donnée à y lier */ } format_matcher_t; @@ -76,6 +77,7 @@ static format_loader_t *find_format_by_key(const char *); /****************************************************************************** * * * Paramètres : func = procédure de détection à utiliser. * +* data = éventuelle donnée à associer aux opérations. * * * * Description : Enregistre un détection de format(s) binaire(s). * * * @@ -85,18 +87,24 @@ static format_loader_t *find_format_by_key(const char *); * * ******************************************************************************/ -bool register_format_matcher(format_match_fc func) +bool register_format_matcher(format_match_fc func, void *data) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ + const format_matcher_t *cur; /* Elément parcouru et analysé */ format_matcher_t *new; /* Nouvel élément à définir */ g_rw_lock_writer_lock(&_formats_lock); for (i = 0; i < _formats_matchers_count; i++) - if (_formats_matchers[i].func == func) + { + cur = &_formats_matchers[i]; + + if (cur->func == func && cur->data == data) break; + } + result = (i == _formats_matchers_count); if (result) @@ -107,6 +115,7 @@ bool register_format_matcher(format_match_fc func) new = &_formats_matchers[_formats_matchers_count - 1]; new->func = func; + new->data = data; } @@ -186,9 +195,9 @@ bool load_hard_coded_formats_definitions(void) /* Détections */ - result &= register_format_matcher(dwarf_is_matching); + result &= register_format_matcher(dwarf_is_matching, NULL); - result &= register_format_matcher(elf_is_matching); + result &= register_format_matcher(elf_is_matching, NULL); /* Chargements */ @@ -315,27 +324,32 @@ const char *get_binary_format_name(const char *key) * * * Paramètres : content = contenu binaire à parcourir. * * parent = éventuel format exécutable déjà chargé. * +* key = identifiant de format trouvé ou NULL. [OUT] * * * * Description : Identifie un format binaire par son contenu. * * * -* Retour : Identifiant du format binaire trouvé ou NULL si échec. * +* Retour : Conclusion de haut niveau sur la reconnaissance effectuée. * * * * Remarques : - * * * ******************************************************************************/ -const char *find_matching_format(GBinContent *content, GExeFormat *parent) +FormatMatchStatus find_matching_format(GBinContent *content, GExeFormat *parent, char **key) { - const char *result; /* Identifiant à retourner */ + FormatMatchStatus result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ + const format_matcher_t *cur; /* Elément parcouru et analysé */ - result = NULL; + result = FMS_UNKNOWN; g_rw_lock_reader_lock(&_formats_lock); - for (i = 0; i < _formats_matchers_count && result == NULL; i++) + for (i = 0; i < _formats_matchers_count && result == FMS_UNKNOWN; i++) { - result = _formats_matchers[i].func(content, parent); + cur = &_formats_matchers[i]; + + result = cur->func(content, parent, cur->data, key); + } g_rw_lock_reader_unlock(&_formats_lock); diff --git a/src/core/formats.h b/src/core/formats.h index 8857217..76b57d0 100644 --- a/src/core/formats.h +++ b/src/core/formats.h @@ -34,15 +34,27 @@ +/* Conclusion d'une opération de reconnaissance */ +typedef enum _FormatMatchStatus +{ + FMS_MATCHED, /* Correspondance établie */ + FMS_FORWARDED, /* Sous-formats détectés */ + FMS_UNKNOWN, /* Aucun format reconnu */ + + FMS_COUNT + +} FormatMatchStatus; + + /* Indication à propos du support d'un format */ -typedef const char * (* format_match_fc) (GBinContent *, GExeFormat *); +typedef FormatMatchStatus (* format_match_fc) (GBinContent *, GExeFormat *, void *, char **); /* Méthode de chargement d'un format */ typedef GBinFormat * (* format_load_fc) (GBinContent *, GExeFormat *); /* Enregistre un détection de format(s) binaire(s). */ -bool register_format_matcher(format_match_fc); +bool register_format_matcher(format_match_fc, void *); /* Enregistre un format de contenu binaire donné. */ bool register_format_loader(const char *, const char *, format_load_fc); @@ -57,11 +69,11 @@ void unload_formats_definitions(void); const char *get_binary_format_name(const char *); /* Identifie un format binaire par son contenu. */ -const char *find_matching_format(GBinContent *, GExeFormat *); +FormatMatchStatus find_matching_format(GBinContent *, GExeFormat *, char **); /* Charge le format binaire correspondant à un type. */ GBinFormat *load_new_named_format(const char *, GBinContent *, GExeFormat *); -#endif /* _ANALYSIS_DB_COLLECTION_H */ +#endif /* _CORE_FORMATS_H */ diff --git a/src/format/dwarf/dwarf.c b/src/format/dwarf/dwarf.c index db8335b..519aa49 100644 --- a/src/format/dwarf/dwarf.c +++ b/src/format/dwarf/dwarf.c @@ -47,18 +47,20 @@ static void g_dwarf_format_finalize(GDwarfFormat *); * * * Paramètres : content = contenu binaire à parcourir. * * parent = éventuel format exécutable déjà chargé. * +* unused = adresse non utilisée ici. * +* key = identifiant de format trouvé ou NULL. [OUT] * * * * Description : Indique si le format peut être pris en charge ici. * * * -* Retour : Désignation du format reconnu ou NULL si aucun. * +* Retour : Conclusion de haut niveau sur la reconnaissance effectuée. * * * * Remarques : - * * * ******************************************************************************/ -const char *dwarf_is_matching(GBinContent *content, GExeFormat *parent) +FormatMatchStatus dwarf_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key) { - const char *result; /* Format détecté à renvoyer */ + FormatMatchStatus result; /* Bilan à renvoyer */ size_t i; /* Boucle de parcours */ mrange_t range; /* Couverture d'une section */ dw_section_header header; /* En-tête DWARF de section */ @@ -114,10 +116,10 @@ const char *dwarf_is_matching(GBinContent *content, GExeFormat *parent) 0 /* .debug_types */ }; - result = NULL; + result = FMS_UNKNOWN; if (parent == NULL) - return NULL; + return FMS_UNKNOWN; /* Lecture des indices présents */ @@ -159,23 +161,32 @@ const char *dwarf_is_matching(GBinContent *content, GExeFormat *parent) found = check_dwarf_version(dwarf_v4_versions, current_versions, ARRAY_SIZE(section_names)); if (found) - result = "dwarf_v4"; + { + result = FMS_MATCHED; + *key = strdup("dwarf_v4"); + } - if (result == NULL) + if (result == FMS_UNKNOWN) { found = check_dwarf_version(dwarf_v3_versions, current_versions, ARRAY_SIZE(section_names)); if (found) - result = "dwarf_v3"; + { + result = FMS_MATCHED; + *key = strdup("dwarf_v3"); + } } - if (result == NULL) + if (result == FMS_UNKNOWN) { found = check_dwarf_version(dwarf_v2_versions, current_versions, ARRAY_SIZE(section_names)); if (found) - result = "dwarf_v2"; + { + result = FMS_MATCHED; + *key = strdup("dwarf_v2"); + } } diff --git a/src/format/dwarf/dwarf.h b/src/format/dwarf/dwarf.h index a5e988b..da5b70a 100644 --- a/src/format/dwarf/dwarf.h +++ b/src/format/dwarf/dwarf.h @@ -25,7 +25,7 @@ #define _FORMAT_DWARF_DWARF_H -#include "../executable.h" +#include "../../core/formats.h" @@ -45,7 +45,7 @@ typedef struct _GDwarfFormatClass GDwarfFormatClass; /* Indique si le format peut être pris en charge ici. */ -const char *dwarf_is_matching(GBinContent *, GExeFormat *); +FormatMatchStatus dwarf_is_matching(GBinContent *, GExeFormat *, void *, char **); /* Indique le type défini pour un format de débogage DWARF. */ GType g_dwarf_format_get_type(void); diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index 5c81b2f..50df077 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -84,18 +84,20 @@ bool g_elf_format_get_section_range_by_name(const GElfFormat *, const char *, mr * * * Paramètres : content = contenu binaire à parcourir. * * parent = éventuel format exécutable déjà chargé. * +* unused = adresse non utilisée ici. * +* key = identifiant de format trouvé ou NULL. [OUT] * * * * Description : Indique si le format peut être pris en charge ici. * * * -* Retour : Désignation du format reconnu ou NULL si aucun. * +* Retour : Conclusion de haut niveau sur la reconnaissance effectuée. * * * * Remarques : - * * * ******************************************************************************/ -const char *elf_is_matching(GBinContent *content, GExeFormat *parent) +FormatMatchStatus elf_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key) { - const char *result; /* Format détecté à renvoyer */ + FormatMatchStatus result; /* Bilan à renvoyer */ vmpa2t addr; /* Tête de lecture initiale */ bool status; /* Bilan des accès mémoire */ char magic[4]; /* Idenfiant standard */ @@ -106,7 +108,13 @@ const char *elf_is_matching(GBinContent *content, GExeFormat *parent) status &= (memcmp(magic, "\x7f\x45\x4c\x46" /* .ELF */, 4) == 0); - result = status ? "elf" : NULL; + if (status) + { + result = FMS_MATCHED; + *key = strdup("elf"); + } + else + result = FMS_UNKNOWN; return result; diff --git a/src/format/elf/elf.h b/src/format/elf/elf.h index 8e9a2cc..a557927 100644 --- a/src/format/elf/elf.h +++ b/src/format/elf/elf.h @@ -31,8 +31,7 @@ #include "elf_def.h" -#include "../executable.h" -#include "../format.h" +#include "../../core/formats.h" @@ -51,7 +50,7 @@ typedef struct _GElfFormatClass GElfFormatClass; /* Indique si le format peut être pris en charge ici. */ -const char *elf_is_matching(GBinContent *, GExeFormat *); +FormatMatchStatus elf_is_matching(GBinContent *, GExeFormat *, void *, char **); /* Indique le type défini pour un format d'exécutable ELF. */ GType g_elf_format_get_type(void); diff --git a/src/format/executable-int.h b/src/format/executable-int.h index 704466e..f5a25b5 100644 --- a/src/format/executable-int.h +++ b/src/format/executable-int.h @@ -62,6 +62,9 @@ struct _GExeFormat { GBinFormat parent; /* A laisser en premier */ + GDbgFormat **debugs; /* Informations de débogage */ + size_t debugs_count; /* Nombre de ces informations */ + get_target_machine_fc get_machine; /* Architecture ciblée */ refine_portions_fc refine_portions; /* Décrit les portions binaires*/ diff --git a/src/format/executable.c b/src/format/executable.c index aae182a..5ff773c 100644 --- a/src/format/executable.c +++ b/src/format/executable.c @@ -84,6 +84,84 @@ static void g_executable_format_init(GExeFormat *format) +/****************************************************************************** +* * +* Paramètres : format = informations chargées à compléter. * +* info = informations de débogage à lier. * +* * +* Description : Rajoute des informations de débogage à un exécutable. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_exe_format_add_debug_info(GExeFormat *format, GDbgFormat *info) +{ + /* Ajout dans la liste */ + + format->debugs = (GDbgFormat **)realloc(format->debugs, + ++format->debugs_count * sizeof(GDbgFormat *)); + + format->debugs[format->debugs_count - 1] = info; + + /* Intégration des symboles */ + + /* TODO */ + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Compte le nombre de formats de débogage liés à l'exécutable. * +* * +* Retour : Nombre de formats de débogage attachés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_exe_format_count_debug_info(const GExeFormat *format) +{ + return format->debugs_count; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* index = indice des informations à transmettre. * +* * +* Description : Fournit un format de débogage attaché à l'exécutable. * +* * +* Retour : Informations de débogage attachées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index) +{ + GDbgFormat *result; /* Format à retourner */ + + if (index >= format->debugs_count) + result = NULL; + + else + { + result = format->debugs[index]; + g_object_ref(G_OBJECT(result)); + } + + return result; + +} + diff --git a/src/format/executable.h b/src/format/executable.h index 45c736b..48a8139 100644 --- a/src/format/executable.h +++ b/src/format/executable.h @@ -28,6 +28,7 @@ #include +#include "debuggable.h" #include "../glibext/gbinportion.h" @@ -52,6 +53,14 @@ typedef struct _GExeFormatClass GExeFormatClass; GType g_executable_format_get_type(void); +/* Rajoute des informations de débogage à un exécutable. */ +void g_exe_format_add_debug_info(GExeFormat *, GDbgFormat *); + +/* Compte le nombre de formats de débogage liés à l'exécutable. */ +size_t g_exe_format_count_debug_info(const GExeFormat *); + +/* Fournit un format de débogage attaché à l'exécutable. */ +GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *, size_t); /* Indique le type d'architecture visée par le format. */ diff --git a/src/gui/menus/project.c b/src/gui/menus/project.c index a68b137..6b7e6b4 100644 --- a/src/gui/menus/project.c +++ b/src/gui/menus/project.c @@ -32,7 +32,7 @@ #include "../editem-int.h" -#include "../../analysis/binaries/file.h" +#include "../../analysis/contents/file.h" #include "../../dialogs/shellcode.h" #include "../../gtkext/easygtk.h" @@ -270,7 +270,7 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar) GtkWidget *dialog; /* Boîte à afficher */ char *dir; /* Répertoire courant */ gchar *filename; /* Nom du fichier à intégrer */ - GLoadedBinary *binary; /* Représentation chargée */ + GBinContent *content; /* Contenu binaire à charger */ dialog = gtk_file_chooser_dialog_new(_("Open a binary file"), GTK_WINDOW(G_EDITOR_ITEM(bar)->ref), @@ -299,14 +299,9 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar) { filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - binary = g_file_binary_new_from_file(filename); + content = g_file_content_new(filename); - if (binary != NULL) - { - g_signal_connect(binary, "disassembly-done", - G_CALLBACK(g_study_project_add_loaded_binary), get_current_project()); - g_loaded_binary_analyse(binary); - } + qck_study_new_content(content, PCS_ROOT); g_free(filename); diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index acaf735..f786c08 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -39,37 +39,40 @@ /* Prend acte du [dé]chargement du greffon. */ typedef bool (* pg_management_fc) (GPluginModule *, GObject *); +/* Exécute une action pendant un désassemblage de binaire. */ +typedef void (* pg_process_disassembly_fc) (const GPluginModule *, PluginAction, GLoadedBinary *); + + + + /* Indique si le format peut être pris en charge ici. */ -typedef bool (* pg_format_is_matching) (const GPluginModule *, GBinContent **); +//typedef bool (* pg_format_is_matching) (const GPluginModule *, GBinContent **); /* Procède à une opération liée au format de fichier uniquement. */ typedef bool (* pg_handle_format) (const GPluginModule *, PluginAction, GBinFormat *); -/* Exécute une action pendant un désassemblage de binaire. */ -typedef void (* pg_process_disassembly) (const GPluginModule *, PluginAction, GLoadedBinary *); - /* Précise le nom associé au greffon. */ -typedef char * (* get_plugin_name_fc) (void); +//typedef char * (* get_plugin_name_fc) (void); /* Procède à l'initialisation du greffon. */ -typedef bool (* init_plugin_fc) (GPluginModule *, GObject *); +//typedef bool (* init_plugin_fc) (GPluginModule *, GObject *); /* Procède à l'extinction du greffon. */ -typedef void (* exit_plugin_fc) (GPluginModule *); +//typedef void (* exit_plugin_fc) (GPluginModule *); /* Fournit une indication sur le type d'opération(s) menée(s). */ -typedef PluginAction (* get_plugin_action_fc) (const GPluginModule *); +//typedef PluginAction (* get_plugin_action_fc) (const GPluginModule *); /* Identifie un format à associer à un contenu binaire. */ //typedef MatchingFormatAction (* is_matching_fc) (const GPluginModule *, char **, bin_t **, off_t *); /* Exécute une action définie sur un binaire chargé. */ -typedef bool (* execute_action_on_binary_fc) (const GPluginModule *, GLoadedBinary *, PluginAction); +//typedef bool (* execute_action_on_binary_fc) (const GPluginModule *, GLoadedBinary *, PluginAction); /* Exécute une action relative à un débogueur. */ //typedef bool (* execute_on_debugger_fc) (const GPluginModule *, GBinaryDebugger *, PluginAction); @@ -88,6 +91,7 @@ struct _GPluginModule pg_management_fc init; /* Procédure d'initialisation */ pg_management_fc exit; /* Procédure d'extinction */ + pg_process_disassembly_fc process_disass; /* Catégorie 'désassemblage' */ //char *name; /* Nom associé au greffon */ @@ -95,18 +99,17 @@ struct _GPluginModule //init_plugin_fc init; /* Procédure d'initialisation */ //exit_plugin_fc exit; /* Procédure d'extinction */ - get_plugin_action_fc get_action; /* Opération(s) menée(s) */ + //get_plugin_action_fc get_action; /* Opération(s) menée(s) */ //is_matching_fc is_matching; /* Recherche de correspondance */ - execute_action_on_binary_fc exec_on_bin;/* Action sur un binaire */ + //execute_action_on_binary_fc exec_on_bin;/* Action sur un binaire */ //execute_on_debugger_fc handle_debugger; /* Action liée à un débogueur */ - pg_format_is_matching is_matching; /* Recherche de correspondance */ + //pg_format_is_matching is_matching; /* Recherche de correspondance */ pg_handle_format handle_format; /* Manipulation du format */ - pg_process_disassembly proc_disass; /* Catégorie 'désassemblage' */ }; diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 9322bcb..c0e9fd1 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -37,6 +37,9 @@ #include "plugin-int.h" +#include "../core/formats.h" + + /* Initialise la classe des greffons. */ static void g_plugin_module_class_init(GPluginModuleClass *); @@ -162,8 +165,10 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) GPluginModule *result; /* Structure à retourner */ plugin_abi_version_t current; /* Version de l'ABI actuelle */ 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 */ + format_match_fc matcher; /* Routine de reconnaissance */ result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL); @@ -215,8 +220,9 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) for (i = 0; i < result->interface->actions_count; i++) { - category = MASK_PLUGIN_CATEGORY(result->interface->actions[i]); - sub = MASK_PLUGIN_SUB_CATEGORY(result->interface->actions[i]); + action = result->interface->actions[i]; + category = MASK_PLUGIN_CATEGORY(action); + sub = MASK_PLUGIN_SUB_CATEGORY(action); switch (category) { @@ -254,8 +260,18 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) { case DPS_FORMAT: - switch (result->interface->actions[i]) + switch (action) { + case PGA_FORMAT_MATCHER: + + if (!load_plugin_symbol(result->module, + "is_format_matching", &matcher)) + goto bad_plugin; + + if (!register_format_matcher(matcher, result)) + goto bad_plugin; + + break; case PGA_FORMAT_LOADER_LAST: if (!load_plugin_symbol(result->module, @@ -275,7 +291,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) case DPS_DISASSEMBLY: if (!load_plugin_symbol(result->module, - "process_binary_disassembly", &result->proc_disass)) + "process_binary_disassembly", &result->process_disass)) goto bad_plugin; break; @@ -504,6 +520,6 @@ bool g_plugin_module_handle_binary_format(const GPluginModule *plugin, PluginAct void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary) { - plugin->proc_disass(plugin, action, binary); + plugin->process_disass(plugin, action, binary); } -- cgit v0.11.2-87-g4458