From b0347ca45a08ac63bc6dd6f244b046c6d19a6cdd Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 6 Apr 2021 00:59:31 +0200 Subject: Build a partial working support for the PE format. --- configure.ac | 2 + plugins/Makefile.am | 1 + plugins/elf/symbols.c | 6 +- plugins/pe/Makefile.am | 50 ++- plugins/pe/core.c | 117 ++++++ plugins/pe/core.h | 41 ++ plugins/pe/format.c | 714 ++++++++++++++++++++++++++++---- plugins/pe/format.h | 34 +- plugins/pe/pe-int.c | 364 +++++++++------- plugins/pe/pe-int.h | 48 +-- plugins/pe/pe_def.h | 165 ++++++-- plugins/pe/python/Makefile.am | 23 + plugins/pe/python/constants.c | 143 +++++++ plugins/pe/python/constants.h | 42 ++ plugins/pe/python/format.c | 595 ++++++++++++++++++++++++++ plugins/pe/python/format.h | 45 ++ plugins/pe/python/module.c | 93 +++++ plugins/pe/python/module.h | 38 ++ plugins/pe/python/routine.c | 472 +++++++++++++++++++++ plugins/pe/python/routine.h | 62 +++ plugins/pe/python/translate.c | 213 ++++++++++ plugins/pe/python/translate.h | 48 +++ plugins/pe/rich.c | 312 ++++++++++++++ plugins/pe/rich.h | 61 +++ plugins/pe/routine.c | 429 +++++++++++++++++++ plugins/pe/routine.h | 111 +++++ plugins/pe/section.c | 36 +- plugins/pe/section.h | 10 +- plugins/pe/symbols.c | 335 +++++++++++++-- plugins/pe/symbols.h | 15 +- plugins/pychrysalide/format/constants.c | 1 - src/format/strsym.h | 4 +- src/format/symbol.c | 2 +- src/format/symbol.h | 6 +- 34 files changed, 4265 insertions(+), 373 deletions(-) create mode 100644 plugins/pe/core.c create mode 100644 plugins/pe/core.h create mode 100644 plugins/pe/python/Makefile.am create mode 100644 plugins/pe/python/constants.c create mode 100644 plugins/pe/python/constants.h create mode 100644 plugins/pe/python/format.c create mode 100644 plugins/pe/python/format.h create mode 100644 plugins/pe/python/module.c create mode 100644 plugins/pe/python/module.h create mode 100644 plugins/pe/python/routine.c create mode 100644 plugins/pe/python/routine.h create mode 100644 plugins/pe/python/translate.c create mode 100644 plugins/pe/python/translate.h create mode 100644 plugins/pe/rich.c create mode 100644 plugins/pe/rich.h create mode 100644 plugins/pe/routine.c create mode 100644 plugins/pe/routine.h diff --git a/configure.ac b/configure.ac index c2c3943..dd463e7 100644 --- a/configure.ac +++ b/configure.ac @@ -497,6 +497,8 @@ AC_CONFIG_FILES([Makefile plugins/libcsem/Makefile plugins/lnxsyscalls/Makefile plugins/mobicore/Makefile + plugins/pe/Makefile + plugins/pe/python/Makefile plugins/pychrysalide/Makefile plugins/pychrysalide/analysis/Makefile plugins/pychrysalide/analysis/contents/Makefile 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 . + */ + + +#include "core.h" + + +#include +#include +#include + + +#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 . + */ + + +#ifndef _PLUGINS_PE_CORE_H +#define _PLUGINS_PE_CORE_H + + +#include +#include + + + +/* 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 +#include #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, §ion_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, §ion_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, §ion)) + 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 #include -#include -#include "../../core/formats.h" +#include +#include + + +#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 #include - -#include "../../common/endianness.h" +#include /****************************************************************************** * * * 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 *)§ion->name[i], content, pos, length); + result = g_binary_content_read_u8(content, pos, (uint8_t *)§ion->name[i]); - result &= read_u32(§ion->misc.physical_address, content, pos, length, SRE_LITTLE); + if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->misc.physical_address); - result &= read_u32(§ion->virtual_address, content, pos, length, SRE_LITTLE); - result &= read_u32(§ion->size_of_raw_data, content, pos, length, SRE_LITTLE); - result &= read_u32(§ion->pointer_to_raw_data, content, pos, length, SRE_LITTLE); - result &= read_u32(§ion->pointer_to_relocations, content, pos, length, SRE_LITTLE); - result &= read_u32(§ion->pointer_to_line_numbers, content, pos, length, SRE_LITTLE); - result &= read_u16(§ion->number_of_relocations, content, pos, length, SRE_LITTLE); - result &= read_u16(§ion->number_of_line_numbers, content, pos, length, SRE_LITTLE); - result &= read_u32(§ion->characteristics, content, pos, length, SRE_LITTLE); + if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->virtual_address); + if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->size_of_raw_data); + if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->pointer_to_raw_data); + if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->pointer_to_relocations); + if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->pointer_to_line_numbers); + if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, §ion->number_of_relocations); + if (result) result = g_binary_content_read_u16(content, pos, SRE_LITTLE, §ion->number_of_line_numbers); + if (result) result = g_binary_content_read_u32(content, pos, SRE_LITTLE, §ion->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 +#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 +/** + * 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 + + +#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 +#include + + + +/* 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 + + +#include +#include +#include +#include +#include + + +#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 +#include + + + +/* 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 + + +#include +#include + + +#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 + + + +/* 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 + + +#include +#include +#include + + +#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 +#include + + + +/* ------------------------ 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 + + +#include + + + +/****************************************************************************** +* * +* 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 + + +#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 . + */ + + +#include "rich.h" + + +#include +#include + + +#include + + +#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 . + */ + + +#ifndef _PLUGINS_PE_RICH_H +#define _PLUGINS_PE_RICH_H + + +#include + + +#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 . + */ + + +#include "routine.h" + + +#include + + + +/* ------------------------ 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 . + */ + + +#ifndef _PLUGINS_PE_ROUTINE_H +#define _PLUGINS_PE_ROUTINE_H + + +#include + + +#include + + + +/* ------------------------ 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 -#include #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 + + +#include + + #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 +#include + /* 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) { diff --git a/src/format/strsym.h b/src/format/strsym.h index 5c8a34f..10ae769 100644 --- a/src/format/strsym.h +++ b/src/format/strsym.h @@ -52,8 +52,8 @@ typedef enum _StringEncodingType #define G_TYPE_STR_SYMBOL g_string_symbol_get_type() -#define G_STR_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_string_symbol_get_type(), GStrSymbol)) -#define G_IS_STR_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_string_symbol_get_type())) +#define G_STR_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_STR_SYMBOL, GStrSymbol)) +#define G_IS_STR_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_STR_SYMBOL)) #define G_STR_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STR_SYMBOL, GStrSymbolClass)) #define G_IS_STR_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STR_SYMBOL)) #define G_STR_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STR_SYMBOL, GStrSymbolClass)) diff --git a/src/format/symbol.c b/src/format/symbol.c index 9e57e14..eb61db8 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -550,7 +550,7 @@ SymbolFlag g_binary_symbol_get_flags(const GBinSymbol *symbol) g_bit_lock(&extra->lock, HOLE_LOCK_BIT); - result = (extra->flags & SFL_MASK); + result = extra->flags; g_bit_unlock(&extra->lock, HOLE_LOCK_BIT); diff --git a/src/format/symbol.h b/src/format/symbol.h index 577eb83..5235410 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -63,12 +63,16 @@ typedef enum _SymbolStatus } SymbolStatus; /* Indications supplémentaires liées aux symboles */ + +#define SFL_USER_BIT 1 + typedef enum _SymbolFlag { SFL_NONE = (0 << 0), /* Aucune propriété */ SFL_HAS_NM_PREFIX = (1 << 0), /* Indication de nature */ - SFL_MASK = (1 << 1) - 1, /* Indication de nature */ + SFL_LOW_USER = (1 << SFL_USER_BIT),/* Premier bit disponible */ + SFL_HIGH_USER = (1 << 7), /* Dernier bit disponible */ } SymbolFlag; -- cgit v0.11.2-87-g4458