summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2023-09-25 23:50:02 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2023-09-25 23:50:02 (GMT)
commit2f740fc8aa705df046a6d32fc98e2787df0e47e1 (patch)
tree5c348351ca39312cb5a54a5c88e95859fe0b7579 /src
parent4c13ca820e4fa01ca62ad66c0665ebbee150f87c (diff)
Handle tags linked to ROST rules.
Diffstat (limited to 'src')
-rw-r--r--src/analysis/scan/grammar.y23
-rw-r--r--src/analysis/scan/options-int.h3
-rw-r--r--src/analysis/scan/options.c76
-rw-r--r--src/analysis/scan/options.h6
-rw-r--r--src/analysis/scan/rule-int.h3
-rw-r--r--src/analysis/scan/rule.c95
-rw-r--r--src/analysis/scan/rule.h6
-rw-r--r--src/analysis/scan/tokens.l6
-rw-r--r--src/rost.c15
9 files changed, 215 insertions, 18 deletions
diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y
index e1f0e9e..741b394 100644
--- a/src/analysis/scan/grammar.y
+++ b/src/analysis/scan/grammar.y
@@ -116,7 +116,7 @@ YY_DECL;
%token INCLUDE "include"
%token RAW_RULE
-%token RULE_NAME
+%token RULE_IDENTIFIER
%token META "meta"
%token BYTES "bytes"
@@ -216,7 +216,7 @@ YY_DECL;
%token IN "in"
-%type <sized_cstring> RULE_NAME
+%type <sized_cstring> RULE_IDENTIFIER
%type <sized_cstring> INFO_KEY
@@ -346,12 +346,12 @@ YY_DECL;
* Définition de règle.
*/
- rule : rule_flags RAW_RULE RULE_NAME
+ rule : rule_flags RAW_RULE RULE_IDENTIFIER
{
*built_rule = g_scan_rule_new($1, $3.data);
$<rule>$ = *built_rule;
}
- BRACE_IN meta bytes condition BRACE_OUT
+ tags BRACE_IN meta bytes condition BRACE_OUT
{
$$ = $<rule>4;
}
@@ -379,6 +379,21 @@ YY_DECL;
;
+ tags : /* empty */
+ | ":" tag_list
+ ;
+
+ tag_list : RULE_IDENTIFIER
+ {
+ g_scan_rule_add_tag(*built_rule, $1.data);
+ }
+ | tag_list RULE_IDENTIFIER
+ {
+ g_scan_rule_add_tag(*built_rule, $2.data);
+ }
+ ;
+
+
/**
* Section "meta:" d'une définition de règle.
*/
diff --git a/src/analysis/scan/options-int.h b/src/analysis/scan/options-int.h
index e8ae428..9e1c7d8 100644
--- a/src/analysis/scan/options-int.h
+++ b/src/analysis/scan/options-int.h
@@ -42,6 +42,9 @@ struct _GScanOptions
bool print_strings; /* Affichage de correspondances*/
bool print_stats; /* Affichage de statistiques ? */
+ char **selected_tags; /* Etiquettes sélectionnées */
+ size_t selected_count; /* Nombre de ces étiquettes */
+
};
/* Rassemblement d'options d'analyses (classe) */
diff --git a/src/analysis/scan/options.c b/src/analysis/scan/options.c
index 637c821..0b50495 100644
--- a/src/analysis/scan/options.c
+++ b/src/analysis/scan/options.c
@@ -24,6 +24,10 @@
#include "options.h"
+#include <malloc.h>
+#include <string.h>
+
+
#include "options-int.h"
@@ -92,6 +96,9 @@ static void g_scan_options_init(GScanOptions *options)
options->print_strings = false;
options->print_stats = false;
+ options->selected_tags = NULL;
+ options->selected_count = 0;
+
}
@@ -128,6 +135,14 @@ static void g_scan_options_dispose(GScanOptions *options)
static void g_scan_options_finalize(GScanOptions *options)
{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < options->selected_count; i++)
+ free(options->selected_tags[i]);
+
+ if (options->selected_tags != NULL)
+ free(options->selected_tags);
+
G_OBJECT_CLASS(g_scan_options_parent_class)->finalize(G_OBJECT(options));
}
@@ -369,3 +384,64 @@ void g_scan_options_set_print_stats(GScanOptions *options, bool state)
options->print_stats = state;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à compléter. *
+* tag = étiquette de règle à sélectionner. *
+* *
+* Description : Inscrit une étiquette comme sélection de règles à afficher. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_scan_options_select_tag(GScanOptions *options, const char *tag)
+{
+ options->selected_tags = realloc(options->selected_tags, ++options->selected_count * sizeof(char *));
+
+ options->selected_tags[options->selected_count - 1] = strdup(tag);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : options = ensemble d'options d'analyses à compléter. *
+* tag = étiquette de règle à auditionner. *
+* *
+* Description : Détermine si une étiquette donnée conduit à un affichage. *
+* *
+* Retour : true si une règle portant l'étiquette doit être affichée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_scan_options_has_tag_as_selected(const GScanOptions *options, const char *tag)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ if (tag == NULL)
+ result = (options->selected_count == 0);
+
+ else
+ {
+ result = false;
+
+ for (i = 0; i < options->selected_count; i++)
+ if (strcmp(options->selected_tags[i], tag) == 0)
+ {
+ result = true;
+ break;
+ }
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/scan/options.h b/src/analysis/scan/options.h
index c6db838..fc1b7d3 100644
--- a/src/analysis/scan/options.h
+++ b/src/analysis/scan/options.h
@@ -81,6 +81,12 @@ bool g_scan_options_get_print_stats(const GScanOptions *);
/* Mémorise un besoin de statistiques en fin de compilation. */
void g_scan_options_set_print_stats(GScanOptions *, bool);
+/* Inscrit une étiquette comme sélection de règles à afficher. */
+void g_scan_options_select_tag(GScanOptions *, const char *);
+
+/* Détermine si une étiquette donnée conduit à un affichage. */
+bool g_scan_options_has_tag_as_selected(const GScanOptions *, const char *);
+
#endif /* _ANALYSIS_SCAN_OPTIONS_H */
diff --git a/src/analysis/scan/rule-int.h b/src/analysis/scan/rule-int.h
index 1ca2b7f..17d4dc2 100644
--- a/src/analysis/scan/rule-int.h
+++ b/src/analysis/scan/rule-int.h
@@ -42,6 +42,9 @@ struct _GScanRule
char *name; /* Désignation de la règle */
fnv64_t name_hash; /* Empreinte de la désignation */
+ char **tags; /* Etiquettes associées */
+ char tags_count; /* Quantité de ces étiquettes */
+
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 */
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c
index 68222dd..29ae826 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,17 @@ 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);
+
G_OBJECT_CLASS(g_scan_rule_parent_class)->finalize(G_OBJECT(rule));
}
@@ -270,6 +281,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. *
* *
@@ -597,19 +656,41 @@ 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 */
- if (full)
- for (i = 0; i < rule->bytes_used; i++)
- g_search_pattern_output_to_text(rule->bytes_locals[i], context, fd);
+ options = g_scan_context_get_options(context);
- if (g_scan_context_has_match_for_rule(context, rule->name))
+ if (rule->tags_count == 0)
+ selected = g_scan_options_has_tag_as_selected(options, NULL);
+
+ else
+ {
+ selected = false;
+
+ 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 (full)
+ 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);
+ }
+
}
+ g_object_unref(G_OBJECT(options));
+
}
diff --git a/src/analysis/scan/rule.h b/src/analysis/scan/rule.h
index 3e6fe9d..b73ee1a 100644
--- a/src/analysis/scan/rule.h
+++ b/src/analysis/scan/rule.h
@@ -75,6 +75,12 @@ ScanRuleFlags g_scan_rule_get_flags(const GScanRule *);
/* Indique le nom associé à une règle de détection. */
const char *g_scan_rule_get_name(const GScanRule *, fnv64_t *);
+/* Lie une règle à une nouvelle étiquette. */
+void g_scan_rule_add_tag(GScanRule *, const char *);
+
+/* Indique les éventuelles étiquettes associées à une règle. */
+const char * const *g_scan_rule_list_tags(const GScanRule *, size_t *);
+
/* Intègre une nouvelle variable locale à une règle. */
void g_scan_rule_add_local_variable(GScanRule *, GSearchPattern *);
diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l
index 1a17344..b284128 100644
--- a/src/analysis/scan/tokens.l
+++ b/src/analysis/scan/tokens.l
@@ -411,12 +411,14 @@ bytes_fuzzy_id [\*A-Za-z_][\*A-Za-z0-9_]*
return RAW_RULE;
}
- <rule_intro>[A-Za-z0-9_]+ {
+ <rule_intro>{bytes_id} {
yylval->sized_cstring.data = yytext;
yylval->sized_cstring.len = yyleng;
- return RULE_NAME;
+ return RULE_IDENTIFIER;
}
+ <rule_intro>":" { return COLON; }
+
<rule_intro>[ \t]* { }
<rule_intro>"{" {
diff --git a/src/rost.c b/src/rost.c
index efe18e5..8a7e806 100644
--- a/src/rost.c
+++ b/src/rost.c
@@ -91,11 +91,12 @@ static void show_rost_help(const char *name)
printf("\n");
- printf("\t-A --algorithm=name\tSelect one of the available algorithms for data: bitmap, acism (default: acsim).\n");
+ printf("\t-A --algorithm=NAME\tSelect one of the available algorithms for data: bitmap, acism (default: acsim).\n");
printf("\t-C --check-only\t\tValidate the rule syntax without performing a scan (discard the file/dir argument).\n");
- printf("\t-j --print-json\t\tPrint matching strings in JSON format.\n");
- printf("\t-s --print-strings\tPrint matching strings.\n");
+ printf("\t-j --print-json\t\tPrint matching strings in JSON format instead of simple text.\n");
+ printf("\t-s --print-strings\tPrint matching strings (default text format only).\n");
printf("\t-S --print-stats\tPrint rules' statistics.\n");
+ printf("\t-t --tag=TAG\t\tprint only matching rules tagged as TAG (default text format only).\n");
printf("\t-V --verbosity=level\tSet the log level (0 for all messages, %u for none).\n", LMT_COUNT);
printf("\n");
@@ -240,6 +241,7 @@ int main(int argc, char **argv)
{ "print-json", no_argument, NULL, 'j' },
{ "print-strings", no_argument, NULL, 's' },
{ "print-stats", no_argument, NULL, 'S' },
+ { "tag", required_argument, NULL, 't' },
{ "verbosity", required_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
@@ -260,7 +262,7 @@ int main(int argc, char **argv)
while (true)
{
- ret = getopt_long(argc, argv, "hvA:CjsSV:", long_options, &index);
+ ret = getopt_long(argc, argv, "hvA:CjsSt:V:", long_options, &index);
if (ret == -1) break;
switch (ret)
@@ -299,6 +301,10 @@ int main(int argc, char **argv)
g_scan_options_set_print_stats(options, true);
break;
+ case 't':
+ g_scan_options_select_tag(options, optarg);
+ break;
+
case 'V':
verbosity = strtoul(optarg, NULL, 10);
break;
@@ -310,7 +316,6 @@ int main(int argc, char **argv)
if ((check_only && (optind + 0) != argc && (optind + 1) != argc)
|| (!check_only && (optind + 1) != argc && (optind + 2) != argc))
{
- printf("failed: check=%d optind=%d argc=%d\n", check_only, optind, argc);
show_rost_help(argv[0]);
goto done;
}