From 4ff5e12f57a4c54e19a7ba987d243e5f86341aeb Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 12 Feb 2020 05:43:01 +0100 Subject: Refreshed the code registering Elf entry points. --- plugins/elf/dynamic.c | 8 +- plugins/elf/symbols.c | 590 ++++++++++++++++++++++++++------------------------ 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; + +} -- cgit v0.11.2-87-g4458