/* Chrysalide - Outil d'analyse de fichiers binaires * plugin.c - interactions avec un greffon donné * * Copyright (C) 2009-2013 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * OpenIDA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "plugin.h" #include #include #include #include #include #include #include #include "plugin-int.h" /* Initialise la classe des greffons. */ static void g_plugin_module_class_init(GPluginModuleClass *); /* Initialise une instance de greffon. */ static void g_plugin_module_init(GPluginModule *); /* Supprime toutes les références externes. */ static void g_plugin_module_dispose(GPluginModule *); /* Procède à la libération totale de la mémoire. */ static void g_plugin_module_finalize(GPluginModule *); /* Indique le type défini pour un greffon. */ G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : class = classe à initialiser. * * * * Description : Initialise la classe des greffons. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_plugin_module_class_init(GPluginModuleClass *class) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(class); object->dispose = (GObjectFinalizeFunc/* ! */)g_plugin_module_dispose; object->finalize = (GObjectFinalizeFunc)g_plugin_module_finalize; } /****************************************************************************** * * * Paramètres : plugin = instance à initialiser. * * * * Description : Initialise une instance de greffon. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_plugin_module_init(GPluginModule *plugin) { } /****************************************************************************** * * * Paramètres : plugin = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_plugin_module_dispose(GPluginModule *plugin) { if (plugin->exit != NULL) plugin->exit(plugin); if (plugin->module != NULL) g_module_close(plugin->module); G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin)); } /****************************************************************************** * * * Paramètres : plugin = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_plugin_module_finalize(GPluginModule *plugin) { free(plugin->filename); G_OBJECT_CLASS(g_plugin_module_parent_class)->finalize(G_OBJECT(plugin)); } /****************************************************************************** * * * Paramètres : filename = nom du fichier à charger. * * * * Description : Crée un module pour un greffon donné. * * * * Retour : Adresse de la structure mise en place. * * * * Remarques : - * * * ******************************************************************************/ GPluginModule *g_plugin_module_new(const gchar *filename) { GPluginModule *result; /* Structure à retourner */ plugin_abi_version_t current; /* Version de l'ABI actuelle */ size_t i; /* Boucle de parcours */ uint32_t category; /* Catégorie principale */ uint32_t sub; /* Sous-catégorie visée */ char *dir; /* Répertoire modifiable */ result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL); result->filename = strdup(filename); result->module = g_module_open(filename, G_MODULE_BIND_LAZY); if (result->module == NULL) { log_variadic_message(LMT_ERROR, _("Error while loading the plugin candidate '%s' : %s"), filename, g_module_error()); goto bad_plugin; } #define load_plugin_symbol(mod, sym, dest) \ ({ \ bool __result; \ if (!g_module_symbol(mod, sym, (gpointer *)dest)) \ { \ log_variadic_message(LMT_ERROR, \ _("No '%s' entry in plugin candidate '%s'"), \ sym, result->filename); \ __result = false; \ } \ else __result = true; \ __result; \ }) /* Récupération de la version d'ABI */ if (!load_plugin_symbol(result->module, "_chrysalide_plugin", &result->interface)) goto bad_plugin; current = CURRENT_ABI_VERSION; if (0 /* check_version() */) { log_variadic_message(LMT_ERROR, _("Bad version... '%s'"), filename); goto bad_plugin; } /* Localisation des différents points d'entrée déclarés */ 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]); printf(" GET cat = 0x%08x - sub = 0x%08x\n", category, sub); switch (category) { case DPC_NONE: switch (sub) { case DPS_NONE: break; default: log_variadic_message(LMT_WARNING, _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); break; } break; case DPC_BINARY_PROCESSING: switch (sub) { case DPS_DISASSEMBLY: if (!load_plugin_symbol(result->module, "process_binary_disassembly", &result->proc_disass)) goto bad_plugin; break; default: log_variadic_message(LMT_WARNING, _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); break; } break; default: log_variadic_message(LMT_WARNING, _("Unknown category '0x%02x' in plugin '%s'..."), category, filename); break; } } /* if (!g_module_symbol(result->module, "init_plugin", (gpointer *)&result->init)) result->init = NULL; if (!g_module_symbol(result->module, "exit_plugin", (gpointer *)&result->exit)) result->exit = NULL; */ /* Conclusion */ dir = strdup(filename); dir = dirname(dir); log_variadic_message(LMT_PROCESS, _("Loaded the '%s' from the '%s' directory"), strrchr(filename, G_DIR_SEPARATOR) + 1, dir); free(dir); return result; bad_plugin: g_object_unref(G_OBJECT(result)); return NULL; } /****************************************************************************** * * * Paramètres : plugin = greffon à consulter. * * * * Description : Fournit la description du greffon dans son intégralité. * * * * Retour : Interfaçage renseigné. * * * * Remarques : - * * * ******************************************************************************/ const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin) { return plugin->interface; } /****************************************************************************** * * * Paramètres : plugin = greffon à consulter. * * msg = message à faire apparaître à l'écran. * * * * Description : Présente dans le journal un message simple. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_plugin_module_log_simple_message(const GPluginModule *plugin, LogMessageType type, const char *msg) { size_t len; /* Taille tampon disponible */ char *buffer; /* Tampon du msg reconstitué */ len = 3 +1 + strlen(plugin->interface->name) + 3 + 2 + strlen(msg) + 1; buffer = calloc(len, sizeof(char)); strcpy(buffer, "["); strcat(buffer, plugin->interface->name); strcat(buffer, "] "); strcat(buffer, msg); log_simple_message(type, buffer); free(buffer); } /****************************************************************************** * * * Paramètres : plugin = greffon à consulter. * * type = espèce du message à ajouter. * * fmt = format du message à faire apparaître à l'écran. * * ... = éventuels arguments venant compléter le message. * * * * Description : Présente dans le journal un message complexe. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessageType type, const char *fmt, ...) { size_t len; /* Taille tampon disponible */ char *buffer; /* Tampon du msg reconstitué */ int ret; /* Bilan d'une impression */ char *ptr; /* Nouvelle allocation */ va_list ap; /* Liste d'arguments variable */ len = VARIADIC_LOG_BUFSIZE; buffer = calloc(len, sizeof(char)); while (buffer != NULL) { va_start(ap, fmt); ret = vsnprintf(buffer, len, fmt, ap); va_end(ap); if (ret >= 0 && ret < len) break; else { if (ret > -1) len += 1; /* glibc 2.1 */ else len *= 2; /* glibc 2.0 */ if ((ptr = realloc(buffer, len)) == NULL) { free(buffer); buffer = NULL; } else buffer = ptr; } } g_plugin_module_log_simple_message(plugin, type, buffer); free(buffer); } /****************************************************************************** * * * Paramètres : plugin = greffon à manipuler. * * action = type d'action attendue. * * binary = binaire dont le contenu est en cours de traitement. * * * * Description : Exécute une action pendant un désassemblage de binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary) { printf("plugin = %p\n", plugin); printf("plugin->proc_disass = %p\n", plugin->proc_disass); plugin->proc_disass(plugin, action, binary); }