diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2009-08-09 18:12:27 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2009-08-09 18:12:27 (GMT) |
commit | 5cd25c4adfe0426520a51a76de3f77c77cfa4b8e (patch) | |
tree | 396514971fb78e81b7bb55c9cd3331d87b45ca9a /src/format | |
parent | d02deb2425d6559c357bdd00e1c0fb05f35d5fc9 (diff) |
Reorganized the way formats are handled (Java and PE got disabled, Dwarf is empty).
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@105 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format')
32 files changed, 3512 insertions, 1521 deletions
diff --git a/src/format/Makefile.am b/src/format/Makefile.am index 92a774b..9bfdd92 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -2,17 +2,35 @@ noinst_LTLIBRARIES = libformat.la libformat_la_SOURCES = \ - exe_format.h exe_format.c \ - exe_format-int.h \ - dbg_format.h dbg_format.c \ - dbg_format-int.h + executable-int.h \ + executable.h executable.c \ + format-int.h \ + format.h format.c \ + part.h part.c \ + symbol.h symbol.c + +# libformat_la_SOURCES = \ +# exe_format.h exe_format.c \ +# exe_format-int.h \ +# executable-int.h \ +# executable.h executable.c \ +# format-int.h \ +# format.h format.c \ +# dbg_format.h dbg_format.c \ +# dbg_format-int.h \ +# part.h part.c libformat_la_LIBADD = \ dwarf/libformatdwarf.la \ elf/libformatelf.la \ - java/libformatjava.la \ - mangling/libformatmangling.la \ - pe/libformatpe.la + mangling/libformatmangling.la + +# libformat_la_LIBADD = \ +# dwarf/libformatdwarf.la \ +# elf/libformatelf.la \ +# java/libformatjava.la \ +# mangling/libformatmangling.la \ +# pe/libformatpe.la libformat_la_LDFLAGS = @@ -23,4 +41,5 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = dwarf elf java mangling pe +SUBDIRS = dwarf elf mangling +#SUBDIRS = dwarf elf java mangling pe diff --git a/src/format/dwarf/Makefile.am b/src/format/dwarf/Makefile.am index de1d228..6c6491a 100644 --- a/src/format/dwarf/Makefile.am +++ b/src/format/dwarf/Makefile.am @@ -2,11 +2,15 @@ noinst_LTLIBRARIES = libformatdwarf.la libformatdwarf_la_SOURCES = \ - abbrev.h abbrev.c \ - d_dwarf.h d_dwarf.c \ - dwarf_def.h \ - info.h info.c \ - utils.h utils.c + dwarf.h dwarf.c + +# libformatdwarf_la_SOURCES = \ +# abbrev.h abbrev.c \ +# dwarf.h dwarf.c \ +# d_dwarf.h d_dwarf.c \ +# dwarf_def.h \ +# info.h info.c \ +# utils.h utils.c libformatdwarf_la_LDFLAGS = $(LIBGTK_LIBS) diff --git a/src/format/dwarf/dwarf.c b/src/format/dwarf/dwarf.c new file mode 100644 index 0000000..dc47ed2 --- /dev/null +++ b/src/format/dwarf/dwarf.c @@ -0,0 +1,86 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dwarf.c - support du format Dwarf + * + * Copyright (C) 2009 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 "dwarf.h" + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : type = type de format recherché. * +* content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Indique si le format peut être pris en charge ici. * +* * +* Retour : true si la réponse est positive, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool dwarf_is_matching(FormatType type, const uint8_t *content, off_t length) +{ + bool result; /* Bilan à faire connaître */ + + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Prend en charge un nouveau format Dwarf. * +* * +* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinFormat *g_dwarf_format_new(const bin_t *content, off_t length) +{ + + + + return NULL; + + + +} diff --git a/src/format/dwarf/dwarf.h b/src/format/dwarf/dwarf.h new file mode 100644 index 0000000..35ab3ec --- /dev/null +++ b/src/format/dwarf/dwarf.h @@ -0,0 +1,40 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dwarf.h - prototypes pour le support du format Dwarf + * + * Copyright (C) 2009 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/>. + */ + + +#ifndef _FORMAT_DWARF_DWARF_H +#define _FORMAT_DWARF_DWARF_H + + +#include "../format.h" + + + +/* Indique si le format peut être pris en charge ici. */ +bool dwarf_is_matching(FormatType, const uint8_t *, off_t); + +/* Prend en charge un nouveau format Dwarf. */ +GBinFormat *g_dwarf_format_new(const bin_t *, off_t); + + + +#endif /* _FORMAT_DWARF_DWARF_H */ diff --git a/src/format/elf/Makefile.am b/src/format/elf/Makefile.am index 822ea44..1e18356 100644 --- a/src/format/elf/Makefile.am +++ b/src/format/elf/Makefile.am @@ -2,13 +2,15 @@ noinst_LTLIBRARIES = libformatelf.la libformatelf_la_SOURCES = \ - e_elf.h e_elf.c \ - elf-int.h \ - helper_mips.h helper_mips.c \ + elf-int.h elf-int.c \ + elf.h elf.c \ + elf_def.h \ helper_x86.h helper_x86.c \ section.h section.c \ strings.h strings.c \ - symbol.h symbol.c + symbols.h symbols.c + +# helper_mips.h helper_mips.c libformatelf_la_LDFLAGS = diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c deleted file mode 100644 index a91e279..0000000 --- a/src/format/elf/e_elf.c +++ /dev/null @@ -1,604 +0,0 @@ - -/* OpenIDA - Outil d'analyse de fichiers binaires - * e_elf.c - support du format 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 "e_elf.h" - - -#include <malloc.h> -#include <string.h> - - -#include "elf-int.h" -#include "section.h" -#include "strings.h" -#include "symbol.h" -#include "../../panel/log.h" -#include "../../common/extstr.h" - - - - -#define _(str) str - - - - -/* Indique le type d'architecture visée par le format. */ -FormatTargetMachine get_elf_target_machine(const elf_format *); - - - -/* Fournit l'adresse mémoire du point d'entrée du programme. */ -uint64_t get_elf_entry_point(const elf_format *); - - - - - -/* Récupère tous les éléments identifiées dans le binaire. */ -size_t get_elf_resolved_items(const elf_format *, char ***, ResolvedType **, uint64_t **); - - - -/****************************************************************************** -* * -* Paramètres : content = contenu binaire à parcourir. * -* length = taille du contenu en question. * -* * -* Description : Indique si le format peut être pris en charge ici. * -* * -* Retour : true si la réponse est positive, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool elf_is_matching(const uint8_t *content, off_t length) -{ - bool result; /* Bilan à faire connaître */ - - result = false; - - if (length >= 4) - result = (strncmp((const char *)content, "\x7f\x45\x4c\x46" /* .ELF */, 4) == 0); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : content = contenu binaire à parcourir. * -* length = taille du contenu en question. * -* * -* Description : Prend en charge un nouvel ELF. * -* * -* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* -* * -* Remarques : - * -* * -******************************************************************************/ - -elf_format *load_elf(const uint8_t *content, off_t length) -{ - elf_format *result; /* Structure à retourner */ - bool test; /* Bilan d'une initialisation */ - - - Elf32_Half i; - Elf32_Phdr phdr; - - size_t count; - - - result = (elf_format *)calloc(1, sizeof(elf_format)); - - EXE_FORMAT(result)->content = content; - EXE_FORMAT(result)->length = length; - - EXE_FORMAT(result)->get_target_machine = (get_target_machine_fc)get_elf_target_machine; - EXE_FORMAT(result)->get_entry_point = (get_entry_point_fc)get_elf_entry_point; - EXE_FORMAT(result)->get_def_parts = (get_def_parts_fc)get_elf_default_code_parts; - EXE_FORMAT(result)->find_section = (find_section_fc)find_elf_section_content_by_name; - EXE_FORMAT(result)->get_symbols = (get_symbols_fc)get_elf_symbols; - EXE_FORMAT(result)->get_resolved = (get_resolved_fc)get_elf_resolved_items; - EXE_FORMAT(result)->resolve_symbol = (resolve_symbol_fc)resolve_elf_symbol; - EXE_FORMAT(result)->get_all_routines = (get_all_routines_fc)get_all_elf_routines; - - memcpy(&result->header, content, sizeof(Elf32_Ehdr)); - - - /* TODO : endian */ - - - /* Vérification des tailles d'entrée de table */ - switch (result->header.e_ident[EI_CLASS]) - { - case ELFCLASS32: - - if (result->header.e_phentsize != sizeof(Elf32_Phdr)) - { - log_variadic_message(LMT_BAD_BINARY, _("Corrupted program header size (%hu); fixed !"), - result->header.e_phentsize); - result->header.e_phentsize = sizeof(Elf32_Phdr); - } - - if (result->header.e_shentsize != sizeof(Elf32_Shdr)) - { - log_variadic_message(LMT_BAD_BINARY, _("Corrupted section header size (%hu); fixed !"), - result->header.e_shentsize); - result->header.e_shentsize = sizeof(Elf32_Shdr); - } - - break; - - case ELFCLASS64: - - if (result->header.e_phentsize != sizeof(Elf64_Phdr)) - { - log_variadic_message(LMT_BAD_BINARY, _("Corrupted program header size (%hu); fixed !"), - result->header.e_phentsize); - result->header.e_phentsize = sizeof(Elf64_Phdr); - } - - if (result->header.e_shentsize != sizeof(Elf64_Shdr)) - { - log_variadic_message(LMT_BAD_BINARY, _("Corrupted section header size (%hu); fixed !"), - result->header.e_shentsize); - result->header.e_shentsize = sizeof(Elf64_Shdr); - } - - break; - - default: - log_variadic_message(LMT_BAD_BINARY, ("Invalid ELF class '%hhu'"), - result->header.e_ident[EI_CLASS]); - break; - - } - - - /* FIXME : à améliorer */ - if ((result->header.e_shnum * result->header.e_shentsize) >= length) - { - log_variadic_message(LMT_BAD_BINARY, ("Suspicious section table (bigger than the binary !) ; reset !")); - result->header.e_shnum = 0; - } - - - result->is_32b = (result->header.e_ident[EI_CLASS] == ELFCLASS32); - - - for (i = 0; i < result->header.e_phnum; i++) - { - - memcpy(&phdr, &content[result->header.e_phoff + i * result->header.e_phentsize], result->header.e_phentsize); - - - printf(" seg [0x%08x] :: %d -> %d\n", phdr.p_type, phdr.p_offset, phdr.p_filesz); - - - } - - - test = read_elf_section_names(result); - - printf("section names ok ? %d\n", test); - - test = find_all_elf_strings(result); - - printf("strings ok ? %d\n", test); - - test = load_elf_symbols(result); - - printf("symbols ok ? %d\n", test); - - - - return result; - - lelf: - - /* TODO */ - - return NULL; - -} - - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* * -* Description : Indique le type d'architecture visée par le format. * -* * -* Retour : Identifiant de l'architecture ciblée par le format. * -* * -* Remarques : - * -* * -******************************************************************************/ - -FormatTargetMachine get_elf_target_machine(const elf_format *format) -{ - FormatTargetMachine result; /* Identifiant à retourner */ - - switch (format->header.e_machine) - { - case EM_MIPS: - result = FTM_MIPS; - break; - - case EM_386: - result = FTM_386; - break; - - default: - /* FIXME */ - break; - - } - - return result; - -} - - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* * -* Description : Fournit l'adresse mémoire du point d'entrée du programme. * -* * -* Retour : Adresse de mémoire. * -* * -* Remarques : - * -* * -******************************************************************************/ - -uint64_t get_elf_entry_point(const elf_format *format) -{ - return format->header.e_entry; - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* count = quantité de zones listées. [OUT] * -* * -* Description : Fournit les références aux zones de code à analyser. * -* * -* Retour : Zones de code à analyser. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count) -{ - bin_part **result; /* Tableau à retourner */ - bin_part *part; /* Partie à intégrer à la liste*/ - off_t offset; /* Position physique */ - off_t size; /* Taille de la partie */ - uint64_t voffset; /* Adresse virtuelle éventuelle*/ - int i; /* Boucle de parcours */ - Elf_Shdr shdr; /* En-tête de section ELF */ - Elf_Phdr phdr; /* En-tête de programme ELF */ - - result = NULL; - *count = 0; - - if (format->sec_size > 0) - { - if (find_elf_section_content_by_name(format, ".plt", &offset, &size, &voffset)) - { - part = create_bin_part(); - - set_bin_part_name(part, ".plt"); - set_bin_part_values(part, offset, size, voffset); - - result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); - result[*count - 1] = part; - - } - - if (find_elf_section_content_by_name(format, ".MIPS.stubs", &offset, &size, &voffset)) - { - part = create_bin_part(); - - set_bin_part_name(part, ".MIPS.stubs"); - set_bin_part_values(part, offset, size, voffset); - - result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); - result[*count - 1] = part; - - } - - if (find_elf_section_content_by_name(format, ".init", &offset, &size, &voffset)) - { - part = create_bin_part(); - - set_bin_part_name(part, ".init"); - set_bin_part_values(part, offset, size, voffset); - - result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); - result[*count - 1] = part; - - } - - if (find_elf_section_content_by_name(format, ".text", &offset, &size, &voffset)) - { - part = create_bin_part(); - - set_bin_part_name(part, ".text"); - set_bin_part_values(part, offset, size, voffset); - - result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); - result[*count - 1] = part; - - } - - if (find_elf_section_content_by_name(format, ".fini", &offset, &size, &voffset)) - { - part = create_bin_part(); - - set_bin_part_name(part, ".fini"); - set_bin_part_values(part, offset, size, voffset); - - result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); - result[*count - 1] = part; - - } - - } - - /* Si aucune section n'a été trouvée... */ - - if (*count == 0) - for (i = 0; i < format->header.e_shnum; i++) - { - offset = format->header.e_shoff + format->header.e_shentsize * i; - if ((offset + format->header.e_shentsize) >= EXE_FORMAT(format)->length) continue; - - memcpy(&shdr, &EXE_FORMAT(format)->content[offset], format->header.e_shentsize); - - if (ELF_SHDR(format, &shdr, sh_flags) & SHF_EXECINSTR) - { - part = create_bin_part(); - - /* TODO : nom */ - - set_bin_part_values(part, ELF_SHDR(format, &shdr, sh_offset), - ELF_SHDR(format, &shdr, sh_size), - ELF_SHDR(format, &shdr, sh_addr)); - - result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); - result[*count - 1] = part; - - } - - } - - /* En désespoir de cause, on se rabbat sur les parties de programme directement */ - - if (*count == 0) - for (i = 0; i < format->header.e_phnum; i++) - { - offset = format->header.e_phoff + format->header.e_phentsize * i; - if ((offset + format->header.e_phentsize) >= EXE_FORMAT(format)->length) continue; - - memcpy(&phdr, &EXE_FORMAT(format)->content[offset], format->header.e_phentsize); - - if (ELF_PHDR(format, &phdr, p_flags) & PF_X) - { - part = create_bin_part(); - - /* TODO : nom */ - - set_bin_part_values(part, ELF_PHDR(format, &phdr, p_offset), - ELF_PHDR(format, &phdr, p_filesz), - ELF_PHDR(format, &phdr, p_vaddr)); - - result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); - result[*count - 1] = part; - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* labels = liste des commentaires à insérer. [OUT] * -* types = type des symboles listés. [OUT] * -* offsets = liste des indices des commentaires. [OUT] * -* * -* Description : Récupère tous les symboles présents dans le contenu binaire. * -* * -* Retour : Nombre d'éléments mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t get_elf_symbols(const elf_format *format, char ***labels, SymbolType **types, uint64_t **offsets) -{ - size_t result; /* Quantité à retourner */ - size_t i; /* Boucle de parcours */ - - result = format->sym_count; - - *labels = (char **)calloc(result, sizeof(char *)); - *types = (SymbolType *)calloc(result, sizeof(SymbolType)); - *offsets = (uint64_t *)calloc(result, sizeof(uint64_t)); - - for (i = 0; i < format->sym_count; i++) - { - (*labels)[i] = strdup(format->symbols[i].name); - (*types)[i] = STP_SECTION; - (*offsets)[i] = format->symbols[i].address; - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* labels = liste des commentaires à insérer. [OUT] * -* types = type des symboles listés. [OUT] * -* offsets = liste des indices des commentaires. [OUT] * -* * -* Description : Récupère tous les éléments identifiées dans le binaire. * -* * -* Retour : Nombre d'éléments mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t get_elf_resolved_items(const elf_format *format, char ***labels, ResolvedType **types, uint64_t **offsets) -{ - size_t result; /* Quantité à retourner */ - size_t i; /* Boucle de parcours */ - size_t start; /* Point de départ du tour */ - - result = format->sym_count + format->str_count; - - *labels = (char **)calloc(result, sizeof(char *)); - *types = (SymbolType *)calloc(result, sizeof(SymbolType)); - *offsets = (uint64_t *)calloc(result, sizeof(uint64_t)); - - for (i = 0; i < format->sym_count; i++) - { - (*labels)[i] = strdup(format->symbols[i].name); - (*types)[i] = RTP_SECTION; - (*offsets)[i] = format->symbols[i].address; - } - - start = format->sym_count; - - for (i = 0; i < format->str_count; i++) - { - (*labels)[start + i] = strndup(format->strings[i].value, format->strings[i].len); - (*types)[start + i] = RTP_STRING; - (*offsets)[start + i] = format->strings[i].address; - - (*labels)[start + i] = escape_crlf((*labels)[start + i]); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* label = étiquette du symbole si trouvé. [OUT] * -* type = type du symbole trouvé. [OUT] * -* address = adresse à cibler, puis décallage final. [OUT] * -* * -* Description : Recherche le symbole correspondant à une adresse. * -* * -* Retour : true si l'opération a été un succès, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool resolve_elf_symbol(const elf_format *format, char **label, SymbolType *type, vmpa_t *address) -{ - bool result; /* Bilan à retourner */ - size_t best_index; /* Meilleur symbole trouvé */ - vmpa_t best_addr; /* Meilleure adresse trouvée */ - vmpa_t addr; /* Adresse de routine */ - size_t i; /* Boucle de parcours */ - - if (resolve_elf_strings(format, label, address)) - { - *type = STP_STRING; - return true; - } - - best_index = format->routines_count; /* Pour GCC */ - best_addr = UINT64_MAX; /* FIXME */ - - for (i = 0; i < format->routines_count; i++) - { - addr = g_binary_routine_get_address(format->routines[i]); - - if (addr <= *address && (*address - addr) < best_addr) - { - best_index = i; - best_addr = *address - addr; - } - - } - - result = (best_addr != UINT64_MAX); - - if (result) - { - *label = strdup(g_binary_routine_get_name(format->routines[best_index])); - *type = STP_SECTION; - *address -= g_binary_routine_get_address(format->routines[best_index]); - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* count = taille du tableau créé. [OUT] * -* * -* Description : Fournit le prototype de toutes les routines détectées. * -* * -* Retour : Tableau créé ou NULL si aucun symbole de routine trouvé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinRoutine **get_all_elf_routines(const elf_format *format, size_t *count) -{ - *count = format->routines_count; - - return format->routines; - -} diff --git a/src/format/elf/e_elf.h b/src/format/elf/e_elf.h deleted file mode 100644 index b8abe05..0000000 --- a/src/format/elf/e_elf.h +++ /dev/null @@ -1,63 +0,0 @@ - -/* OpenIDA - Outil d'analyse de fichiers binaires - * e_elf.h - prototypes pour le support du format 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/>. - */ - - -#ifndef _FORMAT_ELF_ELF_H -#define _FORMAT_ELF_ELF_H - - -#include <stdbool.h> -#include <stdint.h> -#include <sys/types.h> - - -#include "../exe_format.h" - - - -/* Description du format ELF */ -typedef struct _elf_format elf_format; - - -/* Indique si le format peut être pris en charge ici. */ -bool elf_is_matching(const uint8_t *, off_t); - -/* Prend en charge un nouvel ELF. */ -elf_format *load_elf(const uint8_t *, off_t); - - - -/* Fournit les références aux zones de code à analyser. */ -bin_part **get_elf_default_code_parts(const elf_format *, size_t *); - -/* Récupère tous les symboles présents dans le contenu binaire. */ -size_t get_elf_symbols(const elf_format *, char ***, SymbolType **, uint64_t **); - -/* Recherche le symbole correspondant à une adresse. */ -bool resolve_elf_symbol(const elf_format *, char **, SymbolType *, vmpa_t *); - -/* Fournit le prototype de toutes les routines détectées. */ -GBinRoutine **get_all_elf_routines(const elf_format *, size_t *); - - - -#endif /* _FORMAT_ELF_ELF_H */ diff --git a/src/format/elf/elf-int.c b/src/format/elf/elf-int.c new file mode 100644 index 0000000..69363d2 --- /dev/null +++ b/src/format/elf/elf-int.c @@ -0,0 +1,227 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * elf-int.c - structures internes du format ELF + * + * Copyright (C) 2009 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 "elf-int.h" + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* header = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une en-tête de programme ELF. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_elf_program_header(const GElfFormat *format, off_t *pos, elf_phdr *header) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + if (format->is_32b) + { + result = read_u32(&header->phdr32.p_type, content, pos, length, format->endian); + result &= read_u32(&header->phdr32.p_offset, content, pos, length, format->endian); + result &= read_u32(&header->phdr32.p_vaddr, content, pos, length, format->endian); + result &= read_u32(&header->phdr32.p_paddr, content, pos, length, format->endian); + result &= read_u32(&header->phdr32.p_filesz, content, pos, length, format->endian); + result &= read_u32(&header->phdr32.p_memsz, content, pos, length, format->endian); + result &= read_u32(&header->phdr32.p_flags, content, pos, length, format->endian); + result &= read_u32(&header->phdr32.p_align, content, pos, length, format->endian); + } + else + { + result = read_u32(&header->phdr64.p_type, content, pos, length, format->endian); + result &= read_u32(&header->phdr64.p_flags, content, pos, length, format->endian); + result &= read_u64(&header->phdr64.p_offset, content, pos, length, format->endian); + result &= read_u64(&header->phdr64.p_vaddr, content, pos, length, format->endian); + result &= read_u64(&header->phdr64.p_paddr, content, pos, length, format->endian); + result &= read_u64(&header->phdr64.p_filesz, content, pos, length, format->endian); + result &= read_u64(&header->phdr64.p_memsz, content, pos, length, format->endian); + result &= read_u64(&header->phdr64.p_align, content, pos, length, format->endian); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de la tête de lecture. * +* section = section lue. [OUT] * +* * +* Description : Procède à la lecture d'une en-tête de section ELF. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_elf_section_header(const GElfFormat *format, off_t pos, elf_shdr *section) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + elf32_shdr *shdr32; /* Version 32 bits */ + elf64_shdr *shdr64; /* Version 32 bits */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + if (format->is_32b) + { + shdr32 = §ion->shdr32; + + result = read_u32(&shdr32->sh_name, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_type, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_flags, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_addr, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_offset, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_size, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_link, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_info, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_addralign, content, &pos, length, format->endian); + result &= read_u32(&shdr32->sh_entsize, content, &pos, length, format->endian); + + } + else + { + shdr64 = §ion->shdr64; + + result = read_u32(&shdr64->sh_name, content, &pos, length, format->endian); + result &= read_u32(&shdr64->sh_type, content, &pos, length, format->endian); + result &= read_u64(&shdr64->sh_flags, content, &pos, length, format->endian); + result &= read_u64(&shdr64->sh_addr, content, &pos, length, format->endian); + result &= read_u64(&shdr64->sh_offset, content, &pos, length, format->endian); + result &= read_u64(&shdr64->sh_size, content, &pos, length, format->endian); + result &= read_u32(&shdr64->sh_link, content, &pos, length, format->endian); + result &= read_u32(&shdr64->sh_info, content, &pos, length, format->endian); + result &= read_u64(&shdr64->sh_addralign, content, &pos, length, format->endian); + result &= read_u64(&shdr64->sh_entsize, content, &pos, length, format->endian); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* sym = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un symbole ELF. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_elf_symbol(const GElfFormat *format, off_t *pos, elf_sym *sym) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + if (format->is_32b) + { + result = read_u32(&sym->sym32.st_name, content, pos, length, format->endian); + result &= read_u32(&sym->sym32.st_value, content, pos, length, format->endian); + result &= read_u32(&sym->sym32.st_size, content, pos, length, format->endian); + result &= read_u8(&sym->sym32.st_info, content, pos, length, format->endian); + result &= read_u8(&sym->sym32.st_other, content, pos, length, format->endian); + result &= read_u16(&sym->sym32.st_shndx, content, pos, length, format->endian); + } + else + { + result = read_u32(&sym->sym64.st_name, content, pos, length, format->endian); + result &= read_u8(&sym->sym64.st_info, content, pos, length, format->endian); + result &= read_u8(&sym->sym64.st_other, content, pos, length, format->endian); + result &= read_u16(&sym->sym64.st_shndx, content, pos, length, format->endian); + result &= read_u64(&sym->sym64.st_value, content, pos, length, format->endian); + result &= read_u64(&sym->sym64.st_size, content, pos, length, format->endian); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* reloc = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une relocalisation ELF. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_elf_relocation(const GElfFormat *format, off_t *pos, elf_rel *reloc) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + if (format->is_32b) + { + result = read_u32(&reloc->rel32.r_offset, content, pos, length, format->endian); + result &= read_u32(&reloc->rel32.r_info, content, pos, length, format->endian); + } + else + { + result = read_u64(&reloc->rel64.r_offset, content, pos, length, format->endian); + result &= read_u64(&reloc->rel64.r_info, content, pos, length, format->endian); + } + + return result; + +} diff --git a/src/format/elf/elf-int.h b/src/format/elf/elf-int.h index 4339475..f7fd804 100644 --- a/src/format/elf/elf-int.h +++ b/src/format/elf/elf-int.h @@ -25,115 +25,44 @@ #define _FORMAT_ELF_ELF_INT_H +#include "elf.h" +#include "elf_def.h" +#include "../executable-int.h" +#include "../../common/endianness.h" -#include <elf.h> -#include <sys/types.h> -#include "../exe_format-int.h" - - - -/* Chaîne de caractères présente */ -typedef struct _elf_string -{ - const char *value; /* Valeur humainement lisible */ - size_t len; /* Longueur de la chaîne */ - vmpa_t address; /* Adresse de localisation */ - -} elf_string; - -/* Symbole trouvé */ -typedef struct _elf_symbol -{ - const char *name; /* Désignation du symbole */ - uint64_t address; /* Adresse du symbole */ - off_t size; /* Taille du code associé */ - -} elf_symbol; - -/* Relocalisation trouvée */ -typedef struct _elf_relocation +/* Format d'exécutable générique (instance) */ +struct _GElfFormat { - const char *name; /* Désignation du symbole */ - vmpa_t address; /* Adresse du symbole */ + GExeFormat parent; /* A laisser en premier */ -} elf_relocation; - - - -/* Description du format ELF */ -struct _elf_format -{ - exe_format dummy; /* A laisser en premier */ - - Elf32_Ehdr header; /* En-tête du format */ + elf_header header; /* En-tête du format */ bool is_32b; /* Format du binaire */ - - char *sec_names; /* Noms des sections */ - size_t sec_size; /* Taille de ces définitions */ - - elf_relocation *relocations; /* Liste des relocalisations */ - size_t rel_count; /* Taille de cette liste */ - - GBinRoutine **routines; /* Liste des routines trouvées */ - size_t routines_count; /* Nombre de ces routines */ - - elf_symbol *symbols; /* Liste des symboles */ - size_t sym_count; /* Taille de cette liste */ - - elf_string *strings; /* Liste des chaînes */ - size_t str_count; /* Taille de cette liste */ + SourceEndian endian; /* Boutisme du format */ }; - - - -/* En-tête de programme ELF */ -typedef union _Elf_Phdr -{ - Elf32_Phdr header32; /* Version 32 bits */ - Elf64_Phdr header64; /* Version 64 bits */ - -} Elf_Phdr; - -#define ELF_PHDR(fmt, hdr, fld) (fmt->is_32b ? (hdr)->header32.fld : (hdr)->header64.fld) - - -/* Entrée de la table de relocalisation */ - -typedef union _Elf_Rel +/* Format d'exécutable générique (classe) */ +struct _GElfFormatClass { - Elf32_Rel rel32; /* Version 32 bits */ - Elf64_Rel rel64; /* Version 64 bits */ - -} Elf_Rel; - -#define ELF_SIZEOF_REL(fmt) (fmt->is_32b ? sizeof(Elf32_Rel) : sizeof(Elf64_Rel)) - -#define ELF_REL(fmt, rl, fld) (fmt->is_32b ? rl.rel32.fld : rl.rel64.fld) - -#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM(rl.rel32.r_info) : ELF64_R_SYM(rl.rel64.r_info)) -#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE(rl.rel32.r_info) : ELF64_R_TYPE(rl.rel64.r_info)) + GExeFormatClass parent; /* A laisser en premier */ +}; -/* Information sur un symbole */ - -typedef union _Elf_Sym -{ - Elf32_Sym sym32; /* Version 32 bits */ - Elf64_Sym sym64; /* Version 64 bits */ - -} Elf_Sym; -#define ELF_SIZEOF_SYM(fmt) (fmt->is_32b ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym)) -#define ELF_SYM(fmt, sb, fld) (fmt->is_32b ? sb.sym32.fld : sb.sym64.fld) +/* Procède à la lecture d'une en-tête de programme ELF. */ +bool read_elf_program_header(const GElfFormat *, off_t *, elf_phdr *); +/* Procède à la lecture d'une en-tête de section ELF. */ +bool read_elf_section_header(const GElfFormat *, off_t, elf_shdr *); -#define ELF_ST_TYPE ELF32_ST_TYPE +/* Procède à la lecture d'un symbole ELF. */ +bool read_elf_symbol(const GElfFormat *, off_t *, elf_sym *); +/* Procède à la lecture d'une relocalisation ELF. */ +bool read_elf_relocation(const GElfFormat *, off_t *, elf_rel *); diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c new file mode 100644 index 0000000..d24a89e --- /dev/null +++ b/src/format/elf/elf.c @@ -0,0 +1,444 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * elf.c - support du format ELF + * + * Copyright (C) 2009 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 "elf.h" + + +#include <malloc.h> +#include <string.h> + + +#include "elf-int.h" +#include "section.h" +#include "strings.h" +#include "symbols.h" +#include "../../panel/log.h" + + + + +#ifndef _ +# define _(str) (str) +#endif + + + + +/* Initialise la classe des formats d'exécutables ELF. */ +static void g_elf_format_class_init(GElfFormatClass *); + +/* Initialise une instance de format d'exécutable ELF. */ +static void g_elf_format_init(GElfFormat *); + +/* Procède à la lecture de l'en-tête d'un contenu binaire. */ +static bool read_elf_header(const bin_t *, off_t, elf_header *, bool *, SourceEndian *); + +/* Indique le type d'architecture visée par le format. */ +static FormatTargetMachine g_elf_format_get_target_machine(const GElfFormat *); + +/* Fournit l'adresse mémoire du point d'entrée du programme. */ +static vmpa_t g_elf_format_get_entry_point(const GElfFormat *); + +/* Fournit les références aux zones binaires à analyser. */ +static GBinPart **g_elf_format_get_parts(const GElfFormat *, size_t *); + + + +/****************************************************************************** +* * +* Paramètres : type = type de format recherché. * +* content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Indique si le format peut être pris en charge ici. * +* * +* Retour : true si la réponse est positive, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool elf_is_matching(FormatType type, const bin_t *content, off_t length) +{ + bool result; /* Bilan à faire connaître */ + + result = false; + + if (length >= 4) + result = (memcmp(content, "\x7f\x45\x4c\x46" /* .ELF */, 4) == 0); + + return result; + +} + + +/* Indique le type défini pour un format d'exécutable ELF. */ +G_DEFINE_TYPE(GElfFormat, g_elf_format, G_TYPE_EXE_FORMAT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des formats d'exécutables ELF. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_elf_format_class_init(GElfFormatClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance à initialiser. * +* * +* Description : Initialise une instance de format d'exécutable ELF. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_elf_format_init(GElfFormat *format) +{ + GExeFormat *exe_format; + + exe_format = G_EXE_FORMAT(format); + + exe_format->get_machine = (get_target_machine_fc)g_elf_format_get_target_machine; + exe_format->get_entry_point = (get_entry_point_fc)g_elf_format_get_entry_point; + exe_format->get_parts = (get_parts_fc)g_elf_format_get_parts; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* header = en-tête à déterminer. [OUT] * +* is_32b = indique si le format est en 32 ou 64 bits. [OUT] * +* endian = boutisme reconnu dans le format. [OUT] * +* * +* Description : Procède à la lecture de l'en-tête d'un contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool read_elf_header(const bin_t *content, off_t length, elf_header *header, bool *is_32b, SourceEndian *endian) +{ + bool result; /* Bilan à retourner */ + off_t pos; /* Position de lecture */ + + result = (length >= EI_NIDENT); + + pos = 0; + + if (result) + { + memcpy(header->e_ident, content, EI_NIDENT); + pos += EI_NIDENT; + } + + /* Détermination de l'espace d'adressage */ + if (result) + switch (header->e_ident[EI_CLASS]) + { + case ELFCLASS32: + *is_32b = true; + break; + case ELFDATA2MSB: + *is_32b = false; + break; + default: + result = false; + break; + } + + /* Détermination du boutisme */ + if (result) + switch (header->e_ident[EI_DATA]) + { + case ELFDATA2LSB: + *endian = SRE_LITTLE; + break; + case ELFDATA2MSB: + *endian = SRE_BIG; + break; + default: + result = false; + break; + } + + if (result) + result = read_u16(&header->e_type, content, &pos, length, *endian); + + if (result) + result = read_u16(&header->e_machine, content, &pos, length, *endian); + + if (result) + result = read_u32(&header->e_version, content, &pos, length, *endian); + + if (result) + { + if (*is_32b) + result = read_u32(&header->e_entry.addr32, content, &pos, length, *endian); + else + result = read_u64(&header->e_entry.addr64, content, &pos, length, *endian); + } + + if (result) + { + if (*is_32b) + result = read_u32(&header->e_phoff.off32, content, &pos, length, *endian); + else + result = read_u64(&header->e_phoff.off64, content, &pos, length, *endian); + } + + if (result) + { + if (*is_32b) + result = read_u32(&header->e_shoff.off32, content, &pos, length, *endian); + else + result = read_u64(&header->e_shoff.off64, content, &pos, length, *endian); + } + + if (result) + result = read_u32(&header->e_flags, content, &pos, length, *endian); + + if (result) + result = read_u16(&header->e_ehsize, content, &pos, length, *endian); + + if (result) + result = read_u16(&header->e_phentsize, content, &pos, length, *endian); + + if (result) + result = read_u16(&header->e_phnum, content, &pos, length, *endian); + + if (result) + result = read_u16(&header->e_shentsize, content, &pos, length, *endian); + + if (result) + result = read_u16(&header->e_shnum, content, &pos, length, *endian); + + if (result) + result = read_u16(&header->e_shstrndx, content, &pos, length, *endian); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Prend en charge un nouveau format ELF. * +* * +* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinFormat *g_elf_format_new(const bin_t *content, off_t length) +{ + GElfFormat *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ELF_FORMAT, NULL); + + g_binary_format_set_content(G_BIN_FORMAT(result), content, length); + + if (!read_elf_header(content, length, &result->header, &result->is_32b, &result->endian)) + { + /* TODO */ + return NULL; + } + + + /* Vérification des tailles d'entrée de table */ + + if (result->header.e_phentsize != ELF_SIZEOF_PHDR(result)) + { + log_variadic_message(LMT_BAD_BINARY, _("Corrupted program header size (%hu); fixed !"), + result->header.e_phentsize); + result->header.e_phentsize = ELF_SIZEOF_PHDR(result); + } + + if (result->header.e_shentsize != ELF_SIZEOF_SHDR(result)) + { + log_variadic_message(LMT_BAD_BINARY, _("Corrupted section header size (%hu); fixed !"), + result->header.e_shentsize); + result->header.e_shentsize = ELF_SIZEOF_SHDR(result); + } + + /* FIXME : à améliorer */ + if ((result->header.e_shnum * result->header.e_shentsize) >= length) + { + log_variadic_message(LMT_BAD_BINARY, ("Suspicious section table (bigger than the binary !) ; reset !")); + result->header.e_shnum = 0; + } + + + + + if (!load_elf_symbols(result)) + { + /* TODO */ + return NULL; + } + + + if (!find_all_elf_strings(result)) + { + /* TODO */ + return NULL; + } + + + + return G_BIN_FORMAT(result); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Indique le type d'architecture visée par le format. * +* * +* Retour : Identifiant de l'architecture ciblée par le format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static FormatTargetMachine g_elf_format_get_target_machine(const GElfFormat *format) +{ + FormatTargetMachine result; /* Identifiant à retourner */ + + switch (format->header.e_machine) + { + case EM_MIPS: + result = FTM_MIPS; + break; + + case EM_386: + result = FTM_386; + break; + + case EM_NONE: + default: + result = FTM_NONE; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Fournit l'adresse mémoire du point d'entrée du programme. * +* * +* Retour : Adresse de mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static vmpa_t g_elf_format_get_entry_point(const GElfFormat *format) +{ + return (format->is_32b ? format->header.e_entry.addr32 : format->header.e_entry.addr64); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = quantité de zones listées. [OUT] * +* * +* Description : Fournit les références aux zones binaires à analyser. * +* * +* Retour : Zones binaires à analyser. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBinPart **g_elf_format_get_parts(const GElfFormat *format, size_t *count) +{ + GBinPart **result; /* Tableau à retourner */ + uint16_t i; /* Boucle de parcours */ + elf_shdr section; /* En-tête de section ELF */ + GBinPart *part; /* Partie à intégrer à la liste*/ + + result = NULL; + *count = 0; + + /* Première tentative : les sections */ + + for (i = 0; i < format->header.e_shnum; i++) + { + if (!find_elf_section_by_index(format, i, §ion)) + continue; + + + if (ELF_SHDR(format, section, sh_flags) & SHF_EXECINSTR) + { + part = g_binary_part_new(); + + /* TODO : nom, droits/type */ + + g_binary_part_set_values(part, + ELF_SHDR(format, section, sh_offset), + ELF_SHDR(format, section, sh_size), + ELF_SHDR(format, section, sh_addr)); + + result = (GBinPart **)realloc(result, ++(*count) * sizeof(GBinPart *)); + result[*count - 1] = part; + + } + + } + + return result; + +} diff --git a/src/format/elf/elf.h b/src/format/elf/elf.h new file mode 100644 index 0000000..e8ad70b --- /dev/null +++ b/src/format/elf/elf.h @@ -0,0 +1,62 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * elf.h - prototypes pour le support du format ELF + * + * Copyright (C) 2009 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/>. + */ + + +#ifndef _FORMAT_ELF_ELF_H +#define _FORMAT_ELF_ELF_H + + +#include <glib-object.h> +#include <stdbool.h> +#include <sys/types.h> + + +#include "../format.h" + + + +#define G_TYPE_ELF_FORMAT g_elf_format_get_type() +#define G_ELF_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_elf_format_get_type(), GElfFormat)) +#define G_IS_ELF_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_elf_format_get_type())) +#define G_ELF_FORMAT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_elf_format_get_type(), GElfFormatIface)) +#define G_ELF_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ELF_FORMAT, GElfFormatClass)) + + +/* Format d'exécutable ELF (instance) */ +typedef struct _GElfFormat GElfFormat; + +/* Format d'exécutable ELF (classe) */ +typedef struct _GElfFormatClass GElfFormatClass; + + +/* Indique si le format peut être pris en charge ici. */ +bool elf_is_matching(FormatType, const bin_t *, off_t); + +/* Indique le type défini pour un format d'exécutable ELF. */ +GType g_elf_format_get_type(void); + +/* Prend en charge un nouveau format ELF. */ +GBinFormat *g_elf_format_new(const bin_t *, off_t); + + + +#endif /* _FORMAT_ELF_ELF_H */ diff --git a/src/format/elf/elf_def.h b/src/format/elf/elf_def.h new file mode 100644 index 0000000..bbd6117 --- /dev/null +++ b/src/format/elf/elf_def.h @@ -0,0 +1,388 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * elf_def.h - liste des structures et constantes utilisées par le format ELF + * + * Copyright (C) 2009 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/>. + */ + + +#ifndef _FORMAT_ELF_ELF_DEF_H +#define _FORMAT_ELF_ELF_DEF_H + + +#include <stdint.h> + + + +/* Adresses virtuelles */ +typedef union _elf_addr +{ + uint32_t addr32; /* Elf 32 bits */ + uint64_t addr64; /* Elf 64 bits */ + +} elf_addr; + +/* Positions dans le fichier */ +typedef union _elf_off +{ + uint32_t off32; /* Elf 32 bits */ + uint64_t off64; /* Elf 64 bits */ + +} elf_off; + + +#define ELF_OFF(fmt, off) (fmt->is_32b ? (off).off32 : (off).off64) + + + +/* ---------------------------- EN-TETE DES FICHIERS ELF ---------------------------- */ + + +#define EI_NIDENT 16 + + +/* En-tête de fichier ELF */ +typedef struct _elf_header +{ + uint8_t e_ident[EI_NIDENT]; /* Magic number + informations */ + uint16_t e_type; /* Type de fichier */ + uint16_t e_machine; /* Architecture */ + uint32_t e_version; /* Version du type de fichier */ + elf_addr e_entry; /* Point d'entrée du programme */ + elf_off e_phoff; /* Début de la table 'Program' */ + elf_off e_shoff; /* Début de la table 'Section' */ + uint32_t e_flags; /* Prop. spécifiques au proc. */ + uint16_t e_ehsize; /* Taille de l'en-tête en oct. */ + uint16_t e_phentsize; /* Taille d'une entrée Program */ + uint16_t e_phnum; /* Nombre d'éléments 'Program' */ + uint16_t e_shentsize; /* Taille d'une entrée Section */ + uint16_t e_shnum; /* Nombre d'éléments 'Section' */ + uint16_t e_shstrndx; /* Indice de la section chaînes*/ + +} elf_header; + + +/* Composition du champ e_ident */ + + +#define EI_CLASS 4 /* Indice de classe du fichier */ +#define EI_DATA 5 /* Indice de l'encodage */ + + +/* ... EI_CLASS */ + +#define ELFCLASSNONE 0 /* Objet invalide */ +#define ELFCLASS32 1 /* Objet 32 bits */ +#define ELFCLASS64 2 /* Objet 64 bits */ + +/* ... EI_DATA */ + +#define ELFDATANONE 0 /* Encodage invalide */ +#define ELFDATA2LSB 1 /* Complément à 2, petit bout. */ +#define ELFDATA2MSB 2 /* Complément à 2, grand bout. */ + + +/* Valeurs possibles pour e_machine */ + +#define EM_NONE 0 /* Aucune machine */ +#define EM_386 3 /* Intel 80386 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + + + +/* --------------------------- EN-TETE DES PROGRAMMES ELF --------------------------- */ + + +/* Version 32 et 64 bits */ + + +typedef struct _elf32_phdr +{ + uint32_t p_type; /* Type de segment */ + uint32_t p_offset; /* Position dans le fichier */ + uint32_t p_vaddr; /* Adresse virtuelle du segment*/ + uint32_t p_paddr; /* Adresse physique du segment */ + uint32_t p_filesz; /* Taille dans le fichier */ + uint32_t p_memsz; /* Taille en mémoire */ + uint32_t p_flags; /* Drapeaux pour le segment */ + uint32_t p_align; /* Alignement du segment */ + +} elf32_phdr; + +typedef struct _elf64_phdr +{ + uint32_t p_type; /* Type de segment */ + uint32_t p_flags; /* Drapeaux pour le segment */ + uint64_t p_offset; /* Position dans le fichier */ + uint64_t p_vaddr; /* Adresse virtuelle du segment*/ + uint64_t p_paddr; /* Adresse physique du segment */ + uint64_t p_filesz; /* Taille dans le fichier */ + uint64_t p_memsz; /* Taille en mémoire */ + uint64_t p_align; /* Alignement du segment */ + +} elf64_phdr; + +typedef union _elf_phdr +{ + elf32_phdr phdr32; /* Version 32 bits */ + elf64_phdr phdr64; /* Version 32 bits */ + +} elf_phdr; + + +#define ELF_PHDR(fmt, hdr, fld) (fmt->is_32b ? hdr.phdr32.fld : hdr.phdr64.fld) + +#define ELF_SIZEOF_PHDR(fmt) (fmt->is_32b ? sizeof(elf32_phdr) : sizeof(elf64_phdr)) + + +/* Valeurs possibles pour p_flags */ + +#define PF_X (1 << 0) /* Le segment est exécutable */ +#define PF_W (1 << 1) /* Le segment est écrasable */ +#define PF_R (1 << 2) /* Le segment est lisible */ + + + +/* ---------------------------- EN-TETE DES SECTIONS ELF ---------------------------- */ + + +/* Version 32 et 64 bits */ + +typedef struct _elf32_shdr +{ + uint32_t sh_name; /* Indice du nom de la section */ + uint32_t sh_type; /* Type de section */ + uint32_t sh_flags; /* Drapeaux pour la section */ + uint32_t sh_addr; /* Adresse virtuelle à l'exec. */ + uint32_t sh_offset; /* Position dans le fichier */ + uint32_t sh_size; /* Taille en octets */ + uint32_t sh_link; /* Lien vers une autre section */ + uint32_t sh_info; /* Infos. complémentaires */ + uint32_t sh_addralign; /* Alignement de la section */ + uint32_t sh_entsize; /* Eventuelle taille d'élément */ + +} elf32_shdr; + +typedef struct _elf64_shdr +{ + uint32_t sh_name; /* Indice du nom de la section */ + uint32_t sh_type; /* Type de section */ + uint64_t sh_flags; /* Drapeaux pour la section */ + uint64_t sh_addr; /* Adresse virtuelle à l'exec. */ + uint64_t sh_offset; /* Position dans le fichier */ + uint64_t sh_size; /* Taille en octets */ + uint32_t sh_link; /* Lien vers une autre section */ + uint32_t sh_info; /* Infos. complémentaires */ + uint64_t sh_addralign; /* Alignement de la section */ + uint64_t sh_entsize; /* Eventuelle taille d'élément */ + +} elf64_shdr; + +typedef union _elf_shdr +{ + elf32_shdr shdr32; /* Version 32 bits */ + elf64_shdr shdr64; /* Version 32 bits */ + +} elf_shdr; + + +#define ELF_SHDR(fmt, shdr, fld) (fmt->is_32b ? (shdr).shdr32.fld : (shdr).shdr64.fld) + +#define ELF_SIZEOF_SHDR(fmt) (fmt->is_32b ? sizeof(elf32_shdr) : sizeof(elf64_shdr)) + + +/* Valeurs possibles pour sh_type */ + +#define SHT_NULL 0 /* Entrée non utilisée */ +#define SHT_PROGBITS 1 /* Données de programme */ +#define SHT_SYMTAB 2 /* Table des symboles */ +#define SHT_STRTAB 3 /* Table de chaînes de carac. */ +#define SHT_DYNAMIC 6 /* Info. de liaison dynamique */ + + +/* Valeurs possibles pour sh_flags */ + +#define SHF_ALLOC (1 << 1) /* Copie en mémoire pdt l'exec.*/ +#define SHF_EXECINSTR (1 << 2) /* Section exécutable */ +#define SHF_STRINGS (1 << 5) /* Contient des chaînes ('\0') */ + + + +/* ----------------------------- DONNEES POUR LE LINKER ----------------------------- */ + + +/* Entrées de la section dynamique (version 32 et 64 bits) */ + +typedef struct _elf32_dyn +{ + int32_t d_tag; /* Type de l'entrée */ + + union + { + uint32_t d_val; /* Valeur entière */ + uint32_t d_ptr; /* Valeur d'adresse */ + + } d_un; + +} elf32_dyn; + +typedef struct _elf64_dyn +{ + int64_t d_tag; /* Type de l'entrée */ + + union + { + uint64_t d_val; /* Valeur entière */ + uint64_t d_ptr; /* Valeur d'adresse */ + + } d_un; + +} elf64_dyn; + +typedef union _elf_dyn +{ + elf32_dyn dyn32; /* Version 32 bits */ + elf64_dyn dyn64; /* Version 32 bits */ + +} elf_dyn; + + +#define ELF_DYN(fmt, dyn, fld) (fmt->is_32b ? (dyn).dyn32.fld : (dyn).dyn64.fld) + +#define ELF_SIZEOF_DYN(fmt) (fmt->is_32b ? sizeof(elf32_dyn) : sizeof(elf64_dyn)) + + + +/* Valeurs possibles pour d_tag */ + +#define DT_SYMTAB 6 /* Table des symboles */ +#define DT_JMPREL 23 /* Relocalisations PLT */ + + + +/* ---------------------------- SYMBOLES DE BINAIRES ELF ---------------------------- */ + + +/* Elément de la table des symboles */ + +typedef struct _elf32_sym +{ + uint32_t st_name; /* Indice pour le nom */ + uint32_t st_value; /* Valeur du symbole */ + uint32_t st_size; /* Taille du symbole */ + unsigned char st_info; /* Type et infos. du symbole */ + unsigned char st_other; /* Visibilité du symbole */ + uint16_t st_shndx; /* Indice de la section */ + +} elf32_sym; + +typedef struct _elf64_sym +{ + uint32_t st_name; /* Indice pour le nom */ + unsigned char st_info; /* Type et infos. du symbole */ + unsigned char st_other; /* Visibilité du symbole */ + uint16_t st_shndx; /* Indice de la section */ + uint64_t st_value; /* Valeur du symbole */ + uint64_t st_size; /* Taille du symbole */ + +} elf64_sym; + +typedef union _elf_sym +{ + elf32_sym sym32; /* Version 32 bits */ + elf64_sym sym64; /* Version 64 bits */ + +} elf_sym; + + +#define ELF_SYM(fmt, sb, fld) (fmt->is_32b ? sb.sym32.fld : sb.sym64.fld) + +#define ELF_ST_BIND(fmt, sym) (fmt->is_32b ? ELF32_ST_BIND(sym.sym32.st_info) : ELF64_ST_BIND(sym.sym64.st_info)) +#define ELF_ST_TYPE(fmt, sym) (fmt->is_32b ? ELF32_ST_TYPE(sym.sym32.st_info) : ELF64_ST_TYPE(sym.sym64.st_info)) + +#define ELF_SIZEOF_SYM(fmt) (fmt->is_32b ? sizeof(elf32_sym) : sizeof(elf64_sym)) + + +/* Extraction des informations de st_info */ + +#define ELF32_ST_BIND(val) (((unsigned char)(val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) + +#define ELF64_ST_BIND(val) ELF32_ST_BIND(val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE(val) + +/* Valeurs pour le sous-champ ST_TYPE de st_info */ + +#define STT_NOTYPE 0 /* Type de symbole non spécifié*/ +#define STT_OBJECT 1 /* Symbole, objet de données */ +#define STT_FUNC 2 /* Symbole, objet de code */ + + + +/* ------------------------- INFORMATIONS DE RELOCALISATION ------------------------- */ + + +/* Entrée de la table de relocalisation */ + +typedef struct _elf32_rel +{ + uint32_t r_offset; /* Adresse */ + uint32_t r_info; /* Indice de type et symbole */ + +} elf32_rel; + +typedef struct _elf64_rel +{ + uint64_t r_offset; /* Adresse */ + uint64_t r_info; /* Indice de type et symbole */ + +} elf64_rel; + +typedef union _elf_rel +{ + elf32_rel rel32; /* Version 32 bits */ + elf64_rel rel64; /* Version 64 bits */ + +} elf_rel; + + +#define ELF_REL(fmt, rl, fld) (fmt->is_32b ? rl.rel32.fld : rl.rel64.fld) + +#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM(rl.rel32.r_info) : ELF64_R_SYM(rl.rel64.r_info)) +#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE(rl.rel32.r_info) : ELF64_R_TYPE(rl.rel64.r_info)) + +#define ELF_SIZEOF_REL(fmt) (fmt->is_32b ? sizeof(elf32_rel) : sizeof(elf64_rel)) + + +/* Extraction des informations de r_info */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) + +#define ELF64_R_SYM(val) ((val) >> 32) +#define ELF64_R_TYPE(val) ((val) & 0xffffffff) + +/* Type de relocalisation (x86) */ + +#define R_386_NONE 0 /* Pas de relocalisation */ +#define R_386_JMP_SLOT 7 /* Entrée PLT */ + + + +#endif /* _FORMAT_ELF_ELF_DEF_H */ diff --git a/src/format/elf/helper_x86.c b/src/format/elf/helper_x86.c index 1975709..82be74c 100644 --- a/src/format/elf/helper_x86.c +++ b/src/format/elf/helper_x86.c @@ -25,37 +25,117 @@ #include <malloc.h> +#include <stdio.h> #include <string.h> #include "elf-int.h" -#include "section.h" +#include "../symbol.h" #include "../../arch/immediate.h" #include "../../arch/processor.h" #include "../../arch/x86/instruction.h" -#include "../../panel/log.h" -#define _(str) (str) - +/* symbols.c : Récupère la désignation d'un symbole donné. */ +extern const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf_shdr *, off_t); /* Décode les instructions liées à la relocalisation. */ -GArchInstruction **decode_elf_relocations(elf_format *, size_t *); +GArchInstruction **decode_elf_relocations(GElfFormat *, const elf_shdr *, size_t *); /* Déduit les adresses effectives des relocalisations. */ -void translate_elf_relocations(elf_format *, GArchInstruction **, size_t); +void translate_elf_relocations(GElfFormat *, GArchInstruction **, size_t); /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à compléter. * -* dyn_start = début des informations dynamiques associées. * -* dyn_size = taille de la zone associée. * -* str_start = début de la zone de chaîne de caractères. * -* str_size = taille de la zone de chaînes de caractères. * +* Paramètres : format = description de l'exécutable à compléter. * +* relxxx = section .rel.xxx trouvée (zone à traiter). * +* dynsym = section .dynsym trouvée (info. dynamiques). * +* dynstr = section .dynstr trouvée (chaînes de caractères). * +* * +* Description : Charge en mémoire la liste des symboles dynamiques. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_elf_x86_relocated_symbols(GElfFormat *format, const elf_shdr *relxxx, const elf_shdr *dynsym, const elf_shdr *dynstr) +{ + bool result; /* Bilan à retourner */ + off_t rel_start; /* Début de la zone à traiter */ + off_t rel_size; /* Taille de cette même zone */ + off_t iter; /* Boucle de parcours */ + elf_rel reloc; /* Infos de relocalisation */ + off_t index; /* Indice de la portion visée */ + const char *name; /* Nom du symbole trouvé */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + + + + result = true; + + + + get_elf_section_content(format, relxxx, &rel_start, &rel_size, NULL); + + + printf("rel :: %d -> %d\n", rel_start, rel_start + rel_size); + + + + for (iter = rel_start; iter < (rel_start + rel_size); ) + { + result = read_elf_relocation(format, &iter, &reloc); + if (!result) break; + + switch (ELF_REL_TYPE(format, reloc)) + { + case R_386_NONE: + break; + + case R_386_JMP_SLOT: + + index = ELF_REL_SYM(format, reloc); + name = get_elf_symbol_name(format, dynsym, dynstr, index); + + + printf("got a jump ! >> %d - %s\n", index, name); + + + if (name == NULL) + { + /* FIXME */ + name = "unknown"; + } + + symbol = g_binary_symbol_new(STP_FUNCTION, name, ELF_REL(format, reloc, r_offset)); + g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); + + break; + + default: + printf("Relocation not supported (%lld) !\n", ELF_REL_TYPE(format, reloc)); + break; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* plt = section .plt trouvée (points d'entrées dynamiques). * * * * Description : Déduit les adresses effectives des appels externes. * * * @@ -65,13 +145,13 @@ void translate_elf_relocations(elf_format *, GArchInstruction **, size_t); * * ******************************************************************************/ -bool g_elf_format_find_x86_dynamic_symbols(elf_format *format, off_t dyn_start, off_t dyn_size, off_t str_start, off_t str_size) +bool find_elf_x86_dynamic_symbols(GElfFormat *format, const elf_shdr *plt) { GArchInstruction **instructions; /* Instructions décodées */ size_t count; /* Quantité d'instructions */ size_t i; /* Boucle de parcours */ - instructions = decode_elf_relocations(format, &count); + instructions = decode_elf_relocations(format, plt, &count); translate_elf_relocations(format, instructions, count); @@ -89,6 +169,7 @@ bool g_elf_format_find_x86_dynamic_symbols(elf_format *format, off_t dyn_start, /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * +* plt = section .plt trouvée (points d'entrées dynamiques). * * count = nombre d'instructions lues. [OUT] * * * * Description : Décode les instructions liées à la relocalisation. * @@ -99,15 +180,12 @@ bool g_elf_format_find_x86_dynamic_symbols(elf_format *format, off_t dyn_start, * * ******************************************************************************/ -GArchInstruction **decode_elf_relocations(elf_format *format, size_t *count) +GArchInstruction **decode_elf_relocations(GElfFormat *format, const elf_shdr *plt, size_t *count) { GArchInstruction **result; /* Liste à renvoyer */ off_t plt_start; /* Début de section */ off_t plt_size; /* Taille de section */ vmpa_t plt_address; /* Adresse virtuelle associée */ - Elf_Shdr *sections; /* Groupe de sections trouvées */ - size_t sec_count; /* Quantité de données */ - size_t i; /* Boucle de parcours */ GArchProcessor *proc; /* Processeur pour le décodage */ off_t pos; /* Tête de lecture */ vmpa_t address; /* Adresse virtuelle courante */ @@ -116,26 +194,7 @@ GArchInstruction **decode_elf_relocations(elf_format *format, size_t *count) result = NULL; *count = 0; - if (!find_elf_section_content_by_name(format, ".plt", &plt_start, &plt_size, &plt_address)) - { - log_simple_message(LMT_BAD_BINARY, _("No .plt section found ! Trying to guess it...")); - - /* FIXME : 64 bits ! */ - - find_elf_section_by_type(format, SHT_PROGBITS, §ions, &sec_count); - - for (i = 0; i < sec_count; i++) - if (ELF_SHDR(format, §ions[i], sh_entsize) > 0) - { - get_elf_section_content(format, §ions[i], &plt_start, &plt_size, &plt_address); - break; - } - - free(sections); - - if (i == sec_count) return NULL; - - } + get_elf_section_content(format, plt, &plt_start, &plt_size, &plt_address); proc = get_arch_processor_for_type(APT_386); @@ -143,7 +202,7 @@ GArchInstruction **decode_elf_relocations(elf_format *format, size_t *count) { address = plt_address + pos; - instr = g_arch_processor_decode_instruction(proc, &EXE_FORMAT(format)->content[plt_start], + instr = g_arch_processor_decode_instruction(proc, &G_BIN_FORMAT(format)->content[plt_start], &pos, plt_size, 0/* FIXME*/, address); result = (GArchInstruction **)realloc(result, ++(*count) * sizeof(GArchInstruction *)); @@ -170,18 +229,21 @@ GArchInstruction **decode_elf_relocations(elf_format *format, size_t *count) * * ******************************************************************************/ -void translate_elf_relocations(elf_format *format, GArchInstruction **instructions, size_t count) +void translate_elf_relocations(GElfFormat *format, GArchInstruction **instructions, size_t count) { size_t i; /* Boucle de parcours #1 */ X86Opcodes opcode_n0; /* Opcode de l'instruction n */ X86Opcodes opcode_n1; /* Opcode de l'instruction n+1 */ X86Opcodes opcode_n2; /* Opcode de l'instruction n+2 */ - GArchOperand *operand; /* Valeur du saut */ + const GArchOperand *operand; /* Valeur du saut */ vmpa_t address; /* Adresse virtuelle finale */ + GBinSymbol **symbols; /* Liste des symboles existants*/ + size_t symbols_count; /* Taille de cette liste */ size_t j; /* Boucle de parcours #2 */ size_t new_len; /* Taille du nouveau nom */ char *new_name; /* Nom avec suffixe @plt */ GBinRoutine *routine; /* Nouvelle routine déduite */ + GBinSymbol *symbol; /* Nouveau symbole construit */ for (i = 0; (i + 2) < count; ) { @@ -195,31 +257,39 @@ void translate_elf_relocations(elf_format *format, GArchInstruction **instructio { operand = g_arch_instruction_get_operand(instructions[i], 0); - g_imm_operand_to_vmpa_t(G_IMM_OPERAND(operand), &address); if (g_imm_operand_to_vmpa_t(G_IMM_OPERAND(operand), &address)) - for (j = 0; j < format->rel_count; j++) - if (format->relocations[j].address == address) + { + symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &symbols_count); + + for (j = 0; j < symbols_count; j++) + if (g_binary_symbol_get_address(symbols[j]) == address) { - new_len = strlen(format->relocations[j].name) + 4 + 1; + new_len = strlen(g_binary_symbol_to_string(symbols[j])) + 4 + 1; new_name = calloc(new_len, sizeof(char)); - snprintf(new_name, new_len, "%s@plt", format->relocations[j].name); + snprintf(new_name, new_len, "%s@plt", g_binary_symbol_to_string(symbols[j])); g_arch_instruction_get_location(instructions[i], NULL, NULL, &address); + /* Routine */ + routine = g_binary_routine_new(); g_binary_routine_set_name(routine, new_name); g_binary_routine_set_address(routine, address); - format->routines = (GBinRoutine **)realloc(format->routines, - ++format->routines_count * sizeof(GBinRoutine *)); + g_binary_format_add_routine(G_BIN_FORMAT(format), routine); + + /* Symbole uniquement */ - format->routines[format->routines_count - 1] = routine; + symbol = g_binary_symbol_new(STP_FUNCTION, new_name, address); + g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); } + } + i += 3; } diff --git a/src/format/elf/helper_x86.h b/src/format/elf/helper_x86.h index 957c8c3..eae7c8b 100644 --- a/src/format/elf/helper_x86.h +++ b/src/format/elf/helper_x86.h @@ -25,16 +25,15 @@ #define _FORMAT_ELF_HELPER_X86_H -#include <stdbool.h> -#include <sys/types.h> +#include "section.h" -#include "e_elf.h" - +/* Charge en mémoire la liste des symboles dynamiques. */ +bool load_elf_x86_relocated_symbols(GElfFormat *, const elf_shdr *, const elf_shdr *, const elf_shdr *); /* Déduit les adresses effectives des appels externes. */ -bool g_elf_format_find_x86_dynamic_symbols(elf_format *, off_t, off_t, off_t, off_t); +bool find_elf_x86_dynamic_symbols(GElfFormat *, const elf_shdr *); diff --git a/src/format/elf/section.c b/src/format/elf/section.c index c619293..940acdf 100644 --- a/src/format/elf/section.c +++ b/src/format/elf/section.c @@ -34,9 +34,11 @@ /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à compléter. * +* Paramètres : format = description de l'exécutable à consulter. * +* index = indice de la section recherchée. * +* section = ensemble d'informations à faire remonter. [OUT] * * * -* Description : Charge en mémoire la liste humaine des sections. * +* Description : Recherche une section donnée au sein de binaire par indice. * * * * Retour : Bilan de l'opération. * * * @@ -44,25 +46,15 @@ * * ******************************************************************************/ -bool read_elf_section_names(elf_format *format) +bool find_elf_section_by_index(const GElfFormat *format, uint16_t index, elf_shdr *section) { - off_t offset; /* Position des données */ - Elf32_Shdr section; /* Section visée */ - - offset = format->header.e_shoff + format->header.e_shentsize * format->header.e_shstrndx; - - if ((offset + sizeof(Elf32_Shdr)) > EXE_FORMAT(format)->length) return false; - - memcpy(§ion, &EXE_FORMAT(format)->content[offset], sizeof(Elf32_Shdr)); - - if ((section.sh_offset + section.sh_size) > EXE_FORMAT(format)->length) return false; + off_t offset; /* Emplacement à venir lire */ - format->sec_names = (char *)calloc(section.sh_size + 1, sizeof(char)); - format->sec_size = section.sh_size; + if (index >= format->header.e_shnum) return false; - memcpy(format->sec_names, &EXE_FORMAT(format)->content[section.sh_offset], section.sh_size); + offset = ELF_OFF(format, format->header.e_shoff) + format->header.e_shentsize * index; - return true; + return read_elf_section_header(format, offset, section); } @@ -81,13 +73,15 @@ bool read_elf_section_names(elf_format *format) * * ******************************************************************************/ -bool find_elf_section_by_name(const elf_format *format, const char *name, Elf_Shdr *section) +bool find_elf_section_by_name(const GElfFormat *format, const char *name, elf_shdr *section) { - bool result; /* Bilan à retourner */ + bool result; /* Bilan à faire remonter */ + elf_shdr strings; /* Section des descriptions */ uint16_t i; /* Boucle de parcours */ + const char *secname; /* Nom d'une section analysée */ - /* Si on perd notre temps... */ - if (format->sec_size == 0) return false; + if (!find_elf_section_by_index(format, format->header.e_shstrndx, &strings)) + return false; result = false; @@ -95,7 +89,10 @@ bool find_elf_section_by_name(const elf_format *format, const char *name, Elf_Sh { find_elf_section_by_index(format, i, section); - result = (strcmp(name, &format->sec_names[ELF_SHDR(format, section, sh_name)]) == 0); + secname = extract_name_from_elf_string_section(format, &strings, + ELF_SHDR(format, *section, sh_name)); + + result = (strcmp(name, secname) == 0); } @@ -106,10 +103,9 @@ bool find_elf_section_by_name(const elf_format *format, const char *name, Elf_Sh /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * -* type = type de la section recherchée. * -* sections = tableau d'informations à faire remonter. [OUT] * -* count = nombre d'éléments présents dans le tableau. [OUT] * +* Paramètres : format = description de l'exécutable à consulter. * +* addr = adresse de la section recherchée. (32 bits) * +* section = ensemble d'informations à faire remonter. [OUT] * * * * Description : Recherche une section donnée au sein de binaire par type. * * * @@ -119,38 +115,34 @@ bool find_elf_section_by_name(const elf_format *format, const char *name, Elf_Sh * * ******************************************************************************/ -bool find_elf_section_by_type(const elf_format *format, uint16_t type, Elf_Shdr **sections, size_t *count) +bool find_elf_section_by_virtual_address(const GElfFormat *format, uint32_t addr, elf_shdr *section) { + bool result; /* Bilan à faire remonter */ uint16_t i; /* Boucle de parcours */ - Elf_Shdr section; /* Section à analyser */ - *sections = NULL; - *count = 0; + result = false; - for (i = 0; i < format->header.e_shnum; i++) + for (i = 0; i < format->header.e_shnum && !result; i++) { - find_elf_section_by_index(format, i, §ion); + find_elf_section_by_index(format, i, section); - if (type == ELF_SHDR(format, §ion, sh_type)) - { - *sections = (Elf_Shdr *)realloc(*sections, ++(*count) * sizeof(Elf_Shdr)); - (*sections)[*count - 1] = section; - } + result = (addr == ELF_SHDR(format, *section, sh_addr)); } - return (*count > 0); + return result; } /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * -* index = indice de la section recherchée. * -* section = ensemble d'informations à faire remonter. [OUT] * +* Paramètres : format = description de l'exécutable à consulter. * +* type = type de la section recherchée. * +* sections = tableau d'informations à faire remonter. [OUT] * +* count = nombre d'éléments présents dans le tableau. [OUT] * * * -* Description : Recherche une section donnée au sein de binaire par indice. * +* Description : Recherche une section donnée au sein de binaire par type. * * * * Retour : Bilan de l'opération. * * * @@ -158,17 +150,27 @@ bool find_elf_section_by_type(const elf_format *format, uint16_t type, Elf_Shdr * * ******************************************************************************/ -bool find_elf_section_by_index(const elf_format *format, uint16_t index, Elf_Shdr *section) +bool find_elf_sections_by_type(const GElfFormat *format, uint32_t type, elf_shdr **sections, size_t *count) { - off_t offset; /* Emplacement à venir lire */ + uint16_t i; /* Boucle de parcours */ + elf_shdr section; /* Section à analyser */ - if (index >= format->header.e_shnum) return false; + *sections = NULL; + *count = 0; - offset = format->header.e_shoff + format->header.e_shentsize * index; + for (i = 0; i < format->header.e_shnum; i++) + { + find_elf_section_by_index(format, i, §ion); - memcpy(section, &EXE_FORMAT(format)->content[offset], ELF_SIZEOF_SHDR(format)); + if (type == ELF_SHDR(format, section, sh_type)) + { + *sections = (elf_shdr *)realloc(*sections, ++(*count) * sizeof(elf_shdr)); + (*sections)[*count - 1] = section; + } + + } - return true; + return (*count > 0); } @@ -179,7 +181,7 @@ bool find_elf_section_by_index(const elf_format *format, uint16_t index, Elf_Shd * section = section à consulter. * * offset = position de la section trouvée. [OUT] * * size = taille de la section trouvée. [OUT] * -* voffset = adresse virtuelle de la section trouvée. [OUT] * +* addr = adresse virtuelle de la section trouvée. [OUT] * * * * Description : Fournit les adresses et taille contenues dans une section. * * * @@ -189,13 +191,13 @@ bool find_elf_section_by_index(const elf_format *format, uint16_t index, Elf_Shd * * ******************************************************************************/ -void get_elf_section_content(const elf_format *format, const Elf_Shdr *section, off_t *offset, off_t *size, uint64_t *voffset) +void get_elf_section_content(const GElfFormat *format, const elf_shdr *section, off_t *offset, off_t *size, vmpa_t *addr) { - *offset = ELF_SHDR(format, section, sh_offset); - *size = ELF_SHDR(format, section, sh_size); + *offset = ELF_SHDR(format, *section, sh_offset); + *size = ELF_SHDR(format, *section, sh_size); - if (voffset != NULL) - *voffset = ELF_SHDR(format, section, sh_addr); + if (addr != NULL) + *addr = ELF_SHDR(format, *section, sh_addr); } @@ -206,7 +208,7 @@ void get_elf_section_content(const elf_format *format, const Elf_Shdr *section, * name = nom de la section recherchée. * * offset = position de la section trouvée. [OUT] * * size = taille de la section trouvée. [OUT] * -* voffset = adresse virtuelle de la section trouvée. [OUT] * +* address = adresse virtuelle de la section trouvée. [OUT] * * * * Description : Recherche une zone donnée au sein de binaire par nom. * * * @@ -216,15 +218,15 @@ void get_elf_section_content(const elf_format *format, const Elf_Shdr *section, * * ******************************************************************************/ -bool find_elf_section_content_by_name(const elf_format *format, const char *name, off_t *offset, off_t *size, uint64_t *voffset) +bool find_elf_section_content_by_name(const GElfFormat *format, const char *name, off_t *offset, off_t *size, vmpa_t *address) { bool result; /* Bilan à retourner */ - Elf_Shdr section; /* Section trouvée ou non */ + elf_shdr section; /* Section trouvée ou non */ result = find_elf_section_by_name(format, name, §ion); if (result) - get_elf_section_content(format, §ion, offset, size, voffset); + get_elf_section_content(format, §ion, offset, size, address); return result; @@ -234,28 +236,39 @@ bool find_elf_section_content_by_name(const elf_format *format, const char *name /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * -* index = indice de la section recherchée. * -* offset = position de la section trouvée. [OUT] * -* size = taille de la section trouvée. [OUT] * -* voffset = adresse virtuelle de la section trouvée. [OUT] * +* section = section contenant des chaînes terminées par '\0'. * +* index = indice du premier caractères à cerner. * * * -* Description : Recherche une zone donnée au sein de binaire par indice. * +* Description : Identifie une chaîne de caractères dans une section adéquate.* * * -* Retour : Bilan de l'opération. * +* Retour : Pointeur vers la chaîne recherchée ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -bool find_elf_section_content_by_index(const elf_format *format, uint16_t index, off_t *offset, off_t *size, uint64_t *voffset) +const char *extract_name_from_elf_string_section(const GElfFormat *format, const elf_shdr *section, uint16_t index) { - bool result; /* Bilan à retourner */ - Elf_Shdr section; /* Section trouvée ou non */ + const char *result; /* Nom trouvé à renvoyer */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + off_t last; /* Dernier '\0' possible */ + off_t pos; /* Point de lecture */ - result = find_elf_section_by_index(format, index, §ion); + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; - if (result) - get_elf_section_content(format, §ion, offset, size, voffset); + last = ELF_SHDR(format, *section, sh_offset) + ELF_SHDR(format, *section, sh_size); + + pos = ELF_SHDR(format, *section, sh_offset) + index; + + if ((pos + 1) >= MIN(length, last)) + return NULL; + + result = (const char *)&content[pos]; + + if ((pos + strlen(result)) > last) + return NULL; return result; diff --git a/src/format/elf/section.h b/src/format/elf/section.h index 6bc3a75..944fd7c 100644 --- a/src/format/elf/section.h +++ b/src/format/elf/section.h @@ -25,47 +25,31 @@ #define _FORMAT_ELF_SECTION_H -#include <elf.h> +#include "elf.h" +#include "elf_def.h" -#include "e_elf.h" - -/* En-tête de section ELF */ -typedef union _Elf_Shdr -{ - Elf32_Shdr section32; /* Version 32 bits */ - Elf64_Shdr section64; /* Version 64 bits */ - -} Elf_Shdr; - - -#define ELF_SIZEOF_SHDR(fmt) (fmt->is_32b ? sizeof(Elf32_Shdr) : sizeof(Elf64_Shdr)) - -#define ELF_SHDR(fmt, shdr, fld) (fmt->is_32b ? (shdr)->section32.fld : (shdr)->section64.fld) - - - -/* Charge en mémoire la liste humaine des sections. */ -bool read_elf_section_names(elf_format *); +/* Recherche une section donnée au sein de binaire par indice. */ +bool find_elf_section_by_index(const GElfFormat *, uint16_t, elf_shdr *); /* Recherche une section donnée au sein de binaire par nom. */ -bool find_elf_section_by_name(const elf_format *, const char *, Elf_Shdr *); +bool find_elf_section_by_name(const GElfFormat *, const char *, elf_shdr *); /* Recherche une section donnée au sein de binaire par type. */ -bool find_elf_section_by_type(const elf_format *, uint16_t, Elf_Shdr **, size_t *); +bool find_elf_section_by_virtual_address(const GElfFormat *, uint32_t, elf_shdr *); -/* Recherche une section donnée au sein de binaire par indice. */ -bool find_elf_section_by_index(const elf_format *, uint16_t, Elf_Shdr *); +/* Recherche une section donnée au sein de binaire par type. */ +bool find_elf_sections_by_type(const GElfFormat *, uint32_t, elf_shdr **, size_t *); /* Fournit les adresses et taille contenues dans une section. */ -void get_elf_section_content(const elf_format *, const Elf_Shdr *, off_t *, off_t *, uint64_t *); +void get_elf_section_content(const GElfFormat *, const elf_shdr *, off_t *, off_t *, vmpa_t *); /* Recherche une zone donnée au sein de binaire par nom. */ -bool find_elf_section_content_by_name(const elf_format *, const char *, off_t *, off_t *, uint64_t *); +bool find_elf_section_content_by_name(const GElfFormat *, const char *, off_t *, off_t *, vmpa_t *); -/* Recherche une zone donnée au sein de binaire par indice. */ -bool find_elf_section_content_by_index(const elf_format *, uint16_t, off_t *, off_t *, uint64_t *); +/* Identifie une chaîne de caractères dans une section adéquate. */ +const char *extract_name_from_elf_string_section(const GElfFormat *, const elf_shdr *, uint16_t); diff --git a/src/format/elf/strings.c b/src/format/elf/strings.c index 2bcd911..157d3b5 100644 --- a/src/format/elf/strings.c +++ b/src/format/elf/strings.c @@ -27,6 +27,7 @@ #include <ctype.h> #include <malloc.h> #include <string.h> +#include <sys/param.h> #include "elf-int.h" @@ -35,7 +36,7 @@ /* Enregistre toutes les chaînes de caractères trouvées. */ -bool parse_elf_string_data(elf_format *, const off_t, const off_t, uint64_t); +bool parse_elf_string_data(GElfFormat *, off_t, off_t, vmpa_t); @@ -51,63 +52,81 @@ bool parse_elf_string_data(elf_format *, const off_t, const off_t, uint64_t); * * ******************************************************************************/ -bool find_all_elf_strings(elf_format *format) +bool find_all_elf_strings(GElfFormat *format) { + bool got_string; /* Indique un remplissage */ off_t str_start; /* Début de section */ off_t str_size; /* Taille de section */ - uint64_t str_vaddr; /* Adresse virtuelle associée */ - Elf_Shdr *sections; /* Groupe de sections trouvées */ + vmpa_t str_addr; /* Adresse virtuelle associée */ + elf_shdr *sections; /* Groupe de sections trouvées */ size_t count; /* Quantité de données */ - size_t i; /* Boucle de parcours */ - off_t offset; /* Position physique */ - Elf_Phdr phdr; /* En-tête de programme ELF */ + size_t i; /* Boucle de parcours #1 */ + off_t length; /* Taille totale du contenu */ + off_t iter; /* Boucle de parcours #2 */ + elf_phdr phdr; /* En-tête de programme ELF */ + + got_string = false; /* Données en lecture seule */ - if (find_elf_section_content_by_name(format, ".rodata", &str_start, &str_size, &str_vaddr)) - parse_elf_string_data(format, str_start, str_size, str_vaddr); + if (find_elf_section_content_by_name(format, ".rodata", &str_start, &str_size, &str_addr)) + got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); else { - find_elf_section_by_type(format, SHT_PROGBITS, §ions, &count); + if (find_elf_sections_by_type(format, SHT_PROGBITS, §ions, &count)) + { + for (i = 0; i < count; i++) + if (ELF_SHDR(format, sections[i], sh_flags) == SHF_ALLOC + || (ELF_SHDR(format, sections[i], sh_flags) & SHF_STRINGS)) + { + get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_addr); + got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); + } - for (i = 0; i < count; i++) - if (ELF_SHDR(format, §ions[i], sh_flags) == SHF_ALLOC - || (ELF_SHDR(format, §ions[i], sh_flags) & SHF_STRINGS)) - { - get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_vaddr); - parse_elf_string_data(format, str_start, str_size, str_vaddr); - } + free(sections); + + } } /* Chaîne de caractères déclarées */ - find_elf_section_by_type(format, SHT_STRTAB, §ions, &count); - - for (i = 0; i < count; i++) + if (find_elf_sections_by_type(format, SHT_STRTAB, §ions, &count)) { - get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_vaddr); - parse_elf_string_data(format, str_start, str_size, str_vaddr); + for (i = 0; i < count; i++) + { + get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_addr); + got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); + } + + free(sections); + } /* En désespoir de cause, on se rabbat sur les parties de programme directement */ - if (format->str_count == 0 && format->header.e_shnum == 0 /* FIXME : cond. à garder ? */) - for (i = 0; i < format->header.e_phnum; i++) - { - offset = format->header.e_phoff + format->header.e_phentsize * i; - if ((offset + format->header.e_phentsize) >= EXE_FORMAT(format)->length) continue; + if (!got_string) + { + length = G_BIN_FORMAT(format)->length; + length = MIN(length, format->header.e_phnum * ELF_SIZEOF_PHDR(format)); - memcpy(&phdr, &EXE_FORMAT(format)->content[offset], format->header.e_phentsize); + for (iter = ELF_OFF(format, format->header.e_phoff); iter < length; ) + { + if (!read_elf_program_header(format, &iter, &phdr)) + continue; - if (ELF_PHDR(format, &phdr, p_flags) & PF_R && !(ELF_PHDR(format, &phdr, p_flags) & PF_X)) - parse_elf_string_data(format, ELF_PHDR(format, &phdr, p_offset), - ELF_PHDR(format, &phdr, p_filesz), - ELF_PHDR(format, &phdr, p_vaddr)); + if (ELF_PHDR(format, phdr, p_flags) & PF_R + && !(ELF_PHDR(format, phdr, p_flags) & PF_X)) + parse_elf_string_data(format, + ELF_PHDR(format, phdr, p_offset), + ELF_PHDR(format, phdr, p_filesz), + ELF_PHDR(format, phdr, p_vaddr)); } + } + return true; } @@ -115,77 +134,49 @@ bool find_all_elf_strings(elf_format *format) /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à compléter. * -* start = début de la zone à parcourir. * -* size = taille de l'espace à parcourir. * -* vaddress = adresse virtuelle du début de la section. * +* Paramètres : format = description de l'exécutable à compléter. * +* start = début de la zone à parcourir. * +* size = taille de l'espace à parcourir. * +* address = adresse virtuelle du début de la section. * * * * Description : Enregistre toutes les chaînes de caractères trouvées. * * * -* Retour : Bilan de l'opération. * +* Retour : true si des chaînes ont été ajoutées, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -bool parse_elf_string_data(elf_format *format, const off_t start, const off_t size, uint64_t vaddress) +bool parse_elf_string_data(GElfFormat *format, off_t start, off_t size, vmpa_t address) { + bool result; /* Bilan à faire remonter */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ off_t i; /* Boucle de parcours */ off_t end; /* Position de fin de chaîne */ + GBinSymbol *symbol; /* Nouveau symbole construit */ - if (vaddress == 0) return false; - - for (i = start; i < (start + size); i++) - if (isprint(EXE_FORMAT(format)->content[i])) - { - for (end = i + 1; end < (start + size); end++) - if (!isprint(EXE_FORMAT(format)->content[end])) break; - - format->strings = (elf_string *)realloc(format->strings, ++format->str_count * sizeof(elf_string)); - - format->strings[format->str_count - 1].value = strndup((const char *)&EXE_FORMAT(format)->content[i], end - i); - format->strings[format->str_count - 1].len = end - i; - format->strings[format->str_count - 1].address = vaddress + i - start; - - i = end; - - } + if (address == 0) return false; - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* label = étiquette allouée du symbole si trouvé. [OUT] * -* vaddres = adresse à cibler, puis décallage final. [OUT] * -* * -* Description : Recherche une chaîne correspondant à une adresse. * -* * -* Retour : true si l'opération a été un succès, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ + result = false; -bool resolve_elf_strings(const elf_format *format, char **label, vmpa_t *address) -{ - bool result; /* Bilan de recherche remonté */ - size_t real_start; /* Début de chaîne effective */ - size_t i; /* Boucle de parcours */ + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; - result = false; + length = MIN(length, start + size); - for (i = 0; i < format->str_count && !result; i++) - if (format->strings[i].address <= *address - && *address < (format->strings[i].address + format->strings[i].len)) + for (i = start; i < length; i++) + if (isprint(content[i])) { - real_start = *address - format->strings[i].address; - *label = strndup(&format->strings[i].value[real_start], - format->strings[i].len - real_start); + for (end = i + 1; end < length; end++) + if (!isprint(content[end])) break; + + symbol = g_binary_symbol_new(STP_STRING, NULL, address + i - start); + g_binary_symbol_set_alt_name(symbol, strndup((const char *)&content[i], end - i)); + g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); + + i = end; result = true; } diff --git a/src/format/elf/strings.h b/src/format/elf/strings.h index f9b17ac..e52d054 100644 --- a/src/format/elf/strings.h +++ b/src/format/elf/strings.h @@ -25,15 +25,12 @@ #define _FORMAT_ELF_STRINGS_H -#include "e_elf.h" +#include "elf.h" /*Charge en mémoire toutes les chaînes trouvées. */ -bool find_all_elf_strings(elf_format *); - -/* Recherche une chaîne correspondant à une adresse. */ -bool resolve_elf_strings(const elf_format *, char **, vmpa_t *); +bool find_all_elf_strings(GElfFormat *); diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c deleted file mode 100644 index 35943e9..0000000 --- a/src/format/elf/symbol.c +++ /dev/null @@ -1,492 +0,0 @@ - -/* OpenIDA - Outil d'analyse de fichiers binaires - * symbol.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 "symbol.h" - - -#include <malloc.h> -#include <elf.h> -#include <stdio.h> -#include <string.h> - - -#include "elf-int.h" -#include "helper_mips.h" -#include "section.h" - - - - - -/* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */ - - -/* Charge en mémoire la liste des symboles dynamiques. */ -bool load_elf_relocation_table(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *); - -/* Récupère les informations d'un symbole dynamique donné. */ -char *get_elf_dynamic_symbol_info(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *); - - - - -/* Charge en mémoire la liste humaine des symboles (32 bits). */ -bool load_elf_symbol_table_32(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *); - -/* Charge en mémoire la liste humaine des symboles (64 bits). */ -bool load_elf_symbol_table_64(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *); - - - - -/****************************************************************************** -* * -* 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(elf_format *format) -{ - bool result; /* Bilan à retourner */ - Elf_Shdr *sections; /* Groupe de sections trouvées */ - size_t count; /* Quantité de données */ - size_t i; /* Boucle de parcours */ - Elf_Shdr section; /* Section trouvée ou non */ - 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 rel_start; /* Début de section */ - off_t rel_size; /* Taille de section */ - - - bool test; /* Bilan d'une recherche */ - - off_t dyn_start; /* Début de section */ - off_t dyn_size; /* Taille de section */ - - - - result = true; - - - /* Table des symboles */ - - find_elf_section_by_type(format, SHT_SYMTAB, §ions, &count); - - for (i = 0; i < count; i++) - { - /* Section ".symtab" */ - - get_elf_section_content(format, §ions[i], &sym_start, &sym_size, NULL); - - /* Section ".strtab" */ - - result &= find_elf_section_by_index(format, ELF_SHDR(format, §ions[i], sh_link), §ion); - - get_elf_section_content(format, §ion, &str_start, &str_size, NULL); - - if (result) - { - - - - result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_size); - - - - } - - } - - /* Relocalisations */ - - - - /* TODO : fixme ! */ - - find_elf_section_by_type(format, SHT_REL, §ions, &count); - - for (i = 0; i < count; i++) - { - /* Section ".rel.xxx" */ - - get_elf_section_content(format, §ions[i], &rel_start, &rel_size, NULL); - - /* Section ".dynsym" */ - - result &= find_elf_section_by_index(format, ELF_SHDR(format, §ions[i], sh_link), §ion); - - get_elf_section_content(format, §ion, &dyn_start, &dyn_size, NULL); - - /* Section ".dynstr" */ - - result &= find_elf_section_by_index(format, ELF_SHDR(format, §ion, sh_link), §ion); - - get_elf_section_content(format, §ion, &str_start, &str_size, NULL); - - /* Récupération (première partie) */ - if (result) - { - - result = load_elf_relocation_table(format, &rel_start, &rel_size, &dyn_start, &dyn_size, &str_start, &str_size); - - - } - - } - - free(sections); - - /* TODO : fixme ! */ - - - - - - /* Liaison dynamique (si elle existe) */ - - test = find_elf_section_by_name(format, ".dynsym", §ion); - - if (!test) - { - test = find_elf_section_by_type(format, SHT_HASH, §ions, &count); - - if (test) - test = find_elf_section_by_index(format, ELF_SHDR(format, §ions[0], sh_link), §ion); - - } - - if (test) - { - get_elf_section_content(format, §ion, &dyn_start, &dyn_size, NULL); - - result &= find_elf_section_by_index(format, ELF_SHDR(format, §ion, sh_link), §ion); - - } - - if (result) - { - get_elf_section_content(format, §ion, &str_start, &str_size, NULL); - - switch (get_elf_target_machine(format)) - { - case FTM_MIPS: - result = g_elf_format_find_mips_dynamic_symbols(format, dyn_start, dyn_size, str_start, str_size); - break; - - case FTM_386: - result = g_elf_format_find_x86_dynamic_symbols(format, dyn_start, dyn_size, str_start, str_size); - break; - - default: - break; - - } - - } - - return result; - -} - - - - - - -/****************************************************************************** -* * -* Paramètres : format = description de l'exécutable à compléter. * -* sym_start = début de la zone à traiter. * -* sym_size = taille de la zone à traiter. * -* str_start = début de la zone de chaîne de caractères. * -* str_size = taille de la zone de chaînes de caractères. * -* * -* Description : Charge en mémoire la liste humaine des symboles (32 bits). * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool load_elf_symbol_table_32(elf_format *format, const off_t *sym_start, const off_t *sym_size, const off_t *str_start, const off_t *str_size) -{ - off_t iter; /* Boucle de parcours */ - Elf32_Sym symbol; /* Symbole ELF lu */ - GBinRoutine *routine; /* Nouvelle routine trouvée */ - - if (*sym_size % sizeof(Elf32_Sym) != 0) return false; - - for (iter = *sym_start; iter < (*sym_start + *sym_size); iter += sizeof(Elf32_Sym)) - { - memcpy(&symbol, &EXE_FORMAT(format)->content[iter], sizeof(Elf32_Sym)); - - if (!(ELF32_ST_TYPE(symbol.st_info) == STT_FUNC)) continue; - - if (symbol.st_value == 0) continue; - - /* Sécurité anti-débordements */ - if (symbol.st_name >= *str_size) continue; - - /* Si le symbole possède un nom... */ - if (strlen(&EXE_FORMAT(format)->content[*str_start + symbol.st_name]) > 0) - { - routine = g_binary_routine_new(); - - g_binary_routine_set_name(routine, strdup(&EXE_FORMAT(format)->content[*str_start + symbol.st_name])); - g_binary_routine_set_address(routine, symbol.st_value); - g_binary_routine_set_size(routine, symbol.st_size); - - format->routines = (GBinRoutine **)realloc(format->routines, - ++format->routines_count * sizeof(GBinRoutine *)); - - format->routines[format->routines_count - 1] = routine; - - } - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : format = description de l'exécutable à compléter. * -* sym_start = début de la zone à traiter. * -* sym_size = taille de la zone à traiter. * -* str_start = début de la zone de chaîne de caractères. * -* str_size = taille de la zone de chaînes de caractères. * -* * -* Description : Charge en mémoire la liste humaine des symboles (64 bits). * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool load_elf_symbol_table_64(elf_format *format, const off_t *sym_start, const off_t *sym_size, const off_t *str_start, const off_t *str_size) -{ - off_t iter; /* Boucle de parcours */ - Elf64_Sym symbol; /* Symbole ELF lu */ - - if (*sym_size % sizeof(Elf64_Sym) != 0) return false; - - for (iter = *sym_start; iter < (*sym_start + *sym_size); iter += sizeof(Elf64_Sym)) - { - memcpy(&symbol, &EXE_FORMAT(format)->content[iter], sizeof(Elf64_Sym)); - - if (!(ELF64_ST_TYPE(symbol.st_info) == STT_FUNC - || (ELF64_ST_TYPE(symbol.st_info) == STT_NOTYPE - && ELF64_ST_BIND(symbol.st_info) == STB_GLOBAL))) continue; - - if (symbol.st_value == 0) continue; - - /* Sécurité anti-débordements */ - if (symbol.st_name >= *str_size) continue; - - /* Si le symbole possède un nom... */ - if (strlen(&EXE_FORMAT(format)->content[*str_start + symbol.st_name]) > 0) - { - format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol)); - - format->symbols[format->sym_count - 1].name = &EXE_FORMAT(format)->content[*str_start + symbol.st_name]; - format->symbols[format->sym_count - 1].address = symbol.st_value; - - } - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* comments = liste des commentaires à insérer. [OUT] * -* offsets = liste des indices des commentaires. [OUT] * -* count = taille des listes construites. [OUT] * -* * -* Description : Récupère tous les commentaires à insérer dans le code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void get_elf_symbol_comments(const elf_format *format, char ***comments, uint64_t **offsets, size_t *count) -{ - size_t i; /* Boucle de parcours */ - size_t len; /* Longueur d'une désignation */ - - if (format->sym_count > 0) - { - *comments = (char **)calloc(*count + format->sym_count, sizeof(char *)); - *offsets = (uint64_t *)calloc(*count + format->sym_count, sizeof(uint64_t)); - - for (i = 0; i < format->sym_count; i++) - { - len = strlen(format->symbols[i].name); - - (*comments)[i] = (char *)calloc(len + 9, sizeof(char)); - snprintf((*comments)[i], len + 9, "<%s>", format->symbols[i].name); - - (*offsets)[i] = format->symbols[i].address; - - } - - *count += format->sym_count; - - } - -} - - - - - - - - -/* ---------------------------------------------------------------------------------- */ -/* DETAIL DES SYMBOLES EXTERNES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : format = description de l'exécutable à compléter. * -* plt_start = début de la zone à traiter. * -* plt_size = taille de la zone à traiter. * -* dyn_start = début des informations dynamiques associées. * -* dyn_size = taille de la zone associée. * -* str_start = début de la zone de chaîne de caractères. * -* str_size = taille de la zone de chaînes de caractères. * -* * -* Description : Charge en mémoire la liste des symboles dynamiques. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool load_elf_relocation_table(elf_format *format, const off_t *plt_start, const off_t *plt_size, const off_t *dyn_start, const off_t *dyn_size, const off_t *str_start, const off_t *str_size) -{ - off_t iter; /* Boucle de parcours */ - Elf_Rel reloc; /* Infos de relocalisation */ - off_t index; /* Indice de la portion visée */ - char *name; /* Nom du symbole trouvé */ - - for (iter = *plt_start; iter < (*plt_start + *plt_size); iter += ELF_SIZEOF_REL(format)) - { - memcpy(&reloc, &EXE_FORMAT(format)->content[iter], ELF_SIZEOF_REL(format)); - - switch (format->header.e_machine) - { - case EM_386: - switch (ELF32_R_TYPE(ELF_REL_TYPE(format, reloc))) - { - case R_386_JMP_SLOT: - - index = ELF_REL_SYM(format, reloc); - name = get_elf_dynamic_symbol_info(format, dyn_start, dyn_size, &index, str_start, str_size); - - if (name != NULL) - { - format->relocations = (elf_symbol *)realloc(format->relocations, ++format->rel_count * sizeof(elf_symbol)); - - format->relocations[format->rel_count - 1].name = name; - format->relocations[format->rel_count - 1].address = ELF_REL(format, reloc, r_offset); - - } - - break; - - default: - printf("Relocation not supported (%lld) !\n", ELF_REL_TYPE(format, reloc)); - break; - - } - break; - - default: - printf("Machine not recognized !\n"); - return false; - break; - - } - - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : format = description de l'exécutable à compléter. * -* dyn_start = début des informations dynamiques associées. * -* dyn_size = taille de la zone associée. * -* index = indice de l'entrée à venir lire. * -* str_start = début de la zone de chaîne de caractères. * -* str_size = taille de la zone de chaînes de caractères. * -* * -* Description : Récupère les informations d'un symbole dynamique donné. * -* * -* Retour : Nom du symbole trouvé, ou NULL si erreur ou non adapté. * -* * -* Remarques : - * -* * -******************************************************************************/ - -char *get_elf_dynamic_symbol_info(elf_format *format, const off_t *dyn_start, const off_t *dyn_size, const off_t *index, const off_t *str_start, const off_t *str_size) -{ - off_t offset; /* Emplacement à venir lire */ - Elf_Sym symbol; /* Symbole aux infos visées */ - - offset = *dyn_start + *index * ELF_SIZEOF_SYM(format); - if ((offset + ELF_SIZEOF_SYM(format)) > (*dyn_start + *dyn_size)) return NULL; - - memcpy(&symbol, &EXE_FORMAT(format)->content[offset], ELF_SIZEOF_SYM(format)); - - if (ELF_SYM(format, symbol, st_name) >= *str_size) return NULL; - - return (char *)&EXE_FORMAT(format)->content[*str_start + ELF_SYM(format, symbol, st_name)]; - -} 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; + +} diff --git a/src/format/elf/symbol.h b/src/format/elf/symbols.h index 0a8f203..6644cbf 100644 --- a/src/format/elf/symbol.h +++ b/src/format/elf/symbols.h @@ -1,6 +1,6 @@ /* OpenIDA - Outil d'analyse de fichiers binaires - * symbol.h - prototypes pour la gestion des symboles d'un ELF + * symbols.h - prototypes pour la gestion des symboles d'un ELF * * Copyright (C) 2008 Cyrille Bagard * @@ -21,20 +21,16 @@ */ -#ifndef _FORMAT_ELF_SYMBOL_H -#define _FORMAT_ELF_SYMBOL_H +#ifndef _FORMAT_ELF_SYMBOLS_H +#define _FORMAT_ELF_SYMBOLS_H -#include "e_elf.h" - +#include "elf.h" /* Charge en mémoire la liste humaine des symboles. */ -bool load_elf_symbols(elf_format *); - -/* Récupère tous les commentaires à insérer dans le code. */ -void get_elf_symbol_comments(const elf_format *, char ***, uint64_t **, size_t *); +bool load_elf_symbols(GElfFormat *); -#endif /* _FORMAT_ELF_SYMBOL_H */ +#endif /* _FORMAT_ELF_SYMBOLS_H */ diff --git a/src/format/exe_format.h b/src/format/exe_format.h index 32e35ff..b1cbb17 100644 --- a/src/format/exe_format.h +++ b/src/format/exe_format.h @@ -32,6 +32,7 @@ #include "../analysis/prototype.h" +#include "symbol.h" /* ------------------------ MANIPULATION DES PARTIES DE CODE ------------------------ */ @@ -88,7 +89,7 @@ exe_format *load_new_exe_format(const uint8_t *, off_t); - +#if 0 /* Architectures de destination des formats */ typedef enum _FormatTargetMachine { @@ -102,7 +103,6 @@ typedef enum _FormatTargetMachine - /* Types de symbole */ typedef enum _SymbolType { @@ -110,6 +110,7 @@ typedef enum _SymbolType STP_STRING /* Chaîne de caractères */ } SymbolType; +#endif /* Types de symbole */ diff --git a/src/format/executable-int.h b/src/format/executable-int.h new file mode 100644 index 0000000..ca8b7d5 --- /dev/null +++ b/src/format/executable-int.h @@ -0,0 +1,67 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * executable-int.h - prototypes utiles aux formats d'exécutables + * + * 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/>. + */ + + +#ifndef _FORMAT_EXECUTABLE_INT_H +#define _FORMAT_EXECUTABLE_INT_H + + +#include "executable.h" + + +#include "format-int.h" + + + +/* Indique le type d'architecture visée par le format. */ +typedef FormatTargetMachine (* get_target_machine_fc) (const GExeFormat *); + +/* Fournit l'adresse mémoire du point d'entrée du programme. */ +typedef vmpa_t (* get_entry_point_fc) (const GExeFormat *); + +/* Fournit les références aux zones de code à analyser. */ +typedef GBinPart ** (* get_parts_fc) (const GExeFormat *, size_t *); + + + + +/* Format d'exécutable générique (instance) */ +struct _GExeFormat +{ + GBinFormat parent; /* A laisser en premier */ + + get_target_machine_fc get_machine; /* Architecture ciblée */ + get_entry_point_fc get_entry_point; /* Obtention du point d'entrée */ + get_parts_fc get_parts; /* Liste des parties binaires */ + +}; + +/* Format d'exécutable générique (classe) */ +struct _GExeFormatClass +{ + GBinFormatClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _FORMAT_EXECUTABLE_INT_H */ diff --git a/src/format/executable.c b/src/format/executable.c new file mode 100644 index 0000000..4fb6b41 --- /dev/null +++ b/src/format/executable.c @@ -0,0 +1,144 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * executable.c - support des formats d'exécutables + * + * Copyright (C) 2009 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 "executable.h" + + +#include "executable-int.h" +#include "format.h" + + + +/* Initialise la classe des formats d'exécutables génériques. */ +static void g_executable_format_class_init(GExeFormatClass *); + +/* Initialise une instance de format d'exécutable générique. */ +static void g_executable_format_init(GExeFormat *); + + + +/* Indique le type défini pour un format d'exécutable générique. */ +G_DEFINE_TYPE(GExeFormat, g_executable_format, G_TYPE_BIN_FORMAT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des formats d'exécutables génériques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_executable_format_class_init(GExeFormatClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance à initialiser. * +* * +* Description : Initialise une instance de format d'exécutable générique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_executable_format_init(GExeFormat *format) +{ + +} + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Indique le type d'architecture visée par le format. * +* * +* Retour : Identifiant de l'architecture ciblée par le format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +FormatTargetMachine g_exe_format_get_target_machine(const GExeFormat *format) +{ + return format->get_machine(format); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Fournit l'adresse mémoire du point d'entrée du programme. * +* * +* Retour : Adresse de mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +vmpa_t g_exe_format_get_entry_point(const GExeFormat *format) +{ + return format->get_entry_point(format); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = quantité de zones listées. [OUT] * +* * +* Description : Fournit les références aux zones binaires à analyser. * +* * +* Retour : Zones binaires à analyser. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPart **g_exe_format_get_parts(const GExeFormat *format, size_t *count) +{ + return format->get_parts(format, count); + +} diff --git a/src/format/executable.h b/src/format/executable.h new file mode 100644 index 0000000..bf3269d --- /dev/null +++ b/src/format/executable.h @@ -0,0 +1,80 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * executable.h - prototypes pour le support des formats d'exécutables + * + * Copyright (C) 2009 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/>. + */ + + +#ifndef _FORMAT_EXECUTABLE_H +#define _FORMAT_EXECUTABLE_H + + +#include <glib-object.h> + + +#include "part.h" + + + +/* Architectures de destination des formats */ +typedef enum _FormatTargetMachine +{ + FTM_NONE, /* Aucune archi. (reconnue) */ + + FTM_JVM, /* Java Virtual Machine */ + FTM_MIPS, /* Mips 32 ou 64 bits */ + FTM_386, /* Intel 80386 */ + + FTM_COUNT + +} FormatTargetMachine; + + +#define G_TYPE_EXE_FORMAT g_executable_format_get_type() +#define G_EXE_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_executable_format_get_type(), GExeFormat)) +#define G_IS_EXE_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_executable_format_get_type())) +#define G_EXE_FORMAT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_executable_format_get_type(), GExeFormatIface)) +#define G_EXE_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_EXE_FORMAT, GExeFormatClass)) + + +/* Format d'exécutable générique (instance) */ +typedef struct _GExeFormat GExeFormat; + +/* Format d'exécutable générique (classe) */ +typedef struct _GExeFormatClass GExeFormatClass; + + +/* Indique le type défini pour un format d'exécutable générique. */ +GType g_executable_format_get_type(void); + + + + +/* Indique le type d'architecture visée par le format. */ +FormatTargetMachine g_exe_format_get_target_machine(const GExeFormat *); + +/* Fournit l'adresse mémoire du point d'entrée du programme. */ +vmpa_t g_exe_format_get_entry_point(const GExeFormat *); + +/* Fournit les références aux zones binaires à analyser. */ +GBinPart **g_exe_format_get_parts(const GExeFormat *, size_t *); + + + +#endif /* _FORMAT_EXECUTABLE_H */ diff --git a/src/format/format-int.h b/src/format/format-int.h new file mode 100644 index 0000000..13eb50a --- /dev/null +++ b/src/format/format-int.h @@ -0,0 +1,64 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * format-int.h - prototypes utiles aux formats binaires + * + * Copyright (C) 2009 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/>. + */ + + +#ifndef _FORMAT_FORMAT_INT_H +#define _FORMAT_FORMAT_INT_H + + +#include "format.h" + + + +/* ------------------------ TRAITEMENT INDIVIDUEL DE FORMATS ------------------------ */ + + +/* Format binaire générique (instance) */ +struct _GBinFormat +{ + GObject parent; /* A laisser en premier */ + + const bin_t *content; /* Contenu binaire à étudier */ + off_t length; /* Taille de ce contenu */ + + GBinSymbol **symbols; /* Liste des symboles trouvés */ + size_t symbols_count; /* Quantité de ces symboles */ + + GBinRoutine **routines; /* Liste des routines trouvées */ + size_t routines_count; /* Nombre de ces routines */ + +}; + +/* Format binaire générique (classe) */ +struct _GBinFormatClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Définit le contenu binaire à analyser. */ +void g_binary_format_set_content(GBinFormat *, bin_t *, off_t); + + + +#endif /* _FORMAT_FORMAT_INT_H */ diff --git a/src/format/format.c b/src/format/format.c new file mode 100644 index 0000000..912cdd7 --- /dev/null +++ b/src/format/format.c @@ -0,0 +1,375 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * format.c - support des différents formats binaires + * + * Copyright (C) 2009 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 "format.h" + + +#include <malloc.h> + + +#include "format-int.h" +#include "dwarf/dwarf.h" +#include "elf/elf.h" +#include "../panel/log.h" + + + +#ifndef _ +# define _(str) str +#endif + + + + +/* ------------------------ TRAITEMENT INDIVIDUEL DE FORMATS ------------------------ */ + + +/* Initialise la classe des formats binaires génériques. */ +static void g_binary_format_class_init(GBinFormatClass *); + +/* Initialise une instance de format binaire générique. */ +static void g_binary_format_init(GBinFormat *); + + + +/* ----------------------- MANIPULATION D'ENSEMBLE DE FORMATS ----------------------- */ + + +/* Format d'exécutables enregistré */ +typedef struct _registered_format +{ + const char *name; /* Désignation du format */ + + FormatType type; /* Type de format */ + + format_match_fc match; /* Procédure de reconnaissance */ + format_load_fc load; /* Fonction de chargement */ + +} registered_format; + + +/* Liste des formats d'exécutables enregistrés */ +static registered_format _formats[FID_COUNT]; + + +#define register_format(id, n, t, m, l) \ + do \ + { \ + _formats[id].name = n; \ + _formats[id].type = t; \ + _formats[id].match = m; \ + _formats[id].load = l; \ + } \ + while (0) + + + +/* ---------------------------------------------------------------------------------- */ +/* TRAITEMENT INDIVIDUEL DE FORMATS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un format binaire générique. */ +G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des formats binaires génériques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_format_class_init(GBinFormatClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance à initialiser. * +* * +* Description : Initialise une instance de format binaire générique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_format_init(GBinFormat *format) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* content = contenu binaire à parcourir. * +* length = taille du contenu fourni. * +* * +* Description : Définit le contenu binaire à analyser. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_format_set_content(GBinFormat *format, bin_t *content, off_t length) +{ + format->content = content; + format->length = length; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* length = taille du contenu à fournir. [OUT] * +* * +* Description : Fournit une référence vers le contenu binaire analysé. * +* * +* Retour : Adresse du tampon contenant le contenu du binaire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const bin_t *g_binary_format_get_content(const GBinFormat *format, off_t *length) +{ + if (length != NULL) *length = format->length; + + return format->content; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à compléter. * +* symbol = symbole à ajouter à la liste. * +* * +* Description : Ajoute un symbole à la collection du format binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol) +{ + format->symbols = (GBinSymbol **)realloc(format->symbols, + ++format->symbols_count * sizeof(GBinSymbol *)); + + format->symbols[format->symbols_count - 1] = symbol; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = taille du tableau créé. [OUT] * +* * +* Description : Fournit la liste de tous les symboles détectés. * +* * +* Retour : Tableau créé ou NULL si aucun symbole trouvé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol **g_binary_format_get_symbols(const GBinFormat *format, size_t *count) +{ + *count = format->symbols_count; + + return format->symbols; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à compléter. * +* routine = routine à ajouter à la liste. * +* * +* Description : Ajoute une routine à la collection du format binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_format_add_routine(GBinFormat *format, GBinRoutine *routine) +{ + format->routines = (GBinRoutine **)realloc(format->routines, + ++format->routines_count * sizeof(GBinRoutine *)); + + format->routines[format->routines_count - 1] = routine; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = taille du tableau créé. [OUT] * +* * +* Description : Fournit le prototype de toutes les routines détectées. * +* * +* Retour : Tableau créé ou NULL si aucun symbole de routine trouvé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinRoutine **g_binary_format_get_routines(const GBinFormat *format, size_t *count) +{ + *count = format->routines_count; + + return format->routines; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* label = étiquette du symbole si trouvé. [OUT] * +* type = type du symbole trouvé. [OUT] * +* address = adresse à cibler, puis décallage final. [OUT] * +* * +* Description : Recherche le symbole correspondant à une adresse. * +* * +* Retour : true si l'opération a été un succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_format_resolve_symbol(const GBinFormat *format, const char **label, SymbolType *type, vmpa_t *address) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + vmpa_t addr; /* Adresse de symbole */ + off_t size; /* Taille du symole */ + + result = false; + + for (i = 0; i < format->symbols_count && !result; i++) + { + addr = g_binary_symbol_get_address(format->symbols[i]); + size = g_binary_symbol_get_size(format->symbols[i]); + + if (addr <= *address && *address < (addr + size)) + { + *label = g_binary_symbol_to_string(format->symbols[i]); + *type = g_binary_symbol_get_target_type(format->symbols[i]); + *address -= addr; + + if (*type == STP_STRING) + *label += *address; + + result = true; + + } + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION D'ENSEMBLE DE FORMATS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Procède au chargement des formats binaires reconnus. * +* * +* Retour : true pour indiquer un chargement réussi, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_all_formats(void) +{ + register_format(FID_ELF, _("ELF"), FMT_EXEC, elf_is_matching, g_elf_format_new); + register_format(FID_DWARF, _("Dwarf"), FMT_DEBUG, dwarf_is_matching, g_dwarf_format_new); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type de format recherché. * +* content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Charge si possible un nouveau format binaire. * +* * +* Retour : Adresse du nouveau gestionnaire de format ou NULL si erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinFormat *load_new_format(FormatType type, const uint8_t *content, off_t length) +{ + GBinFormat *result; /* Adresse à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + for (i = 0; i < FID_COUNT && result == NULL; i++) + if (_formats[i].type == type && _formats[i].match(type, content, length)) + { + log_variadic_message(LMT_INFO, _("%s is matching..."), _formats[i].name); + + result = _formats[i].load(content, length); + + } + + return result; + +} diff --git a/src/format/format.h b/src/format/format.h new file mode 100644 index 0000000..c485e0b --- /dev/null +++ b/src/format/format.h @@ -0,0 +1,114 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * format.h - prototypes pour le support des différents formats binaires + * + * Copyright (C) 2009 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/>. + */ + + +#ifndef _FORMAT_FORMAT_H +#define _FORMAT_FORMAT_H + + +#include <glib-object.h> +#include <stdbool.h> +#include <sys/types.h> + + +#include "symbol.h" + + + +/* ------------------------ TRAITEMENT INDIVIDUEL DE FORMATS ------------------------ */ + + +#define G_TYPE_BIN_FORMAT g_binary_format_get_type() +#define G_BIN_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_binary_format_get_type(), GBinFormat)) +#define G_IS_BIN_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_binary_format_get_type())) +#define G_BIN_FORMAT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_binary_format_get_type(), GBinFormatIface)) +#define G_BIN_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_FORMAT, GBinFormatClass)) + + +/* Format binaire générique (instance) */ +typedef struct _GBinFormat GBinFormat; + +/* Format binaire générique (classe) */ +typedef struct _GBinFormatClass GBinFormatClass; + + +/* Indique le type défini pour un format binaire générique. */ +GType g_binary_format_get_type(void); + +/* Fournit une référence vers le contenu binaire analysé. */ +const bin_t *g_binary_format_get_content(const GBinFormat *, off_t *); + +/* Ajoute un symbole à la collection du format binaire. */ +void g_binary_format_add_symbol(GBinFormat *, GBinSymbol *); + +/* Fournit la liste de tous les symboles détectés. */ +GBinSymbol **g_binary_format_get_symbols(const GBinFormat *, size_t *); + +/* Ajoute une routine à la collection du format binaire. */ +void g_binary_format_add_routine(GBinFormat *, GBinRoutine *); + +/* Fournit le prototype de toutes les routines détectées. */ +GBinRoutine **g_binary_format_get_routines(const GBinFormat *, size_t *); + +/* Recherche le symbole correspondant à une adresse. */ +bool g_binary_format_resolve_symbol(const GBinFormat *, const char **, SymbolType *, vmpa_t *); + + + +/* ----------------------- MANIPULATION D'ENSEMBLE DE FORMATS ----------------------- */ + + +/* Identifiants pour les différents formats */ +typedef enum _FormatIdentifier +{ + FID_ELF, /* Format ELF */ + FID_DWARF, /* Format Dwarf */ + + FID_COUNT + +} FormatIdentifier; + +/* Spécialité des formats */ +typedef enum _FormatType +{ + FMT_EXEC = (1 << 0), /* Format d'exécutable */ + FMT_DEBUG = (1 << 1) /* Format de débogage */ + +} FormatType; + + +/* Indication à propos du support d'un format */ +typedef bool (* format_match_fc) (FormatType, const bin_t *, off_t); + +/* Méthode de chargement d'un format */ +typedef GBinFormat * (* format_load_fc) (const bin_t *, off_t); + + +/* Procède au chargement des formats binaires reconnus. */ +bool init_all_formats(void); + +/* Charge si possible un nouveau format binaire. */ +GBinFormat *load_new_format(FormatType, const uint8_t *, off_t); + + + +#endif /* _FORMAT_FORMAT_H */ diff --git a/src/format/part.c b/src/format/part.c new file mode 100644 index 0000000..2096c6d --- /dev/null +++ b/src/format/part.c @@ -0,0 +1,217 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * part.h - manipulation des parties de code + * + * Copyright (C) 2009 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 "part.h" + + +#include <malloc.h> +#include <string.h> + + + +/* Bloc de données binaires quelconques (instance) */ +struct _GBinPart +{ + GObject parent; /* A laisser en premier */ + + char *name; /* Désignation humaine */ + + off_t offset; /* Position physique */ + off_t size; /* Taille de la partie */ + vmpa_t addr; /* Adresse associée */ + +}; + +/* Bloc de données binaires quelconques (classe) */ +struct _GBinPartClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des blocs de données binaires. */ +static void g_binary_part_class_init(GBinPartClass *); + +/* Initialise une instance de bloc de données binaires. */ +static void g_binary_part_init(GBinPart *); + + + +/* Indique le type défini par la GLib pour les blocs de doonées. */ +G_DEFINE_TYPE(GBinPart, g_binary_part, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des blocs de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_part_class_init(GBinPartClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : line = instance à initialiser. * +* * +* Description : Initialise une instance de bloc de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_part_init(GBinPart *line) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une description de partie de code vierge. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPart *g_binary_part_new(void) +{ + GBinPart *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BIN_PART, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : part = description de partie à mettre à jour. * +* name = nom à donner à la partie. * +* * +* Description : Attribue une description humaine à une partie de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_part_set_name(GBinPart *part, const char *name) +{ + if (part->name != NULL) free(part->name); + + part->name = strdup(name); + +} + + +/****************************************************************************** +* * +* Paramètres : part = description de partie à mettre à jour. * +* offset = position de la section à conserver. * +* size = taille de la section à conserver. * +* addr = adresse de la section à conserver. * +* * +* Description : Définit les valeurs utiles d'une partie de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_part_set_values(GBinPart *part, off_t offset, off_t size, vmpa_t addr) +{ + part->offset = offset; + part->size = size; + part->addr = addr; + +} + + +/****************************************************************************** +* * +* Paramètres : part = description de partie à consulter. * +* offset = position de la section à donner ou NULL. [OUT] * +* size = taille de la section à donner ou NULL. [OUT] * +* addr = adresse de la section à donner ou NULL. [OUT] * +* * +* Description : Fournit les valeurs utiles d'une partie de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_part_get_values(const GBinPart *part, off_t *offset, off_t *size, vmpa_t *addr) +{ + if (offset != NULL) *offset = part->offset; + if (size != NULL) *size = part->size; + if (addr != NULL) *addr = part->addr; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premières informations à consulter. * +* b = secondes informations à consulter. * +* * +* Description : Etablit la comparaison entre deux blocs binaires. * +* * +* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_binary_part_compare(const GBinPart **a, const GBinPart **b) +{ + int result; /* Bilan à renvoyer */ + + if ((*a)->offset < (*b)->offset) result = -1; + else if((*a)->offset > (*b)->offset) result = 1; + else result = 0; + + return result; + +} diff --git a/src/format/part.h b/src/format/part.h new file mode 100644 index 0000000..aec324d --- /dev/null +++ b/src/format/part.h @@ -0,0 +1,71 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * part.h - prototypes pour la manipulation des parties de code + * + * Copyright (C) 2009 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/>. + */ + + +#ifndef _FORMAT_PART_H +#define _FORMAT_PART_H + + +#include <glib-object.h> +#include <sys/types.h> + + +#include "../arch/archbase.h" + + + +#define G_TYPE_BIN_PART (g_binary_part_get_type()) +#define G_BIN_PART(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BIN_PART, GBinPart)) +#define G_IS_BIN_PART(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BIN_PART)) +#define G_BIN_PART_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BIN_PART, GBinPartClass)) +#define G_IS_BIN_PART_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BIN_PART)) +#define G_BIN_PART_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_PART, GBinPartClass)) + + +/* Bloc de données binaires quelconques (instance) */ +typedef struct _GBinPart GBinPart; + +/* Bloc de données binaires quelconques (classe) */ +typedef struct _GBinPartClass GBinPartClass; + + +/* Indique le type défini par la GLib pour les blocs de doonées. */ +GType g_binary_part_get_type(void); + +/* Crée une description de partie de code vierge. */ +GBinPart *g_binary_part_new(void); + +/* Attribue une description humaine à une partie de code. */ +void g_binary_part_set_name(GBinPart *, const char *); + +/* Définit les valeurs utiles d'une partie de code. */ +void g_binary_part_set_values(GBinPart *, off_t, off_t, vmpa_t); + +/* Fournit les valeurs utiles d'une partie de code. */ +void g_binary_part_get_values(const GBinPart *, off_t *, off_t *, vmpa_t *); + +/* Etablit la comparaison entre deux blocs binaires. */ +int g_binary_part_compare(const GBinPart **, const GBinPart **); + + + +#endif /* _FORMAT_PART_H */ diff --git a/src/format/symbol.c b/src/format/symbol.c new file mode 100644 index 0000000..40efdd2 --- /dev/null +++ b/src/format/symbol.c @@ -0,0 +1,265 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * symbol.c - gestion des symboles dans un binaire + * + * Copyright (C) 2009 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 "symbol.h" + + +#include <string.h> + + + +/* Symbole d'exécutable (instance) */ +struct _GBinSymbol +{ + GObject parent; /* A laisser en premier */ + + SymbolType type; /* Type du symbole */ + + const char *name; /* Désignation du symbole */ + vmpa_t address; /* Adresse du symbole */ + + char *alt; /* Nom alternatif */ + + union + { + GBinRoutine *routine; /* Compléments pour fonction */ + + } extra; + +}; + +/* Symbole d'exécutable (classe) */ +struct _GBinSymbolClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des symboles d'exécutables. */ +static void g_binary_symbol_class_init(GBinSymbolClass *); + +/* Initialise une instance de symbole d'exécutable. */ +static void g_binary_symbol_init(GBinSymbol *); + + + +/* Indique le type défini pour un symbole d'exécutable. */ +G_DEFINE_TYPE(GBinSymbol, g_binary_symbol, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des symboles d'exécutables. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_symbol_class_init(GBinSymbolClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = instance à initialiser. * +* * +* Description : Initialise une instance de symbole d'exécutable. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_symbol_init(GBinSymbol *symbol) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : type = type de symbole à créer. * +* name = désignation humaine du symbole. * +* address = adresse associée au symbole. * +* * +* Description : Crée un nouveau symbole d'exécutable. * +* * +* Retour : Adresse de l'instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *g_binary_symbol_new(SymbolType type, const char *name, vmpa_t address) +{ + GBinSymbol *result; /* Nouveau symbole à renvoyer */ + + result = g_object_new(G_TYPE_BIN_SYMBOL, NULL); + + result->type = type; + result->name = name; + result->address = address; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = symbole à venir consulter. * +* * +* Description : Fournit le type du symbole. * +* * +* Retour : Type de symbole représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +SymbolType g_binary_symbol_get_target_type(const GBinSymbol *symbol) +{ + return symbol->type; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = symbole à venir consulter. * +* * +* Description : Fournit la description humaine du symbole. * +* * +* Retour : Nom du symbole sous forme de chaîne de caractères. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_binary_symbol_to_string(const GBinSymbol *symbol) +{ + return (symbol->alt != NULL ? symbol->alt : symbol->name); + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = symbole à venir consulter. * +* * +* Description : Fournit l'adresse associée à un symbole. * +* * +* Retour : Adresse virtuelle ou physique associée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +vmpa_t g_binary_symbol_get_address(const GBinSymbol *symbol) +{ + return symbol->address; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = symbole à venir consulter. * +* * +* Description : Fournit la taille officielle d'un symbole. * +* * +* Retour : Taille de symbole. * +* * +* Remarques : - * +* * +******************************************************************************/ + +off_t g_binary_symbol_get_size(const GBinSymbol *symbol) +{ + off_t result; /* Taille à renvoyer */ + + switch (symbol->type) + { + case STP_OBJECT: + result = 1; /* FIXME */ + break; + case STP_FUNCTION: + /* FIXME */if (symbol->extra.routine == NULL) result = 1; else + result = g_binary_routine_get_size(symbol->extra.routine); + break; + case STP_STRING: + result = strlen(g_binary_symbol_to_string(symbol)); + break; + } + + return result;; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = symbole à venir consulter. * +* alt = désignation humaine alternative à favoriser. * +* * +* Description : Définit un autre nom pour le symbole. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_symbol_set_alt_name(GBinSymbol *symbol, char *alt) +{ + return symbol->alt = alt; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = symbole à venir consulter. * +* routine = prototype de la fonction représentée. * +* * +* Description : Attache la routine associée au symbole. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine) +{ + symbol->extra.routine = routine; + +} diff --git a/src/format/symbol.h b/src/format/symbol.h new file mode 100644 index 0000000..f4fe299 --- /dev/null +++ b/src/format/symbol.h @@ -0,0 +1,83 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * symbol.h - prototypes pour la gestion des symboles dans un binaire + * + * Copyright (C) 2009 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/>. + */ + + +#ifndef _FORMAT_SYMBOL_H +#define _FORMAT_SYMBOL_H + + +#include <glib-object.h> + + +#include "../analysis/prototype.h" +#include "../arch/archbase.h" + + + +/* Types de symbole */ +typedef enum _SymbolType +{ + STP_OBJECT, /* Objet quelconque */ + STP_FUNCTION, /* Simple morceau de code */ + STP_STRING /* Chaîne de caractères */ + +} SymbolType; + + +#define G_TYPE_BIN_SYMBOL g_binary_symbol_get_type() +#define G_BIN_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_binary_symbol_get_type(), GBinSymbol)) +#define G_IS_BIN_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_binary_symbol_get_type())) +#define G_BIN_SYMBOL_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_binary_symbol_get_type(), GBinSymbolIface)) +#define G_BIN_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_SYMBOL, GBinSymbolClass)) + + +/* Symbole d'exécutable (instance) */ +typedef struct _GBinSymbol GBinSymbol; + +/* Symbole d'exécutable (classe) */ +typedef struct _GBinSymbolClass GBinSymbolClass; + + +/* Indique le type défini pour un symbole d'exécutable. */ +GType g_binary_symbol_get_type(void); + +/* Crée un nouveau symbole d'exécutable. */ +GBinSymbol *g_binary_symbol_new(SymbolType, const char *, vmpa_t); + +/* Fournit le type du symbole. */ +SymbolType g_binary_symbol_get_target_type(const GBinSymbol *); + +/* Fournit la description humaine du symbole. */ +const char *g_binary_symbol_to_string(const GBinSymbol *); + +/* Fournit l'adresse associée à un symbole. */ +vmpa_t g_binary_symbol_get_address(const GBinSymbol *); + +/* Fournit la taille officielle d'un symbole. */ +off_t g_binary_symbol_get_size(const GBinSymbol *); + +/* Définit un autre nom pour le symbole. */ +void g_binary_symbol_set_alt_name(GBinSymbol *, char *); + + + +#endif /* _FORMAT_SYMBOL_H */ |