From 3674529a39efe30672fd386ae25367fea1502a69 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 9 Feb 2020 23:02:42 +0100
Subject: Hardened the renaming of Elf external entries.

---
 plugins/elf/format.c  | 20 ++++++++++++++------
 plugins/elf/loading.c |  4 +++-
 plugins/elf/loading.h |  2 +-
 plugins/elf/symbols.c | 31 +++++++++++++++++++++++++------
 4 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/plugins/elf/format.c b/plugins/elf/format.c
index f2f7609..c5f5530 100644
--- a/plugins/elf/format.c
+++ b/plugins/elf/format.c
@@ -333,7 +333,7 @@ static bool g_elf_format_analyze(GElfFormat *format, wgroup_id_t gid, GtkStatusS
     exe = G_EXE_FORMAT(format);
 
     if (!read_elf_header(format, &format->header, &format->is_32b, &format->endian))
-        goto gefa_error;
+        goto error;
 
     /* Vérification des tailles d'entrée de table */
 
@@ -377,7 +377,7 @@ static bool g_elf_format_analyze(GElfFormat *format, wgroup_id_t gid, GtkStatusS
 
         default:
             log_variadic_message(LMT_ERROR, "Architecture not supported for ELF binaries");
-            goto gefa_error;
+            goto error;
             break;
 
     }
@@ -398,17 +398,17 @@ static bool g_elf_format_analyze(GElfFormat *format, wgroup_id_t gid, GtkStatusS
     preload_binary_format(PGA_FORMAT_PRELOAD, base, base->info, status);
 
     if (!load_elf_symbols(format, gid, status))
-        goto gefa_error;
+        goto error;
 
     if (!find_all_elf_strings(format, gid, status))
-        goto gefa_error;
+        goto error;
 
     if (!g_executable_format_complete_loading(exe, gid, status))
-        goto gefa_error;
+        goto error;
 
     result = true;
 
- gefa_error:
+ error:
 
     return result;
 
@@ -450,6 +450,14 @@ static SourceEndian g_elf_format_get_endianness(const GElfFormat *format)
 
 static void g_elf_format_complete_analysis(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
+    /**
+     * C'est la phase de désassemblage qui produit les symboles externes appelés
+     * au sein du code.
+     *
+     * Le renommage de ces symboles doit donc intervenir une fois les symboles
+     * en place, donc après les opérations de désassemblage terminées.
+     */
+
     refresh_elf_relocations(format, gid, status);
 
 }
diff --git a/plugins/elf/loading.c b/plugins/elf/loading.c
index 7b257f0..5bd7daa 100644
--- a/plugins/elf/loading.c
+++ b/plugins/elf/loading.c
@@ -458,6 +458,7 @@ static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
     phys_t old;                             /* Sauvegarde du point d'avant */
     bool ret;                               /* Bilan d'un appel            */
     size_t processed;                       /* Nombre de symboles traités  */
+    virt_t valid;                           /* Adresse virtuelle valide    */
     GBinSymbol *symbol;                     /* Symbole analysé             */
 
     format = loading->format;
@@ -489,12 +490,13 @@ static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
             ret = true;
 
             processed = 0;
+            valid = 0;
 
             for (symbol = get_symbol_iterator_next(loading->iter);
                  symbol != NULL && ret;
                  symbol = get_symbol_iterator_next(loading->iter))
             {
-                ret = loading->callback_1(loading, format, symbol);
+                ret = loading->callback_1(loading, format, &valid, symbol);
 
                 g_object_unref(G_OBJECT(symbol));
 
diff --git a/plugins/elf/loading.h b/plugins/elf/loading.h
index 62d8efe..8fb4ce9 100644
--- a/plugins/elf/loading.h
+++ b/plugins/elf/loading.h
@@ -52,7 +52,7 @@ typedef struct _GElfLoadingClass GElfLoadingClass;
 typedef bool (* elf_loading_cb) (GElfLoading *, GElfFormat *, phys_t *);
 
 /* Assure l'intégration d'un symbole issu des relocalisations. */
-typedef bool (* elf_applying_cb) (GElfLoading *, GElfFormat *, GBinSymbol *);
+typedef bool (* elf_applying_cb) (GElfLoading *, GElfFormat *, virt_t *, GBinSymbol *);
 
 
 /* Indique le type défini pour les tâches de chargements pour format ELF. */
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index 26876bd..854d724 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -101,7 +101,7 @@ static bool do_elf_relocation_loading(GElfLoading *, GElfFormat *, phys_t *);
 static bool load_elf_relocations(GElfFormat *, const elf_phdr *, elf_rel **, size_t *, wgroup_id_t, GtkStatusStack *);
 
 /* Assure l'intégration d'un symbole issu des relocalisations. */
-static bool do_elf_relocation_renaming(GElfLoading *, GElfFormat *, GBinSymbol *);
+static bool do_elf_relocation_renaming(GElfLoading *, GElfFormat *, virt_t *, GBinSymbol *);
 
 /* Applique les étiquettes issues des relocalisations. */
 static bool apply_elf_relocations(GElfFormat *, elf_rel *, size_t, sym_iter_t *, wgroup_id_t, GtkStatusStack *);
@@ -1263,6 +1263,7 @@ bool refresh_elf_relocations(GElfFormat *format, wgroup_id_t gid, GtkStatusStack
 *                                                                             *
 *  Paramètres  : loading = chargement de relocalisations en cours.            *
 *                format  = format ELF à compléter.                            *
+*                valid   = dernière adresse virtuelle non couverte. [OUT]     *
 *                symbol  = symbole courant issu de la liste à analyser.       *
 *                                                                             *
 *  Description : Assure l'intégration d'un symbole issu des relocalisations.  *
@@ -1273,7 +1274,7 @@ bool refresh_elf_relocations(GElfFormat *format, wgroup_id_t gid, GtkStatusStack
 *                                                                             *
 ******************************************************************************/
 
-static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format, GBinSymbol *symbol)
+static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format, virt_t *valid, GBinSymbol *symbol)
 {
     bool result;                            /* Bilan à retourner           */
     const mrange_t *range;                  /* Espace occupé par le symbole*/
@@ -1290,6 +1291,22 @@ static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format,
 
     range = g_binary_symbol_get_range(symbol);
 
+    /**
+     * Il peut arriver qu'un symbole figure par erreur dans la liste des symboles
+     * importés. Cela fait par exemple suite au désassemblage d'une zone considèrée
+     * de façon erronée comme du code, opération qui conduit à la création fortuite
+     * d'un symbole non désiré.
+     *
+     * On se prémunit ici d'une erreur de traitement en vérifiant simplement la
+     * couverture des symboles externes, qui englobe un éventuel symbole superflu.
+     */
+
+    if (range->addr.virtual < *valid)
+    {
+        result = true;
+        goto exit;
+    }
+
     stype = g_binary_symbol_get_stype(symbol);
 
     if (stype != STP_ROUTINE && stype != STP_CODE_LABEL && stype != STP_ENTRY_POINT)
@@ -1297,7 +1314,7 @@ static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format,
         g_binary_format_add_error(G_BIN_FORMAT(format), BFE_SPECIFICATION, get_mrange_addr(range),
                                   _("The PLT seems to contains more than routines"));
 
-        goto derr_exit;
+        goto exit;
 
     }
 
@@ -1308,10 +1325,10 @@ static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format,
     /* Détermination de la relocalisation associée */
 
     result = format->ops.get_linkage_offset(format, range, &offset);
-    if (!result) goto derr_exit;
+    if (!result) goto exit;
 
     result = g_elf_loading_search_for_relocation(loading, &offset, &reloc);
-    if (!result) goto derr_exit;
+    if (!result) goto exit;
 
     /* Récupération des données du symbole visé */
 
@@ -1342,7 +1359,9 @@ static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format,
 
     free(name);
 
- derr_exit:
+    *valid = range->addr.virtual + range->length;
+
+ exit:
 
     return result;
 
-- 
cgit v0.11.2-87-g4458