diff options
Diffstat (limited to 'plugins/pe/format.c')
-rw-r--r-- | plugins/pe/format.c | 640 |
1 files changed, 347 insertions, 293 deletions
diff --git a/plugins/pe/format.c b/plugins/pe/format.c index 3839063..5ecfb18 100644 --- a/plugins/pe/format.c +++ b/plugins/pe/format.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * pe.c - support du format Portable Executable * - * Copyright (C) 2010-2017 Cyrille Bagard + * Copyright (C) 2010-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,15 +25,18 @@ #include <assert.h> +#include <string.h> #include "pe-int.h" -#include "rich.h" -#include "section.h" -#include "symbols.h" +//#include "rich.h" +//#include "symbols.h" +/* ------------------------- DEFINITION D'UN NOUVEAU FORMAT ------------------------- */ + + /* Initialise la classe des formats d'exécutables ELF. */ static void g_pe_format_class_init(GPeFormatClass *); @@ -46,6 +49,11 @@ static void g_pe_format_dispose(GPeFormat *); /* Procède à la libération totale de la mémoire. */ static void g_pe_format_finalize(GPeFormat *); + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + /* Indique la désignation interne du format. */ static char *g_pe_format_get_key(const GPeFormat *); @@ -53,39 +61,28 @@ static char *g_pe_format_get_key(const GPeFormat *); static char *g_pe_format_get_description(const GPeFormat *); /* Assure l'interprétation d'un format en différé. */ -static bool g_pe_format_analyze(GPeFormat *, wgroup_id_t, GtkStatusStack *); +static bool g_pe_format_analyze(GPeFormat *); /* Informe quant au boutisme utilisé. */ static SourceEndian g_pe_format_get_endianness(const GPeFormat *); /* Indique le type d'architecture visée par le format. */ -static const char *g_pe_format_get_target_machine(const GPeFormat *); +static char *g_pe_format_get_target_machine(const GPeFormat *); -/* Fournit l'adresse principale associée à un format Elf. */ +/* Fournit l'adresse principale associée à un format. */ static bool g_pe_format_get_main_address(GPeFormat *, vmpa2t *); - -#if 0 - /* Etend la définition des portions au sein d'un binaire. */ -static void g_pe_format_refine_portions(GPeFormat *); - -#endif - - - -/* Fournit l'emplacement correspondant à une adresse virtuelle. */ -bool g_pe_format_translate_address_into_vmpa_using_portions(GPeFormat *, virt_t, vmpa2t *); - - -#if 0 +static bool g_pe_format_refine_portions(GPeFormat *); /* Fournit l'emplacement d'une section donnée. */ static bool g_pe_format_get_section_range_by_name(const GPeFormat *, const char *, mrange_t *); -#endif +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UN NOUVEAU FORMAT */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -116,7 +113,7 @@ bool check_pe_format(const GBinContent *content) if (result) { - G_KNOWN_FORMAT(&format)->content = (GBinContent *)content; + ((GKnownFormat *)&format)->content = (GBinContent *)content; result = read_dos_image_header(&format, &format.dos_header); } @@ -137,7 +134,7 @@ bool check_pe_format(const GBinContent *content) /* Indique le type défini pour un format d'exécutable ELF. */ -G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT); +G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXECUTABLE_FORMAT); /****************************************************************************** @@ -156,8 +153,8 @@ static void g_pe_format_class_init(GPeFormatClass *klass) { GObjectClass *object; /* Autre version de la classe */ GKnownFormatClass *known; /* Version de format connu */ - GBinFormatClass *fmt; /* Version en format basique */ - GExeFormatClass *exe; /* Version en exécutable */ + GProgramFormatClass *prgm; /* Version en format basique */ + GExecutableFormatClass *exe; /* Version en exécutable */ object = G_OBJECT_CLASS(klass); @@ -170,20 +167,19 @@ static void g_pe_format_class_init(GPeFormatClass *klass) known->get_desc = (known_get_desc_fc)g_pe_format_get_description; known->analyze = (known_analyze_fc)g_pe_format_analyze; - fmt = G_BIN_FORMAT_CLASS(klass); + prgm = G_PROGRAM_FORMAT_CLASS(klass); - fmt->get_endian = (format_get_endian_fc)g_pe_format_get_endianness; + prgm->get_endian = (program_get_endian_fc)g_pe_format_get_endianness; + prgm->get_range_by_name = (get_range_by_name_fc)g_pe_format_get_section_range_by_name; - exe = G_EXE_FORMAT_CLASS(klass); + exe = G_EXECUTABLE_FORMAT_CLASS(klass); exe->get_machine = (get_target_machine_fc)g_pe_format_get_target_machine; exe->get_main_addr = (get_main_addr_fc)g_pe_format_get_main_address; - //exe->refine_portions = (refine_portions_fc)g_pe_format_refine_portions; + exe->refine_portions = (refine_portions_fc)g_pe_format_refine_portions; - //exe->translate_phys = (translate_phys_fc)g_exe_format_translate_offset_into_vmpa_using_portions; - exe->translate_virt = (translate_virt_fc)g_pe_format_translate_address_into_vmpa_using_portions; - - //exe->get_range_by_name = (get_range_by_name_fc)g_pe_format_get_section_range_by_name; + exe->translate_phys = g_executable_format_translate_offset_into_vmpa_with_portions; + exe->translate_virt = g_executable_format_translate_address_into_vmpa_with_portions; } @@ -262,39 +258,41 @@ static void g_pe_format_finalize(GPeFormat *format) * * ******************************************************************************/ -GExeFormat *g_pe_format_new(GBinContent *content) +GPeFormat *g_pe_format_new(GBinContent *content) { GPeFormat *result; /* Structure à retourner */ - if (!check_pe_format(content)) - return NULL; - result = g_object_new(G_TYPE_PE_FORMAT, NULL); - g_known_format_set_content(G_KNOWN_FORMAT(result), content); + if (!g_pe_format_create(result, content)) + g_clear_object(&result); - return G_EXE_FORMAT(result); + return result; } /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * +* Paramètres : format = description du format connu à consulter. * +* content = contenu binaire à parcourir. * * * -* Description : Indique la désignation interne du format. * +* Description : Met en place une nouvelle instance de format PE. * * * -* Retour : Désignation du format. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static char *g_pe_format_get_key(const GPeFormat *format) +bool g_pe_format_create(GPeFormat *format, GBinContent *content) { - char *result; /* Désignation à retourner */ + bool result; /* Bilan à retourner */ - result = strdup("pe"); + result = true;//check_pe_format(content); + + if (result) + result = g_executable_format_create(G_EXECUTABLE_FORMAT(format), content); return result; @@ -303,21 +301,21 @@ static char *g_pe_format_get_key(const GPeFormat *format) /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * +* Paramètres : format = format en place à consulter. * * * -* Description : Fournit une description humaine du format. * +* Description : Présente l'en-tête MS-DOS du format chargé. * * * -* Retour : Description du format. * +* Retour : Pointeur vers la description principale. * * * * Remarques : - * * * ******************************************************************************/ -static char *g_pe_format_get_description(const GPeFormat *format) +const image_dos_header_t *g_pe_format_get_dos_header(const GPeFormat *format) { - char *result; /* Désignation à retourner */ + const image_dos_header_t *result; /* Informations à retourner */ - result = strdup("Portable Executable"); + result = &format->dos_header; return result; @@ -326,44 +324,21 @@ static char *g_pe_format_get_description(const GPeFormat *format) /****************************************************************************** * * -* Paramètres : format = format chargé dont l'analyse est lancée. * -* gid = groupe de travail dédié. * -* status = barre de statut à tenir informée. * +* Paramètres : format = format en place à consulter. * * * -* Description : Assure l'interprétation d'un format en différé. * +* Description : Présente l'en-tête NT du format chargé. * * * -* Retour : Bilan de l'opération. * +* Retour : Pointeur vers la description principale. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_pe_format_analyze(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status) +const image_nt_headers_t *g_pe_format_get_nt_headers(const GPeFormat *format) { - bool result; /* Bilan à retourner */ - GExeFormat *exe; /* Autre version du format */ - vmpa2t section_start; /* Zone de départ des sections */ - - exe = G_EXE_FORMAT(format); - - result = read_dos_image_header(format, &format->dos_header); - if (!result) goto error; - - result = read_pe_nt_header(format, &format->nt_headers, §ion_start); - if (!result) goto error; + const image_nt_headers_t *result; /* Informations à retourner */ - format->sections = read_all_pe_sections(format, §ion_start); - if (format->sections == NULL) goto error; - - extract_pe_rich_header(format); - - result = load_pe_symbols(format, gid, status); - if (!result) goto error; - - result = g_executable_format_complete_loading(exe, gid, status); - if (!result) goto error; - - error: + result = &format->nt_headers; return result; @@ -372,76 +347,73 @@ static bool g_pe_format_analyze(GPeFormat *format, wgroup_id_t gid, GtkStatusSta /****************************************************************************** * * -* Paramètres : format = informations chargées à consulter. * +* Paramètres : format = format en place à consulter. * * * -* Description : Informe quant au boutisme utilisé. * +* Description : Indique si le format PE est en 32 bits ou en 64 bits. * * * -* Retour : Indicateur de boutisme. * +* Retour : true si le format est en 32 bits, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -static SourceEndian g_pe_format_get_endianness(const GPeFormat *format) +bool g_pe_format_get_is_32b(const GPeFormat *format) { - SourceEndian result; /* Boutisme à retourner */ + bool result; /* Nature à retourner */ - /** - * Sauf exception, le boutisme est généralement petit. - * - * Cf. https://reverseengineering.stackexchange.com/a/17923 - * https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions?view=msvc-160#endianness - */ + assert(format->loaded); - result = SRE_LITTLE; + switch (format->nt_headers.optional_header.header_32.magic) + { + case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + result = true; + break; + case IMAGE_NT_OPTIONAL_HDR64_MAGIC: + result = false; + break; + default: + result = true; + assert(false); + break; + } return result; + } /****************************************************************************** * * -* Paramètres : format = informations chargées à consulter. * +* Paramètres : format = format en place à consulter. * +* count = taille (fixe) du tableau renvoyé. [OUT] * * * -* Description : Indique le type d'architecture visée par le format. * +* Description : Offre un raccourci vers les répertoires du format PE. * * * -* Retour : Identifiant de l'architecture ciblée par le format. * +* Retour : Pointeur vers le tableau des répertoires. * * * * Remarques : - * * * ******************************************************************************/ -static const char *g_pe_format_get_target_machine(const GPeFormat *format) +const image_data_directory_t *g_pe_format_get_directories(const GPeFormat *format, size_t *count) { - const char *result; /* Identifiant à retourner */ + const image_data_directory_t *result; /* Liste à retourner */ - switch (format->nt_headers.file_header.machine) + if (g_pe_format_get_is_32b(format)) { - case IMAGE_FILE_MACHINE_I386: - result = "i386"; - break; + result = format->nt_headers.optional_header.header_32.data_directory; - case IMAGE_FILE_MACHINE_R3000: - case IMAGE_FILE_MACHINE_R4000: - case IMAGE_FILE_MACHINE_R10000: - case IMAGE_FILE_MACHINE_WCEMIPSV2: - case IMAGE_FILE_MACHINE_MIPS16: - case IMAGE_FILE_MACHINE_MIPSFPU: - case IMAGE_FILE_MACHINE_MIPSFPU16: - result = "mips"; - break; + if (count != NULL) + *count = format->nt_headers.optional_header.header_32.number_of_rva_and_sizes; - case IMAGE_FILE_MACHINE_ARM: - case IMAGE_FILE_MACHINE_THUMB: - case IMAGE_FILE_MACHINE_ARMNT: - result = "armv7"; - break; + } + else + { + result = format->nt_headers.optional_header.header_64.data_directory; - case IMAGE_FILE_MACHINE_UNKNOWN: - default: - result = NULL; - break; + if (count != NULL) + *count = format->nt_headers.optional_header.header_64.number_of_rva_and_sizes; } @@ -452,140 +424,174 @@ static const char *g_pe_format_get_target_machine(const GPeFormat *format) /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * -* addr = adresse principale trouvée si possible. [OUT] * +* Paramètres : format = format en place à consulter. * +* index = indice du répertoire visé. * * * -* Description : Fournit l'adresse principale associée à un format Elf. * +* Description : Extrait le contenu d'un répertoire du format PE. * * * -* Retour : Bilan des recherches. * +* Retour : Pointeur vers un contenu chargé ou NULL. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_pe_format_get_main_address(GPeFormat *format, vmpa2t *addr) +void *g_pe_format_get_directory(const GPeFormat *format, size_t index) { - bool result; /* Bilan à retourner */ - GBinSymbol *symbol; /* Point d'entrée trouvé */ - GBinFormat *base; /* Version d'instance parente */ - const mrange_t *range; /* Emplacement de ce point */ - - result = false; - symbol = NULL; + void *result; /* Données à retourner */ + size_t max; /* Quantité de répertoires */ + const image_data_directory_t *dir; /* Localisation du répertoire */ + vmpa2t pos; /* Tête de lecture */ + bool status; /* Bilan d'un traitement */ + image_export_directory_t *export; /* Répertoire de type 0 */ + image_import_descriptor_t *imports; /* Répertoire de type 1 */ + size_t imported_count; /* Quantité de DLL requises */ - base = G_BIN_FORMAT(format); + result = NULL; - if (g_binary_format_find_symbol_by_label(base, "main", &symbol)) - goto done; + dir = g_pe_format_get_directories(format, &max); - if (g_binary_format_find_symbol_by_label(base, "_start", &symbol)) - goto done; + if (index >= max) + goto exit; - if (g_binary_format_find_symbol_by_label(base, "entry_point", &symbol)) - goto done; + dir += index; - done: + status = g_executable_format_translate_address_into_vmpa(G_EXECUTABLE_FORMAT(format), + dir->virtual_address, &pos); + if (!status) goto exit; - if (symbol != NULL) + switch (index) { - result = true; + case IMAGE_DIRECTORY_ENTRY_EXPORT: - range = g_binary_symbol_get_range(symbol); + export = malloc(sizeof(image_export_directory_t)); - copy_vmpa(addr, get_mrange_addr(range)); + status = read_pe_image_export_directory(format, &pos, export); - g_object_unref(G_OBJECT(symbol)); + if (!status) + { + free(export); + goto exit; + } + + result = export; + break; + + case IMAGE_DIRECTORY_ENTRY_IMPORT: + + imports = NULL; + imported_count = 0; + + do + { + imports = realloc(imports, ++imported_count * sizeof(image_import_descriptor_t)); + + status = read_pe_image_import_descriptor(format, &pos, imports + (imported_count - 1)); + + if (!status) + { + free(imports); + goto exit; + } + + } + while (imports[imported_count - 1].original_first_thunk != 0); + + result = imports; + break; } + exit: + return result; } -#if 0 - /****************************************************************************** * * -* Paramètres : format = informations chargées à consulter. * +* Paramètres : format = format en place à consulter. * +* count = taille (fixe) du tableau renvoyé. [OUT] * * * -* Description : Etend la définition des portions au sein d'un binaire. * +* Description : Offre un raccourci vers les sections du format PE. * * * -* Retour : - * +* Retour : Pointeur vers la liste des sections. * * * * Remarques : - * * * ******************************************************************************/ -static void g_pe_format_refine_portions(GPeFormat *format) +const image_section_header_t *g_pe_format_get_sections(const GPeFormat *format, size_t *count) { + const image_section_header_t *result; /* Liste à retourner */ + + if (count != NULL) + *count = format->nt_headers.file_header.number_of_sections; + + result = format->sections; + + return result; } -#endif +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * -* addr = adresse virtuelle à retrouver. * -* pos = position correspondante. [OUT] * * * -* Description : Fournit l'emplacement correspondant à une adresse virtuelle. * +* Description : Indique la désignation interne du format. * * * -* Retour : Bilan de l'opération. * +* Retour : Désignation du format. * * * * Remarques : - * * * ******************************************************************************/ -bool g_pe_format_translate_address_into_vmpa_using_portions(GPeFormat *format, virt_t addr, vmpa2t *pos) +static char *g_pe_format_get_key(const GPeFormat *format) { - bool result; /* Bilan à retourner */ - uint16_t i; /* Boucle de parcours */ - const image_section_header *section; /* Section à consulter */ - phys_t diff; /* Décallage à appliquer */ - - result = false; - - for (i = 0; i < format->nt_headers.file_header.number_of_sections && !result; i++) - { - section = &format->sections[i]; + char *result; /* Désignation à retourner */ - if (addr < section->virtual_address) - continue; + result = strdup("pe"); - if (addr >= (section->virtual_address + section->size_of_raw_data)) - continue; + return result; - diff = addr - section->virtual_address; +} - init_vmpa(pos, section->pointer_to_raw_data + diff, addr); - result = true; +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* * +* Description : Fournit une description humaine du format. * +* * +* Retour : Description du format. * +* * +* Remarques : - * +* * +******************************************************************************/ - } +static char *g_pe_format_get_description(const GPeFormat *format) +{ + char *result; /* Désignation à retourner */ - //printf(" // trans // %x -> %x (valid? %d)\n", (unsigned int)addr, (unsigned int)pos->physical, result); + result = strdup("Portable Executable"); return result; } - - -#if 0 - - /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à consulter. * -* name = nom de la section recherchée. * -* range = emplacement en mémoire à renseigner. [OUT] * +* Paramètres : format = format chargé dont l'analyse est lancée. * * * -* Description : Fournit l'emplacement d'une section donnée. * +* Description : Assure l'interprétation d'un format en différé. * * * * Retour : Bilan de l'opération. * * * @@ -593,51 +599,82 @@ bool g_pe_format_translate_address_into_vmpa_using_portions(GPeFormat *format, v * * ******************************************************************************/ -static bool g_pe_format_get_section_range_by_name(const GPeFormat *format, const char *name, mrange_t *range) +static bool g_pe_format_analyze(GPeFormat *format) { bool result; /* Bilan à retourner */ - phys_t offset; /* Position physique de section*/ - phys_t size; /* Taille de la section trouvée*/ - virt_t address; /* Adresse virtuelle de section*/ - vmpa2t tmp; /* Adresse à initialiser */ + vmpa2t start; /* Zone de départ des sections */ + uint16_t count; /* Quantité de sections */ + uint16_t i; /* Boucle de parcours */ - result = find_elf_section_content_by_name(format, name, &offset, &size, &address); + result = read_dos_image_header(format, &format->dos_header); + if (!result) goto error; - if (result) + result = read_pe_nt_header(format, &format->nt_headers, &start); + if (!result) goto error; + + /* Chargement des définitions des sections déclarées */ + + copy_vmpa(&format->sections_start, &start); + + count = format->nt_headers.file_header.number_of_sections; + + format->sections = malloc(count * sizeof(image_section_header_t)); + + for (i = 0; i < count; i++) { - init_vmpa(&tmp, offset, address); - init_mrange(range, &tmp, size); + result = read_pe_image_section_header(format, &start, &format->sections[i]); + if (!result) goto error; } - return result; + /* Passage de relais */ -} -#endif + if (result) + result = G_KNOWN_FORMAT_CLASS(g_pe_format_parent_class)->analyze(G_KNOWN_FORMAT(format)); +#if 0 + extract_pe_rich_header(format); + result = load_pe_symbols(format, gid, status); + if (!result) goto error; + +#endif + + + error: + + return result; + +} /****************************************************************************** * * -* Paramètres : format = format en place à consulter. * +* Paramètres : format = informations chargées à consulter. * * * -* Description : Présente l'en-tête MS-DOS du format chargé. * +* Description : Informe quant au boutisme utilisé. * * * -* Retour : Pointeur vers la description principale. * +* Retour : Indicateur de boutisme. * * * * Remarques : - * * * ******************************************************************************/ -const image_dos_header *g_pe_format_get_dos_header(const GPeFormat *format) +static SourceEndian g_pe_format_get_endianness(const GPeFormat *format) { - const image_dos_header *result; /* Informations à retourner */ + SourceEndian result; /* Boutisme à retourner */ - result = &format->dos_header; + /** + * Sauf exception, le boutisme est généralement petit. + * + * Cf. https://reverseengineering.stackexchange.com/a/17923 + * https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions?view=msvc-160#endianness + */ + + result = SRE_LITTLE; return result; @@ -646,21 +683,43 @@ const image_dos_header *g_pe_format_get_dos_header(const GPeFormat *format) /****************************************************************************** * * -* Paramètres : format = format en place à consulter. * +* Paramètres : format = description de l'exécutable à consulter. * +* name = nom de la section recherchée. * +* range = emplacement en mémoire à renseigner. [OUT] * * * -* Description : Présente l'en-tête NT du format chargé. * +* Description : Fournit l'emplacement d'une section donnée. * * * -* Retour : Pointeur vers la description principale. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -const image_nt_headers *g_pe_format_get_nt_headers(const GPeFormat *format) +static bool g_pe_format_get_section_range_by_name(const GPeFormat *format, const char *name, mrange_t *range) { - const image_nt_headers *result; /* Informations à retourner */ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + image_section_header_t *section; /* Section à traiter */ + char tmp[IMAGE_SIZEOF_SHORT_NAME + 1]; /* Nom de la section */ + vmpa2t addr; /* Emplacement dans le binaire */ - result = &format->nt_headers; + result = false; + + for (i = 0, section = format->sections; i < format->nt_headers.file_header.number_of_sections; i++, section++) + { + memcpy(tmp, section->name, IMAGE_SIZEOF_SHORT_NAME); + tmp[IMAGE_SIZEOF_SHORT_NAME] = '\0'; + + if (strcmp(name, tmp) != 0) + continue; + + init_vmpa(&addr, section->pointer_to_raw_data, section->virtual_address); + init_mrange(range, &addr, section->size_of_raw_data); + + result = true; + break; + + } return result; @@ -669,75 +728,78 @@ const image_nt_headers *g_pe_format_get_nt_headers(const GPeFormat *format) /****************************************************************************** * * -* Paramètres : format = format en place à consulter. * +* Paramètres : format = informations chargées à consulter. * * * -* Description : Indique si le format PE est en 32 bits ou en 64 bits. * +* Description : Indique le type d'architecture visée par le format. * * * -* Retour : true si le format est en 32 bits, false sinon. * +* Retour : Identifiant de l'architecture ciblée par le format. * * * * Remarques : - * * * ******************************************************************************/ -bool g_pe_format_get_is_32b(const GPeFormat *format) +static char *g_pe_format_get_target_machine(const GPeFormat *format) { - bool result; /* Nature à retourner */ - - assert(format->loaded); + char *result; /* Identifiant à retourner */ - switch (format->nt_headers.optional_header.header_32.magic) + switch (format->nt_headers.file_header.machine) { - case IMAGE_NT_OPTIONAL_HDR32_MAGIC: - result = true; + case IMAGE_FILE_MACHINE_I386: + result = strdup("i386"); break; - case IMAGE_NT_OPTIONAL_HDR64_MAGIC: - result = false; + + case IMAGE_FILE_MACHINE_R3000: + case IMAGE_FILE_MACHINE_R4000: + case IMAGE_FILE_MACHINE_R10000: + case IMAGE_FILE_MACHINE_WCEMIPSV2: + case IMAGE_FILE_MACHINE_MIPS16: + case IMAGE_FILE_MACHINE_MIPSFPU: + case IMAGE_FILE_MACHINE_MIPSFPU16: + result = strdup("mips"); break; + + case IMAGE_FILE_MACHINE_ARM: + case IMAGE_FILE_MACHINE_THUMB: + case IMAGE_FILE_MACHINE_ARMNT: + result = strdup("armv7"); + break; + + case IMAGE_FILE_MACHINE_UNKNOWN: default: - result = true; - assert(false); + result = NULL; break; + } return result; - } /****************************************************************************** * * -* Paramètres : format = format en place à consulter. * -* count = taille (fixe) du tableau renvoyé. [OUT] * +* Paramètres : format = description de l'exécutable à consulter. * +* addr = adresse principale trouvée si possible. [OUT] * * * -* Description : Offre un raccourci vers les répertoires du format PE. * +* Description : Fournit l'adresse principale associée à un format. * * * -* Retour : Pointeur vers le tableau des répertoires. * +* Retour : Bilan des recherches. * * * * Remarques : - * * * ******************************************************************************/ -const image_data_directory *g_pe_format_get_directories(const GPeFormat *format, size_t *count) +static bool g_pe_format_get_main_address(GPeFormat *format, vmpa2t *addr) { - const image_data_directory *result; /* Liste à retourner */ + bool result; /* Bilan à retourner */ + virt_t ep; /* Point d'entrée */ if (g_pe_format_get_is_32b(format)) - { - result = format->nt_headers.optional_header.header_32.data_directory; - - if (count != NULL) - *count = format->nt_headers.optional_header.header_32.number_of_rva_and_sizes; - - } + ep = format->nt_headers.optional_header.header_32.address_of_entry_point; else - { - result = format->nt_headers.optional_header.header_64.data_directory; - - if (count != NULL) - *count = format->nt_headers.optional_header.header_64.number_of_rva_and_sizes; + ep = format->nt_headers.optional_header.header_64.address_of_entry_point; - } + result = g_executable_format_translate_address_into_vmpa(G_EXECUTABLE_FORMAT(format), ep, addr); return result; @@ -746,83 +808,75 @@ const image_data_directory *g_pe_format_get_directories(const GPeFormat *format, /****************************************************************************** * * -* Paramètres : format = format en place à consulter. * -* index = indice du répertoire visé. * +* Paramètres : format = informations chargées à consulter. * * * -* Description : Extrait le contenu d'un répertoire du format PE. * +* Description : Etend la définition des portions au sein d'un binaire. * * * -* Retour : Pointeur vers un contenu chargé ou NULL. * +* Retour : Bilan des définitions de portions. * * * * Remarques : - * * * ******************************************************************************/ -void *g_pe_format_get_directory(const GPeFormat *format, size_t index) +static bool g_pe_format_refine_portions(GPeFormat *format) { - void *result; /* Données à retourner */ - size_t max; /* Quantité de répertoires */ - const image_data_directory *dir; /* Localisation du répertoire */ - vmpa2t pos; /* Tête de lecture */ - bool status; /* Bilan d'un traitement */ - image_export_directory *export; /* Répertoire de type 0 */ - image_import_descriptor *imports; /* Répertoire de type 1 */ - size_t imported_count; /* Quantité de DLL requises */ + bool result; /* Bilan à retourner */ + vmpa2t origin; /* Origine d'une définition */ + uint16_t i; /* Boucle de parcours */ + image_section_header_t *section; /* Section à traiter */ + vmpa2t addr; /* Emplacement dans le binaire */ + GBinaryPortion *portion; /* Nouvelle portion de binaire */ + char name[IMAGE_SIZEOF_SHORT_NAME + 1]; /* Nom de la section */ + PortionAccessRights rights; /* Droits d'accès à la section */ - result = NULL; + result = true; - dir = g_pe_format_get_directories(format, &max); + copy_vmpa(&origin, &format->sections_start); - if (index >= max) - goto exit; + for (i = 0, section = format->sections; i < format->nt_headers.file_header.number_of_sections; i++, section++) + { + if (section->pointer_to_raw_data == 0) + continue; - dir += index; + /* Emplacement */ - status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), dir->virtual_address, &pos); - if (!status) goto exit; + init_vmpa(&addr, section->pointer_to_raw_data, section->virtual_address); - switch (index) - { - case IMAGE_DIRECTORY_ENTRY_EXPORT: + portion = g_binary_portion_new(&addr, section->size_of_raw_data); - export = malloc(sizeof(image_export_directory)); + /* Nom */ - status = read_pe_image_export_directory(format, &pos, export); + memcpy(name, section->name, IMAGE_SIZEOF_SHORT_NAME); + name[IMAGE_SIZEOF_SHORT_NAME] = '\0'; - if (!status) - { - free(export); - goto exit; - } + g_binary_portion_set_desc(portion, name); - result = export; - break; + /* Droits d'accès */ - case IMAGE_DIRECTORY_ENTRY_IMPORT: + rights = PAC_NONE; - imports = NULL; - imported_count = 0; + if (section->characteristics & IMAGE_SCN_MEM_EXECUTE) + rights |= PAC_EXEC; - do - { - imports = realloc(imports, ++imported_count * sizeof(image_import_descriptor)); + if (section->characteristics & IMAGE_SCN_MEM_READ) + rights |= PAC_READ; - status = read_pe_image_import_descriptor(format, &pos, imports + (imported_count - 1)); + if (section->characteristics & IMAGE_SCN_MEM_WRITE) + rights |= PAC_WRITE; - if (!status) - { - free(imports); - goto exit; - } + g_binary_portion_set_rights(portion, rights); - } - while (imports[imported_count - 1].original_first_thunk != 0); + /* Inclusion finale */ - result = imports; - break; + result = g_executable_format_include_portion(G_EXECUTABLE_FORMAT(format), portion, &origin); - } + unref_object(portion); - exit: + if (!result) break; + + advance_vmpa(&origin, sizeof(image_section_header_t)); + + } return result; |