summaryrefslogtreecommitdiff
path: root/src/analysis
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2023-08-18 00:07:39 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2023-08-18 00:07:39 (GMT)
commit2424c52c4f3bc44ce5f36348442cfa103e0989c2 (patch)
treef68aea488f403b234d4fcc6fd6e0f7b88a628ac8 /src/analysis
parent1c5a0e67186def152536d9c506e2e6c3a3a265c5 (diff)
Create some modifiers and handle match properties inside ROST.
Diffstat (limited to 'src/analysis')
-rw-r--r--src/analysis/scan/context-int.h1
-rw-r--r--src/analysis/scan/context.c93
-rw-r--r--src/analysis/scan/context.h11
-rw-r--r--src/analysis/scan/core.c162
-rw-r--r--src/analysis/scan/core.h13
-rw-r--r--src/analysis/scan/expr-int.h4
-rw-r--r--src/analysis/scan/expr.c20
-rw-r--r--src/analysis/scan/expr.h6
-rw-r--r--src/analysis/scan/exprs/Makefile.am4
-rw-r--r--src/analysis/scan/exprs/counter.c22
-rw-r--r--src/analysis/scan/exprs/handler-int.h58
-rw-r--r--src/analysis/scan/exprs/handler.c402
-rw-r--r--src/analysis/scan/exprs/handler.h66
-rw-r--r--src/analysis/scan/exprs/item-int.h58
-rw-r--r--src/analysis/scan/exprs/item.c346
-rw-r--r--src/analysis/scan/exprs/item.h55
-rw-r--r--src/analysis/scan/exprs/literal.c5
-rw-r--r--src/analysis/scan/exprs/set.c10
-rw-r--r--src/analysis/scan/grammar.y559
-rw-r--r--src/analysis/scan/items/count.c2
-rw-r--r--src/analysis/scan/match-int.h10
-rw-r--r--src/analysis/scan/match.c92
-rw-r--r--src/analysis/scan/match.h14
-rw-r--r--src/analysis/scan/matches/bytes-int.h6
-rw-r--r--src/analysis/scan/matches/bytes.c270
-rw-r--r--src/analysis/scan/matches/bytes.h26
-rw-r--r--src/analysis/scan/matches/pending.c243
-rw-r--r--src/analysis/scan/matches/pending.h32
-rw-r--r--src/analysis/scan/options-int.h2
-rw-r--r--src/analysis/scan/options.c86
-rw-r--r--src/analysis/scan/options.h12
-rw-r--r--src/analysis/scan/pattern-int.h13
-rw-r--r--src/analysis/scan/pattern.c111
-rw-r--r--src/analysis/scan/pattern.h18
-rw-r--r--src/analysis/scan/patterns/Makefile.am7
-rw-r--r--src/analysis/scan/patterns/modifier-int.h59
-rw-r--r--src/analysis/scan/patterns/modifier.c181
-rw-r--r--src/analysis/scan/patterns/modifier.h62
-rw-r--r--src/analysis/scan/patterns/modifiers/Makefile.am17
-rw-r--r--src/analysis/scan/patterns/modifiers/hex.c252
-rw-r--r--src/analysis/scan/patterns/modifiers/hex.h58
-rw-r--r--src/analysis/scan/patterns/modifiers/list-int.h54
-rw-r--r--src/analysis/scan/patterns/modifiers/list.c405
-rw-r--r--src/analysis/scan/patterns/modifiers/list.h68
-rw-r--r--src/analysis/scan/patterns/modifiers/plain.c245
-rw-r--r--src/analysis/scan/patterns/modifiers/plain.h58
-rw-r--r--src/analysis/scan/patterns/modifiers/rev.c247
-rw-r--r--src/analysis/scan/patterns/modifiers/rev.h58
-rw-r--r--src/analysis/scan/patterns/token-int.h6
-rw-r--r--src/analysis/scan/patterns/token.c180
-rw-r--r--src/analysis/scan/patterns/token.h1
-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
-rw-r--r--src/analysis/scan/rule-int.h6
-rw-r--r--src/analysis/scan/rule.c194
-rw-r--r--src/analysis/scan/rule.h13
-rw-r--r--src/analysis/scan/scanner.c116
-rw-r--r--src/analysis/scan/scanner.h13
-rw-r--r--src/analysis/scan/tokens.l495
76 files changed, 7897 insertions, 524 deletions
diff --git a/src/analysis/scan/context-int.h b/src/analysis/scan/context-int.h
index 3a971b8..8a5fbaf 100644
--- a/src/analysis/scan/context-int.h
+++ b/src/analysis/scan/context-int.h
@@ -74,6 +74,7 @@ struct _GScanContext
GScanOptions *options; /* Options d'analyses */
GBinContent *content; /* Contenu binaire traité */
+ bool scan_done; /* Phase d'analyse terminée ? */
patid_t next_patid; /* Prochain indice utilisable */
diff --git a/src/analysis/scan/context.c b/src/analysis/scan/context.c
index f108e93..a3be86b 100644
--- a/src/analysis/scan/context.c
+++ b/src/analysis/scan/context.c
@@ -55,7 +55,7 @@ static void add_match_to_full_match_tracker(full_match_tracker_t *, GScanMatch *
-
+/* --------------------- MEMORISATION DE PROGRESSIONS D'ANALYSE --------------------- */
/* Initialise la classe des contextes de suivi d'analyses. */
@@ -72,10 +72,6 @@ static void g_scan_context_finalize(GScanContext *);
-
-
-
-
/* ---------------------------------------------------------------------------------- */
/* ADMINISTRATION DES CORRESPONDANCES TOTALES */
/* ---------------------------------------------------------------------------------- */
@@ -191,10 +187,9 @@ static void add_match_to_full_match_tracker(full_match_tracker_t *tracker, GScan
-
-
-
-
+/* ---------------------------------------------------------------------------------- */
+/* MEMORISATION DE PROGRESSIONS D'ANALYSE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini pour un contexte de suivi d'analyse. */
@@ -242,6 +237,7 @@ static void g_scan_context_init(GScanContext *context)
context->options = NULL;
context->content = NULL;
+ context->scan_done = false;
context->next_patid = 0;
@@ -378,7 +374,7 @@ GScanContext *g_scan_context_new(GScanOptions *options)
* *
******************************************************************************/
-GScanOptions *g_scan_context_get_options(GScanContext *context)
+GScanOptions *g_scan_context_get_options(const GScanContext *context)
{
GScanOptions *result; /* Ensemble à retourner */
@@ -467,6 +463,48 @@ GBinContent *g_scan_context_get_content(const GScanContext *context)
/******************************************************************************
* *
+* Paramètres : context = instance à consulter. *
+* *
+* Description : Indique si la phase d'analyse de contenu est terminée. *
+* *
+* Retour : true si la phase de scan est terminée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_context_is_scan_done(const GScanContext *context)
+{
+ bool result; /* Statut à retourner */
+
+ result = context->scan_done;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à mettre à jour. *
+* *
+* Description : Note que la phase d'analyse de contenu est terminée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_context_mark_scan_as_done(GScanContext *context)
+{
+ context->scan_done = true;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : context = instance à mettre à jour. *
* id = identifiant du motif trouvé. *
* offset = localisation du motif au sein d'un contenu. *
@@ -615,41 +653,6 @@ const GScanMatch **g_scan_context_get_full_matches(const GScanContext *context,
/******************************************************************************
* *
-* Paramètres : context = mémoire de résultats d'analyse à consulter. *
-* *
-* Description : Affiche les correspondances identifiées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_scan_context_display(GScanContext *context)
-{
- size_t i; /* Boucle de parcours */
- const rule_condition_t *cond; /* Conditions de orrespondance */
-
- /*
- FIXME : ordre
- for (i = 0; i < context->full_used; i++)
- g_scan_match_display(context->full_matches[i]);
- */
-
- for (i = 0; i < context->cond_count; i++)
- {
- cond = &context->conditions[i];
-
- if (g_scan_context_has_match_for_rule(context, cond->name))
- fprintf(stderr, "Rule '%s' has matched!\n", cond->name);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : context = mémoire de résultats d'analyse à compléter. *
* name = désignation de la règle ciblée. *
* expr = expression de condition à réduire. *
diff --git a/src/analysis/scan/context.h b/src/analysis/scan/context.h
index 563a53e..ff6b373 100644
--- a/src/analysis/scan/context.h
+++ b/src/analysis/scan/context.h
@@ -66,7 +66,7 @@ GType g_scan_context_get_type(void);
GScanContext *g_scan_context_new(GScanOptions *);
/* Fournit l'ensemble des options à respecter pour les analyses. */
-GScanOptions *g_scan_context_get_options(GScanContext *);
+GScanOptions *g_scan_context_get_options(const GScanContext *);
/* Fournit un identifiant unique pour un motif recherché. */
patid_t g_scan_context_get_new_pattern_id(GScanContext *);
@@ -77,6 +77,12 @@ void g_scan_context_set_content(GScanContext *, GBinContent *);
/* Fournit une référence au contenu principal analysé. */
GBinContent *g_scan_context_get_content(const GScanContext *);
+/* Indique si la phase d'analyse de contenu est terminée. */
+bool g_scan_context_is_scan_done(const GScanContext *);
+
+/* Note que la phase d'analyse de contenu est terminée. */
+void g_scan_context_mark_scan_as_done(GScanContext *);
+
/* Enregistre une correspondance partielle dans un contenu. */
void g_scan_context_register_atom_match(GScanContext *, patid_t, phys_t);
@@ -89,9 +95,6 @@ void g_scan_context_register_full_match(GScanContext *, GScanMatch *);
/* Fournit la liste de toutes les correspondances d'un motif. */
const GScanMatch **g_scan_context_get_full_matches(const GScanContext *, const GSearchPattern *, size_t *);
-/* Affiche les correspondances identifiées. */
-void g_scan_context_display(GScanContext *);
-
/* Intègre une condition de correspondance pour règle. */
bool g_scan_context_set_rule_condition(GScanContext *, const char *, const GScanExpression *);
diff --git a/src/analysis/scan/core.c b/src/analysis/scan/core.c
index d940ab5..d102d58 100644
--- a/src/analysis/scan/core.c
+++ b/src/analysis/scan/core.c
@@ -25,6 +25,8 @@
#include <config.h>
+#include <malloc.h>
+#include <string.h>
#include "items/count.h"
@@ -38,8 +40,168 @@
#endif
#include "items/time/make.h"
#include "items/time/now.h"
+#include "patterns/modifiers/hex.h"
+#include "patterns/modifiers/plain.h"
+#include "patterns/modifiers/rev.h"
+/* Liste des modificateurs disponibles */
+
+typedef struct _available_modifier_t
+{
+ char *name; /* Désignation humaine */
+ GScanTokenModifier *instance; /* Mécanisme correspondant */
+
+} available_modifier_t;
+
+static available_modifier_t *__modifiers = NULL;
+static size_t __modifiers_count = 0;
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à rendre disponible. *
+* *
+* Description : Inscrit un modificateur dans la liste des disponibles. *
+* *
+* Retour : Bilan des enregistrements effectués : true si nouveauté. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool register_scan_token_modifier(GScanTokenModifier *modifier)
+{
+ bool result; /* Bilan à retourner */
+ char *name; /* Nom donné au modificateur */
+ GScanTokenModifier *found; /* Alternative présente */
+ available_modifier_t *last; /* Emplacement disponible */
+
+ name = g_scan_token_modifier_get_name(modifier);
+
+ found = find_scan_token_modifiers_for_name(name);
+
+ result = (found == NULL);
+
+ if (!result)
+ free(name);
+
+ else
+ {
+ __modifiers_count++;
+ __modifiers = realloc(__modifiers, __modifiers_count * sizeof(available_modifier_t));
+
+ last = &__modifiers[__modifiers_count - 1];
+
+ last->name = name;
+ last->instance = modifier;
+
+ g_object_ref(G_OBJECT(modifier));
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Charge tous les modificateurs de base. *
+* *
+* Retour : Bilan des opérations d'enregistrement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_all_known_scan_token_modifiers(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+#define REGISTER_SCAN_MODIFIER(m) \
+ ({ \
+ bool __status; \
+ __status = register_scan_token_modifier(m); \
+ g_object_unref(G_OBJECT(m)); \
+ __status; \
+ })
+
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_hex_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_plain_modifier_new());
+ if (result) result = REGISTER_SCAN_MODIFIER(g_scan_reverse_modifier_new());
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Décharge tous les modificateurs inscrits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void unload_all_scan_token_modifiers(void)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < __modifiers_count; i++)
+ g_object_unref(G_OBJECT(__modifiers[i].instance));
+
+ if (__modifiers != NULL)
+ free(__modifiers);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : name = désignation du modificateur recherché. *
+* *
+* Description : Fournit le modificateur correspondant à un nom. *
+* *
+* Retour : Instance du modificateur identifié ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *find_scan_token_modifiers_for_name(const char *name)
+{
+ GScanTokenModifier *result; /* Instance à renvoyer */
+ size_t i; /* Boucle de parcours */
+ available_modifier_t *registered; /* Infos d'enregistrement */
+
+ result = NULL;
+
+ for (i = 0; i < __modifiers_count; i++)
+ {
+ registered = __modifiers + i;
+
+ if (strcmp(registered->name, name) == 0)
+ {
+ result = registered->instance;
+ g_object_ref(G_OBJECT(result));
+ break;
+ }
+
+ }
+
+ return result;
+
+}
+
/******************************************************************************
* *
diff --git a/src/analysis/scan/core.h b/src/analysis/scan/core.h
index 21d6e7c..86a47da 100644
--- a/src/analysis/scan/core.h
+++ b/src/analysis/scan/core.h
@@ -26,9 +26,22 @@
#include "space.h"
+#include "patterns/modifier.h"
+/* Inscrit un modificateur dans la liste des disponibles. */
+bool register_scan_token_modifier(GScanTokenModifier *);
+
+/* Charge tous les modificateurs de base. */
+bool load_all_known_scan_token_modifiers(void);
+
+/* Décharge tous les modificateurs inscrits. */
+void unload_all_scan_token_modifiers(void);
+
+/* Fournit le modificateur correspondant à un nom. */
+GScanTokenModifier *find_scan_token_modifiers_for_name(const char *);
+
/* Inscrit les principales fonctions dans l'espace racine. */
bool populate_main_scan_namespace(GScanNamespace *);
diff --git a/src/analysis/scan/expr-int.h b/src/analysis/scan/expr-int.h
index 48668b5..30a32d0 100644
--- a/src/analysis/scan/expr-int.h
+++ b/src/analysis/scan/expr-int.h
@@ -54,10 +54,10 @@ typedef ScanReductionState (* reduce_expr_fc) (GScanExpression *, GScanContext *
typedef bool (* reduce_expr_to_bool_fc) (GScanExpression *, GScanContext *, GScanScope *, GScanExpression **);
/* Dénombre les éléments portés par une expression. */
-typedef bool (* count_scan_expr_fc) (const GScanExpression *, size_t *);
+typedef bool (* count_scan_expr_fc) (const GScanExpression *, GScanContext *, size_t *);
/* Fournit un élément donné issu d'un ensemble constitué. */
-typedef bool (* get_scan_expr_fc) (const GScanExpression *, size_t, GScanExpression **);
+typedef bool (* get_scan_expr_fc) (const GScanExpression *, size_t, GScanContext *, GScanExpression **);
/* Réalise l'intersection entre deux ensembles. */
typedef GScanExpression * (* intersect_scan_expr_fc) (GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
diff --git a/src/analysis/scan/expr.c b/src/analysis/scan/expr.c
index 808b14f..2b00544 100644
--- a/src/analysis/scan/expr.c
+++ b/src/analysis/scan/expr.c
@@ -466,6 +466,7 @@ bool g_scan_expression_handle_set_features(const GScanExpression *expr)
/******************************************************************************
* *
* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
* count = quantité d'éléments déterminée. [OUT] *
* *
* Description : Dénombre les éléments portés par une expression. *
@@ -476,7 +477,7 @@ bool g_scan_expression_handle_set_features(const GScanExpression *expr)
* *
******************************************************************************/
-bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
+bool g_scan_expression_count_items(const GScanExpression *expr, GScanContext *ctx, size_t *count)
{
bool result; /* Bilan à retourner */
GScanExpressionClass *class; /* Classe à activer */
@@ -486,7 +487,7 @@ bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
class = G_SCAN_EXPRESSION_GET_CLASS(expr);
if (class->count != NULL)
- result = class->count(expr, count);
+ result = class->count(expr, ctx, count);
else
result = false;
@@ -504,6 +505,7 @@ bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
* *
* Paramètres : expr = expression à consulter. *
* index = indice de l'élément à transférer. *
+* ctx = contexte de suivi de l'analyse courante. *
* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Fournit un élément donné issu d'un ensemble constitué. *
@@ -514,7 +516,7 @@ bool g_scan_expression_count_items(const GScanExpression *expr, size_t *count)
* *
******************************************************************************/
-bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScanExpression **out)
+bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScanContext *ctx, GScanExpression **out)
{
bool result; /* Bilan à retourner */
GScanExpressionClass *class; /* Classe à activer */
@@ -525,7 +527,7 @@ bool g_scan_expression_get_item(const GScanExpression *expr, size_t index, GScan
if (class->get != NULL)
{
- result = class->get(expr, index, out);
+ result = class->get(expr, index, ctx, out);
if (*out != NULL)
g_object_ref(G_OBJECT(*out));
@@ -574,27 +576,27 @@ static GScanExpression *_g_scan_expression_intersect(GScanExpression *expr, cons
result = NULL;
- valid = g_scan_expression_count_items(other, &other_count);
+ valid = g_scan_expression_count_items(other, ctx, &other_count);
if (!valid) goto done;
/* Intersection entre deux ensembles ? */
if (g_scan_expression_handle_set_features(expr))
{
- valid = g_scan_expression_count_items(expr, &expr_count);
+ valid = g_scan_expression_count_items(expr, ctx, &expr_count);
if (!valid) goto done;
result = g_scan_generic_set_new();
for (k = 0; k < expr_count; k++)
{
- valid = g_scan_expression_get_item(expr, k, &item);
+ valid = g_scan_expression_get_item(expr, k, ctx, &item);
if (!valid) break;
comparable = G_COMPARABLE_ITEM(item);
for (i = 0; i < other_count; i++)
{
- valid = g_scan_expression_get_item(other, i, &item);
+ valid = g_scan_expression_get_item(other, i, ctx, &item);
if (!valid) break;
valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status);
@@ -619,7 +621,7 @@ static GScanExpression *_g_scan_expression_intersect(GScanExpression *expr, cons
for (i = 0; i < other_count && result == NULL; i++)
{
- valid = g_scan_expression_get_item(other, i, &item);
+ valid = g_scan_expression_get_item(other, i, ctx, &item);
if (!valid) break;
valid = g_comparable_item_compare_rich(comparable, G_COMPARABLE_ITEM(item), RCO_EQ, &status);
diff --git a/src/analysis/scan/expr.h b/src/analysis/scan/expr.h
index dd4bc3f..797abec 100644
--- a/src/analysis/scan/expr.h
+++ b/src/analysis/scan/expr.h
@@ -50,7 +50,7 @@ typedef struct _GScanExpressionClass GScanExpressionClass;
/* Types naturel équivalant à l'expression */
-typedef enum _ExprValueType
+typedef enum _ExprValueType /* REMME */
{
EVT_BOOLEAN, /* Valeur booléenne */
EVT_INTEGER, /* Nombre entier 64 bits */
@@ -97,10 +97,10 @@ bool g_scan_expression_reduce_to_boolean(GScanExpression *, GScanContext *, GSca
bool g_scan_expression_handle_set_features(const GScanExpression *);
/* Dénombre les éléments portés par une expression. */
-bool g_scan_expression_count_items(const GScanExpression *, size_t *);
+bool g_scan_expression_count_items(const GScanExpression *, GScanContext *, size_t *);
/* Fournit un élément donné issu d'un ensemble constitué. */
-bool g_scan_expression_get_item(const GScanExpression *, size_t, GScanExpression **);
+bool g_scan_expression_get_item(const GScanExpression *, size_t, GScanContext *, GScanExpression **);
/* Réalise l'intersection entre deux ensembles. */
GScanExpression *g_scan_expression_intersect(GScanExpression *, const GScanExpression *, GScanContext *, GScanScope *);
diff --git a/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am
index 1266a63..d1a122a 100644
--- a/src/analysis/scan/exprs/Makefile.am
+++ b/src/analysis/scan/exprs/Makefile.am
@@ -11,8 +11,12 @@ libanalysisscanexprs_la_SOURCES = \
call.h call.c \
counter-int.h \
counter.h counter.c \
+ handler-int.h \
+ handler.h handler.c \
intersect-int.h \
intersect.h intersect.c \
+ item-int.h \
+ item.h item.c \
literal-int.h \
literal.h literal.c \
logical-int.h \
diff --git a/src/analysis/scan/exprs/counter.c b/src/analysis/scan/exprs/counter.c
index 290fd02..bb4e523 100644
--- a/src/analysis/scan/exprs/counter.c
+++ b/src/analysis/scan/exprs/counter.c
@@ -50,7 +50,7 @@ static void g_scan_match_counter_finalize(GScanMatchCounter *);
/* Réduit une expression à une forme plus simple. */
-static bool g_scan_match_counter_reduce(GScanMatchCounter *, GScanContext *, GScanScope *, GScanExpression **);
+static ScanReductionState g_scan_match_counter_reduce(GScanMatchCounter *, GScanContext *, GScanScope *, GScanExpression **);
@@ -226,22 +226,22 @@ bool g_scan_match_counter_create(GScanMatchCounter *counter, GSearchPattern *pat
* *
******************************************************************************/
-static bool g_scan_match_counter_reduce(GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+static ScanReductionState g_scan_match_counter_reduce(GScanMatchCounter *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- bool result; /* Bilan à retourner */
+ ScanReductionState result; /* Etat synthétisé à retourner */
size_t count; /* Quantité de correspondances */
- const GScanMatch **matches; /* Correspondances établies */
-
-
- matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count);
+ if (g_scan_context_is_scan_done(ctx))
+ {
+ g_scan_context_get_full_matches(ctx, expr->pattern, &count);
- printf("matches: %zu\n", count);
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count });
+ result = SRS_REDUCED;
- *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ count });
- result = true;
-
+ }
+ else
+ result = SRS_WAIT_FOR_SCAN;
return result;
diff --git a/src/analysis/scan/exprs/handler-int.h b/src/analysis/scan/exprs/handler-int.h
new file mode 100644
index 0000000..f707fdb
--- /dev/null
+++ b/src/analysis/scan/exprs/handler-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * handler-int.h - prototypes internes pour la manipulation des correspondances établies lors d'un scan
+ *
+ * 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_EXPRS_HANDLER_INT_H
+#define _ANALYSIS_SCAN_EXPRS_HANDLER_INT_H
+
+
+#include "handler.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Manipulation des correspondances établies lors d'un scan de binaire (instance) */
+struct _GScanPatternHandler
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GSearchPattern *pattern; /* Motif associé */
+ ScanHandlerType type; /* Manipulation attendue */
+
+};
+
+/* Manipulation des correspondances établies lors d'un scan de binaire (classe) */
+struct _GScanPatternHandlerClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une manipulation de correspondances établies. */
+bool g_scan_pattern_handler_create(GScanPatternHandler *, GSearchPattern *, ScanHandlerType);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_HANDLER_INT_H */
diff --git a/src/analysis/scan/exprs/handler.c b/src/analysis/scan/exprs/handler.c
new file mode 100644
index 0000000..a14140a
--- /dev/null
+++ b/src/analysis/scan/exprs/handler.c
@@ -0,0 +1,402 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * handler.c - manipulation des correspondances établies lors d'un scan
+ *
+ * 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 "handler.h"
+
+
+#include <assert.h>
+
+
+#include "literal.h"
+#include "handler-int.h"
+#include "../matches/bytes.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des manipulations de correspondances. */
+static void g_scan_pattern_handler_class_init(GScanPatternHandlerClass *);
+
+/* Initialise une instance de manipulation de correspondances. */
+static void g_scan_pattern_handler_init(GScanPatternHandler *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_pattern_handler_dispose(GScanPatternHandler *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_pattern_handler_finalize(GScanPatternHandler *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_pattern_handler_reduce(GScanPatternHandler *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Réduit une expression à une forme booléenne. */
+static bool g_scan_pattern_handler_reduce_to_boolean(GScanPatternHandler *, GScanContext *, GScanScope *, GScanExpression **);
+
+/* Dénombre les éléments portés par une expression. */
+static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *, GScanContext *, size_t *);
+
+/* Fournit un élément donné issu d'un ensemble constitué. */
+static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *, size_t, GScanContext *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une manipulation de correspondances établies lors d'un scan. */
+G_DEFINE_TYPE(GScanPatternHandler, g_scan_pattern_handler, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des manipulations de correspondances. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pattern_handler_class_init(GScanPatternHandlerClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pattern_handler_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_pattern_handler_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_pattern_handler_reduce;
+ expr->reduce_to_bool = (reduce_expr_to_bool_fc)g_scan_pattern_handler_reduce_to_boolean;
+ expr->count = (count_scan_expr_fc)g_scan_pattern_handler_count_items;
+ expr->get = (get_scan_expr_fc)g_scan_pattern_handler_get_item;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = instance à initialiser. *
+* *
+* Description : Initialise une instance de manipulation de correspondances. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pattern_handler_init(GScanPatternHandler *handler)
+{
+ handler->pattern = NULL;
+ handler->type = SHT_RAW;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pattern_handler_dispose(GScanPatternHandler *handler)
+{
+ g_clear_object(&handler->pattern);
+
+ G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->dispose(G_OBJECT(handler));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_pattern_handler_finalize(GScanPatternHandler *handler)
+{
+ G_OBJECT_CLASS(g_scan_pattern_handler_parent_class)->finalize(G_OBJECT(handler));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = motif à impliquer. *
+* type = type de manipulation attendue. *
+* *
+* Description : Met en place une manipulation de correspondances établies. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_pattern_handler_new(GSearchPattern *pattern, ScanHandlerType type)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_PATTERN_HANDLER, NULL);
+
+ if (!g_scan_pattern_handler_create(G_SCAN_PATTERN_HANDLER(result), pattern, type))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : handler = instance à initialiser pleinement. *
+* pattern = motif à impliquer. *
+* type = type de manipulation attendue. *
+* *
+* Description : Met en place une manipulation de correspondances établies. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_pattern_handler_create(GScanPatternHandler *handler, GSearchPattern *pattern, ScanHandlerType type)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ handler->pattern = pattern;
+ g_object_ref(G_OBJECT(pattern));
+
+ handler->type = type;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_pattern_handler_reduce(GScanPatternHandler *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+
+ if (g_scan_context_is_scan_done(ctx))
+ result = SRS_REDUCED;
+
+ else
+ result = SRS_WAIT_FOR_SCAN;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme booléenne. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_pattern_handler_reduce_to_boolean(GScanPatternHandler *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Quantité de correspondances */
+
+ result = true;
+
+ g_scan_context_get_full_matches(ctx, expr->pattern, &count);
+
+ *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 });
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* count = quantité d'éléments déterminée. [OUT] *
+* *
+* Description : Dénombre les éléments portés par une expression. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_pattern_handler_count_items(const GScanPatternHandler *expr, GScanContext *ctx, size_t *count)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ assert(g_scan_context_is_scan_done(ctx));
+
+ g_scan_context_get_full_matches(ctx, expr->pattern, count);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* index = indice de l'élément à transférer. *
+* ctx = contexte de suivi de l'analyse courante. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Fournit un élément donné issu d'un ensemble constitué. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_pattern_handler_get_item(const GScanPatternHandler *expr, size_t index, GScanContext *ctx, GScanExpression **out)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Quantité de correspondances */
+ const GScanMatch **matches; /* Correspondances en place */
+ const GScanBytesMatch *match; /* Correspondance ciblée */
+ phys_t start; /* Point de départ du motif */
+ phys_t end; /* Point d'arrivée du motif */
+ phys_t len; /* Taille du motif */
+ GBinContent *content; /* Contenu binaire à relire */
+ vmpa2t pos; /* Tête de lecture */
+ const bin_t *data; /* Accès aux données brutes */
+ sized_string_t binary; /* Conversion de formats */
+
+ assert(g_scan_context_is_scan_done(ctx));
+
+ matches = g_scan_context_get_full_matches(ctx, expr->pattern, &count);
+
+ result = (index < count);
+ if (!result) goto done;
+
+ result = G_IS_SCAN_BYTES_MATCH(matches[index]);
+ if (!result) goto done;
+
+ match = G_SCAN_BYTES_MATCH(matches[index]);
+
+ len = g_scan_bytes_match_get_location(match, &start, &end);
+
+ switch (expr->type)
+ {
+ case SHT_RAW:
+ content = g_scan_bytes_match_get_content(match);
+
+ init_vmpa(&pos, start, VMPA_NO_VIRTUAL);
+
+ data = g_binary_content_get_raw_access(content, &pos, len);
+
+ binary.data = data;
+ binary.len = len;
+
+ *out = g_scan_literal_expression_new(LVT_STRING, &binary);
+
+ g_object_unref(G_OBJECT(content));
+ break;
+
+ case SHT_START:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ start });
+ break;
+
+ case SHT_LENGTH:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ len });
+ break;
+
+ case SHT_END:
+ *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ end });
+ break;
+
+ }
+
+ done:
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/handler.h b/src/analysis/scan/exprs/handler.h
new file mode 100644
index 0000000..8ad700a
--- /dev/null
+++ b/src/analysis/scan/exprs/handler.h
@@ -0,0 +1,66 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * handler.h - prototypes pour la manipulation des correspondances établies lors d'un scan
+ *
+ * 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_EXPRS_HANDLER_H
+#define _ANALYSIS_SCAN_EXPRS_HANDLER_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_PATTERN_HANDLER g_scan_pattern_handler_get_type()
+#define G_SCAN_PATTERN_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PATTERN_HANDLER, GScanPatternHandler))
+#define G_IS_SCAN_PATTERN_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PATTERN_HANDLER))
+#define G_SCAN_PATTERN_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PATTERN_HANDLER, GScanPatternHandlerClass))
+#define G_IS_SCAN_PATTERN_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PATTERN_HANDLER))
+#define G_SCAN_PATTERN_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PATTERN_HANDLER, GScanPatternHandlerClass))
+
+
+/* Manipulation des correspondances établies lors d'un scan de binaire (instance) */
+typedef struct _GScanPatternHandler GScanPatternHandler;
+
+/* Manipulation des correspondances établies lors d'un scan de binaire (classe) */
+typedef struct _GScanPatternHandlerClass GScanPatternHandlerClass;
+
+
+/* Type de manipulation représentée */
+typedef enum _ScanHandlerType
+{
+ SHT_RAW, /* Correspondances brutes */
+ SHT_START, /* Départs de correspondances */
+ SHT_LENGTH, /* Taille de correspondances */
+ SHT_END, /* Fins de correspondances */
+
+} ScanHandlerType;
+
+
+/* Indique le type défini pour une manipulation de correspondances établies lors d'un scan. */
+GType g_scan_pattern_handler_get_type(void);
+
+/* Met en place une manipulation de correspondances établies. */
+GScanExpression *g_scan_pattern_handler_new(GSearchPattern *, ScanHandlerType);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_HANDLER_H */
diff --git a/src/analysis/scan/exprs/item-int.h b/src/analysis/scan/exprs/item-int.h
new file mode 100644
index 0000000..56b159a
--- /dev/null
+++ b/src/analysis/scan/exprs/item-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item-int.h - prototypes internes pour la récupération d'un élément à partir d'une série
+ *
+ * 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_EXPRS_ITEM_INT_H
+#define _ANALYSIS_SCAN_EXPRS_ITEM_INT_H
+
+
+#include "item.h"
+
+
+#include "../expr-int.h"
+
+
+
+/* Accès à un élément donné d'une série établie (instance) */
+struct _GScanSetItem
+{
+ GScanExpression parent; /* A laisser en premier */
+
+ GScanExpression *set; /* Série d'éléments à consulter*/
+ GScanExpression *index; /* Indice de l'élément visé */
+
+};
+
+/* Accès à un élément donné d'une série établie (classe) */
+struct _GScanSetItemClass
+{
+ GScanExpressionClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un accès à un élément donné d'une série. */
+bool g_scan_set_item_create(GScanSetItem *, GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ITEM_INT_H */
diff --git a/src/analysis/scan/exprs/item.c b/src/analysis/scan/exprs/item.c
new file mode 100644
index 0000000..a6b22f0
--- /dev/null
+++ b/src/analysis/scan/exprs/item.c
@@ -0,0 +1,346 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.c - récupération d'un élément à partir d'une série
+ *
+ * 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 "set.h"
+
+
+#include <assert.h>
+
+
+#include "literal.h"
+#include "item-int.h"
+
+
+
+/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */
+
+
+/* Initialise la classe des accès à un élément de série. */
+static void g_scan_set_item_class_init(GScanSetItemClass *);
+
+/* Initialise une instance d'accès à un élément de série. */
+static void g_scan_set_item_init(GScanSetItem *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_set_item_dispose(GScanSetItem *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_set_item_finalize(GScanSetItem *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réduit une expression à une forme plus simple. */
+static ScanReductionState g_scan_set_item_reduce(GScanSetItem *, GScanContext *, GScanScope *, GScanExpression **);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour la récupération d'un élément à partir d'une série. */
+G_DEFINE_TYPE(GScanSetItem, g_scan_set_item, G_TYPE_SCAN_EXPRESSION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des accès à un élément de série. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_set_item_class_init(GScanSetItemClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanExpressionClass *expr; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_set_item_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_set_item_finalize;
+
+ expr = G_SCAN_EXPRESSION_CLASS(klass);
+
+ expr->reduce = (reduce_expr_fc)g_scan_set_item_reduce;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance à initialiser. *
+* *
+* Description : Initialise une instance d'accès à un élément de série. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_set_item_init(GScanSetItem *item)
+{
+ item->set = NULL;
+ item->index = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_set_item_dispose(GScanSetItem *item)
+{
+ g_clear_object(&item->set);
+ g_clear_object(&item->index);
+
+ G_OBJECT_CLASS(g_scan_set_item_parent_class)->dispose(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_set_item_finalize(GScanSetItem *item)
+{
+ G_OBJECT_CLASS(g_scan_set_item_parent_class)->finalize(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : set = ensemble d'éléments à considérer. *
+* index = indice de l'élément à viser. *
+* *
+* Description : Met en place un accès à un élément donné d'une série. *
+* *
+* Retour : Expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanExpression *g_scan_set_item_new(GScanExpression *set, GScanExpression *index)
+{
+ GScanExpression *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_SET_ITEM, NULL);
+
+ if (!g_scan_set_item_create(G_SCAN_SET_ITEM(result), set, index))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance à initialiser pleinement. *
+* set = ensemble d'éléments à considérer. *
+* index = indice de l'élément à viser. *
+* *
+* Description : Met en place un accès à un élément donné d'une série. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_set_item_create(GScanSetItem *item, GScanExpression *set, GScanExpression *index)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ item->set = set;
+ g_object_ref(G_OBJECT(set));
+
+ item->index = index;
+ g_object_ref(G_OBJECT(index));
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
+* *
+* Description : Réduit une expression à une forme plus simple. *
+* *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static ScanReductionState g_scan_set_item_reduce(GScanSetItem *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
+{
+ ScanReductionState result; /* Etat synthétisé à retourner */
+ GScanExpression *new_set; /* Expression réduite (série) */
+ GScanExpression *new_index; /* Expression réduite (indice) */
+ ScanReductionState state_set; /* Etat synthétisé #1 */
+ ScanReductionState state_index; /* Etat synthétisé #2 */
+ GScanLiteralExpression *op_index; /* Indice d'accès final */
+ LiteralValueType vtype; /* Type de valeur portée */
+ long long val_s; /* Valeur de l'indice (signée) */
+ unsigned long long val_u; /* Valeur de l'indice (!signée)*/
+ bool status; /* Statut final de récupération*/
+
+ /* Réduction des éléments considérés */
+
+ new_set = NULL;
+ new_index = NULL;
+
+ state_set = g_scan_expression_reduce(expr->set, ctx, scope, &new_set);
+ if (state_set == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ state_index = g_scan_expression_reduce(expr->index, ctx, scope, &new_index);
+ if (state_index == SRS_UNRESOLVABLE)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Validation de la nature des éléments en jeu */
+
+ if (state_set == SRS_REDUCED && !g_scan_expression_handle_set_features(new_set))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (state_index == SRS_REDUCED && !G_IS_SCAN_LITERAL_EXPRESSION(new_index))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ /* Tentative d'accès à un élément de série */
+
+ if (state_set == SRS_REDUCED && state_index == SRS_REDUCED)
+ {
+ op_index = G_SCAN_LITERAL_EXPRESSION(new_index);
+ vtype = g_scan_literal_expression_get_value_type(op_index);
+
+ if (vtype == LVT_SIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_signed_integer_value(op_index, &val_s))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ if (val_s < 0)
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ status = g_scan_expression_get_item(expr->set, val_s, ctx, out);
+
+ }
+ else if (vtype == LVT_UNSIGNED_INTEGER)
+ {
+ if (!g_scan_literal_expression_get_unsigned_integer_value(op_index, &val_u))
+ {
+ result = SRS_UNRESOLVABLE;
+ goto exit;
+ }
+
+ status = g_scan_expression_get_item(expr->set, val_u, ctx, out);
+
+ }
+
+ result = (status ? SRS_REDUCED : SRS_UNRESOLVABLE);
+
+ }
+
+ /* Mise à jour de la progression ? */
+
+ else
+ {
+ assert(state_set == SRS_WAIT_FOR_SCAN || state_index == SRS_WAIT_FOR_SCAN);
+
+ if (new_set != expr->set || new_index != expr->index)
+ *out = g_scan_set_item_new(new_set, new_index);
+
+ result = SRS_WAIT_FOR_SCAN;
+
+ }
+
+ /* Sortie propre */
+
+ exit:
+
+ g_clear_object(&new_set);
+ g_clear_object(&new_index);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/exprs/item.h b/src/analysis/scan/exprs/item.h
new file mode 100644
index 0000000..9d3cdfb
--- /dev/null
+++ b/src/analysis/scan/exprs/item.h
@@ -0,0 +1,55 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour la récupération d'un élément à partir d'une série
+ *
+ * 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_EXPRS_ITEM_H
+#define _ANALYSIS_SCAN_EXPRS_ITEM_H
+
+
+#include "../expr.h"
+
+
+
+#define G_TYPE_SCAN_SET_ITEM g_scan_set_item_get_type()
+#define G_SCAN_SET_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SET_ITEM, GScanSetItem))
+#define G_IS_SCAN_SET_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SET_ITEM))
+#define G_SCAN_SET_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SET_ITEM, GScanSetItemClass))
+#define G_IS_SCAN_SET_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SET_ITEM))
+#define G_SCAN_SET_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SET_ITEM, GScanSetItemClass))
+
+
+/* Accès à un élément donné d'une série établie (instance) */
+typedef struct _GScanSetItem GScanSetItem;
+
+/* Accès à un élément donné d'une série établie (classe) */
+typedef struct _GScanSetItemClass GScanSetItemClass;
+
+
+/* Indique le type défini pour la récupération d'un élément à partir d'une série. */
+GType g_scan_set_item_get_type(void);
+
+/* Met en place un accès à un élément donné d'une série. */
+GScanExpression *g_scan_set_item_new(GScanExpression *, GScanExpression *);
+
+
+
+#endif /* _ANALYSIS_SCAN_EXPRS_ITEM_H */
diff --git a/src/analysis/scan/exprs/literal.c b/src/analysis/scan/exprs/literal.c
index e468382..070c177 100644
--- a/src/analysis/scan/exprs/literal.c
+++ b/src/analysis/scan/exprs/literal.c
@@ -60,7 +60,7 @@ static bool g_scan_literal_expression_compare_rich(const GScanLiteralExpression
static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *, GScanContext *, GScanScope *, GScanExpression **);
/* Dénombre les éléments portés par une expression. */
-static bool g_scan_literal_expression_count(const GScanLiteralExpression *, size_t *);
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *, GScanContext *, size_t *);
@@ -623,6 +623,7 @@ static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *
/******************************************************************************
* *
* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
* count = quantité d'éléments déterminée. [OUT] *
* *
* Description : Dénombre les éléments portés par une expression. *
@@ -633,7 +634,7 @@ static bool g_scan_literal_expression_reduce_to_boolean(GScanLiteralExpression *
* *
******************************************************************************/
-static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, size_t *count)
+static bool g_scan_literal_expression_count(const GScanLiteralExpression *expr, GScanContext *ctx, size_t *count)
{
bool result; /* Bilan à retourner */
diff --git a/src/analysis/scan/exprs/set.c b/src/analysis/scan/exprs/set.c
index 0a93ced..d76af4d 100644
--- a/src/analysis/scan/exprs/set.c
+++ b/src/analysis/scan/exprs/set.c
@@ -60,10 +60,10 @@ static ScanReductionState g_scan_generic_set_reduce(GScanGenericSet *, GScanCont
static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *, GScanContext *, GScanScope *, GScanExpression **);
/* Dénombre les éléments portés par une expression. */
-static bool g_scan_generic_set_count_items(const GScanGenericSet *, size_t *);
+static bool g_scan_generic_set_count_items(const GScanGenericSet *, GScanContext *, size_t *);
/* Fournit un élément donné issu d'un ensemble constitué. */
-static bool g_scan_generic_set_get_item(const GScanGenericSet *, size_t, GScanExpression **);
+static bool g_scan_generic_set_get_item(const GScanGenericSet *, size_t, GScanContext *, GScanExpression **);
@@ -328,6 +328,7 @@ static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *expr, GScanCon
/******************************************************************************
* *
* Paramètres : expr = expression à consulter. *
+* ctx = contexte de suivi de l'analyse courante. *
* count = quantité d'éléments déterminée. [OUT] *
* *
* Description : Dénombre les éléments portés par une expression. *
@@ -338,7 +339,7 @@ static bool g_scan_generic_set_reduce_to_boolean(GScanGenericSet *expr, GScanCon
* *
******************************************************************************/
-static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *count)
+static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, GScanContext *ctx, size_t *count)
{
bool result; /* Bilan à retourner */
@@ -355,6 +356,7 @@ static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *
* *
* Paramètres : expr = expression à consulter. *
* index = indice de l'élément à transférer. *
+* ctx = contexte de suivi de l'analyse courante. *
* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Fournit un élément donné issu d'un ensemble constitué. *
@@ -365,7 +367,7 @@ static bool g_scan_generic_set_count_items(const GScanGenericSet *expr, size_t *
* *
******************************************************************************/
-static bool g_scan_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanExpression **out)
+static bool g_scan_generic_set_get_item(const GScanGenericSet *expr, size_t index, GScanContext *ctx, GScanExpression **out)
{
bool result; /* Bilan à retourner */
diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y
index 10e1d42..c0aa52d 100644
--- a/src/analysis/scan/grammar.y
+++ b/src/analysis/scan/grammar.y
@@ -6,7 +6,7 @@
/* Affiche un message d'erreur suite à l'analyse en échec. */
-static int yyerror(GContentScanner *, yyscan_t, GScanRule **, void/*GBytesPattern*/ **, char **, size_t *, size_t *, char *);
+static int yyerror(GContentScanner *, yyscan_t, GScanRule **, sized_string_t *, sized_string_t *, void/*GBytesPattern*/ **, char **, size_t *, size_t *, char *);
%}
@@ -16,34 +16,26 @@ static int yyerror(GContentScanner *, yyscan_t, GScanRule **, void/*GBytesPatter
#define YY_TYPEDEF_YY_SCANNER_T
typedef void *yyscan_t;
+#include "core.h"
#include "scanner.h"
#include "exprs/access.h"
#include "exprs/arithmetic.h"
#include "exprs/call.h"
#include "exprs/counter.h"
+#include "exprs/handler.h"
#include "exprs/intersect.h"
+#include "exprs/item.h"
#include "exprs/literal.h"
#include "exprs/logical.h"
#include "exprs/set.h"
#include "exprs/relational.h"
#include "exprs/strop.h"
+#include "patterns/modifier.h"
+#include "patterns/modifiers/list.h"
+#include "patterns/tokens/hex.h"
#include "patterns/tokens/plain.h"
-
-
-#if 0 /////////////////////////////////////////////////////////////////////////::
-#define handle_coder_conversions(c, r) \
- ({ \
- encoding_spec *__spec; \
- encoding_syntax *__syntax; \
- conv_list *__list; \
- bool __status; \
- __spec = get_current_encoding_spec(c); \
- __syntax = get_current_encoding_syntax(__spec); \
- __list = get_conversions_in_encoding_syntax(__syntax); \
- __status = load_convs_from_raw_block(__list, r); \
- if (!__status) YYABORT; \
- })
-#endif ///////////////////////////////////////////////////////////////////////////
+#include "patterns/tokens/nodes/plain.h"
+#include "../../core/logs.h"
}
@@ -58,9 +50,25 @@ typedef void *yyscan_t;
+ sized_string_t *tmp_cstring; /* Série d'octets reconstituée */
+
+ struct {
+ bin_t byte; /* Valeur partielle recherchée */
+ uint8_t mask; /* Masque associé */
+ } semi_mask;
+
+
GScanRule *rule; /* Nouvelle règle à intégrer */
- void/*GBytesPattern*/ *pattern; /* Nouveau motif à considérer */
+
+
+
+ GScanTokenNode *node; /* Bribe de motif à intégrer */
+ GSearchPattern *pattern; /* Nouveau motif à considérer */
+
+ GScanTokenModifier *modifier;
+
+
GScanExpression *expr; /* Expression de condition */
struct {
@@ -78,13 +86,13 @@ typedef void *yyscan_t;
%define api.pure full
-%parse-param { GContentScanner *scanner } { yyscan_t yyscanner } { GScanRule **built_rule } { void /*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
-%lex-param { yyscan_t yyscanner } { void/*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
+%parse-param { GContentScanner *scanner } { yyscan_t yyscanner } { GScanRule **built_rule } { sized_string_t *tmp_0} { sized_string_t *tmp_1} { void /*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
+%lex-param { yyscan_t yyscanner } { sized_string_t *tmp_0} { sized_string_t *tmp_1} { void/*GBytesPattern*/ **built_pattern } { char **buf } { size_t *allocated } { size_t *used }
%code provides {
#define YY_DECL \
- int rost_lex(YYSTYPE *yylval_param, yyscan_t yyscanner, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used)
+ int rost_lex(YYSTYPE *yylval_param, yyscan_t yyscanner, sized_string_t *tmp_0, sized_string_t *tmp_1, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used)
YY_DECL;
@@ -97,13 +105,26 @@ YY_DECL;
%token RULE_NAME
%token STRINGS CONDITION
-%token IDENTIFIER
+
%token BYTES_ID
%token BYTES_ID_COUNTER
-%token BYTES_ID_LOCATION
+%token BYTES_ID_START
%token BYTES_ID_LENGTH
+%token BYTES_ID_END
%token NAME
+
+%token HEX_BYTES
+%token FULL_MASK
+%token SEMI_MASK
+
+
+%token REGEX_BYTES
+%token REGEX_CLASSES
+%token REGEX_RANGE
+
+
+
%token BRACE_IN BRACE_OUT ASSIGN COLON
@@ -143,11 +164,20 @@ YY_DECL;
%token MUL "*"
%token DIV "/"
%token MOD "%"
+%token TILDE "~"
+
+%token HOOK_O "["
+%token HOOK_C "]"
+
+%token BRACKET_O "{"
+%token BRACKET_C "}"
+%token QUESTION "?"
%token PAREN_O "("
%token PAREN_C ")"
%token COMMA ","
%token DOT "."
+%token PIPE "|"
%token NONE "none"
%token ANY "any"
@@ -160,7 +190,11 @@ YY_DECL;
%type <sized_cstring> RULE_NAME
-%type <sized_cstring> IDENTIFIER BYTES_ID_COUNTER
+%type <sized_cstring> BYTES_ID
+%type <sized_cstring> BYTES_ID_COUNTER
+%type <sized_cstring> BYTES_ID_START
+%type <sized_cstring> BYTES_ID_LENGTH
+%type <sized_cstring> BYTES_ID_END
%type <sized_cstring> NAME
@@ -173,8 +207,27 @@ YY_DECL;
%type <sized_cstring> PLAIN_STRING
%type <pattern> MASKED_STRING
+%type <tmp_cstring> HEX_BYTES
+%type <unsigned_integer> FULL_MASK
+%type <semi_mask> SEMI_MASK
+
+%type <tmp_cstring> REGEX_BYTES
+
+
+%type <modifier> modifiers
+%type <modifier> _modifiers
+%type <modifier> chained_modifiers
+%type <modifier> mod_stage
+%type <modifier> modifier
+
+%type <pattern> hex_pattern
+%type <node> hex_tokens
+%type <node> hex_token
+
+
+
%type <expr> cexpression _cexpression
-%type <expr> pattern_match
+
%type <expr> literal
%type <expr> item_chain
%type <args_list> call_args
@@ -185,7 +238,16 @@ YY_DECL;
%type <expr> set_counter
%type <expr> set
%type <expr> set_items
+%type <expr> set_access
%type <expr> intersection
+%type <expr> pattern_handler
+
+
+
+
+
+%left PIPE
+
%left OR
@@ -200,6 +262,11 @@ YY_DECL;
+%left HOOK_O HOOK_C
+
+
+
+
%destructor { printf("-------- Discarding symbol %p.\n", $$); } <rule>
@@ -257,14 +324,28 @@ strings : /* empty */
;
-string_decls : string_decl
- | string_decls string_decl
- ;
+ string_decls : string_decl
+ | hex_pattern
+ {
+ if ($1 == NULL) YYERROR;
+ g_scan_rule_add_local_variable(*built_rule, $1);
+ g_object_unref(G_OBJECT($1));
+ }
+ | regex_pattern
+ | string_decls string_decl
+ | string_decls hex_pattern
+ {
+ if ($2 == NULL) YYERROR;
+ g_scan_rule_add_local_variable(*built_rule, $2);
+ g_object_unref(G_OBJECT($2));
+ }
+ | string_decls regex_pattern
+ ;
-string_decl : IDENTIFIER ASSIGN PLAIN_STRING
+string_decl : BYTES_ID ASSIGN PLAIN_STRING modifiers
{
GSearchPattern *__pat;
- __pat = g_plain_bytes_new((uint8_t *)$3.data, $3.len);
+ __pat = g_scan_plain_bytes_new(&$3, NULL, SPBF_NONE);
g_search_pattern_set_name(__pat, $1.data, $1.len);
g_scan_rule_add_local_variable(*built_rule, __pat);
g_object_unref(G_OBJECT(__pat));
@@ -281,7 +362,7 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING
g_object_unref(G_OBJECT(__pat));
*/
}
- | IDENTIFIER ASSIGN MASKED_STRING
+ | BYTES_ID ASSIGN MASKED_STRING
{
printf("built %p\n", $3);
/*
@@ -301,6 +382,267 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING
}
;
+
+/**
+ * Prise en charge des modificateurs.
+ */
+
+ modifiers : /* empty */
+ {
+ $$ = NULL;
+ }
+ | _modifiers
+ {
+
+ // if (...) useless
+
+ }
+ ;
+
+ _modifiers : mod_stage
+ {
+ $$ = $1;
+ }
+ | chained_modifiers
+ {
+ $$ = $1;
+ }
+ ;
+
+ chained_modifiers : _modifiers "|" _modifiers
+ ;
+
+ mod_stage : modifier
+ {
+ $$ = $1;
+ }
+ | mod_stage modifier
+ {
+ bool status;
+
+ if (G_IS_SCAN_MODIFIER_LIST($1))
+ $$ = $1;
+ else
+ {
+ $$ = g_scan_modifier_list_new();
+ g_scan_modifier_list_add(G_SCAN_MODIFIER_LIST($$), $1);
+ }
+
+ status = g_scan_modifier_list_add(G_SCAN_MODIFIER_LIST($$), $2);
+ if (!status)
+ {
+ if (1)
+ log_simple_message(LMT_WARNING, "modifier already taken into account!");
+ g_object_unref(G_OBJECT($2));
+ }
+
+ }
+ ;
+
+ modifier : NAME
+ {
+ $$ = find_scan_token_modifiers_for_name($1.data);
+ if ($$ == NULL) YYERROR;
+ }
+ | "(" chained_modifiers ")"
+ {
+ $$ = $2;
+ }
+ ;
+
+/**
+ * Définition de motif en hexadécimal.
+ */
+
+ hex_pattern : BYTES_ID ASSIGN hex_tokens
+ {
+ $$ = g_scan_hex_bytes_new($3);
+ g_search_pattern_set_name($$, $1.data, $1.len);
+ }
+ ;
+
+ hex_tokens : hex_token
+ {
+ $$ = $1;
+ }
+ | hex_tokens hex_token
+ {
+
+ }
+ ;
+
+ hex_token : HEX_BYTES
+ {
+ $$ = g_scan_token_node_plain_new($1, NULL, SPNF_NONE);
+ }
+ | FULL_MASK
+ {
+ printf("mask len: %llu\n", $1);
+ }
+ | SEMI_MASK
+ {
+ printf("semi mask: %hhx / %hhx \n", $1.byte, $1.mask);
+ }
+ | hex_range
+ {
+ printf("...range...\n");
+ }
+ | "~" hex_token
+ {
+
+ printf("hex -- NOT --\n");
+
+ }
+ | "(" hex_token "|" hex_token ")"
+ {
+
+ printf("hex -- OR --\n");
+
+ }
+ ;
+
+ hex_range : "[" "-" "]"
+ {
+
+ printf("got inf range\n");
+
+ }
+ | "[" UNSIGNED_INTEGER "]"
+ {
+
+ printf("got range [%llu]\n", $2);
+
+ }
+ | "[" UNSIGNED_INTEGER "-" "]"
+ {
+
+ printf("got range [%llu -> ]\n", $2);
+
+ }
+ | "[" "-" UNSIGNED_INTEGER "]"
+ {
+
+ printf("got range [ -> %llu]\n", $3);
+
+ }
+ | "[" UNSIGNED_INTEGER "-" UNSIGNED_INTEGER "]"
+ {
+
+ printf("got range [%llu -> %llu]\n", $2, $4);
+
+ }
+ ;
+
+/**
+ * Définition de motif sous forme d'expression régulière
+ */
+
+ regex_pattern : BYTES_ID ASSIGN regex_tokens
+ {
+
+ }
+ ;
+
+ regex_tokens : regex_token
+ {
+
+ }
+ | regex_tokens regex_token
+ {
+
+ }
+ | "(" regex_tokens_list ")"
+ {
+
+ printf("regex -- OR --\n");
+
+ }
+ | regex_tokens "(" regex_tokens_list ")"
+ {
+
+ printf("regex -- OR --\n");
+
+ }
+ ;
+
+
+ regex_tokens_list : regex_tokens
+ | regex_tokens_list "|" regex_tokens
+ ;
+
+
+ regex_token : _regex_token
+ {
+
+ }
+ | _regex_token regex_repeat
+ {
+
+ }
+ ;
+
+ _regex_token : DOT
+ {
+ printf("reg dot!\n");
+ }
+ | REGEX_BYTES
+ {
+ printf("reg bytes: '%s' (l=%zu)\n", $1->data, $1->len);
+ }
+ | REGEX_CLASSES
+ {
+ printf("reg class!\n");
+ }
+ | "[" REGEX_RANGE "]"
+ {
+ printf("reg range!\n");
+ }
+ ;
+
+ regex_repeat : "*"
+ {
+ printf(" .. repeat: *\n");
+ }
+ | "+"
+ {
+ printf(" .. repeat: +\n");
+ }
+ | "?"
+ {
+ printf(" .. repeat: ?\n");
+ }
+ | "{" UNSIGNED_INTEGER "}"
+ {
+
+ printf(" .. repeat {%llu}\n", $2);
+
+ }
+ | "{" UNSIGNED_INTEGER "," "}"
+ {
+
+ printf(" .. repeat {%llu,}\n", $2);
+
+ }
+ | "{" "," UNSIGNED_INTEGER "}"
+ {
+
+ printf(" .. repeat {,%llu}\n", $3);
+
+ }
+ | "{" UNSIGNED_INTEGER "," UNSIGNED_INTEGER "}"
+ {
+
+ printf(" .. repeat {%llu,%llu}\n", $2, $4);
+
+ }
+ ;
+
+
+
+/**
+ * Définition des conditions.
+ */
+
condition : CONDITION COLON cexpression
{
g_scan_rule_set_match_condition(*built_rule, $3);
@@ -310,49 +652,19 @@ string_decl : IDENTIFIER ASSIGN PLAIN_STRING
cexpression : _cexpression { $$ = $1; if ($$ == NULL) { printf("ERROR !!!\n"); YYERROR; } }
- _cexpression : IDENTIFIER
- {
- printf("named var: %s\n", "$1");
- $$ = NULL;
- /*
- GSearchPattern *__pat;
- GMatchCounter *__counter;
- __pat = g_scan_rule_get_local_variable(*built_rule, $1);
- if (__pat != NULL)
- {
- __counter = g_match_counter_new(__pat);
- g_scan_rule_add_condition(*built_rule, G_MATCH_CONDITION(__counter));
- g_object_unref(G_OBJECT(__counter));
- g_object_unref(G_OBJECT(__pat));
- }
- */
- }
- | literal { $$ = $1; }
- | pattern_match { $$ = $1; }
- | item_chain { $$ = $1; }
- | logical_expr { $$ = $1; }
- | relational_expr { $$ = $1; }
- | string_op { $$ = $1; }
- | arithm_expr { $$ = $1; }
- | set_counter { $$ = $1; }
- | set { $$ = $1; }
- | intersection { $$ = $1; }
- | "(" cexpression ")" { $$ = $2; }
- ;
-
- pattern_match : BYTES_ID_COUNTER
- {
- GSearchPattern *__pat;
- __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
- if (__pat == NULL)
- $$ = NULL;
- else
- {
- $$ = g_scan_match_counter_new(__pat);
- g_object_unref(G_OBJECT(__pat));
- }
- }
- ;
+ _cexpression : literal { $$ = $1; }
+ | item_chain { $$ = $1; }
+ | logical_expr { $$ = $1; }
+ | relational_expr { $$ = $1; }
+ | string_op { $$ = $1; }
+ | arithm_expr { $$ = $1; }
+ | set_counter { $$ = $1; }
+ | set { $$ = $1; }
+ | set_access { $$ = $1; }
+ | intersection { $$ = $1; }
+ | pattern_handler { $$ = $1; }
+ | "(" cexpression ")" { $$ = $2; }
+ ;
literal : "true"
{
@@ -538,16 +850,83 @@ set_counter : "none" "of" "them" { $$ = g_scan_literal_expression_new(LVT_BOOLEA
}
;
- intersection : cexpression "in" cexpression
- {
- $$ = g_scan_sets_intersection_new($1, $3);
- g_object_unref(G_OBJECT($1));
- g_object_unref(G_OBJECT($3));
- }
- ;
-
+ set_access : cexpression "[" cexpression "]"
+ {
+ $$ = g_scan_set_item_new($1, $3);
+ g_object_unref(G_OBJECT($1));
+ g_object_unref(G_OBJECT($3));
+ }
+ ;
+ intersection : cexpression "in" cexpression
+ {
+ $$ = g_scan_sets_intersection_new($1, $3);
+ g_object_unref(G_OBJECT($1));
+ g_object_unref(G_OBJECT($3));
+ }
+ ;
+ pattern_handler : BYTES_ID
+ {
+ GSearchPattern *__pat;
+ __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+ if (__pat == NULL)
+ $$ = NULL;
+ else
+ {
+ $$ = g_scan_pattern_handler_new(__pat, SHT_RAW);
+ g_object_unref(G_OBJECT(__pat));
+ }
+ }
+ | BYTES_ID_COUNTER
+ {
+ GSearchPattern *__pat;
+ __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+ if (__pat == NULL)
+ $$ = NULL;
+ else
+ {
+ $$ = g_scan_match_counter_new(__pat);
+ g_object_unref(G_OBJECT(__pat));
+ }
+ }
+ | BYTES_ID_START
+ {
+ GSearchPattern *__pat;
+ __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+ if (__pat == NULL)
+ $$ = NULL;
+ else
+ {
+ $$ = g_scan_pattern_handler_new(__pat, SHT_START);
+ g_object_unref(G_OBJECT(__pat));
+ }
+ }
+ | BYTES_ID_LENGTH
+ {
+ GSearchPattern *__pat;
+ __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+ if (__pat == NULL)
+ $$ = NULL;
+ else
+ {
+ $$ = g_scan_pattern_handler_new(__pat, SHT_LENGTH);
+ g_object_unref(G_OBJECT(__pat));
+ }
+ }
+ | BYTES_ID_END
+ {
+ GSearchPattern *__pat;
+ __pat = g_scan_rule_get_local_variable(*built_rule, $1.data);
+ if (__pat == NULL)
+ $$ = NULL;
+ else
+ {
+ $$ = g_scan_pattern_handler_new(__pat, SHT_END);
+ g_object_unref(G_OBJECT(__pat));
+ }
+ }
+ ;
%%
@@ -566,7 +945,7 @@ set_counter : "none" "of" "them" { $$ = g_scan_literal_expression_new(LVT_BOOLEA
* *
******************************************************************************/
-static int yyerror(GContentScanner *scanner, yyscan_t yyscanner, GScanRule **built_rule, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used, char *msg)
+static int yyerror(GContentScanner *scanner, yyscan_t yyscanner, GScanRule **built_rule, sized_string_t *tmp_0, sized_string_t *tmp_1, void/*GBytesPattern*/ **built_pattern, char **buf, size_t *allocated, size_t *used, char *msg)
{
printf("YYERROR line %d: %s\n", yyget_lineno(yyscanner), msg);
@@ -593,6 +972,8 @@ bool process_rules_definitions(GContentScanner *scanner, const char *text, size_
{
bool result; /* Bilan à renvoyer */
GScanRule *built_rule; /* Règle en construction */
+ sized_string_t tmp_0; /* Zone tampon #1 */
+ sized_string_t tmp_1; /* Zone tampon #2 */
void /*GBytesPattern*/ *built_pattern; /* Motif en construction */
char *buf; /* Zone de travail temporaire */
size_t allocated; /* Taille de mémoire allouée */
@@ -604,6 +985,13 @@ bool process_rules_definitions(GContentScanner *scanner, const char *text, size_
result = false;
built_rule = NULL;
+
+ tmp_0.data = malloc((length + 1) * sizeof(bin_t));
+ tmp_0.len = 0;
+
+ tmp_1.data = malloc((length + 1) * sizeof(bin_t));
+ tmp_1.len = 0;
+
built_pattern = NULL;
allocated = 256;
@@ -616,7 +1004,7 @@ bool process_rules_definitions(GContentScanner *scanner, const char *text, size_
state = rost__scan_bytes(text, length, lexstate);
- status = yyparse(scanner, lexstate, &built_rule, &built_pattern, &buf, &allocated, &used);
+ status = yyparse(scanner, lexstate, &built_rule, &tmp_0, &tmp_1, &built_pattern, &buf, &allocated, &used);
result = (status == EXIT_SUCCESS);
@@ -624,6 +1012,9 @@ bool process_rules_definitions(GContentScanner *scanner, const char *text, size_
rost_lex_destroy(lexstate);
+ exit_szstr(&tmp_0);
+ exit_szstr(&tmp_1);
+
free(buf);
return result;
diff --git a/src/analysis/scan/items/count.c b/src/analysis/scan/items/count.c
index d87d33b..9040ec4 100644
--- a/src/analysis/scan/items/count.c
+++ b/src/analysis/scan/items/count.c
@@ -232,7 +232,7 @@ static bool g_scan_count_function_run_call(GScanCountFunction *item, GScanExpres
else
{
- result = g_scan_expression_count_items(args[0], &value);
+ result = g_scan_expression_count_items(args[0], ctx, &value);
if (result)
*out = G_OBJECT(g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, (unsigned long long []){ value }));
diff --git a/src/analysis/scan/match-int.h b/src/analysis/scan/match-int.h
index 9030d75..cf774c4 100644
--- a/src/analysis/scan/match-int.h
+++ b/src/analysis/scan/match-int.h
@@ -29,8 +29,11 @@
-/* Affiche une correspondance sur la sortie standard. */
-typedef void (* display_scan_match_fc) (const GScanMatch *);
+/* Affiche une correspondance au format texte. */
+typedef void (* output_scan_match_to_text_fc) (const GScanMatch *, int);
+
+/* Affiche une correspondance au format JSON. */
+typedef void (* output_scan_match_to_json_fc) (const GScanMatch *, const sized_string_t *, unsigned int, int);
/* Correspondance trouvée avec un motif (instance) */
@@ -47,7 +50,8 @@ struct _GScanMatchClass
{
GObjectClass parent; /* A laisser en premier */
- display_scan_match_fc display; /* Impression des résultats */
+ output_scan_match_to_text_fc to_text; /* Impression au format texte */
+ output_scan_match_to_json_fc to_json; /* Impression au format JSON */
};
diff --git a/src/analysis/scan/match.c b/src/analysis/scan/match.c
index c7e2a78..b0b4320 100644
--- a/src/analysis/scan/match.c
+++ b/src/analysis/scan/match.c
@@ -157,8 +157,9 @@ GSearchPattern *g_scan_match_get_source(const GScanMatch *match)
/******************************************************************************
* *
* Paramètres : match = définition de correspondance à manipuler. *
+* fd = canal d'écriture. *
* *
-* Description : Affiche une correspondance sur la sortie standard. *
+* Description : Affiche une correspondance au format texte. *
* *
* Retour : - *
* *
@@ -166,12 +167,97 @@ GSearchPattern *g_scan_match_get_source(const GScanMatch *match)
* *
******************************************************************************/
-void g_scan_match_display(const GScanMatch *match)
+void g_scan_match_output_to_text(const GScanMatch *match, int fd)
{
GScanMatchClass *class; /* Classe à activer */
class = G_SCAN_MATCH_GET_CLASS(match);
- class->display(match);
+ class->to_text(match, fd);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = définition de correspondance à manipuler. *
+* *
+* Description : Convertit une correspondance en texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_match_convert_as_text(const GScanMatch *match)
+{
+ /* TODO */
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = définition de correspondance à manipuler. *
+* padding = éventuel bourrage initial à placer ou NULL. *
+* level = profondeur actuelle. *
+* fd = canal d'écriture. *
+* trailing = impose une virgule finale ? *
+* *
+* Description : Affiche une correspondance au format JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_match_output_to_json(const GScanMatch *match, const sized_string_t *padding, unsigned int level, int fd, bool trailing)
+{
+ unsigned int i; /* Boucle de parcours */
+ GScanMatchClass *class; /* Classe à activer */
+
+ /* Introduction */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "{\n", 2);
+
+ /* Affichage du contenu */
+
+ class = G_SCAN_MATCH_GET_CLASS(match);
+
+ class->to_json(match, padding, level + 1, fd);
+
+ /* Conclusion */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ if (trailing)
+ write(fd, "},\n", 3);
+ else
+ write(fd, "}\n", 2);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = définition de correspondance à manipuler. *
+* *
+* Description : Convertit une correspondance en JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_match_convert_as_json(const GScanMatch *match)
+{
+ /* TODO */
}
diff --git a/src/analysis/scan/match.h b/src/analysis/scan/match.h
index 0990ae0..e713b5d 100644
--- a/src/analysis/scan/match.h
+++ b/src/analysis/scan/match.h
@@ -29,6 +29,7 @@
#include "pattern.h"
+#include "../../common/szstr.h"
@@ -53,8 +54,17 @@ GType g_scan_match_get_type(void);
/* Indique la source du motif d'origine recherché. */
GSearchPattern *g_scan_match_get_source(const GScanMatch *);
-/* Affiche une correspondance sur la sortie standard. */
-void g_scan_match_display(const GScanMatch *);
+/* Affiche une correspondance au format texte. */
+void g_scan_match_output_to_text(const GScanMatch *, int);
+
+/* Convertit une correspondance en texte. */
+void g_scan_match_convert_as_text(const GScanMatch *);
+
+/* Affiche une correspondance au format JSON. */
+void g_scan_match_output_to_json(const GScanMatch *, const sized_string_t *, unsigned int, int, bool);
+
+/* Convertit une correspondance en JSON. */
+void g_scan_match_convert_as_json(const GScanMatch *);
diff --git a/src/analysis/scan/matches/bytes-int.h b/src/analysis/scan/matches/bytes-int.h
index c983aa3..6f7e60b 100644
--- a/src/analysis/scan/matches/bytes-int.h
+++ b/src/analysis/scan/matches/bytes-int.h
@@ -33,7 +33,7 @@
/* Correspondance trouvée avec une chaîne (instance) */
-struct _GBytesMatch
+struct _GScanBytesMatch
{
GScanMatch parent; /* A laisser en premier */
@@ -45,7 +45,7 @@ struct _GBytesMatch
};
/* Correspondance trouvée avec une chaîne (classe) */
-struct _GBytesMatchClass
+struct _GScanBytesMatchClass
{
GScanMatchClass parent; /* A laisser en premier */
@@ -53,7 +53,7 @@ struct _GBytesMatchClass
/* Met en place une correspondance trouvée avec un motif. */
-bool g_bytes_match_create(GBytesMatch *, GSearchPattern *, GBinContent *, phys_t, phys_t);
+bool g_scan_bytes_match_create(GScanBytesMatch *, GSearchPattern *, GBinContent *, phys_t, phys_t);
diff --git a/src/analysis/scan/matches/bytes.c b/src/analysis/scan/matches/bytes.c
index 90fa27d..043170e 100644
--- a/src/analysis/scan/matches/bytes.c
+++ b/src/analysis/scan/matches/bytes.c
@@ -24,10 +24,14 @@
#include "bytes.h"
+#include <assert.h>
#include <ctype.h>
+#include <stdio.h>
#include "bytes-int.h"
+#include "../../../common/cpp.h"
+#include "../../../core/logs.h"
@@ -35,24 +39,27 @@
/* Initialise la classe des correspondances de chaînes. */
-static void g_bytes_match_class_init(GBytesMatchClass *);
+static void g_scan_bytes_match_class_init(GScanBytesMatchClass *);
/* Initialise une instance de correspondance de chaîne trouvée. */
-static void g_bytes_match_init(GBytesMatch *);
+static void g_scan_bytes_match_init(GScanBytesMatch *);
/* Supprime toutes les références externes. */
-static void g_bytes_match_dispose(GBytesMatch *);
+static void g_scan_bytes_match_dispose(GScanBytesMatch *);
/* Procède à la libération totale de la mémoire. */
-static void g_bytes_match_finalize(GBytesMatch *);
+static void g_scan_bytes_match_finalize(GScanBytesMatch *);
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* Affiche une correspondance sur la sortie standard. */
-static void g_bytes_match_display(const GBytesMatch *);
+/* Affiche une correspondance au format texte. */
+static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *, int);
+
+/* Affiche une correspondance au format JSON. */
+static void g_scan_bytes_match_output_to_json(const GScanBytesMatch *, const sized_string_t *, unsigned int, int);
@@ -62,7 +69,7 @@ static void g_bytes_match_display(const GBytesMatch *);
/* Indique le type défini pour un correspondance de chaîne identifiée. */
-G_DEFINE_TYPE(GBytesMatch, g_bytes_match, G_TYPE_SCAN_MATCH);
+G_DEFINE_TYPE(GScanBytesMatch, g_scan_bytes_match, G_TYPE_SCAN_MATCH);
/******************************************************************************
@@ -77,19 +84,20 @@ G_DEFINE_TYPE(GBytesMatch, g_bytes_match, G_TYPE_SCAN_MATCH);
* *
******************************************************************************/
-static void g_bytes_match_class_init(GBytesMatchClass *klass)
+static void g_scan_bytes_match_class_init(GScanBytesMatchClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GScanMatchClass *match; /* Version parente de la classe*/
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_bytes_match_dispose;
- object->finalize = (GObjectFinalizeFunc)g_bytes_match_finalize;
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_bytes_match_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_bytes_match_finalize;
match = G_SCAN_MATCH_CLASS(klass);
- match->display = (display_scan_match_fc)g_bytes_match_display;
+ match->to_text = (output_scan_match_to_text_fc)g_scan_bytes_match_output_to_text;
+ match->to_json = (output_scan_match_to_json_fc)g_scan_bytes_match_output_to_json;
}
@@ -106,7 +114,7 @@ static void g_bytes_match_class_init(GBytesMatchClass *klass)
* *
******************************************************************************/
-static void g_bytes_match_init(GBytesMatch *match)
+static void g_scan_bytes_match_init(GScanBytesMatch *match)
{
match->content = NULL;
@@ -128,11 +136,11 @@ static void g_bytes_match_init(GBytesMatch *match)
* *
******************************************************************************/
-static void g_bytes_match_dispose(GBytesMatch *match)
+static void g_scan_bytes_match_dispose(GScanBytesMatch *match)
{
g_clear_object(&match->content);
- G_OBJECT_CLASS(g_bytes_match_parent_class)->dispose(G_OBJECT(match));
+ G_OBJECT_CLASS(g_scan_bytes_match_parent_class)->dispose(G_OBJECT(match));
}
@@ -149,9 +157,9 @@ static void g_bytes_match_dispose(GBytesMatch *match)
* *
******************************************************************************/
-static void g_bytes_match_finalize(GBytesMatch *match)
+static void g_scan_bytes_match_finalize(GScanBytesMatch *match)
{
- G_OBJECT_CLASS(g_bytes_match_parent_class)->finalize(G_OBJECT(match));
+ G_OBJECT_CLASS(g_scan_bytes_match_parent_class)->finalize(G_OBJECT(match));
}
@@ -171,13 +179,13 @@ static void g_bytes_match_finalize(GBytesMatch *match)
* *
******************************************************************************/
-GScanMatch *g_bytes_match_new(GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
+GScanMatch *g_scan_bytes_match_new(GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
{
GScanMatch *result; /* Structure à retourner */
- result = g_object_new(G_TYPE_BYTES_MATCH, NULL);
+ result = g_object_new(G_TYPE_SCAN_BYTES_MATCH, NULL);
- if (!g_bytes_match_create(G_BYTES_MATCH(result), source, content, start, len))
+ if (!g_scan_bytes_match_create(G_SCAN_BYTES_MATCH(result), source, content, start, len))
g_clear_object(&result);
return result;
@@ -201,7 +209,7 @@ GScanMatch *g_bytes_match_new(GSearchPattern *source, GBinContent *content, phys
* *
******************************************************************************/
-bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
+bool g_scan_bytes_match_create(GScanBytesMatch *match, GSearchPattern *source, GBinContent *content, phys_t start, phys_t len)
{
bool result; /* Bilan à retourner */
GScanMatch *base; /* Lien vers les infos de base */
@@ -224,6 +232,58 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten
}
+/******************************************************************************
+* *
+* Paramètres : match = informations de correspondance à consulter. *
+* *
+* Description : Fournit une référence au contenu lié à la correspondance. *
+* *
+* Retour : Content binaire associé au context. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *match)
+{
+ GBinContent *result; /* Instance à retourner */
+
+ result = match->content;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = informations de correspondance à consulter. *
+* start = position de départ d'un motif détecté. [OUT] *
+* end = position d'arrivée d'un motif détecté. [OUT] *
+* *
+* Description : Indique la localisation d'une correspondance établie. *
+* *
+* Retour : Taille mesurée de la correspondance. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *match, phys_t *start, phys_t *end)
+{
+ phys_t result; /* Taille à retourner */
+
+ result = match->len;
+
+ *start = match->start;
+ *end = match->start + result;
+
+ return result;
+
+}
+
/* ---------------------------------------------------------------------------------- */
/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
@@ -233,8 +293,9 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten
/******************************************************************************
* *
* Paramètres : match = définition de correspondance à manipuler. *
+* fd = canal d'écriture. *
* *
-* Description : Affiche une correspondance sur la sortie standard. *
+* Description : Affiche une correspondance au format texte. *
* *
* Retour : - *
* *
@@ -242,15 +303,34 @@ bool g_bytes_match_create(GBytesMatch *match, GSearchPattern *source, GBinConten
* *
******************************************************************************/
-static void g_bytes_match_display(const GBytesMatch *match)
+static void g_scan_bytes_match_output_to_text(const GScanBytesMatch *match, int fd)
{
+ char value[2 + ULLONG_MAXLEN]; /* Impression de la position */
+ int ret; /* Bilan d'une conversion */
GScanMatch *base; /* Lien vers les infos de base */
const char *name; /* Désignation du motif ciblé */
vmpa2t pos; /* Tête de lecture */
const bin_t *data; /* Accès aux données brutes */
- phys_t i; /* Boucle de parcours */
+ phys_t k; /* Boucle de parcours #2 */
+
+ /* Position dans le binaire (hexadécimal) */
+
+ ret = snprintf(value, ULLONG_MAXLEN, "0x%llx", (unsigned long long)match->start);
+
+ if (ret > 0)
+ write(fd, value, ret);
- /* Affichage d'un repère */
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!");
+ write(fd, "\"<error>\"", 9);
+ }
+
+ write(fd, ":", 1);
+
+ /* Affichage de la désignation */
+
+ write(fd, "$", 1);
base = G_SCAN_MATCH(match);
@@ -262,25 +342,151 @@ static void g_bytes_match_display(const GBytesMatch *match)
* Cette absence de nom est supportée ici.
*/
- if (name == NULL)
- name = "";
+ if (name != NULL)
+ write(fd, name, strlen(name));
+
+ write(fd, ": ", 2);
+
+ /* Affichage du contenu */
+
+ init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
+
+ data = g_binary_content_get_raw_access(match->content, &pos, match->len);
+
+ for (k = 0; k < match->len; k++)
+ {
+ if (isprint(data[k]))
+ write(fd, &data[k], 1);
+
+ else
+ {
+ write(fd, "\\x", 2);
+
+ ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]);
+
+ if (ret > 0)
+ {
+ assert(ret == 2);
+ write(fd, value, ret);
+ }
+
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+ write(fd, "??", 2);
+ }
+
+ }
+
+ }
+
+ write(fd, "\n", 1);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : match = définition de correspondance à manipuler. *
+* padding = éventuel bourrage initial à placer ou NULL. *
+* level = profondeur actuelle. *
+* fd = canal d'écriture. *
+* *
+* Description : Affiche une correspondance au format JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_bytes_match_output_to_json(const GScanBytesMatch *match, const sized_string_t *padding, unsigned int level, int fd)
+{
+ unsigned int i; /* Boucle de parcours #1 */
+ vmpa2t pos; /* Tête de lecture */
+ char value[4 + ULLONG_MAXLEN]; /* Impression de la position */
+ int ret; /* Bilan d'une conversion */
+ const bin_t *data; /* Accès aux données brutes */
+ phys_t k; /* Boucle de parcours #2 */
+
+ /* Position dans le binaire (décimal) */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"offset\": ", 10);
+
+ ret = snprintf(value, ULLONG_MAXLEN, "%llu", (unsigned long long)match->start);
+
+ if (ret > 0)
+ write(fd, value, ret);
+
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting offset!");
+ write(fd, "null", 4);
+ }
+
+ write(fd, ",\n", 2);
+
+ /* Position dans le binaire (hexadécimal) */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"offset_hex\": ", 14);
- printf("0x%llx:$%s: ", (unsigned long long)match->start, name);
+ ret = snprintf(value, ULLONG_MAXLEN, "\"0x%llx\"", (unsigned long long)match->start);
+
+ if (ret > 0)
+ write(fd, value, ret);
+
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting offset to hex!");
+ write(fd, "null", 4);
+ }
+
+ write(fd, ",\n", 2);
/* Affichage du contenu */
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"content\": \"", 12);
+
init_vmpa(&pos, match->start, VMPA_NO_VIRTUAL);
data = g_binary_content_get_raw_access(match->content, &pos, match->len);
- for (i = 0; i < match->len; i++)
+ for (k = 0; k < match->len; k++)
{
- if (isprint(data[i]))
- printf("%c", data[i]);
+ if (isprint(data[k]))
+ write(fd, &data[k], 1);
+
else
- printf("\\x%02hhx", data[i]);
+ {
+ write(fd, "\\x", 2);
+
+ ret = snprintf(value, ULLONG_MAXLEN, "%02hhx", data[k]);
+
+ if (ret > 0)
+ {
+ assert(ret == 2);
+ write(fd, value, ret);
+ }
+
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting data!");
+ write(fd, "??", 2);
+ }
+
+ }
+
}
- printf("\n");
+ write(fd, "\"\n", 2);
}
diff --git a/src/analysis/scan/matches/bytes.h b/src/analysis/scan/matches/bytes.h
index 22e76a6..e599ee4 100644
--- a/src/analysis/scan/matches/bytes.h
+++ b/src/analysis/scan/matches/bytes.h
@@ -33,26 +33,32 @@
-#define G_TYPE_BYTES_MATCH g_bytes_match_get_type()
-#define G_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BYTES_MATCH, GBytesMatch))
-#define G_IS_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BYTES_MATCH))
-#define G_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BYTES_MATCH, GBytesMatchClass))
-#define G_IS_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BYTES_MATCH))
-#define G_BYTES_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BYTES_MATCH, GBytesMatchClass))
+#define G_TYPE_SCAN_BYTES_MATCH g_scan_bytes_match_get_type()
+#define G_SCAN_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatch))
+#define G_IS_SCAN_BYTES_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_BYTES_MATCH))
+#define G_SCAN_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatchClass))
+#define G_IS_SCAN_BYTES_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_BYTES_MATCH))
+#define G_SCAN_BYTES_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_BYTES_MATCH, GScanBytesMatchClass))
/* Correspondance trouvée avec une chaîne (instance) */
-typedef struct _GBytesMatch GBytesMatch;
+typedef struct _GScanBytesMatch GScanBytesMatch;
/* Correspondance trouvée avec une chaîne (classe) */
-typedef struct _GBytesMatchClass GBytesMatchClass;
+typedef struct _GScanBytesMatchClass GScanBytesMatchClass;
/* Indique le type défini pour un correspondance de chaîne identifiée. */
-GType g_bytes_match_get_type(void);
+GType g_scan_bytes_match_get_type(void);
/* Prend note d'une correspondance trouvée avec un motif. */
-GScanMatch *g_bytes_match_new(GSearchPattern *, GBinContent *, phys_t, phys_t);
+GScanMatch *g_scan_bytes_match_new(GSearchPattern *, GBinContent *, phys_t, phys_t);
+
+/* Fournit une référence au contenu lié à la correspondance. */
+GBinContent *g_scan_bytes_match_get_content(const GScanBytesMatch *);
+
+/* Indique la localisation d'une correspondance établie. */
+phys_t g_scan_bytes_match_get_location(const GScanBytesMatch *, phys_t *, phys_t *);
diff --git a/src/analysis/scan/matches/pending.c b/src/analysis/scan/matches/pending.c
index 73b7a06..9d1037d 100644
--- a/src/analysis/scan/matches/pending.c
+++ b/src/analysis/scan/matches/pending.c
@@ -79,46 +79,52 @@ void exit_pending_matches(pending_matches_t *matches)
/******************************************************************************
* *
* Paramètres : matches = suivi de correspondances à consulter. *
-* start = point de départ d'une suite pour de correspondance.*
-* mindex = indice de départ et d'arrivée. [OUT] *
* *
-* Description : Détermine la zone de correspondance idéale pour complément. *
+* Description : Dénombre les correspondances établies jusque là. *
* *
-* Retour : Bilan de l'opération : true en cas de succès des recherches. *
+* Retour : Quantité de correspondances complètes jusqu'à présent. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool find_target_in_pending_matches(pending_matches_t *matches, phys_t start, size_t *target)
+size_t count_pending_matches(const pending_matches_t *matches)
{
- bool result; /* Bilan à retourner */
- size_t i; /* Boucle de parcours */
- match_area_t *area; /* Zone à initialiser */
+ size_t result; /* Quantité à renvoyer */
- assert(*target <= matches->used);
+ result = matches->used;
- result = false;
+ return result;
- for (i = *target; i < matches->used; i++)
- {
- area = &matches->areas[i];
+}
- if ((area->start + area->length) == start)
- {
- *target = i;
- result = true;
- break;
- }
- }
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à consulter. *
+* count = nombre de correspondances en attente. [OUT] *
+* *
+* Description : Fournit la liste des correspondances établies à présent. *
+* *
+* Retour : Liste de correspondances en lecture seule. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const match_area_t *get_all_pending_matches(const pending_matches_t *matches, size_t *count)
+{
+ match_area_t *result; /* Série à renvoyer */
+
+ result = matches->areas;
+
+ *count = matches->used;
return result;
}
-
/******************************************************************************
* *
* Paramètres : matches = suivi de correspondances à compléter. *
@@ -133,7 +139,7 @@ bool find_target_in_pending_matches(pending_matches_t *matches, phys_t start, si
* *
******************************************************************************/
-void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length)
+void add_pending_match(pending_matches_t *matches, phys_t start, phys_t length)
{
match_area_t *area; /* Zone à initialiser */
@@ -148,7 +154,9 @@ void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length
area = &matches->areas[matches->used++];
area->start = start;
- area->length = length;
+ area->end = start + length;
+
+ area->ttl = 1;
}
@@ -167,21 +175,71 @@ void add_pending_matches(pending_matches_t *matches, phys_t start, phys_t length
* *
******************************************************************************/
-void extend_pending_matches(pending_matches_t *matches, size_t target, phys_t length)
+void extend_pending_match(pending_matches_t *matches, size_t target, phys_t end)
+{
+ match_area_t *area; /* Zone à actualiser */
+
+ assert(target < matches->used);
+
+ area = &matches->areas[matches->used++];
+
+ if (area->ttl == 0)
+ {
+ area->end = end;
+
+ area->ttl = 1;
+
+ }
+ else
+ {
+ assert(area->ttl == 1);
+
+ add_pending_match(matches, area->start, end - area->start);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à consulter. *
+* target = indice de la zone de correspondance concernée. *
+* pos = position à tester. *
+* *
+* Description : Détermine si une correspondance se termine à une position. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool has_pending_match_ending_at(const pending_matches_t *matches, size_t target, phys_t pos)
{
+ bool result; /* Statut à retourner */
+ match_area_t *area; /* Couverture visée */
+
assert(target < matches->used);
- matches->areas[target].length += length;
+ area = &matches->areas[target];
+
+ result = (area->end == pos);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : matches = suivi de correspondances à modifier. *
+* Paramètres : matches = suivi de correspondances à consulter. *
* target = indice de la zone de correspondance concernée. *
+* pos = position à tester. *
+* min = borne inférieure de l'espace à considérer. *
+* max = borne supérieure de l'espace à considérer. *
* *
-* Description : Retire une correspondance finalement non établie du suivi. *
+* Description : Détermine si une correspondance se situe dans une plage. *
* *
* Retour : - *
* *
@@ -189,14 +247,135 @@ void extend_pending_matches(pending_matches_t *matches, size_t target, phys_t le
* *
******************************************************************************/
-void remove_pending_matches(pending_matches_t *matches, size_t target)
+bool has_pending_match_ending_between(const pending_matches_t *matches, size_t target, phys_t pos, phys_t min, phys_t max)
{
+ bool result; /* Statut à retourner */
+ match_area_t *area; /* Couverture visée */
+
assert(target < matches->used);
- if ((target + 1) < matches->used)
- memmove(&matches->areas[target], &matches->areas[target + 1],
- (matches->used - target - 1) * sizeof(match_area_t));
+ area = &matches->areas[target];
+
+ result = ((area->end + min) <= pos && pos <= (area->end + max));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à modifier. *
+* *
+* Description : Réinitialisation à 0 tous les TTL de correspondances. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void reset_pending_matches_ttl(pending_matches_t *matches)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < matches->used; i++)
+ matches->areas[i].ttl = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : matches = suivi de correspondances à modifier. *
+* *
+* Description : Retire toutes les correspondances sans issue pour l'analyse. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void purge_pending_matches(pending_matches_t *matches)
+{
+ match_area_t *del_start; /* Départ d'une zone morte */
+ match_area_t *del_end; /* Fin d'une zone morte */
+ size_t del_remaining; /* Nombre de valides ensuite */
+ size_t del_count; /* Nombre d'éléments à effacer */
+ size_t i; /* Boucle de parcours */
+
+ /**
+ * Note : le code original était le suivant :
+ *
+
+ * for (i = matches->used; i > 0; i--)
+ * if (matches->areas[i - 1].ttl == 0)
+ * {
+ * memmove(&matches->areas[i - 1], &matches->areas[i], (matches->used - i) * sizeof(match_area_t));
+ * matches->used--;
+ * }
+ *
+ * Pour éviter les appels à memmove(), un déplacement par blocs est désormais visée.
+ */
+
+ del_start = NULL;
+ del_end = NULL;
+ del_count = 0;
+ del_remaining = 0;
- matches->used--;
+ /* Suppression en bloc si possible */
+
+ for (i = matches->used; i > 0; i--)
+ {
+ if (matches->areas[i - 1].ttl == 0)
+ {
+ del_start = &matches->areas[i - 1];
+
+ if (del_end == NULL)
+ {
+ del_end = del_start;
+ del_remaining = matches->used - i;
+ }
+
+ del_count++;
+
+ }
+ else
+ {
+ if (del_start != NULL)
+ {
+ assert(&matches->areas[i] == del_start);
+
+ if (del_remaining > 0)
+ memmove(del_start, del_end + 1, del_remaining * sizeof(match_area_t));
+
+ assert(matches->used > del_count);
+ matches->used -= del_count;
+
+ del_start = NULL;
+ del_end = NULL;
+ del_count = 0;
+ del_remaining = 0;
+
+ }
+
+ }
+
+ }
+
+ /* Dernier traitement au besoin */
+
+ if (del_start != NULL)
+ {
+ assert(&matches->areas[0] == del_start);
+
+ if (del_remaining > 0)
+ memmove(del_start, del_end + 1, del_remaining * sizeof(match_area_t));
+
+ assert(matches->used >= del_count);
+ matches->used -= del_count;
+
+ }
}
diff --git a/src/analysis/scan/matches/pending.h b/src/analysis/scan/matches/pending.h
index de2fd5f..0a1fe5c 100644
--- a/src/analysis/scan/matches/pending.h
+++ b/src/analysis/scan/matches/pending.h
@@ -25,6 +25,9 @@
#define _ANALYSIS_SCAN_MATCHES_PENDING_H
+#include <stdbool.h>
+
+
#include "../../content.h"
@@ -33,7 +36,9 @@
typedef struct _match_area_t
{
phys_t start; /* Point de départ */
- phys_t length; /* Taille de la zone couverte */
+ phys_t end; /* Point d'arrivée (exclus) */
+
+ unsigned long ttl; /* Durée de vie pour analyse */
} match_area_t;
@@ -55,21 +60,34 @@ void init_pending_matches(pending_matches_t *);
/* Libère la mémoire utilisée par une consolidation. */
void exit_pending_matches(pending_matches_t *);
+// TODO ajouter un assert(used == 0) si !initialized */
#define are_pending_matches_initialized(pm) pm->initialized
#define set_pending_matches_initialized(pm) pm->initialized = true
-/* Détermine la zone de correspondance idéale pour complément. */
-bool find_target_in_pending_matches(pending_matches_t *, phys_t, size_t *);
+/* Dénombre les correspondances établies jusque là. */
+size_t count_pending_matches(const pending_matches_t *);
+
+/* Fournit la liste des correspondances établies à présent. */
+const match_area_t *get_all_pending_matches(const pending_matches_t *, size_t *);
/* Ajoute au suivi la définition d'une nouvelle correspondance. */
-void add_pending_matches(pending_matches_t *, phys_t, phys_t);
+void add_pending_match(pending_matches_t *, phys_t, phys_t);
/* Etend une zone couverte dans le suivi des correspondances. */
-void extend_pending_matches(pending_matches_t *, size_t, phys_t);
+void extend_pending_match(pending_matches_t *, size_t, phys_t);
+
+/* Détermine si une correspondance se situe dans une plage. */
+bool has_pending_match_ending_between(const pending_matches_t *, size_t, phys_t, phys_t, phys_t);
+
+/* Détermine si une correspondance se termine à une position. */
+bool has_pending_match_ending_at(const pending_matches_t *, size_t, phys_t);
+
+/* Réinitialisation à 0 tous les TTL de correspondances. */
+void reset_pending_matches_ttl(pending_matches_t *);
-/* Retire une correspondance finalement non établie du suivi. */
-void remove_pending_matches(pending_matches_t *, size_t);
+/* Retire toutes les correspondances sans issue pour l'analyse. */
+void purge_pending_matches(pending_matches_t *);
diff --git a/src/analysis/scan/options-int.h b/src/analysis/scan/options-int.h
index a7772ed..4e85974 100644
--- a/src/analysis/scan/options-int.h
+++ b/src/analysis/scan/options-int.h
@@ -36,6 +36,8 @@ struct _GScanOptions
GType data_backend; /* Choix du moteur d'analyse */
+ bool print_json; /* Sortie au format json ? */
+ bool print_strings; /* Affichage de correspondances*/
bool print_stats; /* Affichage de statistiques ? */
};
diff --git a/src/analysis/scan/options.c b/src/analysis/scan/options.c
index 89e411e..cb56c2b 100644
--- a/src/analysis/scan/options.c
+++ b/src/analysis/scan/options.c
@@ -199,6 +199,92 @@ void g_scan_options_set_backend_for_data(GScanOptions *options, GType backend)
* *
* Paramètres : options = ensemble d'options d'analyses à consulter. *
* *
+* Description : Impose le format JSON comme type de sortie. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_options_get_print_json(const GScanOptions *options)
+{
+ bool result; /* Statut à retourner */
+
+ result = options->print_json;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à modifier. *
+* state = état de l'option visée à conserver. *
+* *
+* Description : Mémorise le format JSON comme type de sortie. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_options_set_print_json(GScanOptions *options, bool state)
+{
+ options->print_json = state;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à consulter. *
+* *
+* Description : Indique un besoin d'affichage des correspondances finales. *
+* *
+* Retour : Etat de l'option visée à conservé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_options_get_print_strings(const GScanOptions *options)
+{
+ bool result; /* Statut à retourner */
+
+ result = options->print_strings;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à modifier. *
+* state = état de l'option visée à conserver. *
+* *
+* Description : Mémorise un besoin d'affichage des correspondances finales. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_options_set_print_strings(GScanOptions *options, bool state)
+{
+ options->print_strings = state;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à consulter. *
+* *
* Description : Indique un besoin de statistiques en fin de compilation. *
* *
* Retour : Etat de l'option visée à conservé. *
diff --git a/src/analysis/scan/options.h b/src/analysis/scan/options.h
index a7931c5..6b027e3 100644
--- a/src/analysis/scan/options.h
+++ b/src/analysis/scan/options.h
@@ -57,6 +57,18 @@ GType g_scan_options_get_backend_for_data(const GScanOptions *);
/* Sélectionne un type de moteur d'analyse pour données brutes. */
void g_scan_options_set_backend_for_data(GScanOptions *, GType);
+/* Impose le format JSON comme type de sortie. */
+bool g_scan_options_get_print_json(const GScanOptions *);
+
+/* Mémorise le format JSON comme type de sortie. */
+void g_scan_options_set_print_json(GScanOptions *, bool);
+
+/* Indique un besoin d'affichage des correspondances finales. */
+bool g_scan_options_get_print_strings(const GScanOptions *);
+
+/* Mémorise un besoin d'affichage des correspondances finales. */
+void g_scan_options_set_print_strings(GScanOptions *, bool);
+
/* Indique un besoin de statistiques en fin de compilation. */
bool g_scan_options_get_print_stats(const GScanOptions *);
diff --git a/src/analysis/scan/pattern-int.h b/src/analysis/scan/pattern-int.h
index 03af30f..b510c75 100644
--- a/src/analysis/scan/pattern-int.h
+++ b/src/analysis/scan/pattern-int.h
@@ -28,9 +28,15 @@
#include "pattern.h"
+#include "context.h"
-/* Décompte le nombre de correspondances identifiées. */
-typedef size_t (* count_pattern_matchs_fc) (const GSearchPattern *);
+
+
+/* Affiche un motif de recherche au format texte. */
+typedef void (* output_pattern_to_text_fc) (const GSearchPattern *, GScanContext *, int);
+
+/* Affiche un motif de recherche au format JSON. */
+typedef void (* output_pattern_to_json_fc) (const GSearchPattern *, GScanContext *, const sized_string_t *, unsigned int, int);
/* Motif à rechercher au sein d'un contenu (instance) */
@@ -47,7 +53,8 @@ struct _GSearchPatternClass
{
GObjectClass parent; /* A laisser en premier */
- count_pattern_matchs_fc count; /* Décompte des résultats */
+ output_pattern_to_text_fc to_text; /* Impression au format texte */
+ output_pattern_to_json_fc to_json; /* Impression au format JSON */
};
diff --git a/src/analysis/scan/pattern.c b/src/analysis/scan/pattern.c
index 53a2662..5b966d2 100644
--- a/src/analysis/scan/pattern.c
+++ b/src/analysis/scan/pattern.c
@@ -186,25 +186,122 @@ void g_search_pattern_set_name(GSearchPattern *pattern, const char *name, size_t
/******************************************************************************
* *
-* Paramètres : pattern = définition de motif à consulter. *
+* Paramètres : pattern = définition de motif à considérer. *
+* context = contexte de l'analyse à mener. *
+* fd = canal d'écriture. *
* *
-* Description : Décompte le nombre de correspondances identifiées. *
+* Description : Affiche un motif de recherche au format texte. *
* *
-* Retour : Quantité d'identifications réalisées. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-size_t g_search_pattern_count_matchs(const GSearchPattern *pattern)
+void g_search_pattern_output_to_text(const GSearchPattern *pattern, GScanContext *context, int fd)
{
- size_t result; /* Décompte à retourner */
GSearchPatternClass *class; /* Classe à activer */
class = G_SEARCH_PATTERN_GET_CLASS(pattern);
- result = 0;//class->count(pattern);
+ class->to_text(pattern, context, fd);
- return result;
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = définition de motif à considérer. *
+* context = contexte de l'analyse à mener. *
+* *
+* Description : Convertit un motif de recherche en texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_search_pattern_convert_as_text(const GSearchPattern *pattern, GScanContext *context)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* trailing = impose une virgule finale ? *
+* *
+* Description : Affiche un motif de recherche au format JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_search_pattern_output_to_json(const GSearchPattern *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd, bool trailing)
+{
+ unsigned int i; /* Boucle de parcours */
+ GSearchPatternClass *class; /* Classe à activer */
+
+ /* Introduction */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "{\n", 2);
+
+ /* Désignation du motif */
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"name\": \"$", 10);
+
+ write(fd, pattern->name, strlen(pattern->name));
+
+ write(fd, "\",\n", 3);
+
+ /* Affichage du contenu */
+
+ class = G_SEARCH_PATTERN_GET_CLASS(pattern);
+
+ class->to_json(pattern, context, padding, level + 1, fd);
+
+ /* Conclusion */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ if (trailing)
+ write(fd, "},\n", 3);
+ else
+ write(fd, "}\n", 2);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pattern = définition de motif à considérer. *
+* context = contexte de l'analyse à mener. *
+* *
+* Description : Convertit un motif de recherche en JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_search_pattern_convert_as_json(const GSearchPattern *pattern, GScanContext *context)
+{
+ /* TODO */
}
diff --git a/src/analysis/scan/pattern.h b/src/analysis/scan/pattern.h
index 9ea66d3..0e4327d 100644
--- a/src/analysis/scan/pattern.h
+++ b/src/analysis/scan/pattern.h
@@ -30,9 +30,14 @@
#include "../../arch/archbase.h"
#include "../../arch/vmpa.h"
+#include "../../common/szstr.h"
+/* Depuis context.h: contexte de suivi d'une analyse en cours (instance) */
+typedef struct _GScanContext GScanContext;
+;
+
#define G_TYPE_SEARCH_PATTERN g_search_pattern_get_type()
#define G_SEARCH_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SEARCH_PATTERN, GSearchPattern))
#define G_IS_SEARCH_PATTERN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SEARCH_PATTERN))
@@ -57,8 +62,17 @@ const char *g_search_pattern_get_name(const GSearchPattern *);
/* Inscrit la désignation attribuée à un motif de recherche. */
void g_search_pattern_set_name(GSearchPattern *, const char *, size_t);
-/* Décompte le nombre de correspondances identifiées. */
-size_t g_search_pattern_count_matchs(const GSearchPattern *);
+/* Affiche un motif de recherche au format texte. */
+void g_search_pattern_output_to_text(const GSearchPattern *, GScanContext *, int);
+
+/* Convertit un motif de recherche en texte. */
+void g_search_pattern_convert_as_text(const GSearchPattern *, GScanContext *);
+
+/* Affiche un motif de recherche au format JSON. */
+void g_search_pattern_output_to_json(const GSearchPattern *, GScanContext *, const sized_string_t *, unsigned int, int, bool);
+
+/* Convertit un motif de recherche en JSON. */
+void g_search_pattern_convert_as_json(const GSearchPattern *, GScanContext *);
diff --git a/src/analysis/scan/patterns/Makefile.am b/src/analysis/scan/patterns/Makefile.am
index 4082275..c3d0994 100644
--- a/src/analysis/scan/patterns/Makefile.am
+++ b/src/analysis/scan/patterns/Makefile.am
@@ -5,14 +5,17 @@ noinst_LTLIBRARIES = libanalysisscanpatterns.la
libanalysisscanpatterns_la_SOURCES = \
backend-int.h \
backend.h backend.c \
+ modifier-int.h \
+ modifier.h modifier.c \
token-int.h \
token.h token.c
libanalysisscanpatterns_la_LIBADD = \
backends/libanalysisscanpatternsbackends.la \
+ modifiers/libanalysisscanpatternsmodifiers.la \
tokens/libanalysisscanpatternstokens.la
-libanalysisscanpatterns_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+libanalysisscanpatterns_la_CFLAGS = $(LIBGOBJ_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS)
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
@@ -20,4 +23,4 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
dev_HEADERS = $(libanalysisscanpatterns_la_SOURCES:%c=)
-SUBDIRS = backends tokens
+SUBDIRS = backends modifiers tokens
diff --git a/src/analysis/scan/patterns/modifier-int.h b/src/analysis/scan/patterns/modifier-int.h
new file mode 100644
index 0000000..246c139
--- /dev/null
+++ b/src/analysis/scan/patterns/modifier-int.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier-int.h - prototypes internes pour la modification d'une séquence d'octets pour un motif recherché
+ *
+ * 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_MODIFIER_INT_H
+#define _ANALYSIS_SCAN_MODIFIER_INT_H
+
+
+#include "modifier.h"
+
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+typedef char * (* get_scan_modifier_name_fc) (const GScanTokenModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+typedef bool (* transform_scan_token_fc) (const GScanTokenModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+/* Transformation d'une séquence d'octets en une ou plusieurs autres formes (instance) */
+struct _GScanTokenModifier
+{
+ GObject parent; /* A laisser en premier */
+
+};
+
+/* Transformation d'une séquence d'octets en une ou plusieurs autres formes (classe) */
+struct _GScanTokenModifierClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ get_scan_modifier_name_fc get_name; /* Fourniture du nom d'appel */
+
+ transform_scan_token_fc transform; /* Opération de transformation */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_MODIFIER_INT_H */
diff --git a/src/analysis/scan/patterns/modifier.c b/src/analysis/scan/patterns/modifier.c
new file mode 100644
index 0000000..77d8bfd
--- /dev/null
+++ b/src/analysis/scan/patterns/modifier.c
@@ -0,0 +1,181 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.c - modification d'une séquence d'octets pour un motif recherché
+ *
+ * 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 "modifier.h"
+
+
+#include "modifier-int.h"
+
+
+
+/* Initialise la classe des transformations d'octets. */
+static void g_scan_token_modifier_class_init(GScanTokenModifierClass *);
+
+/* Initialise une instance de transformation d'octets. */
+static void g_scan_token_modifier_init(GScanTokenModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_token_modifier_dispose(GScanTokenModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_token_modifier_finalize(GScanTokenModifier *);
+
+
+
+/* Indique le type défini pour une transformation d'une séquence d'octets. */
+G_DEFINE_TYPE(GScanTokenModifier, g_scan_token_modifier, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transformations d'octets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_modifier_class_init(GScanTokenModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_token_modifier_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transformation d'octets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_modifier_init(GScanTokenModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_modifier_dispose(GScanTokenModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_token_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_token_modifier_finalize(GScanTokenModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_token_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *g_scan_token_modifier_get_name(const GScanTokenModifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+ GScanTokenModifierClass *class; /* Classe à activer */
+
+ class = G_SCAN_TOKEN_MODIFIER_GET_CLASS(modifier);
+
+ result = class->get_name(modifier);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquence d'octets à traiter. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* count = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_token_modifier_transform(const GScanTokenModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ GScanTokenModifierClass *class; /* Classe à activer */
+
+ class = G_SCAN_TOKEN_MODIFIER_GET_CLASS(modifier);
+
+ result = class->transform(modifier, src, dest, count);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifier.h b/src/analysis/scan/patterns/modifier.h
new file mode 100644
index 0000000..a195ca8
--- /dev/null
+++ b/src/analysis/scan/patterns/modifier.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * modifier.h - prototypes pour la modification d'une séquence d'octets pour un motif recherché
+ *
+ * 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_MODIFIER_H
+#define _ANALYSIS_SCAN_MODIFIER_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../../../common/szstr.h"
+
+
+
+#define G_TYPE_SCAN_TOKEN_MODIFIER g_scan_token_modifier_get_type()
+#define G_SCAN_TOKEN_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_MODIFIER, GScanTokenModifier))
+#define G_IS_SCAN_TOKEN_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_MODIFIER))
+#define G_SCAN_TOKEN_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_MODIFIER, GScanTokenModifierClass))
+#define G_IS_SCAN_TOKEN_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_MODIFIER))
+#define G_SCAN_TOKEN_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_MODIFIER, GScanTokenModifierClass))
+
+
+/* Transformation d'une séquence d'octets en une ou plusieurs autres formes (instance) */
+typedef struct _GScanTokenModifier GScanTokenModifier;
+
+/* Transformation d'une séquence d'octets en une ou plusieurs autres formes (classe) */
+typedef struct _GScanTokenModifierClass GScanTokenModifierClass;
+
+
+/* Indique le type défini pour une transformation d'une séquence d'octets. */
+GType g_scan_token_modifier_get_type(void);
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+char *g_scan_token_modifier_get_name(const GScanTokenModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+bool g_scan_token_modifier_transform(const GScanTokenModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+#endif /* _ANALYSIS_SCAN_MODIFIER_H */
diff --git a/src/analysis/scan/patterns/modifiers/Makefile.am b/src/analysis/scan/patterns/modifiers/Makefile.am
new file mode 100644
index 0000000..fe5263c
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/Makefile.am
@@ -0,0 +1,17 @@
+
+noinst_LTLIBRARIES = libanalysisscanpatternsmodifiers.la
+
+
+libanalysisscanpatternsmodifiers_la_SOURCES = \
+ hex.h hex.c \
+ list-int.h \
+ list.h list.c \
+ plain.h plain.c \
+ rev.h rev.c
+
+libanalysisscanpatternsmodifiers_la_CFLAGS = $(LIBGOBJ_CFLAGS)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(libanalysisscanpatternsmodifiers_la_SOURCES:%c=)
diff --git a/src/analysis/scan/patterns/modifiers/hex.c b/src/analysis/scan/patterns/modifiers/hex.c
new file mode 100644
index 0000000..cf1583c
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/hex.c
@@ -0,0 +1,252 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.c - transformation en version hexadécimale d'une séquence d'octets
+ *
+ * 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 "../modifier-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transformations en hexadécimal. */
+static void g_scan_hex_modifier_class_init(GScanHexModifierClass *klass);
+
+/* Initialise une instance de transformation en hexadécimal. */
+static void g_scan_hex_modifier_init(GScanHexModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_hex_modifier_dispose(GScanHexModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_hex_modifier_finalize(GScanHexModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_hex_modifier_get_name(const GScanHexModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_hex_modifier_transform(const GScanHexModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transformation d'une séquence d'octets dans sa version hexadécimale. */
+G_DEFINE_TYPE(GScanHexModifier, g_scan_hex_modifier, G_TYPE_SCAN_TOKEN_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transformations en hexadécimal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_modifier_class_init(GScanHexModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_hex_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_hex_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_hex_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_hex_modifier_transform;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transformation en hexadécimal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_modifier_init(GScanHexModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_modifier_dispose(GScanHexModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_hex_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_hex_modifier_finalize(GScanHexModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_hex_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur fournistant une vue hexadécimale. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_hex_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_HEX_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_hex_modifier_get_name(const GScanHexModifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("hex");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquence d'octets à traiter. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* count = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_hex_modifier_transform(const GScanHexModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours */
+
+ static char *alphabet = "0123456789abcdef";
+
+ result = true;
+
+ *dest = malloc(1 * sizeof(sized_binary_t));
+ *count = 1;
+
+ binary = &(*dest)[0];
+
+ binary->len = src->len * 2;
+ binary->data = malloc(binary->len);
+
+ for (i = 0; i < src->len; i++)
+ {
+ binary->data[i * 2 + 0] = alphabet[src->data[i] >> 4];
+ binary->data[i * 2 + 1] = alphabet[src->data[i] & 0xf];
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifiers/hex.h b/src/analysis/scan/patterns/modifiers/hex.h
new file mode 100644
index 0000000..1a9b410
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/hex.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hex.h - prototypes pour la transformation en version hexadécimale d'une séquence d'octets
+ *
+ * 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_MODIFIERS_HEX_H
+#define _ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H
+
+
+#include <glib-object.h>
+
+
+#include "../modifier.h"
+
+
+
+#define G_TYPE_SCAN_HEX_MODIFIER g_scan_hex_modifier_get_type()
+#define G_SCAN_HEX_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_HEX_MODIFIER, GScanHexModifier))
+#define G_IS_SCAN_HEX_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_HEX_MODIFIER))
+#define G_SCAN_HEX_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_HEX_MODIFIER, GScanHexModifierClass))
+#define G_IS_SCAN_HEX_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_HEX_MODIFIER))
+#define G_SCAN_HEX_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_HEX_MODIFIER, GScanHexModifierClass))
+
+
+/* Transformation d'une séquence d'octets dans sa version hexadécimale (instance) */
+typedef GScanTokenModifier GScanHexModifier;
+
+/* Transformation d'une séquence d'octets dans sa version hexadécimale (classe) */
+typedef GScanTokenModifierClass GScanHexModifierClass;
+
+
+/* Indique le type défini pour une transformation d'une séquence d'octets dans sa version hexadécimale. */
+GType g_scan_hex_modifier_get_type(void);
+
+/* Construit un modificateur fournistant une vue hexadécimale. */
+GScanTokenModifier *g_scan_hex_modifier_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_MODIFIERS_HEX_H */
diff --git a/src/analysis/scan/patterns/modifiers/list-int.h b/src/analysis/scan/patterns/modifiers/list-int.h
new file mode 100644
index 0000000..c8ed64b
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/list-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list-int.h - prototypes internes pour la gestion d'une liste de transformateurs
+ *
+ * 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_MODIFIERS_LIST_INT_H
+#define _ANALYSIS_SCAN_MODIFIERS_LIST_INT_H
+
+
+#include "list.h"
+
+
+#include "../modifier-int.h"
+
+
+
+/* Liste de transformations d'une séquence d'octets (instance) */
+struct _GScanModifierList
+{
+ GObject parent; /* A laisser en premier */
+
+ GScanTokenModifier **modifiers; /* Liste de transformateurs */
+ size_t count; /* Taille de cette liste */
+
+};
+
+/* Liste de transformations d'une séquence d'octets (classe) */
+struct _GScanModifierListClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_MODIFIERS_LIST_INT_H */
diff --git a/src/analysis/scan/patterns/modifiers/list.c b/src/analysis/scan/patterns/modifiers/list.c
new file mode 100644
index 0000000..e08d509
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/list.c
@@ -0,0 +1,405 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.c - gestion d'une liste de transformateurs
+ *
+ * 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 "list.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "list-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des liste de transformations d'octets. */
+static void g_scan_modifier_list_class_init(GScanModifierListClass *);
+
+/* Initialise une instance de liste de transformations d'octets. */
+static void g_scan_modifier_list_init(GScanModifierList *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_modifier_list_dispose(GScanModifierList *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_modifier_list_finalize(GScanModifierList *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_modifier_list_get_name(const GScanModifierList *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_modifier_list_transform(const GScanModifierList *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une série de transformations d'octets. */
+G_DEFINE_TYPE(GScanModifierList, g_scan_modifier_list, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des liste de transformations d'octets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_modifier_list_class_init(GScanModifierListClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_modifier_list_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_modifier_list_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_modifier_list_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_modifier_list_transform;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = instance à initialiser. *
+* *
+* Description : Initialise une instance de liste de transformations d'octets.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_modifier_list_init(GScanModifierList *list)
+{
+ list->modifiers = NULL;
+ list->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_modifier_list_dispose(GScanModifierList *list)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < list->count; i++)
+ g_clear_object(&list->modifiers[i]);
+
+ G_OBJECT_CLASS(g_scan_modifier_list_parent_class)->dispose(G_OBJECT(list));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_modifier_list_finalize(GScanModifierList *list)
+{
+ if (list->modifiers != NULL)
+ free(list->modifiers);
+
+ G_OBJECT_CLASS(g_scan_modifier_list_parent_class)->finalize(G_OBJECT(list));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit une liste de modificateurs d'octets. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_modifier_list_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_MODIFIER_LIST, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste de modificateurs à étendre. *
+* modifier = modificateur à intégrer. *
+* *
+* Description : Intègre un nouveau transformateur dans une liste. *
+* *
+* Retour : Bilan de l'ajout : false si un élément similaire est déjà là.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_modifier_list_add(GScanModifierList *list, GScanTokenModifier *modifier)
+{
+ bool result; /* Bilan à retourner */
+ char *name; /* Désignation du modificateur */
+ size_t i; /* Boucle de parcours */
+ char *other; /* Désignation de ses collègues*/
+
+ /* Recherche d'une redondance */
+
+ /**
+ * Note : deux listes identiques passent sans soucis.
+ * TODO : comparer les transformateurs ?
+ */
+
+ result = true;
+
+ if (!G_IS_SCAN_MODIFIER_LIST(modifier))
+ {
+ name = g_scan_token_modifier_get_name(modifier);
+
+ for (i = 0; i < list->count && result; i++)
+ {
+ if (G_IS_SCAN_MODIFIER_LIST(list->modifiers[i]))
+ continue;
+
+ other = g_scan_token_modifier_get_name(list->modifiers[i]);
+
+ result = (strcmp(name, other) != 0);
+
+ free(other);
+
+ }
+
+ }
+
+ free(name);
+
+ if (!result)
+ goto done;
+
+ /* Inclusion dans la liste */
+
+ list->modifiers = realloc(list->modifiers, ++list->count * sizeof(GScanTokenModifier *));
+
+ list->modifiers[list->count - 1] = modifier;
+ g_object_ref(G_OBJECT(modifier));
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = série à consulter. *
+* *
+* Description : Indique le nombre de transformateurs intégrés dans la liste. *
+* *
+* Retour : Nombre de modificateurs représentés. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_scan_modifier_list_count(const GScanModifierList *list)
+{
+ size_t result; /* Quantité à retourner */
+
+ result = list->count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = série à consulter. *
+* index = indice du paramètre à retourner. *
+* *
+* Description : Fournit un transformateur donné de la liste. *
+* *
+* Retour : Modificateur inclus dans la liste ou NULL si mauvais indice. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_modifier_list_get(const GScanModifierList *list, size_t index)
+{
+ GScanTokenModifier *result; /* Instance à retourner */
+
+ assert(index < list->count);
+
+ if (index < list->count)
+ {
+ result = list->modifiers[index];
+ g_object_ref(G_OBJECT(result));
+ }
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_modifier_list_get_name(const GScanModifierList *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("(list)");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquence d'octets à traiter. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* count = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_modifier_list_transform(const GScanModifierList *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ size_t i; /* Boucle de parcours #1 */
+ sized_binary_t *extra; /* Motifs supplémentaires */
+ size_t extra_count; /* Quantité de ces motifs */
+ sized_binary_t *new; /* Nouvel emplacement libre */
+ size_t k; /* Boucle de parcours #2 */
+
+ *dest = NULL;
+ *count = 0;
+
+ for (i = 0; i < modifier->count; i++)
+ {
+ result = g_scan_token_modifier_transform(modifier->modifiers[i], src, &extra, &extra_count);
+ if (!result) goto exit;
+
+ new = (*dest) + *count;
+
+ *count += extra_count;
+ *dest = realloc(*dest, *count * sizeof(sized_binary_t));
+
+ for (k = 0; k < extra_count; k++, new++)
+ copy_szstr(*new, extra[k]);
+
+ free(extra);
+
+ }
+
+ exit:
+
+ if (!result)
+ {
+ for (i = 0; i < *count; i++)
+ exit_szstr(dest[i]);
+
+ if (*dest != NULL)
+ free(*dest);
+
+ *dest = NULL;
+ *count = 0;
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifiers/list.h b/src/analysis/scan/patterns/modifiers/list.h
new file mode 100644
index 0000000..abd1eae
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/list.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * list.h - prototypes pour la gestion d'une liste de transformateurs
+ *
+ * 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_MODIFIERS_LIST_H
+#define _ANALYSIS_SCAN_MODIFIERS_LIST_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../modifier.h"
+
+
+
+#define G_TYPE_SCAN_MODIFIER_LIST g_scan_modifier_list_get_type()
+#define G_SCAN_MODIFIER_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_MODIFIER_LIST, GScanModifierList))
+#define G_IS_SCAN_MODIFIER_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_MODIFIER_LIST))
+#define G_SCAN_MODIFIER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_MODIFIER_LIST, GScanModifierListClass))
+#define G_IS_SCAN_MODIFIER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_MODIFIER_LIST))
+#define G_SCAN_MODIFIER_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_MODIFIER_LIST, GScanModifierListClass))
+
+
+/* Liste de transformations d'une séquence d'octets (instance) */
+typedef struct _GScanModifierList GScanModifierList;
+
+/* Liste de transformations d'une séquence d'octets (classe) */
+typedef struct _GScanModifierListClass GScanModifierListClass;
+
+
+/* Indique le type défini pour une série de transformations d'octets. */
+GType g_scan_modifier_list_get_type(void);
+
+/* Construit une liste de modificateurs d'octets. */
+GScanTokenModifier *g_scan_modifier_list_new(void);
+
+/* Intègre un nouveau transformateur dans une liste. */
+bool g_scan_modifier_list_add(GScanModifierList *, GScanTokenModifier *);
+
+/* Indique le nombre de transformateurs intégrés dans la liste. */
+size_t g_scan_modifier_list_count(const GScanModifierList *);
+
+/* Fournit un transformateur donné de la liste. */
+GScanTokenModifier *g_scan_modifier_list_get(const GScanModifierList *, size_t);
+
+
+
+#endif /* _ANALYSIS_SCAN_MODIFIERS_LIST_H */
diff --git a/src/analysis/scan/patterns/modifiers/plain.c b/src/analysis/scan/patterns/modifiers/plain.c
new file mode 100644
index 0000000..5837d46
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/plain.c
@@ -0,0 +1,245 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.c - transmission à l'identique d'une séquence d'octets
+ *
+ * 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 <malloc.h>
+#include <string.h>
+
+
+#include "../modifier-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions à l'identique. */
+static void g_scan_plain_modifier_class_init(GScanPlainModifierClass *klass);
+
+/* Initialise une instance de transmission à l'identique. */
+static void g_scan_plain_modifier_init(GScanPlainModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_plain_modifier_dispose(GScanPlainModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_plain_modifier_finalize(GScanPlainModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_plain_modifier_get_name(const GScanPlainModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_plain_modifier_transform(const GScanPlainModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transmission à l'identique d'une séquence d'octets. */
+G_DEFINE_TYPE(GScanPlainModifier, g_scan_plain_modifier, G_TYPE_SCAN_TOKEN_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions à l'identique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_plain_modifier_class_init(GScanPlainModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_plain_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_plain_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_plain_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_plain_modifier_transform;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission à l'identique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_plain_modifier_init(GScanPlainModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_plain_modifier_dispose(GScanPlainModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_plain_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_plain_modifier_finalize(GScanPlainModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_plain_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des octets à l'identique. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_plain_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_PLAIN_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_plain_modifier_get_name(const GScanPlainModifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("plain");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquence d'octets à traiter. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* count = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_plain_modifier_transform(const GScanPlainModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+
+ result = true;
+
+ *dest = malloc(1 * sizeof(sized_binary_t));
+ *count = 1;
+
+ binary = &(*dest)[0];
+
+ binary->len = src->len;
+ binary->data = malloc(binary->len);
+
+ memcpy(binary->data, src->data, src->len);
+
+ return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifiers/plain.h b/src/analysis/scan/patterns/modifiers/plain.h
new file mode 100644
index 0000000..ecabefd
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/plain.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * plain.h - prototypes pour la transmission à l'identique d'une séquence d'octets
+ *
+ * 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_MODIFIERS_PLAIN_H
+#define _ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H
+
+
+#include <glib-object.h>
+
+
+#include "../modifier.h"
+
+
+
+#define G_TYPE_SCAN_PLAIN_MODIFIER g_scan_plain_modifier_get_type()
+#define G_SCAN_PLAIN_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PLAIN_MODIFIER, GScanPlainModifier))
+#define G_IS_SCAN_PLAIN_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PLAIN_MODIFIER))
+#define G_SCAN_PLAIN_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PLAIN_MODIFIER, GScanPlainModifierClass))
+#define G_IS_SCAN_PLAIN_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PLAIN_MODIFIER))
+#define G_SCAN_PLAIN_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PLAIN_MODIFIER, GScanPlainModifierClass))
+
+
+/* Transmission à l'identique d'une séquence d'octets (instance) */
+typedef GScanTokenModifier GScanPlainModifier;
+
+/* Transmission à l'identique d'une séquence d'octets (classe) */
+typedef GScanTokenModifierClass GScanPlainModifierClass;
+
+
+/* Indique le type défini pour une transmission à l'identique d'une séquence d'octets. */
+GType g_scan_plain_modifier_get_type(void);
+
+/* Construit un modificateur livrant des octets à l'identique. */
+GScanTokenModifier *g_scan_plain_modifier_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_MODIFIERS_PLAIN_H */
diff --git a/src/analysis/scan/patterns/modifiers/rev.c b/src/analysis/scan/patterns/modifiers/rev.c
new file mode 100644
index 0000000..d22b549
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/rev.c
@@ -0,0 +1,247 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rev.c - transormation via inversement d'une séquence d'octets
+ *
+ * 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 "rev.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../modifier-int.h"
+
+
+
+/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */
+
+
+/* Initialise la classe des transmissions via inversement. */
+static void g_scan_reverse_modifier_class_init(GScanReverseModifierClass *klass);
+
+/* Initialise une instance de transmission via inversement. */
+static void g_scan_reverse_modifier_init(GScanReverseModifier *);
+
+/* Supprime toutes les références externes. */
+static void g_scan_reverse_modifier_dispose(GScanReverseModifier *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_scan_reverse_modifier_finalize(GScanReverseModifier *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit le nom d'appel d'un modificateur pour motif. */
+static char *g_scan_reverse_modifier_get_name(const GScanReverseModifier *);
+
+/* Transforme une séquence d'octets pour motif de recherche. */
+static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *, const sized_binary_t *, sized_binary_t **, size_t *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une transormation via inversement d'une séquence d'octets. */
+G_DEFINE_TYPE(GScanReverseModifier, g_scan_reverse_modifier, G_TYPE_SCAN_TOKEN_MODIFIER);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des transmissions via inversement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_reverse_modifier_class_init(GScanReverseModifierClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GScanTokenModifierClass *modifier; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_reverse_modifier_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_scan_reverse_modifier_finalize;
+
+ modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass);
+
+ modifier->get_name = (get_scan_modifier_name_fc)g_scan_reverse_modifier_get_name;
+
+ modifier->transform = (transform_scan_token_fc)g_scan_reverse_modifier_transform;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance à initialiser. *
+* *
+* Description : Initialise une instance de transmission via inversement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_reverse_modifier_init(GScanReverseModifier *modifier)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_reverse_modifier_dispose(GScanReverseModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_reverse_modifier_parent_class)->dispose(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_scan_reverse_modifier_finalize(GScanReverseModifier *modifier)
+{
+ G_OBJECT_CLASS(g_scan_reverse_modifier_parent_class)->finalize(G_OBJECT(modifier));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un modificateur livrant des octets inversés. *
+* *
+* Retour : Mécanisme mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GScanTokenModifier *g_scan_reverse_modifier_new(void)
+{
+ GScanTokenModifier *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_SCAN_REVERSE_MODIFIER, NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à consulter. *
+* *
+* Description : Fournit le nom d'appel d'un modificateur pour motif. *
+* *
+* Retour : Désignation humaine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_scan_reverse_modifier_get_name(const GScanReverseModifier *modifier)
+{
+ char *result; /* Désignation à retourner */
+
+ result = strdup("rev");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : modifier = modificateur à solliciter. *
+* src = séquence d'octets à traiter. *
+* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] *
+* count = quantité de ces séquences. *
+* *
+* Description : Transforme une séquence d'octets pour motif de recherche. *
+* *
+* Retour : Bilan de l'opération : succès ou échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count)
+{
+ bool result; /* Bilan d'opération à renvoyer*/
+ sized_binary_t *binary; /* Raccourci vers le stockage */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ *dest = malloc(1 * sizeof(sized_binary_t));
+ *count = 1;
+
+ binary = &(*dest)[0];
+
+ binary->len = src->len;
+ binary->data = malloc(binary->len);
+
+ for (i = 0; i < src->len; i++)
+ binary->data[src->len - i - 1] = src->data[i];
+
+ return result;
+
+}
diff --git a/src/analysis/scan/patterns/modifiers/rev.h b/src/analysis/scan/patterns/modifiers/rev.h
new file mode 100644
index 0000000..5b4e398
--- /dev/null
+++ b/src/analysis/scan/patterns/modifiers/rev.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rev.h - prototypes pour la transormation via inversement d'une séquence d'octets
+ *
+ * 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_MODIFIERS_REV_H
+#define _ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H
+
+
+#include <glib-object.h>
+
+
+#include "../modifier.h"
+
+
+
+#define G_TYPE_SCAN_REVERSE_MODIFIER g_scan_reverse_modifier_get_type()
+#define G_SCAN_REVERSE_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_REVERSE_MODIFIER, GScanReverseModifier))
+#define G_IS_SCAN_REVERSE_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_REVERSE_MODIFIER))
+#define G_SCAN_REVERSE_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_REVERSE_MODIFIER, GScanReverseModifierClass))
+#define G_IS_SCAN_REVERSE_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_REVERSE_MODIFIER))
+#define G_SCAN_REVERSE_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_REVERSE_MODIFIER, GScanReverseModifierClass))
+
+
+/* Transormation via inversement d'une séquence d'octets (instance) */
+typedef GScanTokenModifier GScanReverseModifier;
+
+/* Transormation via inversement d'une séquence d'octets (classe) */
+typedef GScanTokenModifierClass GScanReverseModifierClass;
+
+
+/* Indique le type défini pour une transormation via inversement d'une séquence d'octets. */
+GType g_scan_reverse_modifier_get_type(void);
+
+/* Construit un modificateur livrant des octets inversés. */
+GScanTokenModifier *g_scan_reverse_modifier_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_MODIFIERS_REV_H */
diff --git a/src/analysis/scan/patterns/token-int.h b/src/analysis/scan/patterns/token-int.h
index a9667c9..294a3b1 100644
--- a/src/analysis/scan/patterns/token-int.h
+++ b/src/analysis/scan/patterns/token-int.h
@@ -44,6 +44,8 @@ struct _GStringToken
{
GSearchPattern parent; /* A laisser en premier */
+ GScanTokenNode *root; /* Motif à rechercher */
+
};
/* Encadrement d'une bribe de recherche textuelle (classe) */
@@ -57,5 +59,9 @@ struct _GStringTokenClass
};
+/* Met en place un gestionnaire de recherche de binaire. */
+bool g_string_token_create(GStringToken *, GScanTokenNode *);
+
+
#endif /* _ANALYSIS_SCAN_PATTERNS_TOKEN_INT_H */
diff --git a/src/analysis/scan/patterns/token.c b/src/analysis/scan/patterns/token.c
index d8a5cbc..cc2d87a 100644
--- a/src/analysis/scan/patterns/token.c
+++ b/src/analysis/scan/patterns/token.c
@@ -25,12 +25,18 @@
#include <assert.h>
+#include <stdio.h>
#include "token-int.h"
+#include "../../../common/cpp.h"
+#include "../../../core/logs.h"
+/* ------------------------- CIBLAGE DES SEQUENCES D'OCTETS ------------------------- */
+
+
/* Initialise la classe des bribes de recherche textuelle. */
static void g_string_token_class_init(GStringTokenClass *);
@@ -45,6 +51,22 @@ static void g_string_token_finalize(GStringToken *);
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Affiche un motif de recherche au format texte. */
+static void g_string_token_output_to_text(const GStringToken *, GScanContext *, int);
+
+/* Affiche un motif de recherche au format JSON. */
+static void g_string_token_output_to_json(const GStringToken *, GScanContext *, const sized_string_t *, unsigned int, int);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CIBLAGE DES SEQUENCES D'OCTETS */
+/* ---------------------------------------------------------------------------------- */
+
+
/* Indique le type défini pour une bribe de recherche textuelle. */
G_DEFINE_TYPE(GStringToken, g_string_token, G_TYPE_SEARCH_PATTERN);
@@ -73,9 +95,8 @@ static void g_string_token_class_init(GStringTokenClass *klass)
pattern = G_SEARCH_PATTERN_CLASS(klass);
- //pattern->prepare = (prepare_pattern_fc)g_string_token_prepare;
- //pattern->analyze = (analyze_pattern_fc)g_string_token_analyze;
- //pattern->count = (count_pattern_matchs_fc);
+ pattern->to_text = (output_pattern_to_text_fc)g_string_token_output_to_text;
+ pattern->to_json = (output_pattern_to_json_fc)g_string_token_output_to_json;
}
@@ -94,6 +115,7 @@ static void g_string_token_class_init(GStringTokenClass *klass)
static void g_string_token_init(GStringToken *token)
{
+ token->root = NULL;
}
@@ -138,6 +160,33 @@ static void g_string_token_finalize(GStringToken *token)
/******************************************************************************
* *
+* Paramètres : token = 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_string_token_create(GStringToken *token, GScanTokenNode *root)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ token->root = root;
+ g_object_ref(G_OBJECT(root));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : token = définition de la bribe à enregistrer. *
* context = contexte de l'analyse à mener. *
* backend = moteur de recherche à préchauffer. *
@@ -151,7 +200,7 @@ static void g_string_token_finalize(GStringToken *token)
* *
******************************************************************************/
-bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+bool g_string_token_enroll__old(GStringToken *token, GScanContext *context, GEngineBackend *backend, size_t maxsize)
{
bool result; /* Statut à retourner */
GStringTokenClass *class; /* Classe de l'instance */
@@ -166,6 +215,16 @@ bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBa
}
+bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBackend *backend, size_t maxsize)
+{
+ bool result; /* Statut à retourner */
+
+ result = g_scan_token_node_enroll(token->root, context, backend, maxsize);
+
+ return result;
+
+}
+
/******************************************************************************
* *
@@ -182,7 +241,7 @@ bool g_string_token_enroll(GStringToken *token, GScanContext *context, GEngineBa
* *
******************************************************************************/
-void g_string_token_check(const GStringToken *token, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+void g_string_token_check__old(const GStringToken *token, GScanContext *context, GBinContent *content, pending_matches_t *matches)
{
GStringTokenClass *class; /* Classe de l'instance */
@@ -191,3 +250,114 @@ void g_string_token_check(const GStringToken *token, GScanContext *context, GBin
class->check(token, context, content, matches);
}
+
+void g_string_token_check(const GStringToken *token, GScanContext *context, GBinContent *content, pending_matches_t *matches)
+{
+ g_scan_token_node_check(token->root, context, content, matches, NULL);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* 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_string_token_output_to_text(const GStringToken *pattern, GScanContext *context, int fd)
+{
+ const GScanMatch **matches; /* Correspondances établies */
+ size_t count; /* Quantité de cette liste */
+ size_t i; /* Boucle de parcours */
+
+ matches = g_scan_context_get_full_matches(context, G_SEARCH_PATTERN(pattern), &count);
+
+ for (i = 0; i < count; i++)
+ g_scan_match_output_to_text(matches[i], 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_string_token_output_to_json(const GStringToken *pattern, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
+{
+ unsigned int i; /* Boucle de parcours #1 */
+ const GScanMatch **matches; /* Correspondances établies */
+ size_t count; /* Quantité de cette liste */
+ char value[ULLONG_MAXLEN]; /* Impression de la position */
+ int ret; /* Bilan d'une conversion */
+ size_t k; /* Boucle de parcours #2 */
+ bool trailing; /* Virgule finale */
+
+ matches = g_scan_context_get_full_matches(context, G_SEARCH_PATTERN(pattern), &count);
+
+ /* Nombre de correspondances */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"match_count\": ", 15);
+
+ ret = snprintf(value, ULLONG_MAXLEN, "%zu", count);
+
+ if (ret > 0)
+ write(fd, value, ret);
+
+ else
+ {
+ log_simple_message(LMT_EXT_ERROR, "Error while converting value!");
+ write(fd, "null", 4);
+ }
+
+ write(fd, ",\n", 2);
+
+ /* Détail des correspondances */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"matches\": [\n", 13);
+
+ for (k = 0; k < count; k++)
+ {
+ trailing = ((k + 1) < count);
+
+ g_scan_match_output_to_json(matches[k], padding, level + 1, fd, trailing);
+
+ }
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "]\n", 2);
+
+}
diff --git a/src/analysis/scan/patterns/token.h b/src/analysis/scan/patterns/token.h
index c1cb173..879d912 100644
--- a/src/analysis/scan/patterns/token.h
+++ b/src/analysis/scan/patterns/token.h
@@ -29,6 +29,7 @@
#include "backend.h"
+#include "tokens/node.h"
#include "../matches/pending.h"
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);
diff --git a/src/analysis/scan/rule-int.h b/src/analysis/scan/rule-int.h
index cc10b08..b43cba9 100644
--- a/src/analysis/scan/rule-int.h
+++ b/src/analysis/scan/rule-int.h
@@ -40,9 +40,9 @@ struct _GScanRule
char *name; /* Désignation de la règle */
fnv64_t name_hash; /* Empreinte de la désignation */
- GSearchPattern **data_locals; /* Variables de données */
- size_t data_allocated; /* Taille allouée du tableau */
- size_t data_used; /* Nombre d'éléments présents */
+ GSearchPattern **bytes_locals; /* Variables de données */
+ size_t bytes_allocated; /* Taille allouée du tableau */
+ size_t bytes_used; /* Nombre d'éléments présents */
GScanExpression *condition; /* Condition de correspondance */
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index 6ca97ab..4727c9d 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -93,9 +93,9 @@ static void g_scan_rule_init(GScanRule *rule)
rule->name = NULL;
rule->name_hash = 0;
- rule->data_locals = NULL;
- rule->data_allocated = 0;
- rule->data_used = 0;
+ rule->bytes_locals = NULL;
+ rule->bytes_allocated = 0;
+ rule->bytes_used = 0;
rule->condition = NULL;
@@ -118,8 +118,8 @@ static void g_scan_rule_dispose(GScanRule *rule)
{
size_t i; /* Boucle de parcours */
- for (i = 0; i < rule->data_used; i++)
- g_clear_object(&rule->data_locals[i]);
+ for (i = 0; i < rule->bytes_used; i++)
+ g_clear_object(&rule->bytes_locals[i]);
g_clear_object(&rule->condition);
@@ -219,13 +219,13 @@ void g_scan_rule_add_local_variable(GScanRule *rule, GSearchPattern *pattern)
{
if (G_IS_STRING_TOKEN(pattern))
{
- if (rule->data_used == rule->data_allocated)
+ if (rule->bytes_used == rule->bytes_allocated)
{
- rule->data_allocated += PATTERN_ALLOC_SIZE;
- rule->data_locals = realloc(rule->data_locals, rule->data_allocated * sizeof(GSearchPattern *));
+ rule->bytes_allocated += PATTERN_ALLOC_SIZE;
+ rule->bytes_locals = realloc(rule->bytes_locals, rule->bytes_allocated * sizeof(GSearchPattern *));
}
- rule->data_locals[rule->data_used++] = pattern;
+ rule->bytes_locals[rule->bytes_used++] = pattern;
g_object_ref(G_OBJECT(pattern));
}
@@ -254,13 +254,13 @@ GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *targ
result = NULL;
- for (i = 0; i < rule->data_used; i++)
+ for (i = 0; i < rule->bytes_used; i++)
{
- name = g_search_pattern_get_name(rule->data_locals[i]);
+ name = g_search_pattern_get_name(rule->bytes_locals[i]);
if (strcmp(name, target) == 0)
{
- result = rule->data_locals[i];
+ result = rule->bytes_locals[i];
break;
}
@@ -327,9 +327,9 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo
maxsize = g_engine_backend_get_atom_max_size(backend);
- for (i = 0; i < rule->data_used && result; i++)
+ for (i = 0; i < rule->bytes_used && result; i++)
{
- pattern = rule->data_locals[i];
+ pattern = rule->bytes_locals[i];
result = g_string_token_enroll(G_STRING_TOKEN(pattern), context, backend, maxsize);
}
@@ -380,11 +380,11 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
/* Consolidation des résultats */
- for (i = 0; i < rule->data_used; i++)
+ for (i = 0; i < rule->bytes_used; i++)
{
init_pending_matches(&matches);
- pattern = rule->data_locals[i];
+ pattern = rule->bytes_locals[i];
g_string_token_check(G_STRING_TOKEN(pattern), context, content, &matches);
@@ -392,7 +392,9 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
{
area = &matches.areas[k];
- match = g_bytes_match_new(G_SEARCH_PATTERN(pattern), content, area->start, area->length);
+ match = g_scan_bytes_match_new(G_SEARCH_PATTERN(pattern), content,
+ area->start, area->end - area->start);
+
g_scan_context_register_full_match(context, match);
g_object_unref(G_OBJECT(match));
@@ -407,3 +409,161 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
g_object_unref(G_OBJECT(content));
}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à considérer. *
+* context = contexte de l'analyse à mener. *
+* fd = canal d'écriture. *
+* *
+* Description : Affiche une règle au format texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_rule_output_to_text(const GScanRule *rule, GScanContext *context, int fd)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < rule->bytes_used; i++)
+ g_search_pattern_output_to_text(rule->bytes_locals[i], context, fd);
+
+ if (g_scan_context_has_match_for_rule(context, rule->name))
+ {
+ write(fd, "Rule '", 6);
+ write(fd, rule->name, strlen(rule->name));
+ write(fd, "' has matched!\n", 15);
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à considérer. *
+* context = contexte de l'analyse à mener. *
+* *
+* Description : Convertit une règle en texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_rule_convert_as_text(const GScanRule *rule, GScanContext *context)
+{
+ /* TODO */
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à considérer. *
+* context = contexte de l'analyse à mener. *
+* padding = éventuel bourrage initial à placer ou NULL. *
+* level = profondeur actuelle. *
+* fd = canal d'écriture. *
+* trailing = impose une virgule finale ? *
+* *
+* Description : Affiche une règle au format JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_rule_output_to_json(const GScanRule *rule, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd, bool trailing)
+{
+ size_t i; /* Boucle de parcours */
+ bool sub_trailing; /* Virgule finale */
+
+ /* Introduction */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "{\n", 2);
+
+ /* Désignation de la règle */
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"name\": \"", 9);
+
+ write(fd, rule->name, strlen(rule->name));
+
+ write(fd, "\",\n", 3);
+
+ /* Affichage des correspondances d'octets */
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"bytes_patterns\": [\n", 20);
+
+ for (i = 0; i < rule->bytes_used; i++)
+ {
+ sub_trailing = ((i + 1) < rule->bytes_used);
+
+ g_search_pattern_output_to_json(rule->bytes_locals[i], context, padding, level + 2, fd, sub_trailing);
+
+ }
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "],\n", 3);
+
+ /* Bilan du filtrage */
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"matched\": ", 11);
+
+ if (g_scan_context_has_match_for_rule(context, rule->name))
+ write(fd, "true", 4);
+ else
+ write(fd, "false", 5);
+
+ write(fd, "\n", 1);
+
+ /* Conclusion */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ if (trailing)
+ write(fd, "},\n", 3);
+ else
+ write(fd, "}\n", 2);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à considérer. *
+* context = contexte de l'analyse à mener. *
+* *
+* Description : Convertit une règle en JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_rule_convert_as_json(const GScanRule *rule, GScanContext *context)
+{
+ /* TODO */
+
+}
diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h
index 12a435c..cb2c287 100644
--- a/src/analysis/scan/rule.h
+++ b/src/analysis/scan/rule.h
@@ -34,6 +34,7 @@
#include "expr.h"
#include "patterns/backend.h"
#include "../../common/fnv1a.h"
+#include "../../common/szstr.h"
@@ -76,6 +77,18 @@ bool g_scan_rule_setup_backend(GScanRule *, GEngineBackend *, GScanContext *);
/* Lance une analyse d'un contenu binaire selon une règle. */
void g_scan_rule_check(GScanRule *, GEngineBackend *, GScanContext *);
+/* Affiche une règle au format texte. */
+void g_scan_rule_output_to_text(const GScanRule *, GScanContext *, int);
+
+/* Convertit une règle en texte. */
+void g_scan_rule_convert_as_text(const GScanRule *, GScanContext *);
+
+/* Affiche une règle au format JSON. */
+void g_scan_rule_output_to_json(const GScanRule *, GScanContext *, const sized_string_t *, unsigned int, int, bool);
+
+/* Convertit une règle en JSON. */
+void g_scan_rule_convert_as_json(const GScanRule *, GScanContext *);
+
#endif /* _ANALYSIS_SCAN_RULE_H */
diff --git a/src/analysis/scan/scanner.c b/src/analysis/scan/scanner.c
index ce8d677..b550b1f 100644
--- a/src/analysis/scan/scanner.c
+++ b/src/analysis/scan/scanner.c
@@ -510,6 +510,8 @@ GScanContext *g_content_scanner_analyze(GContentScanner *scanner, GScanOptions *
g_engine_backend_run_scan(scanner->data_backend, result);
+ g_scan_context_mark_scan_as_done(result);
+
for (i = 0; i < scanner->rule_count; i++)
g_scan_rule_check(scanner->rules[i], scanner->data_backend, result);
@@ -518,3 +520,117 @@ GScanContext *g_content_scanner_analyze(GContentScanner *scanner, GScanOptions *
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = gestionnaire de recherche à consulter. *
+* context = contexte de l'analyse à mener. *
+* fd = canal d'écriture. *
+* *
+* Description : Affiche un gestionnaire de recherches au format texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_content_scanner_output_to_text(const GContentScanner *scanner, GScanContext *context, int fd)
+{
+ size_t i; /* Boucle de parcours */
+
+ /* Sous-traitance aux règles */
+
+ for (i = 0; i < scanner->rule_count; i++)
+ g_scan_rule_output_to_text(scanner->rules[i], context, fd);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = gestionnaire de recherche à consulter. *
+* context = contexte de l'analyse à mener. *
+* *
+* Description : Convertit un gestionnaire de recherches en texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_content_scanner_convert_as_text(const GContentScanner *scanner, GScanContext *context)
+{
+ /* TODO */
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = gestionnaire de recherche à consulter. *
+* context = contexte de l'analyse à mener. *
+* padding = éventuel bourrage initial à placer ou NULL. *
+* level = profondeur actuelle. *
+* fd = canal d'écriture. *
+* *
+* Description : Affiche un gestionnaire de recherches au format JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_content_scanner_output_to_json(const GContentScanner *scanner, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd)
+{
+ size_t i; /* Boucle de parcours */
+ bool trailing; /* Virgule finale */
+
+ /* Introduction */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "[\n", 2);
+
+ /* Sous-traitance aux règles */
+
+ for (i = 0; i < scanner->rule_count; i++)
+ {
+ trailing = ((i + 1) < scanner->rule_count);
+
+ g_scan_rule_output_to_json(scanner->rules[i], context, padding, level + 1, fd, trailing);
+
+ }
+
+ /* Conclusion */
+
+ for (i = 0; i < level; i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "]\n", 2);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : scanner = gestionnaire de recherche à consulter. *
+* context = contexte de l'analyse à mener. *
+* *
+* Description : Convertit un gestionnaire de recherches en JSON. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_content_scanner_convert_as_json(const GContentScanner *scanner, GScanContext *context)
+{
+ /* TODO */
+
+}
diff --git a/src/analysis/scan/scanner.h b/src/analysis/scan/scanner.h
index f838344..58dbe19 100644
--- a/src/analysis/scan/scanner.h
+++ b/src/analysis/scan/scanner.h
@@ -32,6 +32,7 @@
#include "expr.h"
#include "options.h"
#include "rule.h"
+#include "../../common/szstr.h"
@@ -71,6 +72,18 @@ bool g_content_scanner_add_rule(GContentScanner *, GScanRule *);
/* Définit l'expression d'une correspondance recherchée. */
GScanContext *g_content_scanner_analyze(GContentScanner *, GScanOptions *, GBinContent *);
+/* Affiche un gestionnaire de recherches au format texte. */
+void g_content_scanner_output_to_text(const GContentScanner *, GScanContext *, int);
+
+/* Convertit un gestionnaire de recherches en texte. */
+void g_content_scanner_convert_as_text(const GContentScanner *, GScanContext *);
+
+/* Affiche un gestionnaire de recherches au format JSON. */
+void g_content_scanner_output_to_json(const GContentScanner *, GScanContext *, const sized_string_t *, unsigned int, int);
+
+/* Convertit un gestionnaire de recherches en JSON. */
+void g_content_scanner_convert_as_json(const GContentScanner *, GScanContext *);
+
#endif /* _ANALYSIS_SCAN_SCANNER_H */
diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l
index f3dbc79..18594c4 100644
--- a/src/analysis/scan/tokens.l
+++ b/src/analysis/scan/tokens.l
@@ -15,47 +15,140 @@
#include <stdlib.h>
-#define read_block(tmp) \
- ({ \
- unsigned int __depth; \
- bool __is_string; \
- char *__iter; \
- \
- __depth = 1; \
- __is_string = false; \
- \
- for (__iter = temp; __depth > 0; __iter += (__depth > 0 ? 1 : 0)) \
- { \
- *__iter = input(); \
- \
- switch (*__iter) \
- { \
- case '"': \
- __is_string = !__is_string; \
- break; \
- \
- case '{': \
- if (!__is_string) __depth++; \
- break; \
- \
- case '}': \
- if (!__is_string) \
- { \
- __depth--; \
- if (__depth == 0) unput('}'); \
- } \
- break; \
- \
- } \
- \
- } \
- \
- *__iter = '\0'; \
- \
- })
+/******************************************************************************
+* *
+* Paramètres : src = liste d'octets à traiter. *
+* len = taille de cette liste. *
+* out = série d'octets bruts obtenue. [OUT] *
+* *
+* Description : Transcrit une série d'octets en en remplaçant certains. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void rost_unescape_bytes(const char *src, size_t len, sized_string_t *out)
+{
+ size_t i; /* Boucle de parcours */
+ bin_t byte; /* Octet à analyser */
+ bin_t next; /* Octet suivant */
+
+ out->len = 0;
+
+ for (i = 0; i < len; i++)
+ {
+ byte = src[i];
+
+ switch (byte)
+ {
+ case '\\':
+
+ next = src[i + 1];
+
+ switch (next)
+ {
+ case '\a':
+ out->data[out->len++] = '\\';
+ break;
+
+ case '\t':
+ out->data[out->len++] = '\t';
+ break;
+
+ case '\n':
+ out->data[out->len++] = '\n';
+ break;
+
+ case '\v':
+ out->data[out->len++] = '\v';
+ break;
+
+ case '\f':
+ out->data[out->len++] = '\f';
+ break;
+
+ case '\r':
+ out->data[out->len++] = '\r';
+ break;
+
+ case '\\':
+ out->data[out->len++] = '\\';
+ break;
+
+ case 'x':
+
+ next = src[i + 2];
+
+ switch (next)
+ {
+ case '0' ... '9':
+ out->data[out->len] = (next - '0');
+ break;
+
+ case 'A' ... 'F':
+ out->data[out->len] = 0x10 + (next - 'A');
+ break;
+
+ case 'a' ... 'f':
+ out->data[out->len] = 0x10 + (next - 'a');
+ break;
+
+ }
+
+ out->data[out->len] <<= 4;
+
+ next = src[i + 3];
+
+ switch (next)
+ {
+ case '0' ... '9':
+ out->data[out->len] |= (next - '0');
+ break;
+
+ case 'A' ... 'F':
+ out->data[out->len] |= 0x10 + (next - 'A');
+ break;
+
+ case 'a' ... 'f':
+ out->data[out->len] |= 0x10 + (next - 'a');
+ break;
+
+ }
+
+ out->len++;
+
+ i += 2;
+ break;
+
+ case '{':
+ out->data[out->len++] = '{';
+ break;
+
+ case '}':
+ out->data[out->len++] = '}';
+ break;
+
+ }
+
+ i++;
+ break;
+
+ default:
+ out->data[out->len++] = byte;
+ break;
+
+ }
+
+ }
+
+}
+
+
#define PUSH_STATE(s) yy_push_state(s, yyscanner)
#define POP_STATE yy_pop_state(yyscanner)
@@ -88,9 +181,15 @@
%x raw_block
%x strings
-%x strval
-%x strval_raw
-%x strval_hex
+%x bytes_value
+%x bytes_value_raw
+
+%x bytes_hex
+%x bytes_hex_range
+
+%x bytes_regex
+%x bytes_regex_quantifier
+%x bytes_regex_range
%x condition
%x strlit
@@ -101,6 +200,22 @@
%x comment
+
+hbyte [0-9a-fA-F]{2}
+
+reg_allowed [^^$.|/{}()\[\]*+?\\]
+reg_allowed_escaped \\^|\\$|\\\.|\\\||\\\/|\\\{|\\\}|\\\(|\\\)|\\\[|\\\]|\\\*|\\\+|\\\?|\\\\
+reg_escaped \\a|\\t|\\n|\\v|\\f|\\r
+reg_byte \\x[0-9a-fA-F]{2}
+
+regular_chars {reg_allowed}|{reg_allowed_escaped}|{reg_escaped}|{reg_byte}
+
+reg_classes \\w|\\W|\\s|\\S|\\d|\\D|\\b|\\B
+
+
+bytes_id [A-Za-z_][A-Za-z0-9_]*
+
+
%%
@@ -139,8 +254,8 @@
<condition>-(0|[1-9][0-9]*) { yylval->signed_integer = strtoll(yytext, NULL, 10); return SIGNED_INTEGER; }
<condition>-0x[0-9a-f]+ { yylval->signed_integer = strtoll(yytext, NULL, 16); return SIGNED_INTEGER; }
-<condition>(0|[1-9][0-9]*) { yylval->unsigned_integer = strtoull(yytext, NULL, 10); return UNSIGNED_INTEGER; }
-<condition>0x[0-9a-f]+ { yylval->unsigned_integer = strtoull(yytext, NULL, 16); return UNSIGNED_INTEGER; }
+<bytes_hex_range,bytes_regex_quantifier,condition>(0|[1-9][0-9]*) { yylval->unsigned_integer = strtoull(yytext, NULL, 10); return UNSIGNED_INTEGER; }
+<bytes_hex_range,bytes_regex_quantifier,condition>0x[0-9a-f]+ { yylval->unsigned_integer = strtoull(yytext, NULL, 16); return UNSIGNED_INTEGER; }
<condition>[kK][bB] { return KB; }
<condition>[mM][bB] { return MB; }
@@ -181,6 +296,195 @@
+%{ /* Définition de motif en hexadécimal */ %}
+
+ <bytes_value>"{" {
+ POP_STATE;
+ PUSH_STATE(bytes_hex);
+ }
+
+ <bytes_hex>"}" { POP_STATE; }
+
+ <bytes_hex>"[" {
+ PUSH_STATE(bytes_hex_range);
+ return HOOK_O;
+ }
+
+ <bytes_hex_range>"-" { return MINUS; }
+
+ <bytes_hex_range>"]" {
+ POP_STATE;
+ return HOOK_C;
+ }
+
+ <bytes_hex>"(" { return PAREN_O; }
+
+ <bytes_hex>")" { return PAREN_C; }
+
+ <bytes_hex>"|" { return PIPE; }
+
+ <bytes_hex>"~" { return TILDE; }
+
+ <bytes_hex>{hbyte}([ ]*{hbyte})* {
+ bool even;
+ size_t i;
+ bin_t byte;
+ bin_t value;
+
+ tmp_0->len = 0;
+
+ even = true;
+
+ for (i = 0; i < yyleng; i++)
+ {
+ byte = yytext[i];
+
+ switch (byte)
+ {
+ case ' ':
+ continue;
+ break;
+
+ case '0' ... '9':
+ value = (byte - '0');
+ break;
+
+ case 'A' ... 'F':
+ value = 0x10 + (byte - 'A');
+ break;
+
+ case 'a' ... 'f':
+ value = 0x10 + (byte - 'a');
+ break;
+
+ }
+
+ if (even)
+ {
+ tmp_0->data[tmp_0->len] = (value << 4);
+ even = false;
+ }
+
+ else
+ {
+ tmp_0->data[tmp_0->len++] |= value;
+ even = true;
+ }
+
+ }
+
+ assert(even);
+
+#ifndef NDEBUG
+ /* Pour rendre plus lisibles les impressions de débogage */
+ tmp_0->data[tmp_0->len] = '\0';
+#endif
+
+ yylval->tmp_cstring = tmp_0;
+ return HEX_BYTES;
+
+ }
+
+ <bytes_hex>[\?]{2}([ ]*[\?]{2})* {
+ unsigned long long counter;
+ size_t i;
+
+ counter = 0;
+
+ for (i = 0; i < yyleng; i++)
+ if (yytext[i] == '?')
+ counter++;
+
+ assert(counter % 2 == 0);
+
+ yylval->unsigned_integer = counter / 2;
+ return FULL_MASK;
+
+ }
+
+
+%{ /* Définition d'expressions régulières */ %}
+
+ <bytes_value>"/" {
+ POP_STATE;
+ printf(" -- regex\n");
+ PUSH_STATE(bytes_regex);
+ }
+
+ <bytes_regex>"/" { printf("exit regex\n"); POP_STATE; }
+
+ <bytes_regex>"." { return DOT; }
+
+ <bytes_regex>({regular_chars})+ {
+ rost_unescape_bytes(yytext, yyleng, tmp_0);
+
+ printf(" regular: '%s'\n", yytext);
+
+#ifndef NDEBUG
+ /* Pour rendre plus lisibles les impressions de débogage */
+ tmp_0->data[tmp_0->len] = '\0';
+#endif
+
+ yylval->tmp_cstring = tmp_0;
+ return REGEX_BYTES;
+
+ }
+
+ <bytes_regex>({reg_classes})+ {
+
+ return REGEX_CLASSES;
+
+ }
+
+%{ /* <bytes_regex>\[({regular_chars}|({regular_chars})-z|{reg_classes})+\] { */ %}
+
+
+ <bytes_regex>"[" {
+ PUSH_STATE(bytes_regex_range);
+ printf(" !! entering range\n");
+ return HOOK_O;
+ }
+
+ <bytes_regex_range>"]" {
+ POP_STATE;
+ printf(" !! exiting range\n");
+ return HOOK_C;
+ }
+
+
+
+
+<bytes_regex_range>({regular_chars}|({regular_chars}-{regular_chars})|{reg_classes})+ {
+
+ printf("range: '%s'\n", yytext);
+ return REGEX_RANGE;
+
+ }
+
+ <bytes_regex>"(" { return PAREN_O; }
+
+ <bytes_regex>")" { return PAREN_C; }
+
+ <bytes_regex>"|" { return PIPE; }
+
+ <bytes_regex>"*" { return MUL; }
+ <bytes_regex>"+" { return PLUS; }
+ <bytes_regex>"?" { return QUESTION; }
+
+ <bytes_regex>"{" {
+ PUSH_STATE(bytes_regex_quantifier);
+ return BRACKET_O;
+ }
+
+ <bytes_regex_quantifier>"," { return COMMA; }
+
+ <bytes_regex_quantifier>"}" {
+ POP_STATE;
+ return BRACKET_C;
+ }
+
+
+%{ /* Condition de correspondance */ %}
<condition>"and" { return AND; }
<condition>"or" { return OR; }
@@ -208,10 +512,17 @@
<condition>"/" { return DIV; }
<condition>"%" { return MOD; }
-<condition>"(" { return PAREN_O; }
-<condition>")" { return PAREN_C; }
-<condition>"," { return COMMA; }
+<strings,condition>"(" { return PAREN_O; }
+<strings,condition>")" { return PAREN_C; }
+<strings,condition>"," { return COMMA; }
+
+
+<condition>"[" { return HOOK_O; }
+<condition>"]" { return HOOK_C; }
+
+
<condition>"." { return DOT; }
+<strings>"|" { return PIPE; }
<condition>"none" { return NONE; }
<condition>"any" { return ANY; }
@@ -221,36 +532,51 @@
<condition>"in" { return IN; }
-<strings,condition>$[A-Za-z0-9_]* {
- yylval->sized_cstring.data = yytext + 1;
- yylval->sized_cstring.len = yyleng - 1;
- return IDENTIFIER;
- }
+ <strings,condition>${bytes_id} {
+ yylval->sized_cstring.data = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 1;
+ return BYTES_ID;
+ }
+
+ <condition>#{bytes_id} {
+ yylval->sized_cstring.data = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 1;
+ return BYTES_ID_COUNTER;
+ }
+
+ <condition>@{bytes_id} {
+ yylval->sized_cstring.data = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 1;
+ return BYTES_ID_START;
+ }
+
+ <condition>!{bytes_id} {
+ yylval->sized_cstring.data = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 1;
+ return BYTES_ID_LENGTH;
+ }
+
+ <condition>~{bytes_id} {
+ yylval->sized_cstring.data = yytext + 1;
+ yylval->sized_cstring.len = yyleng - 1;
+ return BYTES_ID_END;
+ }
-<condition>$[A-Za-z_][A-Za-z0-9_]* {
- yylval->sized_cstring.data = yytext + 1;
- yylval->sized_cstring.len = yyleng - 1;
- return BYTES_ID;
- }
-<condition>#[A-Za-z_][A-Za-z0-9_]* {
- yylval->sized_cstring.data = yytext + 1;
- yylval->sized_cstring.len = yyleng - 1;
- return BYTES_ID_COUNTER;
- }
-<condition>[A-Za-z_][A-Za-z0-9_]* {
+
+<strings,condition>[A-Za-z_][A-Za-z0-9_]* {
yylval->sized_cstring.data = yytext;
yylval->sized_cstring.len = yyleng;
return NAME;
}
-<strings>"=" { PUSH_STATE(strval); return ASSIGN; }
+<strings>"=" { PUSH_STATE(bytes_value); return ASSIGN; }
-<strval>\"[^\"\\]+\" {
+<bytes_value>\"[^\"\\]+\" {
POP_STATE;
yylval->sized_cstring.data = yytext + 1;
yylval->sized_cstring.len = yyleng - 2;
@@ -260,43 +586,28 @@
-<strval>"\"" {
+<bytes_value>"\"" {
POP_STATE;
// *built_pattern = g_bytes_pattern_new();
- PUSH_STATE(strval_raw);
- }
-<strval>"{" {
- POP_STATE;
- // *built_pattern = g_bytes_pattern_new();
- PUSH_STATE(strval_hex);
+ PUSH_STATE(bytes_value_raw);
}
-<strval_raw>"\"" { POP_STATE; /*yylval->pattern = *built_pattern*/; return MASKED_STRING; }
+<bytes_value_raw>"\"" { POP_STATE; /*yylval->pattern = *built_pattern*/; return MASKED_STRING; }
-<strval_raw>"\\\"" { }//g_bytes_pattern_append_data(*built_pattern, '"', 0xff); }
-<strval_raw>"\\t" { }//g_bytes_pattern_append_data(*built_pattern, '\t', 0xff); }
-<strval_raw>"\\r" { }//g_bytes_pattern_append_data(*built_pattern, '\r', 0xff); }
-<strval_raw>"\\n" { }//g_bytes_pattern_append_data(*built_pattern, '\n', 0xff); }
-<strval_raw>"\\\\" { }//g_bytes_pattern_append_data(*built_pattern, '\\', 0xff); }
+<bytes_value_raw>"\\\"" { }//g_bytes_pattern_append_data(*built_pattern, '"', 0xff); }
+<bytes_value_raw>"\\t" { }//g_bytes_pattern_append_data(*built_pattern, '\t', 0xff); }
+<bytes_value_raw>"\\r" { }//g_bytes_pattern_append_data(*built_pattern, '\r', 0xff); }
+<bytes_value_raw>"\\n" { }//g_bytes_pattern_append_data(*built_pattern, '\n', 0xff); }
+<bytes_value_raw>"\\\\" { }//g_bytes_pattern_append_data(*built_pattern, '\\', 0xff); }
-<strval_raw>\\x[0-9a-fA-F]{2} {
+<bytes_value_raw>\\x[0-9a-fA-F]{2} {
uint8_t __ch;
__ch = strtol(yytext + 2, NULL, 16);
+ printf("__ch: %hhx\n", __ch);
//g_bytes_pattern_append_data(*built_pattern, __ch, 0xff);
}
-<strval_raw>. { }//g_bytes_pattern_append_data(*built_pattern, *yytext, 0xff); }
-
-<strval_hex>"}" { POP_STATE; /*yylval->pattern = *built_pattern;*/ return MASKED_STRING; }
-
-<strval_hex>[0-9a-fA-F]{2} {
- uint8_t __ch;
- __ch = strtol(yytext, NULL, 16);
- //g_bytes_pattern_append_data(*built_pattern, __ch, 0xff);
- }
-
-<strval_hex>"??" { /*g_bytes_pattern_insert_space(*built_pattern, 1, 1);*/ }
-
+<bytes_value_raw>. { }//g_bytes_pattern_append_data(*built_pattern, *yytext, 0xff); }
@@ -318,7 +629,9 @@
%{ /* Actions par défaut */ %}
-<*>[ \t\n]+ { }
+<*>[ \t]+ { }
+
+<*>[\n] { static int ln = 1; if (0) printf("----------- %%< -------------- %%< ---- %d\n", ln++); }
<*>. {
char *msg;