summaryrefslogtreecommitdiff
path: root/plugins/pe/format.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pe/format.c')
-rw-r--r--plugins/pe/format.c640
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, &section_start);
- if (!result) goto error;
+ const image_nt_headers_t *result; /* Informations à retourner */
- format->sections = read_all_pe_sections(format, &section_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;