diff options
Diffstat (limited to 'src/format/elf/symbols.c')
-rw-r--r-- | src/format/elf/symbols.c | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/src/format/elf/symbols.c b/src/format/elf/symbols.c new file mode 100644 index 0000000..97b6ff2 --- /dev/null +++ b/src/format/elf/symbols.c @@ -0,0 +1,418 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * symbols.c - gestion des symboles d'un ELF + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "symbols.h" + + +#include <malloc.h> +#include <string.h> + + +#include "elf-int.h" +#include "helper_x86.h" +#include "section.h" +#include "../../panel/log.h" + + + + + +#define _(str) str + + + + +/* Récupère la désignation d'un symbole donné. */ +const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf_shdr *, off_t); + + + +/* -------------------------- DETAIL DES SYMBOLES INTERNES -------------------------- */ + + +/* Charge tous les symboles internes possibles. */ +static bool load_elf_internal_symbols(GElfFormat *); + + + +/* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */ + + +/* Retrouve un élément donné dans la section dynamique. */ +static bool find_elf_dynamic_item(const GElfFormat *, const elf_shdr *, int32_t, elf_dyn *); + +/* Charge tous les éléments dynamiques externes possibles. */ +static bool load_elf_external_symbols(GElfFormat *, const elf_shdr *); + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* * +* Description : Charge en mémoire la liste humaine des symboles. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_elf_symbols(GElfFormat *format) +{ + bool result; /* Bilan à retourner */ + elf_shdr *sections; /* Groupe de sections trouvées */ + size_t count; /* Quantité de données */ + + result = true; + + /* Symboles externes */ + + if (find_elf_sections_by_type(format, SHT_DYNAMIC, §ions, &count)) + { + log_variadic_message(LMT_INFO, _("Binary is dynamically linked")); + + result &= load_elf_external_symbols(format, §ions[0]); + + free(sections); + + } + else log_variadic_message(LMT_INFO, _("Binary is statically linked")); + + /* Symboles internes */ + result &= load_elf_internal_symbols(format); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* sym = section comprenant les symboles à venir lire. * +* str = section de chaînes de caractères pour les noms. * +* index = indice de l'entrée à venir lire. * +* * +* Description : Récupère la désignation d'un symbole donné. * +* * +* Retour : Nom du symbole trouvé, ou NULL si erreur ou non adapté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *get_elf_symbol_name(GElfFormat *format, const elf_shdr *sym, const elf_shdr *str, off_t index) +{ + const char *result; /* Résultat à retourner */ + off_t sym_start; /* Début de section */ + off_t sym_size; /* Taille de section */ + off_t str_start; /* Début de section */ + off_t str_size; /* Taille de section */ + off_t offset; /* Emplacement à venir lire */ + elf_sym symbol; /* Symbole aux infos visées */ + + result = NULL; + + get_elf_section_content(format, sym, &sym_start, &sym_size, NULL); + get_elf_section_content(format, str, &str_start, &str_size, NULL); + + offset = sym_start + index * ELF_SIZEOF_SYM(format); + if ((offset + ELF_SIZEOF_SYM(format)) > (sym_start + sym_size)) return NULL; + + if (read_elf_symbol(format, &offset, &symbol)) + result = extract_name_from_elf_string_section(format, str, ELF_SYM(format, symbol, st_name)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DETAIL DES SYMBOLES INTERNES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* * +* Description : Charge tous les symboles internes possibles. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool load_elf_internal_symbols(GElfFormat *format) +{ + bool result; /* Bilan à retourner */ + elf_shdr *symtabs; /* Groupe de sections trouvées */ + size_t count; /* Quantité de données */ + size_t i; /* Boucle de parcours */ + elf_shdr strtab; /* Section .strtab trouvée */ + bool has_strtab; /* Présence de cette section */ + off_t sym_start; /* Début de la zone à traiter */ + off_t sym_size; /* Taille de cette même zone */ + off_t iter; /* Boucle de parcours */ + const char *name; /* Nom du symbole trouvé */ + elf_sym sym; /* Symbole aux infos visées */ + GBinRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + result = true; + + if (find_elf_sections_by_type(format, SHT_SYMTAB, &symtabs, &count)) + for (i = 0; i < count && result; i++) + { + has_strtab = find_elf_section_by_index(format, ELF_SHDR(format, symtabs[i], sh_link), &strtab); + + get_elf_section_content(format, &symtabs[i], &sym_start, &sym_size, NULL); + + for (iter = sym_start; iter < (sym_start + sym_size); ) + { + result = read_elf_symbol(format, &iter, &sym); + if (!result) break; + + if (ELF_SYM(format, sym, st_value) == 0) continue; + + if (!(ELF_ST_TYPE(format, sym) == STT_FUNC)) continue; + + if (!has_strtab) name = NULL; + else name = get_elf_symbol_name(format, &symtabs[i], &strtab, + ((iter - sym_start) / ELF_SIZEOF_SYM(format)) - 1); + + if (name == NULL) + { + /* FIXME */ + name = "unknown"; + } + + /* Routine */ + + routine = g_binary_routine_new(); + + g_binary_routine_set_name(routine, strdup(name)); + g_binary_routine_set_address(routine, ELF_SYM(format, sym, st_value)); + g_binary_routine_set_size(routine, ELF_SYM(format, sym, st_size)); + + g_binary_format_add_routine(G_BIN_FORMAT(format), routine); + + /* Symbole uniquement */ + + symbol = g_binary_symbol_new(STP_FUNCTION, name, ELF_SYM(format, sym, st_value)); + + g_binary_symbol_attach_routine(symbol, routine); + + g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); + + } + + + } + + return true; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DETAIL DES SYMBOLES EXTERNES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* dynamic = section de type SHT_DYNAMIC. * +* type = sorte d'élément recherché. * +* item = élément retrouvé dans la section. [OUT] * +* * +* Description : Retrouve un élément donné dans la section dynamique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool find_elf_dynamic_item(const GElfFormat *format, const elf_shdr *section, int32_t type, elf_dyn *item) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + off_t pos; /* Position de lecture */ + off_t tmp; /* Position écrasable */ + int32_t tag32; /* Type de l'entrée (32 bits) */ + int64_t tag64; /* Type de l'entrée (64 bits) */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + for (pos = ELF_SHDR(format, *section, sh_offset); + pos < length/* FIXME !! + xploit */ && result; + pos += ELF_SIZEOF_DYN(format)) + { + tmp = pos; + + if (format->is_32b) + { + result = read_s32(&tag32, content, &tmp, length, format->endian); + if (tag32 == type) break; + } + else + { + result = read_s64(&tag64, content, &tmp, length, format->endian); + if (tag64 == type) break; + } + + } + + result &= (pos < length); + + if (result) + { + if (format->is_32b) + { + result = read_s32(&item->dyn32.d_tag, content, &pos, length, format->endian); + result &= read_s32(&item->dyn32.d_un.d_val, content, &pos, length, format->endian); + } + else + { + result = read_s64(&item->dyn64.d_tag, content, &pos, length, format->endian); + result &= read_s64(&item->dyn64.d_un.d_val, content, &pos, length, format->endian); + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* dynamic = section de type SHT_DYNAMIC. * +* * +* Description : Charge tous les éléments dynamiques externes possibles. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool load_elf_external_symbols(GElfFormat *format, const elf_shdr *section) +{ + bool result; /* Bilan à retourner */ + + elf_dyn item; /* Elément dynamique */ + elf_shdr relxxx; /* Section .rel.xxx trouvée */ + elf_shdr dynsym; /* Section .dynsym trouvée */ + elf_shdr dynstr; /* Section .dynstr trouvée */ + elf_shdr plt; /* Section .plt trouvée */ + + result = true; + + + + + + + /* Section .rel.plt */ + if (find_elf_dynamic_item(format, section, DT_JMPREL, &item)) + { + result &= find_elf_section_by_virtual_address(format, ELF_DYN(format, item, d_un.d_ptr), &relxxx); + + if (result) + result = find_elf_section_by_index(format, ELF_SHDR(format, relxxx, sh_link), &dynsym); + + if (result) + result = find_elf_section_by_index(format, ELF_SHDR(format, dynsym, sh_link), &dynstr); + + if (result) + switch (g_exe_format_get_target_machine(G_EXE_FORMAT(format))) + { + case FTM_386: + result = load_elf_x86_relocated_symbols(format, &relxxx, &dynsym, &dynstr); + break; + + default: + break; + + } + + } + + /* Entrées équivalentes dans le binaire */ + if (find_elf_dynamic_item(format, section, DT_SYMTAB, &item)) + { + result &= find_elf_section_by_virtual_address(format, ELF_DYN(format, item, d_un.d_ptr), &dynsym); + + if (result) + result = find_elf_section_by_index(format, ELF_SHDR(format, dynsym, sh_link), &dynstr); + + if (result) + switch (g_exe_format_get_target_machine(G_EXE_FORMAT(format))) + { + case FTM_MIPS: + //result = find_elf_mips_dynamic_symbols(format, &dynsym, &dynstr); + break; + + case FTM_386: + + if (find_elf_dynamic_item(format, section, DT_JMPREL, &item)) + { + result &= find_elf_section_by_virtual_address(format, ELF_DYN(format, item, d_un.d_ptr), &relxxx); + + if (result) + result = find_elf_section_by_index(format, ELF_SHDR(format, relxxx, sh_info), &plt); + + if (result) + result = find_elf_x86_dynamic_symbols(format, &plt); + + } + + break; + + default: + break; + + } + + } + + return result; + +} |