summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2024-01-28 21:27:09 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2024-01-28 21:27:09 (GMT)
commit24945cea340b7b0ca0fe2ccad7b67519dda1c1bd (patch)
tree97ad3364db5f5f5ab0574310c061f75f42418f0c
parent3231349bac6aae1f236416a8a51f41caccc38961 (diff)
Implement a basic support for Hyperscan.
-rw-r--r--configure.ac15
-rw-r--r--src/Makefile.am2
-rw-r--r--src/analysis/scan/patterns/backends/Makefile.am6
-rw-r--r--src/analysis/scan/patterns/backends/hyperscan-int.h67
-rw-r--r--src/analysis/scan/patterns/backends/hyperscan.c648
-rw-r--r--src/analysis/scan/patterns/backends/hyperscan.h59
-rw-r--r--src/rost.c13
7 files changed, 802 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index 55e8f65..cfb94bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -541,6 +541,20 @@ if test "x$enable_magic_support" = "xyes"; then
fi
+#--- Checks for Hyperscan
+
+PKG_CHECK_MODULES(LIBHS,libhs >= 5.4.9,[libhs_found=yes],[libhs_found=no])
+
+if test "$libhs_found" = "yes"; then
+ libhs_version=`pkg-config libhs --modversion`
+else
+ libhs_version='-'
+fi
+
+AC_SUBST(LIBHS_CFLAGS)
+AC_SUBST(LIBHS_LIBS)
+
+
#--- Checks for Python
if test "x$enable_debug" = "xyes"; then
@@ -822,6 +836,7 @@ echo The cryptography and SSL/TLS toolkit......... : $libssl_version
echo The client URL library....................... : $libcurl_version
echo The YAML support library..................... : $libyaml_version
echo The magic number recognition library......... : $libmagic_version
+echo The high-performance matching library........ : $libhs_version
echo
echo Available Python programming language........ : $python3_version
diff --git a/src/Makefile.am b/src/Makefile.am
index e7aa395..9dc053e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,7 +59,7 @@ libchrysacore_la_LDFLAGS = \
-avoid-version -ldl -lm \
$(TOOLKIT_LIBS) $(LIBXML_LIBS) \
$(LIBSQLITE_LIBS) $(LIBARCHIVE_LIBS) \
- $(LIBSSL_LIBS)
+ $(LIBSSL_LIBS) $(LIBHS_LIBS)
if BUILD_CURL_SUPPORT
diff --git a/src/analysis/scan/patterns/backends/Makefile.am b/src/analysis/scan/patterns/backends/Makefile.am
index 672b7ff..23b0163 100644
--- a/src/analysis/scan/patterns/backends/Makefile.am
+++ b/src/analysis/scan/patterns/backends/Makefile.am
@@ -6,11 +6,13 @@ libanalysisscanpatternsbackends_la_SOURCES = \
acism-int.h \
acism.h acism.c \
bitap-int.h \
- bitap.h bitap.c
+ bitap.h bitap.c \
+ hyperscan-int.h \
+ hyperscan.h hyperscan.c
# Cf. https://www.gnu.org/software/automake/manual/html_node/Per_002dObject-Flags.html
-AM_CFLAGS = $(LIBGOBJ_CFLAGS)
+AM_CFLAGS = $(LIBGOBJ_CFLAGS) $(LIBHS_CFLAGS)
diff --git a/src/analysis/scan/patterns/backends/hyperscan-int.h b/src/analysis/scan/patterns/backends/hyperscan-int.h
new file mode 100644
index 0000000..31d271b
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/hyperscan-int.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hyperscan-int.h - prototypes internes pour la méthode de recherche basée sur la bibliothèque Hyperscan d'Intel
+ *
+ * Copyright (C) 2024 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_BACKENDS_HYPERSCAN_INT_H
+#define _ANALYSIS_SCAN_PATTERNS_BACKENDS_HYPERSCAN_INT_H
+
+
+#include "hyperscan.h"
+
+
+#include "../backend-int.h"
+
+
+
+#define EXPR_COVERAGE_START 0
+#define EXPR_COVERAGE_COUNT 1
+#define EXPR_COVERAGE_END 1
+
+
+/* Méthode de recherche basée sur une bibliothèque d'Intel : Hyperscan (instance) */
+struct _GHyperscanBackend
+{
+ GEngineBackend parent; /* A laisser en premier */
+
+ const uint8_t **atoms; /* Motif remarquable */
+ size_t *lengths; /* Nombre d'octets considérés */
+ uint32_t *coverages; /* Départ et quantité de suivis*/
+ size_t allocated; /* Nombre d'éléments alloués */
+ size_t used; /* Nombre d'éléments utiles */
+
+ unsigned int *lit_ids; /* Identifiants internes */
+
+ hs_database_t *database; /* Compilation d'éléments */
+ hs_scratch_t *scratch; /* Espace de travail */
+
+};
+
+/* Méthode de recherche basée sur une bibliothèque d'Intel : Hyperscan (classe) */
+struct _GHyperscanBackendClass
+{
+ GEngineBackendClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_BACKENDS_HYPERSCAN_INT_H */
diff --git a/src/analysis/scan/patterns/backends/hyperscan.c b/src/analysis/scan/patterns/backends/hyperscan.c
new file mode 100644
index 0000000..5d535e3
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/hyperscan.c
@@ -0,0 +1,648 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hyperscan.c - méthode de recherche basée sur la bibliothèque Hyperscan d'Intel
+ *
+ * Copyright (C) 2024 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 "hyperscan.h"
+
+
+#include <hs.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "hyperscan-int.h"
+#include "../../../../core/logs.h"
+
+
+
+/* ---------------------- IMPLANTATION D'UNE NOUVELLE APPROCHE ---------------------- */
+
+
+/* Initialise la classe des méthodes basée sur Hyperscan. */
+static void g_hyperscan_backend_class_init(GHyperscanBackendClass *);
+
+/* Initialise une instance de méthodes basée sur Hyperscan. */
+static void g_hyperscan_backend_init(GHyperscanBackend *);
+
+/* Supprime toutes les références externes. */
+static void g_hyperscan_backend_dispose(GHyperscanBackend *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_hyperscan_backend_finalize(GHyperscanBackend *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Indique la taille maximale des suites d'octets recherchées. */
+size_t g_hyperscan_backend_get_atom_max_size(const GHyperscanBackend *);
+
+/* Inscrit dans le moteur une chaîne de caractères à rechercher. */
+static bool g_hyperscan_backend_enroll_plain_pattern(GHyperscanBackend *, const uint8_t *, size_t, uint32_t [2]);
+
+/* Met en ordre les derniers détails avant un premier scan. */
+static bool g_hyperscan_backend_warm_up(GHyperscanBackend *);
+
+/* Récupère les identifiants finaux pour un motif recherché. */
+static patid_t g_hyperscan_backend_build_plain_pattern_id(const GHyperscanBackend *, const uint32_t [2]);
+
+/* Détermine le nombre d'identifiants constitués. */
+static size_t g_hyperscan_backend_count_plain_pattern_ids(const GHyperscanBackend *);
+
+/* Informations utiles au traitement d'un événement */
+typedef struct _hyperscan_context_t
+{
+ const size_t *lengths; /* Nombre d'octets considérés */
+ const uint32_t *coverages; /* Départ et quantité de suivis*/
+
+#ifndef NDEBUG
+ size_t used; /* Nombre d'éléments utiles */
+ const unsigned int *lit_ids; /* Identifiants internes */
+#endif
+
+ GUMemSlice **matches; /* Zones d'enregistrements */
+
+} hyperscan_context_t;
+
+/* Prend note d'une correspondance trouvée par Hyperscan. */
+static int handle_hyperscan_match_event(unsigned int, unsigned long long, unsigned long long, unsigned int, const hyperscan_context_t *);
+
+/* Parcours un contenu binaire à la recherche de motifs. */
+static void g_hyperscan_backend_run_scan(const GHyperscanBackend *, GScanContext *);
+
+/* Imprime quelques faits quant aux éléments mis en place. */
+static void g_hyperscan_backend_output_stats(const GHyperscanBackend *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLANTATION D'UNE NOUVELLE APPROCHE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un moteur de recherche pour données. */
+G_DEFINE_TYPE(GHyperscanBackend, g_hyperscan_backend, G_TYPE_ENGINE_BACKEND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des méthodes basée sur Hyperscan. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_hyperscan_backend_class_init(GHyperscanBackendClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GEngineBackendClass *backend; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_hyperscan_backend_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_hyperscan_backend_finalize;
+
+ backend = G_ENGINE_BACKEND_CLASS(klass);
+
+ backend->get_max_size = (get_backend_atom_max_size_fc)g_hyperscan_backend_get_atom_max_size;
+ backend->enroll_plain = (enroll_plain_into_backend_fc)g_hyperscan_backend_enroll_plain_pattern;
+ backend->warm_up = (warm_up_backend_fc)g_hyperscan_backend_warm_up;
+ backend->build_id = (build_backend_plain_pattern_id_fc)g_hyperscan_backend_build_plain_pattern_id;
+ backend->count_ids = (count_backend_plain_pattern_ids_fc)g_hyperscan_backend_count_plain_pattern_ids;
+ backend->run_scan = (run_backend_scan_fc)g_hyperscan_backend_run_scan;
+ backend->output = (output_backend_stats_fc)g_hyperscan_backend_output_stats;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance à initialiser. *
+* *
+* Description : Initialise une instance de méthodes basée sur Hyperscan. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_hyperscan_backend_init(GHyperscanBackend *backend)
+{
+ backend->atoms = NULL;
+ backend->lengths = NULL;
+ backend->coverages = NULL;
+ backend->allocated = 0;
+ backend->used = 0;
+
+ backend->database = NULL;
+ backend->scratch = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_hyperscan_backend_dispose(GHyperscanBackend *backend)
+{
+ G_OBJECT_CLASS(g_hyperscan_backend_parent_class)->dispose(G_OBJECT(backend));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_hyperscan_backend_finalize(GHyperscanBackend *backend)
+{
+ if (backend->atoms != NULL)
+ free(backend->atoms);
+
+ if (backend->lengths != NULL)
+ free(backend->lengths);
+
+ if (backend->coverages != NULL)
+ free(backend->coverages);
+
+ if (backend->scratch != NULL)
+ hs_free_scratch(backend->scratch);
+
+ if (backend->database != NULL)
+ hs_free_database(backend->database);
+
+ G_OBJECT_CLASS(g_hyperscan_backend_parent_class)->finalize(G_OBJECT(backend));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une méthode de recherche avec la bibliothèque Hyperscan.*
+* *
+* Retour : Méthode mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GEngineBackend *g_hyperscan_backend_new(void)
+{
+ GHyperscanBackend *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_HYPERSCAN_BACKEND, NULL);
+
+ return G_ENGINE_BACKEND(result);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à consulter. *
+* *
+* Description : Indique la taille maximale des suites d'octets recherchées. *
+* *
+* Retour : Valeur strictement positive. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_hyperscan_backend_get_atom_max_size(const GHyperscanBackend *backend)
+{
+ size_t result; /* Taille à faire connaître */
+
+ result = ~0;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* plain = chaîne de caractères classique à intégrer. *
+* len = taille de cette chaîne. *
+* tmp_id = identifiants temporaires vers le motif. [OUT] *
+* *
+* Description : Inscrit dans le moteur une chaîne de caractères à rechercher.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_hyperscan_backend_enroll_plain_pattern(GHyperscanBackend *backend, const uint8_t *plain, size_t len, uint32_t tmp_id[2])
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ int ret; /* Bilan d'une comparaison */
+
+ result = true;
+
+ /*Recherche d'un motif déjà sollicité */
+
+ for (i = 0; i < backend->used; i++)
+ {
+ if (backend->lengths[i] != len)
+ continue;
+
+ ret = memcmp(backend->atoms[i], plain, backend->lengths[i]);
+
+ if (ret == 0)
+ {
+ tmp_id[0] = i;
+ tmp_id[1] = backend->coverages[i * 2 + EXPR_COVERAGE_COUNT];
+
+ backend->coverages[i * 2 + EXPR_COVERAGE_COUNT]++;
+ break;
+
+ }
+
+ }
+
+ /* Introduction d'un nouveau motif au besoin */
+
+ if (i == backend->used)
+ {
+ if (backend->used == backend->allocated)
+ {
+ if (backend->allocated == 0)
+ backend->allocated = 64;
+ else
+ backend->allocated *= 2;
+
+ backend->atoms = realloc(backend->atoms, backend->allocated * sizeof(const uint8_t *));
+ backend->lengths = realloc(backend->lengths, backend->allocated * sizeof(size_t));
+ backend->coverages = realloc(backend->coverages, backend->allocated * 2 * sizeof(uint32_t));
+
+ }
+
+ backend->atoms[i] = plain;
+ backend->lengths[i] = len;
+ backend->coverages[i * 2 + EXPR_COVERAGE_COUNT] = 1;
+
+ backend->used++;
+
+ tmp_id[0] = i;
+ tmp_id[1] = 0;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à préparer. *
+* *
+* Description : Met en ordre les derniers détails avant un premier scan. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_hyperscan_backend_warm_up(GHyperscanBackend *backend)
+{
+ bool result; /* Bilan à retourner */
+ uint32_t current_start; /* Indice de gestionnaire */
+ size_t i; /* Boucle de parcours */
+ hs_compile_error_t *error; /* Compléments d'information */
+ hs_error_t ret; /* Code de retour */
+
+ hs_platform_info_t platform;
+
+ result = false;
+
+ /* Mise à jour de la couverture des gestionnaires de suivi */
+
+ current_start = 0;
+
+ for (i = 0; i < backend->used; i++)
+ {
+ backend->coverages[i * 2 + EXPR_COVERAGE_START] = current_start;
+ backend->coverages[i * 2 + EXPR_COVERAGE_END] += current_start;
+
+ current_start = backend->coverages[i * 2 + EXPR_COVERAGE_END];
+
+ }
+
+ /* Enregistrement des expressions à prendre en compte */
+
+ backend->lit_ids = malloc(backend->used * sizeof(unsigned));
+
+ for (i = 0; i < backend->used; i++)
+ backend->lit_ids[i] = i;
+
+ //hs_populate_platform(&platform);
+
+ //platform.tune = 1;
+
+ //platform.cpu_features = HS_CPU_FEATURES_AVX512;
+
+ ret = hs_compile_lit_multi((const char *const *)backend->atoms, NULL, backend->lit_ids, backend->lengths,
+ backend->used, HS_MODE_BLOCK, NULL, &backend->database, &error);
+
+
+ //printf("ret: %d -vs- %d\n", ret, HS_SUCCESS);
+
+ if (ret != HS_SUCCESS)
+ {
+ log_variadic_message(LMT_EXT_ERROR, _("Unable to compile %zu patterns: \"%s\""),
+ backend->used, error->message);
+ printf("FAILED: %s\n", error->message);
+ hs_free_compile_error(error);
+ goto exit;
+ }
+
+#if 0
+ do
+ {
+ //hs_platform_info_t platform;
+ char *__info;
+
+ //hs_populate_platform(&platform);
+
+ printf("TUNE: %u\n", platform.tune);
+
+ printf("CPU: %llx - AVX2? %d - AVX512? %d\n", platform.cpu_features,
+ platform.cpu_features & HS_CPU_FEATURES_AVX2,
+ platform.cpu_features & HS_CPU_FEATURES_AVX512);
+
+ hs_database_info(backend->database, &__info);
+
+ printf("INFO: %s\n", __info);
+
+ }
+ while (0);
+#endif
+
+ /* Création d'un espace de travail */
+
+ ret = hs_alloc_scratch(backend->database, &backend->scratch);
+
+ //printf("ret: %d -vs- %d\n", ret, HS_SUCCESS);
+
+ if (ret != HS_SUCCESS)
+ {
+ log_variadic_message(LMT_EXT_ERROR, _("Unable to allocate scratch space"));
+ goto exit;
+ }
+
+ result = true;
+
+ exit:
+
+ //printf("result: %d\n", result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* tmp_id = identifiants temporaires vers le motif. [OUT] *
+* *
+* Description : Récupère les identifiants finaux pour un motif recherché. *
+* *
+* Retour : Identifiant constitué ou INVALID_PATTERN_ID en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static patid_t g_hyperscan_backend_build_plain_pattern_id(const GHyperscanBackend *backend, const uint32_t tmp_id[2])
+{
+ patid_t result; /* Identifiant à retourner */
+ size_t index; /* Indice reconstitué */
+
+ assert(tmp_id[0] < backend->used);
+
+ index = tmp_id[0] * 2;
+
+ result = backend->coverages[index + EXPR_COVERAGE_START] + tmp_id[1];
+
+ assert(result < backend->coverages[index + EXPR_COVERAGE_END]);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* *
+* Description : Détermine le nombre d'identifiants constitués. *
+* *
+* Retour : Quantité de gestionnaires de suivi à prévoir. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static size_t g_hyperscan_backend_count_plain_pattern_ids(const GHyperscanBackend *backend)
+{
+ size_t result; /* Quantité à retourner */
+
+ if (backend->used == 0)
+ result = 0;
+ else
+ result = backend->coverages[(backend->used - 1) * 2 + EXPR_COVERAGE_END];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* *
+* Description : Prend note d'une correspondance trouvée par Hyperscan. *
+* *
+* Retour : 0 afin de poursuivre les recherches. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int handle_hyperscan_match_event(unsigned int id, unsigned long long from, unsigned long long to, unsigned int flags, const hyperscan_context_t *context)
+{
+ phys_t offset; /* Point de départ établi */
+ const uint32_t *coverage_base; /* Base des suivis */
+ uint32_t k; /* Boucle de parcours */
+ uint32_t final_k; /* Dernier indice à traiter */
+
+ //return 0;
+
+#ifndef NDEBUG
+ assert(id < context->used);
+ assert(id == context->lit_ids[id]);
+#endif
+
+ offset = to - context->lengths[id];
+
+ coverage_base = context->coverages + id * 2;
+
+ k = coverage_base[EXPR_COVERAGE_START];
+ final_k = coverage_base[EXPR_COVERAGE_END];
+
+ for (; k < final_k; k++)
+ g_umem_slice_put_uint64(context->matches[k], offset);
+
+ return 0;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à manipuler. *
+* context = lieu d'enregistrement des résultats. *
+* *
+* Description : Parcours un contenu binaire à la recherche de motifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_hyperscan_backend_run_scan(const GHyperscanBackend *backend, GScanContext *context)
+{
+ GBinContent *content; /* Contenu binaire manipulé */
+ phys_t dlen; /* Quantité de données */
+ vmpa2t pos; /* Point de départ ciblé */
+ const bin_t *data; /* Données à analyser */
+#ifndef NDEBUG
+ siez_t count; /* Nombre de zones prévues */
+#endif
+ hyperscan_context_t hcontext; /* Rassemblement d'informations*/
+ GUMemSlice **matches; /* Zones d'enregistrements */
+ hs_error_t ret; /* Code de retour */
+
+ /* Récupération d'un accès aux données */
+
+ content = g_scan_context_get_content(context);
+
+ dlen = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &pos);
+ data = g_binary_content_get_raw_access(content, &pos, dlen);
+
+ /* Préparation de l'accès aux éléments utiles */
+
+ hcontext.lengths = backend->lengths;
+ hcontext.coverages = backend->coverages;
+
+#ifndef NDEBUG
+ hcontext.used = backend->used;
+ hcontext.lit_ids = backend->lit_ids;
+#endif
+
+#ifndef NDEBUG
+ matches = g_scan_context_get_match_storages(context, &count);
+ assert(count == backend->used);
+#else
+ matches = g_scan_context_get_match_storages(context, (size_t []){ 0 });
+#endif
+
+ hcontext.matches = matches;
+
+ /* Lancement de l'analyse */
+
+ ret = hs_scan(backend->database, (const char *)data, dlen,
+ 0 /* Arg. inutilisé */, backend->scratch,
+ (match_event_handler)handle_hyperscan_match_event, &hcontext);
+
+
+ //printf("ret ok? %d\n", ret == HS_SUCCESS);
+
+
+
+ g_object_unref(G_OBJECT(content));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : backend = moteur de recherche à consulter. *
+* *
+* Description : Imprime quelques faits quant aux éléments mis en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_hyperscan_backend_output_stats(const GHyperscanBackend *backend)
+{
+ printf("TODO: %s\n", __FUNCTION__);
+
+}
diff --git a/src/analysis/scan/patterns/backends/hyperscan.h b/src/analysis/scan/patterns/backends/hyperscan.h
new file mode 100644
index 0000000..d8c0f92
--- /dev/null
+++ b/src/analysis/scan/patterns/backends/hyperscan.h
@@ -0,0 +1,59 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hyperscan.h - prototypes pour la méthode de recherche basée sur la bibliothèque Hyperscan d'Intel
+ *
+ * Copyright (C) 2024 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_BACKENDS_HYPERSCAN_H
+#define _ANALYSIS_SCAN_PATTERNS_BACKENDS_HYPERSCAN_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../backend.h"
+
+
+
+#define G_TYPE_HYPERSCAN_BACKEND g_hyperscan_backend_get_type()
+#define G_HYPERSCAN_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_HYPERSCAN_BACKEND, GHyperscanBackend))
+#define G_IS_HYPERSCAN_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_HYPERSCAN_BACKEND))
+#define G_HYPERSCAN_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_HYPERSCAN_BACKEND, GHyperscanBackendClass))
+#define G_IS_HYPERSCAN_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_HYPERSCAN_BACKEND))
+#define G_HYPERSCAN_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_HYPERSCAN_BACKEND, GHyperscanBackendClass))
+
+
+/* Méthode de recherche basée sur une bibliothèque d'Intel : Hyperscan (instance) */
+typedef struct _GHyperscanBackend GHyperscanBackend;
+
+/* Méthode de recherche basée sur une bibliothèque d'Intel : Hyperscan (classe) */
+typedef struct _GHyperscanBackendClass GHyperscanBackendClass;
+
+
+/* Indique le type défini pour un moteur de recherche pour données. */
+GType g_hyperscan_backend_get_type(void);
+
+/* Crée une méthode de recherche avec la bibliothèque Hyperscan. */
+GEngineBackend *g_hyperscan_backend_new(void);
+
+
+
+#endif /* _ANALYSIS_SCAN_PATTERNS_BACKENDS_HYPERSCAN_H */
diff --git a/src/rost.c b/src/rost.c
index d397a2c..4a052c3 100644
--- a/src/rost.c
+++ b/src/rost.c
@@ -39,8 +39,9 @@
#include "analysis/scan/core.h"
#include "analysis/scan/options.h"
#include "analysis/scan/scanner.h"
-#include "analysis/scan/patterns/backends/bitap.h"
#include "analysis/scan/patterns/backends/acism.h"
+#include "analysis/scan/patterns/backends/bitap.h"
+#include "analysis/scan/patterns/backends/hyperscan.h"
#include "core/core.h"
#include "core/global.h"
#include "core/logs.h"
@@ -92,7 +93,7 @@ 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: acism, bitmap, hyperscan (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 instead of simple text.\n");
printf("\t-s --print-strings\tPrint matching strings (default text format only).\n");
@@ -298,10 +299,12 @@ int main(int argc, char **argv)
break;
case 'A':
- if (strcmp(optarg, "bitmap") == 0)
- g_scan_options_set_backend_for_data(options, G_TYPE_BITAP_BACKEND);
- else if (strcmp(optarg, "acism") == 0)
+ if (strcmp(optarg, "acism") == 0)
g_scan_options_set_backend_for_data(options, G_TYPE_ACISM_BACKEND);
+ else if (strcmp(optarg, "bitmap") == 0)
+ g_scan_options_set_backend_for_data(options, G_TYPE_BITAP_BACKEND);
+ else if (strcmp(optarg, "hyperscan") == 0)
+ g_scan_options_set_backend_for_data(options, G_TYPE_HYPERSCAN_BACKEND);
else
g_scan_options_set_backend_for_data(options, G_TYPE_INVALID);
break;