summaryrefslogtreecommitdiff
path: root/plugins/elf
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-02-12 04:43:01 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-02-12 04:43:01 (GMT)
commit4ff5e12f57a4c54e19a7ba987d243e5f86341aeb (patch)
tree7bb21628e753cf70e294567e782a1c1331804c35 /plugins/elf
parent3674529a39efe30672fd386ae25367fea1502a69 (diff)
Refreshed the code registering Elf entry points.
Diffstat (limited to 'plugins/elf')
-rw-r--r--plugins/elf/dynamic.c8
-rw-r--r--plugins/elf/symbols.c590
2 files changed, 317 insertions, 281 deletions
diff --git a/plugins/elf/dynamic.c b/plugins/elf/dynamic.c
index c6fce14..13292ec 100644
--- a/plugins/elf/dynamic.c
+++ b/plugins/elf/dynamic.c
@@ -333,15 +333,15 @@ bool resolve_plt_using_got(GElfFormat *format, virt_t *virt)
result = false;
if (!find_elf_program_by_type(format, PT_DYNAMIC, &dynamic))
- goto rpug_exit;
+ goto exit;
if (!_find_elf_dynamic_item_by_type(format, &dynamic, DT_PLTGOT, &pltgot))
- goto rpug_exit;
+ goto exit;
got_virt = ELF_DYN(format, pltgot, d_un.d_ptr);
if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), got_virt, &got_addr))
- goto rpug_exit;
+ goto exit;
content = G_BIN_FORMAT(format)->content;
@@ -377,7 +377,7 @@ bool resolve_plt_using_got(GElfFormat *format, virt_t *virt)
}
- rpug_exit:
+ exit:
return result;
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index 854d724..d24b6d6 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -52,12 +52,6 @@
/* ------------------------- CHARGEMENT GLOBAL DES SYMBOLES ------------------------- */
-/* Enregistre un point d'entrée au sein d'un binaire ELF. */
-static void register_elf_entry_point(GElfFormat *, virt_t, phys_t, GBinRoutine *);
-
-/* Enumère tous les points d'entrée principaux d'un binaire ELF. */
-static bool load_all_elf_basic_entry_points(GElfFormat *);
-
/* Assure le chargement des symboles internes ELF en différé. */
static bool do_elf_symbol_loading(GElfLoading *, GElfFormat *, bool, phys_t *, GBinSymbol **);
@@ -108,6 +102,20 @@ static bool apply_elf_relocations(GElfFormat *, elf_rel *, size_t, sym_iter_t *,
+/* ------------------------- INSCRIPTION DE POINTS D'ENTREE ------------------------- */
+
+
+/* Enregistre un point d'entrée au sein d'un binaire ELF. */
+static bool register_elf_entry_point(GElfFormat *, virt_t, GBinRoutine *);
+
+/* Désigne tous les points d'entrée par une étiquette dédiée. */
+static bool load_elf_entry_points_from_array(GElfFormat *, const elf_dyn *, const elf_dyn *, const char *);
+
+/* Enumère tous les points d'entrée principaux d'un binaire ELF. */
+static bool load_all_elf_basic_entry_points(GElfFormat *, GtkStatusStack *);
+
+
+
/* ---------------------------------------------------------------------------------- */
/* CHARGEMENT GLOBAL DES SYMBOLES */
/* ---------------------------------------------------------------------------------- */
@@ -150,11 +158,8 @@ bool load_elf_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *statu
/* Symboles d'entrée, si encore besoin */
- /**
- * Le tri en préalable
- */
-
- result &= load_all_elf_basic_entry_points(format);
+ if (result)
+ result = load_all_elf_basic_entry_points(format, status);
return result;
@@ -163,272 +168,6 @@ bool load_elf_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *statu
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
-* vaddr = adresse virtuelle du symbole à insérer. *
-* len = taille de la routine à ajouter. *
-* routine = représentation de la fonction repérée. *
-* *
-* Description : Enregistre un point d'entrée au sein d'un binaire ELF. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void register_elf_entry_point(GElfFormat *format, virt_t vaddr, phys_t len, GBinRoutine *routine)
-{
- GBinFormat *base; /* Version basique du format */
- virt_t final_vaddr; /* Adresse virtuelle retenue */
- bool status; /* Bilan d'une opération */
- vmpa2t addr; /* Localisation d'une routine */
- mrange_t range; /* Couverture mémoire associée */
- GBinSymbol *symbol; /* Nouveau symbole construit */
-
- /* Localisation complète du symbole */
-
- final_vaddr = format->ops.fix_virt(vaddr);
-
- status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_vaddr, &addr);
- if (!status) return;
-
- /* Comptabilisation en tant que symbole */
-
- if (g_binary_format_find_symbol_at(G_BIN_FORMAT(format), &addr, &symbol))
- {
- g_object_unref(G_OBJECT(symbol));
- g_object_unref(G_OBJECT(routine));
- }
-
- else
- {
- base = G_BIN_FORMAT(format);
-
- init_mrange(&range, &addr, len);
-
- symbol = G_BIN_SYMBOL(routine);
-
- g_binary_symbol_set_range(symbol, &range);
- g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT);
-
- g_binary_format_add_symbol(base, symbol);
-
- /* Comptabilisation pour le désassemblage brut */
- g_binary_format_register_code_point(base, vaddr, true);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* *
-* Description : Enumère tous les points d'entrée principaux d'un binaire ELF.*
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool load_all_elf_basic_entry_points(GElfFormat *format)
-{
- GBinFormat *base; /* Autre version du format */
- virt_t ep; /* Point d'entrée détecté */
- GBinRoutine *routine; /* Routine à associer à un pt. */
- elf_phdr dynamic; /* En-tête de programme DYNAMIC*/
- elf_dyn item_a; /* Premier élément DYNAMIC */
- elf_dyn item_b; /* Second élément DYNAMIC */
- const GBinContent *content; /* Contenu binaire à lire */
- phys_t length; /* Taille totale du contenu */
- bool status; /* Bilan d'une opération */
- vmpa2t pos; /* Tête de lecture courante */
- uint32_t virt_32; /* Adresse virtuelle sur 32b */
- uint64_t virt_64; /* Adresse virtuelle sur 64b */
-
- base = G_BIN_FORMAT(format);
-
- /* Point d'entrée principal éventuel */
-
- ep = ELF_HDR(format, format->header, e_entry);
-
- if (ep != 0x0)
- {
- routine = g_binary_format_decode_routine(base, "entry_point");
- register_elf_entry_point(format, ep, 0, routine);
- }
-
- /* Chargemet de l'en-tête de programme DYNAMIC */
-
- if (!find_elf_dynamic_program_header(format, &dynamic))
- goto laebep_exit;
-
- /* Détection des constructeurs & destructeurs */
-
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT, &item_a))
- {
- ep = ELF_DYN(format, item_a, d_un.d_ptr);
-
- if (ep != 0x0)
- {
- routine = g_binary_format_decode_routine(base, "init_function");
- register_elf_entry_point(format, ep, 0, routine);
- }
-
- }
-
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI, &item_a))
- {
- ep = ELF_DYN(format, item_a, d_un.d_ptr);
-
- if (ep != 0x0)
- {
- routine = g_binary_format_decode_routine(base, "termination_function");
- register_elf_entry_point(format, ep, 0, routine);
- }
-
- }
-
- void load_entry_points_from_array(GElfFormat *fmt, const elf_dyn *ar, const elf_dyn *sz, const char *prefix)
- {
- unsigned int i; /* Boucle de parcours */
- char fullname[64]; /* Désignation humaine */
-
- assert(sizeof(fullname) >= (strlen(prefix) + sizeof(XSTR(UINT64_MAX) + 1)));
-
- content = G_BIN_FORMAT(fmt)->content;
-
- status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format),
- ELF_DYN(fmt, *ar, d_un.d_val),
- &pos);
- if (!status) return;
-
- length = get_phy_addr(&pos) + ELF_DYN(fmt, *sz, d_un.d_val);
-
- for (i = 0; get_phy_addr(&pos) < length; i++)
- {
- /**
- * Selon la libc d'Android (https://www.codeaurora.org/.../android/bionic/linker/README.TXT) :
- *
- * DT_INIT_ARRAY
- * Points to an array of function addresses that must be
- * called, in-order, to perform initialization. Some of
- * the entries in the array can be 0 or -1, and should
- * be ignored.
- *
- * On étend le principe aux sections DT_FINI_ARRAY et DT_PREINIT_ARRAY.
- */
-
- if (fmt->is_32b)
- {
- status = g_binary_content_read_u32(content, &pos, fmt->endian, &virt_32);
- status &= (virt_32 != 0x0 && virt_32 != 0xffffffff);
- ep = virt_32;
- }
- else
- {
- status = g_binary_content_read_u64(content, &pos, fmt->endian, &virt_64);
- status &= (virt_64 != 0x0 && virt_64 != 0xffffffffffffffff);
- ep = virt_64;
- }
-
- if (status)
- {
- snprintf(fullname, sizeof(fullname), "%s%u", prefix, i);
-
- routine = g_binary_format_decode_routine(base, fullname);
- register_elf_entry_point(fmt, ep, 0, routine);
-
- }
-
- }
-
- }
-
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAY, &item_a))
- {
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAYSZ, &item_b))
- {
- load_entry_points_from_array(format, &item_a, &item_b, "init_array_function_");
- }
-
- }
-
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAY, &item_a))
- {
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAYSZ, &item_b))
- {
- load_entry_points_from_array(format, &item_a, &item_b, "fini_array_function_");
- }
-
- }
-
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAY, &item_a))
- {
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAYSZ, &item_b))
- {
- load_entry_points_from_array(format, &item_a, &item_b, "preinit_array_function_");
- }
-
- }
-
- /* Identification de l'entrée de la PLT */
-
- if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PLTGOT, &item_a))
- {
- status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format),
- ELF_DYN(format, item_a, d_un.d_val),
- &pos);
-
- if (status)
- {
- content = G_BIN_FORMAT(format)->content;
-
- /* On saute le premier élément... */
- if (format->is_32b)
- status = g_binary_content_read_u32(content, &pos, format->endian, &virt_32);
- else
- status = g_binary_content_read_u64(content, &pos, format->endian, &virt_64);
-
- while (1)
- {
- if (format->is_32b)
- {
- status = g_binary_content_read_u32(content, &pos, format->endian, &virt_32);
- ep = virt_32;
- }
- else
- {
- status = g_binary_content_read_u64(content, &pos, format->endian, &virt_64);
- ep = virt_64;
- }
-
- if (!status) break;
-
- if (ep != 0x0)
- {
- routine = g_binary_format_decode_routine(base, "plt_entry");
- register_elf_entry_point(format, ep, 0, routine);
- break;
- }
-
- }
-
- }
-
- }
-
- laebep_exit:
-
- return true;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : loading = chargement de symboles en cours. *
* format = format ELF à compléter. *
* local = s'apprête-t-on à constuire un symbole interne ? *
@@ -1449,3 +1188,300 @@ static bool apply_elf_relocations(GElfFormat *format, elf_rel *relocs, size_t re
return result;
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INSCRIPTION DE POINTS D'ENTREE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* vaddr = adresse virtuelle du symbole à insérer. *
+* routine = représentation de la fonction repérée. *
+* *
+* Description : Enregistre un point d'entrée au sein d'un binaire ELF. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool register_elf_entry_point(GElfFormat *format, virt_t vaddr, GBinRoutine *routine)
+{
+ bool result; /* Bilan à renvoyer */
+ virt_t final_vaddr; /* Adresse virtuelle retenue */
+ vmpa2t addr; /* Localisation d'une routine */
+ GBinFormat *base; /* Version basique du format */
+ GBinSymbol *symbol; /* Nouveau symbole construit */
+ mrange_t range; /* Couverture mémoire associée */
+
+ /* Localisation complète du symbole */
+
+ final_vaddr = format->ops.fix_virt(vaddr);
+
+ result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_vaddr, &addr);
+ if (!result) goto exit;
+
+ base = G_BIN_FORMAT(format);
+
+ /* Comptabilisation en tant que symbole */
+
+ if (g_binary_format_find_symbol_at(G_BIN_FORMAT(format), &addr, &symbol))
+ {
+ /**
+ * On ne relâche pas tout de suite le symbole trouvé, afin de le traiter
+ * en fin de fonction.
+ *
+ * Par contre, la routine proposée est détruite ici.
+ */
+
+ g_object_unref(G_OBJECT(routine));
+
+ }
+
+ else
+ {
+ symbol = G_BIN_SYMBOL(routine);
+ g_object_ref(G_OBJECT(symbol));
+
+ init_mrange(&range, &addr, 0);
+ g_binary_symbol_set_range(symbol, &range);
+
+ g_binary_format_add_symbol(base, symbol);
+
+ }
+
+ /* Marquage */
+
+ g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT);
+
+ g_object_unref(G_OBJECT(symbol));
+
+ /* Comptabilisation pour le désassemblage brut */
+ g_binary_format_register_code_point(base, vaddr, true);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à consulter. *
+* array = indications quant au tableau à charger. *
+* size = indications quant à la taille de ce tableau. *
+* prefix = désignation de base des éléments du tableau. *
+* *
+* Description : Désigne tous les points d'entrée par une étiquette dédiée. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool load_elf_entry_points_from_array(GElfFormat *format, const elf_dyn *array, const elf_dyn *size, const char *prefix)
+{
+ bool result; /* Bilan à renvoyer */
+ GBinFormat *base; /* Autre version du format */
+ GBinContent *content; /* Contenu binaire à lire */
+ vmpa2t pos; /* Tête de lecture courante */
+ phys_t length; /* Taille totale du contenu */
+ uint32_t virt_32; /* Adresse virtuelle sur 32b */
+ uint64_t virt_64; /* Adresse virtuelle sur 64b */
+ unsigned int i; /* Boucle de parcours */
+ bool status; /* Bilan d'une opération */
+ virt_t ep; /* Point d'entrée détecté */
+ char fullname[64]; /* Désignation humaine */
+ GBinRoutine *routine; /* Routine à associer à un pt. */
+
+ assert(sizeof(fullname) >= (strlen(prefix) + sizeof(XSTR(UINT64_MAX) + 1)));
+
+ base = G_BIN_FORMAT(format);
+ content = base->content;
+
+ result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format),
+ ELF_DYN(format, *array, d_un.d_val),
+ &pos);
+ if (!result) goto exit;
+
+ length = get_phy_addr(&pos) + ELF_DYN(format, *size, d_un.d_val);
+
+ for (i = 0; get_phy_addr(&pos) < length && result; i++)
+ {
+ /**
+ * Selon la libc d'Android (https://www.codeaurora.org/.../android/bionic/linker/README.TXT) :
+ *
+ * DT_INIT_ARRAY
+ * Points to an array of function addresses that must be
+ * called, in-order, to perform initialization. Some of
+ * the entries in the array can be 0 or -1, and should
+ * be ignored.
+ *
+ * On étend le principe aux sections DT_FINI_ARRAY et DT_PREINIT_ARRAY.
+ */
+
+ if (format->is_32b)
+ {
+ result = g_binary_content_read_u32(content, &pos, format->endian, &virt_32);
+
+ status = (virt_32 != 0x0 && virt_32 != 0xffffffff);
+ ep = virt_32;
+
+ }
+ else
+ {
+ result = g_binary_content_read_u64(content, &pos, format->endian, &virt_64);
+
+ status = (virt_64 != 0x0 && virt_64 != 0xffffffffffffffff);
+ ep = virt_64;
+
+ }
+
+ if (result && status)
+ {
+ snprintf(fullname, sizeof(fullname), "%s%u", prefix, i);
+
+ routine = g_binary_format_decode_routine(base, fullname);
+ result = register_elf_entry_point(format, ep, routine);
+
+ }
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à consulter. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Enumère tous les points d'entrée principaux d'un binaire ELF.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool load_all_elf_basic_entry_points(GElfFormat *format, GtkStatusStack *status)
+{
+ bool result; /* Bilan à renvoyer */
+ activity_id_t msg; /* Message de progression */
+ GBinFormat *base; /* Autre version du format */
+ virt_t ep; /* Point d'entrée détecté */
+ GBinRoutine *routine; /* Routine à associer à un pt. */
+ elf_phdr dynamic; /* En-tête de programme DYNAMIC*/
+ elf_dyn item_a; /* Premier élément DYNAMIC */
+ elf_dyn item_b; /* Second élément DYNAMIC */
+
+ result = true;
+
+ msg = gtk_status_stack_add_activity(status, _("Registering entry points..."), 0);
+
+ base = G_BIN_FORMAT(format);
+
+ /* Point d'entrée principal éventuel */
+
+ ep = ELF_HDR(format, format->header, e_entry);
+
+ if (ep != 0x0)
+ {
+ routine = g_binary_format_decode_routine(base, "entry_point");
+ result = register_elf_entry_point(format, ep, routine);
+ if (!result) goto exit;
+ }
+
+ /* Chargemet de l'en-tête de programme DYNAMIC */
+
+ if (!find_elf_dynamic_program_header(format, &dynamic))
+ goto exit;
+
+ /* Détection des constructeurs & destructeurs */
+
+ if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT, &item_a))
+ {
+ ep = ELF_DYN(format, item_a, d_un.d_ptr);
+
+ if (ep != 0x0)
+ {
+ routine = g_binary_format_decode_routine(base, "init_function");
+ result = register_elf_entry_point(format, ep, routine);
+ if (!result) goto exit;
+ }
+
+ }
+
+ if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI, &item_a))
+ {
+ ep = ELF_DYN(format, item_a, d_un.d_ptr);
+
+ if (ep != 0x0)
+ {
+ routine = g_binary_format_decode_routine(base, "termination_function");
+ result = register_elf_entry_point(format, ep, routine);
+ if (!result) goto exit;
+ }
+
+ }
+
+ if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAY, &item_a))
+ {
+ if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAYSZ, &item_b))
+ {
+ result = load_elf_entry_points_from_array(format, &item_a, &item_b, "init_array_function_");
+ if (!result) goto exit;
+ }
+
+ }
+
+ if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAY, &item_a))
+ {
+ if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAYSZ, &item_b))
+ {
+ result = load_elf_entry_points_from_array(format, &item_a, &item_b, "fini_array_function_");
+ if (!result) goto exit;
+ }
+
+ }
+
+ if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAY, &item_a))
+ {
+ if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAYSZ, &item_b))
+ {
+ result = load_elf_entry_points_from_array(format, &item_a, &item_b, "preinit_array_function_");
+ if (!result) goto exit;
+ }
+
+ }
+
+ /* Identification de l'entrée de la PLT */
+
+ if (resolve_plt_using_got(format, &ep))
+ {
+ if (ep != 0x0)
+ {
+ routine = g_binary_format_decode_routine(base, "plt_entry");
+ result = register_elf_entry_point(format, ep, routine);
+ }
+
+ }
+
+ exit:
+
+ gtk_status_stack_remove_activity(status, msg);
+
+ return result;
+
+}