diff options
Diffstat (limited to 'src/analysis/scan/patterns/tokens')
-rw-r--r-- | src/analysis/scan/patterns/tokens/Makefile.am | 13 | ||||
-rw-r--r-- | src/analysis/scan/patterns/tokens/plain.c | 374 | ||||
-rw-r--r-- | src/analysis/scan/patterns/tokens/plain.h | 67 |
3 files changed, 454 insertions, 0 deletions
diff --git a/src/analysis/scan/patterns/tokens/Makefile.am b/src/analysis/scan/patterns/tokens/Makefile.am new file mode 100644 index 0000000..00cff2a --- /dev/null +++ b/src/analysis/scan/patterns/tokens/Makefile.am @@ -0,0 +1,13 @@ + +noinst_LTLIBRARIES = libanalysisscanpatternstokens.la + + +libanalysisscanpatternstokens_la_SOURCES = \ + plain.h plain.c + +libanalysisscanpatternstokens_la_CFLAGS = $(LIBGOBJ_CFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) + +dev_HEADERS = $(libanalysisscanpatternstokens_la_SOURCES:%c=) diff --git a/src/analysis/scan/patterns/tokens/plain.c b/src/analysis/scan/patterns/tokens/plain.c new file mode 100644 index 0000000..9eb731e --- /dev/null +++ b/src/analysis/scan/patterns/tokens/plain.c @@ -0,0 +1,374 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * plain.c - 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/>. + */ + + +#include "plain.h" + + +#include <malloc.h> +#include <string.h> + + +#include "../token-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); + +/* Initialise une instance de recherche de texte brut. */ +static void g_plain_bytes_init(GPlainBytes *); + +/* Supprime toutes les références externes. */ +static void g_plain_bytes_dispose(GPlainBytes *); + +/* Procède à la libération totale de la mémoire. */ +static void g_plain_bytes_finalize(GPlainBytes *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Inscrit la définition d'un motif dans un moteur de recherche. */ +static bool g_plain_bytes_enroll(GPlainBytes *, GScanContext *, GEngineBackend *, size_t); + +/* Transforme les correspondances locales en trouvailles. */ +static void g_plain_bytes_check(const GPlainBytes *, 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(GPlainBytes, g_plain_bytes, G_TYPE_STRING_TOKEN); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des recherches de texte brut. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_plain_bytes_class_init(GPlainBytesClass *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_plain_bytes_dispose; + object->finalize = (GObjectFinalizeFunc)g_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); + + token = G_STRING_TOKEN_CLASS(klass); + + token->enroll = (enroll_token_fc)g_plain_bytes_enroll; + token->check = (check_token_fc)g_plain_bytes_check; + +} + + +/****************************************************************************** +* * +* Paramètres : pattern = instance à initialiser. * +* * +* Description : Initialise une instance de recherche de texte brut. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_plain_bytes_init(GPlainBytes *bytes) +{ + bytes->raw = NULL; + bytes->allocated = 0; + bytes->used = 0; + + bytes->atom_pos = 0; + bytes->atom_len = 0; + bytes->atom_rem = 0; + bytes->pid = INVALID_PATTERN_ID; + +} + + +/****************************************************************************** +* * +* Paramètres : bytes = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_plain_bytes_dispose(GPlainBytes *bytes) +{ + G_OBJECT_CLASS(g_plain_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_plain_bytes_finalize(GPlainBytes *bytes) +{ + if (bytes->raw != NULL) + free(bytes->raw); + + G_OBJECT_CLASS(g_plain_bytes_parent_class)->finalize(G_OBJECT(bytes)); + +} + + +/****************************************************************************** +* * +* Paramètres : text = texte brut à rechercher. * +* len = longueur de ce texte. * +* * +* Description : Construit un gestionnaire de recherche de texte brut. * +* * +* Retour : Mécanismes mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSearchPattern *g_plain_bytes_new(const uint8_t *raw, size_t len) +{ + GPlainBytes *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_PLAIN_BYTES, NULL); + + result->raw = malloc(len); + result->allocated = len; + result->used = len; + + memcpy(result->raw, raw, len); + + return G_SEARCH_PATTERN(result); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* 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_plain_bytes_enroll(GPlainBytes *bytes, GScanContext *context, GEngineBackend *backend, size_t maxsize) +{ + bool result; /* Statut à retourner */ + + + result = true; + + + + bytes->atom_pos = 0; + + if (bytes->used > maxsize) // Attention à la position de départ (à retrancher) ! + { + bytes->atom_len = maxsize; + bytes->atom_rem = bytes->used - maxsize; + } + else + { + bytes->atom_len = bytes->used; + bytes->atom_rem = 0; + } + + + bytes->pid = g_engine_backend_enroll_plain_pattern(backend, context, bytes->raw, bytes->atom_len); + + + + result = (bytes->pid != INVALID_PATTERN_ID); + + + + 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_plain_bytes_check(const GPlainBytes *bytes, GScanContext *context, GBinContent *content, pending_matches_t *matches) +{ + bool initialized; /* Initialisation du suivi ? */ + 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 */ + 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++) + { + start = found[i] - bytes->atom_pos; + + /* Recherche d'un point de départ attendu et conforme ? */ + + if (initialized) + if (!find_target_in_pending_matches(matches, start, &mindex)) + continue; + + init_vmpa(&pos, start, VMPA_NO_VIRTUAL); + + /* Validation du contenu avant l'atome */ + + if (bytes->atom_pos > 0) + { + 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; + + } + + /* Validation du contenu après l'atome */ + + if (bytes->atom_rem > 0) + { + advance_vmpa(&pos, bytes->atom_len); + + ptr = g_binary_content_get_raw_access(content, &pos, bytes->atom_rem); + + ret = memcmp(bytes->raw + bytes->atom_pos + bytes->atom_len, ptr, bytes->atom_rem); + if (ret != 0) goto exclude_false_positive; + + } + + /* Mémorisation de la correspondance */ + + if (initialized) + extend_pending_matches(matches, mindex, bytes->used); + else + add_pending_matches(matches, start, bytes->used); + + continue; + + exclude_false_positive: + + if (initialized) + remove_pending_matches(matches, mindex); + + } + + set_pending_matches_initialized(matches); + +} diff --git a/src/analysis/scan/patterns/tokens/plain.h b/src/analysis/scan/patterns/tokens/plain.h new file mode 100644 index 0000000..de1d4ec --- /dev/null +++ b/src/analysis/scan/patterns/tokens/plain.h @@ -0,0 +1,67 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * plain.h - prototypes 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_H +#define _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_H + + +#include <glib-object.h> +#include <stdint.h> + + +#include "../../pattern.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)) + + +/* Représentation d'une suite d'octets à retrouver (instance) */ +typedef struct _GPlainBytes GPlainBytes; + +/* Représentation d'une suite d'octets à retrouver (classe) */ +typedef struct _GPlainBytesClass GPlainBytesClass; + + +/* Propriétés d'un élément textuel à rechercher */ +typedef enum _StringTokenAttrib +{ + STP_CASE_INSENSITIVE, + +} StringTokenAttrib; + + +/* Indique le type défini pour une suite d'octets à retrouver dans un binaire. */ +GType g_plain_bytes_get_type(void); + +/* Construit un gestionnaire de recherche de texte brut. */ +GSearchPattern *g_plain_bytes_new(const uint8_t *, size_t); + + + +#endif /* _ANALYSIS_SCAN_PATTERNS_TOKENS_PLAIN_H */ |