summaryrefslogtreecommitdiff
path: root/src/analysis/scan/patterns/tokens/nodes/any.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/scan/patterns/tokens/nodes/any.c')
-rw-r--r--src/analysis/scan/patterns/tokens/nodes/any.c461
1 files changed, 387 insertions, 74 deletions
diff --git a/src/analysis/scan/patterns/tokens/nodes/any.c b/src/analysis/scan/patterns/tokens/nodes/any.c
index 6233cb4..10a01cd 100644
--- a/src/analysis/scan/patterns/tokens/nodes/any.c
+++ b/src/analysis/scan/patterns/tokens/nodes/any.c
@@ -55,10 +55,10 @@ static void g_scan_token_node_any_finalize(GScanTokenNodeAny *);
static bool g_scan_token_node_any_enroll(GScanTokenNodeAny *, GScanContext *, GEngineBackend *, size_t, size_t *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
/* Transforme les correspondances locales en trouvailles. */
-static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *, GScanContext *, GBinContent *, pending_matches_t *, node_search_offset_t *, bool, bool *);
+static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *, scan_node_check_params_t *, TokenNodeCheckFlags, bool *);
@@ -95,6 +95,7 @@ static void g_scan_token_node_any_class_init(GScanTokenNodeAnyClass *klass)
node = G_SCAN_TOKEN_NODE_CLASS(klass);
+ node->apply = (apply_scan_token_node_flags_fc)NULL;
node->visit = (visit_scan_token_node_fc)NULL;
node->enroll = (enroll_scan_token_node_fc)g_scan_token_node_any_enroll;
node->check_forward = (check_scan_token_node_fc)g_scan_token_node_any_check_forward;
@@ -117,8 +118,6 @@ static void g_scan_token_node_any_class_init(GScanTokenNodeAnyClass *klass)
static void g_scan_token_node_any_init(GScanTokenNodeAny *any)
{
- g_scan_token_node_set_flags(G_SCAN_TOKEN_NODE(any), STNF_PROD);
-
any->min = 0;
any->has_max = false;
@@ -297,13 +296,10 @@ static bool g_scan_token_node_any_enroll(GScanTokenNodeAny *node, GScanContext *
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -313,66 +309,250 @@ static bool g_scan_token_node_any_enroll(GScanTokenNodeAny *node, GScanContext *
* *
******************************************************************************/
-static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
- bool initialized; /* Initialisation du suivi ? */
+ ScanTokenNodeFlags flags; /* Particularités du noeud */
bool forced; /* Inclusion dans un scan ? */
phys_t size; /* Quantité d'octets considérés*/
- const phys_t *datasize; /* Taille max. à communiquer */
+ phys_t match_size; /* Taille de correspondance */
+ phys_t i; /* Boucle de parcours #1 */
+ match_area_t *space; /* Nouvelle zone à intégrer */
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
+ phys_t after; /* Espace disposible après */
+ phys_t min_end; /* Fin la plus proche possible */
+ phys_t max_end; /* Fin la plus éloignée trouvée*/
+ bool updated; /* Existence de correspondance */
+ size_t rcount; /* Quantité de bornes présentes*/
+ const node_offset_range_t *ranges; /* Bornes d'espace à parcourir */
+ size_t r; /* Boucle de parcours #2 */
+ phys_t updated_edge; /* Nouvelle bordure de motif */
+ match_area_t *new_area; /* Copie de correspondance */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
if (*skip)
return;
+ flags = g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node));
- // $a = { [1-3] 6f }
- // pas d'initialisation, construction de résultats avec une taille nulle
+ forced = (flags & STNF_MAIN);
+ assert((!params->initialized && forced) || (params->initialized & !forced));
+
+ /**
+ * La situation forcée correspond au cas particulier d'une définition
+ * complètement abstraite : ??, ?? ??, etc.
+ */
+ if (forced)
+ {
+ size = params->content_end - params->content_start;
+ if (node->has_max && 0 /* greedy ? */)
+ {
+ match_size = node->max;
- initialized = are_pending_matches_initialized(matches);
+ if (match_size > size)
+ match_size = node->min;
- forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN);
+ }
+ else
+ match_size = node->min;
+
+ /**
+ * Si le contenu binaire est trop petit pour contenir au moins un enregistrement,
+ * aucune correspondance n'est enregistrée. Comme le noeud est le principale, ie.
+ * seul et unique, l'analyse s'arrête ensuite d'elle même.
+ *
+ * Si le contenu binaire est suffisamment large, des espaces sont créés et l'analyse
+ * se termine ensuite. La conservation des espaces n'est donc pas utile, ni réalisée.
+ */
- size = matches->content_end - matches->content_start;
+ if (match_size <= size)
+ {
+ size -= match_size;
- datasize = (not ? &size : NULL);
+ assert(cflags & TNCF_UPDATE_IN_PLACE);
- if (forced)
- {
- assert(!initialized);
+ for (i = 0; i < size; i++)
+ {
+ space = g_umem_slice_alloc(params->allocator);
- if (node->min > size)
- /* TODO set abort in matches */;
+ space->start = params->content_start + i;
+ space->end = space->start + match_size;
- else
- add_range_to_node_search_offset(offset,
- matches->content_start,
- matches->content_end - matches->content_start,
- datasize);
+ add_tail_match_area(space, &params->main_areas);
+ params->main_count++;
+
+ }
+
+ }
}
+
+ /**
+ * Situation usuelle : des espaces séparent deux noeuds.
+ */
else
{
- assert(initialized);
+ assert(params->initialized);
+
+ /**
+ * Les espaces existants sont à compléter. La présence de tels espaces
+ * restant à traiter peut provenir d'un aiguillage imposé par un motif
+ * tel que :
+ *
+ * ( aa ?? ?? | bb cc dd ) [0-5] ee ee
+ *
+ * Deux espaces sont à considérer avant de rechercher des octets ee :
+ * [2-7] et [0-5].
+ *
+ * Note : ces espaces peuvent être disjoints.
+ *
+ * Si aucun espace n'est en place, un est créé.
+ */
+ extend_node_search_offset(&params->offset, node->min, node->max, node->has_max);
- // TODO : compléter les intervales éventuels déjà en place
+ /**
+ * Si un décalage enregistré ne peut être consommé par un noeud, les
+ * résultats sont étendus ici à minima ou maxima.
+ */
+ if (flags & STNF_LAST)
+ {
+ assert(offsets_exist(&params->offset));
- /*
- printf("[i] create hole: %llx <-> %llx\n",
- (unsigned long long)node->min,
- (unsigned long long)node->max);
- */
+ if (0x1) printf(" LIST : %p (sz = %zu)\n", params->main_areas, params->main_count);
+ for_each_match_area_safe(area, &params->main_areas, next)
+ {
+ assert(area->end <= params->content_end);
- if (node->has_max)
- add_range_to_node_search_offset(offset, node->min, node->max, datasize);
- else
- add_range_to_node_search_offset(offset, node->min, matches->content_end - node->min, datasize);
+ after = params->content_end - area->end;
+
+ if (0x1) printf("---------- iter @ %u -> %u\n", (unsigned int)area->start, (unsigned int)area->end);
- // TODO : si dernier, virer les correspondances qui n'ont plus l'espace de fin requis
- // -> au niveau du noeud, en fonction du flag _LAST
+ min_end = params->content_end;
+ max_end = params->content_start;
+
+ updated = false;
+
+ ranges = get_node_search_offset_ranges_2(&params->offset, &rcount);
+
+ for (r = 0; r < rcount; r++)
+ {
+ if (ranges[r].min > after)
+ continue;
+
+ updated_edge = area->end + ranges[r].min;
+
+ if (updated_edge < min_end)
+ min_end = updated_edge;
+
+ if (ranges[r].has_max)
+ {
+ if (ranges[r].max > after)
+ updated_edge = params->content_end;
+ else
+ updated_edge = area->end + ranges[r].max;
+
+ if (updated_edge > max_end)
+ max_end = updated_edge;
+
+ }
+
+ updated = true;
+
+ }
+
+ if (updated)
+ {
+ /**
+ * Si seuls les rejets sont d'intérêt, les correspondances établies
+ * ne se voient pas mises à jours ni retirées.
+ */
+
+ if ((cflags & TNCF_KEEP_DISCARDED) == 0)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ area->end = (1 /* greedy */ ? min_end : max_end);
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->end = (1 /* greedy */ ? min_end : max_end);
+
+ add_tail_match_area(new_area, &params->created_areas);
+ params->created_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ else
+ {
+ /**
+ * Si la liste principale doit être mise à jour...
+ */
+
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ del_match_area(area, &params->main_areas);
+ assert(params->main_count > 0);
+ params->main_count--;
+ }
+
+ /**
+ * Au cas où le rejet est d'intérêt, l'absence de correspondance
+ * est conservée dans une liste dédiée.
+ */
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ add_tail_match_area(area, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->end = (1 /* greedy */ ? min_end : max_end);
+
+ add_tail_match_area(new_area, &params->kept_areas);
+ params->kept_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ }
+
+ disable_all_ranges_in_node_search_offset(&params->offset);
+
+ }
}
@@ -381,13 +561,10 @@ static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, G
/******************************************************************************
* *
-* Paramètres : node = définition de la bribe à manipuler. *
-* context = contexte de l'analyse à mener. *
-* content = accès au contenu brut pour vérifications (optim.) *
-* matches = suivi des correspondances à consolider. *
-* offset = tolérance dans les positions à appliquer. *
-* not = indique si les résultats doivent être inversés. *
-* skip = détermine si l'analyse est différée. [OUT] *
+* Paramètres : node = définition de la bribe à manipuler. *
+* params = accès direct aux éléments utiles aux validations. *
+* cflags = altérations de traitement à respecter. *
+* skip = détermine si l'analyse est différée. [OUT] *
* *
* Description : Transforme les correspondances locales en trouvailles. *
* *
@@ -397,55 +574,191 @@ static void g_scan_token_node_any_check_forward(const GScanTokenNodeAny *node, G
* *
******************************************************************************/
-static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *node, GScanContext *context, GBinContent *content, pending_matches_t *matches, node_search_offset_t *offset, bool not, bool *skip)
+static void g_scan_token_node_any_check_backward(const GScanTokenNodeAny *node, scan_node_check_params_t *params, TokenNodeCheckFlags cflags, bool *skip)
{
+ ScanTokenNodeFlags flags; /* Particularités du noeud */
#ifndef NDEBUG
bool forced; /* Inclusion dans un scan ? */
#endif
- phys_t size; /* Quantité d'octets considérés*/
- const phys_t *datasize; /* Taille max. à communiquer */
+ match_area_t *area; /* Correspondance à valider */
+ match_area_t *next; /* Correspondance suivante */
+ phys_t before; /* Espace disposible avant */
+ phys_t min_start; /* Début le plus proche trouvé */
+ phys_t max_start; /* Début le plus distant trouvé*/
+ bool updated; /* Existence de correspondance */
+ size_t rcount; /* Quantité de bornes présentes*/
+ const node_offset_range_t *ranges; /* Bornes d'espace à parcourir */
+ size_t r; /* Boucle de parcours */
+ phys_t updated_edge; /* Nouvelle bordure de motif */
+ match_area_t *new_area; /* Copie de correspondance */
+
+ if (0x1) printf("=================== CHECK :: %s (skip? %d)\n", __FUNCTION__, *skip);
if (*skip)
return;
/**
* En lecture à rebourd, au moins un noeud a été solicité pour analyse (lors
- * du sens de lecteur normal). Donc l'initialisation a déjà dû avoir lieu.
+ * du sens de lecture normal). Donc l'initialisation a déjà dû avoir lieu.
*/
- assert(are_pending_matches_initialized(matches));
+
+ assert(params->initialized);
+
+ flags = g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node));
/**
* Si les recherches associées au noeud ont été forcées, alors les traitements
* liés ont déjà été effectués, et l'appel de cette fonction aurait dû être sauté.
*/
#ifndef NDEBUG
- forced = (g_scan_token_node_get_flags(G_SCAN_TOKEN_NODE(node)) & STNF_MAIN);
+ forced = (flags & STNF_MAIN);
assert(!forced);
#endif
- size = matches->content_end - matches->content_start;
+ /**
+ * Les considérations pour l'extension des espaces en place sont identiques
+ * à celles formulées dans la fonction g_scan_token_node_any_check_forward().
+ */
- if (node->min > size)
- /* TODO set abort in matches */;
+ extend_node_search_offset(&params->offset, node->min, node->max, node->has_max);
- else
+ /**
+ * Si un décalage enregistré ne peut être consommé par un noeud, les
+ * résultats sont étendus ici à minima ou maxima.
+ */
+
+ if (flags & STNF_FIRST)
{
- datasize = (not ? &size : NULL);
+ assert(offsets_exist(&params->offset));
- /**
- * Une tolérance basée sur des espaces (et non des positions) est déterminée
- * ici.
- *
- * Charge au prochain noeud de traitement de filtrer les résultats courants
- * avec, voire à la fonction _g_scan_token_node_check_backward() de
- * réaliser une synthèse finale si le noeud courant est le dernier d'une
- * lignée.
- */
+ if (0x1) printf(" LIST : %p (sz = %zu)\n", params->main_areas, params->main_count);
- if (node->has_max)
- add_range_to_node_search_offset(offset, node->min, node->max, datasize);
- else
- add_range_to_node_search_offset(offset, node->min, matches->content_end - node->min, datasize);
+ for_each_match_area_safe(area, &params->main_areas, next)
+ {
+ assert(params->content_start <= area->start);
+
+ before = area->start - params->content_start;
+
+ if (0x1) printf("---------- iter @ %u -> %u\n", (unsigned int)area->start, (unsigned int)area->end);
+
+ min_start = params->content_start;
+ max_start = params->content_end;
+
+ updated = false;
+
+ ranges = get_node_search_offset_ranges_2(&params->offset, &rcount);
+
+ for (r = 0; r < rcount; r++)
+ {
+ if (ranges[r].min > before)
+ continue;
+
+ updated_edge = area->start - ranges[r].min;
+
+ if (updated_edge > min_start)
+ min_start = updated_edge;
+
+ if (ranges[r].has_max)
+ {
+ if (ranges[r].max > before)
+ updated_edge = params->content_start;
+ else
+ updated_edge = area->start - ranges[r].max;
+
+ if (updated_edge < max_start)
+ max_start = updated_edge;
+
+ }
+
+ updated = true;
+
+ }
+
+ if (updated)
+ {
+ /**
+ * Si seuls les rejets sont d'intérêt, les correspondances établies
+ * ne se voient pas mises à jours ni retirées.
+ */
+
+ if ((cflags & TNCF_KEEP_DISCARDED) == 0)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ area->start = (1 /* greedy */ ? min_start : max_start);
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->start = (1 /* greedy */ ? min_start : max_start);
+
+ add_tail_match_area(new_area, &params->created_areas);
+ params->created_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ else
+ {
+ /**
+ * Si la liste principale doit être mise à jour...
+ */
+
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ del_match_area(area, &params->main_areas);
+ assert(params->main_count > 0);
+ params->main_count--;
+ }
+
+ /**
+ * Au cas où le rejet est d'intérêt, l'absence de correspondance
+ * est conservée dans une liste dédiée.
+ */
+
+ if (cflags & TNCF_KEEP_DISCARDED)
+ {
+ if (cflags & TNCF_UPDATE_IN_PLACE)
+ {
+ add_tail_match_area(area, &params->kept_areas);
+ params->kept_count++;
+ }
+
+ else if (cflags & TNCF_CREATE_NEW)
+ {
+ new_area = g_umem_slice_alloc(params->allocator);
+
+ *new_area = *area;
+
+ new_area->start = (1 /* greedy */ ? min_start : max_start);
+
+ add_tail_match_area(new_area, &params->kept_areas);
+ params->kept_count++;
+
+ }
+
+#ifndef NDEBUG
+ else
+ assert(false);
+#endif
+
+ }
+
+ }
+
+ }
+
+ disable_all_ranges_in_node_search_offset(&params->offset);
}