summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am1
-rw-r--r--plugins/elf/symbols.c6
-rw-r--r--plugins/pe/Makefile.am50
-rw-r--r--plugins/pe/core.c117
-rw-r--r--plugins/pe/core.h41
-rw-r--r--plugins/pe/format.c714
-rw-r--r--plugins/pe/format.h34
-rw-r--r--plugins/pe/pe-int.c364
-rw-r--r--plugins/pe/pe-int.h48
-rw-r--r--plugins/pe/pe_def.h165
-rw-r--r--plugins/pe/python/Makefile.am23
-rw-r--r--plugins/pe/python/constants.c143
-rw-r--r--plugins/pe/python/constants.h42
-rw-r--r--plugins/pe/python/format.c595
-rw-r--r--plugins/pe/python/format.h45
-rw-r--r--plugins/pe/python/module.c93
-rw-r--r--plugins/pe/python/module.h38
-rw-r--r--plugins/pe/python/routine.c472
-rw-r--r--plugins/pe/python/routine.h62
-rw-r--r--plugins/pe/python/translate.c213
-rw-r--r--plugins/pe/python/translate.h48
-rw-r--r--plugins/pe/rich.c312
-rw-r--r--plugins/pe/rich.h61
-rw-r--r--plugins/pe/routine.c429
-rw-r--r--plugins/pe/routine.h111
-rw-r--r--plugins/pe/section.c36
-rw-r--r--plugins/pe/section.h10
-rw-r--r--plugins/pe/symbols.c335
-rw-r--r--plugins/pe/symbols.h15
-rw-r--r--plugins/pychrysalide/format/constants.c1
30 files changed, 4255 insertions, 369 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 678e315..e9258df 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -22,6 +22,7 @@ SUBDIRS = \
libcsem \
lnxsyscalls \
mobicore \
+ pe \
readdex \
readelf \
readmc \
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index a7cf05c..6d037cb 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -1195,11 +1195,11 @@ static bool register_elf_entry_point(GElfFormat *format, virt_t vaddr, GBinRouti
result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_vaddr, &addr);
if (!result) goto exit;
- base = G_BIN_FORMAT(format);
-
/* Comptabilisation en tant que symbole */
- if (g_binary_format_find_symbol_at(G_BIN_FORMAT(format), &addr, &symbol))
+ base = G_BIN_FORMAT(format);
+
+ if (g_binary_format_find_symbol_at(base, &addr, &symbol))
{
/**
* On ne relâche pas tout de suite le symbole trouvé, afin de le traiter
diff --git a/plugins/pe/Makefile.am b/plugins/pe/Makefile.am
index 00050a5..8e9bca6 100644
--- a/plugins/pe/Makefile.am
+++ b/plugins/pe/Makefile.am
@@ -1,21 +1,57 @@
-noinst_LTLIBRARIES = libformatpe.la
+DEFAULT_INCLUDES = -idirafter. -I$(top_builddir)
-libformatpe_la_SOURCES = \
+lib_LTLIBRARIES = libpe.la
+
+libdir = $(pluginslibdir)
+
+
+if BUILD_PYTHON3_BINDINGS
+
+PYTHON3_LIBADD = python/libpepython.la
+
+if BUILD_DISCARD_LOCAL
+
+PYTHON3_LDFLAGS = -Wl,-rpath,$(pluginslibdir) \
+ -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+else
+
+PYTHON3_LDFLAGS = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs \
+ -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so
+
+endif
+
+PYTHON3_SUBDIRS = python
+
+endif
+
+
+libpe_la_SOURCES = \
+ core.h core.c \
pe-int.h pe-int.c \
- pe.h pe.c \
+ format.h format.c \
pe_def.h \
+ rich.h rich.c \
+ routine.h routine.c \
section.h section.c \
symbols.h symbols.c
-libformatpe_la_LDFLAGS =
+libpe_la_LIBADD = \
+ $(PYTHON3_LIBADD)
+
+libpe_la_LDFLAGS = \
+ -L$(top_srcdir)/src/.libs -lchrysacore \
+ $(PYTHON3_LDFLAGS)
-devdir = $(includedir)/chrysalide/$(subdir:src/%=%)
+devdir = $(includedir)/chrysalide/$(subdir)
-dev_HEADERS = $(libformatpe_la_SOURCES:%c=)
+dev_HEADERS = $(libpe_la_SOURCES:%c=)
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src
AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS = $(PYTHON3_SUBDIRS)
diff --git a/plugins/pe/core.c b/plugins/pe/core.c
new file mode 100644
index 0000000..aa51c18
--- /dev/null
+++ b/plugins/pe/core.c
@@ -0,0 +1,117 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.c - intégration du support du format PE
+ *
+ * Copyright (C) 2017-2019 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 "core.h"
+
+
+#include <config.h>
+#include <core/global.h>
+#include <plugins/self.h>
+
+
+#include "format.h"
+#ifdef HAVE_PYTHON3_BINDINGS
+# include "python/module.h"
+#endif
+
+
+#ifdef HAVE_PYTHON3_BINDINGS
+# define PG_REQ RL("PyChrysalide")
+#else
+# define PG_REQ NO_REQ
+#endif
+
+
+
+DEFINE_CHRYSALIDE_PLUGIN("Pe", "PE format support",
+ PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/formats"),
+ PG_REQ, AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
+
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* *
+* Description : Prend acte du chargement du greffon. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
+{
+ bool result; /* Bilan à retourner */
+
+#ifdef HAVE_PYTHON3_BINDINGS
+ result = add_format_pe_module_to_python_module();
+#else
+ result = true;
+#endif
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
+* action = type d'action attendue. *
+* content = contenu binaire à traiter. *
+* wid = identifiant du groupe de traitement. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Procède à une opération liée à un contenu binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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 */
+ GExeFormat *format; /* Format PE reconnu */
+ GLoadedContent *loaded; /* Représentation chargée */
+ GContentResolver *resolver; /* Resolveur de contenus */
+
+ test = check_pe_format(content);
+
+ if (test)
+ {
+ format = g_pe_format_new(content);
+ loaded = g_loaded_binary_new(format);
+
+ resolver = get_current_content_resolver();
+ g_content_resolver_add_detected(resolver, wid, loaded);
+ g_object_unref(G_OBJECT(resolver));
+
+ g_object_unref(G_OBJECT(loaded));
+
+ }
+
+}
diff --git a/plugins/pe/core.h b/plugins/pe/core.h
new file mode 100644
index 0000000..4497cf5
--- /dev/null
+++ b/plugins/pe/core.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * core.h - prototypes pour l'intégration du support du format PE
+ *
+ * Copyright (C) 2017-2018 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_CORE_H
+#define _PLUGINS_PE_CORE_H
+
+
+#include <plugins/plugin.h>
+#include <plugins/plugin-int.h>
+
+
+
+/* Prend acte du chargement du greffon. */
+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 *);
+
+
+
+#endif /* _PLUGINS_PE_CORE_H */
diff --git a/plugins/pe/format.c b/plugins/pe/format.c
index 8533d25..f5bdac1 100644
--- a/plugins/pe/format.c
+++ b/plugins/pe/format.c
@@ -21,74 +21,122 @@
*/
-#include "pe.h"
+#include "format.h"
-#include <string.h>
+#include <assert.h>
#include "pe-int.h"
+#include "rich.h"
#include "section.h"
#include "symbols.h"
-/* Initialise la classe des formats d'exécutables PE. */
+/* Initialise la classe des formats d'exécutables ELF. */
static void g_pe_format_class_init(GPeFormatClass *);
-/* Initialise une instance de format d'exécutable PE. */
+/* Initialise une instance de format d'exécutable ELF. */
static void g_pe_format_init(GPeFormat *);
+/* Supprime toutes les références externes. */
+static void g_pe_format_dispose(GPeFormat *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_pe_format_finalize(GPeFormat *);
+
+/* Indique la désignation interne du format. */
+static char *g_pe_format_get_key(const GPeFormat *);
+
+/* Fournit une description humaine du format. */
+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 *);
+
+/* 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 *);
-/* Fournit les références aux zones binaires à analyser. */
-//static GBinPart **g_pe_format_get_parts(const GPeFormat *, size_t *);
+/* Fournit l'adresse principale associée à un format Elf. */
+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
+
+/* 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
+
+
/******************************************************************************
* *
-* Paramètres : content = contenu binaire à parcourir. *
+* Paramètres : content = contenu binaire à traiter. *
* *
-* Description : Indique si le format peut être pris en charge ici. *
+* Description : Valide un contenu comme étant un format PE. *
* *
-* Retour : true si la réponse est positive, false sinon. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool pe_is_matching(GBinContent *content)
+bool check_pe_format(const GBinContent *content)
{
- bool result; /* Bilan à faire connaître */
- image_dos_header dos_header; /* En-tête DOS */
+ bool result; /* Bilan à faire remonter */
+ vmpa2t addr; /* Tête de lecture initiale */
+ char magic[4]; /* Idenfiant standard */
+ GPeFormat format; /* Format factice */
- result = false;
-#if 0
- if (length >= 2)
+ init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
+
+ result = g_binary_content_read_raw(content, &addr, 2, (bin_t *)magic);
+
+ if (result)
+ result = (memcmp(magic, "\x4d\x5a" /* MZ */, 2) == 0);
+
+ if (result)
{
- result = (strncmp((const char *)content, "\x4d\x5a" /* MZ */, 2) == 0);
- result &= length >= sizeof(image_dos_header);
+ G_KNOWN_FORMAT(&format)->content = (GBinContent *)content;
+ result = read_dos_image_header(&format, &format.dos_header);
}
if (result)
{
- memcpy(&dos_header, content, sizeof(image_dos_header));
+ init_vmpa(&addr, format.dos_header.e_lfanew, VMPA_NO_VIRTUAL);
- result = length >= (dos_header.e_lfanew + 4);
+ result = g_binary_content_read_raw(content, &addr, 4, (bin_t *)magic);
- result &= (strncmp((const char *)&content[dos_header.e_lfanew],
- "\x50\x45\x00\x00" /* PE00 */, 4) == 0);
+ if (result)
+ result = (memcmp(magic, "\x50\x45\x00\x00" /* PE00 */, 4) == 0);
}
-#endif
+
return result;
}
-/* Indique le type défini pour un format d'exécutable PE. */
+/* Indique le type défini pour un format d'exécutable ELF. */
G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT);
@@ -96,7 +144,7 @@ G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT);
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des formats d'exécutables PE. *
+* Description : Initialise la classe des formats d'exécutables ELF. *
* *
* Retour : - *
* *
@@ -106,6 +154,36 @@ G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT);
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 */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_pe_format_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_pe_format_finalize;
+
+ known = G_KNOWN_FORMAT_CLASS(klass);
+
+ known->get_key = (known_get_key_fc)g_pe_format_get_key;
+ 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);
+
+ fmt->get_endian = (format_get_endian_fc)g_pe_format_get_endianness;
+
+ exe = G_EXE_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->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;
}
@@ -114,7 +192,7 @@ static void g_pe_format_class_init(GPeFormatClass *klass)
* *
* Paramètres : format = instance à initialiser. *
* *
-* Description : Initialise une instance de format d'exécutable PE. *
+* Description : Initialise une instance de format d'exécutable ELF. *
* *
* Retour : - *
* *
@@ -124,6 +202,50 @@ static void g_pe_format_class_init(GPeFormatClass *klass)
static void g_pe_format_init(GPeFormat *format)
{
+ format->sections = NULL;
+
+ format->loaded = false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_format_dispose(GPeFormat *format)
+{
+ G_OBJECT_CLASS(g_pe_format_parent_class)->dispose(G_OBJECT(format));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_format_finalize(GPeFormat *format)
+{
+ if (format->sections != NULL)
+ free(format->sections);
+
+ G_OBJECT_CLASS(g_pe_format_parent_class)->finalize(G_OBJECT(format));
}
@@ -131,7 +253,6 @@ static void g_pe_format_init(GPeFormat *format)
/******************************************************************************
* *
* Paramètres : content = contenu binaire à parcourir. *
-* length = taille du contenu en question. *
* *
* Description : Prend en charge un nouveau format PE. *
* *
@@ -141,53 +262,140 @@ static void g_pe_format_init(GPeFormat *format)
* *
******************************************************************************/
-GBinFormat *g_pe_format_new(const bin_t *content, off_t length)
+GExeFormat *g_pe_format_new(GBinContent *content)
{
GPeFormat *result; /* Structure à retourner */
- off_t offset; /* Tête de lecture */
+ if (!check_pe_format(content))
+ return NULL;
- int i;
+ result = g_object_new(G_TYPE_PE_FORMAT, NULL);
+ g_known_format_set_content(G_KNOWN_FORMAT(result), content);
- result = g_object_new(G_TYPE_PE_FORMAT, NULL);
+ return G_EXE_FORMAT(result);
- //g_binary_format_set_content(G_BIN_FORMAT(result), content, length);
+}
- offset = 0;
- if (!read_dos_image_header(result, &offset, &result->dos_header))
- {
- /* TODO */
- return NULL;
- }
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à consulter. *
+* *
+* Description : Indique la désignation interne du format. *
+* *
+* Retour : Désignation du format. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- offset = result->dos_header.e_lfanew;
+static char *g_pe_format_get_key(const GPeFormat *format)
+{
+ char *result; /* Désignation à retourner */
- if (!read_pe_nt_header(result, &offset, &result->nt_headers))
- {
- /* TODO */
- return NULL;
- }
+ result = strdup("pe");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 */
+
+ result = strdup("Portable Executable");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format chargé dont l'analyse est lancée. *
+* gid = groupe de travail dédié. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Assure l'interprétation d'un format en différé. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- result->section_offset = offset;
+static bool g_pe_format_analyze(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+ bool result; /* Bilan à retourner */
+ GExeFormat *exe; /* Autre version du format */
+ vmpa2t section_start; /* Zone de départ des sections */
- printf("offset :: 0x%08x\n", offset);
+ exe = G_EXE_FORMAT(format);
- printf("Format :: 0x%08x\n", result->nt_headers.signature);
+ result = read_dos_image_header(format, &format->dos_header);
+ if (!result) goto error;
- printf("directories :: %d\n", result->nt_headers.optional_header.number_of_rva_and_sizes);
+ result = read_pe_nt_header(format, &format->nt_headers, &section_start);
+ if (!result) goto error;
- for (i = 0; i < result->nt_headers.optional_header.number_of_rva_and_sizes; i++)
- printf(" [%d] addr=0x%08x size=%d\n", i,
- result->nt_headers.optional_header.data_directory[i].virtual_address,
- result->nt_headers.optional_header.data_directory[i].size);
+ format->sections = read_all_pe_sections(format, &section_start);
+ if (format->sections == NULL) goto error;
+ extract_pe_rich_header(format);
- load_pe_symbols(result);
+ result = load_pe_symbols(format, gid, status);
+ if (!result) goto error;
+ result = g_executable_format_complete_loading(exe, gid, status);
+ if (!result) goto error;
- return G_BIN_FORMAT(result);
+ error:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* *
+* Description : Informe quant au boutisme utilisé. *
+* *
+* Retour : Indicateur de boutisme. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static SourceEndian g_pe_format_get_endianness(const GPeFormat *format)
+{
+ SourceEndian result; /* Boutisme à 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
+ */
+
+ result = SRE_LITTLE;
+
+ return result;
}
@@ -206,69 +414,405 @@ GBinFormat *g_pe_format_new(const bin_t *content, off_t length)
static const char *g_pe_format_get_target_machine(const GPeFormat *format)
{
- return "i386";
+ const char *result; /* Identifiant à retourner */
+
+ switch (format->nt_headers.file_header.machine)
+ {
+ case IMAGE_FILE_MACHINE_I386:
+ result = "i386";
+ break;
+
+ 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;
+
+ case IMAGE_FILE_MACHINE_ARM:
+ case IMAGE_FILE_MACHINE_THUMB:
+ case IMAGE_FILE_MACHINE_ARMNT:
+ result = "armv7";
+ break;
+
+ case IMAGE_FILE_MACHINE_UNKNOWN:
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : format = informations chargées à consulter. *
-* count = quantité de zones listées. [OUT] *
+* Paramètres : format = description de l'exécutable à consulter. *
+* addr = adresse principale trouvée si possible. [OUT] *
* *
-* Description : Fournit les références aux zones binaires à analyser. *
+* Description : Fournit l'adresse principale associée à un format Elf. *
* *
-* Retour : Zones binaires à analyser. *
+* Retour : Bilan des recherches. *
* *
* Remarques : - *
* *
******************************************************************************/
+
+static bool g_pe_format_get_main_address(GPeFormat *format, vmpa2t *addr)
+{
+ 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;
+
+ base = G_BIN_FORMAT(format);
+
+ if (g_binary_format_find_symbol_by_label(base, "main", &symbol))
+ goto done;
+
+ if (g_binary_format_find_symbol_by_label(base, "_start", &symbol))
+ goto done;
+
+ if (g_binary_format_find_symbol_by_label(base, "entry_point", &symbol))
+ goto done;
+
+ done:
+
+ if (symbol != NULL)
+ {
+ result = true;
+
+ range = g_binary_symbol_get_range(symbol);
+
+ copy_vmpa(addr, get_mrange_addr(range));
+
+ g_object_unref(G_OBJECT(symbol));
+
+ }
+
+ return result;
+
+}
+
+
#if 0
-static GBinPart **g_pe_format_get_parts(const GPeFormat *format, size_t *count)
+
+/******************************************************************************
+* *
+* Paramètres : format = informations chargées à consulter. *
+* *
+* Description : Etend la définition des portions au sein d'un binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_format_refine_portions(GPeFormat *format)
+{
+
+}
+
+#endif
+
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_pe_format_translate_address_into_vmpa_using_portions(GPeFormat *format, virt_t addr, vmpa2t *pos)
{
- GBinPart **result; /* Tableau à retourner */
+ bool result; /* Bilan à retourner */
uint16_t i; /* Boucle de parcours */
- image_section_header section; /* En-tête de section PE */
- GBinPart *part; /* Partie à intégrer à la liste*/
- char name[IMAGE_SIZEOF_SHORT_NAME + 1]; /* Nom de section utilisable */
+ const image_section_header *section; /* Section à consulter */
+ phys_t diff; /* Décallage à appliquer */
- result = NULL;
- *count = 0;
+ result = false;
- for (i = 0; i < format->nt_headers.file_header.number_of_sections; i++)
+ for (i = 0; i < format->nt_headers.file_header.number_of_sections && !result; i++)
{
- if (!find_pe_section_by_index(format, i, &section))
+ section = &format->sections[i];
+
+ if (addr < section->virtual_address)
+ continue;
+
+ if (addr >= (section->virtual_address + section->size_of_raw_data))
continue;
- if (section.characteristics & IMAGE_SCN_MEM_EXECUTE)
- {
- part = g_binary_part_new();
+ diff = addr - section->virtual_address;
- memset(name, 0, (IMAGE_SIZEOF_SHORT_NAME + 1) * sizeof(char));
- memcpy(name, section.name, (IMAGE_SIZEOF_SHORT_NAME + 1) * sizeof(char));
+ init_vmpa(pos, section->pointer_to_raw_data + diff, addr);
- g_binary_part_set_name(part, name);
+ result = true;
- printf("section '%s'\n", name);
+ }
- g_binary_part_set_values(part,
- section.pointer_to_raw_data,
- section.size_of_raw_data,
- section.virtual_address);
+ //printf(" // trans // %x -> %x (valid? %d)\n", (unsigned int)addr, (unsigned int)pos->physical, result);
- printf("section[%d] start=0x%08x size=%d addr=0x%08x\n", i,
- section.pointer_to_raw_data,
- section.size_of_raw_data,
- section.virtual_address);
+ return result;
- result = (GBinPart **)realloc(result, ++(*count) * sizeof(GBinPart *));
- result[*count - 1] = part;
+}
+
+
+
+
+#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] *
+* *
+* Description : Fournit l'emplacement d'une section donnée. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_pe_format_get_section_range_by_name(const GPeFormat *format, const char *name, mrange_t *range)
+{
+ 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 */
+
+ result = find_elf_section_content_by_name(format, name, &offset, &size, &address);
+
+ if (result)
+ {
+ init_vmpa(&tmp, offset, address);
+ init_mrange(range, &tmp, size);
}
return result;
}
#endif
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format en place à consulter. *
+* *
+* Description : Présente l'en-tête MS-DOS du format chargé. *
+* *
+* Retour : Pointeur vers la description principale. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const image_dos_header *g_pe_format_get_dos_header(const GPeFormat *format)
+{
+ const image_dos_header *result; /* Informations à retourner */
+
+ result = &format->dos_header;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format en place à consulter. *
+* *
+* Description : Présente l'en-tête NT du format chargé. *
+* *
+* Retour : Pointeur vers la description principale. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const image_nt_headers *g_pe_format_get_nt_headers(const GPeFormat *format)
+{
+ const image_nt_headers *result; /* Informations à retourner */
+
+ result = &format->nt_headers;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format en place à consulter. *
+* *
+* Description : Indique si le format PE est en 32 bits ou en 64 bits. *
+* *
+* Retour : true si le format est en 32 bits, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_pe_format_get_is_32b(const GPeFormat *format)
+{
+ bool result; /* Nature à retourner */
+
+ assert(format->loaded);
+
+ 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 = format en place à consulter. *
+* count = taille (fixe) du tableau renvoyé. [OUT] *
+* *
+* Description : Offre un raccourci vers les répertoires du format PE. *
+* *
+* Retour : Pointeur vers le tableau des répertoires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const image_data_directory *g_pe_format_get_directories(const GPeFormat *format, size_t *count)
+{
+ const image_data_directory *result; /* Liste à retourner */
+
+ if (count != NULL)
+ *count = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
+
+ if (g_pe_format_get_is_32b(format))
+ result = format->nt_headers.optional_header.header_32.data_directory;
+ else
+ result = format->nt_headers.optional_header.header_64.data_directory;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format en place à consulter. *
+* index = indice du répertoire visé. *
+* *
+* Description : Extrait le contenu d'un répertoire du format PE. *
+* *
+* Retour : Pointeur vers un contenu chargé ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void *g_pe_format_get_directory(const GPeFormat *format, size_t index)
+{
+ void *result; /* Données à retourner */
+ 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 */
+
+ result = NULL;
+
+ if (index >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
+ goto exit;
+
+ dir = g_pe_format_get_directories(format, NULL);
+ dir += index;
+
+ status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), dir->virtual_address, &pos);
+ if (!status) goto exit;
+
+ switch (index)
+ {
+ case IMAGE_DIRECTORY_ENTRY_EXPORT:
+
+ export = malloc(sizeof(image_export_directory));
+
+ status = read_pe_image_export_directory(format, &pos, export);
+
+ 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));
+
+ 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;
+
+}
diff --git a/plugins/pe/format.h b/plugins/pe/format.h
index f757d26..a48e04d 100644
--- a/plugins/pe/format.h
+++ b/plugins/pe/format.h
@@ -21,16 +21,19 @@
*/
-#ifndef _FORMAT_PE_PE_H
-#define _FORMAT_PE_PE_H
+#ifndef _PLUGINS_PE_FORMAT_H
+#define _PLUGINS_PE_FORMAT_H
#include <glib-object.h>
#include <stdbool.h>
-#include <sys/types.h>
-#include "../../core/formats.h"
+#include <analysis/content.h>
+#include <format/executable.h>
+
+
+#include "pe_def.h"
@@ -49,15 +52,30 @@ typedef struct _GPeFormat GPeFormat;
typedef struct _GPeFormatClass GPeFormatClass;
-/* Indique si le format peut être pris en charge ici. */
-bool pe_is_matching(GBinContent *);
+/* Valide un contenu comme étant un format PE. */
+bool check_pe_format(const GBinContent *);
/* Indique le type défini pour un format d'exécutable PE. */
GType g_pe_format_get_type(void);
/* Prend en charge un nouveau format PE. */
-GBinFormat *g_pe_format_new(const bin_t *, off_t);
+GExeFormat *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 *);
+
+/* Présente l'en-tête NT du format chargé. */
+const image_nt_headers *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 *);
+
+/* Extrait le contenu d'un répertoire du format PE. */
+void *g_pe_format_get_directory(const GPeFormat *, size_t);
-#endif /* _FORMAT_PE_PE_H */
+#endif /* _PLUGINS_PE_FORMAT_H */
diff --git a/plugins/pe/pe-int.c b/plugins/pe/pe-int.c
index 0ce1577..db09c15 100644
--- a/plugins/pe/pe-int.c
+++ b/plugins/pe/pe-int.c
@@ -27,18 +27,16 @@
#include <malloc.h>
#include <string.h>
-
-#include "../../common/endianness.h"
+#include <common/endianness.h>
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
-* pos = position de début de lecture. [OUT] *
* header = structure lue à retourner. [OUT] *
* *
-* Description : Procède à la lecture d'une en-tête de programme DOS. *
+* Description : Procède à la lecture d'un en-tête de programme DOS. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -46,41 +44,44 @@
* *
******************************************************************************/
-bool read_dos_image_header(const GPeFormat *format, off_t *pos, image_dos_header *header)
+bool read_dos_image_header(const GPeFormat *format, image_dos_header *header)
{
bool result; /* Bilan à retourner */
- const bin_t *content; /* Contenu binaire à lire */
- off_t length; /* Taille totale du contenu */
+ const GBinContent *content; /* Contenu binaire à lire */
+ vmpa2t pos; /* Position de lecture */
size_t i; /* Boucle de parcours */
- content = NULL; //G_BIN_FORMAT(format)->content;
- length = 0; //G_BIN_FORMAT(format)->length;
-
- result = read_u16(&header->e_magic, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_cblp, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_cp, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_crlc, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_cparhdr, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_minalloc, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_maxalloc, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_ss, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_sp, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_csum, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_ip, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_cs, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_lfarlc, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_ovno, content, pos, length, SRE_LITTLE);
+ result = true;
+
+ content = G_KNOWN_FORMAT(format)->content;
+
+ init_vmpa(&pos, 0, VMPA_NO_VIRTUAL);
+
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_magic);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_cblp);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_cp);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_crlc);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_cparhdr);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_minalloc);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_maxalloc);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_ss);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_sp);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_csum);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_ip);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_cs);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_lfarlc);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_ovno);
for (i = 0; i < 4 && result; i++)
- result = read_u16(&header->e_res[i], content, pos, length, SRE_LITTLE);
+ result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_res[i]);
- result &= read_u16(&header->e_oemid, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->e_oeminfo, content, pos, length, SRE_LITTLE);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_oemid);
+ if (result) result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_oeminfo);
for (i = 0; i < 10 && result; i++)
- result = read_u16(&header->e_res2[i], content, pos, length, SRE_LITTLE);
+ result = g_binary_content_read_u16(content, &pos, SRE_LITTLE, &header->e_res2[i]);
- result &= read_u32(&header->e_lfanew, content, pos, length, SRE_LITTLE);
+ if (result) result = g_binary_content_read_u32(content, &pos, SRE_LITTLE, &header->e_lfanew);
return result;
@@ -93,7 +94,7 @@ bool read_dos_image_header(const GPeFormat *format, off_t *pos, image_dos_header
* pos = position de début de lecture. [OUT] *
* header = structure lue à retourner. [OUT] *
* *
-* Description : Procède à la lecture d'une en-tête de programme PE (1). *
+* Description : Procède à la lecture d'un en-tête de programme PE (1). *
* *
* Retour : Bilan de l'opération. *
* *
@@ -101,22 +102,22 @@ bool read_dos_image_header(const GPeFormat *format, off_t *pos, image_dos_header
* *
******************************************************************************/
-bool read_pe_file_header(const GPeFormat *format, off_t *pos, image_file_header *header)
+bool read_pe_file_header(const GPeFormat *format, vmpa2t *pos, image_file_header *header)
{
bool result; /* Bilan à retourner */
- const bin_t *content; /* Contenu binaire à lire */
- off_t length; /* Taille totale du contenu */
+ const GBinContent *content; /* Contenu binaire à lire */
+
+ result = true;
- content = NULL; //G_BIN_FORMAT(format)->content;
- length = 0; //G_BIN_FORMAT(format)->length;
+ content = G_KNOWN_FORMAT(format)->content;
- result = read_u16(&header->machine, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->number_of_sections, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->time_date_stamp, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->pointer_to_symbol_table, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->number_of_symbols, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->size_of_optional_header, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->characteristics, content, pos, length, SRE_LITTLE);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->machine);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->number_of_sections);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->time_date_stamp);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->pointer_to_symbol_table);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->number_of_symbols);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->size_of_optional_header);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->characteristics);
return result;
@@ -129,7 +130,7 @@ bool read_pe_file_header(const GPeFormat *format, off_t *pos, image_file_header
* pos = position de début de lecture. [OUT] *
* header = structure lue à retourner. [OUT] *
* *
-* Description : Procède à la lecture d'une en-tête de programme PE (2). *
+* Description : Procède à la lecture d'un en-tête de programme PE (2). *
* *
* Retour : Bilan de l'opération. *
* *
@@ -137,53 +138,115 @@ bool read_pe_file_header(const GPeFormat *format, off_t *pos, image_file_header
* *
******************************************************************************/
-bool read_pe_optional_header(const GPeFormat *format, off_t *pos, image_optional_header *header)
+bool read_pe_optional_header(const GPeFormat *format, vmpa2t *pos, image_optional_header *header)
{
bool result; /* Bilan à retourner */
- const bin_t *content; /* Contenu binaire à lire */
- off_t length; /* Taille totale du contenu */
+ 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 */
+ uint32_t number_of_rva_and_sizes; /* Quantité de ces répertoires */
uint32_t i; /* Boucle de parcours */
- content = NULL; //G_BIN_FORMAT(format)->content;
- length = 0; //G_BIN_FORMAT(format)->length;
-
- result = read_u16(&header->magic, content, pos, length, SRE_LITTLE);
- result &= read_u8(&header->major_linker_version, content, pos, length);
- result &= read_u8(&header->minor_linker_version, content, pos, length);
- result &= read_u32(&header->size_of_code, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->size_of_initialized_data, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->size_of_uninitialized_data, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->address_of_entry_point, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->base_of_code, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->base_of_data, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->image_base, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->section_alignment, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->file_alignment, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->major_operating_system_version, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->minor_operating_system_version, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->major_image_version, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->minor_image_version, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->major_subsystem_version, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->minor_subsystem_version, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->win32_version_value, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->size_of_image, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->size_of_headers, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->subsystem, content, pos, length, SRE_LITTLE);
- result &= read_u16(&header->dll_characteristics, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->size_of_stack_reserve, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->size_of_stack_commit, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->size_of_heap_reserve, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->size_of_heap_commit, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->loader_flags, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->number_of_rva_and_sizes, content, pos, length, SRE_LITTLE);
-
- for (i = 0; i < header->number_of_rva_and_sizes && result; i++)
+ content = G_KNOWN_FORMAT(format)->content;
+
+ result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &header->header_32.magic);
+ if (!result) goto exit;
+
+ ((GPeFormat *)format)->loaded = true;
+
+ if (g_pe_format_get_is_32b(format))
+ {
+ hdr32 = &header->header_32;
+
+ if (result) result = g_binary_content_read_u8(content, pos, &hdr32->major_linker_version);
+ if (result) result = g_binary_content_read_u8(content, pos, &hdr32->minor_linker_version);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_code);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_initialized_data);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_uninitialized_data);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->address_of_entry_point);
+
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->base_of_code);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->base_of_data);
+
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->image_base);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->section_alignment);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->file_alignment);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->major_operating_system_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->minor_operating_system_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->major_image_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->minor_image_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->major_subsystem_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->minor_subsystem_version);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->win32_version_value);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_image);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_headers);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->checksum);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->subsystem);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr32->dll_characteristics);
+
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_stack_reserve);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_stack_commit);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_heap_reserve);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->size_of_heap_commit);
+
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->loader_flags);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr32->number_of_rva_and_sizes);
+
+ directories = hdr32->data_directory;
+ number_of_rva_and_sizes = hdr32->number_of_rva_and_sizes;
+
+ }
+ else
+ {
+ hdr64 = &header->header_64;
+
+ if (result) result = g_binary_content_read_u8(content, pos, &hdr64->major_linker_version);
+ if (result) result = g_binary_content_read_u8(content, pos, &hdr64->minor_linker_version);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_code);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_initialized_data);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_uninitialized_data);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->address_of_entry_point);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->base_of_code);
+
+ if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->image_base);
+
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->section_alignment);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->file_alignment);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->major_operating_system_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->minor_operating_system_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->major_image_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->minor_image_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->major_subsystem_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->minor_subsystem_version);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->win32_version_value);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_image);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->size_of_headers);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->checksum);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->subsystem);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &hdr64->dll_characteristics);
+
+ if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->size_of_stack_reserve);
+ if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->size_of_stack_commit);
+ if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->size_of_heap_reserve);
+ if (result) result = g_binary_content_read_u64(content, pos, SRE_LITTLE, &hdr64->size_of_heap_commit);
+
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->loader_flags);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &hdr64->number_of_rva_and_sizes);
+
+ directories = hdr64->data_directory;
+ number_of_rva_and_sizes = hdr64->number_of_rva_and_sizes;
+
+ }
+
+ for (i = 0; i < number_of_rva_and_sizes && result; i++)
{
- result = read_u32(&header->data_directory[i].virtual_address, content, pos, length, SRE_LITTLE);
- result &= read_u32(&header->data_directory[i].size, content, pos, length, SRE_LITTLE);
+ result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &directories[i].virtual_address);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &directories[i].size);
}
+ exit:
+
return result;
}
@@ -192,10 +255,10 @@ bool read_pe_optional_header(const GPeFormat *format, off_t *pos, image_optional
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
-* pos = position de début de lecture. [OUT] *
* header = structure lue à retourner. [OUT] *
+* next = position en fin de lecture. [OUT] *
* *
-* Description : Procède à la lecture d'une en-tête de programme PE. *
+* Description : Procède à la lecture d'un en-tête de programme PE. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -203,19 +266,26 @@ bool read_pe_optional_header(const GPeFormat *format, off_t *pos, image_optional
* *
******************************************************************************/
-bool read_pe_nt_header(const GPeFormat *format, off_t *pos, image_nt_headers *header)
+bool read_pe_nt_header(const GPeFormat *format, image_nt_headers *header, vmpa2t *next)
{
bool result; /* Bilan à retourner */
- const bin_t *content; /* Contenu binaire à lire */
- off_t length; /* Taille totale du contenu */
+ const GBinContent *content; /* Contenu binaire à lire */
+ vmpa2t pos; /* Position de lecture */
+
+ result = true;
+
+ content = G_KNOWN_FORMAT(format)->content;
+
+ init_vmpa(&pos, format->dos_header.e_lfanew, VMPA_NO_VIRTUAL);
- content = NULL; //G_BIN_FORMAT(format)->content;
- length = 0; //G_BIN_FORMAT(format)->length;
+ result = g_binary_content_read_u32(content, &pos, SRE_LITTLE, &header->signature);
- result = read_u32(&header->signature, content, pos, length, SRE_LITTLE);
+ if (result) result = read_pe_file_header(format, &pos, &header->file_header);
- result &= read_pe_file_header(format, pos, &header->file_header);
- result &= read_pe_optional_header(format, pos, &header->optional_header);
+ if (result) result = read_pe_optional_header(format, &pos, &header->optional_header);
+
+ if (result)
+ copy_vmpa(next, &pos);
return result;
@@ -228,7 +298,7 @@ bool read_pe_nt_header(const GPeFormat *format, off_t *pos, image_nt_headers *he
* pos = position de début de lecture. [OUT] *
* section = structure lue à retourner. [OUT] *
* *
-* Description : Procède à la lecture d'une en-tête de section PE. *
+* Description : Procède à la lecture d'un en-tête de section PE. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -236,31 +306,29 @@ bool read_pe_nt_header(const GPeFormat *format, off_t *pos, image_nt_headers *he
* *
******************************************************************************/
-bool read_pe_image_section_header(const GPeFormat *format, off_t *pos, image_section_header *section)
+bool read_pe_image_section_header(const GPeFormat *format, vmpa2t *pos, image_section_header *section)
{
bool result; /* Bilan à retourner */
- const bin_t *content; /* Contenu binaire à lire */
- off_t length; /* Taille totale du contenu */
+ const GBinContent *content; /* Contenu binaire à lire */
size_t i; /* Boucle de parcours */
- content = NULL; //G_BIN_FORMAT(format)->content;
- length = 0; //G_BIN_FORMAT(format)->length;
-
result = true;
+ content = G_KNOWN_FORMAT(format)->content;
+
for (i = 0; i < IMAGE_SIZEOF_SHORT_NAME && result; i++)
- result = read_u8((uint8_t *)&section->name[i], content, pos, length);
+ result = g_binary_content_read_u8(content, pos, (uint8_t *)&section->name[i]);
- result &= read_u32(&section->misc.physical_address, content, pos, length, SRE_LITTLE);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->misc.physical_address);
- result &= read_u32(&section->virtual_address, content, pos, length, SRE_LITTLE);
- result &= read_u32(&section->size_of_raw_data, content, pos, length, SRE_LITTLE);
- result &= read_u32(&section->pointer_to_raw_data, content, pos, length, SRE_LITTLE);
- result &= read_u32(&section->pointer_to_relocations, content, pos, length, SRE_LITTLE);
- result &= read_u32(&section->pointer_to_line_numbers, content, pos, length, SRE_LITTLE);
- result &= read_u16(&section->number_of_relocations, content, pos, length, SRE_LITTLE);
- result &= read_u16(&section->number_of_line_numbers, content, pos, length, SRE_LITTLE);
- result &= read_u32(&section->characteristics, content, pos, length, SRE_LITTLE);
+ 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);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->pointer_to_raw_data);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->pointer_to_relocations);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->pointer_to_line_numbers);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &section->number_of_relocations);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &section->number_of_line_numbers);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &section->characteristics);
return result;
@@ -271,9 +339,9 @@ bool read_pe_image_section_header(const GPeFormat *format, off_t *pos, image_sec
* *
* Paramètres : format = informations chargées à consulter. *
* pos = position de début de lecture. [OUT] *
-* desc = structure lue à retourner. [OUT] *
+* dir = structure lue à retourner. [OUT] *
* *
-* Description : Procède à la lecture d'un répertoire de programme PE. *
+* Description : Procède à la lecture d'un répertoire d'exportations. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -281,20 +349,26 @@ bool read_pe_image_section_header(const GPeFormat *format, off_t *pos, image_sec
* *
******************************************************************************/
-bool read_pe_image_import_descriptor(const GPeFormat *format, off_t *pos, image_import_descriptor *desc)
+bool read_pe_image_export_directory(const GPeFormat *format, vmpa2t *pos, image_export_directory *dir)
{
bool result; /* Bilan à retourner */
- const bin_t *content; /* Contenu binaire à lire */
- off_t length; /* Taille totale du contenu */
+ const GBinContent *content; /* Contenu binaire à lire */
- content = NULL; //G_BIN_FORMAT(format)->content;
- length = 0; //G_BIN_FORMAT(format)->length;
+ result = true;
- result = read_u32(&desc->original_first_thunk, content, pos, length, SRE_LITTLE);
- result &= read_u32(&desc->time_date_stamp, content, pos, length, SRE_LITTLE);
- result &= read_u32(&desc->forwarder_chain, content, pos, length, SRE_LITTLE);
- result &= read_u32(&desc->module_name, content, pos, length, SRE_LITTLE);
- result &= read_u32(&desc->first_thunk, content, pos, length, SRE_LITTLE);
+ content = G_KNOWN_FORMAT(format)->content;
+
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->characteristics);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->time_date_stamp);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &dir->major_version);
+ if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &dir->minor_version);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->name);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->base);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->number_of_functions);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->number_of_names);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->address_of_functions);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->address_of_names);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &dir->address_of_name_ordinals);
return result;
@@ -305,9 +379,9 @@ bool read_pe_image_import_descriptor(const GPeFormat *format, off_t *pos, image_
* *
* Paramètres : format = informations chargées à consulter. *
* pos = position de début de lecture. [OUT] *
-* import = structure lue à retourner. [OUT] *
+* desc = structure lue à retourner. [OUT] *
* *
-* Description : Procède à la lecture d'une fonction importée par son nom. *
+* Description : Procède à la lecture d'un répertoire de programme PE. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -315,44 +389,20 @@ bool read_pe_image_import_descriptor(const GPeFormat *format, off_t *pos, image_
* *
******************************************************************************/
-bool read_pe_image_import_by_name(const GPeFormat *format, off_t *pos, image_import_by_name *import)
+bool read_pe_image_import_descriptor(const GPeFormat *format, vmpa2t *pos, image_import_descriptor *desc)
{
bool result; /* Bilan à retourner */
- const bin_t *content; /* Contenu binaire à lire */
- off_t length; /* Taille totale du contenu */
- uint32_t link; /* Lien vers la prochaine zone */
- off_t new_pos; /* Nouvelle tête de lecture */
- size_t i; /* Boucle de parcours */
-
- content = NULL; //G_BIN_FORMAT(format)->content;
- length = 0; //G_BIN_FORMAT(format)->length;
+ const GBinContent *content; /* Contenu binaire à lire */
- result = read_u32(&link, content, pos, length, SRE_LITTLE);
-
- if (link == 0)
- memset(import, 0, sizeof(image_import_by_name));
-
- else if (link % 2 == 0)
- {
- new_pos = link;
-
- result = read_u16(&import->hint, content, &new_pos, length, SRE_LITTLE);
-
- import->name = (char *)calloc(1, sizeof(char));
-
- for (i = 0; result; i++)
- {
- result = read_u8((uint8_t *)&import->name[i], content, &new_pos, length);
-
- if (import->name[i] == '\0')
- break;
-
- import->name = (char *)realloc(import->name, (i + 2) * sizeof(char));
+ result = true;
- }
+ content = G_KNOWN_FORMAT(format)->content;
- }
- else /* TODO */;
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->original_first_thunk);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->time_date_stamp);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->forwarder_chain);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->module_name);
+ if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &desc->first_thunk);
return result;
diff --git a/plugins/pe/pe-int.h b/plugins/pe/pe-int.h
index 14a6007..ebcf3f0 100644
--- a/plugins/pe/pe-int.h
+++ b/plugins/pe/pe-int.h
@@ -21,17 +21,15 @@
*/
-#ifndef _FORMAT_PE_E_PE_INT_H
-#define _FORMAT_PE_E_PE_INT_H
-
-
-#include "pe.h"
-#include "pe_def.h"
-#include "../executable-int.h"
+#ifndef _PLUGINS_PE_PE_INT_H
+#define _PLUGINS_PE_PE_INT_H
+#include <format/executable-int.h>
+#include "pe_def.h"
+#include "format.h"
@@ -41,9 +39,12 @@ struct _GPeFormat
GExeFormat parent; /* A laisser en premier */
image_dos_header dos_header; /* En-tête DOS */
+ mrange_t rich_header; /* En-tête enrichi */
image_nt_headers nt_headers; /* En-tête Windows */
- off_t section_offset; /* Début des sections */
+ image_section_header *sections; /* Liste des sections */
+
+ bool loaded; /* Détection partielle menée */
};
@@ -55,30 +56,27 @@ struct _GPeFormatClass
};
+/* Procède à la lecture d'un en-tête de programme DOS. */
+bool read_dos_image_header(const GPeFormat *, image_dos_header *);
+/* Procède à la lecture d'un en-tête de programme PE (1). */
+bool read_pe_file_header(const GPeFormat *, vmpa2t *, image_file_header *);
+/* Procède à la lecture d'un en-tête de programme PE (2). */
+bool read_pe_optional_header(const GPeFormat *, vmpa2t *, image_optional_header *);
-/* Procède à la lecture d'une en-tête de programme DOS. */
-bool read_dos_image_header(const GPeFormat *, off_t *, image_dos_header *);
-
-/* Procède à la lecture d'une en-tête de programme PE (1). */
-bool read_pe_file_header(const GPeFormat *, off_t *, image_file_header *);
+/* Procède à la lecture d'un en-tête de programme PE. */
+bool read_pe_nt_header(const GPeFormat *, image_nt_headers *, vmpa2t *);
-/* Procède à la lecture d'une en-tête de programme PE (2). */
-bool read_pe_optional_header(const GPeFormat *, off_t *, image_optional_header *);
+/* Procède à la lecture d'un en-tête de section PE. */
+bool read_pe_image_section_header(const GPeFormat *, vmpa2t *, image_section_header *);
-/* Procède à la lecture d'une en-tête de programme PE. */
-bool read_pe_nt_header(const GPeFormat *, off_t *, image_nt_headers *);
-
-/* Procède à la lecture d'une en-tête de section PE. */
-bool read_pe_image_section_header(const GPeFormat *, off_t *, image_section_header *);
+/* Procède à la lecture d'un répertoire d'exportations. */
+bool read_pe_image_export_directory(const GPeFormat *, vmpa2t *, image_export_directory *);
/* Procède à la lecture d'un répertoire de programme PE. */
-bool read_pe_image_import_descriptor(const GPeFormat *, off_t *, image_import_descriptor *);
-
-/* Procède à la lecture d'une fonction importée par son nom. */
-bool read_pe_image_import_by_name(const GPeFormat *, off_t *, image_import_by_name *);
+bool read_pe_image_import_descriptor(const GPeFormat *, vmpa2t *, image_import_descriptor *);
-#endif /* _FORMAT_PE_E_PE_INT_H */
+#endif /* _PLUGINS_PE_PE_INT_H */
diff --git a/plugins/pe/pe_def.h b/plugins/pe/pe_def.h
index 62d8afc..62b4607 100644
--- a/plugins/pe/pe_def.h
+++ b/plugins/pe/pe_def.h
@@ -21,13 +21,20 @@
*/
-#ifndef _FORMAT_PE_PE_DEF_H
-#define _FORMAT_PE_PE_DEF_H
+#ifndef _PLUGINS_PE_PE_DEF_H
+#define _PLUGINS_PE_PE_DEF_H
#include <stdint.h>
+/**
+ * Références :
+ *
+ * - 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
+ *
+ */
@@ -59,10 +66,44 @@ typedef struct _image_dos_header
} image_dos_header;
-/* Archtecture supportées */
-#define IMAGE_FILE_MACHINE_I386 0x014c /* x86 */
-#define IMAGE_FILE_MACHINE_IA64 0x0200 /* Intel IPF */
-#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* x64 */
+/* Archtectures supportées */
+
+/**
+ * Cf. https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants
+ */
+
+#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 /* Unknown */
+#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 /* Interacts with the host and not a WOW64 guest */
+#define IMAGE_FILE_MACHINE_I386 0x014c /* Intel 386 */
+#define IMAGE_FILE_MACHINE_R3000 0x0162 /* MIPS little-endian, 0x160 big-endian */
+#define IMAGE_FILE_MACHINE_R4000 0x0166 /* MIPS little-endian */
+#define IMAGE_FILE_MACHINE_R10000 0x0168 /* MIPS little-endian */
+#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 /* MIPS little-endian WCE v2 */
+#define IMAGE_FILE_MACHINE_ALPHA 0x0184 /* Alpha_AXP */
+#define IMAGE_FILE_MACHINE_SH3 0x01a2 /* SH3 little-endian */
+#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 /* SH3DSP */
+#define IMAGE_FILE_MACHINE_SH3E 0x01a4 /* SH3E little-endian */
+#define IMAGE_FILE_MACHINE_SH4 0x01a6 /* SH4 little-endian */
+#define IMAGE_FILE_MACHINE_SH5 0x01a8 /* SH5 */
+#define IMAGE_FILE_MACHINE_ARM 0x01c0 /* ARM Little-Endian */
+#define IMAGE_FILE_MACHINE_THUMB 0x01c2 /* ARM Thumb/Thumb-2 Little-Endian */
+#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 /* ARM Thumb-2 Little-Endian */
+#define IMAGE_FILE_MACHINE_AM33 0x01d3 /* TAM33BD */
+#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 /* IBM PowerPC Little-Endian */
+#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 /* POWERPCFP */
+#define IMAGE_FILE_MACHINE_IA64 0x0200 /* Intel 64 */
+#define IMAGE_FILE_MACHINE_MIPS16 0x0266 /* MIPS */
+#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 /* ALPHA64 */
+/*#define IMAGE_FILE_MACHINE_AXP64 0x0284*/ /* AXP64 */
+#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 /* MIPS */
+#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 /* MIPS */
+#define IMAGE_FILE_MACHINE_TRICORE 0x0520 /*Infineon */
+#define IMAGE_FILE_MACHINE_CEF 0x0cef /* CEF */
+#define IMAGE_FILE_MACHINE_EBC 0x0ebc /* EFI Byte Code */
+#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* AMD64 (K8) */
+#define IMAGE_FILE_MACHINE_M32R 0x9041 /* M32R little-endian */
+#define IMAGE_FILE_MACHINE_ARM64 0xaa64 /* ARM64 Little-Endian */
+#define IMAGE_FILE_MACHINE_CEE 0xc0ee /* CEE */
/* Caractéristiques de l'image */
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* Pas de relocalisation */
@@ -96,18 +137,14 @@ typedef struct _image_file_header
-
-
-
-
-
-
-
/* -------------------------- EN-TETE EVOLUEE DU FORMAT PE -------------------------- */
/**
- * cf. http://msdn.microsoft.com/en-us/library/ms680305(VS.85).aspx
+ * Références :
+ *
+ * - http://msdn.microsoft.com/en-us/library/ms680305(VS.85).aspx
+ * - https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32
*/
/* Zone de données Windows */
@@ -144,7 +181,8 @@ typedef struct _image_data_directory
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
/* Seconde en-tête, optionnelle */
-typedef struct _image_optional_header
+
+typedef struct _image_optional_header_32
{
uint16_t magic; /* Type de binaire manipulé */
uint8_t major_linker_version; /* Version majeure du linker */
@@ -178,8 +216,54 @@ typedef struct _image_optional_header
uint32_t number_of_rva_and_sizes; /* Nombre d'entrées suivantes */
image_data_directory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} image_optional_header_32;
+
+typedef struct _image_optional_header_64
+{
+
+ uint16_t magic; /* Type de binaire manipulé */
+ uint8_t major_linker_version; /* Version majeure du linker */
+ uint8_t minor_linker_version; /* Version mineure du linker */
+ uint32_t size_of_code; /* Taille de tout le code */
+ uint32_t size_of_initialized_data; /* Taille des données init. */
+ uint32_t size_of_uninitialized_data; /* Taille des données non init.*/
+ uint32_t address_of_entry_point; /* Point d'entrée pour un exe. */
+ uint32_t base_of_code; /* Adresse relative du code */
+ uint64_t image_base; /* Adresse souhaitée en mémoire*/
+ uint32_t section_alignment; /* Alignement des sections */
+ uint32_t file_alignment; /* Alignement des données */
+ uint16_t major_operating_system_version;/* Numéro majeur d'OS requis */
+ uint16_t minor_operating_system_version;/* Numéro mineur d'OS requis */
+ uint16_t major_image_version; /* Numéro majeur du binaire */
+ uint16_t minor_image_version; /* Numéro mineur du binaire */
+ uint16_t major_subsystem_version; /* Numéro majeur du sous-sys. */
+ uint16_t minor_subsystem_version; /* Numéro mineur du sous-sys. */
+ uint32_t win32_version_value; /* Réservé (-> 0) */
+ uint32_t size_of_image; /* Taille de l'image */
+ uint32_t size_of_headers; /* Taille de l'en-tête */
+ uint32_t checksum; /* Somme de contrôle */
+ uint16_t subsystem; /* Sous-système visé */
+ uint16_t dll_characteristics; /* Propriétés de la DLL */
+ uint64_t size_of_stack_reserve; /* Taille de pile reservée */
+ uint64_t size_of_stack_commit; /* Taille de pile au démarrage */
+ uint64_t size_of_heap_reserve; /* Taille de tas reservée */
+ 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_optional_header_64;
+
+typedef union _image_optional_header
+{
+ image_optional_header_32 header_32; /* Version 32 bits */
+ image_optional_header_64 header_64; /* Version 64 bits */
+
} image_optional_header;
+
+
+
/* Valeurs pour le champ 'magic' */
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b /* Exécutable 32 bits */
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b /* Exécutable 64 bits */
@@ -246,10 +330,11 @@ 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 non init. */
+ uint32_t size_of_raw_data; /* Taille de données définies */
uint32_t pointer_to_raw_data; /* Position de ces données */
uint32_t pointer_to_relocations; /* Position des relocalisations*/
uint32_t pointer_to_line_numbers; /* Position de numéros de ligne*/
@@ -308,10 +393,37 @@ typedef struct _image_section_header
/* --------------------------- IDENTIFICATION DE SYMBOLES --------------------------- */
+
/**
- * cf. http://msdn.microsoft.com/en-us/library/ms809762.aspx
- * http://sandsprite.com/CodeStuff/Understanding_imports.html
- * http://olance.developpez.com/articles/windows/pe-iczelion/import-table/
+ * https://docs.microsoft.com/en-us/previous-versions/ms809762(v=msdn.10)?redirectedfrom=MSDN#pe-file-exports
+ * https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-edata-section-image-only
+ */
+
+/* Répertoire des importations */
+typedef struct _image_export_directory
+{
+ uint32_t characteristics; /* Zéro !? */
+ uint32_t time_date_stamp; /* Date de création du fichier */
+ uint16_t major_version; /* Numéro majeur de version */
+ uint16_t minor_version; /* Numéro lineur de version */
+ uint32_t name; /* RVA du nom de la DLL visée */
+ uint32_t base; /* Départ des ordinaux listés */
+ uint32_t number_of_functions; /* Taille de liste de fonctions*/
+ uint32_t number_of_names; /* Taille de liste de noms */
+ uint32_t address_of_functions; /* Liste de RVA de fonctions */
+ uint32_t address_of_names; /* Liste de RVA de noms */
+ uint32_t address_of_name_ordinals; /* Liste de RVA d'ordinaux */
+
+} image_export_directory;
+
+
+/**
+ * http://msdn.microsoft.com/en-us/library/ms809762.aspx
+ * http://sandsprite.com/CodeStuff/Understanding_imports.html
+ * http://olance.developpez.com/articles/windows/pe-iczelion/import-table/
+ *
+ * https://docs.microsoft.com/en-us/previous-versions/ms809762(v=msdn.10)?redirectedfrom=MSDN#pe-file-imports
+ * https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
*/
/* Point de départ de la chaîne des importations */
@@ -327,17 +439,4 @@ typedef struct _image_import_descriptor
-
-/* Désignation de fonction importée */
-typedef struct _image_import_by_name
-{
- uint16_t hint;
- char *name;
-
-} image_import_by_name;
-
-
-
-
-
-#endif /* _FORMAT_PE_PE_DEF_H */
+#endif /* _PLUGINS_PE_PE_DEF_H */
diff --git a/plugins/pe/python/Makefile.am b/plugins/pe/python/Makefile.am
new file mode 100644
index 0000000..18634a3
--- /dev/null
+++ b/plugins/pe/python/Makefile.am
@@ -0,0 +1,23 @@
+
+noinst_LTLIBRARIES = libpepython.la
+
+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_LDFLAGS =
+
+
+devdir = $(includedir)/chrysalide/$(subdir)
+
+dev_HEADERS = $(libpepython_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pe/python/constants.c b/plugins/pe/python/constants.c
new file mode 100644
index 0000000..9b4942d
--- /dev/null
+++ b/plugins/pe/python/constants.c
@@ -0,0 +1,143 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.c - équivalent Python partiel du fichier "plugins/pe/pe_def.h"
+ *
+ * Copyright (C) 2020 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "constants.h"
+
+
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "../pe_def.h"
+#include "../routine.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes pour le format PE. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_python_pe_format_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ result = true;
+
+ /**
+ * Indices des répertoires PE
+ */
+
+ values = PyDict_New();
+
+ if (result) result = add_const_to_group(values, "EXPORT", IMAGE_DIRECTORY_ENTRY_EXPORT);
+ if (result) result = add_const_to_group(values, "IMPORT", IMAGE_DIRECTORY_ENTRY_IMPORT);
+ if (result) result = add_const_to_group(values, "RESOURCE", IMAGE_DIRECTORY_ENTRY_RESOURCE);
+ if (result) result = add_const_to_group(values, "EXCEPTION", IMAGE_DIRECTORY_ENTRY_EXCEPTION);
+ if (result) result = add_const_to_group(values, "SECURITY", IMAGE_DIRECTORY_ENTRY_SECURITY);
+ if (result) result = add_const_to_group(values, "BASERELOC", IMAGE_DIRECTORY_ENTRY_BASERELOC);
+ if (result) result = add_const_to_group(values, "DEBUG", IMAGE_DIRECTORY_ENTRY_DEBUG);
+ if (result) result = add_const_to_group(values, "ARCHITECTURE", IMAGE_DIRECTORY_ENTRY_ARCHITECTURE);
+ if (result) result = add_const_to_group(values, "GLOBALPTR", IMAGE_DIRECTORY_ENTRY_GLOBALPTR);
+ if (result) result = add_const_to_group(values, "TLS", IMAGE_DIRECTORY_ENTRY_TLS);
+ if (result) result = add_const_to_group(values, "LOAD_CONFIG", IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
+ if (result) result = add_const_to_group(values, "BOUND_IMPORT", IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT);
+ if (result) result = add_const_to_group(values, "IAT", IMAGE_DIRECTORY_ENTRY_IAT);
+ if (result) result = add_const_to_group(values, "DELAY_IMPORT", IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
+ if (result) result = add_const_to_group(values, "COM_DESCRIPTOR", IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, false, "ImageDirectoryEntry", values,
+ "Index number for a kind of data directory entry.");
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type dont le dictionnaire est à compléter. *
+* *
+* Description : Définit les constantes pour les routines du format PE. *
+* *
+* Retour : true en cas de succès de l'opération, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_python_pe_exported_routine_constants(PyTypeObject *type)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *values; /* Groupe de valeurs à établir */
+
+ result = true;
+
+ values = PyDict_New();
+
+ if (result) result = add_const_to_group(values, "HAS_ORDINAL", PSF_HAS_ORDINAL);
+ if (result) result = add_const_to_group(values, "FORWARDED", PSF_FORWARDED);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, true, "PeSymbolFlag", values,
+ "Extra indications for exported PE routine symbols.");
+
+ values = PyDict_New();
+
+ if (result) result = add_const_to_group(values, "UNDEF_PE_ORDINAL", UNDEF_PE_ORDINAL);
+
+ if (!result)
+ {
+ Py_DECREF(values);
+ goto exit;
+ }
+
+ result = attach_constants_group_to_type(type, false, "OrdinalValue", values,
+ "Extra value for exported PE routine ordinals.");
+
+ exit:
+
+ return result;
+
+}
diff --git a/plugins/pe/python/constants.h b/plugins/pe/python/constants.h
new file mode 100644
index 0000000..25b0adb
--- /dev/null
+++ b/plugins/pe/python/constants.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * constants.h - prototypes pour l'équivalent Python partiel du fichier "plugins/pe/pe_def.h"
+ *
+ * Copyright (C) 2020 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_CONSTANTS_H
+#define _PLUGINS_PE_PYTHON_CONSTANTS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit les constantes pour le format PE. */
+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 *);
+
+
+
+#endif /* _PLUGINS_PE_PYTHON_CONSTANTS_H */
diff --git a/plugins/pe/python/format.c b/plugins/pe/python/format.c
new file mode 100644
index 0000000..d295da4
--- /dev/null
+++ b/plugins/pe/python/format.c
@@ -0,0 +1,595 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * format.c - équivalent Python du fichier "plugins/pe/format.c"
+ *
+ * Copyright (C) 2017-2019 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "format.h"
+
+
+#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 "translate.h"
+#include "../format.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 *);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_pe_format_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/* ------------------------------ DEFINITION DE FORMAT ------------------------------ */
+
+
+/* Présente l'en-tête MS-DOS du format chargé. */
+static PyObject *py_pe_format_get_dos_header(PyObject *, void *);
+
+/* Offre un raccourci vers les répertoires du format PE. */
+static PyObject *py_pe_format_get_directories(PyObject *, void *);
+
+/* Présente l'en-tête enrichi du format chargé. */
+static PyObject *py_pe_format_get_rich_header(PyObject *, void *);
+
+/* Présente l'empreinte d'un en-tête enrichi du format chargé. */
+static PyObject *py_pe_format_get_rich_header_checksum(PyObject *, void *);
+
+/* Présente les identifiants contenues dans l'en-tête enrichi. */
+static PyObject *py_pe_format_get_comp_ids(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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, base);
+
+ 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. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_pe_format_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GBinContent *content; /* Instance GLib du contenu */
+ int ret; /* Bilan de lecture des args. */
+ GPeFormat *format; /* Création GLib à transmettre */
+
+#define PE_FORMAT_DOC \
+ "The PeFormat class handles executables with a Portable Executable" \
+ " structure.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " PeFormat(content)" \
+ "\n" \
+ "Where content points to data as a pychrysalide.analysis.BinContent" \
+ " instance."
+
+ /* Récupération des paramètres */
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ format = G_PE_FORMAT(pygobject_get(self));
+
+ g_known_format_set_content(G_KNOWN_FORMAT(format), content);
+
+ return 0;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION DE FORMAT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : self = format en place à consulter. *
+* closure = non utilisé ici. *
+* *
+* Description : Présente l'en-tête MS-DOS du format chargé. *
+* *
+* Retour : Structure Python créée pour l'occasion. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_dos_header(PyObject *self, void *closure)
+{
+ PyObject *result; /* Trouvaille à retourner */
+ GPeFormat *format; /* Version GLib du format */
+
+#define PE_FORMAT_DOS_HEADER_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ dos_header, py_pe_format, \
+ "MS-DOS header of the file format.\n" \
+ "\n" \
+ "This property is a pychrysalide.StructObject instance." \
+ "\n" \
+ "The provided information is composed of the following" \
+ " properties :\n" \
+ "\n" \
+ "* e_magic;\n" \
+ "* e_cblp;\n" \
+ "* e_cp;\n" \
+ "* e_crlc;\n" \
+ "* e_cparhdr;\n" \
+ "* e_minalloc;\n" \
+ "* e_maxalloc;\n" \
+ "* e_ss;\n" \
+ "* e_sp;\n" \
+ "* e_csum;\n" \
+ "* e_ip;\n" \
+ "* e_cs;\n" \
+ "* e_lfarlc;\n" \
+ "* e_ovno;\n" \
+ "* e_res;\n" \
+ "* e_oemid;\n" \
+ "* e_oeminfo;\n" \
+ "* e_res2;\n" \
+ "* e_lfanew." \
+)
+
+ format = G_PE_FORMAT(pygobject_get(self));
+
+ result = translate_pe_dos_header_to_python(format, g_pe_format_get_dos_header(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. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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 */
+ size_t i; /* Boucle de parcours */
+ PyObject *item; /* Elément de tableau */
+ int ret; /* Bilan d'une mise en place */
+
+#define PE_FORMAT_DIRECTORIES_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ directories, py_pe_format, \
+ "Shortcut to the PE format directories.\n" \
+ "\n" \
+ "This property is a pychrysalide.StructObject instance and" \
+ " can also be access trough the" \
+ " *self.nt_headers.data_directory* attribute.\n" \
+ "\n" \
+ "Each returned item is composed of the following properties :\n"\
+ "\n" \
+ "* virtual_address;\n" \
+ "* size." \
+)
+
+ format = G_PE_FORMAT(pygobject_get(self));
+
+ directories = g_pe_format_get_directories(format, &count);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ {
+ item = translate_pe_image_data_directory_to_python(format, directories + 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. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_rich_header(PyObject *self, void *closure)
+{
+ PyObject *result; /* Trouvaille à retourner */
+ GPeFormat *format; /* Version GLib du format */
+ size_t count; /* Quantité de valeurs obtenues*/
+ uint64_t *values; /* Valeurs brutes à transcrire */
+ size_t i; /* Boucle de parcours */
+
+#define PE_FORMAT_RICH_HEADER_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ rich_header, py_pe_format, \
+ "Raw values from the Rich header of the file format.\n" \
+ "\n" \
+ "This property is a tuple of 64-bit values or an empty" \
+ " tuple if no Rich header exists in the PE file." \
+)
+
+ format = G_PE_FORMAT(pygobject_get(self));
+
+ values = g_pe_format_get_rich_header(format, &count);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ PyTuple_SetItem(result, i, PyLong_FromUnsignedLongLong(values[i]));
+
+ if (values != NULL)
+ free(values);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = format en place à consulter. *
+* closure = non utilisé ici. *
+* *
+* Description : Présente l'empreinte d'un en-tête enrichi du format chargé. *
+* *
+* Retour : Valeur de l'empreinte ou None en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_rich_header_checksum(PyObject *self, void *closure)
+{
+ PyObject *result; /* Trouvaille à retourner */
+ GPeFormat *format; /* Version GLib du format */
+ uint32_t checksum; /* Valeur à transcrire */
+ bool status; /* Validité de cette valeur */
+
+#define PE_FORMAT_RICH_HEADER_CHECKSUM_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ rich_header_checksum, py_pe_format, \
+ "Checksum used as XOR value for the Rich header of the file" \
+ " format.\n" \
+ "\n" \
+ "This property is a 32-bit integer value." \
+)
+
+ format = G_PE_FORMAT(pygobject_get(self));
+
+ status = g_pe_format_get_rich_header_checksum(format, &checksum);
+
+ if (status)
+ result = PyLong_FromUnsignedLong(checksum);
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = format en place à consulter. *
+* closure = non utilisé ici. *
+* *
+* Description : Présente les identifiants contenues dans l'en-tête enrichi. *
+* *
+* Retour : Tableau de valeurs raffinées d'information. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_pe_format_get_comp_ids(PyObject *self, void *closure)
+{
+ PyObject *result; /* Trouvaille à retourner */
+ GPeFormat *format; /* Version GLib du format */
+ size_t count; /* Quantité de valeurs obtenues*/
+ comp_id_t *ids; /* Valeurs raffinées à émettre */
+ size_t i; /* Boucle de parcours */
+
+#define PE_FORMAT_COMP_IDS_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ comp_ids, py_pe_format, \
+ "Compiler identifiers carried by the Rich header of the file" \
+ " format.\n" \
+ "\n" \
+ "This property is a tuple of" \
+ " pychrysalide.StructObject items or an empty tuple if no" \
+ " information is found.\n" \
+ "\n" \
+ "Each item contains the the following properties :\n" \
+ "\n" \
+ "* minor_cv;\n" \
+ "* prod_id;\n" \
+ "* count." \
+)
+
+ format = G_PE_FORMAT(pygobject_get(self));
+
+ ids = g_pe_format_get_comp_ids(format, &count);
+
+ result = PyTuple_New(count);
+
+ for (i = 0; i < count; i++)
+ PyTuple_SetItem(result, i, translate_pe_comp_id_to_python(format, &ids[i]));
+
+ if (ids != NULL)
+ free(ids);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_pe_format_type(void)
+{
+ static PyMethodDef py_pe_format_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_pe_format_getseters[] = {
+ PE_FORMAT_DOS_HEADER_ATTRIB,
+ PE_FORMAT_DIRECTORIES_ATTRIB,
+ PE_FORMAT_RICH_HEADER_ATTRIB,
+ PE_FORMAT_RICH_HEADER_CHECKSUM_ATTRIB,
+ PE_FORMAT_COMP_IDS_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_pe_format_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.format.pe.PeFormat",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = PE_FORMAT_DOC,
+
+ .tp_methods = py_pe_format_methods,
+ .tp_getset = py_pe_format_getseters,
+
+ .tp_init = py_pe_format_init,
+ .tp_new = py_pe_format_new,
+
+ };
+
+ return &py_pe_format_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.format.pe.PeFormat'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_pe_format(PyObject *module)
+{
+ PyTypeObject *type; /* Type Python 'PeFormat' */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_pe_format_type();
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PE_FORMAT, type, get_python_executable_format_type()))
+ return false;
+
+ if (!define_python_pe_format_constants(type))
+ return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en format PE. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_pe_format(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_format_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE format");
+ break;
+
+ case 1:
+ *((GPeFormat **)dst) = G_PE_FORMAT(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pe/python/format.h b/plugins/pe/python/format.h
new file mode 100644
index 0000000..4f52a61
--- /dev/null
+++ b/plugins/pe/python/format.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * format.h - prototypes pour l'équivalent Python du fichier "plugins/pe/format.h"
+ *
+ * Copyright (C) 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_FORMAT_H
+#define _PLUGINS_PE_PYTHON_FORMAT_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_pe_format_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.pe.PeFormat'. */
+bool register_python_pe_format(PyObject *);
+
+/* Tente de convertir en format PE. */
+int convert_to_pe_format(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PE_PYTHON_FORMAT_H */
diff --git a/plugins/pe/python/module.c b/plugins/pe/python/module.c
new file mode 100644
index 0000000..93b1337
--- /dev/null
+++ b/plugins/pe/python/module.c
@@ -0,0 +1,93 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire pe en tant que module
+ *
+ * Copyright (C) 2017-2018 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "module.h"
+
+
+#include <Python.h>
+
+
+#include <plugins/pychrysalide/access.h>
+#include <plugins/pychrysalide/helpers.h>
+
+
+#include "format.h"
+#include "routine.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Ajoute le module 'format.pe' au module Python. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_format_pe_module_to_python_module(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *super; /* Module à compléter */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_FORMAT_PE_MODULE_DOC \
+ "This module provides support for the Portable Executable file format" \
+ " defined by Microsoft.\n" \
+ "\n" \
+ "The specification for this format can be found at:" \
+ "\n" \
+ "* https://web.archive.org/web/20081208121446/http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx"
+
+ static PyModuleDef py_chrysalide_pe_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.format.pe",
+ .m_doc = PYCHRYSALIDE_FORMAT_PE_MODULE_DOC,
+
+ .m_size = -1,
+
+ };
+
+ result = false;
+
+ super = get_access_to_python_module("pychrysalide.format");
+
+ module = build_python_module(super, &py_chrysalide_pe_module);
+
+ 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);
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pe/python/module.h b/plugins/pe/python/module.h
new file mode 100644
index 0000000..9e9b33a
--- /dev/null
+++ b/plugins/pe/python/module.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire pe en tant que module
+ *
+ * Copyright (C) 2017-2019 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_MODULE_H
+#define _PLUGINS_PE_PYTHON_MODULE_H
+
+
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'format.pe' au module Python. */
+bool add_format_pe_module_to_python_module(void);
+
+
+
+#endif /* _PLUGINS_PE_PYTHON_MODULE_H */
diff --git a/plugins/pe/python/routine.c b/plugins/pe/python/routine.c
new file mode 100644
index 0000000..89075ea
--- /dev/null
+++ b/plugins/pe/python/routine.c
@@ -0,0 +1,472 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * routine.c - équivalent Python du fichier "plugins/pe/routine.c"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "routine.h"
+
+
+#include <pygobject.h>
+
+
+#include <i18n.h>
+#include <plugins/pychrysalide/helpers.h>
+#include <plugins/pychrysalide/analysis/routine.h>
+
+
+#include "constants.h"
+#include "../routine.h"
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */
+
+
+#define PE_EXPORTED_ROUTINE_DOC \
+ "The PeExportedRoutine is a definition of a binary routine" \
+ " exported for other PE file."
+
+
+/* Fournit l'indice de la routine dans un fichier PE. */
+static PyObject *py_pe_exported_routine_get_ordinal(PyObject *, void *);
+
+/* Définit l'indice de la routine dans un fichier PE. */
+static int py_pe_exported_routine_set_ordinal(PyObject *, PyObject *, void *);
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */
+
+
+#define PE_IMPORTED_ROUTINE_DOC \
+ "The PeImportedRoutine is a definition of a binary routine" \
+ " imported from other PE file symbol."
+
+
+/* Fournit le fichier DLL visé par une importation de format PE. */
+static PyObject *py_pe_imported_routine_get_library(PyObject *, void *);
+
+/* Définit le fichier DLL visé par une importation de format PE. */
+static int py_pe_imported_routine_set_library(PyObject *, PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SYMBOLES D'UN FORMAT PE EXPORTES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit l'indice de la routine dans un fichier PE. *
+* *
+* Retour : Numéro de la routine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_pe_exported_routine_get_ordinal(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GPeExportedRoutine *routine; /* Version native */
+ uint16_t ordinal; /* Valeur native de l'ordinal */
+
+#define PE_EXPORTED_ROUTINE_ORDINAL_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ ordinal, py_pe_exported_routine, \
+ "Ordinal number linked to the symbol.\n" \
+ "\n" \
+ "The returned integer value is valid only if" \
+ " the pychrysalide.format.pe.PeRoutine.PeSymbolFlag.HAS_ORDINAL" \
+ " bit is set in the symbol flags.\n" \
+ "\n" \
+ "This bit is automatically set when the value is defined." \
+)
+
+ routine = G_PE_EXPORTED_ROUTINE(pygobject_get(self));
+
+ ordinal = g_pe_exported_routine_get_ordinal(routine);
+
+ //result = cast_with_constants_group_from_type(get_python_pe_exported_routine_type(), "OrdinalValue", ordinal);
+
+ result = PyLong_FromUnsignedLong(ordinal);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Définit l'indice de la routine dans un fichier PE. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_pe_exported_routine_set_ordinal(PyObject *self, PyObject *value, void *closure)
+{
+ int ret; /* Bilan d'analyse */
+ GPeExportedRoutine *routine; /* Version native */
+ uint16_t ordinal; /* Valeur native de l'ordinal */
+
+ ret = PyObject_IsInstance(value, (PyObject *)&PyLong_Type);
+ if (!ret) return -1;
+
+ routine = G_PE_EXPORTED_ROUTINE(pygobject_get(self));
+
+ ordinal = PyLong_AsUnsignedLong(value);
+
+ g_pe_exported_routine_set_ordinal(routine, ordinal);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_pe_exported_routine_type(void)
+{
+ static PyMethodDef py_pe_exported_routine_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_pe_exported_routine_getseters[] = {
+ PE_EXPORTED_ROUTINE_ORDINAL_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_pe_exported_routine_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.format.pe.PeExportedRoutine",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = PE_EXPORTED_ROUTINE_DOC,
+
+ .tp_methods = py_pe_exported_routine_methods,
+ .tp_getset = py_pe_exported_routine_getseters
+
+ };
+
+ return &py_pe_exported_routine_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.format.pe.PeRoutine'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_pe_exported_routine(PyObject *module)
+{
+ PyTypeObject *type; /* Type Python 'PeRoutine' */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_pe_exported_routine_type();
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PE_EXPORTED_ROUTINE, type, get_python_binary_routine_type()))
+ return false;
+
+ if (!define_python_pe_exported_routine_constants(type))
+ return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en routine de fichier PE. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_pe_exported_routine(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_exported_routine_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE exported routine");
+ break;
+
+ case 1:
+ *((GPeExportedRoutine **)dst) = G_PE_EXPORTED_ROUTINE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SYMBOLES D'UN FORMAT PE IMPORTES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit le fichier DLL visé par une importation de format PE.*
+* *
+* Retour : Désignation d'une bibliothèque Windows. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_pe_imported_routine_get_library(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GPeImportedRoutine *routine; /* Version native */
+ const char *library; /* Nom de bibliothèque */
+
+#define PE_IMPORTED_ROUTINE_ORDINAL_ATTRIB PYTHON_GETSET_DEF_FULL \
+( \
+ library, py_pe_imported_routine, \
+ "Imported DLL's name for the symbol.\n" \
+ "\n" \
+ "The returned value is a string." \
+)
+
+ routine = G_PE_IMPORTED_ROUTINE(pygobject_get(self));
+
+ library = g_pe_imported_routine_get_library(routine);
+
+ result = PyUnicode_FromString(library);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = adresse non utilisée ici. *
+* *
+* Description : Définit le fichier DLL visé par une importation de format PE.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_pe_imported_routine_set_library(PyObject *self, PyObject *value, void *closure)
+{
+ GPeImportedRoutine *routine; /* Version native */
+
+ if (!PyUnicode_Check(value) && value != Py_None)
+ {
+ PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string or None."));
+ return -1;
+ }
+
+ routine = G_PE_IMPORTED_ROUTINE(pygobject_get(self));
+
+ if (value == Py_None)
+ g_pe_imported_routine_set_library(routine, NULL);
+ else
+ g_pe_imported_routine_set_library(routine, strdup(PyUnicode_DATA(value)));
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_pe_imported_routine_type(void)
+{
+ static PyMethodDef py_pe_imported_routine_methods[] = {
+ { NULL }
+ };
+
+ static PyGetSetDef py_pe_imported_routine_getseters[] = {
+ PE_IMPORTED_ROUTINE_ORDINAL_ATTRIB,
+ { NULL }
+ };
+
+ static PyTypeObject py_pe_imported_routine_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.format.pe.PeImportedRoutine",
+ .tp_basicsize = sizeof(PyGObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+
+ .tp_doc = PE_IMPORTED_ROUTINE_DOC,
+
+ .tp_methods = py_pe_imported_routine_methods,
+ .tp_getset = py_pe_imported_routine_getseters
+
+ };
+
+ return &py_pe_imported_routine_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.format.pe.PeRoutine'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_python_pe_imported_routine(PyObject *module)
+{
+ PyTypeObject *type; /* Type Python 'PeRoutine' */
+ PyObject *dict; /* Dictionnaire du module */
+
+ type = get_python_pe_imported_routine_type();
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_class_for_pygobject(dict, G_TYPE_PE_IMPORTED_ROUTINE, type, get_python_pe_exported_routine_type()))
+ return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : arg = argument quelconque à tenter de convertir. *
+* dst = destination des valeurs récupérées en cas de succès. *
+* *
+* Description : Tente de convertir en routine de fichier PE. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_pe_imported_routine(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_imported_routine_type());
+
+ switch (result)
+ {
+ case -1:
+ /* L'exception est déjà fixée par Python */
+ result = 0;
+ break;
+
+ case 0:
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE imported routine");
+ break;
+
+ case 1:
+ *((GPeImportedRoutine **)dst) = G_PE_IMPORTED_ROUTINE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pe/python/routine.h b/plugins/pe/python/routine.h
new file mode 100644
index 0000000..71cb085
--- /dev/null
+++ b/plugins/pe/python/routine.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * routine.h - prototypes pour l'équivalent Python du fichier "plugins/pe/routine.h"
+ *
+ * Copyright (C) 2019 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_ROUTINE_H
+#define _PLUGINS_PE_PYTHON_ROUTINE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_pe_exported_routine_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.pe.PeExportedRoutine'. */
+bool register_python_pe_exported_routine(PyObject *);
+
+/* Tente de convertir en routine de fichier PE. */
+int convert_to_pe_exported_routine(PyObject *, void *);
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_pe_imported_routine_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.format.pe.PeImportedRoutine'. */
+bool register_python_pe_imported_routine(PyObject *);
+
+/* Tente de convertir en routine de fichier PE. */
+int convert_to_pe_imported_routine(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PE_PYTHON_ROUTINE_H */
diff --git a/plugins/pe/python/translate.c b/plugins/pe/python/translate.c
new file mode 100644
index 0000000..c01a337
--- /dev/null
+++ b/plugins/pe/python/translate.c
@@ -0,0 +1,213 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * translate.c - conversion de structures PE en objets Python
+ *
+ * Copyright (C) 2020 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "translate.h"
+
+
+#include <assert.h>
+
+
+#include <plugins/pychrysalide/struct.h>
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format PE chargé sur lequel s'appuyer. *
+* header = en-tête MS-DOS à décrire en Python. *
+* *
+* Description : Traduit un en-tête MS-DOS en Python. *
+* *
+* Retour : Structure mise en place ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_header *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 */
+ size_t i; /* Boucle de parcours */
+ PyObject *item; /* Elément de tableau */
+
+ base = get_python_py_struct_type();
+
+ result = PyObject_CallFunction((PyObject *)base, NULL);
+ assert(result != NULL);
+
+#define TRANSLATE_DOS_HEADER_FIELD(_f) \
+ do \
+ { \
+ attrib = PyLong_FromUnsignedLongLong(header->e_ ## _f); \
+ ret = PyDict_SetItemString(result, "e_" #_f, attrib); \
+ if (ret != 0) goto failed; \
+ } \
+ while (0);
+
+#define TRANSLATE_DOS_HEADER_FIELD_ARRAY(_f, _n) \
+ do \
+ { \
+ attrib = PyTuple_New(_n); \
+ ret = 0; \
+ for (i = 0; i < _n; i++) \
+ { \
+ item = PyLong_FromUnsignedLongLong(header->e_ ## _f [i]); \
+ ret = PyTuple_SetItem(attrib, i, item); \
+ if (ret != 0) break; \
+ } \
+ if (ret != 0) goto failed; \
+ ret = PyDict_SetItemString(result, "e_" #_f, attrib); \
+ if (ret != 0) goto failed; \
+ } \
+ while (0);
+
+ TRANSLATE_DOS_HEADER_FIELD(magic);
+ TRANSLATE_DOS_HEADER_FIELD(cblp);
+ TRANSLATE_DOS_HEADER_FIELD(cp);
+ TRANSLATE_DOS_HEADER_FIELD(crlc);
+ TRANSLATE_DOS_HEADER_FIELD(cparhdr);
+ TRANSLATE_DOS_HEADER_FIELD(minalloc);
+ TRANSLATE_DOS_HEADER_FIELD(maxalloc);
+ TRANSLATE_DOS_HEADER_FIELD(ss);
+ TRANSLATE_DOS_HEADER_FIELD(sp);
+ TRANSLATE_DOS_HEADER_FIELD(csum);
+ TRANSLATE_DOS_HEADER_FIELD(ip);
+ TRANSLATE_DOS_HEADER_FIELD(cs);
+ TRANSLATE_DOS_HEADER_FIELD(lfarlc);
+ TRANSLATE_DOS_HEADER_FIELD(ovno);
+ TRANSLATE_DOS_HEADER_FIELD_ARRAY(res, 4);
+ TRANSLATE_DOS_HEADER_FIELD(oemid);
+ TRANSLATE_DOS_HEADER_FIELD(oeminfo);
+ TRANSLATE_DOS_HEADER_FIELD_ARRAY(res2, 10);
+ TRANSLATE_DOS_HEADER_FIELD(lfanew);
+
+ return result;
+
+ 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. *
+* *
+* Retour : Structure mise en place ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const image_data_directory *dir)
+{
+ 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);
+
+#define TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(_f) \
+ do \
+ { \
+ attrib = PyLong_FromUnsignedLongLong(dir->_f); \
+ ret = PyDict_SetItemString(result, #_f, attrib); \
+ if (ret != 0) goto failed; \
+ } \
+ while (0);
+
+ TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(virtual_address);
+ TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(size);
+
+ 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. *
+* *
+* Retour : Structure mise en place ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyObject *translate_pe_comp_id_to_python(GPeFormat *format, const comp_id_t *id)
+{
+ 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);
+
+#define TRANSLATE_COMP_ID_VALUE(_f) \
+ do \
+ { \
+ attrib = PyLong_FromUnsignedLongLong(id->_f); \
+ ret = PyDict_SetItemString(result, #_f, attrib); \
+ if (ret != 0) goto failed; \
+ } \
+ while (0);
+
+ TRANSLATE_COMP_ID_VALUE(minor_cv);
+ TRANSLATE_COMP_ID_VALUE(prod_id);
+ TRANSLATE_COMP_ID_VALUE(count);
+
+ return result;
+
+ failed:
+
+ Py_DECREF(result);
+
+ return NULL;
+
+}
diff --git a/plugins/pe/python/translate.h b/plugins/pe/python/translate.h
new file mode 100644
index 0000000..dbde6c8
--- /dev/null
+++ b/plugins/pe/python/translate.h
@@ -0,0 +1,48 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * translate.h - prototypes pour la conversion de structures PE en objets Python
+ *
+ * Copyright (C) 2020 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PE_PYTHON_TRANSLATE_H
+#define _PLUGINS_PE_PYTHON_TRANSLATE_H
+
+
+#include <Python.h>
+
+
+#include "../format.h"
+#include "../rich.h"
+
+
+
+/* Traduit un en-tête MS-DOS en Python. */
+PyObject *translate_pe_dos_header_to_python(GPeFormat *, const image_dos_header *);
+
+/* Traduit un répertoire PE en Python. */
+PyObject *translate_pe_image_data_directory_to_python(GPeFormat *, const image_data_directory *);
+
+/* Traduit une série d'informations enrichies en Python. */
+PyObject *translate_pe_comp_id_to_python(GPeFormat *, const comp_id_t *);
+
+
+
+#endif /* _PLUGINS_PE_PYTHON_TRANSLATE_H */
diff --git a/plugins/pe/rich.c b/plugins/pe/rich.c
new file mode 100644
index 0000000..7764f09
--- /dev/null
+++ b/plugins/pe/rich.c
@@ -0,0 +1,312 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rich.c - lecture des informations enrichies d'un format PE
+ *
+ * Copyright (C) 2020 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 "rich.h"
+
+
+#include <assert.h>
+#include <string.h>
+
+
+#include <format/known.h>
+
+
+#include "pe-int.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* *
+* Description : Extrait si elles existant les informations enrichies du PE. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void extract_pe_rich_header(GPeFormat *format)
+{
+ const image_dos_header *header; /* En-tête avec positions */
+ bin_t *dans; /* Motif "DanS" trouvé */
+ GBinContent *content; /* Contenu à parcourir */
+ vmpa2t start; /* Position de départ */
+ const bin_t *data; /* Données brutes à analyser */
+ bin_t *rich; /* Marqueur "Rich" trouvé */
+ uint32_t checksum; /* Empreinte appliquée */
+ bool status; /* Bilan d'une lecture */
+ bin_t words[8]; /* Premiers mots trouvés */
+
+ header = g_pe_format_get_dos_header(format);
+
+ dans = NULL;
+
+ /* Recherche du marqueur final */
+
+ content = g_known_format_get_content(G_KNOWN_FORMAT(format));
+
+ g_binary_content_compute_start_pos(content, &start);
+
+ data = g_binary_content_get_raw_access(content, &start, header->e_lfanew);
+ if (data == NULL) goto exit;
+
+ rich = memmem(data, header->e_lfanew, "Rich", 4);
+ if (rich == NULL) goto exit;
+
+ /* Constitution des premiers mots */
+
+ g_binary_content_compute_start_pos(content, &start);
+
+ advance_vmpa(&start, rich - data);
+ advance_vmpa(&start, 4);
+
+
+ status = g_binary_content_read_u32(content, &start, SRE_LITTLE, &checksum);
+ if (!status) goto exit;
+
+ g_binary_content_compute_start_pos(content, &start);
+
+ advance_vmpa(&start, rich - data);
+ advance_vmpa(&start, 4);
+
+ status = g_binary_content_read_raw(content, &start, 4, words + 4);
+ assert(status);
+
+ words[0] = 'D' ^ words[4];
+ words[1] = 'a' ^ words[5];
+ words[2] = 'n' ^ words[6];
+ words[3] = 'S' ^ words[7];
+
+ /* Recherche du marqueur initial et conclusion */
+
+ dans = memmem(data, header->e_lfanew, words, 8);
+
+ if (dans != NULL && ((rich - dans) % 8 != 0))
+ dans = NULL;
+
+ exit:
+
+ if (dans == NULL)
+ {
+ init_vmpa(&start, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+ init_mrange(&format->rich_header, &start, 0);
+ }
+
+ else
+ {
+ init_vmpa(&start, (bin_t *)dans - data, VMPA_NO_VIRTUAL);
+ init_mrange(&format->rich_header, &start, rich + 8 - dans);
+ }
+
+ g_object_unref(G_OBJECT(content));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format en place à consulter. *
+* area = localisation à constituer. [OUT] *
+* *
+* Description : Décrit la zone couverte par l'en-tête enrichi du format. *
+* *
+* Retour : Validité de la zone définie en sortie. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_pe_format_get_rich_header_area(const GPeFormat *format, mrange_t *area)
+{
+ bool result; /* Validité à renvoyer */
+
+ result = (get_mrange_length(&format->rich_header) > 0);
+
+ if (result)
+ copy_mrange(area, &format->rich_header);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format en place à consulter. *
+* checksum = empreinte incrustée à retrouver. [OUT] *
+* *
+* Description : Présente l'empreinte d'un en-tête enrichi du format chargé. *
+* *
+* Retour : Validité de la zone définie en sortie. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_pe_format_get_rich_header_checksum(const GPeFormat *format, uint32_t *checksum)
+{
+ bool result; /* Validité à renvoyer */
+ GBinContent *content; /* Contenu à parcourir */
+ vmpa2t pos; /* Tête de lecture */
+#ifndef NDEBUG
+ bool status; /* Bilan d'une lecture */
+#endif
+
+ result = (get_mrange_length(&format->rich_header) > 0);
+
+ if (result)
+ {
+ content = g_known_format_get_content(G_KNOWN_FORMAT(format));
+
+ copy_vmpa(&pos, get_mrange_addr(&format->rich_header));
+ advance_vmpa(&pos, sizeof(uint32_t));
+
+#ifndef NDEBUG
+ status = g_binary_content_read_u32(content, &pos, SRE_LITTLE, checksum);
+ assert(status);
+#else
+ g_binary_content_read_u32(content, &pos, SRE_LITTLE, checksum);
+#endif
+
+ g_object_unref(G_OBJECT(content));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format en place à consulter. *
+* count = nombre d'éléments de la liste constituée. [OUT] *
+* *
+* Description : Présente l'en-tête enrichi du format chargé. *
+* *
+* Retour : Tableau de valeurs brutes d'information. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+uint64_t *g_pe_format_get_rich_header(const GPeFormat *format, size_t *count)
+{
+ uint64_t *result; /* Valeurs à retourner */
+ GBinContent *content; /* Contenu à parcourir */
+ vmpa2t iter; /* Tête de lecture */
+ size_t i; /* Boucle de parcours */
+#ifndef NDEBUG
+ bool status; /* Bilan d'une lecture */
+#endif
+
+ if (get_mrange_length(&format->rich_header) == 0)
+ {
+ *count = 0;
+ result = NULL;
+ }
+
+ else
+ {
+ *count = get_mrange_length(&format->rich_header) / 8;
+ result = malloc(*count * sizeof(uint64_t));
+
+ content = g_known_format_get_content(G_KNOWN_FORMAT(format));
+
+ copy_vmpa(&iter, get_mrange_addr(&format->rich_header));
+
+ for (i = 0; i < *count; i++)
+ {
+#ifndef NDEBUG
+ status = g_binary_content_read_u64(content, &iter, SRE_LITTLE, &result[i]);
+ assert(status);
+#else
+ g_binary_content_read_u64(content, &iter, SRE_LITTLE, &result[i]);
+#endif
+ }
+
+ g_object_unref(G_OBJECT(content));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format en place à consulter. *
+* count = nombre d'éléments de la liste constituée. [OUT] *
+* *
+* Description : Présente les identifiants contenues dans l'en-tête enrichi. *
+* *
+* Retour : Tableau de valeurs raffinées d'information. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+comp_id_t *g_pe_format_get_comp_ids(const GPeFormat *format, size_t *count)
+{
+ comp_id_t *result; /* Identifiants à retourner */
+ uint64_t *values; /* Valeurs brutes à traiter */
+ size_t vcount; /* Quantité de ces valeurs */
+ uint64_t mask; /* Masque à appliquer */
+ size_t i; /* Boucle de parcours */
+
+ values = g_pe_format_get_rich_header(format, &vcount);
+
+ if (vcount > 2)
+ {
+ mask = ((values[0] >> 32) & 0xffffffff);
+ mask |= (mask << 32);
+
+ *count = vcount - 2;
+ result = malloc(*count * sizeof(comp_id_t));
+
+ for (i = 0; i < *count; i++)
+ {
+ values[i + 1] ^= mask;
+
+ result[i].minor_cv = values[i + 1] & 0xffff;
+ result[i].prod_id = (values[i + 1] >> 16) & 0xffff;
+ result[i].count = (values[i + 1] >> 32) & 0xffffffff;
+
+ }
+
+ }
+ else
+ {
+ *count = 0;
+ result = NULL;
+ }
+
+ if (values != NULL)
+ free(values);
+
+ return result;
+
+}
diff --git a/plugins/pe/rich.h b/plugins/pe/rich.h
new file mode 100644
index 0000000..c8fb677
--- /dev/null
+++ b/plugins/pe/rich.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rich.h - prototypes pour la lecture des informations enrichies d'un format PE
+ *
+ * Copyright (C) 2020 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_RICH_H
+#define _PLUGINS_PE_RICH_H
+
+
+#include <stdint.h>
+
+
+#include "format.h"
+
+
+
+/* Extrait si elles existant les informations enrichies du PE. */
+void extract_pe_rich_header(GPeFormat *);
+
+/* Décrit la zone couverte par l'en-tête enrichi du format. */
+bool g_pe_format_get_rich_header_area(const GPeFormat *, mrange_t *);
+
+/* Présente l'empreinte d'un en-tête enrichi du format chargé. */
+bool g_pe_format_get_rich_header_checksum(const GPeFormat *, uint32_t *);
+
+/* Présente l'en-tête enrichi du format chargé. */
+uint64_t *g_pe_format_get_rich_header(const GPeFormat *, size_t *);
+
+/* Identifiants apportés par le compilateur */
+typedef struct _comp_id_t
+{
+ uint16_t minor_cv; /* Version mineure du compilo */
+ uint16_t prod_id; /* Identifiant du type d'objet */
+ uint32_t count; /* Nombre d'objets en cause */
+
+} comp_id_t;
+
+/* Présente les identifiants contenues dans l'en-tête enrichi. */
+comp_id_t *g_pe_format_get_comp_ids(const GPeFormat *, size_t *);
+
+
+
+#endif /* _PLUGINS_PE_RICH_H */
diff --git a/plugins/pe/routine.c b/plugins/pe/routine.c
new file mode 100644
index 0000000..3f2e5ba
--- /dev/null
+++ b/plugins/pe/routine.c
@@ -0,0 +1,429 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * routine.c - prototypes pour la manipulation des routines du format PE
+ *
+ * Copyright (C) 2020 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 "routine.h"
+
+
+#include <analysis/routine-int.h>
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */
+
+
+/* Représentation de routine PE exportée (instance) */
+struct _GPeExportedRoutine
+{
+ GBinRoutine parent; /* A laisser en premier */
+
+ uint16_t ordinal; /* Numéro du symbole */
+
+};
+
+
+/* Représentation de routine PE exportée (classe) */
+struct _GPeExportedRoutineClass
+{
+ GBinRoutineClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des routine PE exportées. */
+static void g_pe_exported_routine_class_init(GPeExportedRoutineClass *);
+
+/* Initialise une instance de routine PE exportée. */
+static void g_pe_exported_routine_init(GPeExportedRoutine *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_pe_exported_routine_finalize(GPeExportedRoutine *);
+
+/* Supprime toutes les références externes. */
+static void g_pe_exported_routine_dispose(GPeExportedRoutine *);
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */
+
+
+/* Représentation de routine PE importée (instance) */
+struct _GPeImportedRoutine
+{
+ GPeExportedRoutine parent; /* A laisser en premier */
+
+ char *library; /* Bibliothèque de rattachement*/
+
+};
+
+
+/* Représentation de routine PE importée (classe) */
+struct _GPeImportedRoutineClass
+{
+ GPeExportedRoutineClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des routines PE importées. */
+static void g_pe_imported_routine_class_init(GPeImportedRoutineClass *);
+
+/* Initialise une instance de routine PE importée. */
+static void g_pe_imported_routine_init(GPeImportedRoutine *);
+
+/* Supprime toutes les références externes. */
+static void g_pe_imported_routine_dispose(GPeImportedRoutine *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_pe_imported_routine_finalize(GPeImportedRoutine *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SYMBOLES D'UN FORMAT PE EXPORTES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une représentation de routine exportée. */
+G_DEFINE_TYPE(GPeExportedRoutine, g_pe_exported_routine, G_TYPE_BIN_ROUTINE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des routines PE exportées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_exported_routine_class_init(GPeExportedRoutineClass *klass)
+{
+ GObjectClass *object; /* Version de base de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_pe_exported_routine_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_pe_exported_routine_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = instance à initialiser. *
+* *
+* Description : Initialise une instance de routine PE exportée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_exported_routine_init(GPeExportedRoutine *routine)
+{
+ routine->ordinal = UNDEF_PE_ORDINAL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_exported_routine_dispose(GPeExportedRoutine *routine)
+{
+ G_OBJECT_CLASS(g_pe_exported_routine_parent_class)->dispose(G_OBJECT(routine));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_exported_routine_finalize(GPeExportedRoutine *routine)
+{
+ G_OBJECT_CLASS(g_pe_exported_routine_parent_class)->finalize(G_OBJECT(routine));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : name = désignation humainement lisible. *
+* *
+* Description : Crée une représentation de routine exportée pour format PE. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPeExportedRoutine *g_pe_exported_routine_new(const char *name)
+{
+ GPeExportedRoutine *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_PE_EXPORTED_ROUTINE, NULL);
+
+ if (name != NULL)
+ g_binary_routine_set_name(G_BIN_ROUTINE(result), strdup(name));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine ayant pour origine un fichier PE. *
+* ordinal = indice de symbole à associer à la routine. *
+* *
+* Description : Définit l'indice de la routine dans un fichier PE. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_pe_exported_routine_set_ordinal(GPeExportedRoutine *routine, uint16_t ordinal)
+{
+ routine->ordinal = ordinal;
+
+ g_binary_symbol_set_flag(G_BIN_SYMBOL(routine), PSF_HAS_ORDINAL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine ayant pour origine un fichier PE. *
+* *
+* Description : Fournit l'indice de la routine dans un fichier PE. *
+* *
+* Retour : Numéro de la routine. *
+* *
+* Remarques : C'est à l'appelant de s'assurer de la validité du retour. *
+* *
+******************************************************************************/
+
+uint16_t g_pe_exported_routine_get_ordinal(const GPeExportedRoutine *routine)
+{
+ uint16_t result; /* Indice à retourner */
+
+ result = routine->ordinal;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* SYMBOLES D'UN FORMAT PE IMPORTES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une représentation de routine importée. */
+G_DEFINE_TYPE(GPeImportedRoutine, g_pe_imported_routine, G_TYPE_PE_EXPORTED_ROUTINE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des routines PE importées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_imported_routine_class_init(GPeImportedRoutineClass *klass)
+{
+ GObjectClass *object; /* Version de base de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_pe_imported_routine_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_pe_imported_routine_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = instance à initialiser. *
+* *
+* Description : Initialise une instance de routine PE importée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_imported_routine_init(GPeImportedRoutine *routine)
+{
+ routine->library = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_imported_routine_dispose(GPeImportedRoutine *routine)
+{
+ G_OBJECT_CLASS(g_pe_imported_routine_parent_class)->dispose(G_OBJECT(routine));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_pe_imported_routine_finalize(GPeImportedRoutine *routine)
+{
+ if (routine->library != NULL)
+ free(routine->library);
+
+ G_OBJECT_CLASS(g_pe_imported_routine_parent_class)->finalize(G_OBJECT(routine));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : name = désignation humainement lisible. *
+* *
+* Description : Crée une représentation de routine importée pour format PE. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPeImportedRoutine *g_pe_imported_routine_new(const char *name)
+{
+ GPeImportedRoutine *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_PE_IMPORTED_ROUTINE, NULL);
+
+ if (name != NULL)
+ g_binary_routine_set_name(G_BIN_ROUTINE(result), strdup(name));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine ayant pour origine un fichier PE. *
+* library = désignation d'une bibliothèque Windows. *
+* *
+* Description : Définit le fichier DLL visé par une importation de format PE.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_pe_imported_routine_set_library(GPeImportedRoutine *routine, const char *library)
+{
+ if (routine->library != NULL)
+ free(routine->library);
+
+ if (library == NULL)
+ routine->library = NULL;
+
+ else
+ routine->library = strdup(library);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : routine = routine ayant pour origine un fichier PE. *
+* *
+* Description : Fournit le fichier DLL visé par une importation de format PE.*
+* *
+* Retour : Désignation d'une bibliothèque Windows. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_pe_imported_routine_get_library(const GPeImportedRoutine *routine)
+{
+ char *result; /* Bibliothèque à retourner */
+
+ result = routine->library;
+
+ return result;
+
+}
diff --git a/plugins/pe/routine.h b/plugins/pe/routine.h
new file mode 100644
index 0000000..62faaaa
--- /dev/null
+++ b/plugins/pe/routine.h
@@ -0,0 +1,111 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * routine.h - prototypes pour la manipulation des routines du format PE
+ *
+ * Copyright (C) 2020 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_ROUTINE_H
+#define _PLUGINS_PE_ROUTINE_H
+
+
+#include <glib-object.h>
+
+
+#include <analysis/routine.h>
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */
+
+
+#define G_TYPE_PE_EXPORTED_ROUTINE g_pe_exported_routine_get_type()
+#define G_PE_EXPORTED_ROUTINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PE_EXPORTED_ROUTINE, GPeExportedRoutine))
+#define G_IS_PE_EXPORTED_ROUTINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PE_EXPORTED_ROUTINE))
+#define G_PE_EXPORTED_ROUTINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PE_EXPORTED_ROUTINE, GPeExportedRoutineClass))
+#define G_IS_PE_EXPORTED_ROUTINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PE_EXPORTED_ROUTINE))
+#define G_PE_EXPORTED_ROUTINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PE_EXPORTED_ROUTINE, GPeExportedRoutineClass))
+
+
+/* Représentation de routine PE exportée (instance) */
+typedef struct _GPeExportedRoutine GPeExportedRoutine;
+
+/* Représentation de routine PE exportée (classe) */
+typedef struct _GPeExportedRoutineClass GPeExportedRoutineClass;
+
+
+/* Drapeaux pour informations complémentaires */
+typedef enum _PeSymbolFlag
+{
+ PSF_HAS_ORDINAL = (1 << (SFL_LOW_USER + 0)), /* Numérotation présente */
+ PSF_FORWARDED = (1 << (SFL_LOW_USER + 1)), /* Renvoi vers une DLL ? */
+
+} PeSymbolFlag;
+
+
+#define UNDEF_PE_ORDINAL 0xffff
+
+
+/* Indique le type défini pour une représentation de routine exportée. */
+GType g_pe_exported_routine_get_type(void);
+
+/* Crée une représentation de routine exportée pour format PE. */
+GPeExportedRoutine *g_pe_exported_routine_new(const char *);
+
+/* Définit l'indice de la routine dans un fichier PE. */
+void g_pe_exported_routine_set_ordinal(GPeExportedRoutine *, uint16_t);
+
+/* Fournit l'indice de la routine dans un fichier PE. */
+uint16_t g_pe_exported_routine_get_ordinal(const GPeExportedRoutine *);
+
+
+
+/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */
+
+
+#define G_TYPE_PE_IMPORTED_ROUTINE g_pe_imported_routine_get_type()
+#define G_PE_IMPORTED_ROUTINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PE_IMPORTED_ROUTINE, GPeImportedRoutine))
+#define G_IS_PE_IMPORTED_ROUTINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PE_IMPORTED_ROUTINE))
+#define G_PE_IMPORTED_ROUTINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PE_IMPORTED_ROUTINE, GPeImportedRoutineClass))
+#define G_IS_PE_IMPORTED_ROUTINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PE_IMPORTED_ROUTINE))
+#define G_PE_IMPORTED_ROUTINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PE_IMPORTED_ROUTINE, GPeImportedRoutineClass))
+
+
+/* Représentation de routine PE importée (instance) */
+typedef struct _GPeImportedRoutine GPeImportedRoutine;
+
+/* Représentation de routine PE importée (classe) */
+typedef struct _GPeImportedRoutineClass GPeImportedRoutineClass;
+
+
+/* Indique le type défini pour une représentation de routine importée. */
+GType g_pe_imported_routine_get_type(void);
+
+/* Crée une représentation de routine importée pour format PE. */
+GPeImportedRoutine *g_pe_imported_routine_new(const char *);
+
+/* Définit le fichier DLL visé par une importation de format PE. */
+void g_pe_imported_routine_set_library(GPeImportedRoutine *, const char *);
+
+/* Fournit le fichier DLL visé par une importation de format PE. */
+const char *g_pe_imported_routine_get_library(const GPeImportedRoutine *);
+
+
+
+#endif /* _PLUGINS_PE_ROUTINE_H */
diff --git a/plugins/pe/section.c b/plugins/pe/section.c
index f4cdaf3..732b35c 100644
--- a/plugins/pe/section.c
+++ b/plugins/pe/section.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* section.h - prototypes pour la gestion des sections d'un PE
*
- * Copyright (C) 2010-2017 Cyrille Bagard
+ * Copyright (C) 2010-2021 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,7 +25,6 @@
#include <malloc.h>
-#include <string.h>
#include "pe-int.h"
@@ -34,26 +33,41 @@
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* index = indice de la section recherchée. *
-* section = ensemble d'informations à faire remonter. [OUT] *
+* 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 : Bilan de l'opération. *
+* Retour : Liste de sections reconstituées ou NULL en cas d'échec. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool find_pe_section_by_index(const GPeFormat *format, uint16_t index, image_section_header *section)
+image_section_header *read_all_pe_sections(const GPeFormat *format, vmpa2t *pos)
{
- off_t offset; /* Emplacement à venir lire */
+ image_section_header *result; /* Liste à retourner */
+ uint16_t count; /* Quantité de sections */
+ uint16_t i; /* Boucle de parcours */
+ bool status; /* Bilan d'une lecture */
- if (index >= format->nt_headers.file_header.number_of_sections) return false;
+ count = format->nt_headers.file_header.number_of_sections;
- offset = format->section_offset + sizeof(image_section_header) * index;
+ result = malloc(count * sizeof(image_section_header));
- return read_pe_image_section_header(format, &offset, section);
+ 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
index e7c399b..2ac21d3 100644
--- a/plugins/pe/section.h
+++ b/plugins/pe/section.h
@@ -21,18 +21,18 @@
*/
-#ifndef _FORMAT_PE_SECTION_H
-#define _FORMAT_PE_SECTION_H
+#ifndef _PLUGINS_PE_SECTION_H
+#define _PLUGINS_PE_SECTION_H
-#include "pe.h"
+#include "format.h"
#include "pe_def.h"
/* Recherche une section donnée au sein de binaire par indice. */
-bool find_pe_section_by_index(const GPeFormat *, uint16_t, image_section_header *);
+image_section_header *read_all_pe_sections(const GPeFormat *, vmpa2t *);
-#endif /* _FORMAT_PE_SECTION_H */
+#endif /* _PLUGINS_PE_SECTION_H */
diff --git a/plugins/pe/symbols.c b/plugins/pe/symbols.c
index 30e43b5..9217466 100644
--- a/plugins/pe/symbols.c
+++ b/plugins/pe/symbols.c
@@ -24,20 +24,35 @@
#include "symbols.h"
+#include <malloc.h>
+
+
+#include <i18n.h>
+
+
#include "pe-int.h"
+#include "routine.h"
+/* Charge en mémoire la liste humaine des symboles exportés. */
+static bool load_pe_exported_symbols(GPeFormat *, wgroup_id_t, GtkStatusStack *);
+/* Charge en mémoire la liste humaine des symboles importés. */
+static bool load_pe_imported_symbols(GPeFormat *, wgroup_id_t, GtkStatusStack *);
+/* Assure l'inscription du point d'entrée d'un binaire PE. */
+static bool load_pe_entry_point(GPeFormat *, GtkStatusStack *);
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
+* Paramètres : format = format chargé dont l'analyse est lancée. *
+* gid = groupe de travail dédié. *
+* status = barre de statut à tenir informée. *
* *
-* Description : Charge en mémoire la liste humaine des symboles importés. *
+* Description : Charge en mémoire la liste humaine des symboles exportés. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -45,74 +60,331 @@
* *
******************************************************************************/
-bool load_pe_imported_symbols(GPeFormat *format)
+static bool load_pe_exported_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
{
bool result; /* Bilan à retourner */
- const image_data_directory *directory; /* Répertoire original */
- image_import_descriptor dll; /* DLL importée */
- off_t pos; /* Position de tête de lecture */
- off_t i; /* Boucle de parcours */
- image_import_by_name import; /* Fonction importée */
+ image_export_directory *export; /* Répertoire de type 0 */
+ const image_data_directory *dir; /* Localisation du répertoire */
+ GBinFormat *base; /* Version basique du format */
+ GExeFormat *exe; /* Autre vision du format */
+ bool ret; /* Bilan d'un traitement */
+ vmpa2t functions; /* Localisation des adresses */
+ vmpa2t names; /* Localisation de RVA de noms */
+ vmpa2t ordinals; /* Localisation des ordinaux */
+ const GBinContent *content; /* Contenu binaire à lire */
+ uint32_t i; /* Boucle de parcours */
+ uint32_t rva; /* Adresse relative à traiter */
+ vmpa2t pos; /* Position correspondante */
+ const bin_t *name; /* Pointeur vers des données */
+ uint16_t ordinal; /* Indice de l'exportation */
+ bool forwarded; /* Le symbole est renvoyé ? */
+ GPeExportedRoutine *routine; /* Nouvelle routine trouvée */
+ GBinSymbol *symbol; /* Equivalence en symbole */
+ mrange_t range; /* Couverture mémoire associée */
+
+ result = false;
+
+ export = g_pe_format_get_directory(format, IMAGE_DIRECTORY_ENTRY_EXPORT);
+ if (export == NULL) goto exit;
+
+ dir = g_pe_format_get_directories(format, NULL);
+ dir += IMAGE_DIRECTORY_ENTRY_EXPORT;
+
+ base = G_BIN_FORMAT(format);
+ exe = G_EXE_FORMAT(format);
+
+ ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_functions, &functions);
+ if (!ret) goto exit_loading;
+
+ ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_names, &names);
+ if (!ret) goto exit_loading;
+
+ ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_name_ordinals, &ordinals);
+ if (!ret) goto exit_loading;
+
+ content = G_KNOWN_FORMAT(format)->content;
+
+ for (i = 0; i < export->number_of_names; i++)
+ {
+ /* Dénomination */
+
+ ret = g_binary_content_read_u32(content, &names, SRE_LITTLE, &rva);
+ if (!ret) goto exit_loading;
+
+ ret = g_exe_format_translate_address_into_vmpa(exe, rva, &pos);
+ if (!ret) goto exit_loading;
+
+ name = g_binary_content_get_raw_access(content, &pos, 1);
+ if (name == NULL) goto exit_loading;
+
+ /* Ordinal */
+
+ ret = g_binary_content_read_u16(content, &ordinals, SRE_LITTLE, &ordinal);
+ if (!ret) goto exit_loading;
+
+ ordinal += export->base;
+
+ /* Adresse */
+
+ copy_vmpa(&pos, &functions);
+ advance_vmpa(&pos, ordinal * sizeof(uint32_t));
+
+ ret = g_binary_content_read_u32(content, &pos, SRE_LITTLE, &rva);
+ if (!ret) goto exit_loading;
+
+ /**
+ * Entrée de type "Forwarder RVA" ?
+ */
+ forwarded = (dir->virtual_address <= rva && rva < (dir->virtual_address + dir->size));
+
+ ret = g_exe_format_translate_address_into_vmpa(exe, rva, &pos);
+ if (!ret) continue;
+
+ /* Mise en place du symbole */
+
+ routine = g_pe_exported_routine_new((char *)name);
+
+ g_pe_exported_routine_set_ordinal(routine, ordinal);
+
+ symbol = G_BIN_SYMBOL(routine);
+
+ if (forwarded)
+ g_binary_symbol_set_flag(symbol, PSF_FORWARDED);
+
+ g_binary_symbol_set_status(symbol, SSS_EXPORTED);
+
+ init_mrange(&range, &pos, 0);
+
+ g_binary_symbol_set_range(symbol, &range);
+
+ g_binary_format_add_symbol(base, symbol);
+
+ }
result = true;
- directory = &format->nt_headers.optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+ exit_loading:
+
+ free(export);
+
+ exit:
+
+ return result;
+
+}
+
- /* TODO : msg si size !% sizeof(...) */
+/******************************************************************************
+* *
+* Paramètres : format = format chargé dont l'analyse est lancée. *
+* gid = groupe de travail dédié. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Charge en mémoire la liste humaine des symboles importés. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- for (pos = directory->virtual_address;
- result && pos < (directory->virtual_address + directory->size); )
+static bool load_pe_imported_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+ bool result; /* Bilan à retourner */
+ bool is_32b; /* Exécutable 32 bits ? */
+ image_import_descriptor *imports; /* Répertoire de type 1 */
+ GBinFormat *base; /* Version basique du format */
+ GExeFormat *exe; /* Autre vision du format */
+ const GBinContent *content; /* Contenu binaire à lire */
+ image_import_descriptor *iter; /* Boucle de parcours */
+ vmpa2t dll; /* Nom de la DLL concernée */
+ bool ret; /* Bilan d'un traitement */
+ const bin_t *library; /* Pointeur vers des données */
+ vmpa2t lookup; /* Informations d'importation */
+ vmpa2t overwritten; /* Emplacement d'adresse finale*/
+ uint32_t val32; /* Indications sur 32 bits */
+ uint64_t val64; /* Indications sur 64 bits */
+ uint32_t rva; /* Adresse relative à traiter */
+ vmpa2t name; /* Désignation humaine */
+ const bin_t *hint; /* Pointeur vers des données */
+ GPeImportedRoutine *routine; /* Nouvelle routine trouvée */
+ GBinSymbol *symbol; /* Equivalence en symbole */
+ mrange_t range; /* Couverture mémoire associée */
+
+ result = false;
+
+ is_32b = g_pe_format_get_is_32b(format);
+
+ imports = g_pe_format_get_directory(format, IMAGE_DIRECTORY_ENTRY_IMPORT);
+ if (imports == NULL) goto exit;
+
+ base = G_BIN_FORMAT(format);
+ exe = G_EXE_FORMAT(format);
+
+ content = G_KNOWN_FORMAT(format)->content;
+
+ for (iter = imports; iter->original_first_thunk != 0; iter++)
{
- result = read_pe_image_import_descriptor(format, &pos, &dll);
+ /* Bibliothèque impactée */
- printf("mod orig thunk :: 0x%08x\n", dll.original_first_thunk);
- printf("mod name :: 0x%08x\n", dll.module_name);
- printf("mod first thunk :: 0x%08x\n", dll.first_thunk);
+ ret = g_exe_format_translate_address_into_vmpa(exe, iter->module_name, &dll);
+ if (!ret) goto exit_loading;
- i = dll.original_first_thunk;
+ library = g_binary_content_get_raw_access(content, &dll, 1);
+ if (library == NULL) goto exit_loading;
- /* TODO : i == 0 */
- if (i == 0) continue;
+ /* Liste des fonctions importées */
- while ((result = read_pe_image_import_by_name(format, &i, &import)))
+ ret = g_exe_format_translate_address_into_vmpa(exe, iter->original_first_thunk, &lookup);
+ if (!ret) goto exit_loading;
+
+ ret = g_exe_format_translate_address_into_vmpa(exe, iter->first_thunk, &overwritten);
+ if (!ret) goto exit_loading;
+
+ do
{
- if (import.hint == 0 && import.name == NULL)
+ if (is_32b)
+ {
+ ret = g_binary_content_read_u32(content, &lookup, SRE_LITTLE, &val32);
+ if (!ret) goto exit_loading;
+
+ val64 = ((uint64_t)(val32 & 0x80000000)) << 32 | val32;
+
+ }
+ else
+ {
+ ret = g_binary_content_read_u64(content, &lookup, SRE_LITTLE, &val64);
+ if (!ret) goto exit_loading;
+ }
+
+ if (val64 == 0)
break;
+ if (val64 & 0x8000000000000000)
+ {
+ routine = g_pe_imported_routine_new(NULL);
+ g_pe_exported_routine_set_ordinal(G_PE_EXPORTED_ROUTINE(routine), val64 & 0xffff);
- printf(" >> import '%s'\n", import.name);
+ }
+ else
+ {
+ rva = (val64 & 0x7fffffff);
+ ret = g_exe_format_translate_address_into_vmpa(exe, rva, &name);
+ if (!ret) goto exit_loading;
- }
+ hint = g_binary_content_get_raw_access(content, &name, 3);
+ if (hint == NULL) goto exit_loading;
+
+ hint += 2;
+
+ //routine = g_binary_format_decode_routine(base, hint);
+ routine = g_pe_imported_routine_new((char *)hint);
+ }
+
+ g_pe_imported_routine_set_library(routine, (char *)library);
+
+ symbol = G_BIN_SYMBOL(routine);
+
+ g_binary_symbol_set_status(symbol, SSS_IMPORTED);
+
+ init_mrange(&range, &overwritten, sizeof(uint32_t));
+ advance_vmpa(&overwritten, sizeof(uint32_t));
+
+ g_binary_symbol_set_range(symbol, &range);
+
+ g_binary_format_add_symbol(base, symbol);
+
+ }
+ while (true);
}
- lpis_exit:
+ result = true;
+
+ exit_loading:
+
+ free(imports);
+
+ exit:
return result;
}
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à consulter. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Assure l'inscription du point d'entrée d'un binaire PE. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool load_pe_entry_point(GPeFormat *format, GtkStatusStack *status)
+{
+ bool result; /* Bilan à renvoyer */
+ activity_id_t msg; /* Message de progression */
+ const image_nt_headers *headers; /* Informations d'entête */
+ virt_t ep; /* Point d'entrée détecté */
+ vmpa2t addr; /* Localisation d'une routine */
+ GBinFormat *base; /* Autre version du format */
+ GBinSymbol *symbol; /* Nouveau symbole construit */
+ GBinRoutine *routine; /* Routine à associer au point */
+ mrange_t range; /* Couverture mémoire associée */
+
+ msg = gtk_status_stack_add_activity(status, _("Registering entry point..."), 0);
+
+ headers = g_pe_format_get_nt_headers(format);
+ ep = headers->optional_header.header_32.address_of_entry_point;
+ result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), ep, &addr);
+ if (!result) goto exit;
+ base = G_BIN_FORMAT(format);
+ if (!g_binary_format_find_symbol_at(base, &addr, &symbol))
+ {
+ routine = g_binary_format_decode_routine(base, "entry_point");
+ symbol = G_BIN_SYMBOL(routine);
+ g_object_ref(G_OBJECT(symbol));
+ init_mrange(&range, &addr, 0);
+ g_binary_symbol_set_range(symbol, &range);
+ g_binary_format_add_symbol(base, symbol);
+ }
+ g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT);
+ g_object_unref(G_OBJECT(symbol));
+ /* Comptabilisation pour le désassemblage brut */
+ g_binary_format_register_code_point(base, get_virt_addr(&addr), DPL_ENTRY_POINT);
+ exit:
+ gtk_status_stack_remove_activity(status, msg);
+
+ return result;
+
+}
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
+* Paramètres : format = format chargé dont l'analyse est lancée. *
+* gid = groupe de travail dédié. *
+* status = barre de statut à tenir informée. *
* *
* Description : Charge en mémoire la liste humaine des symboles. *
* *
@@ -122,14 +394,19 @@ bool load_pe_imported_symbols(GPeFormat *format)
* *
******************************************************************************/
-bool load_pe_symbols(GPeFormat *format)
+bool load_pe_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status)
{
bool result; /* Bilan à retourner */
- /* Symboles externes */
- result = load_pe_imported_symbols(format);
+ result = load_pe_exported_symbols(format, gid, status);
+
+ if (result)
+ result = load_pe_imported_symbols(format, gid, status);
+
+ /* Symbole d'entrée, si encore besoin */
- /* Symboles internes */
+ if (result)
+ result = load_pe_entry_point(format, status);
return result;
diff --git a/plugins/pe/symbols.h b/plugins/pe/symbols.h
index 7581152..bb260cd 100644
--- a/plugins/pe/symbols.h
+++ b/plugins/pe/symbols.h
@@ -21,16 +21,21 @@
*/
-#ifndef _FORMAT_PE_SYMBOLS_H
-#define _FORMAT_PE_SYMBOLS_H
+#ifndef _PLUGINS_PE_SYMBOLS_H
+#define _PLUGINS_PE_SYMBOLS_H
-#include "pe.h"
+#include "format.h"
+
+
+#include <glibext/delayed.h>
+#include <gtkext/gtkstatusstack.h>
+
/* Charge en mémoire la liste humaine des symboles. */
-bool load_pe_symbols(GPeFormat *);
+bool load_pe_symbols(GPeFormat *, wgroup_id_t, GtkStatusStack *);
-#endif /* _FORMAT_PE_SYMBOLS_H */
+#endif /* _PLUGINS_PE_SYMBOLS_H */
diff --git a/plugins/pychrysalide/format/constants.c b/plugins/pychrysalide/format/constants.c
index df40479..08d4502 100644
--- a/plugins/pychrysalide/format/constants.c
+++ b/plugins/pychrysalide/format/constants.c
@@ -200,7 +200,6 @@ bool define_binary_symbol_constants(PyTypeObject *type)
result = add_const_to_group(values, "NONE", SFL_NONE);
if (result) result = add_const_to_group(values, "HAS_NM_PREFIX", SFL_HAS_NM_PREFIX);
- if (result) result = add_const_to_group(values, "MASK", SFL_MASK);
if (!result)
{