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