From a6acb5629572e6da4d72f4419b01672c2ea5ddf2 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 11 Mar 2010 22:40:17 +0000 Subject: Added first steps for a full PE support. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@143 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 34 ++++ src/format/Makefile.am | 5 +- src/format/elf/elf.c | 3 +- src/format/format.c | 2 + src/format/format.h | 1 + src/format/pe/Makefile.am | 7 +- src/format/pe/e_pe.c | 138 ----------------- src/format/pe/e_pe.h | 47 ------ src/format/pe/pe-int.c | 359 ++++++++++++++++++++++++++++++++++++++++++ src/format/pe/pe-int.h | 96 ++++-------- src/format/pe/pe.c | 386 ++++++++++++++++++++++++++++++++++++++++++++++ src/format/pe/pe.h | 62 ++++++++ src/format/pe/pe_def.h | 343 ++++++++++++++++++++++++++++++++++++++++ src/format/pe/section.c | 59 +++++++ src/format/pe/section.h | 38 +++++ src/format/pe/symbols.c | 136 ++++++++++++++++ src/format/pe/symbols.h | 36 +++++ 17 files changed, 1496 insertions(+), 256 deletions(-) delete mode 100644 src/format/pe/e_pe.c delete mode 100644 src/format/pe/e_pe.h create mode 100644 src/format/pe/pe-int.c create mode 100644 src/format/pe/pe.c create mode 100644 src/format/pe/pe.h create mode 100644 src/format/pe/pe_def.h create mode 100644 src/format/pe/section.c create mode 100644 src/format/pe/section.h create mode 100644 src/format/pe/symbols.c create mode 100644 src/format/pe/symbols.h diff --git a/ChangeLog b/ChangeLog index 1a1ff62..08af014 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +10-03-11 Cyrille Bagard + + * src/format/elf/elf.c: + Typo. + + * src/format/format.c: + * src/format/format.h: + Include PE as a valid executable format. + + * src/format/Makefile.am: + Add pe/libformatpe.la to libformat_la_LIBADD. + + * src/format/pe/e_pe.c: + * src/format/pe/e_pe.h: + Deleted entries ; see the pe.[ch] files instead. + + * src/format/pe/Makefile.am: + * src/format/pe/pe.c: + * src/format/pe/pe_def.h: + * src/format/pe/pe.h: + * src/format/pe/pe-int.c: + * src/format/pe/pe-int.h: + * src/format/pe/section.c: + * src/format/pe/section.h: + * src/format/pe/symbols.c: + * src/format/pe/symbols.h: + Add first steps for a full PE support. + +10-02-23 Cyrille Bagard + + * src/analysis/binary.c: + * src/gtkext/gtkblockview.c: + Avoid crashes when loading unrecognized files. + 10-01-02 Cyrille Bagard * src/analysis/binary.c: diff --git a/src/format/Makefile.am b/src/format/Makefile.am index 838cb99..82264bb 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -23,7 +23,8 @@ libformat_la_SOURCES = \ libformat_la_LIBADD = \ dwarf/libformatdwarf.la \ elf/libformatelf.la \ - mangling/libformatmangling.la + mangling/libformatmangling.la \ + pe/libformatpe.la # libformat_la_LIBADD = \ # dwarf/libformatdwarf.la \ @@ -41,5 +42,5 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = dwarf elf mangling +SUBDIRS = dwarf elf mangling pe #SUBDIRS = dwarf elf java mangling pe diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index b703dcf..e7bb48c 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -134,7 +134,7 @@ static void g_elf_format_class_init(GElfFormatClass *klass) static void g_elf_format_init(GElfFormat *format) { - GExeFormat *exe_format; + GExeFormat *exe_format; /* Format parent à constituer */ exe_format = G_EXE_FORMAT(format); @@ -436,7 +436,6 @@ static GBinPart **g_elf_format_get_parts(const GElfFormat *format, size_t *count if (!find_elf_section_by_index(format, i, §ion)) continue; - if (ELF_SHDR(format, section, sh_flags) & SHF_EXECINSTR) { part = g_binary_part_new(); diff --git a/src/format/format.c b/src/format/format.c index 0ffbfe0..00c4538 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -30,6 +30,7 @@ #include "format-int.h" #include "dwarf/dwarf.h" #include "elf/elf.h" +#include "pe/pe.h" #include "../panels/log.h" @@ -334,6 +335,7 @@ 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); + register_format(FID_PE, _("PE"), FMT_EXEC, pe_is_matching, g_pe_format_new); return true; diff --git a/src/format/format.h b/src/format/format.h index a4de552..ccd3ee7 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -83,6 +83,7 @@ typedef enum _FormatIdentifier { FID_ELF, /* Format ELF */ FID_DWARF, /* Format Dwarf */ + FID_PE, /* Format PE */ FID_COUNT diff --git a/src/format/pe/Makefile.am b/src/format/pe/Makefile.am index 45f2f6b..c977653 100755 --- a/src/format/pe/Makefile.am +++ b/src/format/pe/Makefile.am @@ -2,8 +2,11 @@ noinst_LTLIBRARIES = libformatpe.la libformatpe_la_SOURCES = \ - e_pe.h e_pe.c \ - pe-int.h + pe-int.h pe-int.c \ + pe.h pe.c \ + pe_def.h \ + section.h section.c \ + symbols.h symbols.c libformatpe_la_LDFLAGS = diff --git a/src/format/pe/e_pe.c b/src/format/pe/e_pe.c deleted file mode 100644 index a10f075..0000000 --- a/src/format/pe/e_pe.c +++ /dev/null @@ -1,138 +0,0 @@ - -/* OpenIDA - Outil d'analyse de fichiers binaires - * e_pe.c - support du format Portable Executable - * - * 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 . - */ - - -#include "e_pe.h" - - -#include -#include - - -#include "pe-int.h" - - - -/****************************************************************************** -* * -* 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 pe_is_matching(const uint8_t *content, off_t length) -{ - bool result; /* Bilan à faire connaître */ - image_dos_header dos_header; /* En-tête DOS */ - - result = false; - - if (length >= 2) - { - result = (strncmp((const char *)content, "\x4d\x5a" /* MZ */, 2) == 0); - result &= length >= sizeof(image_dos_header); - } - - if (result) - { - memcpy(&dos_header, content, sizeof(image_dos_header)); - - result = length >= (dos_header.e_lfanew + 4); - - result &= (strncmp((const char *)&content[dos_header.e_lfanew], - "\x50\x45\x00\x00" /* PE00 */, 4) == 0); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : content = contenu binaire à parcourir. * -* length = taille du contenu en question. * -* * -* Description : Prend en charge une nouvelle classe PE. * -* * -* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* -* * -* Remarques : - * -* * -******************************************************************************/ - -exe_format *load_pe(const uint8_t *content, off_t length) -{ - pe_format *result; /* Adresse à retourner */ - off_t pos; /* Point d'analyse */ - - result = (pe_format *)calloc(1, sizeof(pe_format)); - - EXE_FORMAT(result)->content = content; - EXE_FORMAT(result)->length = length; - - pos = 0; - - - - - - - return EXE_FORMAT(result); - - ldp_error: - - unload_pe(result); - - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : format = description de l'exécutable à supprimer. * -* * -* Description : Efface la prise en charge une nouvelle classe PE. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void unload_pe(pe_format *format) -{ - - - - - free(format); - -} diff --git a/src/format/pe/e_pe.h b/src/format/pe/e_pe.h deleted file mode 100644 index 54820e2..0000000 --- a/src/format/pe/e_pe.h +++ /dev/null @@ -1,47 +0,0 @@ - -/* OpenIDA - Outil d'analyse de fichiers binaires - * e_pe.h - prototypes pour le support du format Portable Executable - * - * 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 . - */ - - -#ifndef _FORMAT_PE_E_PE_H -#define _FORMAT_PE_E_PE_H - - -#include "../exe_format.h" - - - -/* Description du format Pe */ -typedef struct _pe_format pe_format; - - -/* Indique si le format peut être pris en charge ici. */ -bool pe_is_matching(const uint8_t *, off_t); - -/* Prend en charge une nouvelle classe PE. */ -exe_format *load_pe(const uint8_t *, off_t); - -/* Efface la prise en charge une nouvelle classe PE. */ -void unload_pe(pe_format *); - - - -#endif /* _FORMAT_PE_E_PE_H */ diff --git a/src/format/pe/pe-int.c b/src/format/pe/pe-int.c new file mode 100644 index 0000000..3db8318 --- /dev/null +++ b/src/format/pe/pe-int.c @@ -0,0 +1,359 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * pe-int.c - structures internes du format Portable Executable + * + * Copyright (C) 2010 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 . + */ + + +#include "pe-int.h" + + +#include +#include + + +#include "../../common/endianness.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 DOS. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dos_image_header(const GPeFormat *format, off_t *pos, image_dos_header *header) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + size_t i; /* Boucle de parcours */ + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result = read_u16(&header->e_magic, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_cblp, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_cp, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_crlc, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_cparhdr, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_minalloc, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_maxalloc, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_ss, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_sp, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_csum, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_ip, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_cs, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_lfarlc, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_ovno, content, pos, length, SRE_LITTLE); + + for (i = 0; i < 4 && result; i++) + result = read_u16(&header->e_res[i], content, pos, length, SRE_LITTLE); + + result &= read_u16(&header->e_oemid, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->e_oeminfo, content, pos, length, SRE_LITTLE); + + for (i = 0; i < 10 && result; i++) + result = read_u16(&header->e_res2[i], content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->e_lfanew, content, pos, length, SRE_LITTLE); + + return result; + +} + + +/****************************************************************************** +* * +* 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 PE (1). * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_pe_file_header(const GPeFormat *format, off_t *pos, image_file_header *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; + + result = read_u16(&header->machine, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->number_of_sections, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->time_date_stamp, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->pointer_to_symbol_table, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->number_of_symbols, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->size_of_optional_header, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->characteristics, content, pos, length, SRE_LITTLE); + + return result; + +} + + +/****************************************************************************** +* * +* 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 PE (2). * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_pe_optional_header(const GPeFormat *format, off_t *pos, image_optional_header *header) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint32_t i; /* Boucle de parcours */ + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result = read_u16(&header->magic, content, pos, length, SRE_LITTLE); + result &= read_u8(&header->major_linker_version, content, pos, length, SRE_LITTLE); + result &= read_u8(&header->minor_linker_version, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_code, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_initialized_data, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_uninitialized_data, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->address_of_entry_point, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->base_of_code, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->base_of_data, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->image_base, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->section_alignment, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->file_alignment, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->major_operating_system_version, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->minor_operating_system_version, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->major_image_version, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->minor_image_version, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->major_subsystem_version, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->minor_subsystem_version, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->win32_version_value, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_image, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_headers, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->subsystem, content, pos, length, SRE_LITTLE); + result &= read_u16(&header->dll_characteristics, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_stack_reserve, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_stack_commit, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_heap_reserve, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->size_of_heap_commit, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->loader_flags, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->number_of_rva_and_sizes, content, pos, length, SRE_LITTLE); + + for (i = 0; i < header->number_of_rva_and_sizes && result; i++) + { + result = read_u32(&header->data_directory[i].virtual_address, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->data_directory[i].size, content, pos, length, SRE_LITTLE); + } + + return result; + +} + + +/****************************************************************************** +* * +* 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 PE. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_pe_nt_header(const GPeFormat *format, off_t *pos, image_nt_headers *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; + + result = read_u32(&header->signature, content, pos, length, SRE_LITTLE); + + result &= read_pe_file_header(format, pos, &header->file_header); + result &= read_pe_optional_header(format, pos, &header->optional_header); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* section = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une en-tête de section PE. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_pe_image_section_header(const GPeFormat *format, off_t *pos, image_section_header *section) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + size_t i; /* Boucle de parcours */ + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result = true; + + for (i = 0; i < IMAGE_SIZEOF_SHORT_NAME && result; i++) + result = read_u8((uint8_t *)§ion->name[i], content, pos, length, SRE_LITTLE); + + result &= read_u32(§ion->misc.physical_address, content, pos, length, SRE_LITTLE); + + result &= read_u32(§ion->virtual_address, content, pos, length, SRE_LITTLE); + result &= read_u32(§ion->size_of_raw_data, content, pos, length, SRE_LITTLE); + result &= read_u32(§ion->pointer_to_raw_data, content, pos, length, SRE_LITTLE); + result &= read_u32(§ion->pointer_to_relocations, content, pos, length, SRE_LITTLE); + result &= read_u32(§ion->pointer_to_line_numbers, content, pos, length, SRE_LITTLE); + result &= read_u16(§ion->number_of_relocations, content, pos, length, SRE_LITTLE); + result &= read_u16(§ion->number_of_line_numbers, content, pos, length, SRE_LITTLE); + result &= read_u32(§ion->characteristics, content, pos, length, SRE_LITTLE); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* desc = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un répertoire de programme PE. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_pe_image_import_descriptor(const GPeFormat *format, off_t *pos, image_import_descriptor *desc) +{ + 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; + + result = read_u32(&desc->original_first_thunk, content, pos, length, SRE_LITTLE); + result &= read_u32(&desc->time_date_stamp, content, pos, length, SRE_LITTLE); + result &= read_u32(&desc->forwarder_chain, content, pos, length, SRE_LITTLE); + result &= read_u32(&desc->module_name, content, pos, length, SRE_LITTLE); + result &= read_u32(&desc->first_thunk, content, pos, length, SRE_LITTLE); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* import = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une fonction importée par son nom. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_pe_image_import_by_name(const GPeFormat *format, off_t *pos, image_import_by_name *import) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint32_t link; /* Lien vers la prochaine zone */ + off_t new_pos; /* Nouvelle tête de lecture */ + size_t i; /* Boucle de parcours */ + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result = read_u32(&link, content, pos, length, SRE_LITTLE); + + if (link == 0) + memset(import, 0, sizeof(image_import_by_name)); + + else if (link % 2 == 0) + { + new_pos = link; + + result = read_u16(&import->hint, content, &new_pos, length, SRE_LITTLE); + + import->name = (char *)calloc(1, sizeof(char)); + + for (i = 0; result; i++) + { + result = read_u8((uint8_t *)&import->name[i], content, &new_pos, length, SRE_LITTLE); + + if (import->name[i] == '\0') + break; + + import->name = (char *)realloc(import->name, (i + 2) * sizeof(char)); + + } + + } + else /* TODO */; + + return result; + +} diff --git a/src/format/pe/pe-int.h b/src/format/pe/pe-int.h index 8b18055..3322f62 100644 --- a/src/format/pe/pe-int.h +++ b/src/format/pe/pe-int.h @@ -25,7 +25,9 @@ #define _FORMAT_PE_E_PE_INT_H -#include "../exe_format-int.h" +#include "pe.h" +#include "pe_def.h" +#include "../executable-int.h" @@ -33,85 +35,49 @@ +/* Format d'exécutable générique (instance) */ +struct _GPeFormat +{ + GExeFormat parent; /* A laisser en premier */ + image_dos_header dos_header; /* En-tête DOS */ + image_nt_headers nt_headers; /* En-tête Windows */ + off_t section_offset; /* Début des sections */ +}; +/* Format d'exécutable générique (classe) */ +struct _GPeFormatClass +{ + GExeFormatClass parent; /* A laisser en premier */ +}; -/* ---------------------------- DESCRIPTION DU FORMAT PE ---------------------------- */ -/* En-tête DOS */ -typedef struct _image_dos_header -{ - uint16_t e_magic; /* Numéro magique */ - uint16_t e_cblp; /* Octets de la dernière page */ - uint16_t e_cp; /* Pages dans le fichier */ - uint16_t e_crlc; /* Relocalisations */ - uint16_t e_cparhdr; /* Taille en paragraphes */ - uint16_t e_minalloc; /* Nb min de paragraphes requis*/ - uint16_t e_maxalloc; /* Nb max de paragraphes requis*/ - uint16_t e_ss; /* Valeur (relative) SS init. */ - uint16_t e_sp; /* Valeur SP initiale */ - uint16_t e_csum; /* Empreinte */ - uint16_t e_ip; /* Valeur IP initiale */ - uint16_t e_cs; /* Valeur (relative) CS init. */ - uint16_t e_lfarlc; /* Position de table de reloc. */ - uint16_t e_ovno; /* Nombre d'overlay */ - uint16_t e_res[4]; /* Mots réservés */ - uint16_t e_oemid; /* Identifiant OEM */ - uint16_t e_oeminfo; /* Infos OEM pour e_oemid */ - uint16_t e_res2[10]; /* Mots réservés */ - uint32_t e_lfanew; /* Décallage de bonne en-tête */ - -} image_dos_header; - -/* Archtecture supportées */ -#define IMAGE_FILE_MACHINE_I386 0x014c /* x86 */ -#define IMAGE_FILE_MACHINE_IA64 0x0200 /* Intel IPF */ -#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* x64 */ - -/* Caractéristiques de l'image */ -#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* Pas de relocalisation */ -#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 /* Fichier exécutable */ -#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 /* Pas de ligne COFF */ -#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 /* Pas de table de symboles COFF */ -#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 /* Aggressively trim the working set. This value is obsolete as of Windows 2000. */ -#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 /* Adressage > 2 Go */ -#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 /* Octets inv. ; obsolète */ -#define IMAGE_FILE_32BIT_MACHINE 0x0100 /* Machine 32 bits */ -#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 /* Pas d'infos de débogage */ -#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 /* ...support amovible */ -#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 /* Ficher issu du réseau */ -#define IMAGE_FILE_SYSTEM 0x1000 /* Fichier système */ -#define IMAGE_FILE_DLL 0x2000 /* Fichier DLL */ -#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 /* Mono-proc. seulement */ -#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 /* Octets inv. ; obsolète */ - -/* Première en-tête du "vrai" format */ -typedef struct _image_file_header -{ - uint16_t machine; /* Type de machine visée */ - uint16_t number_of_sections; /* Nombre de sections */ - uint32_t time_date_stamp; /* Date de la liaison */ - uint32_t pointer_to_symbol_table; /* Position de ladite table */ - uint32_t number_of_symbols; /* Nombre de symboles */ - uint16_t size_of_optional_header; /* Taille de l'en-tête n°2 */ - uint16_t characteristics; /* Propriétés de l'image */ -} image_file_header; +/* Procède à la lecture d'une en-tête de programme DOS. */ +bool read_dos_image_header(const GPeFormat *, off_t *, image_dos_header *); +/* Procède à la lecture d'une en-tête de programme PE (1). */ +bool read_pe_file_header(const GPeFormat *, off_t *, image_file_header *); -/* Description du format Portable Executable */ -struct _pe_format -{ +/* Procède à la lecture d'une en-tête de programme PE (2). */ +bool read_pe_optional_header(const GPeFormat *, off_t *, image_optional_header *); - int a; +/* Procède à la lecture d'une en-tête de programme PE. */ +bool read_pe_nt_header(const GPeFormat *, off_t *, image_nt_headers *); +/* Procède à la lecture d'une en-tête de section PE. */ +bool read_pe_image_section_header(const GPeFormat *, off_t *, image_section_header *); -}; +/* Procède à la lecture d'un répertoire de programme PE. */ +bool read_pe_image_import_descriptor(const GPeFormat *, off_t *, image_import_descriptor *); + +/* Procède à la lecture d'une fonction importée par son nom. */ +bool read_pe_image_import_by_name(const GPeFormat *, off_t *, image_import_by_name *); diff --git a/src/format/pe/pe.c b/src/format/pe/pe.c new file mode 100644 index 0000000..1d4e6f4 --- /dev/null +++ b/src/format/pe/pe.c @@ -0,0 +1,386 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * pe.c - support du format Portable Executable + * + * 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 . + */ + + +#include "pe.h" + + +#include + + +#include "pe-int.h" +#include "section.h" +#include "symbols.h" + + + +/* Initialise la classe des formats d'exécutables PE. */ +static void g_pe_format_class_init(GPeFormatClass *); + +/* Initialise une instance de format d'exécutable PE. */ +static void g_pe_format_init(GPeFormat *); + +/* Indique le type d'architecture visée par le format. */ +static FormatTargetMachine g_pe_format_get_target_machine(const GPeFormat *); + +/* Fournit l'adresse mémoire du point d'entrée du programme. */ +static vmpa_t g_pe_format_get_entry_point(const GPeFormat *); + +/* Fournit les références aux zones binaires à analyser. */ +static GBinPart **g_pe_format_get_parts(const GPeFormat *, size_t *); + +/* Fournit la position correspondant à une adresse virtuelle. */ +static bool g_pe_format_translate_address_into_offset(const GPeFormat *, vmpa_t, off_t *); + +/* Fournit l'adresse virtuelle correspondant à une position. */ +static bool g_pe_format_translate_offset_into_address(const GPeFormat *, off_t, vmpa_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 pe_is_matching(FormatType type, const uint8_t *content, off_t length) +{ + bool result; /* Bilan à faire connaître */ + image_dos_header dos_header; /* En-tête DOS */ + + result = false; + + if (length >= 2) + { + result = (strncmp((const char *)content, "\x4d\x5a" /* MZ */, 2) == 0); + result &= length >= sizeof(image_dos_header); + } + + if (result) + { + memcpy(&dos_header, content, sizeof(image_dos_header)); + + result = length >= (dos_header.e_lfanew + 4); + + result &= (strncmp((const char *)&content[dos_header.e_lfanew], + "\x50\x45\x00\x00" /* PE00 */, 4) == 0); + + } + + return result; + +} + + +/* Indique le type défini pour un format d'exécutable PE. */ +G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des formats d'exécutables PE. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_pe_format_class_init(GPeFormatClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance à initialiser. * +* * +* Description : Initialise une instance de format d'exécutable PE. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_pe_format_init(GPeFormat *format) +{ + GExeFormat *exe_format; /* Format parent à constituer */ + + exe_format = G_EXE_FORMAT(format); + + exe_format->get_machine = (get_target_machine_fc)g_pe_format_get_target_machine; + exe_format->get_entry_point = (get_entry_point_fc)g_pe_format_get_entry_point; + exe_format->get_parts = (get_parts_fc)g_pe_format_get_parts; + + exe_format->translate_addr = (translate_addr_fc)g_pe_format_translate_address_into_offset; + exe_format->translate_off = (translate_off_fc)g_pe_format_translate_offset_into_address; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Prend en charge un nouveau format PE. * +* * +* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinFormat *g_pe_format_new(const bin_t *content, off_t length) +{ + GPeFormat *result; /* Structure à retourner */ + off_t offset; /* Tête de lecture */ + + + int i; + + + result = g_object_new(G_TYPE_PE_FORMAT, NULL); + + g_binary_format_set_content(G_BIN_FORMAT(result), content, length); + + offset = 0; + + if (!read_dos_image_header(result, &offset, &result->dos_header)) + { + /* TODO */ + return NULL; + } + + offset = result->dos_header.e_lfanew; + + if (!read_pe_nt_header(result, &offset, &result->nt_headers)) + { + /* TODO */ + return NULL; + } + + result->section_offset = offset; + + printf("offset :: 0x%08x\n", offset); + + printf("Format :: 0x%08x\n", result->nt_headers.signature); + + printf("directories :: %d\n", result->nt_headers.optional_header.number_of_rva_and_sizes); + + for (i = 0; i < result->nt_headers.optional_header.number_of_rva_and_sizes; i++) + printf(" [%d] addr=0x%08x size=%d\n", i, + result->nt_headers.optional_header.data_directory[i].virtual_address, + result->nt_headers.optional_header.data_directory[i].size); + + + load_pe_symbols(result); + + + 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_pe_format_get_target_machine(const GPeFormat *format) +{ + FormatTargetMachine result; /* Identifiant à retourner */ + + result = FTM_386; + + /* + 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_pe_format_get_entry_point(const GPeFormat *format) +{ + return 0;//(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_pe_format_get_parts(const GPeFormat *format, size_t *count) +{ + GBinPart **result; /* Tableau à retourner */ + uint16_t i; /* Boucle de parcours */ + image_section_header section; /* En-tête de section PE */ + GBinPart *part; /* Partie à intégrer à la liste*/ + char name[IMAGE_SIZEOF_SHORT_NAME + 1]; /* Nom de section utilisable */ + + result = NULL; + *count = 0; + + for (i = 0; i < format->nt_headers.file_header.number_of_sections; i++) + { + if (!find_pe_section_by_index(format, i, §ion)) + continue; + + if (section.characteristics & IMAGE_SCN_MEM_EXECUTE) + { + part = g_binary_part_new(); + + memset(name, 0, (IMAGE_SIZEOF_SHORT_NAME + 1) * sizeof(char)); + memcpy(name, section.name, (IMAGE_SIZEOF_SHORT_NAME + 1) * sizeof(char)); + + g_binary_part_set_name(part, name); + + printf("section '%s'\n", name); + + g_binary_part_set_values(part, + section.pointer_to_raw_data, + section.size_of_raw_data, + section.virtual_address); + + printf("section[%d] start=0x%08x size=%d addr=0x%08x\n", i, + section.pointer_to_raw_data, + section.size_of_raw_data, + section.virtual_address); + + result = (GBinPart **)realloc(result, ++(*count) * sizeof(GBinPart *)); + result[*count - 1] = part; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* addr = adresse virtuelle à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit la position correspondant à une adresse virtuelle. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_pe_format_translate_address_into_offset(const GPeFormat *format, vmpa_t addr, off_t *pos) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* pos = position dans le flux binaire à retrouver. * +* addr = adresse virtuelle correspondante. [OUT] * +* * +* Description : Fournit l'adresse virtuelle correspondant à une position. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_pe_format_translate_offset_into_address(const GPeFormat *format, off_t pos, vmpa_t *addr) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} diff --git a/src/format/pe/pe.h b/src/format/pe/pe.h new file mode 100644 index 0000000..da1f44d --- /dev/null +++ b/src/format/pe/pe.h @@ -0,0 +1,62 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * pe.h - prototypes pour le support du format Portable Executable + * + * 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 . + */ + + +#ifndef _FORMAT_PE_E_PE_H +#define _FORMAT_PE_E_PE_H + + +#include +#include +#include + + +#include "../format.h" + + + +#define G_TYPE_PE_FORMAT g_pe_format_get_type() +#define G_PE_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_pe_format_get_type(), GPeFormat)) +#define G_IS_PE_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_pe_format_get_type())) +#define G_PE_FORMAT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_pe_format_get_type(), GPeFormatIface)) +#define G_PE_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PE_FORMAT, GPeFormatClass)) + + +/* Format d'exécutable PE (instance) */ +typedef struct _GPeFormat GPeFormat; + +/* Format d'exécutable PE (classe) */ +typedef struct _GPeFormatClass GPeFormatClass; + + +/* Indique si le format peut être pris en charge ici. */ +bool pe_is_matching(FormatType, const bin_t *, off_t); + +/* Indique le type défini pour un format d'exécutable PE. */ +GType g_pe_format_get_type(void); + +/* Prend en charge un nouveau format PE. */ +GBinFormat *g_pe_format_new(const bin_t *, off_t); + + + +#endif /* _FORMAT_PE_E_PE_H */ diff --git a/src/format/pe/pe_def.h b/src/format/pe/pe_def.h new file mode 100644 index 0000000..5440328 --- /dev/null +++ b/src/format/pe/pe_def.h @@ -0,0 +1,343 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * pe_def.h - liste des structures et constantes utilisées par le format PE + * + * Copyright (C) 2010 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 . + */ + + +#ifndef _FORMAT_PE_PE_DEF_H +#define _FORMAT_PE_PE_DEF_H + + +#include + + + + + +/* ---------------------------- DESCRIPTION DU FORMAT PE ---------------------------- */ + + +/* En-tête DOS */ +typedef struct _image_dos_header +{ + uint16_t e_magic; /* Numéro magique */ + uint16_t e_cblp; /* Octets de la dernière page */ + uint16_t e_cp; /* Pages dans le fichier */ + uint16_t e_crlc; /* Relocalisations */ + uint16_t e_cparhdr; /* Taille en paragraphes */ + uint16_t e_minalloc; /* Nb min de paragraphes requis*/ + uint16_t e_maxalloc; /* Nb max de paragraphes requis*/ + uint16_t e_ss; /* Valeur (relative) SS init. */ + uint16_t e_sp; /* Valeur SP initiale */ + uint16_t e_csum; /* Empreinte */ + uint16_t e_ip; /* Valeur IP initiale */ + uint16_t e_cs; /* Valeur (relative) CS init. */ + uint16_t e_lfarlc; /* Position de table de reloc. */ + uint16_t e_ovno; /* Nombre d'overlay */ + uint16_t e_res[4]; /* Mots réservés */ + uint16_t e_oemid; /* Identifiant OEM */ + uint16_t e_oeminfo; /* Infos OEM pour e_oemid */ + uint16_t e_res2[10]; /* Mots réservés */ + uint32_t e_lfanew; /* Décallage de bonne en-tête */ + +} image_dos_header; + +/* Archtecture supportées */ +#define IMAGE_FILE_MACHINE_I386 0x014c /* x86 */ +#define IMAGE_FILE_MACHINE_IA64 0x0200 /* Intel IPF */ +#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* x64 */ + +/* Caractéristiques de l'image */ +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* Pas de relocalisation */ +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 /* Fichier exécutable */ +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 /* Pas de ligne COFF */ +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 /* Pas de table de symboles COFF */ +#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 /* Aggressively trim the working set. This value is obsolete as of Windows 2000. */ +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 /* Adressage > 2 Go */ +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 /* Octets inv. ; obsolète */ +#define IMAGE_FILE_32BIT_MACHINE 0x0100 /* Machine 32 bits */ +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 /* Pas d'infos de débogage */ +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 /* ...support amovible */ +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 /* Ficher issu du réseau */ +#define IMAGE_FILE_SYSTEM 0x1000 /* Fichier système */ +#define IMAGE_FILE_DLL 0x2000 /* Fichier DLL */ +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 /* Mono-proc. seulement */ +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 /* Octets inv. ; obsolète */ + +/* Première en-tête du "vrai" format */ +typedef struct _image_file_header +{ + uint16_t machine; /* Type de machine visée */ + uint16_t number_of_sections; /* Nombre de sections */ + uint32_t time_date_stamp; /* Date de la liaison */ + uint32_t pointer_to_symbol_table; /* Position de ladite table */ + uint32_t number_of_symbols; /* Nombre de symboles */ + uint16_t size_of_optional_header; /* Taille de l'en-tête n°2 */ + uint16_t characteristics; /* Propriétés de l'image */ + +} image_file_header; + + + + + + + + + + +/* -------------------------- EN-TETE EVOLUEE DU FORMAT PE -------------------------- */ + + +/** + * cf. http://msdn.microsoft.com/en-us/library/ms680305(VS.85).aspx + */ + +/* Zone de données Windows */ +typedef struct _image_data_directory +{ + uint32_t virtual_address; /* Adresse de la table */ + uint32_t size; /* Taille de la table */ + +} image_data_directory; + +// Directory Entries +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) +#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers +#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor + + +/** + * cf. http://msdn.microsoft.com/en-us/library/ms680339(VS.85).aspx + */ + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +/* Seconde en-tête, optionnelle */ +typedef struct _image_optional_header +{ + uint16_t magic; /* Type de binaire manipulé */ + uint8_t major_linker_version; /* Version majeure du linker */ + uint8_t minor_linker_version; /* Version mineure du linker */ + uint32_t size_of_code; /* Taille de tout le code */ + uint32_t size_of_initialized_data; /* Taille des données init. */ + uint32_t size_of_uninitialized_data; /* Taille des données non init.*/ + uint32_t address_of_entry_point; /* Point d'entrée pour un exe. */ + uint32_t base_of_code; /* Adresse relative du code */ + uint32_t base_of_data; /* Adresse relative des données*/ + uint32_t image_base; /* Adresse souhaitée en mémoire*/ + uint32_t section_alignment; /* Alignement des sections */ + uint32_t file_alignment; /* Alignement des données */ + uint16_t major_operating_system_version;/* Numéro majeur d'OS requis */ + uint16_t minor_operating_system_version;/* Numéro mineur d'OS requis */ + uint16_t major_image_version; /* Numéro majeur du binaire */ + uint16_t minor_image_version; /* Numéro mineur du binaire */ + uint16_t major_subsystem_version; /* Numéro majeur du sous-sys. */ + uint16_t minor_subsystem_version; /* Numéro mineur du sous-sys. */ + uint32_t win32_version_value; /* Réservé (-> 0) */ + uint32_t size_of_image; /* Taille de l'image */ + uint32_t size_of_headers; /* Taille de l'en-tête */ + uint32_t checksum; /* Somme de contrôle */ + uint16_t subsystem; /* Sous-système visé */ + uint16_t dll_characteristics; /* Propriétés de la DLL */ + uint32_t size_of_stack_reserve; /* Taille de pile reservée */ + uint32_t size_of_stack_commit; /* Taille de pile au démarrage */ + uint32_t size_of_heap_reserve; /* Taille de tas reservée */ + uint32_t size_of_heap_commit; /* Taille de tas au démarrage */ + uint32_t loader_flags; /* Champ obslète */ + uint32_t number_of_rva_and_sizes; /* Nombre d'entrées suivantes */ + image_data_directory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; + +} image_optional_header; + +/* Valeurs pour le champ 'magic' */ +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b /* Exécutable 32 bits */ +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b /* Exécutable 64 bits */ +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 /* Image ROM */ + +/* Sous-système attendu (champ 'subsystem') */ +#define IMAGE_SUBSYSTEM_UNKNOWN 0 /* Inconnu */ +#define IMAGE_SUBSYSTEM_NATIVE 1 /* Rien de requis */ +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 /* Windows GUI */ +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 /* Windows CUI */ +#define IMAGE_SUBSYSTEM_OS2_CUI 5 /* OS/2 CUI */ +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 /* Posix CUI */ +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 /* Windows CE */ +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 /* Application EFI */ +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 /* Pilote EFI + boot */ +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 /* Pilote EFI + serv. */ +#define IMAGE_SUBSYSTEM_EFI_ROM 13 /* Image ROM EFI */ +#define IMAGE_SUBSYSTEM_XBOX 14 /* Xbox */ +#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 /* Application de boot */ + +/* Détails pour le champ 'dll_characteristics' */ +#define IMAGE_DLLCHARACTERISTICS_UNKNOW_0 0x0001 /* Réservé */ +#define IMAGE_DLLCHARACTERISTICS_UNKNOW_1 0x0002 /* Réservé */ +#define IMAGE_DLLCHARACTERISTICS_UNKNOW_2 0x0004 /* Réservé */ +#define IMAGE_DLLCHARACTERISTICS_UNKNOW_3 0x0008 /* Réservé */ +#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040/* Reloc. possible */ +#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 /* Vérif. forcées */ +#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 /* Compatible DEP */ +#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200/* Pas d'isolation */ +#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 /* Pas de SEH */ +#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 /* Ne pas lier */ +#define IMAGE_DLLCHARACTERISTICS_UNKNOW_4 0x1000 /* Réservé */ +#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 /* Pilote WDM */ +#define IMAGE_DLLCHARACTERISTICS_UNKNOW_5 0x4000 /* Réservé */ +#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 /* Support */ + + +/* Résumé global */ +typedef struct _image_nt_headers +{ + uint32_t signature; /* Numéro magique */ + image_file_header file_header; /* En-tête n°1 */ + image_optional_header optional_header; /* En-tête n°2 */ + +} image_nt_headers; + + + +/* --------------------------- SECTIONS POUR LE FORMAT PE --------------------------- */ + +/** + * cf. http://msdn.microsoft.com/en-us/library/ms680341(VS.85).aspx + */ + +/* Taille maximale d'un nom, avec ou sans '\0' final */ +#define IMAGE_SIZEOF_SHORT_NAME 8 + +/* Description d'une section */ +typedef struct _image_section_header +{ + char name[IMAGE_SIZEOF_SHORT_NAME]; /* Nom de la section */ + + union + { + uint32_t physical_address; /* Adresse physique */ + uint32_t virtual_size; /* Taille en mémoire */ + } misc; + + uint32_t virtual_address; /* Adresse en mémoire */ + uint32_t size_of_raw_data; /* Taille de données non init. */ + uint32_t pointer_to_raw_data; /* Position de ces données */ + uint32_t pointer_to_relocations; /* Position des relocalisations*/ + uint32_t pointer_to_line_numbers; /* Position de numéros de ligne*/ + uint16_t number_of_relocations; /* Quantité de relocalisations */ + uint16_t number_of_line_numbers; /* Quantité de numéros de ligne*/ + uint32_t characteristics; /* Caractéristiques */ + +} image_section_header; + +/* Détails des caractéristiques d'une image (champ 'characteristics') */ +#define IMAGE_SCN_UNKNOWN_0 0x00000000 /* Réservé */ +#define IMAGE_SCN_UNKNOWN_1 0x00000001 /* Réservé */ +#define IMAGE_SCN_UNKNOWN_2 0x00000002 /* Réservé */ +#define IMAGE_SCN_UNKNOWN_3 0x00000004 /* Réservé */ +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Pas de complément (obs) */ +#define IMAGE_SCN_UNKNOWN_4 0x00000010 /* Réservé */ +#define IMAGE_SCN_CNT_CODE 0x00000020 /* Code exécutable */ +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Données intialisées */ +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Données non init. */ +#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Réservé */ +#define IMAGE_SCN_LNK_INFO 0x00000200 /* Commentaires ou autres */ +#define IMAGE_SCN_UNKNOWN_5 0x00000400 /* Réservé */ +#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* A ne pas intégrer */ +#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Données COMDAT */ +#define IMAGE_SCN_UNKNOWN_6 0x00002000 /* Réservé */ +#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 /* Reset des exceptions */ +#define IMAGE_SCN_GPREL 0x00008000 /* Références globales */ +#define IMAGE_SCN_UNKNOWN_7 0x00010000 /* Réservé */ +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 /* Réservé */ +#define IMAGE_SCN_MEM_LOCKED 0x00040000 /* Réservé */ +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 /* Réservé */ +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 /* Alignement sur 1 octet */ +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 /* Alignement sur 2 octets */ +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 /* Alignement sur 4 octets */ +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 /* Alignement sur 8 octets */ +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Alignement de 16 octets */ +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 /* Alignement de 32 octets */ +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 /* Alignement de 64 octets */ +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 /* Alignement de 128 octets*/ +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 /* Alignement de 256 octets*/ +#define IMAGE_SCN_ALIGN_512BYTES 0x00a00000 /* Alignement de 512 octets*/ +#define IMAGE_SCN_ALIGN_1024BYTES 0x00b00000 /* Alignement sur 1 ko */ +#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000 /* Alignement sur 2 ko */ +#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000 /* Alignement sur 4 ko */ +#define IMAGE_SCN_ALIGN_8192BYTES 0x00e00000 /* Alignement sur 8 ko */ +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Trop de Relocalisations */ +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 /* Section abandonnable */ +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section non cachable */ +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section non paginable */ +#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section partageable */ +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 /* Section exécutable */ +#define IMAGE_SCN_MEM_READ 0x40000000 /* Section lisible */ +#define IMAGE_SCN_MEM_WRITE 0x80000000 /* Section modifiable */ + + + +/* --------------------------- IDENTIFICATION DE SYMBOLES --------------------------- */ + +/** + * cf. http://msdn.microsoft.com/en-us/library/ms809762.aspx + * http://sandsprite.com/CodeStuff/Understanding_imports.html + * http://olance.developpez.com/articles/windows/pe-iczelion/import-table/ + */ + +/* Point de départ de la chaîne des importations */ +typedef struct _image_import_descriptor +{ + uint32_t original_first_thunk; + uint32_t time_date_stamp; + uint32_t forwarder_chain; + uint32_t module_name; + uint32_t first_thunk; + +} image_import_descriptor; + + + + +/* Désignation de fonction importée */ +typedef struct _image_import_by_name +{ + uint16_t hint; + char *name; + +} image_import_by_name; + + + + + +#endif /* _FORMAT_PE_PE_DEF_H */ diff --git a/src/format/pe/section.c b/src/format/pe/section.c new file mode 100644 index 0000000..210ac37 --- /dev/null +++ b/src/format/pe/section.c @@ -0,0 +1,59 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * section.h - prototypes pour la gestion des sections d'un PE + * + * Copyright (C) 2010 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 . + */ + + +#include "section.h" + + +#include +#include + + +#include "pe-int.h" + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* index = indice de la section recherchée. * +* section = ensemble d'informations à faire remonter. [OUT] * +* * +* Description : Recherche une section donnée au sein de binaire par indice. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool find_pe_section_by_index(const GPeFormat *format, uint16_t index, image_section_header *section) +{ + off_t offset; /* Emplacement à venir lire */ + + if (index >= format->nt_headers.file_header.number_of_sections) return false; + + offset = format->section_offset + sizeof(image_section_header) * index; + + return read_pe_image_section_header(format, &offset, section); + +} diff --git a/src/format/pe/section.h b/src/format/pe/section.h new file mode 100644 index 0000000..cfc8471 --- /dev/null +++ b/src/format/pe/section.h @@ -0,0 +1,38 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * section.h - prototypes pour la gestion des sections d'un PE + * + * Copyright (C) 2010 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 . + */ + + +#ifndef _FORMAT_PE_SECTION_H +#define _FORMAT_PE_SECTION_H + + +#include "pe.h" +#include "pe_def.h" + + + +/* Recherche une section donnée au sein de binaire par indice. */ +bool find_pe_section_by_index(const GPeFormat *, uint16_t, image_section_header *); + + + +#endif /* _FORMAT_PE_SECTION_H */ diff --git a/src/format/pe/symbols.c b/src/format/pe/symbols.c new file mode 100644 index 0000000..8f75029 --- /dev/null +++ b/src/format/pe/symbols.c @@ -0,0 +1,136 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * symbols.c - gestion des symboles d'un PE + * + * Copyright (C) 2010 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 . + */ + + +#include "symbols.h" + + +#include "pe-int.h" + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* * +* Description : Charge en mémoire la liste humaine des symboles importés. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_pe_imported_symbols(GPeFormat *format) +{ + bool result; /* Bilan à retourner */ + const image_data_directory *directory; /* Répertoire original */ + image_import_descriptor dll; /* DLL importée */ + off_t pos; /* Position de tête de lecture */ + off_t i; /* Boucle de parcours */ + image_import_by_name import; /* Fonction importée */ + + result = true; + + directory = &format->nt_headers.optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + + /* TODO : msg si size !% sizeof(...) */ + + for (pos = directory->virtual_address; + result && pos < (directory->virtual_address + directory->size); ) + { + result = read_pe_image_import_descriptor(format, &pos, &dll); + + printf("mod orig thunk :: 0x%08x\n", dll.original_first_thunk); + printf("mod name :: 0x%08x\n", dll.module_name); + printf("mod first thunk :: 0x%08x\n", dll.first_thunk); + + i = dll.original_first_thunk; + + /* TODO : i == 0 */ + if (i == 0) continue; + + while ((result = read_pe_image_import_by_name(format, &i, &import))) + { + if (import.hint == 0 && import.name == NULL) + break; + + + + printf(" >> import '%s'\n", import.name); + + + } + + + } + + lpis_exit: + + return result; + +} + + + + + + + + + + + + + + + + +/****************************************************************************** +* * +* 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_pe_symbols(GPeFormat *format) +{ + bool result; /* Bilan à retourner */ + + /* Symboles externes */ + result = load_pe_imported_symbols(format); + + /* Symboles internes */ + + return result; + +} diff --git a/src/format/pe/symbols.h b/src/format/pe/symbols.h new file mode 100644 index 0000000..3d8fd8f --- /dev/null +++ b/src/format/pe/symbols.h @@ -0,0 +1,36 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * symbols.h - prototypes pour la gestion des symboles d'un PE + * + * Copyright (C) 2010 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 . + */ + + +#ifndef _FORMAT_PE_SYMBOLS_H +#define _FORMAT_PE_SYMBOLS_H + + +#include "pe.h" + + +/* Charge en mémoire la liste humaine des symboles. */ +bool load_pe_symbols(GPeFormat *); + + + +#endif /* _FORMAT_PE_SYMBOLS_H */ -- cgit v0.11.2-87-g4458