From 02cb3aa4e7b18b644b034a5c659c332becf99c9b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 1 Oct 2011 17:20:50 +0000 Subject: Defined the first real [python] plugin. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@210 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 36 ++++++ plugins/pyoida/plugin.c | 250 +++++++++++++++++++++++++++++++++++- plugins/pyoida/plugin.h | 2 +- plugins/pyoida/pyoida.c | 118 ++++++++++++++--- plugins/python/apkfiles/__init__.py | 2 + plugins/python/apkfiles/apkfiles.py | 34 +++++ src/analysis/binary.c | 41 +++++- src/common/environment.c | 2 +- src/format/dex/dex.c | 2 + src/format/format.c | 54 +++++++- src/format/format.h | 2 +- src/gtkext/gtksourceview.c | 3 + src/plugins/plugin-def.h | 27 +++- src/plugins/plugin-int.h | 12 +- src/plugins/plugin.c | 81 ++++++++++-- src/plugins/plugin.h | 6 + 16 files changed, 622 insertions(+), 50 deletions(-) create mode 100644 plugins/python/apkfiles/__init__.py create mode 100644 plugins/python/apkfiles/apkfiles.py diff --git a/ChangeLog b/ChangeLog index 565f288..b2b399e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +11-10-01 Cyrille Bagard + + * plugins/pyoida/plugin.c: + * plugins/pyoida/plugin.h: + Properly load a Python plugin and define some needed functions + for format recognition. + + * plugins/pyoida/pyoida.c: + Browse directories for finding Python plugins. + + * plugins/python/apkfiles/apkfiles.py: + * plugins/python/apkfiles/__init__.py: + New entries: define the first real [python] plugin. + + * src/analysis/binary.c: + Start to update call to load_new_format(). + + * src/common/environment.c: + Fix a bug when getting an environment variable. + + * src/format/dex/dex.c: + Dummy fix. + + * src/format/format.c: + * src/format/format.h: + Load formats usings plugins too. + + * src/gtkext/gtksourceview.c: + Dummy fix. + + * src/plugins/plugin.c: + * src/plugins/plugin-def.h: + * src/plugins/plugin.h: + * src/plugins/plugin-int.h: + Update interfaces for plugins (mainly those which are looking for formats). + 11-07-11 Cyrille Bagard * configure.ac: diff --git a/plugins/pyoida/plugin.c b/plugins/pyoida/plugin.c index 23934a9..e652949 100644 --- a/plugins/pyoida/plugin.c +++ b/plugins/pyoida/plugin.c @@ -46,6 +46,7 @@ struct _GPythonPlugin GPluginModule parent; /* Instance parente */ PyObject *module; /* Script Python chargé */ + PyObject *instance; /* Instance Python du greffon */ }; @@ -64,6 +65,12 @@ static void g_python_plugin_class_init(GPythonPluginClass *); /* Initialise l'instance d'un greffon Python. */ static void g_python_plugin_init(GPythonPlugin *); +/* 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(GPythonPlugin *, GOpenidaBinary *, PluginAction); @@ -94,7 +101,11 @@ static PyObject *pyoida_plugin_run(PyObject *, PyObject *); /* Définit les constantes pour les greffons en Python. */ static bool pyoida_plugin_define_constants(PyObject *); +/* Définit le comportement par défaut d'un greffon Python. */ +static PyObject *pyoida_plugin_get_action(PyObject *, PyObject *); +/* Définit l'issue de la recherche d'un format par défaut. */ +static PyObject *pyoida_plugin_is_matching(PyObject *, PyObject *); @@ -260,7 +271,8 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args /****************************************************************************** * * -* Paramètres : filename = chemin d'accès au code Python à charger. * +* Paramètres : modname = nom du module à charger. * +* filename = chemin d'accès au code Python à charger. * * * * Description : Crée un greffon à partir de code Python. * * * @@ -270,18 +282,20 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args * * ******************************************************************************/ -GPluginModule *g_python_plugin_new(const char *filename) +GPluginModule *g_python_plugin_new(const char *modname, const char *filename) { GPythonPlugin *result; /* Structure à retourner */ PyObject *name; /* Chemin d'accès pour Python */ PyObject *module; /* Script Python chargé */ + PyObject *dict; /* Dictionnaire associé */ + PyObject *class; /* Classe à instancier */ + PyObject *instance; /* Instance Python du greffon */ #if PY_VERSION_HEX >= 0x03000000 name = PyUnicode_FromString(filename); #else name = PyString_FromString(filename); #endif - name = PyString_FromString/*PyUnicode_FromString*/(filename); if (name == NULL) goto gppn_bad_exit; module = PyImport_Import(name); @@ -293,20 +307,37 @@ GPluginModule *g_python_plugin_new(const char *filename) goto gppn_bad_exit; } + dict = PyModule_GetDict(module); + class = PyDict_GetItemString(dict, modname); + Py_DECREF(dict); + if (class == NULL) goto gppn_no_class; + if (!PyType_Check(class->ob_type)) goto gppn_no_class; - //Py_DECREF(module); - + instance = PyObject_CallFunction(class, NULL); + if (instance == NULL) goto gppn_no_instance; + Py_DECREF(class); result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL); - G_PLUGIN_MODULE(result)->action = PGA_CODE_PROCESS; + G_PLUGIN_MODULE(result)->get_action = g_python_plugin_get_action; + + G_PLUGIN_MODULE(result)->is_matching = g_python_plugin_is_matching; result->module = module; + result->instance = instance; return G_PLUGIN_MODULE(result); + gppn_no_instance: + + Py_DECREF(class); + + gppn_no_class: + + Py_DECREF(module); + gppn_bad_exit: return NULL; @@ -317,6 +348,138 @@ GPluginModule *g_python_plugin_new(const char *filename) /****************************************************************************** * * * Paramètres : plugin = greffon de prise en charge à utiliser. * +* * +* Description : Indique l'utilité pratique du greffon. * +* * +* Retour : Action(s) codifiée(s), PGA_NONE par défaut. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PluginAction g_python_plugin_get_action(const GPythonPlugin *plugin) +{ + PluginAction result; /* Valeur à retourner */ + PyObject *value; /* Valeur obtenue */ + + value = run_python_method(plugin->instance, "get_action", NULL); + + result = PyLong_AsLong(value); + Py_DECREF(value); + + 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) +{ + MatchingFormatAction result; /* Valeur à retourner */ + 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 */ + + if (*filename == NULL) + return MFA_NONE; + + args = PyTuple_New(2); + + PyTuple_SetItem(args, 0, PyString_FromString(*filename)); + PyTuple_SetItem(args, 1, PyByteArray_FromStringAndSize(*data, *length)); + + value = run_python_method(plugin->instance, "is_matching", args); + + if (value != NULL && PyTuple_Check(value) && PyTuple_Size(value) == 3) + { + 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) + *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) + *filename = NULL; + + /** + * Pareil que précédemment. + */ + if (new_data != Py_None) + { + tmp = PyByteArray_AsString(new_data); + *length = PyByteArray_Size(new_data); + + *data = (bin_t *)calloc(*length, sizeof(bin_t)); + memcpy(*data, tmp, *length * sizeof(bin_t)); + + } + + goto is_matching_ok; + + } + + is_matching_bad: + + printf("Bad result from is_matching() plugin function.\n"); + + result = MFA_NONE; + + is_matching_ok: + + Py_XDECREF(value); + Py_DECREF(args); + + return result; + +} + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon de prise en charge à utiliser. * * binary = représentation binaire à traiter. * * action = action attendue. * * * @@ -421,12 +584,29 @@ static bool pyoida_plugin_define_constants(PyObject *dict) { int ret; /* Bilan d'un ajout */ + ret = PyDict_SetItemString(dict, "PGA_NONE", PyInt_FromLong(PGA_NONE)); + if (ret == -1) return false; + + ret = PyDict_SetItemString(dict, "PGA_FORMAT_MATCHER", PyInt_FromLong(PGA_FORMAT_MATCHER)); + if (ret == -1) return false; + ret = PyDict_SetItemString(dict, "PGA_DISASSEMBLE", PyInt_FromLong(PGA_DISASSEMBLE)); if (ret == -1) return false; ret = PyDict_SetItemString(dict, "PGA_CODE_PROCESS", PyInt_FromLong(PGA_CODE_PROCESS)); if (ret == -1) return false; + /* PGA_FORMAT_MATCHER */ + + ret = PyDict_SetItemString(dict, "MFA_NONE", PyInt_FromLong(MFA_NONE)); + if (ret == -1) return false; + + ret = PyDict_SetItemString(dict, "MFA_MATCHED", PyInt_FromLong(MFA_MATCHED)); + if (ret == -1) return false; + + ret = PyDict_SetItemString(dict, "MFA_RELOAD", PyInt_FromLong(MFA_RELOAD)); + if (ret == -1) return false; + return true; } @@ -437,6 +617,58 @@ static bool pyoida_plugin_define_constants(PyObject *dict) * Paramètres : self = classe assurant le lien avec l'éditeur de messages. * * args = arguments fournis à l'appel. * * * +* Description : Définit le comportement par défaut d'un greffon Python. * +* * +* Retour : Rien en équivalent Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *pyoida_plugin_get_action(PyObject *self, PyObject *args) +{ + return PyInt_FromLong(PGA_NONE); + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe assurant le lien avec l'éditeur de messages. * +* args = arguments fournis à l'appel. * +* * +* Description : Définit l'issue de la recherche d'un format par défaut. * +* * +* Retour : Rien en équivalent Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *pyoida_plugin_is_matching(PyObject *self, PyObject *args) +{ + PyObject *result; /* Liste à retourner */ + + result = PyTuple_New(3); + + PyTuple_SetItem(result, 0, PyInt_FromLong(MFA_NONE)); + PyTuple_SetItem(result, 1, Py_None); + PyTuple_SetItem(result, 2, Py_None); + + return result; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : self = classe assurant le lien avec l'éditeur de messages. * +* args = arguments fournis à l'appel. * +* * * Description : Exécute une action valide pour le greffon Python. * * * * Retour : Rien en équivalent Python. * @@ -474,6 +706,12 @@ bool add_plugin_to_python_module(PyObject *module) static PyMethodDef pyoida_plugin_methods[] = { + { "get_action", (PyCFunction)pyoida_plugin_get_action, METH_NOARGS, + "Register the plugin for given actions." + }, + { "is_matching", (PyCFunction)pyoida_plugin_is_matching, METH_VARARGS, + "Define if the given file can be handled." + }, { "run", (PyCFunction)pyoida_plugin_run, METH_VARARGS, "Run the plugin for a specific action." }, diff --git a/plugins/pyoida/plugin.h b/plugins/pyoida/plugin.h index f5d4ab4..b8b76d9 100644 --- a/plugins/pyoida/plugin.h +++ b/plugins/pyoida/plugin.h @@ -60,7 +60,7 @@ typedef struct _GPythonPluginClass GPythonPluginClass; GType g_python_plugin_get_type(void); /* Crée un greffon à partir de code Python. */ -GPluginModule *g_python_plugin_new(const char *); +GPluginModule *g_python_plugin_new(const char *, const char *); diff --git a/plugins/pyoida/pyoida.c b/plugins/pyoida/pyoida.c index 4a79bfd..be75b7c 100644 --- a/plugins/pyoida/pyoida.c +++ b/plugins/pyoida/pyoida.c @@ -24,6 +24,10 @@ #include "pyoida.h" +#include +#include + + #include @@ -69,6 +73,7 @@ static PyMethodDef SpamMethods[] = { +static PyObject *__mod; /****************************************************************************** @@ -85,17 +90,37 @@ static PyMethodDef SpamMethods[] = { bool init_plugin(GObject *ref) { + char *paths; /* Emplacements de greffons */ + char *path; /* Chemin à fouiller */ + char *save; /* Sauvegarde pour ré-entrance */ + DIR *dir; /* Répertoire à parcourir */ + struct dirent entry; /* Elément trouvé */ + struct dirent *next; /* Prochain élément fourni */ + int ret; /* Bilan d'un appel système */ + char *filename; /* Chemin d'accès reconstruit */ + + + + GPluginModule *plugin; - int ret; + + printf("Init pyoida\n"); _ref = ref; - add_to_env_var("PYTHONPATH", "/home/ocb/prog/openida/plugins/python", ";"); + + /* Définition des zones d'influence */ + + add_to_env_var("PYTHONPATH", PLUGINS_DIR G_DIR_SEPARATOR_S "python", ";"); + + paths = get_env_var("PYTHONPATH"); + + /* Intialisations Python */ - return false; + //return false; Py_Initialize(); @@ -104,33 +129,92 @@ bool init_plugin(GObject *ref) + /* Chargement des greffons */ - plugin = g_python_plugin_new("lnxsyscalls/lnxsyscalls"); - add_plugin_to_main_list(plugin); + printf("Paths :: '%s'\n", paths); + for (path = strtok_r(paths, ";", &save); + path != NULL; + path = strtok_r(NULL, ";", &save)) + { + dir = opendir(path); + if (dir == NULL) + { + perror("opendir"); + continue; + } + printf("CHEMIN :: '%s'\n", path); -#if 0 + for (ret = readdir_r(dir, &entry, &next); + ret == 0 && next != NULL; + ret = readdir_r(dir, &entry, &next)) + { + if (entry.d_name[0] == '.') continue; -#if 0 - //main2("/home/ocb/prog/openida/plugins/pyoida/lnxsyscalls/lnxsyscalls.py", "get_instance"); - main2("lnxsyscalls", "get_instance"); -#else - //main2("/home/ocb/prog/openida/plugins/pyoida/lnxsyscalls/lnxsyscalls.py", "get_instance"); - main2("lnxsyscalls/lnxsyscalls", "get_instance"); -#endif + filename = strdup(entry.d_name); + filename = stradd(filename, "."); + filename = stradd(filename, "__init__"); -#endif + printf(" - entry :: '%s'\n", filename); - //Py_Finalize(); - //exit(-1); + plugin = g_python_plugin_new(entry.d_name, filename); + + if (plugin == NULL) + printf("No suitable Python plugin found in '%s'\n", filename); /* FIXME : LOG(...) */ + else + { + printf("ok pour %s\n", filename); + add_plugin_to_main_list(plugin); + } + + free(filename); + + } + + closedir(dir); + + break; /* FIXME */ + + } + + //Py_Finalize(); return true; } +/****************************************************************************** +* * +* Paramètres : plugin = greffon à consulter. * +* * +* Description : Indique les opérations offertes par un greffon donné. * +* * +* Retour : Action(s) offerte(s) par le greffon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PluginAction get_plugin_action(const GPluginModule *plugin) +{ + PluginAction result; /* Combinaison à retourner */ + + result = PGA_NONE; + + + + + return result; + +} + + + + + #if PY_VERSION_HEX >= 0x03000000 /* Python 3.x code */ @@ -169,6 +253,8 @@ initpyoida(void) printf("Passage 2\n"); module = Py_InitModule("pyoida", SpamMethods); + __mod = module; + //add_analysis_roptions_to_python_module(module); add_analysis_module_to_python_module(module); add_arch_module_to_python_module(module); diff --git a/plugins/python/apkfiles/__init__.py b/plugins/python/apkfiles/__init__.py new file mode 100644 index 0000000..2ebf824 --- /dev/null +++ b/plugins/python/apkfiles/__init__.py @@ -0,0 +1,2 @@ + +from apkfiles import ApkFiles as apkfiles diff --git a/plugins/python/apkfiles/apkfiles.py b/plugins/python/apkfiles/apkfiles.py new file mode 100644 index 0000000..fe7deb8 --- /dev/null +++ b/plugins/python/apkfiles/apkfiles.py @@ -0,0 +1,34 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from pyoida import Plugin + +import zipfile + + +class ApkFiles(Plugin): + """Open and process APK files.""" + + def get_action(self): + """Register the plugin for given actions.""" + + return Plugin.PGA_FORMAT_MATCHER + + def is_matching(self, filename, data): + """Define if the given file can be handled.""" + + if not zipfile.is_zipfile(filename): + return Plugin.MFA_NONE, None, None + + zf = zipfile.ZipFile(filename) + + if zf.namelist().count('classes.dex') > 0: + + f = zf.open('classes.dex', 'r') + data = f.read() + f.closed + + return Plugin.MFA_RELOAD, None, bytearray(data) + + else: + return Plugin.MFA_NONE, None, None diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 15be43e..f5ff3fb 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -365,17 +365,56 @@ static void g_openida_binary_init(GOpenidaBinary *binary) GOpenidaBinary *g_openida_binary_new_from_file(const char *filename) { GOpenidaBinary *result; /* Adresse à retourner */ + GPluginModule **pglist; /* Liste de greffons */ + size_t pgcount; /* Taille de cette liste */ + size_t i; /* Boucle de parcours */ + + + char *file = strdup(filename); result = g_object_new(G_TYPE_OPENIDA_BINARY, NULL); + + + + printf("%s\n", filename); + + + + pglist = get_all_plugins_for_action(PGA_FORMAT_MATCHER, &pgcount); + + if (pgcount > 0) + { + printf("===>>>> FOUND :: %d\n", pgcount); + + + /* + for (i = 0; i < pgcount; i++) + g_plugin_module_execute_action_on_binary(pglist[i], binary, PGA_CODE_PROCESS); + */ + free(pglist); + + } + + + + + + + + + log_variadic_message(LMT_PROCESS, _("Opening '%s' file..."), filename); result->filename = strdup(filename); + /* result->bin_data = map_binary_file(filename, &result->bin_length); if (result->bin_data == NULL) goto lbf_error; + */ - result->format = G_EXE_FORMAT(load_new_format(FMT_EXEC, result->bin_data, result->bin_length)); + result->format = G_EXE_FORMAT(load_new_format(FMT_EXEC, file, + &result->bin_data, &result->bin_length)); if (result->format == NULL) { log_simple_message(LMT_INFO, _("Unknown binary format")); diff --git a/src/common/environment.c b/src/common/environment.c index a0fa568..633d3e2 100644 --- a/src/common/environment.c +++ b/src/common/environment.c @@ -52,7 +52,7 @@ char *get_env_var(const char *name) result = getenv(name); if (result == NULL) result = strdup(""); - else result = strdup(name); + else result = strdup(result); return result; diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index 174bd2b..287c9ea 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -224,6 +224,8 @@ static void g_dex_format_find_all_sources(GDexFormat *format) bf = G_BIN_FORMAT(format); + return; /* FIXME */ + for (i = 0; i < format->classes_count; i++) { source = g_dex_class_get_source_file(format->classes[i], format); diff --git a/src/format/format.c b/src/format/format.c index 053a7aa..8e1d864 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -35,6 +35,7 @@ #include "pe/pe.h" #include "../decomp/expr/block.h" #include "../panels/log.h" +#include "../plugins/pglist.h" @@ -497,9 +498,10 @@ bool init_all_formats(void) /****************************************************************************** * * -* Paramètres : type = type de format recherché. * -* content = contenu binaire à parcourir. * -* length = taille du contenu en question. * +* Paramètres : type = type de format recherché. * +* filename = fichier d'origine des données initiales. * +* content = contenu binaire à parcourir. [OUT] * +* length = taille du contenu en question. [OUT] * * * * Description : Charge si possible un nouveau format binaire. * * * @@ -509,22 +511,62 @@ bool init_all_formats(void) * * ******************************************************************************/ -GBinFormat *load_new_format(FormatType type, const uint8_t *content, off_t length) +GBinFormat *load_new_format(FormatType type, char *filename, bin_t **content, off_t *length) { GBinFormat *result; /* Adresse à retourner */ + GPluginModule **pglist; /* Liste de greffons */ + size_t pgcount; /* Taille de cette liste */ size_t i; /* Boucle de parcours */ result = NULL; + printf("analysing... %s\n", filename); + + + + pglist = get_all_plugins_for_action(PGA_FORMAT_MATCHER, &pgcount); + + if (pgcount > 0) + { + lnf_rescan: + + for (i = 0; i < pgcount; i++) + switch (g_plugin_module_is_matching(pglist[i], &filename, content, length)) + { + case MFA_MATCHED: + /* FIXME */ + break; + + case MFA_RELOAD: + //goto lnf_rescan; + break; + + default: + break; + + } + + free(pglist); + + } + + + for (i = 0; i < FID_COUNT && result == NULL; i++) - if (_formats[i].type == type && _formats[i].match(type, content, length)) + if (_formats[i].type == type && _formats[i].match(type, *content, *length)) { log_variadic_message(LMT_INFO, _("%s is matching..."), _formats[i].name); - result = _formats[i].load(content, length); + result = _formats[i].load(*content, *length); } + + + printf("FINAL FORMAT :: %p\n", result); + + //exit(0); + return result; } diff --git a/src/format/format.h b/src/format/format.h index dd05dd2..7f0b649 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -121,7 +121,7 @@ typedef GBinFormat * (* format_load_fc) (const bin_t *, off_t); bool init_all_formats(void); /* Charge si possible un nouveau format binaire. */ -GBinFormat *load_new_format(FormatType, const uint8_t *, off_t); +GBinFormat *load_new_format(FormatType, char *filename, bin_t **, off_t *); diff --git a/src/gtkext/gtksourceview.c b/src/gtkext/gtksourceview.c index 33b61c5..5dea05f 100644 --- a/src/gtkext/gtksourceview.c +++ b/src/gtkext/gtksourceview.c @@ -149,6 +149,9 @@ static void gtk_source_view_attach_binary(GtkSourceView *view, GOpenidaBinary *b buffer = g_openida_binary_get_decompiled_buffer(binary, -1); + /* FIXME */ + if (buffer != NULL) + gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(view), buffer); } diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index 50b8df2..43ec28e 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -42,9 +42,13 @@ typedef enum _PluginType /* Action(s) menée(s) par le greffon */ typedef enum _PluginAction { - PGA_DISASSEMBLE = (1 << 0), /* Désassemblage (non trivial) */ + PGA_NONE = (0 << 0), /* Aucun intérêt */ - PGA_CODE_PROCESS = (1 << 1) /* Traitement du code existant */ + PGA_FORMAT_MATCHER = (1 << 0), /* Détection et chargement */ + + PGA_DISASSEMBLE = (1 << 1), /* Désassemblage (non trivial) */ + + PGA_CODE_PROCESS = (1 << 2) /* Traitement du code existant */ } PluginAction; @@ -54,11 +58,28 @@ typedef enum _PluginAction typedef PluginType (* get_plugin_type_fc) (void); /* Fournit une indication sur le type d'opération(s) menée(s). */ -typedef PluginAction (* get_plugin_action_fc) (void); +//typedef PluginAction (* get_plugin_action_fc) (void); /* Exécute une action définie sur un binaire chargé. */ typedef bool (* execute_action_on_binary_fc) (GOpenidaBinary *, PluginAction); +/* PGA_FORMAT_MATCHER */ + +/* Bilans d'une reconnaissance */ +typedef enum _MatchingFormatAction +{ + MFA_NONE, /* Aucune détection */ + MFA_MATCHED, /* Format reconnu */ + MFA_RELOAD, /* Rechargemet opéré */ + + MFA_COUNT + +} MatchingFormatAction; + + + + + #endif /* _PLUGINS_PLUGIN_DEF_H */ diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index 929dbf9..a0b5758 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -36,6 +36,11 @@ /* Procède à l'initialisation du greffon */ typedef bool (* init_plugin_fc) (GObject *); +/* Fournit une indication sur le type d'opération(s) menée(s). */ +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 *); /* Greffon pour OpenIDA (instance) */ @@ -46,9 +51,11 @@ struct _GPluginModule GModule *module; /* Abstration de manipulation */ PluginType type; /* Type(s) du greffon */ - PluginAction action; /* Opération(s) menée(s) */ init_plugin_fc init; /* Procédure d'initialisation */ + 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 */ @@ -66,6 +73,9 @@ struct _GPluginModuleClass + + + /* Ajoute un greffon à la liste principale de greffons. */ void add_plugin_to_main_list(GPluginModule *); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 2443768..ce8ef37 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -99,7 +99,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) { GPluginModule *result; /* Structure à retourner */ get_plugin_action_fc __get_type; /* Type(s) de greffon */ - get_plugin_action_fc __get_action; /* Actions du greffon */ + get_plugin_action_fc get_action; /* Actions du greffon */ result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL); @@ -107,6 +107,21 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) result->module = g_module_open(filename, G_MODULE_BIND_LAZY); + if (!result->module) + { + printf("err null mod\n"); + return NULL; + + } + + + if (!g_module_symbol(result->module, "init_plugin", (gpointer *)&result->init)) + { + printf("Err plugin init sym\n"); + /* TODO */ + } + + /* if (!g_module_symbol(result->module, "get_plugin_type", (gpointer *)&__get_type)) @@ -119,20 +134,20 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) printf("Plugin type :: 0x%08x\n", result->type); + */ - -#if 1 - if (!g_module_symbol(result->module, "get_plugin_action", (gpointer *)&__get_action)) + if (!g_module_symbol(result->module, "get_plugin_action", (gpointer *)&get_action)) { printf("Err plugin get_action sym\n"); //g_object_destroy(result); return NULL; } - result->action = __get_action(); + result->get_action = get_action; + /* if (result->action & (PGA_DISASSEMBLE | PGA_CODE_PROCESS)) { if (!g_module_symbol(result->module, "execute_action_on_binary", (gpointer *)&result->exec_on_bin)) @@ -144,14 +159,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) } -#endif - - - if (!g_module_symbol(result->module, "init_plugin", (gpointer *)&result->init)) - { - printf("Err plugin init sym\n"); - /* TODO */ - } + */ @@ -188,11 +196,56 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref) PluginAction g_plugin_module_get_action(const GPluginModule *plugin) { - return plugin->action; + return plugin->get_action(plugin); + +} + + +/****************************************************************************** +* * +* 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 : Identifie un format à associer à un contenu binaire. * +* * +* Retour : Bilan de la recherche de correspondances. * +* * +* Remarques : - * +* * +******************************************************************************/ + +MatchingFormatAction g_plugin_module_is_matching(const GPluginModule *plugin, char **filename, bin_t **data, off_t *length) +{ + MatchingFormatAction result; /* Valeur à retourner */ + char *old_filename; /* Ancien nom de fichier */ + bin_t *old_data; /* Ancien contenu binaire */ + + if (plugin->is_matching == NULL) + return MFA_NONE; + + old_filename = *filename; + old_data = *data; + + result = plugin->is_matching(plugin, filename, data, length); + + if (result == MFA_RELOAD) + { + if (old_filename != NULL) + free(old_filename); + free(old_data); + } + + return result; } + + + + /****************************************************************************** * * * Paramètres : plugin = greffon à consulter. * diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index d17cee5..8df0e0e 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -57,9 +57,15 @@ GPluginModule *g_plugin_module_new(const gchar *, GObject *); /* Indique les opérations offertes par un greffon donné. */ PluginAction g_plugin_module_get_action(const GPluginModule *); +/* Identifie un format à associer à un contenu binaire. */ +MatchingFormatAction g_plugin_module_is_matching(const GPluginModule *, char **, bin_t **, off_t *); + /* Exécute une action définie sur un binaire chargé. */ bool g_plugin_module_execute_action_on_binary(const GPluginModule *, GOpenidaBinary *, PluginAction); + + + #endif /* _PLUGINS_PLUGIN_H */ -- cgit v0.11.2-87-g4458