diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/mobicore/mobicore.c | 6 | ||||
-rw-r--r-- | plugins/mobicore/mobicore.h | 4 | ||||
-rw-r--r-- | plugins/ropgadgets/Makefile.am | 15 | ||||
-rw-r--r-- | plugins/ropgadgets/finder.c | 399 | ||||
-rw-r--r-- | plugins/ropgadgets/finder.h | 53 | ||||
-rw-r--r-- | plugins/ropgadgets/helper_arm.c | 76 | ||||
-rw-r--r-- | plugins/ropgadgets/helper_arm.h | 37 | ||||
-rw-r--r-- | plugins/ropgadgets/plugin.c | 95 | ||||
-rw-r--r-- | plugins/ropgadgets/plugin.h | 37 | ||||
-rw-r--r-- | plugins/ropgadgets/select.c | 1845 | ||||
-rw-r--r-- | plugins/ropgadgets/select.h | 40 |
12 files changed, 2604 insertions, 5 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 2fdd3ad..726534f 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = androhelpers devdbg libcsem mobicore pychrysa python readelf stackvars +SUBDIRS = androhelpers devdbg libcsem mobicore pychrysa python readelf ropgadgets stackvars diff --git a/plugins/mobicore/mobicore.c b/plugins/mobicore/mobicore.c index 9f7b8a4..15bc0a1 100644 --- a/plugins/mobicore/mobicore.c +++ b/plugins/mobicore/mobicore.c @@ -40,6 +40,7 @@ DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("Mobicore", "Support MobiCore file format for Tr /****************************************************************************** * * * Paramètres : plugin = greffon à manipuler. * +* ref = espace de référencement global. * * * * Description : Prend acte du chargement du greffon. * * * @@ -49,7 +50,7 @@ DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("Mobicore", "Support MobiCore file format for Tr * * ******************************************************************************/ -G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref) { bool result; /* Bilan à retourner */ @@ -65,6 +66,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) /****************************************************************************** * * * Paramètres : plugin = greffon à manipuler. * +* ref = espace de référencement global. * * * * Description : Prend acte du déchargement du greffon. * * * @@ -74,7 +76,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) * * ******************************************************************************/ -G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin) +G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin, GObject *ref) { printf("Unloaded !\n"); diff --git a/plugins/mobicore/mobicore.h b/plugins/mobicore/mobicore.h index d8687a1..ea0cd15 100644 --- a/plugins/mobicore/mobicore.h +++ b/plugins/mobicore/mobicore.h @@ -31,10 +31,10 @@ /* Prend acte du chargement du greffon. */ -G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *); +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *, GObject *); /* Prend acte du déchargement du greffon. */ -G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *); +G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *, GObject *); diff --git a/plugins/ropgadgets/Makefile.am b/plugins/ropgadgets/Makefile.am new file mode 100644 index 0000000..5d11366 --- /dev/null +++ b/plugins/ropgadgets/Makefile.am @@ -0,0 +1,15 @@ + +lib_LTLIBRARIES = libropgadgets.la + +libropgadgets_la_SOURCES = \ + finder.h finder.c \ + helper_arm.h helper_arm.c \ + plugin.h plugin.c \ + select.h select.c + +libropgadgets_la_CFLAGS = $(AM_CFLAGS) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I../../src + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/ropgadgets/finder.c b/plugins/ropgadgets/finder.c new file mode 100644 index 0000000..ff0c6ad --- /dev/null +++ b/plugins/ropgadgets/finder.c @@ -0,0 +1,399 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * finder.c - recherche de gadgets pour ROP + * + * Copyright (C) 2015 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "finder.h" + + +#include <string.h> + + +#include <core/processors.h> + + +#include <i18n.h> + + +#include "helper_arm.h" + + + +/* Données utiles à transmettre */ +typedef struct _search_domain +{ + GBinFormat *format; /* Format du fichier binaire */ + GBinContent *content; /* Contenu associé récupéré */ + GArchProcessor *proc; /* Processeur idéal en place */ + GProcContext *ctx; /* Contexte de désassemblage */ + + mrange_t *exe_ranges; /* Liste de zones exécutables */ + size_t exe_count; /* Nombre de ces zones */ + + phys_t sum; /* Surface totale à parcourir */ + size_t runs_count; /* Nombre de passages à faire */ + size_t runs_done; /* Nombre de passages effectués*/ + +} search_domain; + + +/* Désassemble rapidement une instruction. */ +static GArchInstruction *disassemble_instruction_in_domain(const search_domain *, vmpa2t *); + +/* Désassemble en amont d'une position autant que possible. */ +static GArchInstruction *look_backward_for_gadgets(const search_domain *, const mrange_t *, const vmpa2t *, unsigned int); + +/* Etablit une liste de tous les gadgets présents. */ +static GArchInstruction **list_all_gadgets_in_domain(const search_domain *, unsigned int, update_search_progress_cb, GObject *, size_t *); + + + +/****************************************************************************** +* * +* Paramètres : domain = ensemble d'auxiliaires à disposition. * +* pos = tête de lecture pour le désassemblage. * +* * +* Description : Désassemble rapidement une instruction. * +* * +* Retour : Instruction créée ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchInstruction *disassemble_instruction_in_domain(const search_domain *domain, vmpa2t *pos) +{ + GArchInstruction *result; /* Instruction à retourner */ + GProcContext *ctx; /* Contexte de désassemblage */ + + ctx = domain->ctx; /* TODO : copie */ + + result = g_arch_processor_disassemble_nextgen(domain->proc, ctx, domain->content, pos); + + if (result != NULL) + { + g_arch_instruction_call_hook(result, IPH_LINK, domain->proc, ctx, domain->format); + g_arch_instruction_call_hook(result, IPH_POST, domain->proc, ctx, domain->format); + } + + //g_object_unref(G_OBJECT(ctx)); /* TODO */ + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : domain = ensemble d'auxiliaires à disposition. * +* exe_range = couverture globale dont il ne faut pas sortir. * +* ret = point de retour final déjà trouvé. * +* max_depth = profondeur maximale des recherches. * +* * +* Description : Désassemble en amont d'une position autant que possible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchInstruction *look_backward_for_gadgets(const search_domain *domain, const mrange_t *exe_range, const vmpa2t *ret, unsigned int max_depth) +{ + GArchInstruction *result; /* Liste de gagdets trouvées */ + const phys_t *ins_sizes; /* Tailles potentielles */ + size_t sizes_count; /* Quantité de tailles à tester*/ + vmpa2t last; /* Dernier point de départ */ + unsigned int i; /* Boucle de parcours #1 */ + GArchInstruction *instr; /* Elément de gadget trouvé */ + size_t k; /* Boucle de parcours #2 */ + vmpa2t start; /* Point de départ courant */ + vmpa2t end; /* Point d'arrivée obtenu */ + phys_t diff; /* Volume de données traité */ + mrange_t range; /* Couverture de l'instruction */ + + result = NULL; + + ins_sizes = (phys_t []){ 2, 4 }; /* FIXME */ + sizes_count = 2; + + copy_vmpa(&last, ret); + + /* On parcours jusqu'à la profondeur maximale */ + for (i = 0; i < max_depth; i++) + { + instr = NULL; + + for (k = 0; k < sizes_count && instr == NULL; k++) + { + copy_vmpa(&start, &last); + deminish_vmpa(&start, ins_sizes[k]); + + /* Est-on toujours dans les clous ? */ + if (!mrange_contains_addr(exe_range, &start)) break; + + copy_vmpa(&end, &start); + + instr = disassemble_instruction_in_domain(domain, &end); + if (instr == NULL) continue; + + /* La jointure est-elle parfaite ? */ + + if (cmp_vmpa(&end, &last) != 0) + { + g_object_unref(G_OBJECT(instr)); + instr = NULL; + continue; + } + + /* S'il s'agit d'un point de retour, on laisse la main à une autre liste */ + + if (g_arch_instruction_is_return(instr)) + { + g_object_unref(G_OBJECT(instr)); + instr = NULL; + continue; + } + + } + + /* Aucune instruction n'a été trouvée à cette profondeur, on s'arrête donc */ + if (instr == NULL) break; + + copy_vmpa(&last, &start); + + diff = compute_vmpa_diff(&end, &start); + + init_mrange(&range, &start, diff); + + g_arch_instruction_set_range(instr, &range); + + + g_arch_instruction_merge_lists(&result, &instr); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : domain = ensemble d'auxiliaires à disposition. * +* max_depth = profondeur maximale des recherches. * +* update = fonction de suivi mise à disposition. * +* data = données à associer à une phase d'actualisation. * +* count = nombre de gadgets trouvés. [OUT] * +* * +* Description : Etablit une liste de tous les gadgets présents. * +* * +* Retour : Liste de listes d'instructions, à libérer après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchInstruction **list_all_gadgets_in_domain(const search_domain *domain, unsigned int max_depth, update_search_progress_cb update, GObject *data, size_t *count) +{ + GArchInstruction **result; /* Liste de listes à renvoyer */ + phys_t done; /* Accumulation des quantités */ + size_t i; /* Boucle de parcours #1 */ + phys_t max; /* Borne d'un parcours */ + phys_t k; /* Boucle de parcours #2 */ + gdouble fraction; /* Progression générale */ + vmpa2t ret; /* Emplacement du retour */ + vmpa2t tmp; /* Copie de travail modifiable */ + GArchInstruction *gadget; /* Nouveau gadget détecté */ + phys_t diff; /* Volume de données traité */ + mrange_t ins_range; /* Emplacement d'une instruct° */ + vmpa2t end; /* Point d'arrivée obtenu */ + GArchInstruction *new; /* Nouvelle liste de gadgets */ + + result = NULL; + *count = 0; + + done = 0; + + for (i = 0; i < domain->exe_count; i++) + { + max = get_mrange_length(&domain->exe_ranges[i]); + + for (k = 0; k < max; k++) + { + /* Affichage de la progression */ + + fraction = 1.0 * (domain->runs_done * domain->sum + done + k); + fraction /= (domain->runs_count * domain->sum); + + update(data, fraction); + + /* Réception de la première / dernière instruction */ + + copy_vmpa(&ret, get_mrange_addr(&domain->exe_ranges[i])); + advance_vmpa(&ret, k); + + copy_vmpa(&tmp, &ret); + + gadget = disassemble_instruction_in_domain(domain, &tmp); + if (gadget == NULL) continue; + + /* A-t-on bien affaire à une instruction de retour ? */ + + if (!g_arch_instruction_is_return(gadget)) + { + g_object_unref(G_OBJECT(gadget)); + continue; + } + + /* Ne déborde-t-on pas dans une zone voisine ? */ + + diff = compute_vmpa_diff(&ret, &tmp); + init_mrange(&ins_range, &ret, diff); + + compute_mrange_end_addr(&ins_range, &end); + + if (!mrange_contains_mrange(&domain->exe_ranges[i], &ins_range)) + { + g_object_unref(G_OBJECT(gadget)); + continue; + } + + /* Ajout d'un nouvel ensemble de gadgets */ + + g_arch_instruction_set_range(gadget, &ins_range); + + //printf(" ROP @ 0x%08x / 0x%08x\n", gadget->range.addr.virtual, ret.virtual); + + new = look_backward_for_gadgets(domain, &domain->exe_ranges[i], &ret, max_depth); + + g_arch_instruction_merge_lists(&new, &gadget); + + result = (GArchInstruction **)realloc(result, ++(*count) * sizeof(GArchInstruction *)); + result[*count - 1] = new; + + } + + done += max; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : binary = binaire dont le contenu est à traiter. * +* max_depth = profondeur maximale des recherches. * +* update = fonction de suivi mise à disposition. * +* data = données à associer à une phase d'actualisation. * +* count = nombre de gadgets trouvés. [OUT] * +* * +* Description : Etablit une liste de tous les gadgets présents. * +* * +* Retour : Liste de listes d'instructions, à libérer après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +found_rop_list *list_all_gadgets(GBinFormat *format, unsigned int max_depth, update_search_progress_cb update, GObject *data, size_t *count) +{ + found_rop_list *result; /* Liste de listes à renvoyer */ + const char *target; /* Sous-traitance requise */ + search_domain domain; /* Outils pour la recherche */ + GProcContext **contexts; /* Contextes pour recherches */ + char **names; /* Désignations humaines liées */ + size_t i; /* Boucle de parcours */ + + /* Constitution du socle commun */ + + g_object_ref(G_OBJECT(format)); + domain.format = format; + + domain.content = g_binary_format_get_conten_(format); + + target = g_exe_format_get_target_machine(G_EXE_FORMAT(format)); + domain.proc = get_arch_processor_for_type(target); + + domain.exe_ranges = g_exe_format_get_x_ranges(G_EXE_FORMAT(format), &domain.exe_count); + + /* Récupération des différents contextes */ + + if (strcmp(target, "armv7") == 0) + contexts = get_rop_contexts_for_arm(domain.proc, &names, count); + + else + { + contexts = (GProcContext **)calloc(1, sizeof(GProcContext *)); + names = (char **)calloc(1, sizeof(char *)); + *count = 1; + + contexts[0] = g_arch_processor_get_context(domain.proc); + names[0] = _("all"); + + } + + /* Calcul de la surface totale à parcourir */ + + domain.sum = 0; + + for (i = 0; i < domain.exe_count; i++) + domain.sum += get_mrange_length(&domain.exe_ranges[i]); + + /* Détermination des différents parcours */ + + domain.runs_count = *count; + + domain.runs_done = 0; + + /* Parcours des différentes surfaces */ + + result = (found_rop_list *)calloc(*count, sizeof(found_rop_list)); + + for (i = 0; i < *count; i++) + { + result[i].category = names[i]; + + domain.ctx = contexts[i]; + + result[i].gadgets = list_all_gadgets_in_domain(&domain, max_depth, update, data, &result[i].count); + + g_object_unref(G_OBJECT(domain.ctx)); + + domain.runs_done++; + + } + + free(names); + free(contexts); + + free(domain.exe_ranges); + + g_object_unref(G_OBJECT(domain.proc)); + g_object_unref(G_OBJECT(domain.content)); + g_object_unref(G_OBJECT(domain.format)); + + return result; + +} diff --git a/plugins/ropgadgets/finder.h b/plugins/ropgadgets/finder.h new file mode 100644 index 0000000..fe6dfe7 --- /dev/null +++ b/plugins/ropgadgets/finder.h @@ -0,0 +1,53 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * finder.h - prototypes pour la recherche de gadgets pour ROP + * + * Copyright (C) 2015 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ROPGADGETS_FINDER_H +#define _PLUGINS_ROPGADGETS_FINDER_H + + +#include <arch/instruction.h> +#include <format/format.h> + + + +/* Actualise la barre de progression affichée. */ +typedef void (* update_search_progress_cb) (GObject *, gdouble); + + +/* Catégorisation des résultats */ +typedef struct _found_rop_list +{ + const char *category; /* Désignation du groupe */ + + GArchInstruction **gadgets; /* Gadgets pour ROP trouvés */ + size_t count; /* Taille de cette liste */ + +} found_rop_list; + + +/* Etablit une liste de tous les gadgets présents. */ +found_rop_list *list_all_gadgets(GBinFormat *, unsigned int, update_search_progress_cb, GObject *, size_t *); + + + +#endif /* _PLUGINS_ROPGADGETS_FINDER_H */ diff --git a/plugins/ropgadgets/helper_arm.c b/plugins/ropgadgets/helper_arm.c new file mode 100644 index 0000000..7288399 --- /dev/null +++ b/plugins/ropgadgets/helper_arm.c @@ -0,0 +1,76 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helper_arm.c - prise en compte des spécifités ARM pour la recherche de gadgets + * + * Copyright (C) 2015 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "helper_arm.h" + + +#include <malloc.h> + + +#include <arch/arm/v7/context.h> + + + +/****************************************************************************** +* * +* Paramètres : proc = processeur lié à l'architecture visée. * +* names = noms attribués aux différents contextes. * +* count = nombre de gadgets trouvés. [OUT] * +* * +* Description : Etablit une liste des contextes utiles à la recherche. * +* * +* Retour : Liste de contextes mis en place. * +* * +* Remarques : Toues les tableaux créés sont à libérer après usage. * +* * +******************************************************************************/ + +GProcContext **get_rop_contexts_for_arm(const GArchProcessor *proc, char ***names, size_t *count) +{ + GProcContext **result; /* Contextes à retourner */ + + result = (GProcContext **)calloc(2, sizeof(GProcContext *)); + + (*names) = (char **)calloc(2, sizeof(char *)); + + *count = 2; + + /* Thumb */ + + result[0] = g_arch_processor_get_context(proc); + + g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result[0]), 0, AV7IS_THUMB); + + (*names)[0] = "Thumb"; + + /* ARMM */ + + result[1] = g_arch_processor_get_context(proc); + + g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result[1]), 0, AV7IS_ARM); + + (*names)[1] = "ARM"; + + return result; + +} diff --git a/plugins/ropgadgets/helper_arm.h b/plugins/ropgadgets/helper_arm.h new file mode 100644 index 0000000..afae191 --- /dev/null +++ b/plugins/ropgadgets/helper_arm.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helper_arm.h - prototypes pour la prise en compte des spécifités ARM pour la recherche de gadgets + * + * Copyright (C) 2015 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ROPGADGETS_HELPER_ARM_H +#define _PLUGINS_ROPGADGETS_HELPER_ARM_H + + +#include <arch/processor.h> + + + +/* Etablit une liste des contextes utiles à la recherche. */ +GProcContext **get_rop_contexts_for_arm(const GArchProcessor *, char ***, size_t *); + + + +#endif /* _PLUGINS_ROPGADGETS_HELPER_ARM_H */ diff --git a/plugins/ropgadgets/plugin.c b/plugins/ropgadgets/plugin.c new file mode 100644 index 0000000..a243a74 --- /dev/null +++ b/plugins/ropgadgets/plugin.c @@ -0,0 +1,95 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * plugin.c - description et intégration du présent greffon + * + * Copyright (C) 2015 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "plugin.h" + + +#include <i18n.h> + + +#include <gtkext/easygtk.h> +#include <plugins/plugin-def.h> + + +#include "select.h" + + + +DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("ROP gadgets", "Find available gadgets for a ROP chain", "0.1.0", + PGA_PLUGIN_INIT); + + + +/* Réagit avec le menu "Greffons -> Lister les gadgets ROP". */ +static void mcb_plugins_list_rop_gadgets(GtkMenuItem *, GObject *); + + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* ref = espace de référencement global. * +* * +* Description : Prend acte du chargement du greffon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref) +{ + GtkContainer *menubar; /* Support pour éléments */ + GtkWidget *submenuitem; /* Sous-élément de menu */ + + menubar = GTK_CONTAINER(g_object_get_data(ref, "menubar_plugins")); + if (menubar == NULL) return false; + + submenuitem = qck_create_menu_item(ref, "mnu_plugins_ropgadgets", _("List ROP gadgets"), + G_CALLBACK(mcb_plugins_list_rop_gadgets), ref); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* ref = adresse de l'espace de référencement global. * +* * +* Description : Réagit avec le menu "Greffons -> Lister les gadgets ROP". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_plugins_list_rop_gadgets(GtkMenuItem *menuitem, GObject *ref) +{ + run_rop_finder_assistant(ref, NULL); + +} diff --git a/plugins/ropgadgets/plugin.h b/plugins/ropgadgets/plugin.h new file mode 100644 index 0000000..67612de --- /dev/null +++ b/plugins/ropgadgets/plugin.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * plugin.h - prototypes pour la description et intégration du présent greffon + * + * Copyright (C) 2015 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ROPGADGETS_PLUGIN_H +#define _PLUGINS_ROPGADGETS_PLUGIN_H + + +#include <plugins/plugin.h> + + + +/* Prend acte du chargement du greffon. */ +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *, GObject *ref); + + + +#endif /* _PLUGINS_ROPGADGETS_PLUGIN_H */ diff --git a/plugins/ropgadgets/select.c b/plugins/ropgadgets/select.c new file mode 100644 index 0000000..2889eb5 --- /dev/null +++ b/plugins/ropgadgets/select.c @@ -0,0 +1,1845 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * goto.c - boîte de dialogue pour les sauts à une adresse donnée + * + * Copyright (C) 2012-2014 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "select.h" + + +#include <fcntl.h> +#include <malloc.h> +#include <regex.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + + +#include <i18n.h> + + +#include <project.h> +#include <common/cpp.h> +#include <common/extstr.h> +#include <core/formats.h> +#include <core/processors.h> +#include <gtkext/easygtk.h> + + +#include "finder.h" + + + +/* ------------------------ PARTIE PRINCIPALE DE L'ASSISTANT ------------------------ */ + + +/* Colonnes de la liste des binaires */ +typedef enum _CurrentProjectBinaries +{ + CPB_BINARY, /* Instance GLib du bianire */ + CPB_FILENAME, /* Chemin d'accès au fichier */ + + CPB_COUNT /* Nombre de colonnes */ + +} CurrentProjectBinaries; + + +/* Ferme l'assistant sans dérouler la procédure. */ +static void rop_finder_assistant_cancel(GtkAssistant *, gpointer); + +/* Ferme l'assistant et déroule la procédure. */ +static void rop_finder_assistant_apply(GtkAssistant *, GObject *); + +/* Accompagne le chargement de certaines pages de l'assistant. */ +static void rop_finder_assistant_prepare(GtkAssistant *, GtkWidget *, GObject *); + + + +/* ------------------------ DEFINITION DES ENTREES / SORTIES ------------------------ */ + + +/* Ajoute le panneau de choix quant aux fichiers d'E/S. */ +static void register_input_output_panel(GtkAssistant *, GObject *); + +/* Construit la sélection d'un binaire déjà chargé. */ +static GtkWidget *load_and_populate_current_project_binaries(GObject *); + +/* Met à jour l'accès à la sélection du type d'entrée. */ +static void on_input_type_toggle(GtkToggleButton *, GObject *); + +/* Réagit à un changement de sélection du binaire d'entrée. */ +static void on_loaded_binary_selection_change(GtkComboBox *, GObject *); + +/* Réagit à un changement de fichier binaire d'entrée. */ +static void on_input_filename_change(GtkEditable *, GObject *); + +/* Sélectionne ou non un nouveau fichier d'entrée. */ +static void on_input_filename_browsing_clicked(GtkButton *, GObject *); + +/* Met à jour l'accès à la définition d'un fichier de sortie. */ +static void on_output_need_toggle(GtkToggleButton *, GObject *); + +/* Sélectionne ou non un nouveau fichier de sortie. */ +static void on_output_filename_browsing_clicked(GtkButton *, GObject *); + + + +/* ------------------------- SUIVI DE LA PHASE DE RECHERCHE ------------------------- */ + + +/* Ajoute le panneau de suivi des opérations de recherche. */ +static void register_search_display_panel(GtkAssistant *, GObject *); + +/* Initialise une ligne de rapport quant aux opérations menées. */ +static void init_rop_search_step(GtkGrid *, gint, GObject *, const char *, const char *, GtkWidget *); + +/* Réinitialise tous les rapports de recherches imprimés. */ +static void reset_rop_search_steps(GObject *); + + +/* Description d'une évolution du processus */ +typedef struct _search_step +{ + GObject *ref; /* Espace de référencements */ + + union + { + struct + { + const char *key; /* Clef d'accès partielle */ + bool dynamic; /* Mémoire à libérer ? */ + union + { + const char *msg; /* Message de conclusion */ + char *dmsg; /* Message de conclusion */ + }; + bool success; /* Indication claire */ + }; + + gdouble fraction; /* Avancée du désasssemblage */ + + struct + { + GBinFormat *format; /* Format binaire chargé */ + found_rop_list *list; /* Liste de gadgets ROP trouvés*/ + size_t count; /* Nombre de gadgets trouvés */ + }; + + }; + +} search_step; + + +/* Affiche un message de statut quant aux recherches en cours. */ +static gboolean print_status_of_rop_search_step(search_step *); + +/* Affiche un message de statut quant aux recherches en cours. */ +static void push_status_printing_of_rop_search_step(GObject *, const char *, const char *, bool); + +/* Affiche un message de statut quant aux recherches en cours. */ +static void push_dyn_status_printing_of_rop_search_step(GObject *, const char *, char *, bool); + +/* Actualise la barre de progression affichée. */ +static gboolean update_progress_bar_fraction(search_step *); + +/* Lance l'actualisation de la barre de progression affichée. */ +static void push_new_progress_fraction(GObject *, gdouble); + +/* Enregistre une référence vers les gadgets trouvés. */ +static gboolean register_found_rop_gadgets(search_step *); + +/* Lance une conservation des gadgets trouvés. */ +static void push_found_rop_gadgets(GObject *, GBinFormat *, found_rop_list *, size_t); + +/* Charge un format binaire interne déjà chargé. */ +static GBinFormat *load_internal_format_for_rop_gadgets(GObject *); + +/* Charge un format binaire externe. */ +static GBinFormat *load_external_format_for_rop_gadgets(GObject *); + +/* Procède à la recherche de gadgets de façon séparée. */ +static gpointer look_for_rop_gadgets(GObject *); + + + +/* ----------------------- MISE EN FORME DES GADGETS PRESENTS ----------------------- */ + + +/* Colonnes de la liste des symboles */ +typedef enum _FoundROPGadget +{ + FRG_CATEGORY, /* Catégorie d'appartenance */ + FRG_RAW_VIRTUAL, /* Correspondance virtuelle */ + FRG_RAW, /* Brut pour recherche */ + + FRG_VIRTUAL, /* Correspondance virtuelle */ + FRG_CONTENT, /* Contenu des lignes visées */ + + FRG_COUNT /* Nombre de colonnes */ + +} FoundROPGadget; + + +/* Ajoute le panneau de sélection des gadgets ROP identifiés. */ +static void register_rop_list_panel(GtkAssistant *, GObject *); + +/* Lance l'actualisation du filtrage des gadgets ROP. */ +static void on_rop_gadgets_category_changed(GtkComboBox *, GObject *); + +/* Lance l'actualisation du filtrage des gadgets ROP. */ +static void on_rop_gadgets_filter_changed(GtkSearchEntry *, GObject *); + +/* Détermine la visibilité de tel ou tel gadget ROP. */ +static gboolean filter_visible_rop_gadgets(GtkTreeModel *, GtkTreeIter *, GObject *); + +/* Ajoute de nouvelles chaînes de gadgets localisées. */ +static void add_new_gadgets_for_category(GBinFormat *, GtkComboBoxText *, GtkTreeStore *, const char *, GArchInstruction **, size_t); + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTIE PRINCIPALE DE L'ASSISTANT */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : global = espace de référencements global. * +* parent = fenêtre principale de l'éditeur. * +* * +* Description : Crée et affiche un assistant de sélection de gadgets ROP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void run_rop_finder_assistant(GObject *global, GtkWindow *parent) +{ + GtkWidget *assistant; /* Fenêtre à afficher */ + GObject *ref; /* Espace de référencement */ + + assistant = gtk_assistant_new(); + gtk_widget_set_size_request(assistant, 900, 550); + gtk_window_set_position(GTK_WINDOW(assistant), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(assistant), _("Export assistant")); + + gtk_window_set_modal(GTK_WINDOW(assistant), TRUE); + gtk_window_set_transient_for(GTK_WINDOW(assistant), parent); + + ref = G_OBJECT(assistant); + g_object_set_data(ref, "global", global); + + register_input_output_panel(GTK_ASSISTANT(assistant), ref); + register_search_display_panel(GTK_ASSISTANT(assistant), ref); + register_rop_list_panel(GTK_ASSISTANT(assistant), ref); + + g_signal_connect(G_OBJECT(assistant), "cancel", G_CALLBACK(rop_finder_assistant_cancel), NULL); + g_signal_connect(G_OBJECT(assistant), "close", G_CALLBACK(rop_finder_assistant_cancel), NULL); + g_signal_connect(G_OBJECT(assistant), "apply", G_CALLBACK(rop_finder_assistant_apply), ref); + g_signal_connect(G_OBJECT(assistant), "prepare", G_CALLBACK(rop_finder_assistant_prepare), ref); + + gtk_widget_show_all(assistant); + +} + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre d'assistance à traiter. * +* data = adresse non utilisée ici. * +* * +* Description : Ferme l'assistant sans dérouler la procédure. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void rop_finder_assistant_cancel(GtkAssistant *assistant, gpointer data) +{ + gtk_widget_destroy(GTK_WIDGET(assistant)); + +} + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre d'assistance à traiter. * +* ref = adresse de l'espace de référencement global. * +* * +* Description : Ferme l'assistant et déroule la procédure. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void rop_finder_assistant_apply(GtkAssistant *assistant, GObject *ref) +{ + GtkEntry *entry; /* Zone de saisie */ + const gchar *filename; /* Chemin d'accès du fichier */ + int fd; /* Flux ouvert en écriture */ + GtkTreeView *treeview; /* Arborescence à actualiser */ + GtkTreeModel *model; /* Modèle de gestion */ + GtkTreeIter iter; /* Boucle de parcours */ + gboolean loop; /* Poursuite de la boucle ? */ + gchar *virtual; /* Adresse correspondante */ + gchar *raw; /* ROP en format texte simple */ + + /* Fichier de sortie */ + + entry = GTK_ENTRY(g_object_get_data(ref, "output_filename")); + filename = gtk_entry_get_text(entry); + + fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd == -1) + { + perror("open"); + return; + } + + /* Boucle de parcours */ + + treeview = GTK_TREE_VIEW(g_object_get_data(ref, "treeview")); + model = gtk_tree_view_get_model(treeview); + + for (loop = gtk_tree_model_get_iter_first(model, &iter); + loop; + loop = gtk_tree_model_iter_next(model, &iter)) + { + gtk_tree_model_get(model, &iter, FRG_RAW_VIRTUAL, &virtual, FRG_RAW, &raw, -1); + + dprintf(fd, "%s\t%s\n", virtual, raw); + + g_free(virtual); + g_free(raw); + + } + + /* Conclusion */ + + close(fd); + +} + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre d'assistance à traiter. * +* page = élément de l'assistant à préparer. * +* ref = adresse de l'espace de référencement global. * +* * +* Description : Accompagne le chargement de certaines pages de l'assistant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void rop_finder_assistant_prepare(GtkAssistant *assistant, GtkWidget *page, GObject *ref) +{ + GtkWidget *test; /* Reconnaissance à l'aveugle */ + GThread *thread; /* Tâche de fond à programmer */ + + test = gtk_assistant_get_nth_page(assistant, 1); + + if (test == page) + { + reset_rop_search_steps(ref); + + thread = g_thread_new("gadgets_finder", (GThreadFunc)look_for_rop_gadgets, ref); + g_thread_unref(thread); + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DES ENTREES / SORTIES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre d'assistance à compléter. * +* ref = espace de référencements inter-panneaux. * +* * +* Description : Ajoute le panneau de choix quant aux fichiers d'E/S. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void register_input_output_panel(GtkAssistant *assistant, GObject *ref) +{ + GtkWidget *vbox; /* Support principal */ + GtkWidget *frame; /* Support avec encadrement */ + GtkWidget *alignment; /* Disposition sur le support */ + GtkWidget *sub_vbox; /* Division verticale */ + GtkWidget *radio; /* Choix du type d'entrée */ + GtkWidget *combobox; /* Sélection du binaire interne*/ + GtkWidget *sub_hbox; /* Division horizontale */ + GtkWidget *entry; /* Zone de saisie de texte */ + GtkWidget *button; /* Sélection de fichier */ + GtkWidget *checkbutton; /* Coche pour une option */ + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 16); + gtk_widget_show(vbox); + + /* Fichier de sortie */ + + frame = qck_create_frame(_("<b>Input binary</b>"), &alignment, 0, 0, 12, 8); + gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0); + + sub_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_show(sub_vbox); + gtk_container_add(GTK_CONTAINER(alignment), sub_vbox); + + radio = qck_create_radio_button(ref, "loaded_as_input", _("Use a binary from the current project:"), + NULL, G_CALLBACK(on_input_type_toggle), ref); + gtk_box_pack_start(GTK_BOX(sub_vbox), radio, FALSE, FALSE, 0); + + combobox = load_and_populate_current_project_binaries(ref); + gtk_box_pack_start(GTK_BOX(sub_vbox), combobox, TRUE, TRUE, 0); + + radio = qck_create_radio_button(ref, "extern_as_input", _("Open a new binary file:"), + GTK_RADIO_BUTTON(radio), G_CALLBACK(on_input_type_toggle), ref); + gtk_box_pack_start(GTK_BOX(sub_vbox), radio, FALSE, FALSE, 0); + + sub_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(sub_hbox); + gtk_box_pack_start(GTK_BOX(sub_vbox), sub_hbox, FALSE, FALSE, 0); + + entry = qck_create_entry(ref, "input_filename", NULL); + g_signal_connect(entry, "changed", G_CALLBACK(on_input_filename_change), ref); + gtk_box_pack_start(GTK_BOX(sub_hbox), entry, TRUE, TRUE, 0); + + button = qck_create_button(ref, "input_browser", _("Browse..."), + G_CALLBACK(on_input_filename_browsing_clicked), assistant); + gtk_box_pack_start(GTK_BOX(sub_hbox), button, FALSE, FALSE, 0); + + /* Actualisation des accès */ + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); + on_input_type_toggle(GTK_TOGGLE_BUTTON(radio), ref); + + /* Fichier de sortie */ + + frame = qck_create_frame(_("<b>Ouput results</b>"), &alignment, 0, 0, 12, 8); + gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0); + + sub_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_show(sub_vbox); + gtk_container_add(GTK_CONTAINER(alignment), sub_vbox); + + checkbutton = qck_create_check_button(ref, "use_output", + _("Save selected ROP gadgets in a file:"), + G_CALLBACK(on_output_need_toggle), ref); + gtk_widget_show(checkbutton); + + gtk_box_pack_start(GTK_BOX(sub_vbox), checkbutton, FALSE, FALSE, 0); + + sub_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(sub_hbox); + gtk_box_pack_start(GTK_BOX(sub_vbox), sub_hbox, FALSE, TRUE, 0); + + entry = qck_create_entry(ref, "output_filename", NULL); + gtk_box_pack_start(GTK_BOX(sub_hbox), entry, TRUE, TRUE, 0); + + button = qck_create_button(ref, "output_browser", _("Browse..."), + G_CALLBACK(on_output_filename_browsing_clicked), assistant); + gtk_box_pack_start(GTK_BOX(sub_hbox), button, FALSE, FALSE, 0); + + /* Actualisation des accès */ + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), FALSE); + on_output_need_toggle(GTK_TOGGLE_BUTTON(checkbutton), ref); + + /* Intégration */ + + gtk_assistant_append_page(assistant, vbox); + gtk_assistant_set_page_title(assistant, vbox, _("Input / output")); + gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_INTRO); + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* * +* Description : Construit la sélection d'un binaire déjà chargé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GtkWidget *load_and_populate_current_project_binaries(GObject *ref) +{ + GtkWidget *result; /* Composant à retourner */ + GObject *global; /* Espace de référencements */ + GLoadedBinary *current; /* Binaire actif courant */ + gint selected; /* Indice à sélectionner */ + GtkListStore *store; /* Modèle de gestion en liste */ + GLoadedBinary **binaries; /* Liste de binaires */ + size_t count; /* Taille de cette liste */ + size_t i; /* Boucle de parcours */ + GtkTreeIter iter; /* Point d'insertion */ + GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ + + /* Récupération du binaire courant */ + + global = G_OBJECT(g_object_get_data(ref, "global")); + + current = G_LOADED_BINARY(g_object_get_data(global, "current_binary")); + + /* Constitution d'une liste de binaires courants */ + + selected = -1; + + store = gtk_list_store_new(CPB_COUNT, G_TYPE_OBJECT, G_TYPE_STRING); + + binaries = g_study_project_get_binaries(get_current_project(), &count); + + if (binaries != NULL) + { + for (i = 0; i < count; i++) + { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + CPB_BINARY, binaries[i], + CPB_FILENAME, g_loaded_binary_get_name(binaries[i], true), + -1); + + if (binaries[i] == current) + selected = i; + + g_object_unref(G_OBJECT(binaries[i])); + + } + + free(binaries); + + } + + /* Mise en place d'un affichage graphique */ + + result = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + g_object_set_data(ref, "input_binary", result); + + g_signal_connect(result, "changed", G_CALLBACK(on_loaded_binary_selection_change), ref); + + gtk_widget_show(result); + + gtk_combo_box_set_active(GTK_COMBO_BOX(result), selected); + + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(result), renderer, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(result), renderer, + "text", CPB_FILENAME, + NULL); + + g_object_unref(G_OBJECT(store)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : button = oche dont le status vient de changer. * +* ref = espace de référencements inter-panneaux. * +* * +* Description : Met à jour l'accès à la sélection du type d'entrée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_input_type_toggle(GtkToggleButton *button, GObject *ref) +{ + GtkToggleButton *internal; /* Bouton de sélection interne */ + gboolean state; /* Etat du bouton courant */ + GtkWidget *widget; /* Element dont l'accès change */ + + internal = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "loaded_as_input")); + state = gtk_toggle_button_get_active(internal); + + /* Elément de sélection interne */ + + widget = GTK_WIDGET(g_object_get_data(ref, "input_binary")); + + if (widget != NULL) + { + gtk_widget_set_sensitive(widget, state); + + if (state) + on_loaded_binary_selection_change(GTK_COMBO_BOX(widget), ref); + + } + + /* Elément de sélection externe */ + + widget = GTK_WIDGET(g_object_get_data(ref, "input_filename")); + + if (widget != NULL) + { + gtk_widget_set_sensitive(widget, !state); + + if (!state) + on_input_filename_change(GTK_EDITABLE(widget), ref); + + } + + widget = GTK_WIDGET(g_object_get_data(ref, "input_browser")); + if (widget != NULL) + gtk_widget_set_sensitive(widget, !state); + +} + + +/****************************************************************************** +* * +* Paramètres : combo = composant graphique de sélection concerné. * +* ref = espace de référencement principal. * +* * +* Description : Réagit à un changement de sélection du binaire d'entrée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_loaded_binary_selection_change(GtkComboBox *combo, GObject *ref) +{ + gint selected; /* Indice sélectionné */ + GtkWidget *page; /* Page de la partie terminée */ + + selected = gtk_combo_box_get_active(combo); + + page = gtk_assistant_get_nth_page(GTK_ASSISTANT(ref), 0); + + if (page != NULL) + gtk_assistant_set_page_complete(GTK_ASSISTANT(ref), page, selected != -1); + +} + + +/****************************************************************************** +* * +* Paramètres : editable = composant graphique d'édition concerné. * +* ref = espace de référencement principal. * +* * +* Description : Réagit à un changement de fichier binaire d'entrée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_input_filename_change(GtkEditable *editable, GObject *ref) +{ + guint16 length; /* Taille du texte fourni */ + GtkWidget *page; /* Page de la partie terminée */ + + length = gtk_entry_get_text_length(GTK_ENTRY(editable)); + + page = gtk_assistant_get_nth_page(GTK_ASSISTANT(ref), 0); + + if (page != NULL) + gtk_assistant_set_page_complete(GTK_ASSISTANT(ref), page, length > 0); + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton d'édition de la sélection. * +* ref = espace de référencement principal. * +* * +* Description : Sélectionne ou non un nouveau fichier d'entrée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_input_filename_browsing_clicked(GtkButton *button, GObject *ref) +{ + GtkWidget *dialog; /* Boîte à afficher */ + gchar *filename; /* Nom du fichier à intégrer */ + GtkEntry *entry; /* Zone de saisie à maj. */ + + dialog = gtk_file_chooser_dialog_new(_("Choose an input filename"), GTK_WINDOW(ref), + GTK_FILE_CHOOSER_ACTION_OPEN, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Open"), GTK_RESPONSE_ACCEPT, + NULL); + + entry = GTK_ENTRY(g_object_get_data(ref, "input_filename")); + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), gtk_entry_get_text(entry)); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + gtk_entry_set_text(GTK_ENTRY(entry), filename); + + g_free(filename); + + } + + gtk_widget_destroy(dialog); + +} + + +/****************************************************************************** +* * +* Paramètres : button = coche dont le status vient de changer. * +* ref = espace de référencements inter-panneaux. * +* * +* Description : Met à jour l'accès à la définition d'un fichier de sortie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_output_need_toggle(GtkToggleButton *button, GObject *ref) +{ + gboolean state; /* Etat du bouton courant */ + GtkWidget *widget; /* Element dont l'accès change */ + + state = gtk_toggle_button_get_active(button); + + widget = GTK_WIDGET(g_object_get_data(ref, "output_filename")); + if (widget != NULL) + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(g_object_get_data(ref, "output_browser")); + if (widget != NULL) + gtk_widget_set_sensitive(widget, state); + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton d'édition de la sélection. * +* ref = espace de référencement principal. * +* * +* Description : Sélectionne ou non un nouveau fichier de sortie. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_output_filename_browsing_clicked(GtkButton *button, GObject *ref) +{ + GtkWidget *dialog; /* Boîte à afficher */ + gchar *filename; /* Nom du fichier à intégrer */ + GtkEntry *entry; /* Zone de saisie à maj. */ + + dialog = gtk_file_chooser_dialog_new(_("Choose an output filename"), GTK_WINDOW(ref), + GTK_FILE_CHOOSER_ACTION_SAVE, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Save"), GTK_RESPONSE_ACCEPT, + NULL); + + entry = GTK_ENTRY(g_object_get_data(ref, "output_filename")); + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), gtk_entry_get_text(entry)); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + gtk_entry_set_text(GTK_ENTRY(entry), filename); + + g_free(filename); + + } + + gtk_widget_destroy(dialog); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* SUIVI DE LA PHASE DE RECHERCHE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre d'assistance à compléter. * +* ref = espace de référencements inter-panneaux. * +* * +* Description : Ajoute le panneau de suivi des opérations de recherche. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void register_search_display_panel(GtkAssistant *assistant, GObject *ref) +{ + GtkGrid *grid; /* Table de résumé */ + GtkWidget *pbar; /* barre de progression */ + + grid = GTK_GRID(gtk_grid_new()); + gtk_grid_set_column_spacing(grid, 8); + gtk_grid_set_row_spacing(grid, 8); + + g_object_set(G_OBJECT(grid), + "halign", GTK_ALIGN_CENTER, + "valign", GTK_ALIGN_CENTER, + "margin-bottom", 100, NULL); + + /* Représentation des étapes */ + + init_rop_search_step(grid, 0, ref, "loading", _("Loading the input binary..."), NULL); + + init_rop_search_step(grid, 1, ref, "format", _("Detecting the proper format..."), NULL); + + pbar = gtk_progress_bar_new(); + g_object_set(G_OBJECT(pbar), "valign", GTK_ALIGN_CENTER, NULL); + gtk_widget_show(pbar); + + init_rop_search_step(grid, 2, ref, "gadgets", _("Looking for all ROP gadgets..."), pbar); + + init_rop_search_step(grid, 3, ref, "final", _("Results:"), NULL); + + /* Intégration */ + + gtk_assistant_append_page(assistant, GTK_WIDGET(grid)); + gtk_assistant_set_page_title(assistant, GTK_WIDGET(grid), _("Search process")); + gtk_assistant_set_page_type(assistant, GTK_WIDGET(grid), GTK_ASSISTANT_PAGE_PROGRESS); + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* key = clef partielle d'accès aux composants concernés. * +* info = message d'information annonçant la conclusion. * +* pbar = éventuel composant de statut ou NULL. * +* * +* Description : Initialise une ligne de rapport quant aux opérations menées. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void init_rop_search_step(GtkGrid *grid, gint top, GObject *ref, const char *key, const char *info, GtkWidget *pbar) +{ + char *access; /* Chemin d'accès final */ + GtkWidget *render; /* Image de statut à afficher */ + GtkWidget *label; /* Etiquette d'indication */ + + /* Icone de représentation */ + + access = strdup("process_"); + access = stradd(access, key); + access = stradd(access, "_icon"); + + render = gtk_image_new_from_icon_name("dialog-question", GTK_ICON_SIZE_DND); + g_object_set_data(ref, access, render); + gtk_widget_show(render); + gtk_grid_attach(grid, render, 0, top, 1, 1); + + free(access); + + /* Désignation humaine d'indicatif */ + + access = strdup("process_"); + access = stradd(access, key); + access = stradd(access, "_caption"); + + label = qck_create_label(ref, access, info); + gtk_grid_attach(grid, label, 1, top, 1, 1); + + free(access); + + /* Statut final */ + + access = strdup("process_"); + access = stradd(access, key); + access = stradd(access, "_status"); + + if (pbar == NULL) + { + label = qck_create_label(ref, access, "done"); + gtk_grid_attach(grid, label, 2, top, 1, 1); + } + else + { + g_object_set_data(ref, access, pbar); + gtk_grid_attach(grid, pbar, 2, top, 1, 1); + } + + free(access); + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* * +* Description : Réinitialise tous les rapports de recherches imprimés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_rop_search_steps(GObject *ref) +{ + size_t i; /* Boucle de parcours */ + char *access; /* Chemin d'accès final */ + GObject *render; /* Image de statut à afficher */ + GtkLabel *label; /* Etiquette d'indication */ + GtkProgressBar *pbar; /* Barre à mettre à jour */ + + static const char *icon_keys[] = { "loading", "format", "gadgets", "final" }; + static const char *status_keys[] = { "loading", "format", "final" }; + + /* Réinitialisation des images */ + + for (i = 0; i < ARRAY_SIZE(icon_keys); i++) + { + access = strdup("process_"); + access = stradd(access, icon_keys[i]); + access = stradd(access, "_icon"); + + render = G_OBJECT(g_object_get_data(ref, access)); + g_object_set(render, "icon-name", "dialog-question", NULL); + + free(access); + + } + + /* Statut final */ + + for (i = 0; i < ARRAY_SIZE(status_keys); i++) + { + access = strdup("process_"); + access = stradd(access, status_keys[i]); + access = stradd(access, "_status"); + + label = GTK_LABEL(g_object_get_data(ref, access)); + gtk_label_set_text(label, ""); + + free(access); + + } + + /* Progression des recherches */ + + pbar = GTK_PROGRESS_BAR(g_object_get_data(ref, "process_gadgets_status")); + + gtk_progress_bar_set_fraction(pbar, 0.0); + +} + + +/****************************************************************************** +* * +* Paramètres : step = informations quant à l'étape avancée. * +* * +* Description : Affiche un message de statut quant aux recherches en cours. * +* * +* Retour : FALSE pour ne pas reprogrammer l'exécution de la tâche. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean print_status_of_rop_search_step(search_step *step) +{ + char *access; /* Chemin d'accès final */ + GObject *render; /* Image de statut à afficher */ + GtkLabel *status; /* Bilan à faire paraître */ + + /* Icone de représentation */ + + access = strdup("process_"); + access = stradd(access, step->key); + access = stradd(access, "_icon"); + + render = G_OBJECT(g_object_get_data(step->ref, access)); + g_object_set(render, "icon-name", step->success ? "face-smile" : "face-sad", NULL); + + free(access); + + /* Mot de la fin */ + + if (step->msg != NULL) + { + access = strdup("process_"); + access = stradd(access, step->key); + access = stradd(access, "_status"); + + status = GTK_LABEL(g_object_get_data(step->ref, access)); + gtk_label_set_text(status, step->msg); + + free(access); + + } + + /* Nettoyage final */ + + if (step->dynamic) + free(step->dmsg); + + free(step); + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* key = clef partielle d'accès aux composants concernés. * +* msg = message d'information accompagnant la conclusion. * +* success = indication quant à la réussite de l'opération. * +* * +* Description : Affiche un message de statut quant aux recherches en cours. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void push_dyn_status_printing_of_rop_search_step(GObject *ref, const char *key, char *dmsg, bool success) +{ + search_step *step; /* Informations d'étape */ + + step = (search_step *)calloc(1, sizeof(search_step)); + + step->ref = ref; + + step->key = key; + step->dynamic = true; + step->dmsg = dmsg; + step->success = success; + + g_idle_add((GSourceFunc)print_status_of_rop_search_step, step); + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* key = clef partielle d'accès aux composants concernés. * +* msg = message d'information accompagnant la conclusion. * +* success = indication quant à la réussite de l'opération. * +* * +* Description : Affiche un message de statut quant aux recherches en cours. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void push_status_printing_of_rop_search_step(GObject *ref, const char *key, const char *msg, bool success) +{ + search_step *step; /* Informations d'étape */ + + step = (search_step *)calloc(1, sizeof(search_step)); + + step->ref = ref; + + step->key = key; + step->dynamic = false; + step->msg = msg; + step->success = success; + + g_idle_add((GSourceFunc)print_status_of_rop_search_step, step); + +} + + +/****************************************************************************** +* * +* Paramètres : step = informations quant à l'étape avancée. * +* * +* Description : Actualise la barre de progression affichée. * +* * +* Retour : FALSE pour ne pas reprogrammer l'exécution de la tâche. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean update_progress_bar_fraction(search_step *step) +{ + GtkProgressBar *pbar; /* Barre à mettre à jour */ + + pbar = GTK_PROGRESS_BAR(g_object_get_data(step->ref, "process_gadgets_status")); + + gtk_progress_bar_set_fraction(pbar, step->fraction); + + /* Nettoyage final */ + + free(step); + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* fraction = avancée globale du désassemblage en cours. * +* * +* Description : Lance l'actualisation de la barre de progression affichée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void push_new_progress_fraction(GObject *ref, gdouble fraction) +{ + search_step *step; /* Informations d'étape */ + + step = (search_step *)calloc(1, sizeof(search_step)); + + step->ref = ref; + + step->fraction = fraction; + + g_idle_add((GSourceFunc)update_progress_bar_fraction, step); + +} + + +/****************************************************************************** +* * +* Paramètres : step = informations quant à l'étape avancée. * +* * +* Description : Enregistre une référence vers les gadgets trouvés. * +* * +* Retour : FALSE pour ne pas reprogrammer l'exécution de la tâche. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean register_found_rop_gadgets(search_step *step) +{ + GtkComboBoxText *combo; /* Sélection d'une catégorie */ + GtkTreeView *treeview; /* Arborescence à actualiser */ + GtkTreeModelFilter *filter; /* Modèle de gestion associé */ + size_t i; /* Boucle de parcours */ + GtkWidget *page; /* Page de la partie terminée */ + + /* Affichage des résulats */ + + if (step->format != NULL) + { + combo = GTK_COMBO_BOX_TEXT(g_object_get_data(step->ref, "filter_cat")); + + treeview = GTK_TREE_VIEW(g_object_get_data(step->ref, "treeview")); + filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(treeview)); + + for (i = 0; i < step->count; i++) + add_new_gadgets_for_category(step->format, + combo, GTK_TREE_STORE(gtk_tree_model_filter_get_model(filter)), + step->list[i].category, step->list[i].gadgets, step->list[i].count); + + if (step->list != NULL) + free(step->list); + + } + + /* Déverrouillage des accès à la suite */ + + page = gtk_assistant_get_nth_page(GTK_ASSISTANT(step->ref), 1); + + gtk_assistant_set_page_complete(GTK_ASSISTANT(step->ref), page, TRUE); + + /* Nettoyage final */ + + free(step); + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* format = format binaire chargé. * +* list = liste de liste de gadgets pour ROP. * +* count = taille de cette liste. * +* * +* Description : Lance une conservation des gadgets trouvés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void push_found_rop_gadgets(GObject *ref, GBinFormat *format, found_rop_list *list, size_t count) +{ + search_step *step; /* Informations d'étape */ + + step = (search_step *)calloc(1, sizeof(search_step)); + + step->ref = ref; + + step->format = format; + step->list = list; + step->count = count; + + g_idle_add((GSourceFunc)register_found_rop_gadgets, step); + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* * +* Description : Charge un format binaire interne déjà chargé. * +* * +* Retour : Nouveau format au contenu à fouiller ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBinFormat *load_internal_format_for_rop_gadgets(GObject *ref) +{ + GBinFormat *result; /* Format chargé à retourner */ + GtkComboBox *combo; /* Composant de sélection */ + GtkTreeIter iter; /* Tête de lecture à placer */ + GtkTreeModel *model; /* Modèle de gestion */ + GLoadedBinary *binary; /* Binaire chargé à utiliser */ + + combo = GTK_COMBO_BOX(g_object_get_data(ref, "input_binary")); + + if (!gtk_combo_box_get_active_iter(combo, &iter)) + { + push_status_printing_of_rop_search_step(ref, "loading", _("unable to get the current binary"), false); + return NULL; + } + + model = gtk_combo_box_get_model(combo); + gtk_tree_model_get(model, &iter, CPB_BINARY, &binary, -1); + + push_status_printing_of_rop_search_step(ref, "loading", _("done"), true); + + result = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); + + push_status_printing_of_rop_search_step(ref, "format", _("already loaded"), true); + + g_object_ref(G_OBJECT(result)); + g_object_unref(G_OBJECT(binary)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* * +* Description : Charge un format binaire externe. * +* * +* Retour : Nouveau format au contenu à fouiller ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBinFormat *load_external_format_for_rop_gadgets(GObject *ref) +{ + GBinFormat *result; /* Format chargé à retourner */ + 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 */ + const char *desc; /* Description humaine associée*/ + + /* Récupération du nom de fichier */ + + entry = GTK_ENTRY(g_object_get_data(ref, "input_filename")); + + filename = gtk_entry_get_text(entry); + + /* Récupération du contenu binaire */ + + content = g_binary_content_new_from_file(filename); + if (content == NULL) + { + push_status_printing_of_rop_search_step(ref, "loading", _("unable to get the binary content"), false); + goto leffrg_error; + } + + push_status_printing_of_rop_search_step(ref, "loading", _("done"), true); + + /* Récupération du format de fichier associé */ + + target = find_matching_format(content); + desc = get_binary_format_name(target); + + if (desc == NULL) + { + g_object_unref(G_OBJECT(content)); + push_status_printing_of_rop_search_step(ref, "format", _("unknown binary format"), false); + goto leffrg_error; + } + + result = load_new_named_format(target, content); + + if (result == NULL) + { + push_status_printing_of_rop_search_step(ref, "format", _("error while loading the binary"), false); + goto leffrg_error; + } + + push_status_printing_of_rop_search_step(ref, "format", desc, true); + + return result; + + leffrg_error: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements inter-panneaux. * +* * +* Description : Procède à la recherche de gadgets de façon séparée. * +* * +* Retour : ? * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gpointer look_for_rop_gadgets(GObject *ref) +{ + GtkToggleButton *internal; /* Bouton de sélection interne */ + gboolean state; /* Etat du bouton courant */ + GBinFormat *format; /* Format du binaire à traiter */ + found_rop_list *list; /* Liste de gadgets ROP trouvés*/ + size_t count; /* Nombre de ces listes */ + size_t found; /* Nombre de gadgets trouvés */ + size_t i; /* Boucle de parcours */ + char *msg; /* Message final à faire passer*/ + + internal = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "loaded_as_input")); + state = gtk_toggle_button_get_active(internal); + + if (state) + format = load_internal_format_for_rop_gadgets(ref); + else + format = load_external_format_for_rop_gadgets(ref); + + if (format == NULL) goto lfrg_unlock; + + list = list_all_gadgets(format, 7, push_new_progress_fraction, ref, &count); + + push_status_printing_of_rop_search_step(ref, "gadgets", NULL, true); + + found = 0; + + for (i = 0; i < count; i++) + found += list[i].count; + + switch (found) + { + case 0: + msg = strdup(_("No ROP gadget has been found.")); + break; + + case 1: + msg = strdup(_("1 ROP gadget has been found.")); + break; + + default: + asprintf(&msg, _("%zu gadgets have been found."), found); + break; + + } + + push_dyn_status_printing_of_rop_search_step(ref, "final", msg, count > 0); + + lfrg_unlock: + + push_found_rop_gadgets(ref, format, list, count); + + return NULL; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MISE EN FORME DES GADGETS PRESENTS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : assistant = fenêtre d'assistance à compléter. * +* ref = espace de référencements inter-panneaux. * +* * +* Description : Ajoute le panneau de sélection des gadgets ROP identifiés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void register_rop_list_panel(GtkAssistant *assistant, GObject *ref) +{ + GtkWidget *vbox; /* Support principal */ + GtkWidget *hbox; /* Petite barre supérieure */ + GtkWidget *label; /* Etiquette d'indication */ + GtkWidget *comboboxentry; /* Liste de sélection simple */ + GtkWidget *vseparator; /* Barre de séparation */ + GtkWidget *filter; /* Zone de recherche */ + GtkWidget *scrollwnd; /* Support défilant */ + GtkTreeStore *store; /* Modèle de gestion */ + GtkTreeModel *model; /* Modèle de gestion supérieur */ + GtkWidget *treeview; /* Affichage de la liste */ + GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ + GtkTreeViewColumn *column; /* Colonne de la liste */ + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 8); + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + + /* Choix de la catégorie */ + + label = gtk_label_new(_("ROP selection:")); + gtk_widget_show(label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + comboboxentry = qck_create_combobox(ref, "filter_cat", G_CALLBACK(on_rop_gadgets_category_changed), ref); + gtk_box_pack_start(GTK_BOX(hbox), comboboxentry, FALSE, TRUE, 0); + + /* Séparation fine */ + + vseparator = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + gtk_widget_show(vseparator); + gtk_box_pack_start(GTK_BOX(hbox), vseparator, FALSE, FALSE, 0); + + /* Espace de recherche */ + + label = gtk_label_new(_("Filter:")); + gtk_widget_show(label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + filter = gtk_search_entry_new(); + g_object_set_data(ref, "filter_rop", filter); + gtk_widget_set_tooltip_text(filter, _("Filter gadgets using POSIX extended regular expressions")); + + g_signal_connect(filter, "search-changed", G_CALLBACK(on_rop_gadgets_filter_changed), ref); + gtk_widget_show(filter); + gtk_widget_set_hexpand(filter, TRUE); + + gtk_box_pack_start(GTK_BOX(hbox), filter, TRUE, TRUE, 0); + + /* Liste arborescente ou linéaire */ + + scrollwnd = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_show(scrollwnd); + gtk_box_pack_start(GTK_BOX(vbox), scrollwnd, TRUE, TRUE, 0); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN); + + store = gtk_tree_store_new(FRG_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING); + + model = gtk_tree_model_filter_new(GTK_TREE_MODEL(store), NULL); + + gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(model), + (GtkTreeModelFilterVisibleFunc)filter_visible_rop_gadgets, + ref, NULL); + + treeview = gtk_tree_view_new_with_model(model); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE); + gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(treeview), TRUE); + + g_object_set_data(ref, "treeview", treeview); + + gtk_widget_show(treeview); + gtk_container_add(GTK_CONTAINER(scrollwnd), treeview); + + /* Cellules d'affichage */ + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Address"), renderer, + "markup", FRG_VIRTUAL, + NULL); + gtk_tree_view_column_set_sort_column_id(column, FRG_VIRTUAL); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Gadgets"), renderer, + "markup", FRG_CONTENT, + NULL); + gtk_tree_view_column_set_sort_column_id(column, FRG_CONTENT); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); + + /* Intégration */ + + gtk_assistant_append_page(assistant, vbox); + gtk_assistant_set_page_title(assistant, vbox, _("ROP Gadgets")); + gtk_assistant_set_page_type(assistant, vbox, GTK_ASSISTANT_PAGE_CONFIRM); + + gtk_assistant_set_page_complete(assistant, vbox, TRUE); + +} + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : combo = composant de choix contenant le filtre brut. * +* ref = espace de référencements inter-panneaux. * +* * +* Description : Lance l'actualisation du filtrage des gadgets ROP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_rop_gadgets_category_changed(GtkComboBox *combo, GObject *ref) +{ + GtkTreeView *treeview; /* Arborescence à actualiser */ + GtkTreeModelFilter *filter; /* Modèle de gestion associé */ + + treeview = GTK_TREE_VIEW(g_object_get_data(ref, "treeview")); + + filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(treeview)); + + gtk_tree_model_filter_refilter(filter); + +} + + +/****************************************************************************** +* * +* Paramètres : entry = entrée de texte contenant le filtre brut. * +* ref = espace de référencements inter-panneaux. * +* * +* Description : Lance l'actualisation du filtrage des gadgets ROP. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_rop_gadgets_filter_changed(GtkSearchEntry *entry, GObject *ref) +{ + regex_t preg; /* Expression régulière de test*/ + const gchar *text; /* Texte de l'utilisateur */ + int ret; /* Bilan de mise en place */ + GdkRGBA error; /* Couleur d'erreur */ + GtkTreeView *treeview; /* Arborescence à actualiser */ + GtkTreeModelFilter *filter; /* Modèle de gestion associé */ + + text = gtk_entry_get_text(GTK_ENTRY(entry)); + + if (text[0] != '\0') + { + ret = regcomp(&preg, text, REG_EXTENDED); + + if (ret != 0) + { + error.red = 1.0; + error.green = 0.0; + error.blue = 0.0; + error.alpha = 1.0; + gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error); + + return; + + } + + regfree(&preg); + + } + + gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL); + + treeview = GTK_TREE_VIEW(g_object_get_data(ref, "treeview")); + + filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(treeview)); + + gtk_tree_model_filter_refilter(filter); + +} + + +/****************************************************************************** +* * +* Paramètres : model = gestionnaire des lignes et colonnes affichées. * +* iter = ligne concernée par l'analyse à mener. * +* ref = espace de référencements inter-panneaux. * +* * +* Description : Détermine la visibilité de tel ou tel gadget ROP. * +* * +* Retour : Indication d'affichage pour une ligne donnée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean filter_visible_rop_gadgets(GtkTreeModel *model, GtkTreeIter *iter, GObject *ref) +{ + gboolean result; /* Visibilité à retourner */ + gchar *category; /* Catégorie d'appartenance */ + gchar *raw; /* Brut pour recherche */ + GtkComboBoxText *combo; /* Sélection à choix multiples */ + gchar *selected; /* Texte de l'utilisateur #1 */ + GtkEntry *entry; /* Zone de texte à utiliser */ + const gchar *text; /* Texte de l'utilisateur #2 */ + regex_t preg; /* Expression régulière de test*/ + int ret; /* Bilan de mise en place */ + regmatch_t match; /* Récupération des trouvailles*/ + + result = TRUE; + + gtk_tree_model_get(model, iter, FRG_CATEGORY, &category, FRG_RAW, &raw, -1); + + if (category == NULL || raw == NULL) return FALSE; + + /* Filtre sur les catégories */ + + combo = g_object_get_data(ref, "filter_cat"); + + selected = gtk_combo_box_text_get_active_text(combo); + + result &= (g_strcmp0(category, selected) == 0); + + g_free(selected); + + /* Filtre sur les gadgets ROP */ + + entry = g_object_get_data(ref, "filter_rop"); + + text = gtk_entry_get_text(GTK_ENTRY(entry)); + + ret = regcomp(&preg, text, REG_EXTENDED); + result &= (ret == 0); + + if (ret == 0) + { + ret = regexec(&preg, raw, 1, &match, 0); + result &= (ret != REG_NOMATCH); + + regfree(&preg); + + } + + /* Nettoyages finaux */ + + g_free(category); + g_free(raw); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format binaire chargé sur lequel se reposer. * +* combo = composant de sélection des catégories à compléter.* +* store = modèle de gestionnaire pour la liste affichée. * +* category = représentation du binaire chargé en mémoire. * +* gadgets = liste de listes d'instructions de ROP. * +* count = taille de cette liste. * +* * +* Description : Ajoute de nouvelles chaînes de gadgets localisées. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void add_new_gadgets_for_category(GBinFormat *format, GtkComboBoxText *combo, GtkTreeStore *store, const char *category, GArchInstruction **gadgets, size_t count) +{ + const char *target; /* Sous-traitance requise */ + GArchProcessor *proc; /* Architecture du binaire */ + MemoryDataSize msize; /* Taille du bus d'adresses */ + const bin_t *content; /* Contenu binaire global */ + GCodeBuffer *buffer; /* Tampon de rassemblement */ + size_t i; /* Boucle de parcours */ + GArchInstruction *instr; /* Elément de liste de gadgets */ + GBufferLine *line; /* Ligne présente à l'adresse */ + char *raw_virtual; /* Transcription pour export */ + char *virtual; /* Transcription d'adresse */ + char *partial_raw; /* Contenu de la ligne visée */ + char *partial_markup; /* Contenu de la ligne visée */ + char *content_raw; /* Contenu assemblé de chaîne */ + char *content_markup; /* Contenu assemblé de chaîne */ + GtkTreeIter iter; /* Point d'insertion */ + + /* Définition de l'écosystème nécessaire */ + + target = g_exe_format_get_target_machine(G_EXE_FORMAT(format)); + proc = get_arch_processor_for_type(target); + + msize = g_arch_processor_get_memory_size(proc); + + g_object_unref(G_OBJECT(proc)); + + content = g_binary_format_get_content(G_BIN_FORMAT(format), NULL); + + /* Conversion en contenu textuel */ + + buffer = g_code_buffer_new(BLC_ASSEMBLY); + + for (i = 0; i < count; i++) + { + /* Parcours des différentes lignes */ + + content_raw = NULL; + content_markup = NULL; + + for (instr = gadgets[i]; instr != NULL; instr = g_arch_instruction_get_next_iter(gadgets[i], instr, ~0)) + { + line = g_arch_instruction_print(instr, buffer, msize, content, ASX_INTEL); + if (line == NULL) continue; + + if (instr == gadgets[i]) + { + raw_virtual = g_buffer_line_get_text(line, BLC_VIRTUAL, BLC_VIRTUAL + 1, false); + virtual = g_buffer_line_get_text(line, BLC_VIRTUAL, BLC_VIRTUAL + 1, true); + } + + partial_raw = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, false); + partial_markup = g_buffer_line_get_text(line, BLC_ASSEMBLY_HEAD, BLC_COUNT, true); + + if (content_raw != NULL) + content_raw = stradd(content_raw, " ; "); + + content_raw = stradd(content_raw, partial_raw); + + if (content_markup != NULL) + content_markup = stradd(content_markup, " ; "); + + content_markup = stradd(content_markup, partial_markup); + + free(partial_raw); + free(partial_markup); + + } + + /* Insertion finale */ + + gtk_tree_store_append(store, &iter, NULL); + + gtk_tree_store_set(store, &iter, + FRG_CATEGORY, category, + FRG_RAW_VIRTUAL, raw_virtual, + FRG_RAW, content_raw, + FRG_VIRTUAL, virtual, + FRG_CONTENT, content_markup, + -1); + + /* Nettoyage de la mémoire */ + + free(raw_virtual); + free(virtual); + free(content_raw); + free(content_markup); + + } + + g_object_unref(G_OBJECT(buffer)); + + /* Rajout de la catégorie et filtre au besoin */ + + gtk_combo_box_text_append_text(combo, category); + + if (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)) == -1) + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); + +} diff --git a/plugins/ropgadgets/select.h b/plugins/ropgadgets/select.h new file mode 100644 index 0000000..9e18ddd --- /dev/null +++ b/plugins/ropgadgets/select.h @@ -0,0 +1,40 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * goto.h - prototypes pour la boîte de dialogue pour les sauts à une adresse donnée + * + * Copyright (C) 2012 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _DIALOGS_GOTOX_H +#define _DIALOGS_GOTOX_H + + +#include <gtk/gtk.h> + + +#include <analysis/binary.h> + + + +/* Crée et affiche un assistant de sélection de gadgets ROP. */ +void run_rop_finder_assistant(GObject *, GtkWindow *); + + + +#endif /* _DIALOGS_GOTOX_H */ |