diff options
Diffstat (limited to 'src/analysis/scan/patterns/tokens')
35 files changed, 4252 insertions, 756 deletions
| diff --git a/src/analysis/scan/patterns/tokens/Makefile.am b/src/analysis/scan/patterns/tokens/Makefile.am index 7fb515f..f0ab3d5 100644 --- a/src/analysis/scan/patterns/tokens/Makefile.am +++ b/src/analysis/scan/patterns/tokens/Makefile.am @@ -8,6 +8,7 @@ libanalysisscanpatternstokens_la_SOURCES =	\  	hex.h hex.c								\  	node-int.h								\  	node.h node.c							\ +	offset.h offset.c						\  	plain-int.h								\  	plain.h plain.c diff --git a/src/analysis/scan/patterns/tokens/atom.c b/src/analysis/scan/patterns/tokens/atom.c index fcb585d..52f239c 100644 --- a/src/analysis/scan/patterns/tokens/atom.c +++ b/src/analysis/scan/patterns/tokens/atom.c @@ -251,6 +251,7 @@ void find_best_atom(const sized_binary_t *raw, size_t maxsize, tracked_scan_atom  /******************************************************************************  *                                                                             *  *  Paramètres  : src   = chaîne ed référence à dupliquer.                     * +*                atom  = préselection opérée en amont.                        *  *                count = nombre de lettres présentes.                         *  *                                                                             *  *  Description : Etablit la liste des cas de figures ignorant la casse.       * @@ -261,7 +262,7 @@ void find_best_atom(const sized_binary_t *raw, size_t maxsize, tracked_scan_atom  *                                                                             *  ******************************************************************************/ -sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, size_t count) +sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, const tracked_scan_atom_t *atom, size_t count)  {      sized_binary_t *result;                 /* Liste à retourner           */      size_t i;                               /* Boucle de parcours #1       */ @@ -274,16 +275,20 @@ sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, size_t co      size_t divisor;                         /* Taille de la découpe        */      size_t quotient;                        /* Reste de la position        */ -    count *= 2; -      /* Création du réceptacle */      result = malloc(count * sizeof(tracked_scan_atom_t)); +    assert(src->len == (atom->pos + atom->len + atom->rem)); +      for (i = 0; i < count; i++)      {          result[i].data = malloc(src->len);          result[i].len = src->len; + +        memcpy(result[i].data, src->data, atom->pos); +        memcpy(&result[i].data[atom->pos + atom->len], &src->data[atom->pos + atom->len], atom->rem); +      }      /* Remplissage */ @@ -294,7 +299,7 @@ sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, size_t co      check = 1;  #endif -    for (i = 0; i < src->len; i++) +    for (i = atom->pos; i < (atom->pos + atom->len); i++)      {          ch = src->data[i]; @@ -315,8 +320,8 @@ sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, size_t co              replaced *= 2;  #ifndef NDEBUG -            check++; -            assert((check - 1) <= count); +            check *= 2; +            assert(check <= count);  #endif          } @@ -326,7 +331,51 @@ sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, size_t co      } -    assert((check - 1) == count); +    assert(check == count); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : byte     = octet partiel à interpréter.                      * +*                mask     = valeur du masque à appliquer.                     * +*                produced = nombre de contenus générés. [OUT]                 * +*                                                                             * +*  Description : Etablit la liste des cas de figures avec un octet partiel.   * +*                                                                             * +*  Retour      : Liste de toutes les combinaisons possibles.                  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +sized_binary_t *make_atoms_from_masked_byte(bin_t value, bin_t mask, size_t *produced) +{ +    sized_binary_t *result;                 /* Liste à retourner           */ +    size_t i;                               /* Boucle de parcours #1       */ + +    *produced = 16; + +    /* Création du réceptacle */ + +    result = malloc(16 * sizeof(tracked_scan_atom_t)); + +    /* Remplissage */ + +    for (i = 0; i < 16; i++) +    { +        result[i].data = malloc(1); +        result[i].len = 1; + +        if (mask == 0x0f) +            result[i].data[0] = value | (i << 4); +        else +            result[i].data[0] = value | i; + +    }      return result; diff --git a/src/analysis/scan/patterns/tokens/atom.h b/src/analysis/scan/patterns/tokens/atom.h index daa1f16..2fbc19e 100644 --- a/src/analysis/scan/patterns/tokens/atom.h +++ b/src/analysis/scan/patterns/tokens/atom.h @@ -58,7 +58,10 @@ int finish_quality_rating(const bitfield_t *, size_t);  void find_best_atom(const sized_binary_t *, size_t , tracked_scan_atom_t *, size_t *);  /* Etablit la liste des cas de figures ignorant la casse. */ -sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *, size_t); +sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *, const tracked_scan_atom_t *, size_t); + +/* Etablit la liste des cas de figures avec un octet partiel. */ +sized_binary_t *make_atoms_from_masked_byte(bin_t, bin_t, size_t *);  /* Enregistre l'atome déterminé d'une série d'octets. */  bool enroll_prepared_atom(const sized_binary_t *, GScanContext *, GEngineBackend *, tracked_scan_atom_t *); diff --git a/src/analysis/scan/patterns/tokens/hex-int.h b/src/analysis/scan/patterns/tokens/hex-int.h index f0460c8..440f693 100644 --- a/src/analysis/scan/patterns/tokens/hex-int.h +++ b/src/analysis/scan/patterns/tokens/hex-int.h @@ -49,7 +49,7 @@ struct _GScanHexBytesClass  /* Met en place un gestionnaire de recherche de binaire. */ -bool g_scan_hex_bytes_create(GScanHexBytes *, GScanTokenNode *); +bool g_scan_hex_bytes_create(GScanHexBytes *, GScanTokenNode *, bool); diff --git a/src/analysis/scan/patterns/tokens/hex.c b/src/analysis/scan/patterns/tokens/hex.c index c1cdbdf..1fda597 100644 --- a/src/analysis/scan/patterns/tokens/hex.c +++ b/src/analysis/scan/patterns/tokens/hex.c @@ -58,12 +58,6 @@ static void g_scan_hex_bytes_output_to_text(const GScanHexBytes *, GScanContext  /* Affiche un motif de recherche au format JSON. */  static void g_scan_hex_bytes_output_to_json(const GScanHexBytes *, GScanContext *, const sized_string_t *, unsigned int, int); -/* Inscrit la définition d'un motif dans un moteur de recherche. */ -//static bool g_scan_hex_bytes_enroll(GScanHexBytes *, GScanContext *, GEngineBackend *, size_t); - -/* Transforme les correspondances locales en trouvailles. */ -//static void g_scan_hex_bytes_check(const GScanHexBytes *, GScanContext *, GBinContent *, pending_matches_t *); -  /* ---------------------------------------------------------------------------------- */ @@ -91,7 +85,6 @@ static void g_scan_hex_bytes_class_init(GScanHexBytesClass *klass)  {      GObjectClass *object;                   /* Autre version de la classe  */      GSearchPatternClass *pattern;           /* Version de classe ancêtre   */ -    GStringTokenClass *token;               /* Version de classe parente   */      object = G_OBJECT_CLASS(klass); @@ -103,11 +96,6 @@ static void g_scan_hex_bytes_class_init(GScanHexBytesClass *klass)      pattern->to_text = (output_pattern_to_text_fc)g_scan_hex_bytes_output_to_text;      pattern->to_json = (output_pattern_to_json_fc)g_scan_hex_bytes_output_to_json; -    token = G_STRING_TOKEN_CLASS(klass); - -    //token->enroll = (enroll_token_fc)g_scan_hex_bytes_enroll; -    //token->check = (check_token_fc)g_scan_hex_bytes_check; -  } @@ -170,6 +158,7 @@ static void g_scan_hex_bytes_finalize(GScanHexBytes *bytes)  /******************************************************************************  *                                                                             *  *  Paramètres  : root  = représentation du motif à recherche.                 * +*                private  = donne une vocation privée au motif de recherche.  *  *                                                                             *  *  Description : Construit un gestionnaire de recherche de texte brut.        *  *                                                                             * @@ -179,13 +168,13 @@ static void g_scan_hex_bytes_finalize(GScanHexBytes *bytes)  *                                                                             *  ******************************************************************************/ -GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *root) +GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *root, bool private)  {      GSearchPattern *result;                 /* Structure à retourner       */      result = g_object_new(G_TYPE_SCAN_HEX_BYTES, NULL); -    if (!g_scan_hex_bytes_create(G_SCAN_HEX_BYTES(result), root)) +    if (!g_scan_hex_bytes_create(G_SCAN_HEX_BYTES(result), root, private))          g_clear_object(&result);      return result; @@ -197,6 +186,7 @@ GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *root)  *                                                                             *  *  Paramètres  : bytes = encadrement de motif à initialiser pleinement.       *  *                root  = représentation du motif à recherche.                 * +*                private  = donne une vocation privée au motif de recherche.  *  *                                                                             *  *  Description : Met en place un gestionnaire de recherche de binaire.        *  *                                                                             * @@ -206,11 +196,11 @@ GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *root)  *                                                                             *  ******************************************************************************/ -bool g_scan_hex_bytes_create(GScanHexBytes *bytes, GScanTokenNode *root) +bool g_scan_hex_bytes_create(GScanHexBytes *bytes, GScanTokenNode *root, bool private)  {      bool result;                            /* Bilan à retourner           */ -    result = g_string_token_create(G_STRING_TOKEN(bytes), root); +    result = g_string_token_create(G_STRING_TOKEN(bytes), root, false, private);      return result; @@ -267,191 +257,3 @@ static void g_scan_hex_bytes_output_to_json(const GScanHexBytes *pattern, GScanC      /* TODO */  } - -#if 0 - -/****************************************************************************** -*                                                                             * -*  Paramètres  : bytes   = définition de la bribe à enregistrer.              * -*                context = contexte de l'analyse à mener.                     * -*                backend = moteur de recherche à préchauffer.                 * -*                maxsize = taille max. des atomes (mise en commun optimisée). * -*                                                                             * -*  Description : Inscrit la définition d'un motif dans un moteur de recherche.* -*                                                                             * -*  Retour      : Bilan de l'opération à renvoyer.                             * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_scan_hex_bytes_enroll(GScanHexBytes *bytes, GScanContext *context, GEngineBackend *backend, size_t maxsize) -{ -    bool result;                            /* Statut à retourner          */ -    size_t i;                               /* Boucle de parcours #1       */ -    tracked_scan_atom_t atom;               /* Atome identifié             */ -    size_t letters;                         /* Nombre de lettres présentes */ -    size_t k;                               /* Boucle de parcours #2       */ -    size_t extra_count;                     /* Quantité pour l'exhaustivité*/ -    sized_binary_t *extra;                  /* Couverture supplémntaire    */ -    size_t remaining;                       /* Quantité restant à traiter  */ - -    /* Génération d'une base de chaînes à couvrir */ - -    if (bytes->modifier == NULL) -    { -        bytes->raw = malloc(sizeof(sized_binary_t)); -        bytes->count = 1; - -        szstrdup(&bytes[0].raw[0], &bytes->orig); - -        result = true; - -    } -    else -        result = g_scan_token_modifier_transform(bytes->modifier, &bytes->orig, &bytes->raw, &bytes->count); - -    if (!result) -        goto exit; - -    /* Préparation pour la mémorisation des atomes */ - -    bytes->atoms = malloc(bytes->count * sizeof(tracked_scan_atom_t)); - -    /* Recherche des atomes */ - -    for (i = 0; i < bytes->count; i++) -    { -        if (bytes->flags & SPBF_CASE_INSENSITIVE) -        { -            find_best_atom(&bytes->raw[i], maxsize, &atom, &letters); - -            if (letters == 0) -                bytes->atoms[i] = atom; - -            /* Insertion des combinaisons pour couvrir toutes les casses */ -            else -            { -                for (k = 0, extra_count = 1; k < letters; k++, extra_count *= 2) -                    ; - -                extra = make_atoms_case_insensitive(&bytes->raw[i], extra_count); - -                remaining = bytes->count - i - 1; - -                bytes->count += (extra_count - 1); - -                bytes->raw = realloc(bytes->raw, bytes->count * sizeof(sized_binary_t)); - -                memmove(&bytes->raw[i + extra_count], &bytes->raw[i + 1], remaining * sizeof(sized_binary_t)); - -                for (k = 0; k < extra_count; k++) -                    bytes->raw[i + k] = extra[k]; - -                free(extra); - -                bytes->atoms = realloc(bytes->raw, bytes->count * sizeof(tracked_scan_atom_t)); - -                for (k = 0; k < extra_count; k++) -                    bytes->atoms[i + k] = atom; - -                i += extra_count - 1; - -            } - -        } - -        else -            find_best_atom(&bytes->raw[i], maxsize, &bytes->atoms[i], &letters); - -    } - -    /* Enregistrements en masse */ - - -    for (i = 0; i < bytes->count && result; i++) -        result = enroll_prepared_atom(&bytes->raw[i], context, backend, &bytes->atoms[i]); - - exit: - -    return result; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : bytes   = définition de la bribe à manipuler.                * -*                context = contexte de l'analyse à mener.                     * -*                content = accès au contenu brut pour vérifications (optim.)  * -*                matches = suivi des correspondances à consolider.            * -*                                                                             * -*  Description : Transforme les correspondances locales en trouvailles.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_scan_hex_bytes_check(const GScanHexBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches) -{ -    size_t i;                               /* Boucle de parcours #1       */ -    const sized_binary_t *raw;              /* Données brutes d'origine    */ -    const tracked_scan_atom_t *atom;        /* Atome correspondant         */ -    size_t count;                           /* Quantité de bribes trouvées */ -    const phys_t *found;                    /* Localisations des bribes    */ -    size_t k;                               /* Boucle de parcours #2       */ -    phys_t start;                           /* Point de départ             */ -    vmpa2t pos;                             /* Position dans les données   */ -    const bin_t *ptr;                       /* Accès aux données brutes    */ -    int ret;                                /* Bilan d'une comparaison     */ - -    for (i = 0; i < bytes->count; i++) -    { -        raw = &bytes->raw[i]; -        atom = &bytes->atoms[i]; - -        found = g_scan_context_get_atom_matches(context, atom->pid, &count); - -        for (k = 0; k < count; k++) -        { -            start = found[k] - atom->pos; - -            init_vmpa(&pos, start, VMPA_NO_VIRTUAL); - -            /* Validation du contenu avant l'atome */ - -            if (atom->pos > 0) -            { -                ptr = g_binary_content_get_raw_access(content, &pos, atom->pos); - -                ret = memcmp(raw->data, ptr, atom->pos); -                if (ret != 0) continue; - -            } - -            /* Validation du contenu après l'atome */ - -            if (atom->rem > 0) -            { -                advance_vmpa(&pos, atom->len); - -                ptr = g_binary_content_get_raw_access(content, &pos, atom->rem); - -                ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem); -                if (ret != 0) continue; - -            } - -            /* Mémorisation de la correspondance */ - -            add_pending_matches(matches, start, raw->len); - -        } - -    } - -} - -#endif diff --git a/src/analysis/scan/patterns/tokens/hex.h b/src/analysis/scan/patterns/tokens/hex.h index 1db8eb6..fe5268c 100644 --- a/src/analysis/scan/patterns/tokens/hex.h +++ b/src/analysis/scan/patterns/tokens/hex.h @@ -52,7 +52,7 @@ typedef struct _GScanHexBytesClass GScanHexBytesClass;  GType g_scan_hex_bytes_get_type(void);  /* Construit un gestionnaire de recherche de texte brut. */ -GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *); +GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *, bool); diff --git a/src/analysis/scan/patterns/tokens/node-int.h b/src/analysis/scan/patterns/tokens/node-int.h index c543cbf..091a5be 100644 --- a/src/analysis/scan/patterns/tokens/node-int.h +++ b/src/analysis/scan/patterns/tokens/node-int.h @@ -28,12 +28,33 @@  #include "node.h" +#include "offset.h" + + + +/* Prend acte d'une nouvelle propriété pour le noeud. */ +typedef void (* apply_scan_token_node_flags_fc) (GScanTokenNode *, ScanTokenNodeFlags); + +/* Noeuds clefs de l'arborescence mise en place */ +typedef struct _scan_tree_points_t +{ +    GScanTokenNode *first_node;             /* Premier noeud de traitement */ +    GScanTokenNode *last_node;              /* Dernier noeud de traitement */ + +    GScanTokenNode *first_plain;            /* Premier noeud textuel       */ +    GScanTokenNode *best_masked;            /* Noeud masqué le plus long   */ + +} scan_tree_points_t; + + +/* Parcourt une arborescence de noeuds et y relève des éléments. */ +typedef void (* visit_scan_token_node_fc) (GScanTokenNode *, scan_tree_points_t *);  /* Inscrit la définition d'un motif dans un moteur de recherche. */ -typedef bool (* enroll_scan_token_node_fc) (GScanTokenNode *, GScanContext *, GEngineBackend *, size_t); +typedef bool (* enroll_scan_token_node_fc) (GScanTokenNode *, GScanContext *, GEngineBackend *, size_t, size_t *);  /* Transforme les correspondances locales en trouvailles. */ -typedef void (* check_scan_token_node_fc) (const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, const node_search_offset_t *); +typedef void (* check_scan_token_node_fc) (const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);  /* Décomposition d'un motif de recherche en atomes (instance) */ @@ -41,6 +62,8 @@ struct _GScanTokenNode  {      GObject parent;                         /* A laisser en premier        */ +    ScanTokenNodeFlags flags;               /* Propriétés particulières    */ +  };  /* Décomposition d'un motif de recherche en atomes (classe) */ @@ -48,11 +71,29 @@ struct _GScanTokenNodeClass  {      GObjectClass parent;                    /* A laisser en premier        */ +    apply_scan_token_node_flags_fc apply;   /* Prise en compte de fanions  */ + +    visit_scan_token_node_fc visit;         /* Phase de répérage initial   */      enroll_scan_token_node_fc enroll;       /* Inscription d'un motif      */ -    check_scan_token_node_fc check;         /* Conversion en trouvailles   */ + +    check_scan_token_node_fc check_forward; /* Conversion en trouvailles   */ +    check_scan_token_node_fc check_backward;/* Conversion en trouvailles   */  }; +/* Parcourt une arborescence de noeuds et y relève des éléments. */ +void g_scan_token_node_visit(GScanTokenNode *, scan_tree_points_t *); + +/* Inscrit la définition d'un motif dans un moteur de recherche. */ +bool _g_scan_token_node_enroll(GScanTokenNode *, GScanContext *, GEngineBackend *, size_t, size_t *); + +/* Transforme les correspondances locales en trouvailles. */ +void _g_scan_token_node_check_forward(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + +/* Transforme les correspondances locales en trouvailles. */ +void _g_scan_token_node_check_backward(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + +  #endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_INT_H */ diff --git a/src/analysis/scan/patterns/tokens/node.c b/src/analysis/scan/patterns/tokens/node.c index 224328a..1354fff 100644 --- a/src/analysis/scan/patterns/tokens/node.c +++ b/src/analysis/scan/patterns/tokens/node.c @@ -28,6 +28,7 @@  #include "node-int.h" +#include "nodes/any.h" @@ -35,7 +36,7 @@  /* Initialise la classe des éléments de décomposition. */ -static void g_scan_token_node_class_init(GScanTokenNodeClass *klass); +static void g_scan_token_node_class_init(GScanTokenNodeClass *);  /* Initialise une instance d'élément décomposant un motif. */  static void g_scan_token_node_init(GScanTokenNode *); @@ -95,6 +96,7 @@ static void g_scan_token_node_class_init(GScanTokenNodeClass *klass)  static void g_scan_token_node_init(GScanTokenNode *node)  { +    node->flags = STNF_NONE;  } @@ -139,10 +141,148 @@ static void g_scan_token_node_finalize(GScanTokenNode *node)  /******************************************************************************  *                                                                             * +*  Paramètres  : node = noeud de motif à consulter.                           * +*                                                                             * +*  Description : Indique les propriétés particulières d'un noeud d'analyse.   * +*                                                                             * +*  Retour      : Propriétés particulières associées au noeud.                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +ScanTokenNodeFlags g_scan_token_node_get_flags(const GScanTokenNode *node) +{ +    ScanTokenNodeFlags result;              /* Statut à retourner          */ + +    result = node->flags; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node  = noeud de motif à mettre à jour.                      * +*                flags = propriétés particulières à associer au noeud.        * +*                                                                             * +*  Description : Marque le noeud avec des propriétés particulières.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_scan_token_node_set_flags(GScanTokenNode *node, ScanTokenNodeFlags flags) +{ +    GScanTokenNodeClass *class;             /* Classe de l'instance        */ + +    node->flags |= flags; + +    class = G_SCAN_TOKEN_NODE_GET_CLASS(node); + +    if (class->apply != NULL) +        class->apply(node, flags); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node   = point de départ du parcours à effectuer.            * +*                points = points capitaux de l'arborescence. [OUT]            * +*                                                                             * +*  Description : Parcourt une arborescence de noeuds et y relève des éléments.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_scan_token_node_visit(GScanTokenNode *node, scan_tree_points_t *points) +{ +    GScanTokenNodeClass *class;             /* Classe de l'instance        */ + +    if (node->flags & STNF_PROD) +    { +        if (points->first_node == NULL) +            points->first_node = node; + +        points->last_node = node; + +    } + +    class = G_SCAN_TOKEN_NODE_GET_CLASS(node); + +    if (class->visit != NULL) +        class->visit(node, points); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node   = point de départ du parcours à préparer.             * +*                                                                             * +*  Description : Détermine et prépare les éléments clefs d'une arborescence.  * +*                                                                             * +*  Retour      : true si une analyse à rebourd complémentaire est requise.    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_token_node_setup_tree(GScanTokenNode *node) +{ +    bool result;                            /* Prévision à retourner       */ +    scan_tree_points_t points;              /* Repérage de points capitaux */ +    GScanTokenNode *main;                   /* Principal noeud d'opération */ + +    /* Phase de localisation */ + +    points.first_node = NULL; +    points.last_node = NULL; + +    points.first_plain = NULL; +    points.best_masked = NULL; + +    g_scan_token_node_visit(node, &points); + +    /* Phase d'application */ + +    //g_scan_token_node_set_flags(points.first_node, STNF_FIRST); +    //g_scan_token_node_set_flags(points.last_node, STNF_LAST); + +    if (points.first_plain != NULL) +        main = points.first_plain; + +    else if (points.best_masked != NULL) +        main = points.best_masked; + +    else +        main = node;//points.first_node; + +    g_scan_token_node_set_flags(main, STNF_MAIN); + +    printf("main : %p (%s)\n", main, G_OBJECT_TYPE_NAME(main)); + +    result = (main != node/*points.first_node*/); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : node    = définition de la bribe à enregistrer.              *  *                context = contexte de l'analyse à mener.                     *  *                backend = moteur de recherche à préchauffer.                 *  *                maxsize = taille max. des atomes (mise en commun optimisée). * +*                slow    = niveau de ralentissement induit (0 = idéal). [OUT] *  *                                                                             *  *  Description : Inscrit la définition d'un motif dans un moteur de recherche.*  *                                                                             * @@ -152,16 +292,45 @@ static void g_scan_token_node_finalize(GScanTokenNode *node)  *                                                                             *  ******************************************************************************/ -bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngineBackend *backend, size_t maxsize) +bool _g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)  {      bool result;                            /* Statut à retourner          */      GScanTokenNodeClass *class;             /* Classe de l'instance        */ +    class = G_SCAN_TOKEN_NODE_GET_CLASS(node); + +    result = class->enroll(node, context, backend, maxsize, slow); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à enregistrer.              * +*                context = contexte de l'analyse à mener.                     * +*                backend = moteur de recherche à préchauffer.                 * +*                maxsize = taille max. des atomes (mise en commun optimisée). * +*                slow    = niveau de ralentissement induit (0 = idéal). [OUT] * +*                                                                             * +*  Description : Inscrit la définition d'un motif dans un moteur de recherche.* +*                                                                             * +*  Retour      : Bilan de l'opération à renvoyer.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow) +{ +    bool result;                            /* Statut à retourner          */ +      assert(g_engine_backend_get_atom_max_size(backend) == maxsize); -    class = G_SCAN_TOKEN_NODE_GET_CLASS(node); +    *slow = 0; -    result = class->enroll(node, context, backend, maxsize); +    result = _g_scan_token_node_enroll(node, context, backend, maxsize, slow);      return result; @@ -175,6 +344,8 @@ bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngi  *                content = accès au contenu brut pour vérifications (optim.)  *  *                matches = suivi des correspondances à consolider.            *  *                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         *  *                                                                             *  *  Description : Transforme les correspondances locales en trouvailles.       *  *                                                                             * @@ -184,12 +355,236 @@ bool g_scan_token_node_enroll(GScanTokenNode *node, GScanContext *context, GEngi  *                                                                             *  ******************************************************************************/ -void g_scan_token_node_check(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, const node_search_offset_t *offset) +void _g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)  {      GScanTokenNodeClass *class;             /* Classe de l'instance        */ +    if (node->flags & STNF_MAIN) +    { +        //assert(*skip); //REMME +        *skip = false; +    } + +    printf("Checking forward... node=%p / %s skip=%d main=%u\n", +           node, G_OBJECT_TYPE_NAME(node), *skip, (node->flags & STNF_MAIN) == STNF_MAIN); +      class = G_SCAN_TOKEN_NODE_GET_CLASS(node); -    class->check(node, context, content, matches, offset); +    class->check_forward(node, context, content, matches, offset, not, skip); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_scan_token_node_check_forward(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches) +{ +    node_search_offset_t offset;            /* Espace des correspondances  */ +    bool skip;                              /* Mise en attente des analyses*/ +    size_t ocount;                          /* Quantité de bornes présentes*/ +    node_offset_range_t * const *ranges_ptr;/* Bornes d'espace à parcourir */ +    size_t pcount;                          /* Nombre de correspondances   */ +    match_area_t * const *pending_ptr;      /* Correspondances actuelles   */ +    size_t p;                               /* Boucle de parcours #2       */ +    match_area_t *pending;                  /* Correspondance à traiter    */ +    phys_t old_end;                         /* Ancien point d'arrivée      */ +    size_t o;                               /* Boucle de parcours #1       */ +    const node_offset_range_t *range;       /* Bornes d'espace à parcourir */ +    phys_t new_end;                         /* Nouveau point d'arrivée     */ + +    init_node_search_offset(&offset); + +    skip = true; + +    _g_scan_token_node_check_forward(node, context, content, matches, &offset, false, &skip); + +    /** +     * Si un décalage entre octets n'a pas été consommé, +     * les résultats sont étendus à minima. +     */ + +    ranges_ptr = get_node_search_offset_ranges(&offset, &ocount); + +    if (ocount > 0) +    { +        reset_pending_matches_ttl(matches); + +        pending_ptr = get_all_pending_matches(matches, &pcount); + +        for (p = 0; p < pcount; p++) +        { +            pending = (*pending_ptr) + p; + +            old_end = pending->end; + +            for (o = 0; o < ocount; o++) +            { +                range = (*ranges_ptr) + o; + +                new_end = old_end + range->min; + +                if (new_end > matches->content_end) +                    new_end = matches->content_end; + +                extend_pending_match_ending(matches, p, new_end); + +            } + +        } + +        /** +         * Pas besoin de purge ici puisque tous les résultats ont été traités +         * au moins une fois, sans condition. +         */ +        /* purge_pending_matches(matches); */ + +        disable_all_ranges_in_node_search_offset(&offset); + +    } + +    assert(offset.used == 0); + +    exit_node_search_offset(&offset); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void _g_scan_token_node_check_backward(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +    GScanTokenNodeClass *class;             /* Classe de l'instance        */ + +    printf("Checking backward... node=%p / %s skip=%d main=%u\n", +           node, G_OBJECT_TYPE_NAME(node), *skip, (node->flags & STNF_MAIN) == STNF_MAIN); + +    class = G_SCAN_TOKEN_NODE_GET_CLASS(node); + +    class->check_backward(node, context, content, matches, offset, not, skip); + +    if (node->flags & STNF_MAIN) +    { +        //assert(*skip); //REMME +        *skip = false; +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_scan_token_node_check_backward(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches) +{ +    node_search_offset_t offset;            /* Espace des correspondances  */ +    bool skip;                              /* Mise en attente des analyses*/ +    size_t ocount;                          /* Quantité de bornes présentes*/ +    node_offset_range_t * const *ranges_ptr;/* Bornes d'espace à parcourir */ +    size_t pcount;                          /* Nombre de correspondances   */ +    match_area_t * const *pending_ptr;      /* Correspondances actuelles   */ +    size_t p;                               /* Boucle de parcours #2       */ +    match_area_t *pending;                  /* Correspondance à traiter    */ +    phys_t old_start;                       /* Ancien point d'arrivée      */ +    size_t o;                               /* Boucle de parcours #1       */ +    const node_offset_range_t *range;       /* Bornes d'espace à parcourir */ +    phys_t new_start;                       /* Nouveau point d'arrivée     */ + +    init_node_search_offset(&offset); + +    skip = true; + +    _g_scan_token_node_check_backward(node, context, content, matches, &offset, false, &skip); + +    /** +     * Si un décalage entre octets n'a pas été consommé, +     * les résultats sont étendus à minima. +     */ + +    ranges_ptr = get_node_search_offset_ranges(&offset, &ocount); + +    if (ocount > 0) +    { +        reset_pending_matches_ttl(matches); + +        pending_ptr = get_all_pending_matches(matches, &pcount); + +        for (p = 0; p < pcount; p++) +        { +            pending = (*pending_ptr) + p; + +            old_start = pending->start; + +            for (o = 0; o < ocount; o++) +            { +                range = (*ranges_ptr) + o; + +                if (old_start < range->min) +                    new_start = 0; +                else +                    new_start = old_start - range->min; + +                if (new_start < matches->content_start) +                    new_start = matches->content_start; + +                extend_pending_match_beginning(matches, p, new_start); + +            } + +        } + +        /** +         * Pas besoin de purge ici puisque tous les résultats ont été traités +         * au moins une fois, sans condition. +         */ +        /* purge_pending_matches(matches); */ + +        disable_all_ranges_in_node_search_offset(&offset); + +    } + +    assert(offset.used == 0); + +    exit_node_search_offset(&offset);  } diff --git a/src/analysis/scan/patterns/tokens/node.h b/src/analysis/scan/patterns/tokens/node.h index 4c9eb48..a2e3b0d 100644 --- a/src/analysis/scan/patterns/tokens/node.h +++ b/src/analysis/scan/patterns/tokens/node.h @@ -49,28 +49,38 @@ typedef struct _GScanTokenNode GScanTokenNode;  typedef struct _GScanTokenNodeClass GScanTokenNodeClass; +/* Propriétés particulières pour noeud d'analyse */ +typedef enum _ScanTokenNodeFlags +{ +    STNF_NONE  = (0 << 0),                  /* Absence de singularité      */ +    STNF_PROD  = (1 << 0),                  /* Absence de singularité      */ +    STNF_FIRST = (1 << 1),                  /* Premier noeud de traitement */   /* REMME ? */ +    STNF_LAST  = (1 << 2),                  /* Dernier noeud de traitement */   /* REMME ? */ +    STNF_MAIN  = (1 << 3),                  /* Point de départ d'analyse   */ + +} ScanTokenNodeFlags; + +  /* Indique le type défini pour un élément décomposant un motif d'octets à rechercher. */  GType g_scan_token_node_get_type(void); +/* Indique les propriétés particulières d'un noeud d'analyse. */ +ScanTokenNodeFlags g_scan_token_node_get_flags(const GScanTokenNode *); -// TODO -// validate -// force_plain_registration // set begin/end +/* Marque le noeud avec des propriétés particulières. */ +void g_scan_token_node_set_flags(GScanTokenNode *, ScanTokenNodeFlags); +/* Détermine et prépare les éléments clefs d'une arborescence. */ +bool g_scan_token_node_setup_tree(GScanTokenNode *);  /* Inscrit la définition d'un motif dans un moteur de recherche. */ -bool g_scan_token_node_enroll(GScanTokenNode *, GScanContext *, GEngineBackend *, size_t); +bool g_scan_token_node_enroll(GScanTokenNode *, GScanContext *, GEngineBackend *, size_t, size_t *); -/* Mémorisation d'une souplesse dans les positions visées */ -typedef struct _node_search_offset_t -{ -    phys_t min;                             /* Position minimale           */ -    phys_t max;                             /* Position maxnimale           */ - -} node_search_offset_t; +/* Transforme les correspondances locales en trouvailles. */ +void g_scan_token_node_check_forward(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *);  /* Transforme les correspondances locales en trouvailles. */ -void g_scan_token_node_check(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, const node_search_offset_t *); +void g_scan_token_node_check_backward(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *); diff --git a/src/analysis/scan/patterns/tokens/nodes/Makefile.am b/src/analysis/scan/patterns/tokens/nodes/Makefile.am index c20beaf..b5da1ee 100644 --- a/src/analysis/scan/patterns/tokens/nodes/Makefile.am +++ b/src/analysis/scan/patterns/tokens/nodes/Makefile.am @@ -3,10 +3,18 @@ noinst_LTLIBRARIES  = libanalysisscanpatternstokensnodes.la  libanalysisscanpatternstokensnodes_la_SOURCES =	\ -	hub-int.h								\ -	hub.h hub.c								\ +	any-int.h								\ +	any.h any.c								\ +	choice-int.h							\ +	choice.h choice.c						\ +	masked-int.h							\ +	masked.h masked.c						\ +	not-int.h								\ +	not.h not.c								\  	plain-int.h								\ -	plain.h plain.c +	plain.h plain.c							\ +	sequence-int.h							\ +	sequence.h sequence.c  libanalysisscanpatternstokensnodes_la_CFLAGS = $(LIBGOBJ_CFLAGS) diff --git a/src/analysis/scan/patterns/tokens/nodes/any-int.h b/src/analysis/scan/patterns/tokens/nodes/any-int.h new file mode 100644 index 0000000..705aab3 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/any-int.h @@ -0,0 +1,60 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * any-int.h - prototypes internes pour une suite d'octets quelconques + * + * 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_PATTERNS_TOKENS_NODES_ANY_INT_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_ANY_INT_H + + +#include "any.h" + + +#include "../atom.h" +#include "../node-int.h" + + + +/* Espace constitué d'un ou plusieurs octets quelconques (instance) */ +struct _GScanTokenNodeAny +{ +    GScanTokenNode parent;                  /* A laisser en premier        */ + +    phys_t min;                             /* Quantité minimale           */ +    phys_t max;                             /* Quantité maximale           */ +    bool has_max;                           /* Quantité définie ?          */ + +}; + +/* Espace constitué d'un ou plusieurs octets quelconques (classe) */ +struct _GScanTokenNodeAnyClass +{ +    GScanTokenNodeClass parent;             /* A laisser en premier        */ + +}; + + +/* Met en place un un noeud pointant une série d'octets. */ +bool g_scan_token_node_any_create(GScanTokenNodeAny *, const phys_t *, const phys_t *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_ANY_INT_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/any.c b/src/analysis/scan/patterns/tokens/nodes/any.c new file mode 100644 index 0000000..af2ae29 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/any.c @@ -0,0 +1,425 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * any.c - suite d'octets quelconques + * + * 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 "any.h" + + +#include <assert.h> + + +#include "any-int.h" + + + +/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */ + + +/* Initialise la classe des séries d'octets quelconques. */ +static void g_scan_token_node_any_class_init(GScanTokenNodeAnyClass *); + +/* Initialise une instance de série d'octets quelconques. */ +static void g_scan_token_node_any_init(GScanTokenNodeAny *); + +/* Supprime toutes les références externes. */ +static void g_scan_token_node_any_dispose(GScanTokenNodeAny *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_token_node_any_finalize(GScanTokenNodeAny *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Inscrit la définition d'un motif dans un moteur de recherche. */ +static bool g_scan_token_node_any_enroll(GScanTokenNodeAny *, GScanContext *, GEngineBackend *, size_t, size_t *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une série d'octets quelconque, vide ou non. */ +G_DEFINE_TYPE(GScanTokenNodeAny, g_scan_token_node_any, G_TYPE_SCAN_TOKEN_NODE); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des séries d'octets quelconques.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_any_class_init(GScanTokenNodeAnyClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GScanTokenNodeClass *node;              /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_any_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_any_finalize; + +    node = G_SCAN_TOKEN_NODE_CLASS(klass); + +    node->visit = (visit_scan_token_node_fc)NULL; +    node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_any_enroll; +    node->check_forward = (check_scan_token_node_fc)g_scan_token_node_any_check_forward; +    node->check_backward = (check_scan_token_node_fc)g_scan_token_node_any_check_backward; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : any = instance à initialiser.                                * +*                                                                             * +*  Description : Initialise une instance de série d'octets quelconques.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_any_init(GScanTokenNodeAny *any) +{ +    g_scan_token_node_set_flags(G_SCAN_TOKEN_NODE(any), STNF_PROD); + +    any->min = 0; +    any->has_max = false; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : any = instance d'objet GLib à traiter.                       * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_any_dispose(GScanTokenNodeAny *any) +{ +    G_OBJECT_CLASS(g_scan_token_node_any_parent_class)->dispose(G_OBJECT(any)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : any = instance d'objet GLib à traiter.                       * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_any_finalize(GScanTokenNodeAny *any) +{ +    G_OBJECT_CLASS(g_scan_token_node_any_parent_class)->finalize(G_OBJECT(any)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : min = éventuelle quantité minimale à retrouver.              * +*                max = éventuelle quantité maximale à retrouver.              * +*                                                                             * +*  Description : Construit un noeud pointant une série d'octets quelconques.  * +*                                                                             * +*  Retour      : Mécanismes mis en place.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanTokenNode *g_scan_token_node_any_new(const phys_t *min, const phys_t *max) +{ +    GScanTokenNode *result;                 /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_TOKEN_NODE_ANY, NULL); + +    if (!g_scan_token_node_any_create(G_SCAN_TOKEN_NODE_ANY(result), min, max)) +        g_clear_object(&result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : any = séquence d'octets quelconques à initialiser pleinement.* +*                min = éventuelle quantité minimale à retrouver.              * +*                max = éventuelle quantité maximale à retrouver.              * +*                                                                             * +*  Description : Met en place un un noeud pointant une série d'octets.        * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_token_node_any_create(GScanTokenNodeAny *any, const phys_t *min, const phys_t *max) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    if (min != NULL) +        any->min = *min; +    else +        any->min = 0; + +    if (max != NULL) +    { +        any->max = *max; + +        result = (any->min <= any->max); + +    } + +    any->has_max = (max != NULL); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à enregistrer.              * +*                context = contexte de l'analyse à mener.                     * +*                backend = moteur de recherche à préchauffer.                 * +*                maxsize = taille max. des atomes (mise en commun optimisée). * +*                slow    = niveau de ralentissement induit (0 = idéal). [OUT] * +*                                                                             * +*  Description : Inscrit la définition d'un motif dans un moteur de recherche.* +*                                                                             * +*  Retour      : Bilan de l'opération à renvoyer.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_token_node_any_enroll(GScanTokenNodeAny *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow) +{ +    bool result;                            /* Statut à retourner          */ +    bool forced;                            /* Inclusion dans un scan ?    */ + +    result = true; + +    forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN); + +    if (forced) +        *slow += (maxsize * 4); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +    bool initialized;                       /* Initialisation du suivi ?   */ +    bool forced;                            /* Inclusion dans un scan ?    */ +    phys_t size;                            /* Quantité d'octets considérés*/ +    const phys_t *datasize;                 /* Taille max. à communiquer   */ + +    if (*skip) +        return; + + +    //         $a = { [1-3] 6f } +    // pas d'initialisation, construction de résultats avec une taille nulle + + + +    initialized = are_pending_matches_initialized(matches); + +    forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN); + +    size = matches->content_end - matches->content_start; + +    datasize = (not ? &size : NULL); + +    if (forced) +    { +        assert(!initialized); + +        if (node->min > size) +            /* TODO set abort in matches */; + +        else +            add_range_to_node_search_offset(offset, +                                            matches->content_start, +                                            matches->content_end - matches->content_start, +                                            datasize); + +    } +    else +    { +        assert(initialized); + + +        // TODO : compléter les intervales éventuels déjà en place + + +        printf("[i] create hole: %llx <-> %llx\n", +               (unsigned long long)node->min, +               (unsigned long long)node->max); + + + +        if (node->has_max) +            add_range_to_node_search_offset(offset, node->min, node->max, datasize); +        else +            add_range_to_node_search_offset(offset, node->min, matches->content_end - node->min, datasize); + +        // TODO : si dernier, virer les correspondances qui n'ont plus l'espace de fin requis +        // -> au niveau du noeud, en fonction du flag _LAST + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +#ifndef NDEBUG +    bool forced;                            /* Inclusion dans un scan ?    */ +#endif +    phys_t size;                            /* Quantité d'octets considérés*/ +    const phys_t *datasize;                 /* Taille max. à communiquer   */ + +    if (*skip) +        return; + +    /** +     * En lecture à rebourd, au moins un noeud a été solicité pour analyse (lors +     * du sens de lecteur normal). Donc l'initialisation a déjà dû avoir lieu. +     */ +    assert(are_pending_matches_initialized(matches)); + +    /** +     * Si les recherches associées au noeud ont été forcées, alors les traitements +     * liés ont déjà été effectués, et l'appel de cette fonction aurait dû être sauté. +     */ +#ifndef NDEBUG +    forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN); +    assert(!forced); +#endif + +    size = matches->content_end - matches->content_start; + +    if (node->min > size) +        /* TODO set abort in matches */; + +    else +    { +        datasize = (not ? &size : NULL); + +        /** +         * Une tolérance basée sur des espaces (et non des positions) est déterminée +         * ici. +         * +         * Charge au prochain noeud de traitement de filtrer les résultats courants +         * avec, voire à la fonction _g_scan_token_node_check_backward() de +         * réaliser une synthèse finale si le noeud courant est le dernier d'une +         * lignée. +         */ + +        if (node->has_max) +            add_range_to_node_search_offset(offset, node->min, node->max, datasize); +        else +            add_range_to_node_search_offset(offset, node->min, matches->content_end - node->min, datasize); + +    } + +} diff --git a/src/analysis/scan/patterns/tokens/nodes/any.h b/src/analysis/scan/patterns/tokens/nodes/any.h new file mode 100644 index 0000000..6a5628a --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/any.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * any.h - prototypes pour une suite d'octets quelconques + * + * 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_PATTERNS_TOKENS_NODES_ANY_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_ANY_H + + +#include <glib-object.h> + + +#include "../node.h" + + + +#define G_TYPE_SCAN_TOKEN_NODE_ANY            g_scan_token_node_any_get_type() +#define G_SCAN_TOKEN_NODE_ANY(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_ANY, GScanTokenNodeAny)) +#define G_IS_SCAN_TOKEN_NODE_ANY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_ANY)) +#define G_SCAN_TOKEN_NODE_ANY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_ANY, GScanTokenNodeAnyClass)) +#define G_IS_SCAN_TOKEN_NODE_ANY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_ANY)) +#define G_SCAN_TOKEN_NODE_ANY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_ANY, GScanTokenNodeAnyClass)) + + +/* Espace constitué d'un ou plusieurs octets quelconques (instance) */ +typedef struct _GScanTokenNodeAny GScanTokenNodeAny; + +/* Espace constitué d'un ou plusieurs octets quelconques (classe) */ +typedef struct _GScanTokenNodeAnyClass GScanTokenNodeAnyClass; + + +/* Indique le type défini pour une série d'octets quelconque, vide ou non. */ +GType g_scan_token_node_any_get_type(void); + +/* Construit un noeud pointant une série d'octets quelconques. */ +GScanTokenNode *g_scan_token_node_any_new(const phys_t *, const phys_t *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_ANY_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/hub-int.h b/src/analysis/scan/patterns/tokens/nodes/choice-int.h index df05112..77a4058 100644 --- a/src/analysis/scan/patterns/tokens/nodes/hub-int.h +++ b/src/analysis/scan/patterns/tokens/nodes/choice-int.h @@ -1,6 +1,6 @@  /* Chrysalide - Outil d'analyse de fichiers binaires - * hub-int.h - prototypes internes pour un groupe de décompositions de motif de recherche en atomes assemblés + * choice-int.h - prototypes internes pour des décompositions alternatives de motif de recherche   *   * Copyright (C) 2023 Cyrille Bagard   * @@ -21,26 +21,29 @@   */ -#ifndef _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_INT_H -#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_INT_H +#ifndef _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_CHOICE_INT_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_CHOICE_INT_H -#include "hub.h" +#include "choice.h"  #include "../node-int.h" -/* Groupe de décompositions de motif de recherche en atomes (instance) */ -struct _GScanTokenNodeHub +/* Décompositions alternatives de motif de recherche (instance) */ +struct _GScanTokenNodeChoice  {      GScanTokenNode parent;                  /* A laisser en premier        */ +    GScanTokenNode **children;              /* Sous-noeuds à représenter   */ +    size_t count;                           /* Taille de cette liste       */ +  }; -/* Groupe de décompositions de motif de recherche en atomes (classe) */ -struct _GScanTokenNodeHubClass +/* Décompositions alternatives de motif de recherche (classe) */ +struct _GScanTokenNodeChoiceClass  {      GScanTokenNodeClass parent;             /* A laisser en premier        */ @@ -48,4 +51,4 @@ struct _GScanTokenNodeHubClass -#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_INT_H */ +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_CHOICE_INT_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/choice.c b/src/analysis/scan/patterns/tokens/nodes/choice.c new file mode 100644 index 0000000..df6ae45 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/choice.c @@ -0,0 +1,486 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * choice.c - décompositions alternatives de motif de recherche + * + * 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 "choice.h" + + +#include "choice-int.h" + + + +/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */ + + +/* Initialise la classe des décompositions alternatives. */ +static void g_scan_token_node_choice_class_init(GScanTokenNodeChoiceClass *); + +/* Initialise une instance de décompositions alternatives. */ +static void g_scan_token_node_choice_init(GScanTokenNodeChoice *); + +/* Supprime toutes les références externes. */ +static void g_scan_token_node_choice_dispose(GScanTokenNodeChoice *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_token_node_choice_finalize(GScanTokenNodeChoice *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Prend acte d'une nouvelle propriété pour le noeud. */ +static void g_scan_token_node_choice_apply_flags(GScanTokenNodeChoice *, ScanTokenNodeFlags); + +/* Parcourt une arborescence de noeuds et y relève des éléments. */ +static void g_scan_token_node_choice_visit(GScanTokenNodeChoice *, scan_tree_points_t *); + +/* Inscrit la définition d'un motif dans un moteur de recherche. */ +static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *, GScanContext *, GEngineBackend *, size_t, size_t *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_choice_check_forward(const GScanTokenNodeChoice *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_choice_check_backward(const GScanTokenNodeChoice *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour des décompositions alternatives de motif de recherche. */ +G_DEFINE_TYPE(GScanTokenNodeChoice, g_scan_token_node_choice, G_TYPE_SCAN_TOKEN_NODE); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des décompositions alternatives.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_choice_class_init(GScanTokenNodeChoiceClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GScanTokenNodeClass *node;              /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_choice_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_choice_finalize; + +    node = G_SCAN_TOKEN_NODE_CLASS(klass); + +    node->apply = (apply_scan_token_node_flags_fc)g_scan_token_node_choice_apply_flags; +    node->visit = (visit_scan_token_node_fc)g_scan_token_node_choice_visit; +    node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_choice_enroll; +    node->check_forward = (check_scan_token_node_fc)g_scan_token_node_choice_check_forward; +    node->check_backward = (check_scan_token_node_fc)g_scan_token_node_choice_check_backward; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : choice = instance à initialiser.                             * +*                                                                             * +*  Description : Initialise une instance de décompositions alternatives.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_choice_init(GScanTokenNodeChoice *choice) +{ +    choice->children = NULL; +    choice->count = 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : choice = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_choice_dispose(GScanTokenNodeChoice *choice) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < choice->count; i++) +        g_clear_object(&choice->children[i]); + +    G_OBJECT_CLASS(g_scan_token_node_choice_parent_class)->dispose(G_OBJECT(choice)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : choice = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_choice_finalize(GScanTokenNodeChoice *choice) +{ +    if (choice->children != NULL) +        free(choice->children); + +    G_OBJECT_CLASS(g_scan_token_node_choice_parent_class)->finalize(G_OBJECT(choice)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Construit une série de décompositions alternatives de motif. * +*                                                                             * +*  Retour      : Mécanismes mis en place.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanTokenNode *g_scan_token_node_choice_new(void) +{ +    GScanTokenNode *result;                 /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_TOKEN_NODE_CHOICE, NULL); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : choice = ensemble de noeuds à compléter.                     * +*                node   = nouveau noeud à intégrer.                           * +*                                                                             * +*  Description : Ajoute un noeud à aux décompositions alternatives de motif.  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_scan_token_node_choice_add(GScanTokenNodeChoice *choice, GScanTokenNode *node) +{ +    choice->children = realloc(choice->children, ++choice->count * sizeof(GScanTokenNode *)); + +    choice->children[choice->count - 1] = node; +    g_object_ref(G_OBJECT(node)); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node  = noeud de motif à mettre à jour.                      * +*                flags = propriétés particulières à associer au noeud.        * +*                                                                             * +*  Description : Prend acte d'une nouvelle propriété pour le noeud.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_choice_apply_flags(GScanTokenNodeChoice *node, ScanTokenNodeFlags flags) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < node->count; i++) +        g_scan_token_node_set_flags(node->children[i], flags); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node   = point de départ du parcours à effectuer.            * +*                points = points capitaux de l'arborescence. [OUT]            * +*                                                                             * +*  Description : Parcourt une arborescence de noeuds et y relève des éléments.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_choice_visit(GScanTokenNodeChoice *node, scan_tree_points_t *points) +{ +    size_t first_plain_count;               /* Décompte de noeuds textuels */ +    size_t i;                               /* Boucle de parcours          */ +    scan_tree_points_t tmp_points;          /* Synthèse d'analyse locale   */ + +    if (points->first_plain != NULL) +        return; + +    first_plain_count = 0; + +    for (i = 0; i < node->count; i++) +    { +        tmp_points.first_node = NULL; +        tmp_points.last_node = NULL; + +        tmp_points.first_plain = NULL; +        tmp_points.best_masked = NULL; + +        g_scan_token_node_visit(node->children[i], &tmp_points); + +        if (tmp_points.first_plain != NULL) +            first_plain_count++; + +    } + +    if (first_plain_count == node->count) +        points->first_plain = G_SCAN_TOKEN_NODE(node); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à enregistrer.              * +*                context = contexte de l'analyse à mener.                     * +*                backend = moteur de recherche à préchauffer.                 * +*                maxsize = taille max. des atomes (mise en commun optimisée). * +*                slow    = niveau de ralentissement induit (0 = idéal). [OUT] * +*                                                                             * +*  Description : Inscrit la définition d'un motif dans un moteur de recherche.* +*                                                                             * +*  Retour      : Bilan de l'opération à renvoyer.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_token_node_choice_enroll(GScanTokenNodeChoice *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow) +{ +    bool result;                            /* Statut à retourner          */ +    size_t i;                               /* Boucle de parcours          */ + +    result = true; + +    for (i = 0; i < node->count && result; i++) +        result = _g_scan_token_node_enroll(node->children[i], context, backend, maxsize, slow); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_choice_check_forward(const GScanTokenNodeChoice *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +    pending_matches_t init_matches;         /* Correspondances initiales   */ +    node_search_offset_t init_offset;       /* Intervales initiaux         */  +    size_t new_offset;                      /* Décompte d'intervales       */ +    size_t i;                               /* Boucle de parcours          */ +    pending_matches_t tmp_matches;          /* Copie locale de travail #1  */ +    node_search_offset_t tmp_offset;        /* Copie locale de travail #2  */ + +    if (*skip) +        return; + +    /* Copie des contextes de départ */ + +    copy_pending_matches(&init_matches, matches); + +    exit_pending_matches(matches); +    init_pending_matches(matches, &init_matches.content_start, &init_matches.content_end); + +    copy_node_search_offset(&init_offset, offset); + +    exit_node_search_offset(offset); +    init_node_search_offset(offset); + +    /* Lancement des sous-traitements */ + +    new_offset = 0; + +    for (i = 0; i < node->count; i++) +    { +        copy_pending_matches(&tmp_matches, &init_matches); +        copy_node_search_offset(&tmp_offset, &init_offset); + +        _g_scan_token_node_check_forward(node->children[i], context, content, +                                         &tmp_matches, &tmp_offset, not, skip); + +        merge_pending_matches(matches, &tmp_matches); +        merge_node_search_offset(offset, &tmp_offset); + +        if (tmp_offset.used > 0) +            new_offset++; + +        exit_pending_matches(&tmp_matches); +        exit_node_search_offset(&tmp_offset); + +    } + +    /* Sortie propre */ + +    exit_pending_matches(&init_matches); +    exit_node_search_offset(&init_offset); + +    /* "Alternative" directe en cas de motif(s) non terminé(s) par un intervale */ + +    if (new_offset != node->count) +    { +        assert(node->count > 1); +        add_range_to_node_search_offset(offset, 0, 0, NULL); +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offsets = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_choice_check_backward(const GScanTokenNodeChoice *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +    pending_matches_t init_matches;         /* Correspondances initiales   */ +    node_search_offset_t init_offset;       /* Intervales initiaux         */  +    size_t new_offset;                      /* Décompte d'intervales       */ +    size_t i;                               /* Boucle de parcours          */ +    pending_matches_t tmp_matches;          /* Copie locale de travail #1  */ +    node_search_offset_t tmp_offset;        /* Copie locale de travail #2  */ + +    if (*skip) +        return; + +    /* Copie des contextes de départ */ + +    copy_pending_matches(&init_matches, matches); + +    exit_pending_matches(matches); +    init_pending_matches(matches, &init_matches.content_start, &init_matches.content_end); + +    copy_node_search_offset(&init_offset, offset); + +    exit_node_search_offset(offset); +    init_node_search_offset(offset); + +    /* Lancement des sous-traitements */ + +    new_offset = 0; + +    for (i = 0; i < node->count; i++) +    { +        copy_pending_matches(&tmp_matches, &init_matches); +        copy_node_search_offset(&tmp_offset, &init_offset); + +        _g_scan_token_node_check_backward(node->children[i], context, content, +                                          &tmp_matches, &tmp_offset, not, skip); + +        merge_pending_matches(matches, &tmp_matches); +        merge_node_search_offset(offset, &tmp_offset); + +        if (tmp_offset.used > 0) +            new_offset++; + +        exit_pending_matches(&tmp_matches); +        exit_node_search_offset(&tmp_offset); + +    } + +    /* Sortie propre */ + +    exit_pending_matches(&init_matches); +    exit_node_search_offset(&init_offset); + +    /* "Alternative" directe en cas de motif(s) non terminé(s) par un intervale */ + +    if (new_offset != node->count) +    { +        assert(node->count > 1); +        add_range_to_node_search_offset(offset, 0, 0, NULL); +    } + +} diff --git a/src/analysis/scan/patterns/tokens/nodes/choice.h b/src/analysis/scan/patterns/tokens/nodes/choice.h new file mode 100644 index 0000000..e793b1e --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/choice.h @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * choice.h - prototypes pour des décompositions alternatives de motif de recherche + * + * 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_PATTERNS_TOKENS_NODES_CHOICE_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_CHOICE_H + + +#include <glib-object.h> + + +#include "../node.h" + + + +#define G_TYPE_SCAN_TOKEN_NODE_CHOICE            g_scan_token_node_choice_get_type() +#define G_SCAN_TOKEN_NODE_CHOICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_CHOICE, GScanTokenNodeChoice)) +#define G_IS_SCAN_TOKEN_NODE_CHOICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_CHOICE)) +#define G_SCAN_TOKEN_NODE_CHOICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_CHOICE, GScanTokenNodeChoiceClass)) +#define G_IS_SCAN_TOKEN_NODE_CHOICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_CHOICE)) +#define G_SCAN_TOKEN_NODE_CHOICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_CHOICE, GScanTokenNodeChoiceClass)) + + +/* Décompositions alternatives de motif de recherche (instance) */ +typedef struct _GScanTokenNodeChoice GScanTokenNodeChoice; + +/* Décompositions alternatives de motif de recherche (classe) */ +typedef struct _GScanTokenNodeChoiceClass GScanTokenNodeChoiceClass; + + +/* Indique le type défini pour des décompositions alternatives de motif de recherche. */ +GType g_scan_token_node_choice_get_type(void); + +/* Construit une série de décompositions alternatives de motif. */ +GScanTokenNode *g_scan_token_node_choice_new(void); + +/* Ajoute un noeud à aux décompositions alternatives de motif. */ +void g_scan_token_node_choice_add(GScanTokenNodeChoice *, GScanTokenNode *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_CHOICE_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/hub.c b/src/analysis/scan/patterns/tokens/nodes/hub.c deleted file mode 100644 index a11531d..0000000 --- a/src/analysis/scan/patterns/tokens/nodes/hub.c +++ /dev/null @@ -1,150 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * hub.c - groupe de décompositions de motif de recherche en atomes assemblés - * - * 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 "hub.h" - - -#include "hub-int.h" - - - -/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */ - - -/* Initialise la classe des groupes de décompositions. */ -static void g_scan_token_node_hub_class_init(GScanTokenNodeHubClass *klass); - -/* Initialise une instance de groupe de décompositions. */ -static void g_scan_token_node_hub_init(GScanTokenNodeHub *); - -/* Supprime toutes les références externes. */ -static void g_scan_token_node_hub_dispose(GScanTokenNodeHub *); - -/* Procède à la libération totale de la mémoire. */ -static void g_scan_token_node_hub_finalize(GScanTokenNodeHub *); - - - -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ - - - - - -/* ---------------------------------------------------------------------------------- */ -/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini pour un groupe de décompositions de motif d'octets à rechercher. */ -G_DEFINE_TYPE(GScanTokenNodeHub, g_scan_token_node_hub, G_TYPE_SCAN_TOKEN_NODE); - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : klass = classe à initialiser.                                * -*                                                                             * -*  Description : Initialise la classe des groupes de décompositions.          * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_scan_token_node_hub_class_init(GScanTokenNodeHubClass *klass) -{ -    GObjectClass *object;                   /* Autre version de la classe  */ - -    object = G_OBJECT_CLASS(klass); - -    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_hub_dispose; -    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_hub_finalize; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : hub = instance à initialiser.                                * -*                                                                             * -*  Description : Initialise une instance de groupe de décompositions.         * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_scan_token_node_hub_init(GScanTokenNodeHub *hub) -{ - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : hub = instance d'objet GLib à traiter.                       * -*                                                                             * -*  Description : Supprime toutes les références externes.                     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_scan_token_node_hub_dispose(GScanTokenNodeHub *hub) -{ -    G_OBJECT_CLASS(g_scan_token_node_hub_parent_class)->dispose(G_OBJECT(hub)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : hub = instance d'objet GLib à traiter.                       * -*                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_scan_token_node_hub_finalize(GScanTokenNodeHub *hub) -{ -    G_OBJECT_CLASS(g_scan_token_node_hub_parent_class)->finalize(G_OBJECT(hub)); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ -/* ---------------------------------------------------------------------------------- */ - - - - diff --git a/src/analysis/scan/patterns/tokens/nodes/hub.h b/src/analysis/scan/patterns/tokens/nodes/hub.h deleted file mode 100644 index b2cb0fc..0000000 --- a/src/analysis/scan/patterns/tokens/nodes/hub.h +++ /dev/null @@ -1,55 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * hub.h - prototypes pour un groupe de décompositions de motif de recherche en atomes assemblés - * - * 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_PATTERNS_TOKENS_NODES_HUB_H -#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_H - - -#include <glib-object.h> - - -#include "../node.h" - - - -#define G_TYPE_SCAN_TOKEN_NODE_HUB            g_scan_token_node_hub_get_type() -#define G_SCAN_TOKEN_NODE_HUB(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_HUB, GScanTokenNodeHub)) -#define G_IS_SCAN_TOKEN_NODE_HUB(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_HUB)) -#define G_SCAN_TOKEN_NODE_HUB_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_HUB, GScanTokenNodeHubClass)) -#define G_IS_SCAN_TOKEN_NODE_HUB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_HUB)) -#define G_SCAN_TOKEN_NODE_HUB_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_HUB, GScanTokenNodeHubClass)) - - -/* Groupe de décompositions de motif de recherche en atomes (instance) */ -typedef struct _GScanTokenNodeHub GScanTokenNodeHub; - -/* Groupe de décompositions de motif de recherche en atomes (classe) */ -typedef struct _GScanTokenNodeHubClass GScanTokenNodeHubClass; - - -/* Indique le type défini pour un groupe de décompositions de motif d'octets à rechercher. */ -GType g_scan_token_node_hub_get_type(void); - - - -#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/masked-int.h b/src/analysis/scan/patterns/tokens/nodes/masked-int.h new file mode 100644 index 0000000..9eb8712 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/masked-int.h @@ -0,0 +1,63 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * masked-int.h - prototypes internes pour la gestion d'une recherche de motif partielle + * + * 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_PATTERNS_TOKENS_NODES_MASKED_INT_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_MASKED_INT_H + + +#include "masked.h" + + +#include "../node-int.h" + + + +/* Bribe de motif partielle pour recherches (instance) */ +struct _GScanTokenNodeMasked +{ +    GScanTokenNode parent;                  /* A laisser en premier        */ + +    masked_byte_t *bytes;                   /* Série d'octets masqués      */ +    size_t len;                             /* Taille de cette série       */ + +    sized_binary_t *raw;                    /* Liste de motifs à couvrir   */ +    tracked_scan_atom_t *atoms;             /* Atomes correspondants       */ +    size_t count;                           /* Taille de cette liste       */ +    size_t enrolled_count;                  /* Quantité avec identifiant   */ + +}; + +/* Bribe de motif partielle pour recherches (classe) */ +struct _GScanTokenNodeMaskedClass +{ +    GScanTokenNodeClass parent;             /* A laisser en premier        */ + +}; + + +/* Met en place une bribe de motif partielle. */ +bool g_scan_token_node_masked_create(GScanTokenNodeMasked *, const masked_byte_t *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_MASKED_INT_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/masked.c b/src/analysis/scan/patterns/tokens/nodes/masked.c new file mode 100644 index 0000000..25f0315 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/masked.c @@ -0,0 +1,814 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * masked.c - gestion d'une recherche de motif partielle + * + * 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 "masked.h" + + +#include <assert.h> + + +#include "masked-int.h" +#include "../../backends/bitap.h" + + + +/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */ + + +/* Initialise la classe des bribes de motif partielles. */ +static void g_scan_token_node_masked_class_init(GScanTokenNodeMaskedClass *); + +/* Initialise une instance de bribe de motif partielle. */ +static void g_scan_token_node_masked_init(GScanTokenNodeMasked *); + +/* Supprime toutes les références externes. */ +static void g_scan_token_node_masked_dispose(GScanTokenNodeMasked *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_token_node_masked_finalize(GScanTokenNodeMasked *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Parcourt une arborescence de noeuds et y relève des éléments. */ +static void g_scan_token_node_masked_visit(GScanTokenNodeMasked *, scan_tree_points_t *); + +/* Inscrit la définition d'un motif dans un moteur de recherche. */ +static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *, GScanContext *, GEngineBackend *, size_t, size_t *); + +/* Détermine si un contenu d'intérêt est présent à une position. */ +static bool check_scan_token_node_masked_content(const masked_byte_t *, size_t, phys_t, GBinContent *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un noeud représentant une bribe partielle à retrouver. */ +G_DEFINE_TYPE(GScanTokenNodeMasked, g_scan_token_node_masked, G_TYPE_SCAN_TOKEN_NODE); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des bribes de motif partielles.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_masked_class_init(GScanTokenNodeMaskedClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GScanTokenNodeClass *node;              /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_masked_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_masked_finalize; + +    node = G_SCAN_TOKEN_NODE_CLASS(klass); + +    node->visit = (visit_scan_token_node_fc)g_scan_token_node_masked_visit; +    node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_masked_enroll; +    node->check_forward = (check_scan_token_node_fc)g_scan_token_node_masked_check_forward; +    node->check_backward = (check_scan_token_node_fc)g_scan_token_node_masked_check_backward; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : masked = instance à initialiser.                             * +*                                                                             * +*  Description : Initialise une instance de bribe de motif partielle.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_masked_init(GScanTokenNodeMasked *masked) +{ +    g_scan_token_node_set_flags(G_SCAN_TOKEN_NODE(masked), STNF_PROD); + +    masked->bytes = NULL; +    masked->len = 0; + +    masked->raw = NULL; +    masked->atoms = NULL; +    masked->count = 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : masked = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_masked_dispose(GScanTokenNodeMasked *masked) +{ +    G_OBJECT_CLASS(g_scan_token_node_masked_parent_class)->dispose(G_OBJECT(masked)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : masked = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_masked_finalize(GScanTokenNodeMasked *masked) +{ +    size_t i;                               /* Boucle de parcours          */ + +    if (masked->bytes != NULL) +        free(masked->bytes); + +    for (i = 0; i < masked->count; i++) +        exit_szstr(&masked->raw[i]); + +    if (masked->raw != NULL) +        free(masked->raw); + +    if (masked->atoms != NULL) +        free(masked->atoms); + +    G_OBJECT_CLASS(g_scan_token_node_masked_parent_class)->finalize(G_OBJECT(masked)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : byte = valeur masquée à intégrer.                            * +*                                                                             * +*  Description : Construit une bribe de motif partielle.                      * +*                                                                             * +*  Retour      : Mécanismes mis en place.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanTokenNode *g_scan_token_node_masked_new(const masked_byte_t *byte) +{ +    GScanTokenNode *result;                 /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_TOKEN_NODE_MASKED, NULL); + +    if (!g_scan_token_node_masked_create(G_SCAN_TOKEN_NODE_MASKED(result), byte)) +        g_clear_object(&result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : masked = bribe partielle à initialiser pleinement.           * +*                byte   = valeur masquée à intégrer.                          * +*                                                                             * +*  Description : Met en place une bribe de motif partielle.                   * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_token_node_masked_create(GScanTokenNodeMasked *masked, const masked_byte_t *byte) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    g_scan_token_node_masked_add(masked, byte); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : masked = ensemble de noeuds à compléter.                     * +*                byte = valeur masquée à intégrer.                            * +*                                                                             * +*  Description : Enregistre la valeur d'octet à rechercher avec son masque.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_scan_token_node_masked_add(GScanTokenNodeMasked *masked, const masked_byte_t *byte) +{ +    assert((byte->value & 0x0f) == 0 || (byte->value & 0xf0) == 0); + +    masked->bytes = realloc(masked->bytes, ++masked->len * sizeof(masked_byte_t)); + +    masked->bytes[masked->len - 1] = *byte; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node   = point de départ du parcours à effectuer.            * +*                points = points capitaux de l'arborescence. [OUT]            * +*                                                                             * +*  Description : Parcourt une arborescence de noeuds et y relève des éléments.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_masked_visit(GScanTokenNodeMasked *node, scan_tree_points_t *points) +{ +    GScanTokenNodeMasked *other;            /* Concurrence à mesurer       */ + +    if (points->best_masked == NULL) +        points->best_masked = G_SCAN_TOKEN_NODE(node); + +    else +    { +        other = G_SCAN_TOKEN_NODE_MASKED(points->best_masked); + +        if (node->len > other->len) +            points->best_masked = G_SCAN_TOKEN_NODE(node); + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à enregistrer.              * +*                context = contexte de l'analyse à mener.                     * +*                backend = moteur de recherche à préchauffer.                 * +*                maxsize = taille max. des atomes (mise en commun optimisée). * +*                slow    = niveau de ralentissement induit (0 = idéal). [OUT] * +*                                                                             * +*  Description : Inscrit la définition d'un motif dans un moteur de recherche.* +*                                                                             * +*  Retour      : Bilan de l'opération à renvoyer.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_token_node_masked_enroll(GScanTokenNodeMasked *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow) +{ +    bool result;                            /* Statut à retourner          */ +    bool forced;                            /* Inclusion dans un scan ?    */ +    //size_t len_to_enroll;                   /* Taille à considérer         */ +    size_t i;                               /* Boucle de parcours          */ + +    result = true; + +    forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN); + +    if (forced) +    { +        *slow += (maxsize * 2); + +        /** +         * Dans le cas bien précis de l'usage de l'algorithme Bitap pour les recherches +         * dans le contenu binaire à analyser, on tire parti du coût nul des recherches +         * multiples pour une même position. +         */ + +        if (G_IS_BITAP_BACKEND(backend)) +        { +            //len_to_enroll = (node->len < maxsize ? node->len : maxsize); + +            /* TODO */ +            assert(false); + + +            node->enrolled_count = 1; + +        } + +        else +        { +            node->raw = make_atoms_from_masked_byte(node->bytes[0].value, node->bytes[0].mask, &node->count); + +            node->atoms = malloc(node->count * sizeof(tracked_scan_atom_t)); + +            for (i = 0; i < node->count && result; i++) +            { +                find_best_atom(&node->raw[i], maxsize, &node->atoms[i], NULL); + +                result = enroll_prepared_atom(&node->raw[i], context, backend, &node->atoms[i]); + +            } + +            node->enrolled_count = node->count; + +        } + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : bytes   = octets partiels avec leur masque à interpréter.    * +*                len     = quantité d'octets à interpréter.                   * +*                start   = point d'analyse à respecter.                       * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                                                                             * +*  Description : Détermine si un contenu d'intérêt est présent à une position.* +*                                                                             * +*  Retour      : Bilan de l'analyse : true pour une correspondance.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool check_scan_token_node_masked_content(const masked_byte_t *bytes, size_t len, phys_t start, GBinContent *content) +{ +    bool result;                            /* Bilan à retourner           */ +    vmpa2t pos;                             /* Position dans les données   */ +    const bin_t *ptr;                       /* Accès aux données brutes    */ +    size_t i;                               /* Boucle de parcours          */ + +    result = false; + +    init_vmpa(&pos, start, VMPA_NO_VIRTUAL); + +    ptr = g_binary_content_get_raw_access(content, &pos, len); + +    for (i = 0; i < len; i++) +    { +        if ((ptr[i] & bytes[i].mask) != bytes[i].value) +            break; +    } + +    result = (i == len); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_masked_check_forward(const GScanTokenNodeMasked *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +    bool initialized;                       /* Initialisation du suivi ?   */ +#ifndef NDEBUG +    bool forced;                            /* Inclusion dans un scan ?    */ +#endif +    size_t ocount;                          /* Quantité de bornes présentes*/ +    node_offset_range_t * const *ranges_ptr;/* Bornes d'espace à parcourir */ +    size_t i;                               /* Boucle de parcours #1       */ +    const tracked_scan_atom_t *atom;        /* Atome correspondant         */ +    size_t count;                           /* Quantité de bribes trouvées */ +    const phys_t *found;                    /* Localisations des bribes    */ +    size_t k;                               /* Boucle de parcours #2       */ +    phys_t new_begin;                       /* Nouveau départ à tester     */ +    size_t o;                               /* Boucle de parcours #3       */ +    const node_offset_range_t *range;       /* Bornes d'espace à parcourir */ +    bool status;                            /* Bilan d'une correspondance  */ +    size_t pcount;                          /* Nombre de correspondances   */ +    match_area_t * const *pending_ptr;      /* Correspondances actuelles   */ +    size_t p;                               /* Boucle de parcours #4       */ +    match_area_t *pending;                  /* Correspondance à traiter    */ +    phys_t after;                           /* Espace disposible après     */ +    phys_t min;                             /* Borne minimale déterminée   */ +    phys_t max;                             /* Borne maximale déterminée   */ +    phys_t j;                               /* Boucle de parcours #5       */ + +    if (*skip) +        return; + +    initialized = are_pending_matches_initialized(matches); + +    /** +     * Si l'analyse arrive à un ou plusieurs octets masqués, soit il s'agit du +     * premier noeud, et la génération d'atomes a été forcée pour obtenir des +     * points de départ, soit des correspondances ont été établies au préalable, +     * et il ne doit alors pas y avoir d'atome mis en place (si l'initialisation +     * ne provient pas d'une mise en place artificielle par une inversion NOT). +     */ +#ifndef NDEBUG +    forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN); +    assert((!initialized && forced) || (initialized && (!forced || not))); +#endif + +    ranges_ptr = get_node_search_offset_ranges(offset, &ocount); + +    /* Si aucune correspondance n'a été établie */ +    if (!initialized) +    { +        for (i = 0; i < node->enrolled_count; i++) +        { +            atom = &node->atoms[i]; + +            found = g_scan_context_get_atom_matches(context, atom->pid, &count); + +            for (k = 0; k < count; k++) +            { +                assert(atom->pos == 0); + +                new_begin = found[k]; + +                /** +                 * Si des bornes sont spécifiées, la position de l'atome est testée. +                 * +                 * Dans la pratique, cette situation (non initialisée) ne peut provenir +                 * que d'un espace situé dans le vide, donc couvrant un large périmètre. +                 * La validation a ainsi de grandes chances de passer... +                 * +                 * Le motif pouvant amener à cette situation (pas d'initialisation, +                 * mais à décalage à considérer) est par exemple : +                 * +                 *    ~( ?? ?1 ) +                 * +                 */ +                if (ocount > 0) +                { +                    if (!does_node_search_offset_include_pos_forward(offset, 0, new_begin)) +                        continue; +                } + +                /** +                 * Existe-t-il assez de place pour faire tenir le motif masqué ? +                 */ +                if ((new_begin + node->len) > matches->content_end) +                    continue; + +                status = check_scan_token_node_masked_content(node->bytes, node->len, 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 (start, len) enregistré est +                     * unique. +                     */ +                    add_pending_match(matches, new_begin, node->len); + +                } + +            } + +        } + +    } + +    /* Si les correspondances en place sont à confirmer et compléter */ +    else +    { +        reset_pending_matches_ttl(matches); + +        pending_ptr = get_all_pending_matches(matches, &pcount); + +        for (p = 0; p < pcount; p++) +        { +            pending = (*pending_ptr) + p; + +            assert(pending->end <= matches->content_end); + +            after = matches->content_end - pending->end; + +            new_begin = pending->end; + +            if (ocount > 0) +            { +                for (o = 0; o < ocount; o++) +                { +                    range = (*ranges_ptr) + o; + +                    /** +                     * Si bornes de tolérance il y a, l'espace restant est validé en +                     * tenant compte de ces bornes. +                     */ +                    if (!get_node_offset_range(range, node->len, after, &min, &max)) +                        continue; + +                    /** +                     * Une recherche des différentes correspondances amont est lancée. +                     */ +                    for (j = min; j <= max; j++) +                    { +                        status = check_scan_token_node_masked_content(node->bytes, node->len, +                                                                      new_begin + j, content); + +                        if ((status && !not) || (!status && not)) +                        { +                            /** +                             * S'il s'avère qu'il existe de multiples correspondances dans l'espace +                             * analysé, c'est la fonction extend_pending_match_ending() qui +                             * duplique cette correspondance, en s'appuyant sur le TTL pour +                             * repérer ce cas de figure. +                             * +                             * Par exemple, deux correspondances '?1 ?1 [1-3] ?2 ?2' +                             * sont valides pour un même contenu : +                             * +                             *    aa.bbb -> correspondance 'aa.bb' +                             *      ^ +                             * +                             *    aa.bbb -> correspondance 'aa..bb' +                             *      ^ +                             */ +                            extend_pending_match_ending(matches, p, new_begin + j + node->len); + +                            /** +                             * Comme l'extension a pu conduire à un ajout et donc à une +                             * réallocation de la liste, on recharge l'élément pour les +                             * itérations suivantes. +                             */ +                            pending = (*pending_ptr) + p; + +                        } + +                    } + +                } + +            } + +            else +            { +                /** +                 * Si la fin d'une correspondance potentielle est trop près de +                 * la fin du contenu binaire et ne peut contenir le motif +                 * représenté, alors la corresponance est écartée. +                 */ +                if (node->len > after) +                    continue; + +                new_begin = pending->end; + +                status = check_scan_token_node_masked_content(node->bytes, node->len, new_begin, content); + +                if ((status && !not) || (!status && not)) +                { +                    extend_pending_match_ending(matches, p, new_begin + node->len); + +                    /** +                     * Comme il n'y a qu'une seule itération par correspondance, +                     * nul besoin de recharcher l'élément. +                     */ + +                } + +            } + +        } + +        purge_pending_matches(matches); + +    } + +    set_pending_matches_initialized(matches); + +    disable_all_ranges_in_node_search_offset(offset); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offsets = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_masked_check_backward(const GScanTokenNodeMasked *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +#ifndef NDEBUG +    bool forced;                            /* Inclusion dans un scan ?    */ +#endif +    size_t pcount;                          /* Nombre de correspondances   */ +    match_area_t * const *pending_ptr;      /* Correspondances actuelles   */ +    size_t ocount;                          /* Quantité de bornes présentes*/ +    node_offset_range_t * const *ranges_ptr;/* Bornes d'espace à parcourir */ +    size_t p;                               /* Boucle de parcours #1       */ +    const match_area_t *pending;            /* Correspondance à traiter    */ +    phys_t before;                          /* Espace disposible avant     */ +    phys_t new_begin;                       /* Nouveau départ à tester     */ +    size_t o;                               /* Boucle de parcours #2       */ +    const node_offset_range_t *range;       /* Bornes d'espace à parcourir */ +    phys_t min;                             /* Borne minimale déterminée   */ +    phys_t max;                             /* Borne maximale déterminée   */ +    phys_t j;                               /* Boucle de parcours #3       */ +    bool status;                            /* Bilan d'une correspondance  */ + +    if (*skip) +        return; + +    /** +     * En lecture à rebourd, au moins un noeud a été solicité pour analyse (lors +     * du sens de lecteur normal). Donc l'initialisation a déjà dû avoir lieu. +     */ +    assert(are_pending_matches_initialized(matches)); + +    /** +     * Si les recherches associées au noeud ont été forcées, alors les traitements +     * liés ont déjà été effectués, et l'appel de cette fonction aurait dû être sauté. +     */ +#ifndef NDEBUG +    forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN); +    assert(!forced); +#endif + +    reset_pending_matches_ttl(matches); + +    pending_ptr = get_all_pending_matches(matches, &pcount); + +    ranges_ptr = get_node_search_offset_ranges(offset, &ocount); + +    for (p = 0; p < pcount; p++) +    { +        pending = (*pending_ptr) + p; + +        assert(matches->content_start <= pending->start); + +        before = pending->start - matches->content_start; + +        printf(" (masked) pending: %u - len=%u\n", +               (unsigned int)pending->start, (unsigned int)node->len); + +        new_begin = pending->start - node->len; + +        if (ocount > 0) +        { +            for (o = 0; o < ocount; o++) +            { +                range = (*ranges_ptr) + o; + +                /** +                 * Si bornes de tolérance il y a, l'espace restant est validé en +                 * tenant compte de ces bornes. +                 */ +                if (!get_node_offset_range(range, node->len, before, &min, &max)) +                { +                    if (not) +                        extend_pending_match_beginning(matches, p, pending->start - node->len); + +                    continue; + +                } + +                /** +                 * Une recherche des différentes correspondances amont est lancée. +                 */ +                for (j = min; j <= max; j++) +                { +                    status = check_scan_token_node_masked_content(node->bytes, node->len, +                                                                  new_begin - j, content); + +                    if ((status && !not) || (!status && not)) +                    { +                        /** +                         * S'il s'avère qu'il existe de multiples correspondances dans l'espace +                         * analysé, c'est la fonction extend_pending_match_beginning() qui +                         * duplique cette correspondance, en s'appuyant sur le TTL pour +                         * repérer ce cas de figure. +                         */ +                        extend_pending_match_beginning(matches, p, new_begin); + +                        /** +                         * Comme l'extension a pu conduire à un ajout et donc à une +                         * réallocation de la liste, on recharge l'élément pour les +                         * itérations suivantes. +                         */ +                        pending = (*pending_ptr) + p; + +                    } + +                } + +            } + +        } + +        else +        { +            /** +             * Si le début d'une correspondance potentielle est trop près du début +             * du contenu binaire et ne peut contenir le motif représenté, alors +             * la corresponance est écartée. +             */ +            if (node->len > before) +            { +                if (not) +                    extend_pending_match_beginning(matches, p, new_begin); + +                continue; + +            } + +            status = check_scan_token_node_masked_content(node->bytes, node->len, new_begin, content); + +            printf(" (masked) found new @ %llx ? %d\n", +                   (unsigned long long)new_begin, status); + + +            if ((status && !not) || (!status && not)) +                extend_pending_match_beginning(matches, p, new_begin); + +        } + +    } + +    purge_pending_matches(matches); + +    disable_all_ranges_in_node_search_offset(offset); + +} diff --git a/src/analysis/scan/patterns/tokens/nodes/masked.h b/src/analysis/scan/patterns/tokens/nodes/masked.h new file mode 100644 index 0000000..d1765fa --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/masked.h @@ -0,0 +1,72 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * masked.h - prototypes pour la gestion d'une recherche de motif partielle + * + * 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_PATTERNS_TOKENS_NODES_MASKED_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_MASKED_H + + +#include <glib-object.h> + + +#include "../atom.h" +#include "../node.h" +#include "../../../../../arch/archbase.h" + + + +#define G_TYPE_SCAN_TOKEN_NODE_MASKED            g_scan_token_node_masked_get_type() +#define G_SCAN_TOKEN_NODE_MASKED(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_MASKED, GScanTokenNodeMasked)) +#define G_IS_SCAN_TOKEN_NODE_MASKED(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_MASKED)) +#define G_SCAN_TOKEN_NODE_MASKED_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_MASKED, GScanTokenNodeMaskedClass)) +#define G_IS_SCAN_TOKEN_NODE_MASKED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_MASKED)) +#define G_SCAN_TOKEN_NODE_MASKED_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_MASKED, GScanTokenNodeMaskedClass)) + + +/* Bribe de motif partielle pour recherches (instance) */ +typedef struct _GScanTokenNodeMasked GScanTokenNodeMasked; + +/* Bribe de motif partielle pour recherches (classe) */ +typedef struct _GScanTokenNodeMaskedClass GScanTokenNodeMaskedClass; + + +/* Mémorisation d'un octet visé avec son masque */ +typedef struct _masked_byte_t +{ +    bin_t value;                            /* Valeur de l'octet visé      */ +    bin_t mask;                             /* Masque à appliquer          */ + +} masked_byte_t; + + +/* Indique le type défini pour un noeud représentant une bribe partielle à retrouver. */ +GType g_scan_token_node_masked_get_type(void); + +/* Construit une bribe de motif partielle. */ +GScanTokenNode *g_scan_token_node_masked_new(const masked_byte_t *); + +/* Enregistre la valeur d'octet à rechercher avec son masque. */ +void g_scan_token_node_masked_add(GScanTokenNodeMasked *, const masked_byte_t *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_MASKED_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/not-int.h b/src/analysis/scan/patterns/tokens/nodes/not-int.h new file mode 100644 index 0000000..5f92afd --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/not-int.h @@ -0,0 +1,57 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * not-int.h - prototypes internes pour l'inversion de résultats de correspondances établis + * + * 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_PATTERNS_TOKENS_NODES_NOT_INT_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_NOT_INT_H + + +#include "not.h" + + +#include "../node-int.h" + + + +/* Inversion de résultats de correspondances établis (instance) */ +struct _GScanTokenNodeNot +{ +    GScanTokenNode parent;                  /* A laisser en premier        */ + +    GScanTokenNode *child;                  /* Sous-noeud à considérer     */ + +}; + +/* Inversion de résultats de correspondances établis (classe) */ +struct _GScanTokenNodeNotClass +{ +    GScanTokenNodeClass parent;             /* A laisser en premier        */ + +}; + + +/* Met en place une inversion de résultats de correspondances. */ +bool g_scan_token_node_not_create(GScanTokenNodeNot *, GScanTokenNode *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_NOT_INT_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/not.c b/src/analysis/scan/patterns/tokens/nodes/not.c new file mode 100644 index 0000000..c54a66f --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/not.c @@ -0,0 +1,364 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * not.c - inversion de résultats de correspondances établis + * + * 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 "not.h" + + +#include "not-int.h" + + + +/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */ + + +/* Initialise la classe des inversions de correspondances. */ +static void g_scan_token_node_not_class_init(GScanTokenNodeNotClass *); + +/* Initialise une instance d'inversion de correspondances. */ +static void g_scan_token_node_not_init(GScanTokenNodeNot *); + +/* Supprime toutes les références externes. */ +static void g_scan_token_node_not_dispose(GScanTokenNodeNot *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_token_node_not_finalize(GScanTokenNodeNot *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Parcourt une arborescence de noeuds et y relève des éléments. */ +static void g_scan_token_node_not_visit(GScanTokenNodeNot *, scan_tree_points_t *); + +/* Inscrit la définition d'un motif dans un moteur de recherche. */ +static bool g_scan_token_node_not_enroll(GScanTokenNodeNot *, GScanContext *, GEngineBackend *, size_t, size_t *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_not_check_backward(const GScanTokenNodeNot *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une inversion des résultats de correspondances. */ +G_DEFINE_TYPE(GScanTokenNodeNot, g_scan_token_node_not, G_TYPE_SCAN_TOKEN_NODE); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des inversions de correspondances.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_not_class_init(GScanTokenNodeNotClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GScanTokenNodeClass *node;              /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_not_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_not_finalize; + +    node = G_SCAN_TOKEN_NODE_CLASS(klass); + +    node->visit = (visit_scan_token_node_fc)g_scan_token_node_not_visit; +    node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_not_enroll; +    node->check_forward = (check_scan_token_node_fc)g_scan_token_node_not_check_forward; +    node->check_backward = (check_scan_token_node_fc)g_scan_token_node_not_check_backward; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : not = instance à initialiser.                                * +*                                                                             * +*  Description : Initialise une instance d'inversion de correspondances.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_not_init(GScanTokenNodeNot *not) +{ +    not->child = NULL; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : not = instance d'objet GLib à traiter.                       * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_not_dispose(GScanTokenNodeNot *not) +{ +    g_clear_object(¬->child); + +    G_OBJECT_CLASS(g_scan_token_node_not_parent_class)->dispose(G_OBJECT(not)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : not = instance d'objet GLib à traiter.                       * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_not_finalize(GScanTokenNodeNot *not) +{ +    G_OBJECT_CLASS(g_scan_token_node_not_parent_class)->finalize(G_OBJECT(not)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : child = noeud dont les résultats sont à écarter.             * +*                                                                             * +*  Description : Construit une inversion de résultats de correspondances.     * +*                                                                             * +*  Retour      : Mécanismes mis en place.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanTokenNode *g_scan_token_node_not_new(GScanTokenNode *child) +{ +    GScanTokenNode *result;                 /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_TOKEN_NODE_NOT, NULL); + +    if (!g_scan_token_node_not_create(G_SCAN_TOKEN_NODE_NOT(result), child)) +        g_clear_object(&result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : not   = encadrement d'inversion à initialiser pleinement.    * +*                child = noeud dont les résultats sont à écarter.             * +*                                                                             * +*  Description : Met en place une inversion de résultats de correspondances.  * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_token_node_not_create(GScanTokenNodeNot *not, GScanTokenNode *child) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    not->child = child; +    g_object_ref(G_OBJECT(child)); + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node   = point de départ du parcours à effectuer.            * +*                points = points capitaux de l'arborescence. [OUT]            * +*                                                                             * +*  Description : Parcourt une arborescence de noeuds et y relève des éléments.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_not_visit(GScanTokenNodeNot *node, scan_tree_points_t *points) +{ +    g_scan_token_node_visit(node->child, points); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à enregistrer.              * +*                context = contexte de l'analyse à mener.                     * +*                backend = moteur de recherche à préchauffer.                 * +*                maxsize = taille max. des atomes (mise en commun optimisée). * +*                slow    = niveau de ralentissement induit (0 = idéal). [OUT] * +*                                                                             * +*  Description : Inscrit la définition d'un motif dans un moteur de recherche.* +*                                                                             * +*  Retour      : Bilan de l'opération à renvoyer.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_token_node_not_enroll(GScanTokenNodeNot *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow) +{ +    bool result;                            /* Statut à retourner          */ + +    result = _g_scan_token_node_enroll(node->child, context, backend, maxsize, slow); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_not_check_forward(const GScanTokenNodeNot *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +    bool initialized;                       /* Initialisation du suivi ?   */ +    phys_t i;                               /* Boucle de parcours          */ + + +    /* + +      ????????????????????????? + + +    if (*skip) +        return; +    */ + + + +    initialized = are_pending_matches_initialized(matches); + + +    printf("TOTO......(init done? %d)\n", initialized); + + + +    if (!initialized) +    { +        for (i = matches->content_start; i < matches->content_end; i++) +            add_pending_match(matches, i, 0); + +        set_pending_matches_initialized(matches); + +    } + +    _g_scan_token_node_check_forward(node->child, context, content, matches, offset, !not, skip); + + + + + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_not_check_backward(const GScanTokenNodeNot *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ + + + +    if (*skip) +        return; + + + +    printf("TODO\n"); +    assert(0); + + + +} diff --git a/src/analysis/scan/patterns/tokens/nodes/not.h b/src/analysis/scan/patterns/tokens/nodes/not.h new file mode 100644 index 0000000..58630e8 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/not.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * not.h - prototypes pour l'inversion de résultats de correspondances établis + * + * 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_PATTERNS_TOKENS_NODES_NOT_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_NOT_H + + +#include <glib-object.h> + + +#include "../node.h" +#include "../../../../../arch/archbase.h" + + + +#define G_TYPE_SCAN_TOKEN_NODE_NOT            g_scan_token_node_not_get_type() +#define G_SCAN_TOKEN_NODE_NOT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_NOT, GScanTokenNodeNot)) +#define G_IS_SCAN_TOKEN_NODE_NOT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_NOT)) +#define G_SCAN_TOKEN_NODE_NOT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_NOT, GScanTokenNodeNotClass)) +#define G_IS_SCAN_TOKEN_NODE_NOT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_NOT)) +#define G_SCAN_TOKEN_NODE_NOT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_NOT, GScanTokenNodeNotClass)) + + +/* Inversion de résultats de correspondances établis (instance) */ +typedef struct _GScanTokenNodeNot GScanTokenNodeNot; + +/* Inversion de résultats de correspondances établis (classe) */ +typedef struct _GScanTokenNodeNotClass GScanTokenNodeNotClass; + + +/* Indique le type défini pour une inversion des résultats de correspondances. */ +GType g_scan_token_node_not_get_type(void); + +/* Construit une inversion de résultats de correspondances. */ +GScanTokenNode *g_scan_token_node_not_new(GScanTokenNode *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_NOT_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/plain-int.h b/src/analysis/scan/patterns/tokens/nodes/plain-int.h index a38359d..2077c6f 100644 --- a/src/analysis/scan/patterns/tokens/nodes/plain-int.h +++ b/src/analysis/scan/patterns/tokens/nodes/plain-int.h @@ -28,8 +28,8 @@  #include "plain.h" -#include "../node-int.h"  #include "../atom.h" +#include "../node-int.h" @@ -56,7 +56,7 @@ struct _GScanTokenNodePlainClass  }; -/* Met en place un un noeud représentant un motif textuel. */ +/* Met en place un noeud représentant un motif textuel. */  bool g_scan_token_node_plain_create(GScanTokenNodePlain *, const sized_binary_t *, GScanTokenModifier *, ScanPlainNodeFlags); diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.c b/src/analysis/scan/patterns/tokens/nodes/plain.c index ee87c73..5a7f976 100644 --- a/src/analysis/scan/patterns/tokens/nodes/plain.c +++ b/src/analysis/scan/patterns/tokens/nodes/plain.c @@ -24,7 +24,11 @@  #include "plain.h" +#include <assert.h> + +  #include "plain-int.h" +#include "../../../../../common/extstr.h" @@ -32,7 +36,7 @@  /* Initialise la classe des noeuds pour motif textuel. */ -static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass); +static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *);  /* Initialise une instance de noeud pour motif textuel. */  static void g_scan_token_node_plain_init(GScanTokenNodePlain *); @@ -48,14 +52,20 @@ static void g_scan_token_node_plain_finalize(GScanTokenNodePlain *);  /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Parcourt une arborescence de noeuds et y relève des éléments. */ +static void g_scan_token_node_plain_visit(GScanTokenNodePlain *, scan_tree_points_t *); +  /* Inscrit la définition d'un motif dans un moteur de recherche. */ -static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *, GScanContext *, GEngineBackend *, size_t ); +static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *, GScanContext *, GEngineBackend *, size_t, size_t *);  /* Détermine si un contenu d'intérêt est présent à une position. */ -static bool check_scan_token_node_plain_content(const sized_binary_t *, const tracked_scan_atom_t *, phys_t, GBinContent *); +static bool check_scan_token_node_plain_content(const sized_binary_t *, const tracked_scan_atom_t *, bool, phys_t, GBinContent *);  /* Transforme les correspondances locales en trouvailles. */ -static void g_scan_plain_bytes_check(const GScanTokenNodePlain *, GScanContext *, GBinContent *, pending_matches_t *, const node_search_offset_t *); +static void g_scan_token_node_plain_check_forward(const GScanTokenNodePlain *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_plain_check_backward(const GScanTokenNodePlain *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); @@ -92,8 +102,10 @@ static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass)      node = G_SCAN_TOKEN_NODE_CLASS(klass); +    node->visit = (visit_scan_token_node_fc)g_scan_token_node_plain_visit;      node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_plain_enroll; -    node->check = (check_scan_token_node_fc)g_scan_plain_bytes_check; +    node->check_forward = (check_scan_token_node_fc)g_scan_token_node_plain_check_forward; +    node->check_backward = (check_scan_token_node_fc)g_scan_token_node_plain_check_backward;  } @@ -112,6 +124,8 @@ static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass)  static void g_scan_token_node_plain_init(GScanTokenNodePlain *plain)  { +    g_scan_token_node_set_flags(G_SCAN_TOKEN_NODE(plain), STNF_PROD); +      init_szstr(&plain->orig);      plain->modifier = NULL;      plain->flags = SPNF_NONE; @@ -203,6 +217,7 @@ GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *text, GScanTok  } +  /******************************************************************************  *                                                                             *  *  Paramètres  : plain    = encadrement de motif à initialiser pleinement.    * @@ -210,7 +225,7 @@ GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *text, GScanTok  *                modifier = transformateur éventuel à solliciter.             *  *                flags    = particularités à prendre en considération.        *  *                                                                             * -*  Description : Met en place un un noeud représentant un motif textuel.      * +*  Description : Met en place un noeud représentant un motif textuel.         *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        *  *                                                                             * @@ -239,6 +254,29 @@ bool g_scan_token_node_plain_create(GScanTokenNodePlain *plain, const sized_bina  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : plain = noeud de motif textuel à consulter.                  * +*                                                                             * +*  Description : Indique les propriétés particulières d'un noeud de texte.    * +*                                                                             * +*  Retour      : Propriétés particulières associées au noeud.                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +ScanPlainNodeFlags g_scan_token_node_plain_get_flags(const GScanTokenNodePlain *plain) +{ +    ScanPlainNodeFlags result;              /* Statut à retourner          */ + +    result = plain->flags; + +    return result; + +} + +  /* ---------------------------------------------------------------------------------- */  /*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ @@ -247,10 +285,32 @@ bool g_scan_token_node_plain_create(GScanTokenNodePlain *plain, const sized_bina  /******************************************************************************  *                                                                             * +*  Paramètres  : node   = point de départ du parcours à effectuer.            * +*                points = points capitaux de l'arborescence. [OUT]            * +*                                                                             * +*  Description : Parcourt une arborescence de noeuds et y relève des éléments.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_plain_visit(GScanTokenNodePlain *node, scan_tree_points_t *points) +{ +    if (points->first_plain == NULL) +        points->first_plain = G_SCAN_TOKEN_NODE(node); + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : node    = définition de la bribe à enregistrer.              *  *                context = contexte de l'analyse à mener.                     *  *                backend = moteur de recherche à préchauffer.                 *  *                maxsize = taille max. des atomes (mise en commun optimisée). * +*                slow    = niveau de ralentissement induit (0 = idéal). [OUT] *  *                                                                             *  *  Description : Inscrit la définition d'un motif dans un moteur de recherche.*  *                                                                             * @@ -260,7 +320,7 @@ bool g_scan_token_node_plain_create(GScanTokenNodePlain *plain, const sized_bina  *                                                                             *  ******************************************************************************/ -static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanContext *context, GEngineBackend *backend, size_t maxsize) +static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow)  {      bool result;                            /* Statut à retourner          */      size_t i;                               /* Boucle de parcours #1       */ @@ -312,13 +372,14 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte              if (letters == 0)                  node->atoms[i] = atom; -            /* Insertion des combinaisons pour couvrir toutes les casses */ +            /* Insertion des nouvelles combinaisons pour couvrir toutes les casses */              else              { -                for (k = 0, extra_count = 1; k < letters; k++, extra_count *= 2) +                /* extra_count = 2^letters */ +                for (k = 1, extra_count = 2; k < letters; k++, extra_count *= 2)                      ; -                extra = make_atoms_case_insensitive(&node->raw[i], extra_count); +                extra = make_atoms_case_insensitive(&node->raw[i], &atom, extra_count);                  remaining = node->count - i - 1; @@ -333,7 +394,7 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte                  free(extra); -                node->atoms = realloc(node->raw, node->count * sizeof(tracked_scan_atom_t)); +                node->atoms = realloc(node->atoms, node->count * sizeof(tracked_scan_atom_t));                  for (k = 0; k < extra_count; k++)                      node->atoms[i + k] = atom; @@ -365,6 +426,7 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte  *                                                                             *  *  Paramètres  : raw     = contneu brut à retrouver idéalement.               *  *                atom    = contenu brut représentatif ciblé.                  * +*                nocase  = marque un éventuel désintérêt pour la casse.       *  *                start   = point d'analyse à respecter.                       *  *                content = accès au contenu brut pour vérifications (optim.)  *  *                                                                             * @@ -376,7 +438,7 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte  *                                                                             *  ******************************************************************************/ -static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const tracked_scan_atom_t *atom, phys_t start, GBinContent *content) +static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const tracked_scan_atom_t *atom, bool nocase, phys_t start, GBinContent *content)  {      bool result;                            /* Bilan à retourner           */      vmpa2t pos;                             /* Position dans les données   */ @@ -393,7 +455,11 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const      {          ptr = g_binary_content_get_raw_access(content, &pos, atom->pos); -        ret = memcmp(raw->data, ptr, atom->pos); +        if (nocase) +            ret = memcasecmp(raw->data, ptr, atom->pos); +        else +            ret = memcmp(raw->data, ptr, atom->pos); +          if (ret != 0) goto done;      } @@ -406,7 +472,11 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const          ptr = g_binary_content_get_raw_access(content, &pos, atom->rem); -        ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem); +        if (nocase) +            ret = memcasecmp(raw->data + atom->pos + atom->len, ptr, atom->rem); +        else +            ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem); +          if (ret != 0) goto done;      } @@ -427,6 +497,8 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const  *                content = accès au contenu brut pour vérifications (optim.)  *  *                matches = suivi des correspondances à consolider.            *  *                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         *  *                                                                             *  *  Description : Transforme les correspondances locales en trouvailles.       *  *                                                                             * @@ -436,22 +508,33 @@ static bool check_scan_token_node_plain_content(const sized_binary_t *raw, const  *                                                                             *  ******************************************************************************/ -static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, const node_search_offset_t *offset) +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 nocase;                            /* Pas d'intérêt pour la casse */ +    size_t ocount;                          /* Quantité de bornes présentes*/      size_t i;                               /* Boucle de parcours #1       */      const sized_binary_t *raw;              /* Données brutes d'origine    */      const tracked_scan_atom_t *atom;        /* Atome correspondant         */      size_t count;                           /* Quantité de bribes trouvées */      const phys_t *found;                    /* Localisations des bribes    */      size_t k;                               /* Boucle de parcours #2       */ -    phys_t start;                           /* Point de départ             */ +    phys_t new_begin;                       /* Nouveau départ à tester     */      bool status;                            /* Bilan d'une correspondance  */      size_t pcount;                          /* Nombre de correspondances   */ +    match_area_t * const *pending_ptr;      /* Correspondances actuelles   */      size_t p;                               /* Boucle de parcours #3       */ +    const match_area_t *pending;            /* Correspondance à traiter    */ + +    if (*skip) +        return;      initialized = are_pending_matches_initialized(matches); +    nocase = (node->flags & SPNF_CASE_INSENSITIVE); + +    get_node_search_offset_ranges(offset, &ocount); +      for (i = 0; i < node->count; i++)      {          raw = &node->raw[i]; @@ -463,28 +546,34 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte          {              for (k = 0; k < count; k++)              { -                start = found[k] - atom->pos; +                new_begin = found[k] - atom->pos;                  /**                   * Si personne n'a manipulé les pré-résultats, mais qu'un décallage                   * est spécifié par un noeud précédent, une validation sur la base                   * d'une position 0 est menée.                   */ -                if (offset != NULL) +                if (ocount > 0)                  { -                    if (start < offset->min || start > offset->max) +                    if (!does_node_search_offset_include_pos_forward(offset, 0, new_begin)) +                    { +                        if (not) +                            add_pending_match(matches, new_begin, raw->len); +                          continue; + +                    }                  } -                status = check_scan_token_node_plain_content(raw, atom, start, content); +                status = check_scan_token_node_plain_content(raw, atom, nocase, new_begin, content); -                if (status) +                if ((status && !not) || (!status && not))                      /**                       * Il ne peut y avoir qu'une seule séquence d'octets à un même -                     * emplacement, donc le couple (start, len) enregistré est +                     * emplacement, donc le couple (new_begin, len) enregistré est                       * unique.                       */ -                    add_pending_match(matches, start, raw->len); +                    add_pending_match(matches, new_begin, raw->len);              } @@ -494,12 +583,17 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte          {              reset_pending_matches_ttl(matches); -            pcount = count_pending_matches(matches); +            pending_ptr = get_all_pending_matches(matches, &pcount);              for (p = 0; p < pcount; p++) +            { +                pending = (*pending_ptr) + p; + +                assert(matches->content_start <= pending->start); +                  for (k = 0; k < count; k++)                  { -                    start = found[k] - atom->pos; +                    new_begin = found[k] - atom->pos;                      /**                       * Si bornes de tolérance il y a, on valide la position. @@ -507,20 +601,52 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte                       * Sinon les correspondances passées et actuelle doivent                       * être jointes.                       */ -                    if (offset != NULL) +                    if (ocount > 0)                      { -                        if (!has_pending_match_ending_between(matches, p, start, offset->min, offset->max)) +                        if (!does_node_search_offset_include_pos_forward(offset, pending->end, new_begin)) +                        { +                            if (not) +                            { +                                extend_pending_match_ending(matches, p, pending->end + raw->len); + +                                /** +                                 * Comme l'extension a pu conduire à un ajout et donc à une +                                 * réallocation de la liste, on recharge l'élément pour les +                                 * itérations suivantes. +                                 */ +                                pending = (*pending_ptr) + p; + +                            } +                              continue; + +                        }                      }                      else                      { -                        if (!has_pending_match_ending_at(matches, p, start)) +                        if (pending->end != new_begin) +                        { +                            if (not) +                            { +                                extend_pending_match_ending(matches, p, pending->end + raw->len); + +                                /** +                                 * Comme l'extension a pu conduire à un ajout et donc à une +                                 * réallocation de la liste, on recharge l'élément pour les +                                 * itérations suivantes. +                                 */ +                                pending = (*pending_ptr) + p; + +                            } +                              continue; + +                        }                      } -                    status = check_scan_token_node_plain_content(raw, atom, start, content); +                    status = check_scan_token_node_plain_content(raw, atom, nocase, new_begin, content); -                    if (status) +                    if ((status && !not) || (!status && not))                      {                          /**                           * Même si une base de couples uniques est assurée, @@ -559,18 +685,28 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte                          /**                           * La seconde situation est prise en compte par la fonction -                         * extend_pending_match() qui s'appuie sur le TTL pour dupliquer -                         * la correspondance pending[x] initiale. Le nouvel élément est -                         * placé en fin de liste, ce qui ne boulverse pas le parcours -                         * de liste courant, la valeur de pcount n'étant pas actualisée. +                         * extend_pending_match_ending() qui s'appuie sur le TTL pour +                         * dupliquer la correspondance pending[x] initiale. Le nouvel +                         * élément est placé en fin de liste, ce qui ne boulverse pas +                         * le parcours de liste courant, la valeur de pcount n'étant +                         * pas actualisée.                           */ -                        extend_pending_match(matches, p, start + raw->len); +                        extend_pending_match_ending(matches, p, new_begin + raw->len); + +                        /** +                         * Comme l'extension a pu conduire à un ajout et donc à une +                         * réallocation de la liste, on recharge l'élément pour les +                         * itérations suivantes. +                         */ +                        pending = (*pending_ptr) + p;                      }                  } +            } +              purge_pending_matches(matches);          } @@ -579,4 +715,42 @@ static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanConte      set_pending_matches_initialized(matches); +    disable_all_ranges_in_node_search_offset(offset); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_plain_check_backward(const GScanTokenNodePlain *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ + + + +    if (*skip) +        return; + + + +    printf("TODO\n"); +    assert(0); + + +  } diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.h b/src/analysis/scan/patterns/tokens/nodes/plain.h index 33e7feb..c8f3920 100644 --- a/src/analysis/scan/patterns/tokens/nodes/plain.h +++ b/src/analysis/scan/patterns/tokens/nodes/plain.h @@ -52,9 +52,16 @@ typedef struct _GScanTokenNodePlainClass GScanTokenNodePlainClass;  /* Propriétés d'un élément textuel à rechercher */  typedef enum _ScanPlainNodeFlags  { -    SPNF_NONE             = 0x0,            /* Aucune particularité        */ -    SPNF_CASE_INSENSITIVE = 0x1,            /* Ignorance de la casse       */ -    SPNF_FULL_WORD        = 0x2,            /* Recherche de mot entier     */ +    SPNF_NONE             = (0 << 0),       /* Aucune particularité        */ +    SPNF_CASE_INSENSITIVE = (1 << 0),       /* Ignorance de la casse       */ + +    /** +     * Les deux propriétés suivantes sont récupérées et traitées +     * au niveau du Token propriétaire. +     */ + +    SPNF_FULLWORD         = (1 << 1),       /* Recherche de mot entier     */ +    SPNF_PRIVATE          = (1 << 2),       /* Marque privative            */  } ScanPlainNodeFlags; @@ -65,6 +72,9 @@ GType g_scan_token_node_plain_get_type(void);  /* Construit un noeud représentant un motif textuel. */  GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *, GScanTokenModifier *, ScanPlainNodeFlags); +/* Indique les propriétés particulières d'un noeud de texte. */ +ScanPlainNodeFlags g_scan_token_node_plain_get_flags(const GScanTokenNodePlain *); +  #endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/sequence-int.h b/src/analysis/scan/patterns/tokens/nodes/sequence-int.h new file mode 100644 index 0000000..f0ea6ae --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/sequence-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sequence-int.h - prototypes internes pour des décompositions séquentielles de motif de recherche + * + * 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_PATTERNS_TOKENS_NODES_SEQUENCE_INT_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_SEQUENCE_INT_H + + +#include "sequence.h" + + +#include "../node-int.h" + + + +/* Décompositions séquentielles de motif de recherche (instance) */ +struct _GScanTokenNodeSequence +{ +    GScanTokenNode parent;                  /* A laisser en premier        */ + +    GScanTokenNode **children;              /* Sous-noeuds à représenter   */ +    size_t count;                           /* Taille de cette liste       */ + +}; + +/* Décompositions séquentielles de motif de recherche (classe) */ +struct _GScanTokenNodeSequenceClass +{ +    GScanTokenNodeClass parent;             /* A laisser en premier        */ + +}; + + +/* Met en place une série de décompositions séquentielles. */ +bool g_scan_token_node_sequence_create(GScanTokenNodeSequence *, GScanTokenNode *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_SEQUENCE_INT_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/sequence.c b/src/analysis/scan/patterns/tokens/nodes/sequence.c new file mode 100644 index 0000000..ad332fc --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/sequence.c @@ -0,0 +1,360 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sequence.c - décompositions séquentielles de motif de recherche + * + * 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 "sequence.h" + + +#include "sequence-int.h" + + + +/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */ + + +/* Initialise la classe des décompositions séquentielles. */ +static void g_scan_token_node_sequence_class_init(GScanTokenNodeSequenceClass *); + +/* Initialise une instance de décompositions séquentielles. */ +static void g_scan_token_node_sequence_init(GScanTokenNodeSequence *); + +/* Supprime toutes les références externes. */ +static void g_scan_token_node_sequence_dispose(GScanTokenNodeSequence *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_token_node_sequence_finalize(GScanTokenNodeSequence *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Parcourt une arborescence de noeuds et y relève des éléments. */ +static void g_scan_token_node_sequence_visit(GScanTokenNodeSequence *node, scan_tree_points_t *); + +/* Inscrit la définition d'un motif dans un moteur de recherche. */ +static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *, GScanContext *, GEngineBackend *, size_t, size_t *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_sequence_check_forward(const GScanTokenNodeSequence *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_scan_token_node_sequence_check_backward(const GScanTokenNodeSequence *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                          DECOMPOSITION DE MOTIF RECHERCHE                          */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour des décompositions séquentielles de motif de recherche. */ +G_DEFINE_TYPE(GScanTokenNodeSequence, g_scan_token_node_sequence, G_TYPE_SCAN_TOKEN_NODE); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des décompositions séquentielles.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_sequence_class_init(GScanTokenNodeSequenceClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GScanTokenNodeClass *node;              /* Version de classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_sequence_dispose; +    object->finalize = (GObjectFinalizeFunc)g_scan_token_node_sequence_finalize; + +    node = G_SCAN_TOKEN_NODE_CLASS(klass); + +    node->visit = (visit_scan_token_node_fc)g_scan_token_node_sequence_visit; +    node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_sequence_enroll; +    node->check_forward = (check_scan_token_node_fc)g_scan_token_node_sequence_check_forward; +    node->check_backward = (check_scan_token_node_fc)g_scan_token_node_sequence_check_backward; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : sequence = instance à initialiser.                           * +*                                                                             * +*  Description : Initialise une instance de décompositions séquentielles.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_sequence_init(GScanTokenNodeSequence *sequence) +{ +    sequence->children = NULL; +    sequence->count = 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : sequence = instance d'objet GLib à traiter.                  * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_sequence_dispose(GScanTokenNodeSequence *sequence) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < sequence->count; i++) +        g_clear_object(&sequence->children[i]); + +    G_OBJECT_CLASS(g_scan_token_node_sequence_parent_class)->dispose(G_OBJECT(sequence)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : sequence = instance d'objet GLib à traiter.                  * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_sequence_finalize(GScanTokenNodeSequence *sequence) +{ +    if (sequence->children != NULL) +        free(sequence->children); + +    G_OBJECT_CLASS(g_scan_token_node_sequence_parent_class)->finalize(G_OBJECT(sequence)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : child    = noeud dont les résultats sont à écarter.          * +*                                                                             * +*  Description : Construit une série de décompositions séquentielles de motif.* +*                                                                             * +*  Retour      : Mécanismes mis en place.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GScanTokenNode *g_scan_token_node_sequence_new(GScanTokenNode *child) +{ +    GScanTokenNode *result;                 /* Structure à retourner       */ + +    result = g_object_new(G_TYPE_SCAN_TOKEN_NODE_SEQUENCE, NULL); + +    if (!g_scan_token_node_sequence_create(G_SCAN_TOKEN_NODE_SEQUENCE(result), child)) +        g_clear_object(&result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : sequence = décompositions à initialiser pleinement.          * +*                child    = noeud dont les résultats sont à écarter.          * +*                                                                             * +*  Description : Met en place une série de décompositions séquentielles.      * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_scan_token_node_sequence_create(GScanTokenNodeSequence *sequence, GScanTokenNode *child) +{ +    bool result;                            /* Bilan à retourner           */ + +    result = true; + +    g_scan_token_node_sequence_add(sequence, child); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : sequence = ensemble de noeuds à compléter.                   * +*                child  = nouveau noeud à intégrer.                           * +*                                                                             * +*  Description : Ajoute un noeud à aux décompositions séquentielles de motif. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_scan_token_node_sequence_add(GScanTokenNodeSequence *sequence, GScanTokenNode *child) +{ +    sequence->children = realloc(sequence->children, ++sequence->count * sizeof(GScanTokenNode *)); + +    sequence->children[sequence->count - 1] = child; +    g_object_ref(G_OBJECT(child)); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node   = point de départ du parcours à effectuer.            * +*                points = points capitaux de l'arborescence. [OUT]            * +*                                                                             * +*  Description : Parcourt une arborescence de noeuds et y relève des éléments.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_sequence_visit(GScanTokenNodeSequence *node, scan_tree_points_t *points) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < node->count; i++) +        g_scan_token_node_visit(node->children[i], points); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à enregistrer.              * +*                context = contexte de l'analyse à mener.                     * +*                backend = moteur de recherche à préchauffer.                 * +*                maxsize = taille max. des atomes (mise en commun optimisée). * +*                slow    = niveau de ralentissement induit (0 = idéal). [OUT] * +*                                                                             * +*  Description : Inscrit la définition d'un motif dans un moteur de recherche.* +*                                                                             * +*  Retour      : Bilan de l'opération à renvoyer.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_scan_token_node_sequence_enroll(GScanTokenNodeSequence *node, GScanContext *context, GEngineBackend *backend, size_t maxsize, size_t *slow) +{ +    bool result;                            /* Statut à retourner          */ +    size_t i;                               /* Boucle de parcours          */ + +    result = true; + +    for (i = 0; i < node->count && result; i++) +        result = _g_scan_token_node_enroll(node->children[i], context, backend, maxsize, slow); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_sequence_check_forward(const GScanTokenNodeSequence *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < node->count; i++) +        _g_scan_token_node_check_forward(node->children[i], context, content, matches, offset, not, skip); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : node    = définition de la bribe à manipuler.                * +*                context = contexte de l'analyse à mener.                     * +*                content = accès au contenu brut pour vérifications (optim.)  * +*                matches = suivi des correspondances à consolider.            * +*                offset  = tolérance dans les positions à appliquer.          * +*                not     = indique si les résultats doivent être inversés.    * +*                skip    = détermine si l'analyse est différée. [OUT]         * +*                                                                             * +*  Description : Transforme les correspondances locales en trouvailles.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_scan_token_node_sequence_check_backward(const GScanTokenNodeSequence *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = node->count; i > 0 ; i--) +        _g_scan_token_node_check_backward(node->children[i - 1], context, content, matches, offset, not, skip); + +} diff --git a/src/analysis/scan/patterns/tokens/nodes/sequence.h b/src/analysis/scan/patterns/tokens/nodes/sequence.h new file mode 100644 index 0000000..fc181c6 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/nodes/sequence.h @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sequence.h - prototypes pour des décompositions séquentielles de motif de recherche + * + * 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_PATTERNS_TOKENS_NODES_SEQUENCE_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_SEQUENCE_H + + +#include <glib-object.h> + + +#include "../node.h" + + + +#define G_TYPE_SCAN_TOKEN_NODE_SEQUENCE            g_scan_token_node_sequence_get_type() +#define G_SCAN_TOKEN_NODE_SEQUENCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_SEQUENCE, GScanTokenNodeSequence)) +#define G_IS_SCAN_TOKEN_NODE_SEQUENCE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_SEQUENCE)) +#define G_SCAN_TOKEN_NODE_SEQUENCE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_SEQUENCE, GScanTokenNodeSequenceClass)) +#define G_IS_SCAN_TOKEN_NODE_SEQUENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_SEQUENCE)) +#define G_SCAN_TOKEN_NODE_SEQUENCE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_SEQUENCE, GScanTokenNodeSequenceClass)) + + +/* Décompositions séquentielles de motif de recherche (instance) */ +typedef struct _GScanTokenNodeSequence GScanTokenNodeSequence; + +/* Décompositions séquentielles de motif de recherche (classe) */ +typedef struct _GScanTokenNodeSequenceClass GScanTokenNodeSequenceClass; + + +/* Indique le type défini pour des décompositions séquentielles de motif de recherche. */ +GType g_scan_token_node_sequence_get_type(void); + +/* Construit une série de décompositions séquentielles de motif. */ +GScanTokenNode *g_scan_token_node_sequence_new(GScanTokenNode *); + +/* Ajoute un noeud à aux décompositions séquentielles de motif. */ +void g_scan_token_node_sequence_add(GScanTokenNodeSequence *, GScanTokenNode *); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_SEQUENCE_H */ diff --git a/src/analysis/scan/patterns/tokens/offset.c b/src/analysis/scan/patterns/tokens/offset.c new file mode 100644 index 0000000..010ec67 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/offset.c @@ -0,0 +1,352 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * offset.c - décomposition d'un motif de recherche en atomes assemblés + * + * 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 "offset.h" + + +#include <assert.h> + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : range     = bornes décrivant un espace quelconque.           * +*                available = espace restant disponible.                       * +*                min       = point de départ pour parcourir une zone. [OUT]   * +*                max       = point d'arrivée pour parcourir une zone. [OUT]   * +*                                                                             * +*  Description : Fournit les bornes d'une zone à analyser.                    * +*                                                                             * +*  Retour      : true si assez d'espace est disponible, false sinon.          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool get_node_offset_range(const node_offset_range_t *range, phys_t len, phys_t available, phys_t *min, phys_t *max) +{ +    bool result;                            /* Bilan à retourner           */ + +    if ((len + range->min) > available) +        result = false; + +    else +    { +        result = true; + +        *min = range->min; +        *max = range->max; + +        if ((len + *max) > available) +        { +            *max = available - len; +            assert(*max >= *min); +        } + +    } + +    return result; + +} + + + + + + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : offset = suivi de tolérances bornées à initialiser.          * +*                                                                             * +*  Description : Initialise une mémorisation d'intervales de tolérance.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void init_node_search_offset(node_search_offset_t *offset) +{ +    offset->ranges = NULL; +    offset->allocated = 0; + +    offset->gen_ptr = NULL; + +    offset->used = 0; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : dest = suivi de tolérances bornées à initialiser. [OUT]      * +*                src  = suivi de tolérances bornées à copier.                 * +*                                                                             * +*  Description : Copie une mémorisation d'intervales entre positions.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void copy_node_search_offset(node_search_offset_t *dest, const node_search_offset_t *src) +{ +    init_node_search_offset(dest); + +    switch (src->used) +    { +        case 0: +            dest->gen_ptr = NULL; +            break; + +        case 1: +            dest->range = src->range; +            dest->gen_ptr = &dest->range; +            break; + +        default: +            dest->ranges = malloc(src->used * sizeof(node_offset_range_t)); +            memcpy(dest->ranges, src->ranges, src->used * sizeof(node_offset_range_t)); +            dest->gen_ptr = dest->ranges;; +            break; + +    } + +    dest->used = src->used; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : dest = suivi de tolérances bornées à initialiser. [OUT]      * +*                src  = suivi de tolérances bornées à copier.                 * +*                                                                             * +*  Description : Fusionne une mémorisation d'intervales entre positions.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void merge_node_search_offset(node_search_offset_t *dest, const node_search_offset_t *src) +{ +    node_offset_range_t * const *list;      /* Liste d'intervales à copier */ +    size_t i;                               /* Boucle de parcours          */ + +    if ((dest->used + src->used) > 1 && (dest->used + src->used) > dest->allocated) +    { +        dest->allocated += src->used; + +        dest->ranges = realloc(dest->ranges, dest->allocated * sizeof(node_offset_range_t)); + +    } + +    list = get_node_search_offset_ranges(src, (size_t []){ 0 }); + +    for (i = 0; i < src->used; i++) +        add_range_to_node_search_offset(dest, (*list)[i].min, (*list)[i].max, NULL); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : offset = suivi de tolérances bornées à terminer.             * +*                                                                             * +*  Description : Met fin à une mémorisation d'intervales de tolérance.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void exit_node_search_offset(node_search_offset_t *offset) +{ +    if (offset->ranges != NULL) +        free(offset->ranges); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : offset = suivi de tolérances bornées à consulter.            * +*                count  = nombre de bornes enregistrées. [OUT]                * +*                                                                             * +*  Description : Fournit la liste des tolérances bornées établies à présent.  * +*                                                                             * +*  Retour      : Liste d'intervales en lecture seule.                         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +node_offset_range_t * const *get_node_search_offset_ranges(const node_search_offset_t *offset, size_t *count) +{ +    node_offset_range_t * const *result;    /* Série à renvoyer            */ + +    result = &offset->gen_ptr; + +    *count = offset->used; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : offset   = suivi de tolérances bornées à consulter.          * +*                min      = point de départ pour parcourir une zone.          * +*                max      = point d'arrivée pour parcourir une zone.          * +*                datasize = taille maximale pour définir une inversion NOT.   * +*                                                                             * +*  Description : Ajoute un nouvel espace borné aux décalages tolérés.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void add_range_to_node_search_offset(node_search_offset_t *offset, phys_t min, phys_t max, const phys_t *datasize) +{ +    bool not;                               /* Traduction de la taille     */ +    size_t needed;                          /* Nombre d'emplacements requis*/ + +    not = (datasize != NULL); + +    /* Si le réceptacle unique peut être employé... */ +    if (offset->used == 0 && !not) +    { +        offset->range.min = min; +        offset->range.max = max; + +        offset->used = 1; + +        offset->gen_ptr = &offset->range; + +    } + +    /* Sinon le groupe dynamique est sollicité */ +    else +    { +        needed = offset->used + (not ? 2 : 1); + +        if (needed > offset->allocated) +        { +            offset->ranges = realloc(offset->ranges, needed * sizeof(node_offset_range_t)); +            offset->allocated = needed; +        } + +        /* Bascule d'un éventuel intervale courant */ +        if (offset->used == 1) +        { +            offset->ranges[0].min = offset->range.min; +            offset->ranges[0].max = offset->range.max; +        } + +        if (not) +        { +            if (min > 0) +            { +                offset->ranges[offset->used].min = 0; +                offset->ranges[offset->used].max = min - 1; + +                offset->used++; + +            } + +            if ((max + 1) < *datasize) +            { +                offset->ranges[offset->used].min = max + 1; +                offset->ranges[offset->used].max = *datasize - (max + 1); + +                offset->used++; + +            } + +        } +        else +        { +            offset->ranges[offset->used].min = min; +            offset->ranges[offset->used].max = max; + +            offset->used++; + +        } + +        offset->gen_ptr = offset->ranges; + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : offset = suivi de tolérances bornées à consulter.            * +*                last   = dernière position validée.                          * +*                pos    = nouvelle position potentielle.                      * +*                                                                             * +*  Description : Indique si une position est comprise dans un intervale.      * +*                                                                             * +*  Retour      : Bilan de la détermination.                                   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool does_node_search_offset_include_pos_forward(const node_search_offset_t *offset, phys_t last, phys_t pos) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours          */ +    const node_offset_range_t *range;       /* Accès rapide aux infos.     */ + +    result = false; + +    for (i = 0; i < offset->used; i++) +    { +        range = &offset->gen_ptr[i]; + +        result = ((last + range->min) <= pos && pos <= (last + range->max)); +        if (result) break; + +    } + +    return result; + +} diff --git a/src/analysis/scan/patterns/tokens/offset.h b/src/analysis/scan/patterns/tokens/offset.h new file mode 100644 index 0000000..b458717 --- /dev/null +++ b/src/analysis/scan/patterns/tokens/offset.h @@ -0,0 +1,101 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * offset.h - prototypes pour la prise en compte des espaces entre octets dans un motif de recherche + * + * 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_PATTERNS_TOKENS_OFFSET_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_OFFSET_H + + +#include <stdbool.h> + +#include "../../../../arch/vmpa.h" + + + +/* Mémorisation d'une souplesse dans les positions visées */ +typedef struct _node_offset_range_t +{ +    /** +     * Les deux champs ci-après font bien référence à des positions absolues, +     * et non à des bornes d'espace, lors que les résultats de correspondances +     * sont encore non initialisés. +     * +     * Ensuite ces bornes représentent bien un espace séparant les résultats +     * issus de deux noeuds. +     */ +    phys_t min;                             /* Position minimale           */ +    phys_t max;                             /* Position maximale           */ + +} node_offset_range_t; + + +/* Fournit les bornes d'une zone à analyser. */ +bool get_node_offset_range(const node_offset_range_t *, phys_t, phys_t, phys_t *, phys_t *); + + + + + + +/* Mémorisation d'une souplesse dans les positions visées */ +typedef struct _node_search_offset_t +{ +    node_offset_range_t range;              /* Bornes de décalage uniques  */ + +    node_offset_range_t *ranges;            /* Bornes de décalage multiples*/ +    size_t allocated;                       /* Nombre d'allocations        */ + +    node_offset_range_t *gen_ptr;           /* Accès générique à la liste  */ + +    size_t used;                            /* Nombre de bornes présentes  */ + +} node_search_offset_t; + + +/* Initialise une mémorisation d'intervales de tolérance. */ +void init_node_search_offset(node_search_offset_t *); + +/* Copie une mémorisation d'intervales entre positions. */ +void copy_node_search_offset(node_search_offset_t *, const node_search_offset_t *); + +/* Fusionne une mémorisation d'intervales entre positions. */ +void merge_node_search_offset(node_search_offset_t *, const node_search_offset_t *); + +/* Met fin à une mémorisation d'intervales de tolérance. */ +void exit_node_search_offset(node_search_offset_t *); + +/* Fournit la liste des tolérances bornées établies à présent. */ +/* TODO : supprimer un niveau d'indirection */ +node_offset_range_t * const *get_node_search_offset_ranges(const node_search_offset_t *, size_t *); + +/* Ajoute un nouvel espace borné aux décalages tolérés. */ +void add_range_to_node_search_offset(node_search_offset_t *, phys_t, phys_t, const phys_t *); + +#define disable_all_ranges_in_node_search_offset(off) \ +    (off)->used = 0 + +/* Indique si une position est comprise dans un intervale. */ +bool does_node_search_offset_include_pos_forward(const node_search_offset_t *, phys_t, phys_t); + + + +#endif  /* _ANALYSIS_SCAN_PATTERNS_TOKENS_OFFSET_H */ diff --git a/src/analysis/scan/patterns/tokens/plain-int.h b/src/analysis/scan/patterns/tokens/plain-int.h index 40a71b5..5748160 100644 --- a/src/analysis/scan/patterns/tokens/plain-int.h +++ b/src/analysis/scan/patterns/tokens/plain-int.h @@ -38,14 +38,6 @@ struct _GScanPlainBytes  {      GStringToken parent;                    /* A laisser en premier        */ -    sized_binary_t orig;                    /* Motif d'origine avant modifs*/ -    GScanTokenModifier *modifier;           /* Transformateur pour le motif*/ -    ScanPlainBytesFlags flags;              /* Fanions associés au motif   */ - -    sized_binary_t *raw;                    /* Liste de motifs à couvrir   */ -    tracked_scan_atom_t *atoms;             /* Atomes correspondants       */ -    size_t count;                           /* Taille de cette liste       */ -  };  /* Encadrement d'une recherche de texte brut (classe) */ @@ -57,7 +49,7 @@ struct _GScanPlainBytesClass  /* Met en place un gestionnaire de recherche de texte brut. */ -bool g_scan_plain_bytes_create(GScanPlainBytes *, const sized_binary_t *, GScanTokenModifier *, ScanPlainBytesFlags); +bool g_scan_plain_bytes_create(GScanPlainBytes *, GScanTokenNode *); diff --git a/src/analysis/scan/patterns/tokens/plain.c b/src/analysis/scan/patterns/tokens/plain.c index 26e7dfa..2eb6bbc 100644 --- a/src/analysis/scan/patterns/tokens/plain.c +++ b/src/analysis/scan/patterns/tokens/plain.c @@ -29,6 +29,7 @@  #include "plain-int.h" +#include "nodes/plain.h" @@ -58,12 +59,6 @@ static void g_scan_plain_bytes_output_to_text(const GScanPlainBytes *, GScanCont  /* Affiche un motif de recherche au format JSON. */  static void g_scan_plain_bytes_output_to_json(const GScanPlainBytes *, GScanContext *, const sized_string_t *, unsigned int, int); -/* Inscrit la définition d'un motif dans un moteur de recherche. */ -static bool g_scan_plain_bytes_enroll(GScanPlainBytes *, GScanContext *, GEngineBackend *, size_t); - -/* Transforme les correspondances locales en trouvailles. */ -static void g_scan_plain_bytes_check(const GScanPlainBytes *, GScanContext *, GBinContent *, pending_matches_t *); -  /* ---------------------------------------------------------------------------------- */ @@ -91,7 +86,6 @@ static void g_scan_plain_bytes_class_init(GScanPlainBytesClass *klass)  {      GObjectClass *object;                   /* Autre version de la classe  */      GSearchPatternClass *pattern;           /* Version de classe ancêtre   */ -    GStringTokenClass *token;               /* Version de classe parente   */      object = G_OBJECT_CLASS(klass); @@ -103,11 +97,6 @@ static void g_scan_plain_bytes_class_init(GScanPlainBytesClass *klass)      pattern->to_text = (output_pattern_to_text_fc)g_scan_plain_bytes_output_to_text;      pattern->to_json = (output_pattern_to_json_fc)g_scan_plain_bytes_output_to_json; -    token = G_STRING_TOKEN_CLASS(klass); - -    token->enroll = (enroll_token_fc)g_scan_plain_bytes_enroll; -    token->check = (check_token_fc)g_scan_plain_bytes_check; -  } @@ -125,13 +114,6 @@ static void g_scan_plain_bytes_class_init(GScanPlainBytesClass *klass)  static void g_scan_plain_bytes_init(GScanPlainBytes *bytes)  { -    init_szstr(&bytes->orig); -    bytes->modifier = NULL; -    bytes->flags = SPBF_NONE; - -    bytes->raw = NULL; -    bytes->atoms = NULL; -    bytes->count = 0;  } @@ -150,8 +132,6 @@ static void g_scan_plain_bytes_init(GScanPlainBytes *bytes)  static void g_scan_plain_bytes_dispose(GScanPlainBytes *bytes)  { -    g_clear_object(&bytes->modifier); -      G_OBJECT_CLASS(g_scan_plain_bytes_parent_class)->dispose(G_OBJECT(bytes));  } @@ -171,19 +151,6 @@ static void g_scan_plain_bytes_dispose(GScanPlainBytes *bytes)  static void g_scan_plain_bytes_finalize(GScanPlainBytes *bytes)  { -    size_t i;                               /* Boucle de parcours          */ - -    exit_szstr(&bytes->orig); - -    for (i = 0; i < bytes->count; i++) -        exit_szstr(&bytes->raw[i]); - -    if (bytes->raw != NULL) -        free(bytes->raw); - -    if (bytes->atoms != NULL) -        free(bytes->atoms); -      G_OBJECT_CLASS(g_scan_plain_bytes_parent_class)->finalize(G_OBJECT(bytes));  } @@ -191,9 +158,7 @@ static void g_scan_plain_bytes_finalize(GScanPlainBytes *bytes)  /******************************************************************************  *                                                                             * -*  Paramètres  : text     = texte brut à rechercher.                          * -*                modifier = transformateur éventuel à solliciter.             * -*                flags    = particularités à prendre en considération.        * +*  Paramètres  : root  = représentation du motif à recherche.                 *  *                                                                             *  *  Description : Construit un gestionnaire de recherche de texte brut.        *  *                                                                             * @@ -203,25 +168,24 @@ static void g_scan_plain_bytes_finalize(GScanPlainBytes *bytes)  *                                                                             *  ******************************************************************************/ -GSearchPattern *g_scan_plain_bytes_new(const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainBytesFlags flags) +GSearchPattern *g_scan_plain_bytes_new(GScanTokenNode *root)  {      GSearchPattern *result;                 /* Structure à retourner       */      result = g_object_new(G_TYPE_SCAN_PLAIN_BYTES, NULL); -    if (!g_scan_plain_bytes_create(G_SCAN_PLAIN_BYTES(result), text, modifier, flags)) +    if (!g_scan_plain_bytes_create(G_SCAN_PLAIN_BYTES(result), root))          g_clear_object(&result);      return result;  } +  /******************************************************************************  *                                                                             * -*  Paramètres  : bytes    = encadrement de motif à initialiser pleinement.    * -*                text     = texte brut à rechercher.                          * -*                modifier = transformateur éventuel à solliciter.             * -*                flags    = particularités à prendre en considération.        * +*  Paramètres  : bytes = encadrement de motif à initialiser pleinement.       * +*                root  = représentation du motif à recherche.                 *  *                                                                             *  *  Description : Met en place un gestionnaire de recherche de texte brut.     *  *                                                                             * @@ -231,21 +195,19 @@ GSearchPattern *g_scan_plain_bytes_new(const sized_binary_t *text, GScanTokenMod  *                                                                             *  ******************************************************************************/ -bool g_scan_plain_bytes_create(GScanPlainBytes *bytes, const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainBytesFlags flags) +bool g_scan_plain_bytes_create(GScanPlainBytes *bytes, GScanTokenNode *root)  {      bool result;                            /* Bilan à retourner           */ +    ScanPlainNodeFlags flags;               /* Propriétés à interpréter    */ +    bool fullword;                          /* Cible de mots entiers ?     */ +    bool private;                           /* Vocation privée ?           */ -    result = true; +    flags = g_scan_token_node_plain_get_flags(G_SCAN_TOKEN_NODE_PLAIN(root)); -    szstrdup(&bytes->orig, text); +    fullword = (flags & SPNF_FULLWORD); +    private = (flags & SPNF_PRIVATE); -    if (modifier != NULL) -    { -        bytes->modifier = modifier; -        g_object_ref(G_OBJECT(modifier)); -    } - -    bytes->flags = flags; +    result = g_string_token_create(G_STRING_TOKEN(bytes), root, fullword, private);      return result; @@ -302,192 +264,3 @@ static void g_scan_plain_bytes_output_to_json(const GScanPlainBytes *pattern, GS      /* TODO */  } - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : bytes   = définition de la bribe à enregistrer.              * -*                context = contexte de l'analyse à mener.                     * -*                backend = moteur de recherche à préchauffer.                 * -*                maxsize = taille max. des atomes (mise en commun optimisée). * -*                                                                             * -*  Description : Inscrit la définition d'un motif dans un moteur de recherche.* -*                                                                             * -*  Retour      : Bilan de l'opération à renvoyer.                             * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_scan_plain_bytes_enroll(GScanPlainBytes *bytes, GScanContext *context, GEngineBackend *backend, size_t maxsize) -{ -    return false; -#if 0 -    bool result;                            /* Statut à retourner          */ -    size_t i;                               /* Boucle de parcours #1       */ -    tracked_scan_atom_t atom;               /* Atome identifié             */ -    size_t letters;                         /* Nombre de lettres présentes */ -    size_t k;                               /* Boucle de parcours #2       */ -    size_t extra_count;                     /* Quantité pour l'exhaustivité*/ -    sized_binary_t *extra;                  /* Couverture supplémntaire    */ -    size_t remaining;                       /* Quantité restant à traiter  */ - -    /* Génération d'une base de chaînes à couvrir */ - -    if (bytes->modifier == NULL) -    { -        bytes->raw = malloc(sizeof(sized_binary_t)); -        bytes->count = 1; - -        szstrdup(&bytes[0].raw[0], &bytes->orig); - -        result = true; - -    } -    else -        result = g_scan_token_modifier_transform(bytes->modifier, &bytes->orig, &bytes->raw, &bytes->count); - -    if (!result) -        goto exit; - -    /* Préparation pour la mémorisation des atomes */ - -    bytes->atoms = malloc(bytes->count * sizeof(tracked_scan_atom_t)); - -    /* Recherche des atomes */ - -    for (i = 0; i < bytes->count; i++) -    { -        if (bytes->flags & SPBF_CASE_INSENSITIVE) -        { -            find_best_atom(&bytes->raw[i], maxsize, &atom, &letters); - -            if (letters == 0) -                bytes->atoms[i] = atom; - -            /* Insertion des combinaisons pour couvrir toutes les casses */ -            else -            { -                for (k = 0, extra_count = 1; k < letters; k++, extra_count *= 2) -                    ; - -                extra = make_atoms_case_insensitive(&bytes->raw[i], extra_count); - -                remaining = bytes->count - i - 1; - -                bytes->count += (extra_count - 1); - -                bytes->raw = realloc(bytes->raw, bytes->count * sizeof(sized_binary_t)); - -                memmove(&bytes->raw[i + extra_count], &bytes->raw[i + 1], remaining * sizeof(sized_binary_t)); - -                for (k = 0; k < extra_count; k++) -                    bytes->raw[i + k] = extra[k]; - -                free(extra); - -                bytes->atoms = realloc(bytes->raw, bytes->count * sizeof(tracked_scan_atom_t)); - -                for (k = 0; k < extra_count; k++) -                    bytes->atoms[i + k] = atom; - -                i += extra_count - 1; - -            } - -        } - -        else -            find_best_atom(&bytes->raw[i], maxsize, &bytes->atoms[i], &letters); - -    } - -    /* Enregistrements en masse */ - - -    for (i = 0; i < bytes->count && result; i++) -        result = enroll_prepared_atom(&bytes->raw[i], context, backend, &bytes->atoms[i]); - - exit: - -    return result; -#endif -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : bytes   = définition de la bribe à manipuler.                * -*                context = contexte de l'analyse à mener.                     * -*                content = accès au contenu brut pour vérifications (optim.)  * -*                matches = suivi des correspondances à consolider.            * -*                                                                             * -*  Description : Transforme les correspondances locales en trouvailles.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_scan_plain_bytes_check(const GScanPlainBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches) -{ -#if 0 - -    size_t i;                               /* Boucle de parcours #1       */ -    const sized_binary_t *raw;              /* Données brutes d'origine    */ -    const tracked_scan_atom_t *atom;        /* Atome correspondant         */ -    size_t count;                           /* Quantité de bribes trouvées */ -    const phys_t *found;                    /* Localisations des bribes    */ -    size_t k;                               /* Boucle de parcours #2       */ -    phys_t start;                           /* Point de départ             */ -    vmpa2t pos;                             /* Position dans les données   */ -    const bin_t *ptr;                       /* Accès aux données brutes    */ -    int ret;                                /* Bilan d'une comparaison     */ - -    for (i = 0; i < bytes->count; i++) -    { -        raw = &bytes->raw[i]; -        atom = &bytes->atoms[i]; - -        found = g_scan_context_get_atom_matches(context, atom->pid, &count); - -        for (k = 0; k < count; k++) -        { -            start = found[k] - atom->pos; - -            init_vmpa(&pos, start, VMPA_NO_VIRTUAL); - -            /* Validation du contenu avant l'atome */ - -            if (atom->pos > 0) -            { -                ptr = g_binary_content_get_raw_access(content, &pos, atom->pos); - -                ret = memcmp(raw->data, ptr, atom->pos); -                if (ret != 0) continue; - -            } - -            /* Validation du contenu après l'atome */ - -            if (atom->rem > 0) -            { -                advance_vmpa(&pos, atom->len); - -                ptr = g_binary_content_get_raw_access(content, &pos, atom->rem); - -                ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem); -                if (ret != 0) continue; - -            } - -            /* Mémorisation de la correspondance */ - -            add_pending_matches(matches, start, raw->len); - -        } - -    } -#endif -} diff --git a/src/analysis/scan/patterns/tokens/plain.h b/src/analysis/scan/patterns/tokens/plain.h index 80a0b4d..6ff48d7 100644 --- a/src/analysis/scan/patterns/tokens/plain.h +++ b/src/analysis/scan/patterns/tokens/plain.h @@ -28,9 +28,8 @@  #include <glib-object.h> -#include "../modifier.h" +#include "node.h"  #include "../../pattern.h" -#include "../../../../common/szstr.h" @@ -49,21 +48,11 @@ typedef struct _GScanPlainBytes GScanPlainBytes;  typedef struct _GScanPlainBytesClass GScanPlainBytesClass; -/* Propriétés d'un élément textuel à rechercher */ -typedef enum _ScanPlainBytesFlags -{ -    SPBF_NONE             = 0x0,            /* Aucune particularité        */ -    SPBF_CASE_INSENSITIVE = 0x1,            /* Ignorance de la casse       */ -    SPBF_FULL_WORD        = 0x2,            /* Recherche de mot entier     */ - -} ScanPlainBytesFlags; - -  /* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */  GType g_scan_plain_bytes_get_type(void);  /* Construit un gestionnaire de recherche de texte brut. */ -GSearchPattern *g_scan_plain_bytes_new(const sized_binary_t *, GScanTokenModifier *, ScanPlainBytesFlags); +GSearchPattern *g_scan_plain_bytes_new(GScanTokenNode *); | 
