From 461f42dd8eb8b1932c11364d9d15367eeb294848 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 24 Nov 2024 08:56:28 +0100 Subject: Restore and improve the support for PE files. --- plugins/Makefile.am | 3 +- plugins/pe/Makefile.am | 17 +- plugins/pe/core.c | 5 +- plugins/pe/core.h | 2 +- plugins/pe/format.c | 640 +++++++++++++++++++++++------------------- plugins/pe/format.h | 30 +- plugins/pe/pe-int.c | 24 +- plugins/pe/pe-int.h | 28 +- plugins/pe/pe_def.h | 55 ++-- plugins/pe/python/Makefile.am | 8 +- plugins/pe/python/constants.c | 5 +- plugins/pe/python/constants.h | 2 +- plugins/pe/python/format.c | 204 +++++++++----- plugins/pe/python/module.c | 6 +- plugins/pe/python/translate.c | 290 ++++++++++++++++++- plugins/pe/python/translate.h | 10 +- plugins/pe/section.c | 73 ----- plugins/pe/section.h | 38 --- 18 files changed, 870 insertions(+), 570 deletions(-) delete mode 100644 plugins/pe/section.c delete mode 100644 plugins/pe/section.h diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 9e177fa..89a8e25 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -13,7 +13,8 @@ endif # androhelpers SUBDIRS = \ - $(PYTHON3_SUBDIRS) + $(PYTHON3_SUBDIRS) \ + pe # arm \ # bootimg \ diff --git a/plugins/pe/Makefile.am b/plugins/pe/Makefile.am index e9cd482..fb04367 100644 --- a/plugins/pe/Makefile.am +++ b/plugins/pe/Makefile.am @@ -41,20 +41,23 @@ libpe_la_SOURCES = \ core.h core.c \ pe-int.h pe-int.c \ format.h format.c \ - pe_def.h \ - rich.h rich.c \ - routine.h routine.c \ - section.h section.c \ - symbols.h symbols.c + pe_def.h + + +# rich.h rich.c \ +# routine.h routine.c \ +# symbols.h symbols.c + + libpe_la_LIBADD = \ $(PYTHON3_LIBADD) -libpe_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src +libpe_la_CFLAGS = $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src libpe_la_LDFLAGS = \ -avoid-version \ - -L$(top_srcdir)/src/.libs -lchrysacore \ + -L$(top_srcdir)/src/.libs -lchrysacore4 \ $(RUN_PATH) $(PYTHON3_LDFLAGS) diff --git a/plugins/pe/core.c b/plugins/pe/core.c index ddbacf5..e8e6f5e 100644 --- a/plugins/pe/core.c +++ b/plugins/pe/core.c @@ -44,7 +44,7 @@ DEFINE_CHRYSALIDE_PLUGIN("Pe", "PE format support", PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/formats"), - PG_REQ, AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER)); + PG_REQ, AL(PGA_PLUGIN_INIT));//, PGA_CONTENT_RESOLVER)); @@ -90,7 +90,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) * Remarques : - * * * ******************************************************************************/ - +#if 0 G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status) { bool test; /* Bilan des accès mémoire */ @@ -114,3 +114,4 @@ G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule } } +#endif diff --git a/plugins/pe/core.h b/plugins/pe/core.h index 4497cf5..2d9aeb5 100644 --- a/plugins/pe/core.h +++ b/plugins/pe/core.h @@ -34,7 +34,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *); /* Procède à une opération liée à un contenu binaire. */ -G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *); +//G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *); 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 +#include #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; diff --git a/plugins/pe/format.h b/plugins/pe/format.h index a48e04d..5cc7c53 100644 --- a/plugins/pe/format.h +++ b/plugins/pe/format.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * pe.h - prototypes pour le support du format Portable Executable * - * Copyright (C) 2010-2017 Cyrille Bagard + * Copyright (C) 2010-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,31 +25,20 @@ #define _PLUGINS_PE_FORMAT_H -#include #include #include -#include +#include #include "pe_def.h" -#define G_TYPE_PE_FORMAT g_pe_format_get_type() -#define G_PE_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PE_FORMAT, GPeFormat)) -#define G_IS_PE_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PE_FORMAT)) -#define G_PE_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PE_FORMAT, GPeFormatClass)) -#define G_IS_PE_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PE_FORMAT)) -#define G_PE_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PE_FORMAT, GPeFormatClass)) +#define G_TYPE_PE_FORMAT (g_pe_format_get_type()) - -/* Format d'exécutable PE (instance) */ -typedef struct _GPeFormat GPeFormat; - -/* Format d'exécutable PE (classe) */ -typedef struct _GPeFormatClass GPeFormatClass; +DECLARE_GTYPE(GPeFormat, g_pe_format, G, PE_FORMAT); /* Valide un contenu comme étant un format PE. */ @@ -59,23 +48,26 @@ bool check_pe_format(const GBinContent *); GType g_pe_format_get_type(void); /* Prend en charge un nouveau format PE. */ -GExeFormat *g_pe_format_new(GBinContent *); +GPeFormat *g_pe_format_new(GBinContent *); /* Présente l'en-tête MS-DOS du format chargé. */ -const image_dos_header *g_pe_format_get_dos_header(const GPeFormat *); +const image_dos_header_t *g_pe_format_get_dos_header(const GPeFormat *); /* Présente l'en-tête NT du format chargé. */ -const image_nt_headers *g_pe_format_get_nt_headers(const GPeFormat *); +const image_nt_headers_t *g_pe_format_get_nt_headers(const GPeFormat *); /* Indique si le format PE est en 32 bits ou en 64 bits. */ bool g_pe_format_get_is_32b(const GPeFormat *); /* Offre un raccourci vers les répertoires du format PE. */ -const image_data_directory *g_pe_format_get_directories(const GPeFormat *, size_t *); +const image_data_directory_t *g_pe_format_get_directories(const GPeFormat *, size_t *); /* Extrait le contenu d'un répertoire du format PE. */ void *g_pe_format_get_directory(const GPeFormat *, size_t); +/* Offre un raccourci vers les sections du format PE. */ +const image_section_header_t *g_pe_format_get_sections(const GPeFormat *, size_t *); + #endif /* _PLUGINS_PE_FORMAT_H */ diff --git a/plugins/pe/pe-int.c b/plugins/pe/pe-int.c index 4104ce1..1c09929 100644 --- a/plugins/pe/pe-int.c +++ b/plugins/pe/pe-int.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include @@ -46,7 +46,7 @@ * * ******************************************************************************/ -bool read_dos_image_header(const GPeFormat *format, image_dos_header *header) +bool read_dos_image_header(const GPeFormat *format, image_dos_header_t *header) { bool result; /* Bilan à retourner */ const GBinContent *content; /* Contenu binaire à lire */ @@ -104,7 +104,7 @@ bool read_dos_image_header(const GPeFormat *format, image_dos_header *header) * * ******************************************************************************/ -bool read_pe_file_header(const GPeFormat *format, vmpa2t *pos, image_file_header *header) +bool read_pe_file_header(const GPeFormat *format, vmpa2t *pos, image_file_header_t *header) { bool result; /* Bilan à retourner */ const GBinContent *content; /* Contenu binaire à lire */ @@ -140,13 +140,13 @@ bool read_pe_file_header(const GPeFormat *format, vmpa2t *pos, image_file_header * * ******************************************************************************/ -bool read_pe_optional_header(const GPeFormat *format, vmpa2t *pos, image_optional_header *header) +bool read_pe_optional_header(const GPeFormat *format, vmpa2t *pos, image_optional_header_t *header) { bool result; /* Bilan à retourner */ const GBinContent *content; /* Contenu binaire à lire */ - image_optional_header_32 *hdr32; /* Version 32 bits */ - image_optional_header_64 *hdr64; /* Version 64 bits */ - image_data_directory *directories; /* Répertoires à charger */ + image_optional_header_32_t *hdr32; /* Version 32 bits */ + image_optional_header_64_t *hdr64; /* Version 64 bits */ + image_data_directory_t *directories; /* Répertoires à charger */ uint32_t *number_of_rva_and_sizes; /* Quantité de ces répertoires */ uint32_t i; /* Boucle de parcours */ @@ -278,7 +278,7 @@ bool read_pe_optional_header(const GPeFormat *format, vmpa2t *pos, image_optiona * * ******************************************************************************/ -bool read_pe_nt_header(const GPeFormat *format, image_nt_headers *header, vmpa2t *next) +bool read_pe_nt_header(const GPeFormat *format, image_nt_headers_t *header, vmpa2t *next) { bool result; /* Bilan à retourner */ const GBinContent *content; /* Contenu binaire à lire */ @@ -318,7 +318,7 @@ bool read_pe_nt_header(const GPeFormat *format, image_nt_headers *header, vmpa2t * * ******************************************************************************/ -bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_section_header *section) +bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_section_header_t *section) { bool result; /* Bilan à retourner */ const GBinContent *content; /* Contenu binaire à lire */ @@ -331,7 +331,7 @@ bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_se for (i = 0; i < IMAGE_SIZEOF_SHORT_NAME && result; i++) result = g_binary_content_read_u8(content, pos, (uint8_t *)§ion->name[i]); - if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->misc.physical_address); + if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->physical_address); if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->virtual_address); if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->size_of_raw_data); @@ -361,7 +361,7 @@ bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_se * * ******************************************************************************/ -bool read_pe_image_export_directory(const GPeFormat *format, vmpa2t *pos, image_export_directory *dir) +bool read_pe_image_export_directory(const GPeFormat *format, vmpa2t *pos, image_export_directory_t *dir) { bool result; /* Bilan à retourner */ const GBinContent *content; /* Contenu binaire à lire */ @@ -401,7 +401,7 @@ bool read_pe_image_export_directory(const GPeFormat *format, vmpa2t *pos, image_ * * ******************************************************************************/ -bool read_pe_image_import_descriptor(const GPeFormat *format, vmpa2t *pos, image_import_descriptor *desc) +bool read_pe_image_import_descriptor(const GPeFormat *format, vmpa2t *pos, image_import_descriptor_t *desc) { bool result; /* Bilan à retourner */ const GBinContent *content; /* Contenu binaire à lire */ diff --git a/plugins/pe/pe-int.h b/plugins/pe/pe-int.h index ebcf3f0..262fe1f 100644 --- a/plugins/pe/pe-int.h +++ b/plugins/pe/pe-int.h @@ -36,13 +36,14 @@ /* Format d'exécutable PE (instance) */ struct _GPeFormat { - GExeFormat parent; /* A laisser en premier */ + GExecutableFormat parent; /* A laisser en premier */ - image_dos_header dos_header; /* En-tête DOS */ + image_dos_header_t dos_header; /* En-tête DOS */ mrange_t rich_header; /* En-tête enrichi */ - image_nt_headers nt_headers; /* En-tête Windows */ + image_nt_headers_t nt_headers; /* En-tête Windows */ - image_section_header *sections; /* Liste des sections */ + vmpa2t sections_start; /* Début de la zone de sections*/ + image_section_header_t *sections; /* Liste des sections */ bool loaded; /* Détection partielle menée */ @@ -51,31 +52,34 @@ struct _GPeFormat /* Format d'exécutable PE (classe) */ struct _GPeFormatClass { - GExeFormatClass parent; /* A laisser en premier */ + GExecutableFormatClass parent; /* A laisser en premier */ }; +/* Met en place une nouvelle instance de format PE. */ +bool g_pe_format_create(GPeFormat *, GBinContent *); + /* Procède à la lecture d'un en-tête de programme DOS. */ -bool read_dos_image_header(const GPeFormat *, image_dos_header *); +bool read_dos_image_header(const GPeFormat *, image_dos_header_t *); /* Procède à la lecture d'un en-tête de programme PE (1). */ -bool read_pe_file_header(const GPeFormat *, vmpa2t *, image_file_header *); +bool read_pe_file_header(const GPeFormat *, vmpa2t *, image_file_header_t *); /* Procède à la lecture d'un en-tête de programme PE (2). */ -bool read_pe_optional_header(const GPeFormat *, vmpa2t *, image_optional_header *); +bool read_pe_optional_header(const GPeFormat *, vmpa2t *, image_optional_header_t *); /* Procède à la lecture d'un en-tête de programme PE. */ -bool read_pe_nt_header(const GPeFormat *, image_nt_headers *, vmpa2t *); +bool read_pe_nt_header(const GPeFormat *, image_nt_headers_t *, vmpa2t *); /* Procède à la lecture d'un en-tête de section PE. */ -bool read_pe_image_section_header(const GPeFormat *, vmpa2t *, image_section_header *); +bool read_pe_image_section_header(const GPeFormat *, vmpa2t *, image_section_header_t *); /* Procède à la lecture d'un répertoire d'exportations. */ -bool read_pe_image_export_directory(const GPeFormat *, vmpa2t *, image_export_directory *); +bool read_pe_image_export_directory(const GPeFormat *, vmpa2t *, image_export_directory_t *); /* Procède à la lecture d'un répertoire de programme PE. */ -bool read_pe_image_import_descriptor(const GPeFormat *, vmpa2t *, image_import_descriptor *); +bool read_pe_image_import_descriptor(const GPeFormat *, vmpa2t *, image_import_descriptor_t *); diff --git a/plugins/pe/pe_def.h b/plugins/pe/pe_def.h index 62b4607..4812897 100644 --- a/plugins/pe/pe_def.h +++ b/plugins/pe/pe_def.h @@ -31,6 +31,7 @@ /** * Références : * + * - https://learn.microsoft.com/en-us/windows/win32/debug/pe-format * - https://fr.wikipedia.org/wiki/Portable_Executable#En-tête_MZ_sous_MS-DOS * - https://www.nirsoft.net/kernel_struct/vista/IMAGE_DOS_HEADER.html * @@ -42,7 +43,7 @@ /* En-tête DOS */ -typedef struct _image_dos_header +typedef struct _image_dos_header_t { uint16_t e_magic; /* Numéro magique */ uint16_t e_cblp; /* Octets de la dernière page */ @@ -64,7 +65,7 @@ typedef struct _image_dos_header uint16_t e_res2[10]; /* Mots réservés */ uint32_t e_lfanew; /* Décalage de bon en-tête */ -} image_dos_header; +} image_dos_header_t; /* Archtectures supportées */ @@ -123,7 +124,7 @@ typedef struct _image_dos_header #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 /* Octets inv. ; obsolète */ /* Première en-tête du "vrai" format */ -typedef struct _image_file_header +typedef struct _image_file_header_t { uint16_t machine; /* Type de machine visée */ uint16_t number_of_sections; /* Nombre de sections */ @@ -133,7 +134,7 @@ typedef struct _image_file_header 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; +} image_file_header_t; @@ -148,12 +149,12 @@ typedef struct _image_file_header */ /* Zone de données Windows */ -typedef struct _image_data_directory +typedef struct _image_data_directory_t { uint32_t virtual_address; /* Adresse de la table */ uint32_t size; /* Taille de la table */ -} image_data_directory; +} image_data_directory_t; // Directory Entries #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory @@ -182,7 +183,7 @@ typedef struct _image_data_directory /* Seconde en-tête, optionnelle */ -typedef struct _image_optional_header_32 +typedef struct _image_optional_header_32_t { uint16_t magic; /* Type de binaire manipulé */ uint8_t major_linker_version; /* Version majeure du linker */ @@ -214,11 +215,11 @@ typedef struct _image_optional_header_32 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_data_directory_t data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; -} image_optional_header_32; +} image_optional_header_32_t; -typedef struct _image_optional_header_64 +typedef struct _image_optional_header_64_t { uint16_t magic; /* Type de binaire manipulé */ @@ -250,16 +251,16 @@ typedef struct _image_optional_header_64 uint64_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_data_directory_t data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; -} image_optional_header_64; +} image_optional_header_64_t; -typedef union _image_optional_header +typedef union _image_optional_header_t { - image_optional_header_32 header_32; /* Version 32 bits */ - image_optional_header_64 header_64; /* Version 64 bits */ + image_optional_header_32_t header_32; /* Version 32 bits */ + image_optional_header_64_t header_64; /* Version 64 bits */ -} image_optional_header; +} image_optional_header_t; @@ -302,13 +303,13 @@ typedef union _image_optional_header /* Résumé global */ -typedef struct _image_nt_headers +typedef struct _image_nt_headers_t { 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_file_header_t file_header; /* En-tête n°1 */ + image_optional_header_t optional_header;/* En-tête n°2 */ -} image_nt_headers; +} image_nt_headers_t; @@ -322,7 +323,7 @@ typedef struct _image_nt_headers #define IMAGE_SIZEOF_SHORT_NAME 8 /* Description d'une section */ -typedef struct _image_section_header +typedef struct _image_section_header_t { char name[IMAGE_SIZEOF_SHORT_NAME]; /* Nom de la section */ @@ -331,7 +332,7 @@ typedef struct _image_section_header 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 définies */ @@ -342,7 +343,7 @@ typedef struct _image_section_header uint16_t number_of_line_numbers; /* Quantité de numéros de ligne*/ uint32_t characteristics; /* Caractéristiques */ -} image_section_header; +} image_section_header_t; /* Détails des caractéristiques d'une image (champ 'characteristics') */ #define IMAGE_SCN_UNKNOWN_0 0x00000000 /* Réservé */ @@ -400,7 +401,7 @@ typedef struct _image_section_header */ /* Répertoire des importations */ -typedef struct _image_export_directory +typedef struct _image_export_directory_t { uint32_t characteristics; /* Zéro !? */ uint32_t time_date_stamp; /* Date de création du fichier */ @@ -414,7 +415,7 @@ typedef struct _image_export_directory uint32_t address_of_names; /* Liste de RVA de noms */ uint32_t address_of_name_ordinals; /* Liste de RVA d'ordinaux */ -} image_export_directory; +} image_export_directory_t; /** @@ -427,7 +428,7 @@ typedef struct _image_export_directory */ /* Point de départ de la chaîne des importations */ -typedef struct _image_import_descriptor +typedef struct _image_import_descriptor_t { uint32_t original_first_thunk; uint32_t time_date_stamp; @@ -435,7 +436,7 @@ typedef struct _image_import_descriptor uint32_t module_name; uint32_t first_thunk; -} image_import_descriptor; +} image_import_descriptor_t; diff --git a/plugins/pe/python/Makefile.am b/plugins/pe/python/Makefile.am index 5949821..4a70769 100644 --- a/plugins/pe/python/Makefile.am +++ b/plugins/pe/python/Makefile.am @@ -1,14 +1,16 @@ noinst_LTLIBRARIES = libpepython.la +# libpepython_la_SOURCES = \ +# constants.h constants.c \ +# routine.h routine.c + libpepython_la_SOURCES = \ - constants.h constants.c \ format.h format.c \ module.h module.c \ - routine.h routine.c \ translate.h translate.c -libpepython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +libpepython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT diff --git a/plugins/pe/python/constants.c b/plugins/pe/python/constants.c index 9b4942d..bb10a7e 100644 --- a/plugins/pe/python/constants.c +++ b/plugins/pe/python/constants.c @@ -29,7 +29,7 @@ #include "../pe_def.h" -#include "../routine.h" +//#include "../routine.h" @@ -101,7 +101,7 @@ bool define_python_pe_format_constants(PyTypeObject *type) * Remarques : - * * * ******************************************************************************/ - +#if 0 bool define_python_pe_exported_routine_constants(PyTypeObject *type) { bool result; /* Bilan à retourner */ @@ -141,3 +141,4 @@ bool define_python_pe_exported_routine_constants(PyTypeObject *type) return result; } +#endif diff --git a/plugins/pe/python/constants.h b/plugins/pe/python/constants.h index 25b0adb..fe4293c 100644 --- a/plugins/pe/python/constants.h +++ b/plugins/pe/python/constants.h @@ -35,7 +35,7 @@ bool define_python_pe_format_constants(PyTypeObject *); /* Définit les constantes pour les routines du format PE. */ -bool define_python_pe_exported_routine_constants(PyTypeObject *); +//bool define_python_pe_exported_routine_constants(PyTypeObject *); diff --git a/plugins/pe/python/format.c b/plugins/pe/python/format.c index 4bbb99a..6c97c7d 100644 --- a/plugins/pe/python/format.c +++ b/plugins/pe/python/format.c @@ -28,25 +28,23 @@ #include -#include #include #include #include #include -#include "constants.h" +//#include "constants.h" #include "translate.h" -#include "../format.h" -#include "../rich.h" +#include "../pe-int.h" +//#include "../rich.h" /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_pe_format_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(pe_format, G_TYPE_PE_FORMAT); /* Initialise une instance sur la base du dérivé de GObject. */ static int py_pe_format_init(PyObject *, PyObject *, PyObject *); @@ -59,9 +57,15 @@ static int py_pe_format_init(PyObject *, PyObject *, PyObject *); /* Présente l'en-tête MS-DOS du format chargé. */ static PyObject *py_pe_format_get_dos_header(PyObject *, void *); +/* Présente l'en-tête NT du format chargé. */ +static PyObject *py_pe_format_get_nt_headers(PyObject *, void *); + /* Offre un raccourci vers les répertoires du format PE. */ static PyObject *py_pe_format_get_directories(PyObject *, void *); +/* Offre un raccourci vers les sections du format PE. */ +static PyObject *py_pe_format_get_sections(PyObject *, void *); + /* Présente l'en-tête enrichi du format chargé. */ static PyObject *py_pe_format_get_rich_header(PyObject *, void *); @@ -80,66 +84,6 @@ static PyObject *py_pe_format_get_comp_ids(PyObject *, void *); /****************************************************************************** * * -* Paramètres : type = type du nouvel objet à mettre en place. * -* args = éventuelle liste d'arguments. * -* kwds = éventuel dictionnaire de valeurs mises à disposition. * -* * -* Description : Accompagne la création d'une instance dérivée en Python. * -* * -* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_pe_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *result; /* Objet à retourner */ - PyTypeObject *base; /* Type de base à dériver */ - bool first_time; /* Evite les multiples passages*/ - GType gtype; /* Nouveau type de processeur */ - bool status; /* Bilan d'un enregistrement */ - - /* Validations diverses */ - - base = get_python_pe_format_type(); - - if (type == base) - goto simple_way; - - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); - - gtype = build_dynamic_type(G_TYPE_PE_FORMAT, type->tp_name, NULL, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); - - if (!status) - { - result = NULL; - goto exit; - } - - } - - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - - simple_way: - - result = PyType_GenericNew(type, args, kwds); - - exit: - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * @@ -183,7 +127,8 @@ static int py_pe_format_init(PyObject *self, PyObject *args, PyObject *kwds) format = G_PE_FORMAT(pygobject_get(self)); - g_known_format_set_content(G_KNOWN_FORMAT(format), content); + if (!g_pe_format_create(format, content)) + return -1; return 0; @@ -223,7 +168,6 @@ static PyObject *py_pe_format_get_dos_header(PyObject *self, void *closure) "\n" \ "The provided information is composed of the following" \ " properties :\n" \ - "\n" \ "* e_magic;\n" \ "* e_cblp;\n" \ "* e_cp;\n" \ @@ -259,6 +203,52 @@ static PyObject *py_pe_format_get_dos_header(PyObject *self, void *closure) * Paramètres : self = format en place à consulter. * * closure = non utilisé ici. * * * +* Description : Présente l'en-tête NT du format chargé. * +* * +* Retour : Structure Python créée pour l'occasion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_format_get_nt_headers(PyObject *self, void *closure) +{ + PyObject *result; /* Trouvaille à retourner */ + GPeFormat *format; /* Version GLib du format */ + +#define PE_FORMAT_NT_HEADERS_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + nt_headers, py_pe_format, \ + "NT headers of the file format.\n" \ + "\n" \ + "This property is a pychrysalide.StructObject instance." \ + "\n" \ + "The provided information is composed of the following" \ + " properties :\n" \ + "* signature;\n" \ + "* file_header;\n" \ + "* optional_header.\n" \ + "\n" \ + "The last two fields are pychrysalide.StructObject" \ + " which contain more fields. These fields can be" \ + " enumerated with the keys() method (for instance:" \ + " *mype.nt_headers.file_header.keys()*).\n" \ +) + + format = G_PE_FORMAT(pygobject_get(self)); + + result = translate_pe_nt_headers_to_python(format, g_pe_format_get_nt_headers(format)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format en place à consulter. * +* closure = non utilisé ici. * +* * * Description : Offre un raccourci vers les répertoires du format PE. * * * * Retour : Structure Python créée pour l'occasion. * @@ -272,7 +262,7 @@ static PyObject *py_pe_format_get_directories(PyObject *self, void *closure) PyObject *result; /* Trouvaille à retourner */ GPeFormat *format; /* Version GLib du format */ size_t count; /* Quantité de répertoires */ - const image_data_directory *directories; /* Répertoires à exporter */ + const image_data_directory_t *directories; /* Répertoires à exporter */ size_t i; /* Boucle de parcours */ PyObject *item; /* Elément de tableau */ int ret; /* Bilan d'une mise en place */ @@ -323,6 +313,76 @@ static PyObject *py_pe_format_get_directories(PyObject *self, void *closure) * Paramètres : self = format en place à consulter. * * closure = non utilisé ici. * * * +* Description : Offre un raccourci vers les sections du format PE. * +* * +* Retour : Structure Python créée pour l'occasion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_format_get_sections(PyObject *self, void *closure) +{ + PyObject *result; /* Trouvaille à retourner */ + GPeFormat *format; /* Version GLib du format */ + size_t count; /* Quantité de répertoires */ + const image_section_header_t *sections; /* Sections à exporter */ + size_t i; /* Boucle de parcours */ + PyObject *item; /* Elément de tableau */ + int ret; /* Bilan d'une mise en place */ + +#define PE_FORMAT_SECTIONS_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + sections, py_pe_format, \ + "Shortcut to the definitions of all PE format sections.\n" \ + "\n" \ + "This property is a pychrysalide.StructObject instance.\n" \ + "\n" \ + "Each returned item is composed of the following properties :\n"\ + "\n" \ + "* name;\n" \ + "* misc.virtual_size;\n" \ + "* virtual_address;\n" \ + "* size_of_raw_data;\n" \ + "* pointer_to_raw_data;\n" \ + "* pointer_to_relocations;\n" \ + "* pointer_to_line_numbers;\n" \ + "* number_of_relocations;\n" \ + "* number_of_line_numbers;\n" \ + "* characteristics." \ +) + + format = G_PE_FORMAT(pygobject_get(self)); + + sections = g_pe_format_get_sections(format, &count); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + item = translate_pe_section_header_to_python(format, sections + i); + + ret = PyTuple_SetItem(result, i, item); + + if (ret != 0) + { + Py_DECREF(result); + result = NULL; + break; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format en place à consulter. * +* closure = non utilisé ici. * +* * * Description : Présente l'en-tête enrichi du format chargé. * * * * Retour : Tableau de valeurs brutes d'information. * @@ -487,7 +547,9 @@ PyTypeObject *get_python_pe_format_type(void) static PyGetSetDef py_pe_format_getseters[] = { PE_FORMAT_DOS_HEADER_ATTRIB, + PE_FORMAT_NT_HEADERS_ATTRIB, PE_FORMAT_DIRECTORIES_ATTRIB, + PE_FORMAT_SECTIONS_ATTRIB, PE_FORMAT_RICH_HEADER_ATTRIB, PE_FORMAT_RICH_HEADER_CHECKSUM_ATTRIB, PE_FORMAT_COMP_IDS_ATTRIB, @@ -545,8 +607,8 @@ bool register_python_pe_format(PyObject *module) if (!register_class_for_pygobject(dict, G_TYPE_PE_FORMAT, type)) return false; - if (!define_python_pe_format_constants(type)) - return false; + //if (!define_python_pe_format_constants(type)) + // return false; return true; diff --git a/plugins/pe/python/module.c b/plugins/pe/python/module.c index 93b1337..ce0c8d7 100644 --- a/plugins/pe/python/module.c +++ b/plugins/pe/python/module.c @@ -33,7 +33,7 @@ #include "format.h" -#include "routine.h" +//#include "routine.h" @@ -83,8 +83,8 @@ bool add_format_pe_module_to_python_module(void) result = (module != NULL); if (result) result = register_python_pe_format(module); - if (result) result = register_python_pe_exported_routine(module); - if (result) result = register_python_pe_imported_routine(module); + //if (result) result = register_python_pe_exported_routine(module); + //if (result) result = register_python_pe_imported_routine(module); assert(result); diff --git a/plugins/pe/python/translate.c b/plugins/pe/python/translate.c index c01a337..1b4b3ce 100644 --- a/plugins/pe/python/translate.c +++ b/plugins/pe/python/translate.c @@ -45,7 +45,7 @@ * * ******************************************************************************/ -PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_header *header) +PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_header_t *header) { PyObject *result; /* Construction à retourner */ PyTypeObject *base; /* Modèle d'objet à créer */ @@ -64,6 +64,7 @@ PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_h { \ attrib = PyLong_FromUnsignedLongLong(header->e_ ## _f); \ ret = PyDict_SetItemString(result, "e_" #_f, attrib); \ + Py_DECREF(attrib); \ if (ret != 0) goto failed; \ } \ while (0); @@ -79,8 +80,13 @@ PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_h ret = PyTuple_SetItem(attrib, i, item); \ if (ret != 0) break; \ } \ - if (ret != 0) goto failed; \ + if (i < _n) \ + { \ + Py_DECREF(attrib); \ + goto failed; \ + } \ ret = PyDict_SetItemString(result, "e_" #_f, attrib); \ + Py_DECREF(attrib); \ if (ret != 0) goto failed; \ } \ while (0); @@ -119,6 +125,215 @@ PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_h /****************************************************************************** * * * Paramètres : format = format PE chargé sur lequel s'appuyer. * +* header = en-tête NT à décrire en Python. * +* * +* Description : Traduit un en-tête PE en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_pe_nt_headers_to_python(GPeFormat *format, const image_nt_headers_t *header) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + PyObject *sub; /* Sous-construction #1 */ + bool is_32b; /* Format en version 32 bits ? */ + const image_data_directory_t *directories; /* Répertoires à charger */ + uint32_t number_of_rva_and_sizes; /* Quantité de ces répertoires */ + uint32_t i; /* Boucle de parcours */ + PyObject *dirs; /* Répertoires de données */ + PyObject *subsub; /* Sous-construction #2 */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + +#define TRANSLATE_IMAGE_NT_HEADERS_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(header->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + Py_DECREF(attrib); \ + if (ret != 0) goto failed; \ + } \ + while (0); + + TRANSLATE_IMAGE_NT_HEADERS_FIELD(signature); + + /* Partie file_header */ + + sub = PyObject_CallFunction((PyObject *)base, NULL); + assert(sub != NULL); + +#define TRANSLATE_IMAGE_FILE_HEADER_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(header->file_header._f); \ + ret = PyDict_SetItemString(sub, #_f, attrib); \ + Py_DECREF(attrib); \ + if (ret != 0) \ + { \ + Py_DECREF(sub); \ + goto failed; \ + } \ + } \ + while (0); + + TRANSLATE_IMAGE_FILE_HEADER_FIELD(machine); + TRANSLATE_IMAGE_FILE_HEADER_FIELD(number_of_sections); + TRANSLATE_IMAGE_FILE_HEADER_FIELD(time_date_stamp); + TRANSLATE_IMAGE_FILE_HEADER_FIELD(pointer_to_symbol_table); + TRANSLATE_IMAGE_FILE_HEADER_FIELD(number_of_symbols); + TRANSLATE_IMAGE_FILE_HEADER_FIELD(size_of_optional_header); + TRANSLATE_IMAGE_FILE_HEADER_FIELD(characteristics); + + ret = PyDict_SetItemString(result, "file_header", sub); + Py_DECREF(sub); + if (ret != 0) goto failed; + + /* Partie optional_header */ + + sub = PyObject_CallFunction((PyObject *)base, NULL); + assert(sub != NULL); + + is_32b = g_pe_format_get_is_32b(format); + +#define TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(_f) \ + do \ + { \ + if (is_32b) \ + attrib = PyLong_FromUnsignedLongLong(header->optional_header.header_32._f); \ + else \ + attrib = PyLong_FromUnsignedLongLong(header->optional_header.header_64._f); \ + ret = PyDict_SetItemString(sub, #_f, attrib); \ + Py_DECREF(attrib); \ + if (ret != 0) \ + { \ + Py_DECREF(sub); \ + goto failed; \ + } \ + } \ + while (0); + +#define TRANSLATE_IMAGE_OPTIONAL_HEADER_32B_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(header->optional_header.header_32._f); \ + ret = PyDict_SetItemString(sub, #_f, attrib); \ + Py_DECREF(attrib); \ + if (ret != 0) \ + { \ + Py_DECREF(sub); \ + goto failed; \ + } \ + } \ + while (0); + + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(magic); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(major_linker_version); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(minor_linker_version); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_code); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_initialized_data); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_uninitialized_data); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(address_of_entry_point); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(base_of_code); + if (is_32b) TRANSLATE_IMAGE_OPTIONAL_HEADER_32B_FIELD(base_of_data); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(image_base); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(section_alignment); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(file_alignment); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(major_operating_system_version); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(minor_operating_system_version); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(major_image_version); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(minor_image_version); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(major_subsystem_version); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(minor_subsystem_version); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(win32_version_value); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_image); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_headers); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(checksum); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(subsystem); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(dll_characteristics); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_stack_reserve); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_stack_commit); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_heap_reserve); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(size_of_heap_commit); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(loader_flags); + TRANSLATE_IMAGE_OPTIONAL_HEADER_FIELD(number_of_rva_and_sizes); + + ret = PyDict_SetItemString(result, "optional_header", sub); + Py_DECREF(sub); + if (ret != 0) goto failed; + + /* Répertoires de données */ + + if (is_32b) + { + directories = header->optional_header.header_32.data_directory; + number_of_rva_and_sizes = header->optional_header.header_32.number_of_rva_and_sizes; + } + else + { + directories = header->optional_header.header_64.data_directory; + number_of_rva_and_sizes = header->optional_header.header_64.number_of_rva_and_sizes; + } + + dirs = PyTuple_New(number_of_rva_and_sizes); + + for (i = 0; i < number_of_rva_and_sizes; i++) + { + subsub = translate_pe_image_data_directory_to_python(format, directories + i); + if (subsub == NULL) break; + + ret = PyTuple_SetItem(dirs, i, subsub); + if (ret != 0) break; + + } + + if (i < number_of_rva_and_sizes) + goto failed_with_dirs; + + /** + * La fonction PyTuple_SetItem() comporte le prologue suivant : + * + * if (!PyTuple_Check(op) || Py_REFCNT(op) != 1) { + * Py_XDECREF(newitem); + * PyErr_BadInternalCall(); + * return -1; + * } + * + * Comme l'appel à PyDict_SetItemString() incrémente le compte de référence + * de dirs, il convient de le réaliser après la consitution de la liste. + */ + + ret = PyDict_SetItemString(sub, "directories", dirs); + if (ret != 0) goto failed_with_dirs; + + Py_DECREF(dirs); + + return result; + + failed_with_dirs: + + Py_DECREF(dirs); + + failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format PE chargé sur lequel s'appuyer. * * dir = répertoire PE à décrire en Python. * * * * Description : Traduit un répertoire PE en Python. * @@ -129,7 +344,7 @@ PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_h * * ******************************************************************************/ -PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const image_data_directory *dir) +PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const image_data_directory_t *dir) { PyObject *result; /* Construction à retourner */ PyTypeObject *base; /* Modèle d'objet à créer */ @@ -146,6 +361,7 @@ PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const i { \ attrib = PyLong_FromUnsignedLongLong(dir->_f); \ ret = PyDict_SetItemString(result, #_f, attrib); \ + Py_DECREF(attrib); \ if (ret != 0) goto failed; \ } \ while (0); @@ -167,6 +383,73 @@ PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const i /****************************************************************************** * * * Paramètres : format = format PE chargé sur lequel s'appuyer. * +* header = en-tête de section à décrire en Python. * +* * +* Description : Traduit une section PE en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_pe_section_header_to_python(GPeFormat *format, const image_section_header_t *header) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Nom de la section */ + + attrib = PyBytes_FromStringAndSize(header->name, IMAGE_SIZEOF_SHORT_NAME); + + ret = PyDict_SetItemString(result, "name", attrib); + Py_DECREF(attrib); + + if (ret != 0) goto failed; + + /* Eléments classiques */ + +#define TRANSLATE_IMAGE_SECTION_HEADER_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(header->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + Py_DECREF(attrib); \ + if (ret != 0) goto failed; \ + } \ + while (0); + + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(virtual_size); + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(virtual_address); + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(size_of_raw_data); + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(pointer_to_raw_data); + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(pointer_to_relocations); + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(pointer_to_line_numbers); + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(number_of_relocations); + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(number_of_line_numbers); + TRANSLATE_IMAGE_SECTION_HEADER_FIELD(characteristics); + + return result; + + failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format PE chargé sur lequel s'appuyer. * * id = ensemble d'informations à décrire en Python. * * * * Description : Traduit une série d'informations enrichies en Python. * @@ -194,6 +477,7 @@ PyObject *translate_pe_comp_id_to_python(GPeFormat *format, const comp_id_t *id) { \ attrib = PyLong_FromUnsignedLongLong(id->_f); \ ret = PyDict_SetItemString(result, #_f, attrib); \ + Py_DECREF(attrib); \ if (ret != 0) goto failed; \ } \ while (0); diff --git a/plugins/pe/python/translate.h b/plugins/pe/python/translate.h index dbde6c8..e12b4ae 100644 --- a/plugins/pe/python/translate.h +++ b/plugins/pe/python/translate.h @@ -35,10 +35,16 @@ /* Traduit un en-tête MS-DOS en Python. */ -PyObject *translate_pe_dos_header_to_python(GPeFormat *, const image_dos_header *); +PyObject *translate_pe_dos_header_to_python(GPeFormat *, const image_dos_header_t *); + +/* Traduit un en-tête PE en Python. */ +PyObject *translate_pe_nt_headers_to_python(GPeFormat *, const image_nt_headers_t *); /* Traduit un répertoire PE en Python. */ -PyObject *translate_pe_image_data_directory_to_python(GPeFormat *, const image_data_directory *); +PyObject *translate_pe_image_data_directory_to_python(GPeFormat *, const image_data_directory_t *); + +/* Traduit une section PE en Python. */ +PyObject *translate_pe_section_header_to_python(GPeFormat *, const image_section_header_t *); /* Traduit une série d'informations enrichies en Python. */ PyObject *translate_pe_comp_id_to_python(GPeFormat *, const comp_id_t *); diff --git a/plugins/pe/section.c b/plugins/pe/section.c deleted file mode 100644 index 732b35c..0000000 --- a/plugins/pe/section.c +++ /dev/null @@ -1,73 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * section.h - prototypes pour la gestion des sections d'un PE - * - * Copyright (C) 2010-2021 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide 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. - * - * Chrysalide 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 Chrysalide. If not, see . - */ - - -#include "section.h" - - -#include - - -#include "pe-int.h" - - - -/****************************************************************************** -* * -* Paramètres : format = description de l'exécutable à consulter. * -* pos = tête de lecture positionnée. [OUT] * -* * -* Description : Recherche une section donnée au sein de binaire par indice. * -* * -* Retour : Liste de sections reconstituées ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -image_section_header *read_all_pe_sections(const GPeFormat *format, vmpa2t *pos) -{ - image_section_header *result; /* Liste à retourner */ - uint16_t count; /* Quantité de sections */ - uint16_t i; /* Boucle de parcours */ - bool status; /* Bilan d'une lecture */ - - count = format->nt_headers.file_header.number_of_sections; - - result = malloc(count * sizeof(image_section_header)); - - for (i = 0; i < count; i++) - { - status = read_pe_image_section_header(format, pos, &result[i]); - - if (!status) - { - free(result); - result = NULL; - break; - } - - } - - return result; - -} diff --git a/plugins/pe/section.h b/plugins/pe/section.h deleted file mode 100644 index 2ac21d3..0000000 --- a/plugins/pe/section.h +++ /dev/null @@ -1,38 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * section.h - prototypes pour la gestion des sections d'un PE - * - * Copyright (C) 2010-2017 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide 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. - * - * Chrysalide 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 Chrysalide. If not, see . - */ - - -#ifndef _PLUGINS_PE_SECTION_H -#define _PLUGINS_PE_SECTION_H - - -#include "format.h" -#include "pe_def.h" - - - -/* Recherche une section donnée au sein de binaire par indice. */ -image_section_header *read_all_pe_sections(const GPeFormat *, vmpa2t *); - - - -#endif /* _PLUGINS_PE_SECTION_H */ -- cgit v0.11.2-87-g4458