summaryrefslogtreecommitdiff
path: root/plugins/pe
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pe')
-rw-r--r--plugins/pe/Makefile.am17
-rw-r--r--plugins/pe/core.c5
-rw-r--r--plugins/pe/core.h2
-rw-r--r--plugins/pe/format.c640
-rw-r--r--plugins/pe/format.h30
-rw-r--r--plugins/pe/pe-int.c24
-rw-r--r--plugins/pe/pe-int.h28
-rw-r--r--plugins/pe/pe_def.h55
-rw-r--r--plugins/pe/python/Makefile.am8
-rw-r--r--plugins/pe/python/constants.c5
-rw-r--r--plugins/pe/python/constants.h2
-rw-r--r--plugins/pe/python/format.c204
-rw-r--r--plugins/pe/python/module.c6
-rw-r--r--plugins/pe/python/translate.c290
-rw-r--r--plugins/pe/python/translate.h10
-rw-r--r--plugins/pe/section.c73
-rw-r--r--plugins/pe/section.h38
17 files changed, 868 insertions, 569 deletions
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 <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;
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 <glib-object.h>
#include <stdbool.h>
#include <analysis/content.h>
-#include <format/executable.h>
+#include <glibext/helpers.h>
#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 <string.h>
#include <i18n.h>
-#include <common/endianness.h>
+#include <common/datatypes.h>
#include <core/logs.h>
@@ -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 *)&section->name[i]);
- if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->misc.physical_address);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->physical_address);
if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->virtual_address);
if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->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 <pygobject.h>
-#include <format/known.h>
#include <plugins/dt.h>
#include <plugins/pychrysalide/helpers.h>
#include <plugins/pychrysalide/analysis/content.h>
#include <plugins/pychrysalide/format/executable.h>
-#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 <http://www.gnu.org/licenses/>.
- */
-
-
-#include "section.h"
-
-
-#include <malloc.h>
-
-
-#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 <http://www.gnu.org/licenses/>.
- */
-
-
-#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 */