summaryrefslogtreecommitdiff
path: root/src/analysis/scan/patterns/tokens/plain.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/scan/patterns/tokens/plain.c')
-rw-r--r--src/analysis/scan/patterns/tokens/plain.c374
1 files changed, 374 insertions, 0 deletions
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);
+
+}