summaryrefslogtreecommitdiff
path: root/src/analysis/scan/rule.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/scan/rule.c')
-rw-r--r--src/analysis/scan/rule.c352
1 files changed, 292 insertions, 60 deletions
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index 68222dd..d3acbc2 100644
--- a/src/analysis/scan/rule.c
+++ b/src/analysis/scan/rule.c
@@ -102,6 +102,9 @@ static void g_scan_rule_init(GScanRule *rule)
rule->name = NULL;
rule->name_hash = 0;
+ rule->tags = NULL;
+ rule->tags_count = 0;
+
rule->bytes_locals = NULL;
rule->bytes_allocated = 0;
rule->bytes_used = 0;
@@ -151,9 +154,20 @@ static void g_scan_rule_dispose(GScanRule *rule)
static void g_scan_rule_finalize(GScanRule *rule)
{
+ size_t i; /* Boucle de parcours */
+
if (rule->name != NULL)
free(rule->name);
+ for (i = 0; i < rule->tags_count; i++)
+ free(rule->tags[i]);
+
+ if (rule->tags != NULL)
+ free(rule->tags);
+
+ if (rule->bytes_locals != NULL)
+ free(rule->bytes_locals);
+
G_OBJECT_CLASS(g_scan_rule_parent_class)->finalize(G_OBJECT(rule));
}
@@ -270,6 +284,54 @@ const char *g_scan_rule_get_name(const GScanRule *rule, fnv64_t *hash)
/******************************************************************************
* *
+* Paramètres : rule = règle de détection à compléter. *
+* tag = étiquette à associer à la règle. *
+* *
+* Description : Lie une règle à une nouvelle étiquette. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_rule_add_tag(GScanRule *rule, const char *tag)
+{
+ rule->tags = realloc(rule->tags, ++rule->tags_count * sizeof(char *));
+
+ rule->tags[rule->tags_count - 1] = strdup(tag);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à consulter. *
+* count = quantité d'éléments retournés. [OUT] *
+* *
+* Description : Indique les éventuelles étiquettes associées à une règle. *
+* *
+* Retour : Liste d'étiquettes associées à la règle consultée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char * const *g_scan_rule_list_tags(const GScanRule *rule, size_t *count)
+{
+ const char * const *result; /* Liste à retourner */
+
+ result = rule->tags;
+
+ *count = rule->tags_count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : rule = règle de détection à compléter. *
* pattern = nouveau motif de détection. *
* *
@@ -283,7 +345,7 @@ const char *g_scan_rule_get_name(const GScanRule *rule, fnv64_t *hash)
void g_scan_rule_add_local_variable(GScanRule *rule, GSearchPattern *pattern)
{
- if (G_IS_STRING_TOKEN(pattern))
+ if (G_IS_BYTES_TOKEN(pattern))
{
if (rule->bytes_used == rule->bytes_allocated)
{
@@ -308,13 +370,13 @@ void g_scan_rule_add_local_variable(GScanRule *rule, GSearchPattern *pattern)
* *
* Retour : Motif de détection retrouvé ou NULL en cas d'échec. *
* *
-* Remarques : - *
+* Remarques : La propriétée de l'instance renvoyée est partagée ! *
* *
******************************************************************************/
-GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *target)
+const GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *target)
{
- GSearchPattern *result; /* Variable à retourner */
+ const GSearchPattern *result; /* Variable à retourner */
size_t i; /* Boucle de parcours */
const char *name; /* Désignation d'un motif */
@@ -332,9 +394,6 @@ GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *targ
}
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
return result;
}
@@ -350,13 +409,16 @@ GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *targ
* *
* Retour : Motifs de détection retrouvés ou NULL en cas d'échec. *
* *
-* Remarques : - *
+* Remarques : La propriétée des instances renvoyées est partagée ! *
* *
******************************************************************************/
-GSearchPattern **g_scan_rule_get_local_variables(GScanRule *rule, const char *target, size_t *count)
+const GSearchPattern **g_scan_rule_get_local_variables(GScanRule *rule, const char *target, size_t *count)
{
- GSearchPattern **result; /* Variables à retourner */
+ const GSearchPattern **result; /* Variables à retourner */
+ size_t target_len; /* Nbre de caractères à évaluer*/
+ size_t len_without_star; /* Taille sans masque */
+ bool need_regex; /* Traitement complexe requis */
size_t i; /* Boucle de parcours */
char *regex; /* Définition complète */
regex_t preg; /* Expression compilée */
@@ -371,20 +433,68 @@ GSearchPattern **g_scan_rule_get_local_variables(GScanRule *rule, const char *ta
if (target == NULL)
{
+ need_all_of_them:
+
*count = rule->bytes_used;
result = malloc(*count * sizeof(GSearchPattern *));
+ memcpy(result, rule->bytes_locals, *count);
+
+ }
+
+ /* Second cas de figure : identification au cas par cas */
+
+ else
+ {
+ target_len = strlen(target);
+
+ len_without_star = 0;
+
+ need_regex = false;
+
+ for (i = 0; i < target_len; i++)
+ if (target[i] == '*')
+ break;
+ else
+ len_without_star++;
+
+ for (i++; i < target_len; i++)
+ if (target[i] != '*')
+ {
+ need_regex = true;
+ goto try_harder;
+ }
+
+ if (len_without_star == 0)
+ goto need_all_of_them;
+
+ result = malloc(rule->bytes_used * sizeof(GSearchPattern *));
+
for (i = 0; i < rule->bytes_used; i++)
{
- result[i] = rule->bytes_locals[i];
- g_object_ref(G_OBJECT(result[i]));
+ name = g_search_pattern_get_name(rule->bytes_locals[i]);
+
+ if (strncmp(name, target, len_without_star) == 0)
+ {
+ result[*count] = rule->bytes_locals[i];
+ (*count)++;
+ }
+
+ }
+
+ if (*count == 0)
+ {
+ free(result);
+ result = NULL;
}
}
- /* Second cas de figure : une expression régulière est vraisemblablement de mise */
+ try_harder:
- else
+ /* Dernier cas de figure : une expression régulière est vraisemblablement de mise */
+
+ if (need_regex)
{
regex = strdup(target);
@@ -411,10 +521,7 @@ GSearchPattern **g_scan_rule_get_local_variables(GScanRule *rule, const char *ta
if (ret != REG_NOMATCH)
{
result[*count] = rule->bytes_locals[i];
- g_object_ref(G_OBJECT(result[*count]));
-
(*count)++;
-
}
}
@@ -479,7 +586,6 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo
bool result; /* Statut à retourner */
size_t maxsize; /* Taille maximale des atomes */
GSearchPattern *pattern; /* Motif à intégrer */
- GScanOptions *options; /* Options d'analyse */
size_t i; /* Boucle de parcours */
/* Suivi des conditions de correspondance */
@@ -494,22 +600,42 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo
for (i = 0; i < rule->bytes_used && result; i++)
{
pattern = rule->bytes_locals[i];
- result = g_string_token_enroll(G_STRING_TOKEN(pattern), context, backend, maxsize);
+ result = g_bytes_token_enroll(G_BYTES_TOKEN(pattern), backend, maxsize);
}
- g_engine_backend_warm_up(backend);
+ exit:
- /* Affichage éventuel de statistiques */
+ return result;
- options = g_scan_context_get_options(context);
+}
- if (g_scan_options_get_print_stats(options))
- g_engine_backend_output_stats(backend);
+/******************************************************************************
+* *
+* Paramètres : rule = règle de détection à considérer. *
+* backend = moteur d'analyse pour données brutes. *
+* *
+* Description : Récupère les identifiants finaux pour les motifs recherchés. *
+* *
+* Retour : Bilan de l'opération à renvoyer. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- g_object_unref(G_OBJECT(options));
+bool g_scan_rule_define_pattern_ids(GScanRule *rule, GEngineBackend *backend)
+{
+ bool result; /* Statut à retourner */
+ size_t i; /* Boucle de parcours */
+ GSearchPattern *pattern; /* Motif à intégrer */
- exit:
+ result = true;
+
+ for (i = 0; i < rule->bytes_used && result; i++)
+ {
+ pattern = rule->bytes_locals[i];
+ result = g_bytes_token_build_id(G_BYTES_TOKEN(pattern), backend);
+ }
return result;
@@ -532,50 +658,43 @@ bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanCo
void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *context)
{
- GBinContent *content; /* Contenu à manipuler */
+ scan_node_check_params_t params; /* Rassemblement de paramètres */
vmpa2t start; /* Point de début du contenu */
vmpa2t end; /* Point de fin du contenu */
- pending_matches_t matches; /* Suivi de correspondances */
- size_t i; /* Boucle de parcours #1 */
+ size_t i; /* Boucle de parcours */
GSearchPattern *pattern; /* Motif à intégrer */
- size_t k; /* Boucle de parcours #2 */
- match_area_t *area; /* Zone à initialiser */
- GScanMatch *match; /* Correspondance à mémoriser */
+ GScanMatches *matches; /* Correspondances établies */
- content = g_scan_context_get_content(context);
+ /* Définition d'un contexte */
+
+ params.context = context;
+ params.content = g_scan_context_get_content(context);
+ params.allocator = g_umem_slice_new(sizeof(match_area_t));
+
+ g_binary_content_compute_start_pos(params.content, &start);
+ g_binary_content_compute_end_pos(params.content, &end);
- g_binary_content_compute_start_pos(content, &start);
- g_binary_content_compute_end_pos(content, &end);
+ params.content_start = start.physical;
+ params.content_end = end.physical;
- /* Consolidation des résultats */
+ /* Vérifications */
for (i = 0; i < rule->bytes_used; i++)
{
- init_pending_matches(&matches, &start.physical, &end.physical);
-
pattern = rule->bytes_locals[i];
- g_string_token_check(G_STRING_TOKEN(pattern), context, content, &matches);
-
- for (k = 0; k < matches.used; k++)
- {
- area = &matches.areas[k];
+ matches = g_scan_bytes_matches_new();
- match = g_scan_bytes_match_new(G_SEARCH_PATTERN(pattern), content,
- area->start, area->end - area->start);
+ g_bytes_token_check(G_BYTES_TOKEN(pattern), G_SCAN_BYTES_MATCHES(matches), &params);
- g_scan_context_register_full_match(context, match);
- g_object_unref(G_OBJECT(match));
-
- }
+ g_scan_context_register_full_matches(context, pattern, matches);
- exit_pending_matches(&matches);
+ g_object_unref(G_OBJECT(matches));
}
- /* Sortie propre */
-
- g_object_unref(G_OBJECT(content));
+ g_object_unref(G_OBJECT(params.content));
+ //g_object_unref(G_OBJECT(params.allocator));
}
@@ -597,19 +716,74 @@ void g_scan_rule_check(GScanRule *rule, GEngineBackend *backend, GScanContext *c
void g_scan_rule_output_to_text(const GScanRule *rule, GScanContext *context, bool full, int fd)
{
+ GScanOptions *options; /* Options de l'utilisateur */
+ bool selected; /* Affichage attendu ? */
size_t i; /* Boucle de parcours */
+ GBinContent *content; /* Contenu binaire scanné */
+ char *desc; /* Description de ce contenu */
- if (full)
- for (i = 0; i < rule->bytes_used; i++)
- g_search_pattern_output_to_text(rule->bytes_locals[i], context, fd);
+ /**
+ * Si la règle n'a pas fait mouche, rien n'est imprimé.
+ */
+ if (!g_scan_context_has_match_for_rule(context, rule->name))
+ return;
- if (g_scan_context_has_match_for_rule(context, rule->name))
+ options = g_scan_context_get_options(context);
+
+ selected = g_scan_options_has_tag_as_selected(options, NULL);
+
+ /**
+ * Si la règle comporte des étiquettes et que l'utilisateur en a spécifié
+ * également.
+ */
+ if (rule->tags_count > 0 && !selected)
+ {
+ for (i = 0; i < rule->tags_count && !selected; i++)
+ selected = g_scan_options_has_tag_as_selected(options, rule->tags[i]);
+ }
+
+ if (selected)
{
- write(fd, "Rule '", 6);
write(fd, rule->name, strlen(rule->name));
- write(fd, "' has matched!\n", 15);
+
+ if (g_scan_options_get_print_tags(options))
+ {
+ write(fd, " [", 2);
+
+ for (i = 0; i < rule->tags_count; i++)
+ {
+ if (i > 0)
+ write(fd, ",", 1);
+
+ write(fd, rule->tags[i], strlen(rule->tags[i]));
+
+ }
+
+ write(fd, "]", 1);
+
+ }
+
+ write(fd, " ", 1);
+
+ content = g_scan_context_get_content(context);
+
+ desc = g_binary_content_describe(content, true);
+
+ write(fd, desc, strlen(desc));
+ write(fd, "\n", 1);
+
+ free(desc);
+
+ g_object_unref(G_OBJECT(content));
+
+ if (full)
+ for (i = 0; i < rule->bytes_used; i++)
+ g_search_pattern_output_to_text(rule->bytes_locals[i], context, fd);
+
}
+ g_object_unref(G_OBJECT(options));
+
}
@@ -706,8 +880,11 @@ char *g_scan_rule_convert_as_text(const GScanRule *rule, GScanContext *context)
void g_scan_rule_output_to_json(const GScanRule *rule, GScanContext *context, const sized_string_t *padding, unsigned int level, int fd, bool tail)
{
- size_t i; /* Boucle de parcours */
+ size_t i; /* Boucle de parcours #1 */
bool sub_tail; /* Saut de la virgule finale ? */
+ size_t k; /* Boucle de parcours #2 */
+ GBinContent *content; /* Contenu binaire scanné */
+ char *desc; /* Description de ce contenu */
/* Introduction */
@@ -727,6 +904,61 @@ void g_scan_rule_output_to_json(const GScanRule *rule, GScanContext *context, co
write(fd, "\",\n", 3);
+ /* Etiquettes ? */
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"tags\": [", 9);
+
+ if (rule->tags_count > 0)
+ {
+ write(fd, "\n", 1);
+
+ for (k = 0; k < rule->tags_count; k++)
+ {
+ for (i = 0; i < (level + 2); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"", 1);
+
+ write(fd, rule->tags[k], strlen(rule->tags[k]));
+
+ write(fd, "\"", 1);
+
+ if ((k + 1) < rule->tags_count)
+ write(fd, ",", 1);
+
+ write(fd, "\n", 1);
+
+ }
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ }
+
+ write(fd, "],\n", 3);
+
+ /* Cible du scan */
+
+ for (i = 0; i < (level + 1); i++)
+ write(fd, padding->data, padding->len);
+
+ write(fd, "\"target\": \"", 11);
+
+ content = g_scan_context_get_content(context);
+
+ desc = g_binary_content_describe(content, true);
+
+ write(fd, desc, strlen(desc));
+
+ free(desc);
+
+ g_object_unref(G_OBJECT(content));
+
+ write(fd, "\",\n", 3);
+
/* Affichage des correspondances d'octets */
for (i = 0; i < (level + 1); i++)