From 4da58817622d6c4c35e4cd4e6a99111065a87f54 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 28 Nov 2018 19:30:12 +0100
Subject: Adapted ROP finding to architectures in a better way.

---
 plugins/ropgadgets/Makefile.am  |   1 +
 plugins/ropgadgets/finder.c     |  70 ++++++++++++++-----------
 plugins/ropgadgets/helper.c     | 110 ++++++++++++++++++++++++++++++++++++++++
 plugins/ropgadgets/helper.h     |  43 ++++++++++++++++
 plugins/ropgadgets/helper_arm.c |  87 ++++++++++++++++++++++++-------
 plugins/ropgadgets/helper_arm.h |   8 ++-
 6 files changed, 269 insertions(+), 50 deletions(-)
 create mode 100644 plugins/ropgadgets/helper.c
 create mode 100644 plugins/ropgadgets/helper.h

diff --git a/plugins/ropgadgets/Makefile.am b/plugins/ropgadgets/Makefile.am
index 8df1c2e..3302421 100644
--- a/plugins/ropgadgets/Makefile.am
+++ b/plugins/ropgadgets/Makefile.am
@@ -6,6 +6,7 @@ libdir = $(pluginslibdir)
 
 libropgadgets_la_SOURCES =				\
 	finder.h finder.c					\
+	helper.h helper.c					\
 	helper_arm.h helper_arm.c			\
 	plugin.h plugin.c					\
 	select.h select.c
diff --git a/plugins/ropgadgets/finder.c b/plugins/ropgadgets/finder.c
index 7296757..3e7ed1a 100644
--- a/plugins/ropgadgets/finder.c
+++ b/plugins/ropgadgets/finder.c
@@ -28,22 +28,33 @@
 #include <string.h>
 
 
-#include <i18n.h>
 #include <core/processors.h>
 #include <format/format.h>
 
 
+#include "helper.h"
 #include "helper_arm.h"
 
 
 
