summaryrefslogtreecommitdiff
path: root/plugins/ropgadgets
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-05-11 00:58:05 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-05-11 00:58:05 (GMT)
commit46bcc7f122245f22772fd3e38d16e6afa7bd5881 (patch)
treed3c2ba1a9999e373428954f24d0e60c1ea63b756 /plugins/ropgadgets
parent1bda6c517d30d873ff0d92a96380946ef944c9ae (diff)
Provided a way to look for ROP gadgets in binary code.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@533 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'plugins/ropgadgets')
-rw-r--r--plugins/ropgadgets/Makefile.am15
-rw-r--r--plugins/ropgadgets/finder.c399
-rw-r--r--plugins/ropgadgets/finder.h53
-rw-r--r--plugins/ropgadgets/helper_arm.c76
-rw-r--r--plugins/ropgadgets/helper_arm.h37
-rw-r--r--plugins/ropgadgets/plugin.c95
-rw-r--r--plugins/ropgadgets/plugin.h37
-rw-r--r--plugins/ropgadgets/select.c1845
-rw-r--r--plugins/ropgadgets/select.h40
9 files changed, 2597 insertions, 0 deletions
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 */