diff options
Diffstat (limited to 'src/analysis')
29 files changed, 1379 insertions, 32 deletions
| diff --git a/src/analysis/scan/core.c b/src/analysis/scan/core.c index fdee1c7..7b1a455 100644 --- a/src/analysis/scan/core.c +++ b/src/analysis/scan/core.c @@ -30,6 +30,8 @@  #include "items/count.h"  #include "items/datasize.h" +#include "items/maxcommon.h" +#include "items/modpath.h"  #include "items/uint.h"  #include "items/console/log.h"  #ifdef INCLUDE_MAGIC_SUPPORT @@ -249,6 +251,8 @@ bool populate_main_scan_namespace(GScanNamespace *space)      if (result) result = REGISTER_FUNC(space, g_scan_count_function_new());      if (result) result = REGISTER_FUNC(space, g_scan_datasize_function_new()); +    if (result) result = REGISTER_FUNC(space, g_scan_maxcommon_function_new()); +    if (result) result = REGISTER_FUNC(space, g_scan_modpath_function_new());      if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_8_BITS_SIGNED, SRE_LITTLE));      if (result) result = REGISTER_FUNC(space, g_scan_uint_function_new(MDS_8_BITS_UNSIGNED, SRE_LITTLE)); diff --git a/src/analysis/scan/exprs/handler-int.h b/src/analysis/scan/exprs/handler-int.h index f707fdb..a38dd03 100644 --- a/src/analysis/scan/exprs/handler-int.h +++ b/src/analysis/scan/exprs/handler-int.h @@ -37,7 +37,9 @@ struct _GScanPatternHandler  {      GScanExpression parent;                 /* A laisser en premier        */ -    GSearchPattern *pattern;                /* Motif associé               */ +    GSearchPattern **patterns;              /* Motifs associés             */ +    size_t count;                           /* Nombre de ces motifs        */ +      ScanHandlerType type;                   /* Manipulation attendue       */  }; @@ -51,7 +53,7 @@ struct _GScanPatternHandlerClass  /* Met en place une manipulation de correspondances établies. */ -bool g_scan_pattern_handler_create(GScanPatternHandler *, GSearchPattern *, ScanHandlerType); +bool g_scan_pattern_handler_create(GScanPatternHandler *, GSearchPattern ** const, size_t, ScanHandlerType); diff --git a/src/analysis/scan/exprs/handler.c b/src/analysis/scan/exprs/handler.c index 1676522..1b6416e 100644 --- a/src/analysis/scan/exprs/handler.c +++ b/src/analysis/scan/exprs/handler.c @@ -122,7 +122,9 @@ static void g_scan_pattern_handler_class_init(GScanPatternHandlerClass *klass)  static void g_scan_pattern_handler_init(GScanPatternHandler *handler)  { -    handler->pattern = NULL; +    handler->patterns = NULL; +    handler->count = 0; +      handler->type = SHT_RAW;  } @@ -142,7 +144,10 @@ static void g_scan_pattern_handler_init(GScanPatternHandler *handler)  static void g_scan_pattern_handler_dispose(GScanPatternHandler *handler)  { -    g_clear_object(&handler->pattern); +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < handler->count; i++) +         g_clear_object(&handler->patterns[i]);      G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->dispose(G_OBJECT(handler)); @@ -170,8 +175,9 @@ static void g_scan_pattern_handler_finalize(GScanPatternHandler *handler)  /******************************************************************************  *                                                                             * -*  Paramètres  : pattern = motif à impliquer.                                 * -*                type    = type de manipulation attendue.                     * +*  Paramètres  : patterns = motifs à impliquer.                               * +*                count    = quantité de ces motifs.                           * +*                type     = type de manipulation attendue.                    *  *                                                                             *  *  Description : Met en place une manipulation de correspondances établies.   *  *                                                                             * @@ -181,13 +187,13 @@ static void g_scan_pattern_handler_finalize(GScanPatternHandler *handler)  *                                                                             *  ******************************************************************************/ -GScanExpression *g_scan_pattern_handler_new(GSearchPattern *pattern, ScanHandlerType type) +GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const patterns, size_t count, ScanHandlerType type)  {      GScanExpression *result;                /* Structure à retourner       */      result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL); -    if (!g_scan_pattern_handler_create(G_SCAN_PATTERN_HANDLER(result), pattern, type)) +    if (!g_scan_pattern_handler_create(G_SCAN_PATTERN_HANDLER(result), patterns, count, type))          g_clear_object(&result);      return result; @@ -197,9 +203,10 @@ GScanExpression *g_scan_pattern_handler_new(GSearchPattern *pattern, ScanHandler  /******************************************************************************  *                                                                             * -*  Paramètres  : handler = instance à initialiser pleinement.                 * -*                pattern = motif à impliquer.                                 * -*                type    = type de manipulation attendue.                     * +*  Paramètres  : handler  = instance à initialiser pleinement.                * +*                patterns = motifs à impliquer.                               * +*                count    = quantité de ces motifs.                           * +*                type     = type de manipulation attendue.                    *  *                                                                             *  *  Description : Met en place une manipulation de correspondances établies.   *  *                                                                             * @@ -209,15 +216,22 @@ GScanExpression *g_scan_pattern_handler_new(GSearchPattern *pattern, ScanHandler  *                                                                             *  ******************************************************************************/ -bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern *pattern, ScanHandlerType type) +bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern ** const patterns, size_t count, ScanHandlerType type)  {      bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours          */      result = g_scan_expression_create(G_SCAN_EXPRESSION(handler), SRS_WAIT_FOR_SCAN);      if (!result) goto exit; -    handler->pattern = pattern; -    g_object_ref(G_OBJECT(pattern)); +    handler->patterns = malloc(count * sizeof(GSearchPattern *)); +    handler->count = count; + +    for (i = 0; i < count; i++) +    { +        handler->patterns[i] = patterns[i]; +        g_object_ref(G_OBJECT(patterns[i])); +    }      handler->type = type; @@ -228,6 +242,63 @@ bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : handler = instance à initialiser pleinement.                 * +*                ctx     = contexte de suivi de l'analyse courante.           * +*                count   = quantité de correspondances enregistrées. [OUT]    * +*                                                                             * +*  Description : Fournit la liste de toutes les correspondances représentées. * +*                                                                             * +*  Retour      : Liste courante de correspondances établies.                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanMatch **g_scan_pattern_handler_get_all_matches(const GScanPatternHandler *handler, GScanContext *ctx, size_t *count) +{ +    GScanMatch **result;                    /* Liste à retourner           */ +    size_t used;                            /* Indice pour le stockage     */ +    size_t i;                               /* Boucle de parcours #1       */ +    size_t partial;                         /* Décompte partiel            */ +    const GScanMatch **matches;             /* Correspondances en place    */ +    size_t k;                               /* Boucle de parcours #2       */ + +    result = NULL; + +    if (!g_scan_pattern_handler_count_items(handler, ctx, count)) +    { +        *count = 0; +        goto exit; +    } + +    if (*count == 0) +        goto exit; + +    result = malloc(*count * sizeof(GScanMatch *)); + +    used = 0; + +    for (i = 0; i < handler->count; i++) +    { +        matches = g_scan_context_get_full_matches(ctx, handler->patterns[i], &partial); + +        for (k = 0; k < partial; k++) +        { +            result[used++] = matches[k]; +            g_object_ref(G_OBJECT(matches[k])); +        } + +    } + + exit: + +    return result; + +} + +  /* ---------------------------------------------------------------------------------- */  /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ @@ -284,9 +355,7 @@ static bool g_scan_pattern_handler_reduce_to_boolean(const GScanPatternHandler *      bool result;                            /* Bilan à retourner           */      size_t count;                           /* Quantité de correspondances */ -    result = true; - -    g_scan_context_get_full_matches(ctx, expr->pattern, &count); +    result = g_scan_pattern_handler_count_items(expr, ctx, &count);      *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 }); @@ -312,12 +381,20 @@ static bool g_scan_pattern_handler_reduce_to_boolean(const GScanPatternHandler *  static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *expr, GScanContext *ctx, size_t *count)  {      bool result;                            /* Bilan à retourner           */ +    size_t partial;                         /* Décompte partiel            */ +    size_t i;                               /* Boucle de parcours          */      result = true;      assert(g_scan_context_is_scan_done(ctx)); -    g_scan_context_get_full_matches(ctx, expr->pattern, count); +    *count = 0; + +    for (i = 0; i < expr->count; i++) +    { +        g_scan_context_get_full_matches(ctx, expr->patterns[i], &partial); +        *count += partial; +    }      return result; @@ -342,6 +419,7 @@ static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *expr,  static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, size_t index, GScanContext *ctx, GScanExpression **out)  {      bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours          */      size_t count;                           /* Quantité de correspondances */      const GScanMatch **matches;             /* Correspondances en place    */      const GScanBytesMatch *match;           /* Correspondance ciblée       */ @@ -353,18 +431,32 @@ static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, siz      const bin_t *data;                      /* Accès aux données brutes    */      sized_string_t binary;                  /* Conversion de formats       */ +    result = false; +      assert(g_scan_context_is_scan_done(ctx)); -    matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count); +    /* Identification du motif concerné */ -    result = (index < count); -    if (!result) goto done; +    for (i = 0; i < expr->count; i++) +    { +        matches = g_scan_context_get_full_matches(ctx, expr->patterns[i], &count); + +        if (index < count) +            break; +        else +            index -= count; + +    } + +    if (i == expr->count) goto done;      result = G_IS_SCAN_BYTES_MATCH(matches[index]);      if (!result) goto done;      match = G_SCAN_BYTES_MATCH(matches[index]); +    /* Traitement adapté de la requête */ +      len = g_scan_bytes_match_get_location(match, &start, &end);      switch (expr->type) @@ -376,7 +468,7 @@ static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, siz              data = g_binary_content_get_raw_access(content, &pos, len); -            binary.data = data; +            binary.static_bin_data = data;              binary.len = len;              *out = g_scan_literal_expression_new(LVT_STRING, &binary); diff --git a/src/analysis/scan/exprs/handler.h b/src/analysis/scan/exprs/handler.h index 8ad700a..36985e7 100644 --- a/src/analysis/scan/exprs/handler.h +++ b/src/analysis/scan/exprs/handler.h @@ -59,7 +59,10 @@ typedef enum _ScanHandlerType  GType g_scan_pattern_handler_get_type(void);  /* Met en place une manipulation de correspondances établies. */ -GScanExpression *g_scan_pattern_handler_new(GSearchPattern *, ScanHandlerType); +GScanExpression *g_scan_pattern_handler_new(GSearchPattern ** const, size_t, ScanHandlerType); + +/* Fournit la liste de toutes les correspondances représentées. */ +GScanMatch **g_scan_pattern_handler_get_all_matches(const GScanPatternHandler *, GScanContext *, size_t *); diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c index de7e32a..b1a094c 100644 --- a/src/analysis/scan/exprs/literal.c +++ b/src/analysis/scan/exprs/literal.c @@ -62,6 +62,9 @@ static bool g_scan_literal_expression_reduce_to_boolean(const GScanLiteralExpres  /* Dénombre les éléments portés par une expression. */  static bool g_scan_literal_expression_count(const GScanLiteralExpression *, GScanContext *, size_t *); +/* Fournit un élément donné issu d'un ensemble constitué. */ +static bool g_scan_literal_expression_get_item(const GScanLiteralExpression *, size_t, GScanContext *, GScanExpression **); +  /* ---------------------------------------------------------------------------------- */ @@ -100,6 +103,7 @@ static void g_scan_literal_expression_class_init(GScanLiteralExpressionClass *kl      expr->cmp_rich = (compare_expr_rich_fc)g_scan_literal_expression_compare_rich;      expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_literal_expression_reduce_to_boolean;      expr->count = (count_scan_expr_fc)g_scan_literal_expression_count; +    expr->get = (get_scan_expr_fc)g_scan_literal_expression_get_item;  } @@ -659,3 +663,51 @@ static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr,      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : expr  = expression à consulter.                              * +*                index = indice de l'élément à transférer.                    * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                out   = zone d'enregistrement de la réduction opérée. [OUT]  * +*                                                                             * +*  Description : Fournit un élément donné issu d'un ensemble constitué.       * +*                                                                             * +*  Retour      : Bilan de l'opération : false en cas d'erreur irrécupérable.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_literal_expression_get_item(const GScanLiteralExpression *expr, size_t index, GScanContext *ctx, GScanExpression **out) +{ +    bool result;                            /* Bilan à retourner           */ +    sized_string_t ch;                      /* Caractère extrait           */ + +    switch (expr->value_type) +    { +        case LVT_STRING: + +            result = (index < expr->value.string.len); + +            if (result) +            { +                ch.data = expr->value.string.data + index; +                ch.len = 1; + +                *out = g_scan_literal_expression_new(LVT_STRING, &ch); + +            } + +            break; + +        default: +            result = false; +            break; + +    } + +    return result; + +} diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y index 2863e21..36f6df9 100644 --- a/src/analysis/scan/grammar.y +++ b/src/analysis/scan/grammar.y @@ -1376,7 +1376,7 @@ relational_expr : cexpression "<" cexpression  { $$ = g_scan_relational_operatio                             $$ = NULL;                         else                         { -                           $$ = g_scan_pattern_handler_new(__pat, SHT_RAW); +                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_RAW);                             g_object_unref(G_OBJECT(__pat));                         }                     } @@ -1400,7 +1400,7 @@ relational_expr : cexpression "<" cexpression  { $$ = g_scan_relational_operatio                             $$ = NULL;                         else                         { -                           $$ = g_scan_pattern_handler_new(__pat, SHT_START); +                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_START);                             g_object_unref(G_OBJECT(__pat));                         }                     } @@ -1412,7 +1412,7 @@ relational_expr : cexpression "<" cexpression  { $$ = g_scan_relational_operatio                             $$ = NULL;                         else                         { -                           $$ = g_scan_pattern_handler_new(__pat, SHT_LENGTH); +                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_LENGTH);                             g_object_unref(G_OBJECT(__pat));                         }                     } @@ -1424,7 +1424,7 @@ relational_expr : cexpression "<" cexpression  { $$ = g_scan_relational_operatio                             $$ = NULL;                         else                         { -                           $$ = g_scan_pattern_handler_new(__pat, SHT_END); +                           $$ = g_scan_pattern_handler_new((GSearchPattern *[]) { __pat }, 1, SHT_END);                             g_object_unref(G_OBJECT(__pat));                         }                     } diff --git a/src/analysis/scan/items/Makefile.am b/src/analysis/scan/items/Makefile.am index 89ae41e..9263c7b 100644 --- a/src/analysis/scan/items/Makefile.am +++ b/src/analysis/scan/items/Makefile.am @@ -14,6 +14,8 @@ endif  libanalysisscanitems_la_SOURCES =			\  	count.h count.c							\  	datasize.h datasize.c					\ +	maxcommon.h maxcommon.c					\ +	modpath.h modpath.c						\  	uint-int.h								\  	uint.h uint.c diff --git a/src/analysis/scan/items/maxcommon.c b/src/analysis/scan/items/maxcommon.c new file mode 100644 index 0000000..a2e0f2a --- /dev/null +++ b/src/analysis/scan/items/maxcommon.c @@ -0,0 +1,366 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * maxcommon.c - détermination de la plus grand occurrence au sein d'un ensemble d'éléments + * + * Copyright (C) 2023 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 Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "maxcommon.h" + + +#include <assert.h> +#include <malloc.h> + + +#include "../item-int.h" +#include "../exprs/literal.h" +#include "../../../glibext/comparison-int.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des repérages de plus grande occurrence. */ +static void g_scan_maxcommon_function_class_init(GScanMaxcommonFunctionClass *); + +/* Initialise une instance de repérage d'occurrence maximake. */ +static void g_scan_maxcommon_function_init(GScanMaxcommonFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_maxcommon_function_dispose(GScanMaxcommonFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_maxcommon_function_finalize(GScanMaxcommonFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_maxcommon_function_get_name(const GScanMaxcommonFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_maxcommon_function_run_call(GScanMaxcommonFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un décompte d'élément le plus représenté dans une série. */ +G_DEFINE_TYPE(GScanMaxcommonFunction, g_scan_maxcommon_function, G_TYPE_SCAN_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des repérages de plus grande occurrence.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_maxcommon_function_class_init(GScanMaxcommonFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GScanRegisteredItemClass *registered;   /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_maxcommon_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_maxcommon_function_finalize; + +    registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_maxcommon_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_maxcommon_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de repérage d'occurrence maximake.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_maxcommon_function_init(GScanMaxcommonFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_maxcommon_function_dispose(GScanMaxcommonFunction *func) +{ +    G_OBJECT_CLASS(g_scan_maxcommon_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_maxcommon_function_finalize(GScanMaxcommonFunction *func) +{ +    G_OBJECT_CLASS(g_scan_maxcommon_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction de calcul de plus grande occurrence.  * +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanRegisteredItem *g_scan_maxcommon_function_new(void) +{ +    GScanRegisteredItem *result;            /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_MAXCOMMON_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_maxcommon_function_get_name(const GScanMaxcommonFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("maxcommon"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_maxcommon_function_run_call(GScanMaxcommonFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t used;                            /* Prochain emplacement libre  */ +    GScanExpression **collected;            /* Représentants de groupes    */ +    size_t *scores;                         /* Taille de ces groupes       */ +    size_t i;                               /* Boucle de parcours #1       */ +    size_t k;                               /* Boucle de parcours #2       */ +    bool status;                            /* Bilan de la comparaison     */ +    bool equal;                             /* Egalité établie ?           */ +    size_t arg0_count;                      /* Taille de l'argument unique */ +    GScanExpression *arg0_item;             /*  Elément de cet argument    */ +    size_t best;                            /* Meilleur score identifié    */ + +    result = (count > 0); +    if (!result) goto exit; + +    used = 0; + +    /* Si la série à étudier est directement fournie */ +    if (count > 1) +    { +        collected = malloc(count * sizeof(GScanExpression *)); +        scores = malloc(count * sizeof(size_t)); + +        for (i = 0; i < count; i++) +        { +            for (k = 0; k < used; k++) +            { +                status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(args[i]), +                                                        G_COMPARABLE_ITEM(collected[k]), +                                                        RCO_EQ, &equal); + +                if (status && equal) +                    break; + +            } + +            if (k < used) +                scores[k]++; + +            else +            { +                collected[used] = args[i]; +                g_object_ref(G_OBJECT(args[i])); +                scores[used] = 1; + +                used++; + +            } + +        } + +    } + +    /* Sinon on considère que l'arguement unique porte la liste (idéalement) */ +    else +    { +        if (G_IS_SCAN_LITERAL_EXPRESSION(args[0]) || !g_scan_expression_handle_set_features(args[0])) +        { +            best = 1; +            goto quick_unique; +        } + +#ifndef NDEBUG +        g_scan_expression_count_items(args[0], ctx, &arg0_count); +#else +        status = bool g_scan_expression_count_items(args[0], ctx, &arg0_count); +        assert(status); +#endif + +        collected = malloc(arg0_count * sizeof(GScanExpression *)); +        scores = malloc(arg0_count * sizeof(size_t)); + +        for (i = 0; i < arg0_count; i++) +        { +#ifndef NDEBUG +            g_scan_expression_get_item(args[0], i, ctx, &arg0_item); +#else +            status = g_scan_expression_get_item(args[0], i, ctx, &arg0_item); +            assert(status); +#endif + +            for (k = 0; k < used; k++) +            { +                status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(arg0_item), +                                                        G_COMPARABLE_ITEM(collected[k]), +                                                        RCO_EQ, &equal); + +                if (status && equal) +                    break; + +            } + +            if (k < used) +            { +                g_object_unref(G_OBJECT(arg0_item)); +                scores[k]++; +            } + +            else +            { +                collected[used] = arg0_item; +                scores[used] = 1; + +                used++; + +            } + +        } + +    } + +    /* Analyse des résultats */ + +    best = 0; + +    for (i = 0; i < used; i++) +        if (scores[i] > best) +            best = scores[i]; + +    for (i = 0; i < used; i++) +        g_object_unref(G_OBJECT(collected[i])); + +    free(collected); +    free(scores); + + quick_unique: + +    assert(best > 0); + +    *out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ best })); + + exit: + +    return result; + +} diff --git a/src/analysis/scan/items/maxcommon.h b/src/analysis/scan/items/maxcommon.h new file mode 100644 index 0000000..a834c00 --- /dev/null +++ b/src/analysis/scan/items/maxcommon.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * maxcommon.h - prototypes pour la détermination de la plus grand occurrence au sein d'un ensemble d'éléments + * + * Copyright (C) 2023 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 Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_ITEMS_MAXCOMMON_H +#define _ANALYSIS_SCAN_ITEMS_MAXCOMMON_H + + +#include <glib-object.h> + + +#include "../item.h" + + + +#define G_TYPE_SCAN_MAXCOMMON_FUNCTION            g_scan_maxcommon_function_get_type() +#define G_SCAN_MAXCOMMON_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MAXCOMMON_FUNCTION, GScanMaxcommonFunction)) +#define G_IS_SCAN_MAXCOMMON_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MAXCOMMON_FUNCTION)) +#define G_SCAN_MAXCOMMON_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MAXCOMMON_FUNCTION, GScanMaxcommonFunctionClass)) +#define G_IS_SCAN_MAXCOMMON_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MAXCOMMON_FUNCTION)) +#define G_SCAN_MAXCOMMON_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MAXCOMMON_FUNCTION, GScanMaxcommonFunctionClass)) + + +/* Détermination de la plus grand occurrence au sein d'un ensemble (instance) */ +typedef GScanRegisteredItem GScanMaxcommonFunction; + +/* Détermination de la plus grand occurrence au sein d'un ensemble (classe) */ +typedef GScanRegisteredItemClass GScanMaxcommonFunctionClass; + + +/* Indique le type défini pour un décompte d'élément le plus représenté dans une série. */ +GType g_scan_maxcommon_function_get_type(void); + +/* Constitue une fonction de calcul de plus grande occurrence. */ +GScanRegisteredItem *g_scan_maxcommon_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_MAXCOMMON_H */ diff --git a/src/analysis/scan/items/modpath.c b/src/analysis/scan/items/modpath.c new file mode 100644 index 0000000..2171bda --- /dev/null +++ b/src/analysis/scan/items/modpath.c @@ -0,0 +1,301 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * modpath.c - récupération des combinaisons de modification de motifs + * + * Copyright (C) 2023 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 Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "modpath.h" + + +#include "../item-int.h" + + +#include "../exprs/handler.h" +#include "../exprs/literal.h" +#include "../exprs/set.h" +#include "../matches/bytes.h" + + + +/* ---------------------- INTRODUCTION D'UNE NOUVELLE FONCTION ---------------------- */ + + +/* Initialise la classe des énumérations de formules de motifs. */ +static void g_scan_modpath_function_class_init(GScanModpathFunctionClass *); + +/* Initialise une instance d'énumération de formules de motifs. */ +static void g_scan_modpath_function_init(GScanModpathFunction *); + +/* Supprime toutes les références externes. */ +static void g_scan_modpath_function_dispose(GScanModpathFunction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_modpath_function_finalize(GScanModpathFunction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_scan_modpath_function_get_name(const GScanModpathFunction *); + +/* Réduit une expression à une forme plus simple. */ +static bool g_scan_modpath_function_run_call(GScanModpathFunction *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ---------------------------------------------------------------------------------- */ +/*                        INTRODUCTION D'UNE NOUVELLE FONCTION                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une énumération de formules créant des motifs. */ +G_DEFINE_TYPE(GScanModpathFunction, g_scan_modpath_function, G_TYPE_SCAN_REGISTERED_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des énumérations de formules de motifs. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_modpath_function_class_init(GScanModpathFunctionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GScanRegisteredItemClass *registered;   /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_modpath_function_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_modpath_function_finalize; + +    registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + +    registered->get_name = (get_registered_item_name_fc)g_scan_modpath_function_get_name; +    registered->run_call = (run_registered_item_call_fc)g_scan_modpath_function_run_call; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance d'énumération de formules de motifs. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_modpath_function_init(GScanModpathFunction *func) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_modpath_function_dispose(GScanModpathFunction *func) +{ +    G_OBJECT_CLASS(g_scan_modpath_function_parent_class)->dispose(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : func = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_modpath_function_finalize(GScanModpathFunction *func) +{ +    G_OBJECT_CLASS(g_scan_modpath_function_parent_class)->finalize(G_OBJECT(func)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Constitue une fonction d'énumération des formules de motifs. * +*                                                                             * +*  Retour      : Fonction mise en place.                                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanRegisteredItem *g_scan_modpath_function_new(void) +{ +    GScanRegisteredItem *result;            /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_MODPATH_FUNCTION, NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item = élément d'appel à consulter.                          * +*                                                                             * +*  Description : Indique le nom associé à une expression d'évaluation.        * +*                                                                             * +*  Retour      : Désignation humaine de l'expression d'évaluation.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_modpath_function_get_name(const GScanModpathFunction *item) +{ +    char *result;                           /* Désignation à retourner     */ + +    result = strdup("modpath"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item  = élément d'appel à consulter.                         * +*                args  = liste d'éventuels arguments fournis.                 * +*                count = taille de cette liste.                               * +*                ctx   = contexte de suivi de l'analyse courante.             * +*                scope = portée courante des variables locales.               * +*                out   = zone d'enregistrement de la résolution opérée. [OUT] * +*                                                                             * +*  Description : Réduit une expression à une forme plus simple.               * +*                                                                             * +*  Retour      : Réduction correspondante, expression déjà réduite, ou NULL.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_modpath_function_run_call(GScanModpathFunction *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours #1       */ +    size_t mcount;                          /* Quantité de correspondances */ +    GScanMatch **matches;                   /* Correspondances établies    */ +    size_t k;                               /* Boucle de parcours #2       */ +    sized_string_t path;                    /* Combinaison à conserver     */ +    GScanExpression *subitem;               /* Nouvel élément à transmettre*/ + +    /* Validation préalable du type des arguments */ + +    result = true; + +    for (i = 0; i < count && result; i++) +        result = G_IS_SCAN_PATTERN_HANDLER(args[i]); + +    if (!result) +        goto exit; + +    /* Construction des chemins attendus */ + +    *out = G_OBJECT(g_scan_generic_set_new()); + +    for (i = 0; i < count; i++) +    { +        matches = g_scan_pattern_handler_get_all_matches(G_SCAN_PATTERN_HANDLER(args[i]), ctx, &mcount); +        if (mcount == 0) continue; + +        /** +         * La série est à priori constituée d'éléments de même type, donc +         * un test unique suffit. +         */ +        if (!G_IS_SCAN_BYTES_MATCH(matches[0])) +        { +            for (k = 0; k < mcount; k++) +                g_object_unref(G_OBJECT(matches[k])); +        } + +        else +        { +            for (k = 0; k < mcount; k++) +            { +                path.data = g_scan_bytes_match_get_modifier_path(G_SCAN_BYTES_MATCH(matches[k])); +                if (path.data == NULL) continue; + +                path.len = strlen(path.data); + +                printf(" >> add '%s'\n", path.data); + +                subitem = g_scan_literal_expression_new(LVT_STRING, &path); + +                g_scan_generic_set_add_item(G_SCAN_GENERIC_SET(*out), subitem); + +                g_object_unref(G_OBJECT(subitem)); + +                exit_szstr(&path); + +                g_object_unref(G_OBJECT(matches[k])); + +            } + +        } + +        free(matches); + +    } + + exit: + +    return result; + +} diff --git a/src/analysis/scan/items/modpath.h b/src/analysis/scan/items/modpath.h new file mode 100644 index 0000000..3a78ef7 --- /dev/null +++ b/src/analysis/scan/items/modpath.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * modpath.h - prototypes pour la récupération des combinaisons de modification de motifs + * + * Copyright (C) 2023 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 Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_SCAN_ITEMS_MODPATH_H +#define _ANALYSIS_SCAN_ITEMS_MODPATH_H + + +#include <glib-object.h> + + +#include "../item.h" + + + +#define G_TYPE_SCAN_MODPATH_FUNCTION            g_scan_modpath_function_get_type() +#define G_SCAN_MODPATH_FUNCTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MODPATH_FUNCTION, GScanModpathFunction)) +#define G_IS_SCAN_MODPATH_FUNCTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MODPATH_FUNCTION)) +#define G_SCAN_MODPATH_FUNCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MODPATH_FUNCTION, GScanModpathFunctionClass)) +#define G_IS_SCAN_MODPATH_FUNCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MODPATH_FUNCTION)) +#define G_SCAN_MODPATH_FUNCTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MODPATH_FUNCTION, GScanModpathFunctionClass)) + + +/* Récupération de formules à l'origine de la construction de motifs (instance) */ +typedef GScanRegisteredItem GScanModpathFunction; + +/* Récupération de formules à l'origine de la construction de motifs (classe) */ +typedef GScanRegisteredItemClass GScanModpathFunctionClass; + + +/* Indique le type défini pour une énumération de formules créant des motifs. */ +GType g_scan_modpath_function_get_type(void); + +/* Constitue une fonction d'énumération des formules de motifs. */ +GScanRegisteredItem *g_scan_modpath_function_new(void); + + + +#endif  /* _ANALYSIS_SCAN_ITEMS_MODPATH_H */ diff --git a/src/analysis/scan/matches/bytes-int.h b/src/analysis/scan/matches/bytes-int.h index 6f7e60b..f57cb9f 100644 --- a/src/analysis/scan/matches/bytes-int.h +++ b/src/analysis/scan/matches/bytes-int.h @@ -42,6 +42,9 @@ struct _GScanBytesMatch      phys_t start;                           /* Début du motif représenté   */      phys_t len;                             /* Taille du motif représenté  */ +    size_t mod_path_index;                  /* Indice de construction      */ +    bool has_mod_path;                      /* Validité du champ précédent */ +  };  /* Correspondance trouvée avec une chaîne (classe) */ diff --git a/src/analysis/scan/matches/bytes.c b/src/analysis/scan/matches/bytes.c index de101c4..f0b97fe 100644 --- a/src/analysis/scan/matches/bytes.c +++ b/src/analysis/scan/matches/bytes.c @@ -30,6 +30,7 @@  #include "bytes-int.h" +#include "../patterns/token.h"  #include "../../../common/cpp.h"  #include "../../../core/logs.h" @@ -121,6 +122,8 @@ static void g_scan_bytes_match_init(GScanBytesMatch *match)      match->start = VMPA_NO_PHYSICAL;      match->len = VMPA_NO_PHYSICAL; +    match->has_mod_path = false; +  } @@ -285,6 +288,59 @@ phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *match, phys_t *sta  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : match = informations de correspondance à compléter.          * +*                index = indice de la combinaison de modificateurs ciblée.    * +*                                                                             * +*  Description : Mémorise l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_scan_bytes_match_remember_modifier_path(GScanBytesMatch *match, size_t index) +{ +    match->mod_path_index = index; +    match->has_mod_path = true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : match = informations de correspondance à consulter.          * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison gagnante.      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +char *g_scan_bytes_match_get_modifier_path(const GScanBytesMatch *match) +{ +    char *result;                           /* Combinaison à retourner     */ +    GBytesToken *pattern;                   /* Autre version du motif      */ + +    if (match->has_mod_path) +    { +        pattern = G_BYTES_TOKEN(G_SCAN_MATCH(match)->source); +        result = g_bytes_token_get_modifier_path(pattern, match->mod_path_index); +    } + +    else +        result = NULL; + +    return result; + +} + + +  /* ---------------------------------------------------------------------------------- */  /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */  /* ---------------------------------------------------------------------------------- */ diff --git a/src/analysis/scan/matches/bytes.h b/src/analysis/scan/matches/bytes.h index e599ee4..bd7425d 100644 --- a/src/analysis/scan/matches/bytes.h +++ b/src/analysis/scan/matches/bytes.h @@ -60,6 +60,12 @@ GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *);  /* Indique la localisation d'une correspondance établie. */  phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *, phys_t *, phys_t *); +/* Mémorise l'origine d'une correspondance à partir d'un indice. */ +void g_scan_bytes_match_remember_modifier_path(GScanBytesMatch *, size_t); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +char *g_scan_bytes_match_get_modifier_path(const GScanBytesMatch *); +  #endif  /* _ANALYSIS_SCAN_MATCHES_BYTES_H */ diff --git a/src/analysis/scan/matches/pending.c b/src/analysis/scan/matches/pending.c index 9ed4de3..57c63d7 100644 --- a/src/analysis/scan/matches/pending.c +++ b/src/analysis/scan/matches/pending.c @@ -48,10 +48,6 @@ static int compare_match_area(const match_area_t *, const match_area_t *); - - - -  /* ---------------------------------------------------------------------------------- */  /*                           MEMORISATION D'UNE ZONE BORNEE                           */  /* ---------------------------------------------------------------------------------- */ @@ -82,6 +78,12 @@ static int compare_match_area(const match_area_t *a, const match_area_t *b)      if (result == 0)          result = sort_unsigned_long_long(a->ttl, b->ttl); +    if (result == 0) +        result = sort_unsigned_long_long(a->has_mod_path, b->has_mod_path); + +    if (result == 0) +        result = sort_unsigned_long_long(a->mod_path_index, b->mod_path_index); +      return result;  } @@ -293,6 +295,51 @@ void add_pending_match(pending_matches_t *matches, phys_t start, phys_t length)      area->ttl = 1; +    area->has_mod_path = false; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : matches = suivi de correspondances à compléter.              * +*                start   = point de départ d'une nouvelle correspondance.     * +*                length  = taille de la zone couverte.                        * +*                index   = indice de construction pour le motif concerné.     * +*                                                                             * +*  Description : Ajoute au suivi la définition d'une nouvelle correspondance. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void add_pending_match_with_path(pending_matches_t *matches, phys_t start, phys_t length, size_t index) +{ +    match_area_t *area;                     /* Zone à initialiser          */ + +    if (matches->used == matches->allocated) +    { +        matches->allocated += PENDING_ALLOC_SIZE; + +        matches->areas = realloc(matches->areas, matches->allocated * sizeof(match_area_t)); + +    } + +    area = &matches->areas[matches->used++]; + +    area->start = start; +    area->end = start + length; + +    assert(matches->content_start <= area->start); +    assert(area->end <= matches->content_end); + +    area->ttl = 1; + +    area->mod_path_index = index; +    area->has_mod_path = true; +  } diff --git a/src/analysis/scan/matches/pending.h b/src/analysis/scan/matches/pending.h index 6df01c9..f4ac7a2 100644 --- a/src/analysis/scan/matches/pending.h +++ b/src/analysis/scan/matches/pending.h @@ -41,6 +41,9 @@ typedef struct _match_area_t      unsigned long ttl;                      /* Durée de vie pour analyse   */ +    size_t mod_path_index;                  /* Indice de construction      */ +    bool has_mod_path;                      /* Validité du champ précédent */ +  } match_area_t;  /* Suivi de correspondances */ @@ -86,6 +89,9 @@ match_area_t * const  *get_all_pending_matches(const pending_matches_t *, size_t  /*  Ajoute au suivi la définition d'une nouvelle correspondance. */  void add_pending_match(pending_matches_t *, phys_t, phys_t); +/* Ajoute au suivi la définition d'une nouvelle correspondance. */ +void add_pending_match_with_path(pending_matches_t *, phys_t, phys_t, size_t); +  /* Etend une zone couverte dans le suivi des correspondances. */  void extend_pending_match_beginning(pending_matches_t *, size_t, phys_t); diff --git a/src/analysis/scan/patterns/modifier-int.h b/src/analysis/scan/patterns/modifier-int.h index e1de2d8..c9b3a36 100644 --- a/src/analysis/scan/patterns/modifier-int.h +++ b/src/analysis/scan/patterns/modifier-int.h @@ -41,6 +41,9 @@ typedef bool (* can_token_modifier_handle_arg) (const GScanTokenModifier *, cons  /* Transforme une séquence d'octets pour motif de recherche. */  typedef bool (* transform_scan_token_with_fc) (const GScanTokenModifier *, const sized_binary_t *, size_t, const modifier_arg_t *, sized_binary_t **, size_t *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +typedef char * (* get_modifier_path) (const GScanTokenModifier *, size_t *); +  /* Transformation d'une séquence d'octets en une ou plusieurs autres formes (instance) */  struct _GScanTokenModifier @@ -59,6 +62,7 @@ struct _GScanTokenModifierClass      transform_scan_token_fc transform;      /* Opération de transformation */      can_token_modifier_handle_arg can_handle; /* Support d'argument donné  */      transform_scan_token_with_fc transform_with; /* Opération encadrée     */ +    get_modifier_path get_path;             /* Rappel d'une combinaison    */  }; diff --git a/src/analysis/scan/patterns/modifier.c b/src/analysis/scan/patterns/modifier.c index 65f671f..9efd404 100644 --- a/src/analysis/scan/patterns/modifier.c +++ b/src/analysis/scan/patterns/modifier.c @@ -249,3 +249,30 @@ bool g_scan_token_modifier_transform_with_arg(const GScanTokenModifier *modifier      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : modifier = modificateur à consulter.                         * +*                index    = indice de la combinaison ciblée. [OUT]            * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison.               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +char *g_scan_token_modifier_get_path(const GScanTokenModifier *modifier, size_t *index) +{ +    char *result;                           /* Combinaison à retourner     */ +    GScanTokenModifierClass *class;         /* Classe à activer            */ + +    class = G_SCAN_TOKEN_MODIFIER_GET_CLASS(modifier); + +    result = class->get_path(modifier, index); + +    return result; + +} diff --git a/src/analysis/scan/patterns/modifier.h b/src/analysis/scan/patterns/modifier.h index ce2589a..9030a72 100644 --- a/src/analysis/scan/patterns/modifier.h +++ b/src/analysis/scan/patterns/modifier.h @@ -65,6 +65,9 @@ bool g_scan_token_modifier_can_handle_arg(const GScanTokenModifier *, const modi  /* Transforme une séquence d'octets pour motif de recherche. */  bool g_scan_token_modifier_transform_with_arg(const GScanTokenModifier *, const sized_binary_t *, size_t, const modifier_arg_t *, sized_binary_t **, size_t *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +char *g_scan_token_modifier_get_path(const GScanTokenModifier *, size_t *); +  #endif  /* _ANALYSIS_SCAN_MODIFIER_H */ diff --git a/src/analysis/scan/patterns/modifiers/hex.c b/src/analysis/scan/patterns/modifiers/hex.c index 849d9ff..4a41c7d 100644 --- a/src/analysis/scan/patterns/modifiers/hex.c +++ b/src/analysis/scan/patterns/modifiers/hex.c @@ -58,6 +58,9 @@ static char *g_scan_hex_modifier_get_name(const GScanHexModifier *);  /* Transforme une séquence d'octets pour motif de recherche. */  static bool g_scan_hex_modifier_transform(const GScanHexModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_hex_modifier_get_path(const GScanHexModifier *, size_t *); +  /* ---------------------------------------------------------------------------------- */ @@ -96,6 +99,7 @@ static void g_scan_hex_modifier_class_init(GScanHexModifierClass *klass)      modifier->get_name = (get_scan_modifier_name_fc)g_scan_hex_modifier_get_name;      modifier->transform = (transform_scan_token_fc)g_scan_hex_modifier_transform; +    modifier->get_path = (get_modifier_path)g_scan_hex_modifier_get_path;  } @@ -259,3 +263,34 @@ static bool g_scan_hex_modifier_transform(const GScanHexModifier *modifier, cons      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : modifier = modificateur à consulter.                         * +*                index    = indice de la combinaison ciblée. [OUT]            * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison.               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_hex_modifier_get_path(const GScanHexModifier *modifier, size_t *index) +{ +    char *result;                           /* Combinaison à retourner     */ + +    if (*index > 0) +    { +        result = NULL; +        (*index)--; +    } + +    else +        result = strdup("hex"); + +    return result; + +} diff --git a/src/analysis/scan/patterns/modifiers/list.c b/src/analysis/scan/patterns/modifiers/list.c index 0390f47..040d2f8 100644 --- a/src/analysis/scan/patterns/modifiers/list.c +++ b/src/analysis/scan/patterns/modifiers/list.c @@ -58,6 +58,9 @@ static char *g_scan_modifier_list_get_name(const GScanModifierList *);  /* Transforme une séquence d'octets pour motif de recherche. */  static bool g_scan_modifier_list_transform(const GScanModifierList *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_modifier_list_get_path(const GScanModifierList *, size_t *); +  /* ---------------------------------------------------------------------------------- */ @@ -96,6 +99,7 @@ static void g_scan_modifier_list_class_init(GScanModifierListClass *klass)      modifier->get_name = (get_scan_modifier_name_fc)g_scan_modifier_list_get_name;      modifier->transform = (transform_scan_token_fc)g_scan_modifier_list_transform; +    modifier->get_path = (get_modifier_path)g_scan_modifier_list_get_path;  } @@ -404,3 +408,31 @@ static bool g_scan_modifier_list_transform(const GScanModifierList *modifier, co      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : modifier = modificateur à consulter.                         * +*                index    = indice de la combinaison ciblée. [OUT]            * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison.               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_modifier_list_get_path(const GScanModifierList *modifier, size_t *index) +{ +    char *result;                           /* Combinaison à retourner     */ +    size_t i;                               /* Boucle de parcours #1       */ + +    result = NULL; + +    for (i = 0; i < modifier->count && result == NULL; i++) +        result = g_scan_token_modifier_get_path(modifier->modifiers[i], index); + +    return result; + +} diff --git a/src/analysis/scan/patterns/modifiers/plain.c b/src/analysis/scan/patterns/modifiers/plain.c index 9ed0d7b..ad09129 100644 --- a/src/analysis/scan/patterns/modifiers/plain.c +++ b/src/analysis/scan/patterns/modifiers/plain.c @@ -58,6 +58,9 @@ static char *g_scan_plain_modifier_get_name(const GScanPlainModifier *);  /* Transforme une séquence d'octets pour motif de recherche. */  static bool g_scan_plain_modifier_transform(const GScanPlainModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_plain_modifier_get_path(const GScanPlainModifier *, size_t *); +  /* ---------------------------------------------------------------------------------- */ @@ -96,6 +99,7 @@ static void g_scan_plain_modifier_class_init(GScanPlainModifierClass *klass)      modifier->get_name = (get_scan_modifier_name_fc)g_scan_plain_modifier_get_name;      modifier->transform = (transform_scan_token_fc)g_scan_plain_modifier_transform; +    modifier->get_path = (get_modifier_path)g_scan_plain_modifier_get_path;  } @@ -252,3 +256,34 @@ static bool g_scan_plain_modifier_transform(const GScanPlainModifier *modifier,      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : modifier = modificateur à consulter.                         * +*                index    = indice de la combinaison ciblée. [OUT]            * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison.               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_plain_modifier_get_path(const GScanPlainModifier *modifier, size_t *index) +{ +    char *result;                           /* Combinaison à retourner     */ + +    if (*index > 0) +    { +        result = NULL; +        (*index)--; +    } + +    else +        result = strdup("plain"); + +    return result; + +} diff --git a/src/analysis/scan/patterns/modifiers/rev.c b/src/analysis/scan/patterns/modifiers/rev.c index 9d74afe..ef4d5fa 100644 --- a/src/analysis/scan/patterns/modifiers/rev.c +++ b/src/analysis/scan/patterns/modifiers/rev.c @@ -58,6 +58,9 @@ static char *g_scan_reverse_modifier_get_name(const GScanReverseModifier *);  /* Transforme une séquence d'octets pour motif de recherche. */  static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_reverse_modifier_get_path(const GScanReverseModifier *, size_t *); +  /* ---------------------------------------------------------------------------------- */ @@ -96,6 +99,7 @@ static void g_scan_reverse_modifier_class_init(GScanReverseModifierClass *klass)      modifier->get_name = (get_scan_modifier_name_fc)g_scan_reverse_modifier_get_name;      modifier->transform = (transform_scan_token_fc)g_scan_reverse_modifier_transform; +    modifier->get_path = (get_modifier_path)g_scan_reverse_modifier_get_path;  } @@ -254,3 +258,34 @@ static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *modifi      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : modifier = modificateur à consulter.                         * +*                index    = indice de la combinaison ciblée. [OUT]            * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison.               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_reverse_modifier_get_path(const GScanReverseModifier *modifier, size_t *index) +{ +    char *result;                           /* Combinaison à retourner     */ + +    if (*index > 0) +    { +        result = NULL; +        (*index)--; +    } + +    else +        result = strdup("rev"); + +    return result; + +} diff --git a/src/analysis/scan/patterns/modifiers/xor.c b/src/analysis/scan/patterns/modifiers/xor.c index 53d75a5..d932c82 100644 --- a/src/analysis/scan/patterns/modifiers/xor.c +++ b/src/analysis/scan/patterns/modifiers/xor.c @@ -27,6 +27,7 @@  #include <assert.h>  #include <malloc.h>  #include <stdint.h> +#include <stdio.h>  #include <string.h> @@ -66,6 +67,9 @@ static bool g_scan_xor_modifier_can_handle_arg(const GScanXorModifier *, const m  /* Transforme une séquence d'octets pour motif de recherche. */  static bool g_scan_xor_modifier_transform_with_arg(const GScanXorModifier *, const sized_binary_t *, size_t, const modifier_arg_t *, sized_binary_t **, size_t *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_xor_modifier_get_path(const GScanXorModifier *, size_t *); +  /* ---------------------------------------------------------------------------------- */ @@ -106,6 +110,7 @@ static void g_scan_xor_modifier_class_init(GScanXorModifierClass *klass)      modifier->transform = (transform_scan_token_fc)g_scan_xor_modifier_transform;      modifier->can_handle = (can_token_modifier_handle_arg)g_scan_xor_modifier_can_handle_arg;      modifier->transform_with = (transform_scan_token_with_fc)g_scan_xor_modifier_transform_with_arg; +    modifier->get_path = (get_modifier_path)g_scan_xor_modifier_get_path;  } @@ -393,3 +398,41 @@ static bool g_scan_xor_modifier_transform_with_arg(const GScanXorModifier *modif      return result;  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : modifier = modificateur à consulter.                         * +*                index    = indice de la combinaison ciblée. [OUT]            * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison.               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static char *g_scan_xor_modifier_get_path(const GScanXorModifier *modifier, size_t *index) +{ +    char *result;                           /* Combinaison à retourner     */ +    int ret;                                /* Bilan intermédiaire         */ + +    if (*index > 255) +    { +        result = NULL; +        (*index) -= 256; +    } + +    else +    { +        ret = asprintf(&result, "xor(0x%02hhx)", (unsigned char)*index); + +        if (ret == -1) +            result = strdup("xor(0x?)"); + +    } + +    return result; + +} diff --git a/src/analysis/scan/patterns/token.c b/src/analysis/scan/patterns/token.c index 8b3a843..030e4a1 100644 --- a/src/analysis/scan/patterns/token.c +++ b/src/analysis/scan/patterns/token.c @@ -30,6 +30,7 @@  #include "token-int.h" +#include "tokens/nodes/plain.h"  #include "../../../common/cpp.h"  #include "../../../core/logs.h" @@ -342,6 +343,33 @@ void g_bytes_token_check(const GBytesToken *token, GScanContext *context, GBinCo  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : token   = définition de la bribe à consulter.                * +*                index = indice de la combinaison de modificateurs ciblée.    * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison gagnante.      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +char *g_bytes_token_get_modifier_path(const GBytesToken *token, size_t index) +{ +    char *result;                           /* Combinaison à retourner     */ + +    if (G_IS_SCAN_TOKEN_NODE_PLAIN(token->root)) +        result = g_scan_token_node_plain_get_modifier_path(G_SCAN_TOKEN_NODE_PLAIN(token->root), index); +    else +        result = NULL; + +    return result; + +} + +  /* ---------------------------------------------------------------------------------- */  /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ diff --git a/src/analysis/scan/patterns/token.h b/src/analysis/scan/patterns/token.h index a71e367..2816bf8 100644 --- a/src/analysis/scan/patterns/token.h +++ b/src/analysis/scan/patterns/token.h @@ -64,6 +64,9 @@ bool g_bytes_token_enroll(GBytesToken *, GScanContext *, GEngineBackend *, size_  /* Transforme les correspondances locales en trouvailles. */  void g_bytes_token_check(const GBytesToken *, GScanContext *, GBinContent *, pending_matches_t *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +char *g_bytes_token_get_modifier_path(const GBytesToken *, size_t); +  #endif  /* _ANALYSIS_SCAN_PATTERNS_TOKEN_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.c b/src/analysis/scan/patterns/tokens/nodes/plain.c index 5d89cf8..7309574 100644 --- a/src/analysis/scan/patterns/tokens/nodes/plain.c +++ b/src/analysis/scan/patterns/tokens/nodes/plain.c @@ -277,6 +277,35 @@ ScanPlainNodeFlags g_scan_token_node_plain_get_flags(const GScanTokenNodePlain *  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : node  = définition de la bribe à consulter.                  * +*                index = indice de la combinaison de modificateurs ciblée.    * +*                                                                             * +*  Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +*                                                                             * +*  Retour      : Version humainement lisible de la combinaison.               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +char *g_scan_token_node_plain_get_modifier_path(const GScanTokenNodePlain *node, size_t index) +{ +    char *result;                           /* Combinaison à retourner     */ + +    if (node->modifier == NULL) +        result = strdup("plain"); + +    else +        result = g_scan_token_modifier_get_path(node->modifier, (size_t []){ index }); + +    return result; + + +} + +  /* ---------------------------------------------------------------------------------- */  /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ @@ -511,6 +540,7 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const  static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)  {      bool initialized;                       /* Initialisation du suivi ?   */ +    bool track_path;                        /* Conservation du chemin      */      bool nocase;                            /* Pas d'intérêt pour la casse */      size_t ocount;                          /* Quantité de bornes présentes*/      size_t i;                               /* Boucle de parcours #1       */ @@ -531,6 +561,10 @@ static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *nod      initialized = are_pending_matches_initialized(matches); +    track_path = (G_SCAN_TOKEN_NODE(node)->flags & STNF_MAIN); + +    assert((track_path && !initialized) || !track_path); +      nocase = (node->flags & SPNF_CASE_INSENSITIVE);      get_node_search_offset_ranges(offset, &ocount); @@ -568,12 +602,18 @@ static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *nod                  status = check_scan_token_node_plain_content(raw, atom, nocase, new_begin, content);                  if ((status && !not) || (!status && not)) +                {                      /**                       * Il ne peut y avoir qu'une seule séquence d'octets à un même                       * emplacement, donc le couple (new_begin, len) enregistré est                       * unique.                       */ -                    add_pending_match(matches, new_begin, raw->len); +                    if (track_path) +                        add_pending_match_with_path(matches, new_begin, raw->len, i); +                    else +                        add_pending_match(matches, new_begin, raw->len); + +                }              } diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.h b/src/analysis/scan/patterns/tokens/nodes/plain.h index c8f3920..abf71de 100644 --- a/src/analysis/scan/patterns/tokens/nodes/plain.h +++ b/src/analysis/scan/patterns/tokens/nodes/plain.h @@ -75,6 +75,9 @@ GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *, GScanTokenMo  /* Indique les propriétés particulières d'un noeud de texte. */  ScanPlainNodeFlags g_scan_token_node_plain_get_flags(const GScanTokenNodePlain *); +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +char *g_scan_token_node_plain_get_modifier_path(const GScanTokenNodePlain *, size_t); +  #endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_H */ diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c index 77a05b4..5826db9 100644 --- a/src/analysis/scan/rule.c +++ b/src/analysis/scan/rule.c @@ -623,6 +623,9 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c              match = g_scan_bytes_match_new(G_SEARCH_PATTERN(pattern), content,                                             area->start, area->end - area->start); +            if (area->has_mod_path) +                g_scan_bytes_match_remember_modifier_path(G_SCAN_BYTES_MATCH(match), area->mod_path_index); +              g_scan_context_register_full_match(context, match);              g_object_unref(G_OBJECT(match)); | 
