From bacf50f92fb497b201925b010cae78bf44584072 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 8 Feb 2020 01:21:49 +0100 Subject: Counted Elf symbols using the DT_GNU_HASH dynamic item. --- plugins/elf/elf_def.h | 2 + plugins/elf/symbols.c | 120 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 108 insertions(+), 14 deletions(-) diff --git a/plugins/elf/elf_def.h b/plugins/elf/elf_def.h index 355fa2f..915eb15 100644 --- a/plugins/elf/elf_def.h +++ b/plugins/elf/elf_def.h @@ -518,6 +518,8 @@ typedef union _elf_dyn #define DT_PREINIT_ARRAYSZ 33 /* Taille de DT_PREINIT_ARRAY */ #define DT_NUM 34 /* Nombre utilisé */ +#define DT_GNU_HASH 0x6ffffef5 /* Table d'empreintes version GNU */ + /* ---------------------------- SYMBOLES DE BINAIRES ELF ---------------------------- */ diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c index d90f4a5..26876bd 100644 --- a/plugins/elf/symbols.c +++ b/plugins/elf/symbols.c @@ -781,6 +781,13 @@ static bool count_elf_global_symbols(GElfFormat *format, GExeFormat *exec, uint3 elf_dyn hash; /* Table de type DT_HASH */ bool found; /* Détection validée */ vmpa2t addr; /* Position de départ brute */ + uint32_t n_buckets; /* Quantité de bacs en place */ + uint32_t sym_offset; /* Indice du premier symbole */ + uint32_t bloom_size; /* Taille du filtre Bloom */ + uint32_t last_symbol; /* Indice de dernier symbole */ + uint32_t i; /* Boucle de parcours */ + uint32_t start; /* Indice de départ d'un bac */ + uint32_t value; /* Valeur d'un maillon */ result = false; @@ -790,22 +797,107 @@ static bool count_elf_global_symbols(GElfFormat *format, GExeFormat *exec, uint3 * - http://www.gabriel.urdhr.fr/2015/09/28/elf-file-format/#symbol-tables * - http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash * + * Le fonctionnement global des chaînes est décrit ici : + * + * - https://flapenguin.me/2017/04/24/elf-lookup-dt-hash/ + * + * Celui des chaînes GNU fait l'objet de l'article suivant : + * + * - https://flapenguin.me/2017/05/10/elf-lookup-dt-gnu-hash/ + * */ + /* Méthode DT_HASH */ + found = find_elf_dynamic_item_by_type(format, DT_HASH, &hash); - if (!found) goto cegs_exit; - exec = G_EXE_FORMAT(format); + if (found) + { + result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, hash, d_un.d_ptr), &addr); + if (!result) goto exit; + + advance_vmpa(&addr, sizeof(uint32_t)); + + result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, count); + if (!result) goto exit; + + goto exit; + + } - result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, hash, d_un.d_ptr), &addr); - if (!result) goto cegs_exit; + /* Méthode DT_GNU_HASH */ - advance_vmpa(&addr, 4); + found = find_elf_dynamic_item_by_type(format, DT_GNU_HASH, &hash); - result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, count); - if (!result) goto cegs_exit; + if (found) + { + result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, hash, d_un.d_ptr), &addr); + if (!result) goto exit; + + result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &n_buckets); + if (!result) goto exit; + + result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &sym_offset); + if (!result) goto exit; + + result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &bloom_size); + if (!result) goto exit; + + /* Saut de bloom_shift */ + advance_vmpa(&addr, sizeof(uint32_t)); + + /* Saut de bloom[bloom_size] */ + if (format->is_32b) + advance_vmpa(&addr, bloom_size * sizeof(uint32_t)); + else + advance_vmpa(&addr, bloom_size * sizeof(uint64_t)); + + /* Localisation de la chaîne comportant le plus grand index */ + + last_symbol = 0; + + for (i = 0; i < n_buckets; i++) + { + result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &start); + if (!result) goto exit; + + if (last_symbol < start) + last_symbol = start; + + } + + if (last_symbol < sym_offset) + { + *count = sym_offset; + result = true; + } + + else + { + /* Parcours de la chaîne au plus haut potentiel */ + + advance_vmpa(&addr, (last_symbol - sym_offset) * sizeof(uint32_t)); + + while (true) + { + result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &value); + if (!result) goto exit; + + last_symbol++; + + if (value & 0x1) + break; + + } + + *count = last_symbol; + result = true; + + } + + } - cegs_exit: + exit: return result; @@ -851,23 +943,23 @@ static bool load_elf_global_symbols(GElfFormat *format, wgroup_id_t gid, GtkStat /* Récupération du début des chaînes de description */ result = find_elf_dynamic_item_by_type(format, DT_STRTAB, &strtab); - if (!result) goto lees_exit; + if (!result) goto exit; result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, strtab, d_un.d_ptr), &str_start); - if (!result) goto lees_exit; + if (!result) goto exit; /* Récupération du début des définitions de symboles */ result = find_elf_dynamic_item_by_type(format, DT_SYMTAB, &symtab); - if (!result) goto lees_exit; + if (!result) goto exit; result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, symtab, d_un.d_ptr), &sym_start); - if (!result) goto lees_exit; + if (!result) goto exit; /* Détermination du nombre d'éléments */ result = count_elf_global_symbols(format, exec, &count); - if (!result) goto lees_exit; + if (!result) goto exit; /* Chargement des symboles */ @@ -882,7 +974,7 @@ static bool load_elf_global_symbols(GElfFormat *format, wgroup_id_t gid, GtkStat gtk_status_stack_remove_activity(status, msg); - lees_exit: + exit: return result; -- cgit v0.11.2-87-g4458