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/elf/elf.c | |
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/elf/elf.c')
-rw-r--r-- | src/format/elf/elf.c | 444 |
1 files changed, 444 insertions, 0 deletions
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; + +} |