diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2023-01-30 06:59:35 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2023-01-30 06:59:35 (GMT) |
commit | db3b204dd7a71b2f74a4e69b2159a96e3ab66614 (patch) | |
tree | 34174311b7ac504f03a10a889ada7f28db7a06c0 /src/analysis/scan/rule.c | |
parent | 34ee1bfca78e8423cfa29329fdc756569d6b1960 (diff) |
Save an initial version of rost.
Diffstat (limited to 'src/analysis/scan/rule.c')
-rw-r--r-- | src/analysis/scan/rule.c | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/src/analysis/scan/rule.c b/src/analysis/scan/rule.c new file mode 100644 index 0000000..6c771fb --- /dev/null +++ b/src/analysis/scan/rule.c @@ -0,0 +1,383 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * rule.c - parcours de contenus à la recherche de motifs + * + * Copyright (C) 2022 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 "rule.h" + + +#include <assert.h> +#include <strings.h> + + +#include "rule-int.h" +#include "matches/bytes.h" +#include "patterns/token.h" + + + +/* Initialise la classe des règles de détection statique. */ +static void g_scan_rule_class_init(GScanRuleClass *); + +/* Initialise une instance de règle de détection statique. */ +static void g_scan_rule_init(GScanRule *); + +/* Supprime toutes les références externes. */ +static void g_scan_rule_dispose(GScanRule *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_rule_finalize(GScanRule *); + + + +/* Indique le type défini pour une règle de détection par motifs. */ +G_DEFINE_TYPE(GScanRule, g_scan_rule, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des règles de détection statique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_rule_class_init(GScanRuleClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_rule_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_rule_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : rule = instance à initialiser. * +* * +* Description : Initialise une instance de règle de détection statique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_rule_init(GScanRule *rule) +{ + rule->name = NULL; + + rule->data_locals = NULL; + rule->data_allocated = 0; + rule->data_used = 0; + + rule->condition = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : rule = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +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]); + + g_clear_object(&rule->condition); + + G_OBJECT_CLASS(g_scan_rule_parent_class)->dispose(G_OBJECT(rule)); + +} + + +/****************************************************************************** +* * +* Paramètres : rule = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_rule_finalize(GScanRule *rule) +{ + if (rule->name != NULL) + free(rule->name); + + G_OBJECT_CLASS(g_scan_rule_parent_class)->finalize(G_OBJECT(rule)); + +} + + +/****************************************************************************** +* * +* Paramètres : name = désignation à associer à la future règle. * +* * +* Description : Crée une règle de détection statique à l'aide de motifs. * +* * +* Retour : Règle de détection mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanRule *g_scan_rule_new(const char *name) +{ + GScanRule *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_RULE, NULL); + + result->name = strdup(name); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : rule = règle de détection à compléter. * +* pattern = nouveau motif de détection. * +* * +* Description : Intègre une nouvelle variable locale à une règle. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_scan_rule_add_local_variable(GScanRule *rule, GSearchPattern *pattern) +{ + if (G_IS_STRING_TOKEN(pattern)) + { + if (rule->data_used == rule->data_allocated) + { + rule->data_allocated += PATTERN_ALLOC_SIZE; + rule->data_locals = realloc(rule->data_locals, rule->data_allocated * sizeof(GSearchPattern *)); + } + + rule->data_locals[rule->data_used++] = pattern; + g_object_ref(G_OBJECT(pattern)); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : rule = règle de détection à consulter. * +* target = nom d'une variable locale à retrouver. * +* * +* Description : Fournit une variable locale à une règle selon un nom. * +* * +* Retour : Motif de détection retrouvé ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSearchPattern *g_scan_rule_get_local_variable(GScanRule *rule, const char *target) +{ + GSearchPattern *result; /* Variable à retourner */ + size_t i; /* Boucle de parcours */ + const char *name; /* Désignation d'un motif */ + + result = NULL; + + for (i = 0; i < rule->data_used; i++) + { + name = g_search_pattern_get_name(rule->data_locals[i]); + + if (strcmp(name, target) == 0) + { + result = rule->data_locals[i]; + break; + } + + } + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : rule = règle de détection à compléter. * +* expr = expression de condition à satisfaire. * +* * +* Description : Définit l'expression d'une correspondance recherchée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_scan_rule_set_match_condition(GScanRule *rule, GScanExpression *expr) +{ + rule->condition = expr; + + g_object_ref(G_OBJECT(expr)); + +} + + +/****************************************************************************** +* * +* Paramètres : rule = règle de détection à considérer. * +* backend = moteur d'analyse pour données brutes. * +* context = contexte de l'analyse à mener. * +* * +* Description : Prépare le suivi de recherche de motifs pour une règle. * +* * +* Retour : Bilan de l'opération à renvoyer. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_rule_setup_backend(GScanRule *rule, GEngineBackend *backend, GScanContext *context) +{ + 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 */ + + result = g_scan_context_set_rule_condition(context, rule->name, rule->condition); + if (!result) goto exit; + + /* Programmation des motifs recherchés */ + + maxsize = g_engine_backend_get_atom_max_size(backend); + + for (i = 0; i < rule->data_used && result; i++) + { + pattern = rule->data_locals[i]; + result = g_string_token_enroll(G_STRING_TOKEN(pattern), context, backend, maxsize); + } + + g_engine_backend_warm_up(backend); + + /* Affichage éventuel de statistiques */ + + options = g_scan_context_get_options(context); + + if (g_scan_options_get_print_stats(options)) + g_engine_backend_output_stats(backend); + + + g_object_unref(G_OBJECT(options)); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : rule = règle de détection à considérer. * +* backend = moteur d'analyse pour données brutes. * +* context = contexte de l'analyse à mener. * +* * +* Description : Lance une analyse d'un contenu binaire selon une règle. * +* * +* Retour : Contexte de suivi pour l'analyse menée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_scan_rule_analyze(GScanRule *rule, GEngineBackend *backend, GScanContext *context) +{ + GBinContent *content; /* Contenu à manipuler */ + pending_matches_t matches; /* Suivi de correspondances */ + size_t i; /* Boucle de parcours #1 */ + GSearchPattern *pattern; /* Motif à intégrer */ + size_t k; /* Boucle de parcours #2 */ + match_area_t *area; /* Zone à initialiser */ + GScanMatch *match; /* Correspondance à mémoriser */ + + content = g_scan_context_get_content(context); + + g_engine_backend_run_scan(backend, context, content); + + /* Consolidation des résultats */ + + for (i = 0; i < rule->data_used; i++) + { + init_pending_matches(&matches); + + pattern = rule->data_locals[i]; + + g_string_token_check(G_STRING_TOKEN(pattern), context, content, &matches); + + for (k = 0; k < matches.used; k++) + { + area = &matches.areas[k]; + + match = g_bytes_match_new(G_SEARCH_PATTERN(pattern), content, area->start, area->length); + g_scan_context_register_full_match(context, match); + g_object_unref(G_OBJECT(match)); + + } + + exit_pending_matches(&matches); + + } + + /* Sortie propre */ + + g_object_unref(G_OBJECT(content)); + +} |