summaryrefslogtreecommitdiff
path: root/src/analysis/scan/patterns/tokens
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/scan/patterns/tokens')
-rw-r--r--src/analysis/scan/patterns/tokens/Makefile.am12
-rw-r--r--src/analysis/scan/patterns/tokens/atom.c364
-rw-r--r--src/analysis/scan/patterns/tokens/atom.h68
-rw-r--r--src/analysis/scan/patterns/tokens/hex-int.h56
-rw-r--r--src/analysis/scan/patterns/tokens/hex.c457
-rw-r--r--src/analysis/scan/patterns/tokens/hex.h59
-rw-r--r--src/analysis/scan/patterns/tokens/node-int.h58
-rw-r--r--src/analysis/scan/patterns/tokens/node.c195
-rw-r--r--src/analysis/scan/patterns/tokens/node.h77
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/Makefile.am16
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/hub-int.h51
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/hub.c150
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/hub.h55
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/plain-int.h64
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/plain.c582
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/plain.h70
-rw-r--r--src/analysis/scan/patterns/tokens/plain-int.h64
-rw-r--r--src/analysis/scan/patterns/tokens/plain.c365
-rw-r--r--src/analysis/scan/patterns/tokens/plain.h31
19 files changed, 2657 insertions, 137 deletions
diff --git a/src/analysis/scan/patterns/tokens/Makefile.am b/src/analysis/scan/patterns/tokens/Makefile.am
index 00cff2a..7fb515f 100644
--- a/src/analysis/scan/patterns/tokens/Makefile.am
+++ b/src/analysis/scan/patterns/tokens/Makefile.am
@@ -3,11 +3,23 @@ noinst_LTLIBRARIES = libanalysisscanpatternstokens.la
libanalysisscanpatternstokens_la_SOURCES = \
+ atom.h atom.c \
+ hex-int.h \
+ hex.h hex.c \
+ node-int.h \
+ node.h node.c \
+ plain-int.h \
plain.h plain.c
+libanalysisscanpatternstokens_la_LIBADD = \
+ nodes/libanalysisscanpatternstokensnodes.la
+
libanalysisscanpatternstokens_la_CFLAGS = $(LIBGOBJ_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libanalysisscanpatternstokens_la_SOURCES:%c=)
+
+
+SUBDIRS = nodes
diff --git a/src/analysis/scan/patterns/tokens/atom.c b/src/analysis/scan/patterns/tokens/atom.c
new file mode 100644
index 0000000..fcb585d
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/atom.c
@@ -0,0 +1,364 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * atom.c - détermination d'atomes à partir de motifs
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "atom.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+
+/**
+ * Remplacement des fonctions de <ctypes.h> dans support des locales.
+ */
+
+#define IS_CH_LETTER(ch) (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z'))
+
+#define MAKE_CH_UPPER(ch) (ch & 0xdf)
+#define MAKE_CH_LOWER(ch) (ch | 0x20)
+
+
+
+/******************************************************************************
+* *
+* Paramètres : ch = octet dont la valeur est à analyser. *
+* seen = suivi des octets déjà rencontrés. [OUT] *
+* letters = nombre de lettres rencontrées. [OUT] *
+* *
+* Description : Note l'intêret de rechercher un octet particulier. *
+* *
+* Retour : Note positive ou négative. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int rate_byte_quality(bin_t ch, bitfield_t *seen, size_t *letters)
+{
+ int result; /* Note à retourner */
+
+ switch (ch)
+ {
+ case 0x00:
+ case 0x20:
+ case 0x90:
+ case 0xcc:
+ case 0xff:
+ result = 12;
+ break;
+
+ case 'A' ... 'Z':
+ case 'z' ... 'z':
+ if (letters == NULL)
+ result = 20;
+ else
+ {
+ result = 18;
+ (*letters)++;
+ }
+ break;
+
+ default:
+ result = 20;
+ break;
+
+ }
+
+ set_in_bit_field(seen, ch, 1);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : seen = suivi des octets déjà rencontrés. *
+* max = nombre d'octets considérés à la base. *
+* *
+* Description : Termine la notation d'un ensemble d'octets. *
+* *
+* Retour : Note positive ou négative. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int finish_quality_rating(const bitfield_t *seen, size_t max)
+{
+ int result; /* Note à retourner */
+ size_t uniq; /* Quantié d'octets uniques */
+ bool bad; /* Indice de mauvaise qualité */
+
+ uniq = popcount_for_bit_field(seen);
+
+ if (uniq == 1)
+ {
+ bad = test_in_bit_field(seen, 0x00)
+ || test_in_bit_field(seen, 0x20)
+ || test_in_bit_field(seen, 0x90)
+ || test_in_bit_field(seen, 0xcc)
+ || test_in_bit_field(seen, 0xff);
+
+ result = (bad ? -10 * max : 2);
+
+ }
+
+ else
+ result = uniq * 2;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : raw = définition de la bribe à enregistrer. *
+* maxsize = taille max. des atomes (mise en commun optimisée). *
+* atom = informations de suivi constituées. [OUT] *
+* letters = nombre de lettres rencontrées. [OUT] *
+* *
+* Description : Détermine la portion idéale de recherche. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void find_best_atom(const sized_binary_t *raw, size_t maxsize, tracked_scan_atom_t *atom, size_t *letters)
+{
+ size_t i; /* Boucle de parcours #1 */
+ bin_t ch; /* Octets à étudier */
+ size_t best_letters; /* Mémorisation de décompte */
+ size_t *ptr_letters; /* Pointeur vers le décompte */
+ int best_rating; /* Meilleur notation obtenue */
+ bitfield_t *seen; /* Mémorise les octets déjà vus*/
+ size_t max_loop; /* Limitation des itérations */
+ size_t k; /* Boucle de parcours #2 */
+ size_t local_letters; /* Décompte courant des lettres*/
+ int local_rating; /* Notation courante */
+
+ /* Si la chaîne fournie est plus petite que la taille d'un atome... */
+ if (raw->len <= maxsize)
+ {
+ atom->pos = 0;
+ atom->len = raw->len;
+ atom->rem = 0;
+
+ if (letters != NULL)
+ {
+ *letters = 0;
+
+ for (i = 0; i < raw->len; i++)
+ {
+ ch = raw->data[i];
+
+ if (IS_CH_LETTER(ch))
+ (*letters)++;
+
+ }
+
+ }
+
+ }
+
+ /* ... ou si une sélection doit s'opérer */
+ else
+ {
+ /* Etablissement d'une mesure de référence à la position 0 */
+
+ atom->pos = 0;
+ atom->len = maxsize;
+
+ ptr_letters = (letters != NULL ? &best_letters : NULL);
+
+ best_letters = 0;
+ best_rating = 0;
+
+ seen = create_bit_field(256, false);
+
+ for (k = 0; k < maxsize; k++)
+ best_rating += rate_byte_quality(raw->data[k], seen, ptr_letters);
+
+ best_rating += finish_quality_rating(seen, maxsize);
+
+ /* Parcours du reste du contenu */
+
+ max_loop = (raw->len - maxsize);
+
+ ptr_letters = (letters != NULL ? &local_letters : NULL);
+
+ for (i = 1; i < max_loop; i++)
+ {
+ local_letters = 0;
+ local_rating = 0;
+
+ reset_all_in_bit_field(seen);
+
+ for (k = 0; k < maxsize; k++)
+ local_rating += rate_byte_quality(raw->data[i + k], seen, ptr_letters);
+
+ local_rating += finish_quality_rating(seen, maxsize);
+
+ if (local_rating > best_rating)
+ {
+ atom->pos = i;
+
+ best_letters = local_letters;
+ best_rating = local_rating;
+
+ }
+
+ }
+
+ /* Conclusion */
+
+ delete_bit_field(seen);
+
+ atom->rem = raw->len - atom->pos - maxsize;
+
+ if (letters != NULL)
+ *letters = best_letters;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : src = chaîne ed référence à dupliquer. *
+* count = nombre de lettres présentes. *
+* *
+* Description : Etablit la liste des cas de figures ignorant la casse. *
+* *
+* Retour : Liste de toutes les combinaisons possibles. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+sized_binary_t *make_atoms_case_insensitive(const sized_binary_t *src, size_t count)
+{
+ sized_binary_t *result; /* Liste à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ size_t replaced; /* 2^(alternatives créées) */
+#ifndef NDEBUG
+ size_t check; /* Validation du compte max. */
+#endif
+ bin_t ch; /* Octet à recopier */
+ size_t k; /* Boucle de parcours #2 */
+ 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));
+
+ for (i = 0; i < count; i++)
+ {
+ result[i].data = malloc(src->len);
+ result[i].len = src->len;
+ }
+
+ /* Remplissage */
+
+ replaced = 2;
+
+#ifndef NDEBUG
+ check = 1;
+#endif
+
+ for (i = 0; i < src->len; i++)
+ {
+ ch = src->data[i];
+
+ if (IS_CH_LETTER(ch))
+ {
+ for (k = 0; k < count; k++)
+ {
+ divisor = count / replaced;
+ quotient = k / divisor;
+
+ if ((quotient % 2) == 0)
+ result[k].data[i] = MAKE_CH_UPPER(ch);
+ else
+ result[k].data[i] = MAKE_CH_LOWER(ch);
+
+ }
+
+ replaced *= 2;
+
+#ifndef NDEBUG
+ check++;
+ assert((check - 1) <= count);
+#endif
+
+ }
+ else
+ for (k = 0; k < count; k++)
+ result[k].data[i] = ch;
+
+ }
+
+ assert((check - 1) == count);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : raw = définition de la bribe à enregistrer. *
+* context = contexte de l'analyse à mener. *
+* backend = moteur de recherche à préchauffer. *
+* atom = informations de suivi constituées. [OUT] *
+* *
+* Description : Enregistre l'atome déterminé d'une série d'octets. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool enroll_prepared_atom(const sized_binary_t *raw, GScanContext *context, GEngineBackend *backend, tracked_scan_atom_t *atom)
+{
+ bool result; /* Statut à retourner */
+ const bin_t *data; /* Données à rechercher */
+
+ data = raw->data + atom->pos;
+
+ atom->pid = g_engine_backend_enroll_plain_pattern(backend, context, data, atom->len);
+
+ result = (atom->pid != INVALID_PATTERN_ID);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/patterns/tokens/atom.h b/src/analysis/scan/patterns/tokens/atom.h
new file mode 100644
index 0000000..daa1f16
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/atom.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * atom.h - prototypes pour la détermination d'atomes à partir de motifs
+ *
+ * Copyright (C) 2023 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_PATTERNS_TOKENS_ATOM_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_ATOM_H
+
+
+#include <stdbool.h>
+
+
+#include "../backend.h"
+#include "../../context.h"
+#include "../../../../arch/vmpa.h"
+#include "../../../../common/bits.h"
+#include "../../../../common/szstr.h"
+
+
+
+/* Suivi des motifs réellement recherchés */
+typedef struct _tracked_scan_atom_t
+{
+ phys_t pos; /* Début de sélection atomique */
+ phys_t len; /* Taille de ladite sélection */
+ phys_t rem; /* Reste après l'atome */
+
+ patid_t pid; /* Identifiant de la bribe */
+
+} tracked_scan_atom_t;
+
+
+/* Note l'intêret de rechercher un octet particulier. */
+int rate_byte_quality(bin_t, bitfield_t *, size_t *);
+
+/* Termine la notation d'un ensemble d'octets. */
+int finish_quality_rating(const bitfield_t *, size_t);
+
+/* Détermine la portion idéale de recherche. */
+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);
+
+/* 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 *);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_ATOM_H */
diff --git a/src/analysis/scan/patterns/tokens/hex-int.h b/src/analysis/scan/patterns/tokens/hex-int.h
new file mode 100644
index 0000000..f0460c8
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/hex-int.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex-int.h - prototypes internes pour la recherche de morceaux de binaire
+ *
+ * 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_HEX_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_HEX_INT_H
+
+
+#include "hex.h"
+
+
+#include "atom.h"
+#include "../token-int.h"
+
+
+
+/* Encadrement d'une recherche de morceaux de binaire (instance) */
+struct _GScanHexBytes
+{
+ GStringToken parent; /* A laisser en premier */
+
+};
+
+/* Encadrement d'une recherche de morceaux de binaire (classe) */
+struct _GScanHexBytesClass
+{
+ GStringTokenClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un gestionnaire de recherche de binaire. */
+bool g_scan_hex_bytes_create(GScanHexBytes *, GScanTokenNode *);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_HEX_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/hex.c b/src/analysis/scan/patterns/tokens/hex.c
new file mode 100644
index 0000000..c1cdbdf
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/hex.c
@@ -0,0 +1,457 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - recherche de morceaux de binaire
+ *
+ * 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 "hex.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "hex-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des recherches de texte brut. */
+static void g_scan_hex_bytes_class_init(GScanHexBytesClass *klass);
+
+/* Initialise une instance de recherche de texte brut. */
+static void g_scan_hex_bytes_init(GScanHexBytes *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_hex_bytes_dispose(GScanHexBytes *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_hex_bytes_finalize(GScanHexBytes *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Affiche un motif de recherche au format texte. */
+static void g_scan_hex_bytes_output_to_text(const GScanHexBytes *, GScanContext *, int);
+
+/* 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 *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
+G_DEFINE_TYPE(GScanHexBytes, g_scan_hex_bytes, G_TYPE_STRING_TOKEN);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des recherches de texte brut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_hex_bytes_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_hex_bytes_finalize;
+
+ pattern = G_SEARCH_PATTERN_CLASS(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;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bytes = instance à initialiser. *
+* *
+* Description : Initialise une instance de recherche de texte brut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_bytes_init(GScanHexBytes *bytes)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bytes = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_bytes_dispose(GScanHexBytes *bytes)
+{
+ G_OBJECT_CLASS(g_scan_hex_bytes_parent_class)->dispose(G_OBJECT(bytes));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bytes = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_bytes_finalize(GScanHexBytes *bytes)
+{
+ G_OBJECT_CLASS(g_scan_hex_bytes_parent_class)->finalize(G_OBJECT(bytes));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : root = représentation du motif à recherche. *
+* *
+* Description : Construit un gestionnaire de recherche de texte brut. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *root)
+{
+ 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))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bytes = encadrement de motif à initialiser pleinement. *
+* root = représentation du motif à recherche. *
+* *
+* Description : Met en place un gestionnaire de recherche de binaire. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_hex_bytes_create(GScanHexBytes *bytes, GScanTokenNode *root)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_string_token_create(G_STRING_TOKEN(bytes), root);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = définition de motif à considérer. *
+* context = contexte de l'analyse à mener. *
+* fd = canal d'écriture. *
+* *
+* Description : Affiche un motif de recherche au format texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_bytes_output_to_text(const GScanHexBytes *pattern, GScanContext *context, int fd)
+{
+ G_SEARCH_PATTERN_CLASS(g_scan_hex_bytes_parent_class)->to_text(G_SEARCH_PATTERN(pattern), context, fd);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = définition de motif à considérer. *
+* context = contexte de l'analyse à mener. *
+* padding = éventuel bourrage initial à placer ou NULL. *
+* level = profondeur actuelle. *
+* fd = canal d'écriture. *
+* *
+* Description : Affiche un motif de recherche au format JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_bytes_output_to_json(const GScanHexBytes *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
+{
+ G_SEARCH_PATTERN_CLASS(g_scan_hex_bytes_parent_class)->to_json(G_SEARCH_PATTERN(pattern), context, padding, level, fd);
+
+ /* 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
new file mode 100644
index 0000000..1db8eb6
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/hex.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.h - prototypes pour la recherche de morceaux de binaire
+ *
+ * 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_HEX_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_HEX_H
+
+
+#include <glib-object.h>
+
+
+#include "node.h"
+#include "../../pattern.h"
+
+
+
+#define G_TYPE_SCAN_HEX_BYTES g_scan_hex_bytes_get_type()
+#define G_SCAN_HEX_BYTES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_HEX_BYTES, GScanHexBytes))
+#define G_IS_SCAN_HEX_BYTES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_HEX_BYTES))
+#define G_SCAN_HEX_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_HEX_BYTES, GScanHexBytesClass))
+#define G_IS_SCAN_HEX_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_HEX_BYTES))
+#define G_SCAN_HEX_BYTES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_HEX_BYTES, GScanHexBytesClass))
+
+
+/* Encadrement d'une recherche de morceaux de binaire (instance) */
+typedef struct _GScanHexBytes GScanHexBytes;
+
+/* Encadrement d'une recherche de morceaux de binaire (classe) */
+typedef struct _GScanHexBytesClass GScanHexBytesClass;
+
+
+/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
+GType g_scan_hex_bytes_get_type(void);
+
+/* Construit un gestionnaire de recherche de texte brut. */
+GSearchPattern *g_scan_hex_bytes_new(GScanTokenNode *);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_HEX_H */
diff --git a/src/analysis/scan/patterns/tokens/node-int.h b/src/analysis/scan/patterns/tokens/node-int.h
new file mode 100644
index 0000000..c543cbf
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/node-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * node-int.h - prototypes internes pour la 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/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_INT_H
+
+
+#include "node.h"
+
+
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+typedef bool (* enroll_scan_token_node_fc) (GScanTokenNode *, GScanContext *, GEngineBackend *, 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 *);
+
+
+/* Décomposition d'un motif de recherche en atomes (instance) */
+struct _GScanTokenNode
+{
+ GObject parent; /* A laisser en premier */
+
+};
+
+/* Décomposition d'un motif de recherche en atomes (classe) */
+struct _GScanTokenNodeClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ enroll_scan_token_node_fc enroll; /* Inscription d'un motif */
+ check_scan_token_node_fc check; /* Conversion en trouvailles */
+
+};
+
+
+
+#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
new file mode 100644
index 0000000..224328a
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/node.c
@@ -0,0 +1,195 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * node.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 "node.h"
+
+
+#include <assert.h>
+
+
+#include "node-int.h"
+
+
+
+/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */
+
+
+/* Initialise la classe des éléments de décomposition. */
+static void g_scan_token_node_class_init(GScanTokenNodeClass *klass);
+
+/* Initialise une instance d'élément décomposant un motif. */
+static void g_scan_token_node_init(GScanTokenNode *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_token_node_dispose(GScanTokenNode *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_token_node_finalize(GScanTokenNode *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DECOMPOSITION DE MOTIF RECHERCHE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un élément décomposant un motif d'octets à rechercher. */
+G_DEFINE_TYPE(GScanTokenNode, g_scan_token_node, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des éléments de décomposition. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_class_init(GScanTokenNodeClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_node_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_token_node_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = instance à initialiser. *
+* *
+* Description : Initialise une instance d'élément décomposant un motif. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_init(GScanTokenNode *node)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_dispose(GScanTokenNode *node)
+{
+ G_OBJECT_CLASS(g_scan_token_node_parent_class)->dispose(G_OBJECT(node));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_finalize(GScanTokenNode *node)
+{
+ G_OBJECT_CLASS(g_scan_token_node_parent_class)->finalize(G_OBJECT(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). *
+* *
+* 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)
+{
+ bool result; /* Statut à retourner */
+ GScanTokenNodeClass *class; /* Classe de l'instance */
+
+ assert(g_engine_backend_get_atom_max_size(backend) == maxsize);
+
+ class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
+
+ result = class->enroll(node, context, backend, maxsize);
+
+ 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. *
+* *
+* Description : Transforme les correspondances locales en trouvailles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_token_node_check(const GScanTokenNode *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, const node_search_offset_t *offset)
+{
+ GScanTokenNodeClass *class; /* Classe de l'instance */
+
+ class = G_SCAN_TOKEN_NODE_GET_CLASS(node);
+
+ class->check(node, context, content, matches, offset);
+
+}
diff --git a/src/analysis/scan/patterns/tokens/node.h b/src/analysis/scan/patterns/tokens/node.h
new file mode 100644
index 0000000..4c9eb48
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/node.h
@@ -0,0 +1,77 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * node.h - prototypes pour la 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/>.
+ */
+
+
+#ifndef _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../backend.h"
+#include "../../context.h"
+#include "../../matches/pending.h"
+
+
+#define G_TYPE_SCAN_TOKEN_NODE g_scan_token_node_get_type()
+#define G_SCAN_TOKEN_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE, GScanTokenNode))
+#define G_IS_SCAN_TOKEN_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE))
+#define G_SCAN_TOKEN_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE, GScanTokenNodeClass))
+#define G_IS_SCAN_TOKEN_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE))
+#define G_SCAN_TOKEN_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE, GScanTokenNodeClass))
+
+
+/* Décomposition d'un motif de recherche en atomes (instance) */
+typedef struct _GScanTokenNode GScanTokenNode;
+
+/* Décomposition d'un motif de recherche en atomes (classe) */
+typedef struct _GScanTokenNodeClass GScanTokenNodeClass;
+
+
+/* Indique le type défini pour un élément décomposant un motif d'octets à rechercher. */
+GType g_scan_token_node_get_type(void);
+
+
+// TODO
+// validate
+// force_plain_registration // set begin/end
+
+
+/* Inscrit la définition d'un motif dans un moteur de recherche. */
+bool g_scan_token_node_enroll(GScanTokenNode *, GScanContext *, GEngineBackend *, 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(const GScanTokenNode *, GScanContext *, GBinContent *, pending_matches_t *, const node_search_offset_t *);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODE_H */
diff --git a/src/analysis/scan/patterns/tokens/nodes/Makefile.am b/src/analysis/scan/patterns/tokens/nodes/Makefile.am
new file mode 100644
index 0000000..c20beaf
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/Makefile.am
@@ -0,0 +1,16 @@
+
+noinst_LTLIBRARIES = libanalysisscanpatternstokensnodes.la
+
+
+libanalysisscanpatternstokensnodes_la_SOURCES = \
+ hub-int.h \
+ hub.h hub.c \
+ plain-int.h \
+ plain.h plain.c
+
+libanalysisscanpatternstokensnodes_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanpatternstokensnodes_la_SOURCES:%c=)
diff --git a/src/analysis/scan/patterns/tokens/nodes/hub-int.h b/src/analysis/scan/patterns/tokens/nodes/hub-int.h
new file mode 100644
index 0000000..df05112
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/hub-int.h
@@ -0,0 +1,51 @@
+
+/* 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
+ *
+ * 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_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_INT_H
+
+
+#include "hub.h"
+
+
+#include "../node-int.h"
+
+
+
+/* Groupe de décompositions de motif de recherche en atomes (instance) */
+struct _GScanTokenNodeHub
+{
+ GScanTokenNode parent; /* A laisser en premier */
+
+};
+
+/* Groupe de décompositions de motif de recherche en atomes (classe) */
+struct _GScanTokenNodeHubClass
+{
+ GScanTokenNodeClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_HUB_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/nodes/hub.c b/src/analysis/scan/patterns/tokens/nodes/hub.c
new file mode 100644
index 0000000..a11531d
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/hub.c
@@ -0,0 +1,150 @@
+
+/* 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
new file mode 100644
index 0000000..b2cb0fc
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/hub.h
@@ -0,0 +1,55 @@
+
+/* 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/plain-int.h b/src/analysis/scan/patterns/tokens/nodes/plain-int.h
new file mode 100644
index 0000000..a38359d
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/plain-int.h
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain-int.h - prototypes internes pour la gestion d'une recherche de motif textuel
+ *
+ * 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_PLAIN_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_INT_H
+
+
+#include "plain.h"
+
+
+#include "../node-int.h"
+#include "../atom.h"
+
+
+
+/* Bribe de motif textuelle pour recherches (instance) */
+struct _GScanTokenNodePlain
+{
+ GScanTokenNode parent; /* A laisser en premier */
+
+ sized_binary_t orig; /* Motif d'origine avant modifs*/
+ GScanTokenModifier *modifier; /* Transformateur pour le motif*/
+ ScanPlainNodeFlags 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 */
+
+};
+
+/* Bribe de motif textuelle pour recherches (instance) */
+struct _GScanTokenNodePlainClass
+{
+ GScanTokenNodeClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un un noeud représentant un motif textuel. */
+bool g_scan_token_node_plain_create(GScanTokenNodePlain *, const sized_binary_t *, GScanTokenModifier *, ScanPlainNodeFlags);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.c b/src/analysis/scan/patterns/tokens/nodes/plain.c
new file mode 100644
index 0000000..ee87c73
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/plain.c
@@ -0,0 +1,582 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.c - gestion d'une recherche de motif textuel
+ *
+ * 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 "plain.h"
+
+
+#include "plain-int.h"
+
+
+
+/* ------------------------ DECOMPOSITION DE MOTIF RECHERCHE ------------------------ */
+
+
+/* Initialise la classe des noeuds pour motif textuel. */
+static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *klass);
+
+/* Initialise une instance de noeud pour motif textuel. */
+static void g_scan_token_node_plain_init(GScanTokenNodePlain *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_token_node_plain_dispose(GScanTokenNodePlain *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_token_node_plain_finalize(GScanTokenNodePlain *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* 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 );
+
+/* 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 *);
+
+/* 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 *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DECOMPOSITION DE MOTIF RECHERCHE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un noeud représentant une bribe de texte à retrouver. */
+G_DEFINE_TYPE(GScanTokenNodePlain, g_scan_token_node_plain, G_TYPE_SCAN_TOKEN_NODE);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des noeuds pour motif textuel. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_plain_class_init(GScanTokenNodePlainClass *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_plain_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_token_node_plain_finalize;
+
+ node = G_SCAN_TOKEN_NODE_CLASS(klass);
+
+ 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;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plain = instance à initialiser. *
+* *
+* Description : Initialise une instance de noeud pour motif textuel. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_plain_init(GScanTokenNodePlain *plain)
+{
+ init_szstr(&plain->orig);
+ plain->modifier = NULL;
+ plain->flags = SPNF_NONE;
+
+ plain->raw = NULL;
+ plain->atoms = NULL;
+ plain->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plain = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_plain_dispose(GScanTokenNodePlain *plain)
+{
+ g_clear_object(&plain->modifier);
+
+ G_OBJECT_CLASS(g_scan_token_node_plain_parent_class)->dispose(G_OBJECT(plain));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plain = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_node_plain_finalize(GScanTokenNodePlain *plain)
+{
+ size_t i; /* Boucle de parcours */
+
+ exit_szstr(&plain->orig);
+
+ for (i = 0; i < plain->count; i++)
+ exit_szstr(&plain->raw[i]);
+
+ if (plain->raw != NULL)
+ free(plain->raw);
+
+ if (plain->atoms != NULL)
+ free(plain->atoms);
+
+ G_OBJECT_CLASS(g_scan_token_node_plain_parent_class)->finalize(G_OBJECT(plain));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : text = texte brut à rechercher. *
+* modifier = transformateur éventuel à solliciter. *
+* flags = particularités à prendre en considération. *
+* *
+* Description : Construit un noeud représentant un motif textuel. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenNode *g_scan_token_node_plain_new(const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainNodeFlags flags)
+{
+ GScanTokenNode *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_TOKEN_NODE_PLAIN, NULL);
+
+ if (!g_scan_token_node_plain_create(G_SCAN_TOKEN_NODE_PLAIN(result), text, modifier, flags))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+/******************************************************************************
+* *
+* Paramètres : plain = encadrement de motif à initialiser pleinement. *
+* text = texte brut à rechercher. *
+* modifier = transformateur éventuel à solliciter. *
+* flags = particularités à prendre en considération. *
+* *
+* Description : Met en place un un noeud représentant un motif textuel. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_token_node_plain_create(GScanTokenNodePlain *plain, const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainNodeFlags flags)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ szstrdup(&plain->orig, text);
+
+ if (modifier != NULL)
+ {
+ plain->modifier = modifier;
+ g_object_ref(G_OBJECT(modifier));
+ }
+
+ plain->flags = flags;
+
+ 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). *
+* *
+* 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_plain_enroll(GScanTokenNodePlain *node, 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 (node->modifier == NULL)
+ {
+ node->raw = malloc(sizeof(sized_binary_t));
+ node->count = 1;
+
+ szstrdup(&node->raw[0], &node->orig);
+
+ result = true;
+
+ }
+ else
+ result = g_scan_token_modifier_transform(node->modifier, &node->orig, &node->raw, &node->count);
+
+ if (!result)
+ goto exit;
+
+ /* Préparation pour la mémorisation des atomes */
+
+ node->atoms = malloc(node->count * sizeof(tracked_scan_atom_t));
+
+ /* Validation du besoin effectif dans les cas extrèmes */
+
+
+
+ // TODO : if (orig.len < ...)
+
+
+
+ /* Recherche des atomes */
+
+ for (i = 0; i < node->count; i++)
+ {
+ if (node->flags & SPNF_CASE_INSENSITIVE)
+ {
+ find_best_atom(&node->raw[i], maxsize, &atom, &letters);
+
+ if (letters == 0)
+ node->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(&node->raw[i], extra_count);
+
+ remaining = node->count - i - 1;
+
+ node->count += (extra_count - 1);
+
+ node->raw = realloc(node->raw, node->count * sizeof(sized_binary_t));
+
+ memmove(&node->raw[i + extra_count], &node->raw[i + 1], remaining * sizeof(sized_binary_t));
+
+ for (k = 0; k < extra_count; k++)
+ node->raw[i + k] = extra[k];
+
+ free(extra);
+
+ node->atoms = realloc(node->raw, node->count * sizeof(tracked_scan_atom_t));
+
+ for (k = 0; k < extra_count; k++)
+ node->atoms[i + k] = atom;
+
+ i += extra_count - 1;
+
+ }
+
+ }
+
+ else
+ find_best_atom(&node->raw[i], maxsize, &node->atoms[i], &letters);
+
+ }
+
+ /* Enregistrements en masse */
+
+ for (i = 0; i < node->count && result; i++)
+ result = enroll_prepared_atom(&node->raw[i], context, backend, &node->atoms[i]);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : raw = contneu brut à retrouver idéalement. *
+* atom = contenu brut représentatif ciblé. *
+* 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_plain_content(const sized_binary_t *raw, const tracked_scan_atom_t *atom, 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 */
+ int ret; /* Bilan d'une comparaison */
+
+ result = false;
+
+ 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) goto done;
+
+ }
+
+ /* 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) goto done;
+
+ }
+
+ result = true;
+
+ done:
+
+ 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. *
+* *
+* Description : Transforme les correspondances locales en trouvailles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_plain_bytes_check(const GScanTokenNodePlain *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, const node_search_offset_t *offset)
+{
+ bool initialized; /* Initialisation du suivi ? */
+ 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 */
+ bool status; /* Bilan d'une correspondance */
+ size_t pcount; /* Nombre de correspondances */
+ size_t p; /* Boucle de parcours #3 */
+
+ initialized = are_pending_matches_initialized(matches);
+
+ for (i = 0; i < node->count; i++)
+ {
+ raw = &node->raw[i];
+ atom = &node->atoms[i];
+
+ found = g_scan_context_get_atom_matches(context, atom->pid, &count);
+
+ if (!initialized)
+ {
+ for (k = 0; k < count; k++)
+ {
+ start = 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 (start < offset->min || start > offset->max)
+ continue;
+ }
+
+ status = check_scan_token_node_plain_content(raw, atom, start, content);
+
+ if (status)
+ /**
+ * 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, start, raw->len);
+
+ }
+
+ }
+
+ else
+ {
+ reset_pending_matches_ttl(matches);
+
+ pcount = count_pending_matches(matches);
+
+ for (p = 0; p < pcount; p++)
+ for (k = 0; k < count; k++)
+ {
+ start = found[k] - atom->pos;
+
+ /**
+ * Si bornes de tolérance il y a, on valide la position.
+ *
+ * Sinon les correspondances passées et actuelle doivent
+ * être jointes.
+ */
+ if (offset != NULL)
+ {
+ if (!has_pending_match_ending_between(matches, p, start, offset->min, offset->max))
+ continue;
+ }
+ else
+ {
+ if (!has_pending_match_ending_at(matches, p, start))
+ continue;
+ }
+
+ status = check_scan_token_node_plain_content(raw, atom, start, content);
+
+ if (status)
+ {
+ /**
+ * Même si une base de couples uniques est assurée,
+ * la constitution d'un ensemble de noeuds peut amener une
+ * redondance dans les emplacements de correspondances.
+ *
+ * Par exemple, pour la séquence d'octets analysés suivante :
+ *
+ * aaa....bbb
+ *
+ * La définition { (61 61 | 61 61 61) [4-5] 62 62 62 } peut établir
+ * les correspondances suivantes :
+ *
+ * aa.....bbb -> couple pending[x] (0;2) puis (0;10)
+ * ^
+ * aa....bbb -> couple pending[y] (1;3) puis (1;10)
+ * ^
+ * aaa....bbb -> couple pending[z] (0;3) puis (0;10)
+ * ^
+ *
+ * Par ailleurs, une même base de départ peut conduire
+ * à plusieurs zone de correspondances.
+ *
+ * Par exemple, pour la séquence d'octets analysés suivante :
+ *
+ * aa..bb..bb
+ *
+ * La définition { 61 61 [2-6] 62 62 } peut établir
+ * les correspondances suivantes :
+ *
+ * aa..bb..bb -> couple pending[x] (0;2) puis (0;6)
+ * ^
+ * aa..bb..bb -> couple pending[x] (0;2) puis (0;10)
+ * ^
+ */
+
+ /**
+ * 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(matches, p, start + raw->len);
+
+ }
+
+ }
+
+ purge_pending_matches(matches);
+
+ }
+
+ }
+
+ set_pending_matches_initialized(matches);
+
+}
diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.h b/src/analysis/scan/patterns/tokens/nodes/plain.h
new file mode 100644
index 0000000..33e7feb
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/nodes/plain.h
@@ -0,0 +1,70 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.h - prototypes pour la gestion d'une recherche de motif textuel
+ *
+ * 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_PLAIN_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_H
+
+
+#include <glib-object.h>
+
+
+#include "../node.h"
+#include "../../modifier.h"
+#include "../../../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_TOKEN_NODE_PLAIN g_scan_token_node_plain_get_type()
+#define G_SCAN_TOKEN_NODE_PLAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_NODE_PLAIN, GScanTokenNodePlain))
+#define G_IS_SCAN_TOKEN_NODE_PLAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_NODE_PLAIN))
+#define G_SCAN_TOKEN_NODE_PLAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_NODE_PLAIN, GScanTokenNodePlainClass))
+#define G_IS_SCAN_TOKEN_NODE_PLAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_NODE_PLAIN))
+#define G_SCAN_TOKEN_NODE_PLAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_NODE_PLAIN, GScanTokenNodePlainClass))
+
+
+/* Bribe de motif textuelle pour recherches (instance) */
+typedef struct _GScanTokenNodePlain GScanTokenNodePlain;
+
+/* Bribe de motif textuelle pour recherches (classe) */
+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 */
+
+} ScanPlainNodeFlags;
+
+
+/* Indique le type défini pour un noeud représentant une bribe de texte à retrouver. */
+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);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_NODES_PLAIN_H */
diff --git a/src/analysis/scan/patterns/tokens/plain-int.h b/src/analysis/scan/patterns/tokens/plain-int.h
new file mode 100644
index 0000000..40a71b5
--- /dev/null
+++ b/src/analysis/scan/patterns/tokens/plain-int.h
@@ -0,0 +1,64 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain-int.h - prototypes internes pour la recherche d'une chaîne de caractères brute
+ *
+ * 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_PLAIN_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_INT_H
+
+
+#include "plain.h"
+
+
+#include "atom.h"
+#include "../token-int.h"
+
+
+
+/* Encadrement d'une recherche de texte brut (instance) */
+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) */
+struct _GScanPlainBytesClass
+{
+ GStringTokenClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un gestionnaire de recherche de texte brut. */
+bool g_scan_plain_bytes_create(GScanPlainBytes *, const sized_binary_t *, GScanTokenModifier *, ScanPlainBytesFlags);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_INT_H */
diff --git a/src/analysis/scan/patterns/tokens/plain.c b/src/analysis/scan/patterns/tokens/plain.c
index 9eb731e..26e7dfa 100644
--- a/src/analysis/scan/patterns/tokens/plain.c
+++ b/src/analysis/scan/patterns/tokens/plain.c
@@ -28,59 +28,41 @@
#include <string.h>
-#include "../token-int.h"
+#include "plain-int.h"
/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
-/* Encadrement d'une recherche de texte brut (instance) */
-struct _GPlainBytes
-{
- GStringToken parent; /* A laisser en premier */
-
- uint8_t *raw; /* Octets recherchés */
- size_t allocated; /* Taille allouée */
- size_t used; /* Quantité d'octets utilisée */
-
- phys_t atom_pos; /* Début de sélection atomique */
- phys_t atom_len; /* Taille de ladite sélection */
- phys_t atom_rem; /* Reste après l'atome */
- patid_t pid; /* Identifiant de la bribe */
-
-};
-
-/* Encadrement d'une recherche de texte brut (classe) */
-struct _GPlainBytesClass
-{
- GStringTokenClass parent; /* A laisser en premier */
-
-};
-
-
/* Initialise la classe des recherches de texte brut. */
-static void g_plain_bytes_class_init(GPlainBytesClass *klass);
+static void g_scan_plain_bytes_class_init(GScanPlainBytesClass *klass);
/* Initialise une instance de recherche de texte brut. */
-static void g_plain_bytes_init(GPlainBytes *);
+static void g_scan_plain_bytes_init(GScanPlainBytes *);
/* Supprime toutes les références externes. */
-static void g_plain_bytes_dispose(GPlainBytes *);
+static void g_scan_plain_bytes_dispose(GScanPlainBytes *);
/* Procède à la libération totale de la mémoire. */
-static void g_plain_bytes_finalize(GPlainBytes *);
+static void g_scan_plain_bytes_finalize(GScanPlainBytes *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Affiche un motif de recherche au format texte. */
+static void g_scan_plain_bytes_output_to_text(const GScanPlainBytes *, GScanContext *, int);
+
+/* 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_plain_bytes_enroll(GPlainBytes *, GScanContext *, GEngineBackend *, size_t);
+static bool g_scan_plain_bytes_enroll(GScanPlainBytes *, GScanContext *, GEngineBackend *, size_t);
/* Transforme les correspondances locales en trouvailles. */
-static void g_plain_bytes_check(const GPlainBytes *, GScanContext *, GBinContent *, pending_matches_t *);
+static void g_scan_plain_bytes_check(const GScanPlainBytes *, GScanContext *, GBinContent *, pending_matches_t *);
@@ -90,7 +72,7 @@ static void g_plain_bytes_check(const GPlainBytes *, GScanContext *, GBinContent
/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
-G_DEFINE_TYPE(GPlainBytes, g_plain_bytes, G_TYPE_STRING_TOKEN);
+G_DEFINE_TYPE(GScanPlainBytes, g_scan_plain_bytes, G_TYPE_STRING_TOKEN);
/******************************************************************************
@@ -105,7 +87,7 @@ G_DEFINE_TYPE(GPlainBytes, g_plain_bytes, G_TYPE_STRING_TOKEN);
* *
******************************************************************************/
-static void g_plain_bytes_class_init(GPlainBytesClass *klass)
+static void g_scan_plain_bytes_class_init(GScanPlainBytesClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GSearchPatternClass *pattern; /* Version de classe ancêtre */
@@ -113,26 +95,25 @@ static void g_plain_bytes_class_init(GPlainBytesClass *klass)
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_plain_bytes_dispose;
- object->finalize = (GObjectFinalizeFunc)g_plain_bytes_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_plain_bytes_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_plain_bytes_finalize;
pattern = G_SEARCH_PATTERN_CLASS(klass);
- //pattern->prepare = (prepare_pattern_fc)g_plain_bytes_prepare;
- //pattern->analyze = (analyze_pattern_fc)g_plain_bytes_analyze;
- //pattern->count = (count_pattern_matchs_fc);
+ 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_plain_bytes_enroll;
- token->check = (check_token_fc)g_plain_bytes_check;
+ token->enroll = (enroll_token_fc)g_scan_plain_bytes_enroll;
+ token->check = (check_token_fc)g_scan_plain_bytes_check;
}
/******************************************************************************
* *
-* Paramètres : pattern = instance à initialiser. *
+* Paramètres : bytes = instance à initialiser. *
* *
* Description : Initialise une instance de recherche de texte brut. *
* *
@@ -142,16 +123,15 @@ static void g_plain_bytes_class_init(GPlainBytesClass *klass)
* *
******************************************************************************/
-static void g_plain_bytes_init(GPlainBytes *bytes)
+static void g_scan_plain_bytes_init(GScanPlainBytes *bytes)
{
- bytes->raw = NULL;
- bytes->allocated = 0;
- bytes->used = 0;
+ init_szstr(&bytes->orig);
+ bytes->modifier = NULL;
+ bytes->flags = SPBF_NONE;
- bytes->atom_pos = 0;
- bytes->atom_len = 0;
- bytes->atom_rem = 0;
- bytes->pid = INVALID_PATTERN_ID;
+ bytes->raw = NULL;
+ bytes->atoms = NULL;
+ bytes->count = 0;
}
@@ -168,9 +148,11 @@ static void g_plain_bytes_init(GPlainBytes *bytes)
* *
******************************************************************************/
-static void g_plain_bytes_dispose(GPlainBytes *bytes)
+static void g_scan_plain_bytes_dispose(GScanPlainBytes *bytes)
{
- G_OBJECT_CLASS(g_plain_bytes_parent_class)->dispose(G_OBJECT(bytes));
+ g_clear_object(&bytes->modifier);
+
+ G_OBJECT_CLASS(g_scan_plain_bytes_parent_class)->dispose(G_OBJECT(bytes));
}
@@ -187,20 +169,31 @@ static void g_plain_bytes_dispose(GPlainBytes *bytes)
* *
******************************************************************************/
-static void g_plain_bytes_finalize(GPlainBytes *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);
- G_OBJECT_CLASS(g_plain_bytes_parent_class)->finalize(G_OBJECT(bytes));
+ if (bytes->atoms != NULL)
+ free(bytes->atoms);
+
+ G_OBJECT_CLASS(g_scan_plain_bytes_parent_class)->finalize(G_OBJECT(bytes));
}
/******************************************************************************
* *
-* Paramètres : text = texte brut à rechercher. *
-* len = longueur de ce texte. *
+* Paramètres : text = texte brut à rechercher. *
+* modifier = transformateur éventuel à solliciter. *
+* flags = particularités à prendre en considération. *
* *
* Description : Construit un gestionnaire de recherche de texte brut. *
* *
@@ -210,19 +203,51 @@ static void g_plain_bytes_finalize(GPlainBytes *bytes)
* *
******************************************************************************/
-GSearchPattern *g_plain_bytes_new(const uint8_t *raw, size_t len)
+GSearchPattern *g_scan_plain_bytes_new(const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainBytesFlags flags)
{
- GPlainBytes *result; /* Structure à retourner */
+ GSearchPattern *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_PLAIN_BYTES, NULL);
+ result = g_object_new(G_TYPE_SCAN_PLAIN_BYTES, NULL);
- result->raw = malloc(len);
- result->allocated = len;
- result->used = len;
+ if (!g_scan_plain_bytes_create(G_SCAN_PLAIN_BYTES(result), text, modifier, flags))
+ g_clear_object(&result);
- memcpy(result->raw, raw, len);
+ return result;
+
+}
- return G_SEARCH_PATTERN(result);
+/******************************************************************************
+* *
+* Paramètres : bytes = encadrement de motif à initialiser pleinement. *
+* text = texte brut à rechercher. *
+* modifier = transformateur éventuel à solliciter. *
+* flags = particularités à prendre en considération. *
+* *
+* Description : Met en place un gestionnaire de recherche de texte brut. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_plain_bytes_create(GScanPlainBytes *bytes, const sized_binary_t *text, GScanTokenModifier *modifier, ScanPlainBytesFlags flags)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ szstrdup(&bytes->orig, text);
+
+ if (modifier != NULL)
+ {
+ bytes->modifier = modifier;
+ g_object_ref(G_OBJECT(modifier));
+ }
+
+ bytes->flags = flags;
+
+ return result;
}
@@ -235,6 +260,52 @@ GSearchPattern *g_plain_bytes_new(const uint8_t *raw, size_t len)
/******************************************************************************
* *
+* Paramètres : pattern = définition de motif à considérer. *
+* context = contexte de l'analyse à mener. *
+* fd = canal d'écriture. *
+* *
+* Description : Affiche un motif de recherche au format texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_plain_bytes_output_to_text(const GScanPlainBytes *pattern, GScanContext *context, int fd)
+{
+ G_SEARCH_PATTERN_CLASS(g_scan_plain_bytes_parent_class)->to_text(G_SEARCH_PATTERN(pattern), context, fd);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = définition de motif à considérer. *
+* context = contexte de l'analyse à mener. *
+* padding = éventuel bourrage initial à placer ou NULL. *
+* level = profondeur actuelle. *
+* fd = canal d'écriture. *
+* *
+* Description : Affiche un motif de recherche au format JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_plain_bytes_output_to_json(const GScanPlainBytes *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
+{
+ G_SEARCH_PATTERN_CLASS(g_scan_plain_bytes_parent_class)->to_json(G_SEARCH_PATTERN(pattern), context, padding, level, fd);
+
+ /* TODO */
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : bytes = définition de la bribe à enregistrer. *
* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
@@ -248,39 +319,99 @@ GSearchPattern *g_plain_bytes_new(const uint8_t *raw, size_t len)
* *
******************************************************************************/
-static bool g_plain_bytes_enroll(GPlainBytes *bytes, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+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 */
- result = true;
-
+ if (bytes->modifier == NULL)
+ {
+ bytes->raw = malloc(sizeof(sized_binary_t));
+ bytes->count = 1;
+ szstrdup(&bytes[0].raw[0], &bytes->orig);
- bytes->atom_pos = 0;
+ result = true;
- if (bytes->used > maxsize) // Attention à la position de départ (à retrancher) !
- {
- bytes->atom_len = maxsize;
- bytes->atom_rem = bytes->used - maxsize;
}
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++)
{
- bytes->atom_len = bytes->used;
- bytes->atom_rem = 0;
- }
+ if (bytes->flags & SPBF_CASE_INSENSITIVE)
+ {
+ find_best_atom(&bytes->raw[i], maxsize, &atom, &letters);
+ if (letters == 0)
+ bytes->atoms[i] = atom;
- bytes->pid = g_engine_backend_enroll_plain_pattern(backend, context, bytes->raw, bytes->atom_len);
+ /* 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;
- result = (bytes->pid != INVALID_PATTERN_ID);
+ 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));
- return result;
+ 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
}
@@ -299,76 +430,64 @@ static bool g_plain_bytes_enroll(GPlainBytes *bytes, GScanContext *context, GEng
* *
******************************************************************************/
-static void g_plain_bytes_check(const GPlainBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+static void g_scan_plain_bytes_check(const GScanPlainBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches)
{
- bool initialized; /* Initialisation du suivi ? */
+#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 mindex; /* Indice d'élément à compléter*/
- size_t i; /* Boucle de parcours */
+ 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 */
- initialized = are_pending_matches_initialized(matches);
-
- found = g_scan_context_get_atom_matches(context, bytes->pid, &count);
-
- mindex = 0;
-
- for (i = 0; i < count; i++)
+ for (i = 0; i < bytes->count; i++)
{
- start = found[i] - bytes->atom_pos;
-
- /* Recherche d'un point de départ attendu et conforme ? */
+ raw = &bytes->raw[i];
+ atom = &bytes->atoms[i];
- if (initialized)
- if (!find_target_in_pending_matches(matches, start, &mindex))
- continue;
+ found = g_scan_context_get_atom_matches(context, atom->pid, &count);
- init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
-
- /* Validation du contenu avant l'atome */
-
- if (bytes->atom_pos > 0)
+ for (k = 0; k < count; k++)
{
- ptr = g_binary_content_get_raw_access(content, &pos, bytes->atom_len);
-
- ret = memcmp(bytes->raw + bytes->atom_pos, ptr, bytes->atom_len);
- if (ret != 0) goto exclude_false_positive;
+ start = found[k] - atom->pos;
- }
+ init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
- /* Validation du contenu après l'atome */
+ /* Validation du contenu avant l'atome */
- if (bytes->atom_rem > 0)
- {
- advance_vmpa(&pos, bytes->atom_len);
+ if (atom->pos > 0)
+ {
+ ptr = g_binary_content_get_raw_access(content, &pos, atom->pos);
- ptr = g_binary_content_get_raw_access(content, &pos, bytes->atom_rem);
+ ret = memcmp(raw->data, ptr, atom->pos);
+ if (ret != 0) continue;
- ret = memcmp(bytes->raw + bytes->atom_pos + bytes->atom_len, ptr, bytes->atom_rem);
- if (ret != 0) goto exclude_false_positive;
+ }
- }
+ /* Validation du contenu après l'atome */
- /* Mémorisation de la correspondance */
+ if (atom->rem > 0)
+ {
+ advance_vmpa(&pos, atom->len);
- if (initialized)
- extend_pending_matches(matches, mindex, bytes->used);
- else
- add_pending_matches(matches, start, bytes->used);
+ ptr = g_binary_content_get_raw_access(content, &pos, atom->rem);
- continue;
+ ret = memcmp(raw->data + atom->pos + atom->len, ptr, atom->rem);
+ if (ret != 0) continue;
- exclude_false_positive:
+ }
- if (initialized)
- remove_pending_matches(matches, mindex);
+ /* Mémorisation de la correspondance */
- }
+ add_pending_matches(matches, start, raw->len);
- set_pending_matches_initialized(matches);
+ }
+ }
+#endif
}
diff --git a/src/analysis/scan/patterns/tokens/plain.h b/src/analysis/scan/patterns/tokens/plain.h
index de1d4ec..80a0b4d 100644
--- a/src/analysis/scan/patterns/tokens/plain.h
+++ b/src/analysis/scan/patterns/tokens/plain.h
@@ -26,41 +26,44 @@
#include <glib-object.h>
-#include <stdint.h>
+#include "../modifier.h"
#include "../../pattern.h"
+#include "../../../../common/szstr.h"
-#define G_TYPE_PLAIN_BYTES g_plain_bytes_get_type()
-#define G_PLAIN_BYTES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLAIN_BYTES, GPlainBytes))
-#define G_IS_PLAIN_BYTES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLAIN_BYTES))
-#define G_PLAIN_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLAIN_BYTES, GPlainBytesClass))
-#define G_IS_PLAIN_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLAIN_BYTES))
-#define G_PLAIN_BYTES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLAIN_BYTES, GPlainBytesClass))
+#define G_TYPE_SCAN_PLAIN_BYTES g_scan_plain_bytes_get_type()
+#define G_SCAN_PLAIN_BYTES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PLAIN_BYTES, GScanPlainBytes))
+#define G_IS_SCAN_PLAIN_BYTES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PLAIN_BYTES))
+#define G_SCAN_PLAIN_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PLAIN_BYTES, GScanPlainBytesClass))
+#define G_IS_SCAN_PLAIN_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PLAIN_BYTES))
+#define G_SCAN_PLAIN_BYTES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PLAIN_BYTES, GScanPlainBytesClass))
/* Représentation d'une suite d'octets à retrouver (instance) */
-typedef struct _GPlainBytes GPlainBytes;
+typedef struct _GScanPlainBytes GScanPlainBytes;
/* Représentation d'une suite d'octets à retrouver (classe) */
-typedef struct _GPlainBytesClass GPlainBytesClass;
+typedef struct _GScanPlainBytesClass GScanPlainBytesClass;
/* Propriétés d'un élément textuel à rechercher */
-typedef enum _StringTokenAttrib
+typedef enum _ScanPlainBytesFlags
{
- STP_CASE_INSENSITIVE,
+ SPBF_NONE = 0x0, /* Aucune particularité */
+ SPBF_CASE_INSENSITIVE = 0x1, /* Ignorance de la casse */
+ SPBF_FULL_WORD = 0x2, /* Recherche de mot entier */
-} StringTokenAttrib;
+} ScanPlainBytesFlags;
/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */
-GType g_plain_bytes_get_type(void);
+GType g_scan_plain_bytes_get_type(void);
/* Construit un gestionnaire de recherche de texte brut. */
-GSearchPattern *g_plain_bytes_new(const uint8_t *, size_t);
+GSearchPattern *g_scan_plain_bytes_new(const sized_binary_t *, GScanTokenModifier *, ScanPlainBytesFlags);