+/* Actions selon l'architecture */
+typedef struct _domain_ops
+{
+    size_t (* list) (char ***);
+    GProcContext * (* get) (const GArchProcessor *, size_t);
+
+    const phys_t * (* setup) (size_t *);
+
+} domain_ops;
+
 /* Données utiles à transmettre */
 typedef struct _search_domain
 {
     GExeFormat *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   */
+
+    domain_ops ops;                         /* Actions particulières       */
 
     mrange_t *exe_ranges;                   /* Liste de zones exécutables  */
     size_t exe_count;                       /* Nombre de ces zones         */
@@ -56,22 +67,23 @@ typedef struct _search_domain
 
 
 /* Désassemble rapidement une instruction. */
-static GArchInstruction *disassemble_instruction_in_domain(const search_domain *, vmpa2t *);
+static GArchInstruction *disassemble_instruction_in_domain(const search_domain *, size_t, vmpa2t *);
 
 /* Etend la constitution d'une chaîne d'instructions. */
 static rop_chain *push_new_instruction(rop_chain *, GArchInstruction *);
 
 /* Désassemble en amont d'une position autant que possible. */
-static void look_backward_for_gadgets(const search_domain *, const mrange_t *, const vmpa2t *, unsigned int, rop_chain *);
+static void look_backward_for_gadgets(const search_domain *, size_t, const mrange_t *, const vmpa2t *, unsigned int, rop_chain *);
 
 /* Etablit une liste de tous les gadgets présents. */
-static rop_chain **list_all_gadgets_in_domain(const search_domain *, unsigned int, update_search_progress_cb, GObject *, size_t *);
+static rop_chain **list_all_gadgets_in_domain(const search_domain *, size_t, unsigned int, update_search_progress_cb, GObject *, size_t *);
 
 
 
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : domain = ensemble d'auxiliaires à disposition.               *
+*                index = indice du type de contexte désiré.                   *
 *                pos    = tête de lecture pour le désassemblage.              *
 *                                                                             *
 *  Description : Désassemble rapidement une instruction.                      *
@@ -82,12 +94,12 @@ static rop_chain **list_all_gadgets_in_domain(const search_domain *, unsigned in
 *                                                                             *
 ******************************************************************************/
 
-static GArchInstruction *disassemble_instruction_in_domain(const search_domain *domain, vmpa2t *pos)
+static GArchInstruction *disassemble_instruction_in_domain(const search_domain *domain, size_t index, vmpa2t *pos)
 {
     GArchInstruction *result;               /* Instruction à retourner     */
     GProcContext *ctx;                      /* Contexte de désassemblage   */
 
-    ctx = domain->ctx;  /* TODO : copie */
+    ctx = domain->ops.get(domain->proc, index);
 
     result = g_arch_processor_disassemble(domain->proc, ctx, domain->content, pos, domain->format);
 
@@ -97,7 +109,7 @@ static GArchInstruction *disassemble_instruction_in_domain(const search_domain *
         g_arch_instruction_call_hook(result, IPH_POST, domain->proc, ctx, domain->format);
     }
 
-    //g_object_unref(G_OBJECT(ctx)); /* TODO */
+    g_object_unref(G_OBJECT(ctx));
 
     return result;
 
@@ -151,6 +163,7 @@ static rop_chain *push_new_instruction(rop_chain *chain, GArchInstruction *instr
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : domain    = ensemble d'auxiliaires à disposition.            *
+*                index     = indice du type de contexte désiré.               *
 *                exe_range = couverture globale dont il ne faut pas sortir.   *
 *                ret       = point de retour final déjà trouvé.               *
 *                max_depth = profondeur maximale des recherches.              *
@@ -164,7 +177,7 @@ static rop_chain *push_new_instruction(rop_chain *chain, GArchInstruction *instr
 *                                                                             *
 ******************************************************************************/
 
-static void look_backward_for_gadgets(const search_domain *domain, const mrange_t *exe_range, const vmpa2t *ret, unsigned int max_depth, rop_chain *chain)
+static void look_backward_for_gadgets(const search_domain *domain, size_t index, const mrange_t *exe_range, const vmpa2t *ret, unsigned int max_depth, rop_chain *chain)
 {
     const phys_t *ins_sizes;                /* Tailles potentielles        */
     size_t sizes_count;                     /* Quantité de tailles à tester*/
@@ -177,8 +190,7 @@ static void look_backward_for_gadgets(const search_domain *domain, const mrange_
     phys_t diff;                            /* Volume de données traité    */
     mrange_t range;                         /* Couverture de l'instruction */
 
-    ins_sizes = (phys_t []){ 2, 4 };    /* FIXME */
-    sizes_count = 2;
+    ins_sizes = domain->ops.setup(&sizes_count);
 
     copy_vmpa(&last, ret);
 
@@ -197,7 +209,7 @@ static void look_backward_for_gadgets(const search_domain *domain, const mrange_
 
             copy_vmpa(&end, &start);
 
-            instr = disassemble_instruction_in_domain(domain, &end);
+            instr = disassemble_instruction_in_domain(domain, index, &end);
             if (instr == NULL) continue;
 
             /* La jointure est-elle parfaite ? */
@@ -241,6 +253,7 @@ static void look_backward_for_gadgets(const search_domain *domain, const mrange_
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : domain    = ensemble d'auxiliaires à disposition.            *
+*                index     = indice du type de contexte désiré.               *
 *                max_depth = profondeur maximale des recherches.              *
 *                update    = fonction de suivi mise à disposition.            *
 *                data      = données à associer à une phase d'actualisation.  *
@@ -254,7 +267,7 @@ static void look_backward_for_gadgets(const search_domain *domain, const mrange_
 *                                                                             *
 ******************************************************************************/
 
-static rop_chain **list_all_gadgets_in_domain(const search_domain *domain, unsigned int max_depth, update_search_progress_cb update, GObject *data, size_t *count)
+static rop_chain **list_all_gadgets_in_domain(const search_domain *domain, size_t index, unsigned int max_depth, update_search_progress_cb update, GObject *data, size_t *count)
 {
     rop_chain **result;                     /* Liste de listes à renvoyer  */
     phys_t done;                            /* Accumulation des quantités  */
@@ -295,7 +308,7 @@ static rop_chain **list_all_gadgets_in_domain(const search_domain *domain, unsig
 
             copy_vmpa(&tmp, &ret);
 
-            gadget = disassemble_instruction_in_domain(domain, &tmp);
+            gadget = disassemble_instruction_in_domain(domain, index, &tmp);
             if (gadget == NULL) continue;
 
             /* A-t-on bien affaire à une instruction de retour ? */
@@ -325,7 +338,7 @@ static rop_chain **list_all_gadgets_in_domain(const search_domain *domain, unsig
 
             chain = push_new_instruction(NULL, gadget);
 
-            look_backward_for_gadgets(domain, &domain->exe_ranges[i], &ret, max_depth, chain);
+            look_backward_for_gadgets(domain, index, &domain->exe_ranges[i], &ret, max_depth, chain);
 
             result = (rop_chain **)realloc(result, ++(*count) * sizeof(rop_chain *));
             result[*count - 1] = chain;
@@ -363,7 +376,6 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd
     const char *target;                     /* Sous-traitance requise      */
     search_domain domain;                   /* Outils pour la recherche    */
     GBinPortion *portions;                  /* Couche première de portions */
-    GProcContext **contexts;                /* Contextes pour recherches   */
     char **names;                           /* Désignations humaines liées */
     size_t i;                               /* Boucle de parcours          */
 
@@ -410,19 +422,20 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd
     /* Récupération des différents contextes */
 
     if (strcmp(target, "armv7") == 0)
-        contexts = get_rop_contexts_for_arm(domain.proc, &names, count);
-
+    {
+        domain.ops.list = list_rop_contexts_for_arm;
+        domain.ops.get = get_rop_contexts_for_arm;
+        domain.ops.setup = setup_instruction_sizes_for_arm;
+    }
     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");
-
+        domain.ops.list = list_rop_contexts_by_default;
+        domain.ops.get = get_rop_contexts_by_default;
+        domain.ops.setup = setup_instruction_sizes_by_default;
     }
 
+    *count = domain.ops.list(&names);
+
     /* Calcul de la surface totale à parcourir */
 
     domain.sum = 0;
@@ -444,18 +457,13 @@ found_rop_list *list_all_gadgets(GExeFormat *format, unsigned int max_depth, upd
     {
         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));
+        result[i].gadgets = list_all_gadgets_in_domain(&domain, i, max_depth, update, data, &result[i].count);
 
         domain.runs_done++;
 
     }
 
     free(names);
-    free(contexts);
 
     free(domain.exe_ranges);
 
diff --git a/plugins/ropgadgets/helper.c b/plugins/ropgadgets/helper.c
new file mode 100644
index 0000000..ff89e85
--- /dev/null
+++ b/plugins/ropgadgets/helper.c
@@ -0,0 +1,110 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helper.c - recherche générique de gadgets
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "helper.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include <i18n.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : names = noms attribués aux différents contextes. [OUT]       *
+*                                                                             *
+*  Description : Etablit une liste des contextes utiles à la recherche.       *
+*                                                                             *
+*  Retour      : Nombre de contextes gérés pour cette architecture.           *
+*                                                                             *
+*  Remarques   : Tous les tableaux créés sont à libérer après usage.          *
+*                                                                             *
+******************************************************************************/
+
+size_t list_rop_contexts_by_default(char ***names)
+{
+    size_t result;                          /* Quantité à renvoyer         */
+
+    result = 1;
+
+    (*names) = malloc(result * sizeof(char *));
+
+    (*names)[0] = _("all");
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc  = processeur lié à l'architecture visée.               *
+*                index = indice du type de contexte désiré.                   *
+*                                                                             *
+*  Description : Etablit un contexte utile et adapté à une recherche.         *
+*                                                                             *
+*  Retour      : Contexte mis en place.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GProcContext *get_rop_contexts_by_default(const GArchProcessor *proc, size_t index)
+{
+    GProcContext *result;                   /* Contexte à retourner        */
+
+    assert(index == 0);
+
+    result = g_arch_processor_get_context(proc);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : count = nombre d'éléments du tableau retourné. [OUT]         *
+*                                                                             *
+*  Description : Définit les tailles possibles d'une instruction recherchée.  *
+*                                                                             *
+*  Retour      : Liste de tailles plausibles.                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const phys_t *setup_instruction_sizes_by_default(size_t *count)
+{
+    const phys_t *result;                   /* Liste de taille à renvoyer  */
+
+    result = (phys_t []){ 1 };
+
+    *count = 1;
+
+    return result;
+
+}
diff --git a/plugins/ropgadgets/helper.h b/plugins/ropgadgets/helper.h
new file mode 100644
index 0000000..84e5e13
--- /dev/null
+++ b/plugins/ropgadgets/helper.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helper.h - prototypes pour la recherche générique de gadgets
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_ROPGADGETS_HELPER_H
+#define _PLUGINS_ROPGADGETS_HELPER_H
+
+
+#include <arch/processor.h>
+
+
+
+/* Etablit une liste des contextes utiles à la recherche. */
+size_t list_rop_contexts_by_default(char ***);
+
+/* Etablit un contexte utile et adapté à une recherche. */
+GProcContext *get_rop_contexts_by_default(const GArchProcessor *, size_t);
+
+/* Définit les tailles possibles d'une instruction recherchée. */
+const phys_t *setup_instruction_sizes_by_default(size_t *);
+
+
+
+#endif  /* _PLUGINS_ROPGADGETS_HELPER_H */
diff --git a/plugins/ropgadgets/helper_arm.c b/plugins/ropgadgets/helper_arm.c
index 2361f06..ae6edf3 100644
--- a/plugins/ropgadgets/helper_arm.c
+++ b/plugins/ropgadgets/helper_arm.c
@@ -24,6 +24,7 @@
 #include "helper_arm.h"
 
 
+#include <assert.h>
 #include <malloc.h>
 
 
@@ -33,43 +34,93 @@
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : proc  = processeur lié à l'architecture visée.               *
-*                names = noms attribués aux différents contextes.             *
-*                count = nombre de gadgets trouvés. [OUT]                     *
+*  Paramètres  : names = noms attribués aux différents contextes. [OUT]       *
 *                                                                             *
 *  Description : Etablit une liste des contextes utiles à la recherche.       *
 *                                                                             *
-*  Retour      : Liste de contextes mis en place.                             *
+*  Retour      : Nombre de contextes gérés pour cette architecture.           *
 *                                                                             *
-*  Remarques   : Toues les tableaux créés sont à libérer après usage.         *
+*  Remarques   : Tous les tableaux créés sont à libérer après usage.          *
 *                                                                             *
 ******************************************************************************/
 
-GProcContext **get_rop_contexts_for_arm(const GArchProcessor *proc, char ***names, size_t *count)
+size_t list_rop_contexts_for_arm(char ***names)
 {
-    GProcContext **result;                  /* Contextes à retourner       */
+    size_t result;                          /* Quantité à renvoyer         */
 
-    result = (GProcContext **)calloc(2, sizeof(GProcContext *));
+    result = 2;
 
-    (*names) = (char **)calloc(2, sizeof(char *));
+    (*names) = malloc(result * sizeof(char *));
 
-    *count = 2;
+    (*names)[0] = "Thumb";
+    (*names)[1] = "ARM";
 
-    /* Thumb */
+    return result;
 
-    result[0] = g_arch_processor_get_context(proc);
+}
 
-    g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result[0]), 0, AV7IS_THUMB);
 
-    (*names)[0] = "Thumb";
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc  = processeur lié à l'architecture visée.               *
+*                index = indice du type de contexte désiré.                   *
+*                                                                             *
+*  Description : Etablit un contexte utile et adapté à une recherche.         *
+*                                                                             *
+*  Retour      : Contexte mis en place.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    /* ARMM */
+GProcContext *get_rop_contexts_for_arm(const GArchProcessor *proc, size_t index)
+{
+    GProcContext *result;                   /* Contexte à retourner        */
 
-    result[1] = g_arch_processor_get_context(proc);
+    result = g_arch_processor_get_context(proc);
 
-    g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result[1]), 0, AV7IS_ARM);
+    switch (index)
+    {
+        /* Thumb */
+        case 0:
+            g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result), 0, AV7IS_THUMB);
+            break;
 
-    (*names)[1] = "ARM";
+        /* ARM */
+        case 1:
+            g_armv7_context_define_encoding(G_ARMV7_CONTEXT(result), 0, AV7IS_ARM);
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : count = nombre d'éléments du tableau retourné. [OUT]         *
+*                                                                             *
+*  Description : Définit les tailles possibles d'une instruction recherchée.  *
+*                                                                             *
+*  Retour      : Liste de tailles plausibles.                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const phys_t *setup_instruction_sizes_for_arm(size_t *count)
+{
+    const phys_t *result;                   /* Liste de taille à renvoyer  */
+
+    result = (phys_t []){ 2, 4 };
+
+    *count = 2;
 
     return result;
 
diff --git a/plugins/ropgadgets/helper_arm.h b/plugins/ropgadgets/helper_arm.h
index cb2021f..c9f3892 100644
--- a/plugins/ropgadgets/helper_arm.h
+++ b/plugins/ropgadgets/helper_arm.h
@@ -30,7 +30,13 @@
 
 
 /* Etablit une liste des contextes utiles à la recherche. */
-GProcContext **get_rop_contexts_for_arm(const GArchProcessor *, char ***, size_t *);
+size_t list_rop_contexts_for_arm(char ***);
+
+/* Etablit un contexte utile et adapté à une recherche. */
+GProcContext *get_rop_contexts_for_arm(const GArchProcessor *, size_t);
+
+/* Définit les tailles possibles d'une instruction recherchée. */
+const phys_t *setup_instruction_sizes_for_arm(size_t *);
 
 
 
-- 
cgit v0.11.2-87-g4458