diff options
Diffstat (limited to 'plugins')
172 files changed, 14974 insertions, 588 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 7ce4229..1cda6e0 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -28,8 +28,10 @@ SUBDIRS = \ mobicore \ pe \ yaml \ + apihashing \ bhash \ dalvik \ + encodings \ libcsem \ lnxsyscalls \ readdex \ diff --git a/plugins/apihashing/Makefile.am b/plugins/apihashing/Makefile.am new file mode 100644 index 0000000..d73f8b0 --- /dev/null +++ b/plugins/apihashing/Makefile.am @@ -0,0 +1,65 @@ + +lib_LTLIBRARIES = libapihashing.la + +libdir = $(pluginslibdir) + + +if BUILD_PYTHON_PACKAGE + +RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs:$$ORIGIN' + +else + +RUN_PATH = -Wl,-rpath,'$$ORIGIN' + +endif + +if BUILD_PYTHON3_BINDINGS + +PYTHON3_LIBADD = python/libapihashingpython.la + +if BUILD_DISCARD_LOCAL + +if BUILD_PYTHON_PACKAGE +PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN/..' +else +PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN' +endif + +else + +PYTHON3_RUN_PATH = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs + +endif + +PYTHON3_LDFLAGS = $(PYTHON3_RUN_PATH) -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so + +PYTHON3_SUBDIRS = python + +endif + + +libapihashing_la_SOURCES = \ + apihash.h apihash.c \ + core.h core.c + +libapihashing_la_LIBADD = \ + $(PYTHON3_LIBADD) \ + classics/libapihashingclassics.la \ + custom/libapihashingcustom.la + +libapihashing_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + +libapihashing_la_LDFLAGS = \ + -avoid-version \ + -L$(top_srcdir)/src/.libs -lchrysacore \ + -L$(top_srcdir)/plugins/pe/.libs -lpe \ + $(RUN_PATH) $(PYTHON3_LDFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libapihashing_la_SOURCES:%c=) + + +SUBDIRS = $(PYTHON3_SUBDIRS) classics custom diff --git a/plugins/apihashing/apihash.c b/plugins/apihashing/apihash.c new file mode 100644 index 0000000..3313073 --- /dev/null +++ b/plugins/apihashing/apihash.c @@ -0,0 +1,134 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * apihash.c - détermination d'API par empreinte de fonction + * + * 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 "apihash.h" + + +#include <analysis/scan/patterns/modifier-int.h> + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en empreintes d'API. */ +static void g_api_hash_modifier_class_init(GApiHashModifierClass *klass); + +/* Initialise une instance de transmission en empreinte d'API. */ +static void g_api_hash_modifier_init(GApiHashModifier *); + +/* Supprime toutes les références externes. */ +static void g_api_hash_modifier_dispose(GApiHashModifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_api_hash_modifier_finalize(GApiHashModifier *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte d'API. */ +G_DEFINE_TYPE(GApiHashModifier, g_api_hash_modifier, G_TYPE_SCAN_TOKEN_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en empreintes d'API. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_api_hash_modifier_class_init(GApiHashModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_api_hash_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_api_hash_modifier_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en empreinte d'API. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_api_hash_modifier_init(GApiHashModifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_api_hash_modifier_dispose(GApiHashModifier *modifier) +{ + G_OBJECT_CLASS(g_api_hash_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_api_hash_modifier_finalize(GApiHashModifier *modifier) +{ + G_OBJECT_CLASS(g_api_hash_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} diff --git a/plugins/apihashing/apihash.h b/plugins/apihashing/apihash.h new file mode 100644 index 0000000..cfc3365 --- /dev/null +++ b/plugins/apihashing/apihash.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * apihash.h - prototypes pour la détermination d'API par empreinte de fonction + * + * 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 _PLUGINS_APIHASHING_APIHASH_H +#define _PLUGINS_APIHASHING_APIHASH_H + + +#include <glib-object.h> + + +#include <analysis/scan/patterns/modifier.h> + + + +#define G_TYPE_API_HASH_MODIFIER g_api_hash_modifier_get_type() +#define G_API_HASH_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_API_HASH_MODIFIER, GApiHashModifier)) +#define G_IS_API_HASH_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_API_HASH_MODIFIER)) +#define G_API_HASH_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_API_HASH_MODIFIER, GApiHashModifierClass)) +#define G_IS_API_HASH_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_API_HASH_MODIFIER)) +#define G_API_HASH_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_API_HASH_MODIFIER, GApiHashModifierClass)) + + +/* Transormation en empreinte d'API (instance) */ +typedef GScanTokenModifier GApiHashModifier; + +/* Transormation en empreinte d'API (classe) */ +typedef GScanTokenModifierClass GApiHashModifierClass; + + +/* Indique le type défini pour une transormation en empreinte d'API. */ +GType g_api_hash_modifier_get_type(void); + + + +#endif /* _PLUGINS_APIHASHING_APIHASH_H */ diff --git a/plugins/apihashing/classics/Makefile.am b/plugins/apihashing/classics/Makefile.am new file mode 100644 index 0000000..9f97b47 --- /dev/null +++ b/plugins/apihashing/classics/Makefile.am @@ -0,0 +1,14 @@ + +noinst_LTLIBRARIES = libapihashingclassics.la + +libapihashingclassics_la_SOURCES = \ + crc32.h crc32.c \ + djb2.h djb2.c \ + ror13.h ror13.c + +libapihashingclassics_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libapihashingclassics_la_SOURCES:%c=) diff --git a/plugins/apihashing/classics/crc32.c b/plugins/apihashing/classics/crc32.c new file mode 100644 index 0000000..98f9a6b --- /dev/null +++ b/plugins/apihashing/classics/crc32.c @@ -0,0 +1,332 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * crc32.c - transormation en empreinte d'API crc32 + * + * 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 "crc32.h" + + +#include <malloc.h> +#include <string.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en empreintes crc32. */ +static void g_scan_crc32_modifier_class_init(GScanCrc32ModifierClass *klass); + +/* Initialise une instance de transmission en empreinte crc32. */ +static void g_scan_crc32_modifier_init(GScanCrc32Modifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_crc32_modifier_dispose(GScanCrc32Modifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_crc32_modifier_finalize(GScanCrc32Modifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_crc32_modifier_get_name(const GScanCrc32Modifier *); + +/* Calcule l'empreinte crc32 d'un motif de recherche. */ +static uint32_t compute_crc32(const sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_crc32_modifier_transform(const GScanCrc32Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_crc32_modifier_get_path(const GScanCrc32Modifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en encodage Crc32. */ +G_DEFINE_TYPE(GScanCrc32Modifier, g_scan_crc32_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en empreintes crc32. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_crc32_modifier_class_init(GScanCrc32ModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_crc32_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_crc32_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_crc32_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_crc32_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_crc32_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en empreinte crc32. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_crc32_modifier_init(GScanCrc32Modifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_crc32_modifier_dispose(GScanCrc32Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_crc32_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_crc32_modifier_finalize(GScanCrc32Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_crc32_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur livrant des empreintes crc32. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_crc32_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_CRC32_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_crc32_modifier_get_name(const GScanCrc32Modifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("crc32"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : src = séquence d'octets à traiter. * +* * +* Description : Calcule l'empreinte crc32 d'un motif de recherche. * +* * +* Retour : Valeur entière de l'empreinte déterminée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static uint32_t compute_crc32(const sized_binary_t *src) +{ + uint32_t result; /* Valeur à retourner */ + size_t i; /* Boucle de parcours #1 */ + size_t k; /* Boucle de parcours #2 */ + + result = 0xffffffff; + + for (i = 0; i < src->len; i++) + { + result ^= src->data[i]; + + for (k = 0; k < 8; k++) + result = result & 1 ? (result >> 1) ^ 0xedb88320 : result >> 1; + + } + + result = ~result; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_crc32_modifier_transform(const GScanCrc32Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + uint32_t hash; /* Valeur d'empreinte calculée */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + hash = compute_crc32(_src); + + binary->data = malloc(sizeof(hash) * sizeof(bin_t)); + binary->len = sizeof(hash); + + memcpy(binary->data, &hash, sizeof(hash)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_crc32_modifier_get_path(const GScanCrc32Modifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("crc32"); + + return result; + +} diff --git a/plugins/apihashing/classics/crc32.h b/plugins/apihashing/classics/crc32.h new file mode 100644 index 0000000..0198c5d --- /dev/null +++ b/plugins/apihashing/classics/crc32.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * crc32.h - prototypes pour la transormation en empreinte d'API crc32 + * + * 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 _PLUGINS_APIHASHING_CLASSICS_CRC32_H +#define _PLUGINS_APIHASHING_CLASSICS_CRC32_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_CRC32_MODIFIER g_scan_crc32_modifier_get_type() +#define G_SCAN_CRC32_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_CRC32_MODIFIER, GScanCrc32Modifier)) +#define G_IS_SCAN_CRC32_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_CRC32_MODIFIER)) +#define G_SCAN_CRC32_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_CRC32_MODIFIER, GScanCrc32ModifierClass)) +#define G_IS_SCAN_CRC32_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_CRC32_MODIFIER)) +#define G_SCAN_CRC32_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_CRC32_MODIFIER, GScanCrc32ModifierClass)) + + +/* Transormation en empreinte d'API crc32 (instance) */ +typedef GApiHashModifier GScanCrc32Modifier; + +/* Transormation en empreinte d'API crc32 (classe) */ +typedef GApiHashModifierClass GScanCrc32ModifierClass; + + +/* Indique le type défini pour une transormation en empreinte crc32. */ +GType g_scan_crc32_modifier_get_type(void); + +/* Construit un modificateur livrant des empreintes crc32. */ +GScanTokenModifier *g_scan_crc32_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CLASSICS_CRC32_H */ diff --git a/plugins/apihashing/classics/djb2.c b/plugins/apihashing/classics/djb2.c new file mode 100644 index 0000000..524218f --- /dev/null +++ b/plugins/apihashing/classics/djb2.c @@ -0,0 +1,323 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * djb2.c - transormation en empreinte d'API djb2 + * + * 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 "djb2.h" + + +#include <malloc.h> +#include <string.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en empreintes djb2. */ +static void g_scan_djb2_modifier_class_init(GScanDjb2ModifierClass *klass); + +/* Initialise une instance de transmission en empreinte djb2. */ +static void g_scan_djb2_modifier_init(GScanDjb2Modifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_djb2_modifier_dispose(GScanDjb2Modifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_djb2_modifier_finalize(GScanDjb2Modifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_djb2_modifier_get_name(const GScanDjb2Modifier *); + +/* Calcule l'empreinte djb2 d'un motif de recherche. */ +static uint32_t compute_djb2(const sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_djb2_modifier_transform(const GScanDjb2Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_djb2_modifier_get_path(const GScanDjb2Modifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en encodage Djb2. */ +G_DEFINE_TYPE(GScanDjb2Modifier, g_scan_djb2_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en empreintes djb2. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_djb2_modifier_class_init(GScanDjb2ModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_djb2_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_djb2_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_djb2_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_djb2_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_djb2_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en empreinte djb2. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_djb2_modifier_init(GScanDjb2Modifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_djb2_modifier_dispose(GScanDjb2Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_djb2_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_djb2_modifier_finalize(GScanDjb2Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_djb2_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur livrant des empreintes djb2. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_djb2_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_DJB2_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_djb2_modifier_get_name(const GScanDjb2Modifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("djb2"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : src = séquence d'octets à traiter. * +* * +* Description : Calcule l'empreinte djb2 d'un motif de recherche. * +* * +* Retour : Valeur entière de l'empreinte déterminée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static uint32_t compute_djb2(const sized_binary_t *src) +{ + uint32_t result; /* Valeur à retourner */ + size_t i; /* Boucle de parcours */ + + result = 0x1505; /* 5381 */ + + for (i = 0; i < src->len; i++) + result = ((result << 5) + result) + src->data[i]; /* hash * 33 + c */ + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_djb2_modifier_transform(const GScanDjb2Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + uint32_t hash; /* Valeur d'empreinte calculée */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + hash = compute_djb2(_src); + + binary->data = malloc(sizeof(hash) * sizeof(bin_t)); + binary->len = sizeof(hash); + + memcpy(binary->data, &hash, sizeof(hash)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_djb2_modifier_get_path(const GScanDjb2Modifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("djb2"); + + return result; + +} diff --git a/plugins/apihashing/classics/djb2.h b/plugins/apihashing/classics/djb2.h new file mode 100644 index 0000000..04df1df --- /dev/null +++ b/plugins/apihashing/classics/djb2.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * djb2.h - prototypes pour la transormation en empreinte d'API djb2 + * + * 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 _PLUGINS_APIHASHING_CLASSICS_DJB2_H +#define _PLUGINS_APIHASHING_CLASSICS_DJB2_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_DJB2_MODIFIER g_scan_djb2_modifier_get_type() +#define G_SCAN_DJB2_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_DJB2_MODIFIER, GScanDjb2Modifier)) +#define G_IS_SCAN_DJB2_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_DJB2_MODIFIER)) +#define G_SCAN_DJB2_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_DJB2_MODIFIER, GScanDjb2ModifierClass)) +#define G_IS_SCAN_DJB2_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_DJB2_MODIFIER)) +#define G_SCAN_DJB2_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_DJB2_MODIFIER, GScanDjb2ModifierClass)) + + +/* Transormation en empreinte d'API DJB2 (instance) */ +typedef GApiHashModifier GScanDjb2Modifier; + +/* Transormation en empreinte d'API DJB2 (classe) */ +typedef GApiHashModifierClass GScanDjb2ModifierClass; + + +/* Indique le type défini pour une transormation en empreinte djb2. */ +GType g_scan_djb2_modifier_get_type(void); + +/* Construit un modificateur livrant des empreintes djb2. */ +GScanTokenModifier *g_scan_djb2_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CLASSICS_DJB2_H */ diff --git a/plugins/apihashing/classics/ror13.c b/plugins/apihashing/classics/ror13.c new file mode 100644 index 0000000..e557804 --- /dev/null +++ b/plugins/apihashing/classics/ror13.c @@ -0,0 +1,323 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * ror13.c - transormation en empreinte d'API ror13 + * + * 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 "ror13.h" + + +#include <malloc.h> +#include <string.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en empreintes ror13. */ +static void g_scan_ror13_modifier_class_init(GScanRor13ModifierClass *klass); + +/* Initialise une instance de transmission en empreinte ror13. */ +static void g_scan_ror13_modifier_init(GScanRor13Modifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_ror13_modifier_dispose(GScanRor13Modifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_ror13_modifier_finalize(GScanRor13Modifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_ror13_modifier_get_name(const GScanRor13Modifier *); + +/* Calcule l'empreinte ror13 d'un motif de recherche. */ +static uint32_t compute_ror13(const sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_ror13_modifier_transform(const GScanRor13Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_ror13_modifier_get_path(const GScanRor13Modifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte ror13. */ +G_DEFINE_TYPE(GScanRor13Modifier, g_scan_ror13_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en empreintes ror13. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_ror13_modifier_class_init(GScanRor13ModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_ror13_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_ror13_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_ror13_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_ror13_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_ror13_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en empreinte ror13. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_ror13_modifier_init(GScanRor13Modifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_ror13_modifier_dispose(GScanRor13Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_ror13_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_ror13_modifier_finalize(GScanRor13Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_ror13_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur livrant des empreintes ror13. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_ror13_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_ROR13_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_ror13_modifier_get_name(const GScanRor13Modifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("ror13"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : src = séquence d'octets à traiter. * +* * +* Description : Calcule l'empreinte ror13 d'un motif de recherche. * +* * +* Retour : Valeur entière de l'empreinte déterminée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static uint32_t compute_ror13(const sized_binary_t *src) +{ + uint32_t result; /* Valeur à retourner */ + size_t i; /* Boucle de parcours */ + + result = 0; + + for (i = 0; i < src->len; i++) + result = src->data[i] + ((result << 19) | (result >> 13)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_ror13_modifier_transform(const GScanRor13Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + uint32_t hash; /* Valeur d'empreinte calculée */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + hash = compute_ror13(_src); + + binary->data = malloc(sizeof(hash) * sizeof(bin_t)); + binary->len = sizeof(hash); + + memcpy(binary->data, &hash, sizeof(hash)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_ror13_modifier_get_path(const GScanRor13Modifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("ror13"); + + return result; + +} diff --git a/plugins/apihashing/classics/ror13.h b/plugins/apihashing/classics/ror13.h new file mode 100644 index 0000000..43480bd --- /dev/null +++ b/plugins/apihashing/classics/ror13.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * ror13.h - prototypes pour la transormation en empreinte d'API ror13 + * + * 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 _PLUGINS_APIHASHING_CLASSICS_ROR13_H +#define _PLUGINS_APIHASHING_CLASSICS_ROR13_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_ROR13_MODIFIER g_scan_ror13_modifier_get_type() +#define G_SCAN_ROR13_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ROR13_MODIFIER, GScanRor13Modifier)) +#define G_IS_SCAN_ROR13_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ROR13_MODIFIER)) +#define G_SCAN_ROR13_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ROR13_MODIFIER, GScanRor13ModifierClass)) +#define G_IS_SCAN_ROR13_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ROR13_MODIFIER)) +#define G_SCAN_ROR13_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ROR13_MODIFIER, GScanRor13ModifierClass)) + + +/* Transormation en empreinte d'API ror13 (instance) */ +typedef GApiHashModifier GScanRor13Modifier; + +/* Transormation en empreinte d'API ror13 (classe) */ +typedef GApiHashModifierClass GScanRor13ModifierClass; + + +/* Indique le type défini pour une transormation en empreinte ror13. */ +GType g_scan_ror13_modifier_get_type(void); + +/* Construit un modificateur livrant des empreintes ror13. */ +GScanTokenModifier *g_scan_ror13_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CLASSICS_ROR13_H */ diff --git a/plugins/apihashing/core.c b/plugins/apihashing/core.c new file mode 100644 index 0000000..a74a637 --- /dev/null +++ b/plugins/apihashing/core.c @@ -0,0 +1,110 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.c - prototypes pour le calcul d'encodages + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "core.h" + + +#include <analysis/scan/core.h> +#include <plugins/self.h> + + +#ifdef INCLUDE_PYTHON3_BINDINGS +# include "python/module.h" +# include "python/classics/module.h" +#endif +#include "classics/crc32.h" +#include "classics/djb2.h" +#include "classics/ror13.h" +#include "custom/add1505-shl5.h" +#include "custom/enigma-murmur.h" +#include "custom/imul21-add.h" +#include "custom/imul83-add.h" +#include "custom/sll1-add-hash32.h" +#include "custom/sub-index1.h" +#include "custom/sub42.h" + + +#ifdef INCLUDE_PYTHON3_BINDINGS_ +# define PG_REQ RL("PyChrysalide") +#else +# define PG_REQ NO_REQ +#endif + + + +DEFINE_CHRYSALIDE_PLUGIN("ApiHashing", "API hash computing as ROST modifiers", + PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/formats"), + PG_REQ, AL(PGA_PLUGIN_INIT)); + + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* * +* Description : Prend acte du chargement du greffon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) +{ + bool result; /* Bilan à retourner */ + + result = true; + +#define REGISTER_SCAN_MODIFIER(m) \ + ({ \ + GScanTokenModifier *__mod; \ + bool __status; \ + __mod = m; \ + __status = register_scan_token_modifier(__mod); \ + g_object_unref(G_OBJECT(__mod)); \ + __status; \ + }) + + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_crc32_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_djb2_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_ror13_modifier_new()); + + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_add1505_shl5_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_enigma_murmur_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_imul21_add_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_imul83_add_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_sll1_add_hash32_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_sub42_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_sub_index1_modifier_new()); + +#ifdef INCLUDE_PYTHON3_BINDINGS + + if (result) result = add_apihashing_module_to_python_module(); + if (result) result = register_apihashing_classics_modifiers(); + +#endif + + return result; + +} diff --git a/plugins/apihashing/core.h b/plugins/apihashing/core.h new file mode 100644 index 0000000..75a6e73 --- /dev/null +++ b/plugins/apihashing/core.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.h - prototypes pour le calcul d'encodages + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ENCODINGS_CORE_H +#define _PLUGINS_ENCODINGS_CORE_H + + +#include <plugins/plugin.h> +#include <plugins/plugin-int.h> + + + +/* Prend acte du chargement du greffon. */ +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *); + + + +#endif /* _PLUGINS_ENCODINGS_CORE_H */ diff --git a/plugins/apihashing/custom/Makefile.am b/plugins/apihashing/custom/Makefile.am new file mode 100644 index 0000000..026addc --- /dev/null +++ b/plugins/apihashing/custom/Makefile.am @@ -0,0 +1,18 @@ + +noinst_LTLIBRARIES = libapihashingcustom.la + +libapihashingcustom_la_SOURCES = \ + add1505-shl5.h add1505-shl5.c \ + enigma-murmur.h enigma-murmur.c \ + imul21-add.h imul21-add.c \ + imul83-add.h imul83-add.c \ + sll1-add-hash32.h sll1-add-hash32.c \ + sub-index1.h sub-index1.c \ + sub42.h sub42.c + +libapihashingcustom_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libapihashingcustom_la_SOURCES:%c=) diff --git a/plugins/apihashing/custom/add1505-shl5.c b/plugins/apihashing/custom/add1505-shl5.c new file mode 100644 index 0000000..db96cf1 --- /dev/null +++ b/plugins/apihashing/custom/add1505-shl5.c @@ -0,0 +1,325 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * add1505-shl5.c - transormation en empreinte d'API add1505-shl5 + * + * 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 "add1505-shl5.h" + + +#include <malloc.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en empreintes add1505-shl5. */ +static void g_scan_add1505_shl5_modifier_class_init(GScanAdd1505Shl5ModifierClass *); + +/* Initialise une instance de transmission en empreinte add1505-shl5. */ +static void g_scan_add1505_shl5_modifier_init(GScanAdd1505Shl5Modifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_add1505_shl5_modifier_dispose(GScanAdd1505Shl5Modifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_add1505_shl5_modifier_finalize(GScanAdd1505Shl5Modifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_add1505_shl5_modifier_get_name(const GScanAdd1505Shl5Modifier *); + +/* Calcule l'empreinte add1505-shl5 d'un motif de recherche. */ +static uint32_t compute_add1505_shl5_hash32(const sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_add1505_shl5_modifier_transform(const GScanAdd1505Shl5Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_add1505_shl5_modifier_get_path(const GScanAdd1505Shl5Modifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte add1505-shl5. */ +G_DEFINE_TYPE(GScanAdd1505Shl5Modifier, g_scan_add1505_shl5_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en empreintes add1505-shl5. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_add1505_shl5_modifier_class_init(GScanAdd1505Shl5ModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_add1505_shl5_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_add1505_shl5_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_add1505_shl5_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_add1505_shl5_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_add1505_shl5_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en empreinte add1505-shl5. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_add1505_shl5_modifier_init(GScanAdd1505Shl5Modifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_add1505_shl5_modifier_dispose(GScanAdd1505Shl5Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_add1505_shl5_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_add1505_shl5_modifier_finalize(GScanAdd1505Shl5Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_add1505_shl5_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur livrant des empreintes add1505-shl5. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_add1505_shl5_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_add1505_shl5_modifier_get_name(const GScanAdd1505Shl5Modifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("add1505-shl5"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : src = séquence d'octets à traiter. * +* * +* Description : Calcule l'empreinte add1505-shl5 d'un motif de recherche. * +* * +* Retour : Valeur entière de l'empreinte déterminée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static uint32_t compute_add1505_shl5_hash32(const sized_binary_t *src) +{ + uint32_t result; /* Valeur à retourner */ + size_t i; /* Boucle de parcours */ + + result = 0x1505; + + for (i = 0; i < src->len; i++) + { + result += (result << 5); + result += src->data[i]; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_add1505_shl5_modifier_transform(const GScanAdd1505Shl5Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + uint32_t hash; /* Valeur d'empreinte calculée */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + hash = compute_add1505_shl5_hash32(_src); + + binary->data = malloc(sizeof(hash) * sizeof(bin_t)); + binary->len = sizeof(hash); + + memcpy(binary->data, &hash, sizeof(hash)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_add1505_shl5_modifier_get_path(const GScanAdd1505Shl5Modifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("add1505-shl5"); + + return result; + +} diff --git a/plugins/apihashing/custom/add1505-shl5.h b/plugins/apihashing/custom/add1505-shl5.h new file mode 100644 index 0000000..5e71987 --- /dev/null +++ b/plugins/apihashing/custom/add1505-shl5.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * add1505-shl5.h - prototypes pour la transormation en empreinte d'API add1505-shl5 + * + * 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 _PLUGINS_APIHASHING_CUSTOM_ADD1505_SHL5_H +#define _PLUGINS_APIHASHING_CUSTOM_ADD1505_SHL5_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_ADD1505_SHL5_MODIFIER g_scan_add1505_shl5_modifier_get_type() +#define G_SCAN_ADD1505_SHL5_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, GScanAdd1505Shl5Modifier)) +#define G_IS_SCAN_ADD1505_SHL5_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER)) +#define G_SCAN_ADD1505_SHL5_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, GScanAdd1505Shl5ModifierClass)) +#define G_IS_SCAN_ADD1505_SHL5_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER)) +#define G_SCAN_ADD1505_SHL5_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, GScanAdd1505Shl5ModifierClass)) + + +/* Transormation en empreinte d'API add1505-shl5 (instance) */ +typedef GApiHashModifier GScanAdd1505Shl5Modifier; + +/* Transormation en empreinte d'API add1505-shl5 (classe) */ +typedef GApiHashModifierClass GScanAdd1505Shl5ModifierClass; + + +/* Indique le type défini pour une transormation en empreinte add1505-shl5. */ +GType g_scan_add1505_shl5_modifier_get_type(void); + +/* Construit un modificateur livrant des empreintes add1505-shl5. */ +GScanTokenModifier *g_scan_add1505_shl5_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CUSTOM_ADD1505_SHL5_H */ diff --git a/plugins/apihashing/custom/enigma-murmur.c b/plugins/apihashing/custom/enigma-murmur.c new file mode 100644 index 0000000..cdc35b0 --- /dev/null +++ b/plugins/apihashing/custom/enigma-murmur.c @@ -0,0 +1,377 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * enigma-murmur.c - transormation en empreinte d'API enigma-murmur + * + * 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 "enigma-murmur.h" + + +#include <malloc.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des empreintes enigma-murmur. */ +static void g_scan_enigma_murmur_modifier_class_init(GScanEnigmaMurmurModifierClass *); + +/* Initialise une instance d'empreinte enigma-murmur. */ +static void g_scan_enigma_murmur_modifier_init(GScanEnigmaMurmurModifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_enigma_murmur_modifier_dispose(GScanEnigmaMurmurModifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_enigma_murmur_modifier_finalize(GScanEnigmaMurmurModifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_enigma_murmur_modifier_get_name(const GScanEnigmaMurmurModifier *); + +/* Calcule l'empreinte enigma-murmur d'un motif de recherche. */ +static uint32_t compute_enigma_murmur_hash32(const sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_enigma_murmur_modifier_transform(const GScanEnigmaMurmurModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_enigma_murmur_modifier_get_path(const GScanEnigmaMurmurModifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte enigma-murmur. */ +G_DEFINE_TYPE(GScanEnigmaMurmurModifier, g_scan_enigma_murmur_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des empreintes enigma-murmur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_enigma_murmur_modifier_class_init(GScanEnigmaMurmurModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_enigma_murmur_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_enigma_murmur_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_enigma_murmur_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_enigma_murmur_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_enigma_murmur_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance d'empreinte enigma-murmur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_enigma_murmur_modifier_init(GScanEnigmaMurmurModifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_enigma_murmur_modifier_dispose(GScanEnigmaMurmurModifier *modifier) +{ + G_OBJECT_CLASS(g_scan_enigma_murmur_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_enigma_murmur_modifier_finalize(GScanEnigmaMurmurModifier *modifier) +{ + G_OBJECT_CLASS(g_scan_enigma_murmur_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur pour des empreintes enigma-murmur. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_enigma_murmur_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_enigma_murmur_modifier_get_name(const GScanEnigmaMurmurModifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("enigma-murmur"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : src = séquence d'octets à traiter. * +* * +* Description : Calcule l'empreinte enigma-murmur d'un motif de recherche. * +* * +* Retour : Valeur entière de l'empreinte déterminée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static uint32_t compute_enigma_murmur_hash32(const sized_binary_t *src) +{ + uint32_t result; /* Valeur à retourner */ + size_t blk_count; /* Nombre de blocs présents */ + size_t i; /* Boucle de parcours */ + uint32_t k; /* Valeur pour un bloc */ + const bin_t *tail; /* Fragement de bloc final */ + + result = 0x4a03bdfa; + + /* Traitement par blocs de 4 octets */ + + blk_count = src->len / 4; + + for (i = 0; i < blk_count; i++) + { + k = ((uint32_t *)src->data)[i]; + + k *= 0xcc9e2d51; + k = (k << 15) | (k >> 17); + k *= 0x1b873593; + + result ^= k; + result = (result << 13) | (result >> 19); + result = result * 5 + 0xe6546b64; + + } + + /* Traitement du reste */ + + tail = src->static_bin_data + 4 * blk_count; + + k = 0; + + switch (src->len & 3) + { + case 3: + k ^= (tail[2] << 16); + + case 2: + k ^= (tail[1] << 8); + + case 1: + k ^= tail[0]; + k *= 0xcc9e2d51; + k = (k << 15) | (k >> (17)); + k *= 0x1b873593; + result ^= k; + break; + + case 0: + break; + + } + + /* Conclusion */ + + result ^= src->len; + + result ^= (result >> 16); + result *= 0x85ebca6b; + result ^= (result >> 13); + result *= 0xc2b2ae35; + result ^= (result >> 16); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_enigma_murmur_modifier_transform(const GScanEnigmaMurmurModifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + uint32_t hash; /* Valeur d'empreinte calculée */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + hash = compute_enigma_murmur_hash32(_src); + + binary->data = malloc(sizeof(hash) * sizeof(bin_t)); + binary->len = sizeof(hash); + + memcpy(binary->data, &hash, sizeof(hash)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_enigma_murmur_modifier_get_path(const GScanEnigmaMurmurModifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("enigma-murmur"); + + return result; + +} diff --git a/plugins/apihashing/custom/enigma-murmur.h b/plugins/apihashing/custom/enigma-murmur.h new file mode 100644 index 0000000..29ae803 --- /dev/null +++ b/plugins/apihashing/custom/enigma-murmur.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * enigma-murmur.h - prototypes pour la transormation en empreinte d'API enigma-murmur + * + * 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 _PLUGINS_APIHASHING_CUSTOM_ENIGMA_MURMUR_H +#define _PLUGINS_APIHASHING_CUSTOM_ENIGMA_MURMUR_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER g_scan_enigma_murmur_modifier_get_type() +#define G_SCAN_ENIGMA_MURMUR_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, GScanEnigmaMurmurModifier)) +#define G_IS_SCAN_ENIGMA_MURMUR_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER)) +#define G_SCAN_ENIGMA_MURMUR_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, GScanEnigmaMurmurModifierClass)) +#define G_IS_SCAN_ENIGMA_MURMUR_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER)) +#define G_SCAN_ENIGMA_MURMUR_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, GScanEnigmaMurmurModifierClass)) + + +/* Transormation en empreinte d'API enigma-murmur (instance) */ +typedef GApiHashModifier GScanEnigmaMurmurModifier; + +/* Transormation en empreinte d'API enigma-murmur (classe) */ +typedef GApiHashModifierClass GScanEnigmaMurmurModifierClass; + + +/* Indique le type défini pour une transormation en empreinte enigma-murmur. */ +GType g_scan_enigma_murmur_modifier_get_type(void); + +/* Construit un modificateur pour des empreintes enigma-murmur. */ +GScanTokenModifier *g_scan_enigma_murmur_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CUSTOM_ENIGMA_MURMUR_H */ diff --git a/plugins/apihashing/custom/imul21-add.c b/plugins/apihashing/custom/imul21-add.c new file mode 100644 index 0000000..2f71910 --- /dev/null +++ b/plugins/apihashing/custom/imul21-add.c @@ -0,0 +1,326 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * imul21-add.c - transormation en empreinte d'API imul21-add + * + * 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 "imul21-add.h" + + +#include <malloc.h> +#include <string.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en imul21-add. */ +static void g_scan_imul21_add_modifier_class_init(GScanImul21AddModifierClass *); + +/* Initialise une instance de transmission en imul21-add. */ +static void g_scan_imul21_add_modifier_init(GScanImul21AddModifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_imul21_add_modifier_dispose(GScanImul21AddModifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_imul21_add_modifier_finalize(GScanImul21AddModifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_imul21_add_modifier_get_name(const GScanImul21AddModifier *); + +/* Calcule l'empreinte imul21-add d'un motif de recherche. */ +static uint32_t compute_imul21_add(const sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_imul21_add_modifier_transform(const GScanImul21AddModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_imul21_add_modifier_get_path(const GScanImul21AddModifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte imul21-add. */ +G_DEFINE_TYPE(GScanImul21AddModifier, g_scan_imul21_add_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en imul21-add. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_imul21_add_modifier_class_init(GScanImul21AddModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_imul21_add_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_imul21_add_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_imul21_add_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_imul21_add_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_imul21_add_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en imul21-add. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_imul21_add_modifier_init(GScanImul21AddModifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_imul21_add_modifier_dispose(GScanImul21AddModifier *modifier) +{ + G_OBJECT_CLASS(g_scan_imul21_add_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_imul21_add_modifier_finalize(GScanImul21AddModifier *modifier) +{ + G_OBJECT_CLASS(g_scan_imul21_add_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur vers empreintes imul21-add. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_imul21_add_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_IMUL21_ADD_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_imul21_add_modifier_get_name(const GScanImul21AddModifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("imul21-add"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : src = séquence d'octets à traiter. * +* * +* Description : Calcule l'empreinte imul21-add d'un motif de recherche. * +* * +* Retour : Valeur entière de l'empreinte déterminée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static uint32_t compute_imul21_add(const sized_binary_t *src) +{ + uint32_t result; /* Valeur à retourner */ + size_t i; /* Boucle de parcours */ + + result = 0; + + for (i = 0; i < src->len; i++) + { + result *= 0x21; + result += src->data[i]; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_imul21_add_modifier_transform(const GScanImul21AddModifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + uint32_t hash; /* Valeur d'empreinte calculée */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + hash = compute_imul21_add(_src); + + binary->data = malloc(sizeof(hash) * sizeof(bin_t)); + binary->len = sizeof(hash); + + memcpy(binary->data, &hash, sizeof(hash)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_imul21_add_modifier_get_path(const GScanImul21AddModifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("imul21-add"); + + return result; + +} diff --git a/plugins/apihashing/custom/imul21-add.h b/plugins/apihashing/custom/imul21-add.h new file mode 100644 index 0000000..fcaa140 --- /dev/null +++ b/plugins/apihashing/custom/imul21-add.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * imul21-add.h - prototypes pour la transormation en empreinte d'API imul21-add + * + * 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 _PLUGINS_APIHASHING_CUSTOM_IMUL21_ADD_H +#define _PLUGINS_APIHASHING_CUSTOM_IMUL21_ADD_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_IMUL21_ADD_MODIFIER g_scan_imul21_add_modifier_get_type() +#define G_SCAN_IMUL21_ADD_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_IMUL21_ADD_MODIFIER, GScanImul21AddModifier)) +#define G_IS_SCAN_IMUL21_ADD_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_IMUL21_ADD_MODIFIER)) +#define G_SCAN_IMUL21_ADD_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_IMUL21_ADD_MODIFIER, GScanImul21AddModifierClass)) +#define G_IS_SCAN_IMUL21_ADD_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_IMUL21_ADD_MODIFIER)) +#define G_SCAN_IMUL21_ADD_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_IMUL21_ADD_MODIFIER, GScanImul21AddModifierClass)) + + +/* Transformation en empreinte d'API imul21-add (instance) */ +typedef GApiHashModifier GScanImul21AddModifier; + +/* Transformation en empreinte d'API imul21-add (classe) */ +typedef GApiHashModifierClass GScanImul21AddModifierClass; + + +/* Indique le type défini pour une transormation en empreinte imul21-add. */ +GType g_scan_imul21_add_modifier_get_type(void); + +/* Construit un modificateur vers empreintes imul21-add. */ +GScanTokenModifier *g_scan_imul21_add_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CUSTOM_IMUL21_ADD_H */ diff --git a/plugins/apihashing/custom/imul83-add.c b/plugins/apihashing/custom/imul83-add.c new file mode 100644 index 0000000..29f8cf5 --- /dev/null +++ b/plugins/apihashing/custom/imul83-add.c @@ -0,0 +1,326 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * imul83-add.c - transormation en empreinte d'API imul83-add + * + * 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 "imul83-add.h" + + +#include <malloc.h> +#include <string.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en imul83-add. */ +static void g_scan_imul83_add_modifier_class_init(GScanImul83AddModifierClass *); + +/* Initialise une instance de transmission en imul83-add. */ +static void g_scan_imul83_add_modifier_init(GScanImul83AddModifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_imul83_add_modifier_dispose(GScanImul83AddModifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_imul83_add_modifier_finalize(GScanImul83AddModifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_imul83_add_modifier_get_name(const GScanImul83AddModifier *); + +/* Calcule l'empreinte imul83-add d'un motif de recherche. */ +static uint32_t compute_imul83_add(const sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_imul83_add_modifier_transform(const GScanImul83AddModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_imul83_add_modifier_get_path(const GScanImul83AddModifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte imul83-add. */ +G_DEFINE_TYPE(GScanImul83AddModifier, g_scan_imul83_add_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en imul83-add. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_imul83_add_modifier_class_init(GScanImul83AddModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_imul83_add_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_imul83_add_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_imul83_add_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_imul83_add_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_imul83_add_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en imul83-add. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_imul83_add_modifier_init(GScanImul83AddModifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_imul83_add_modifier_dispose(GScanImul83AddModifier *modifier) +{ + G_OBJECT_CLASS(g_scan_imul83_add_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_imul83_add_modifier_finalize(GScanImul83AddModifier *modifier) +{ + G_OBJECT_CLASS(g_scan_imul83_add_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur vers empreintes imul83-add. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_imul83_add_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_IMUL83_ADD_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_imul83_add_modifier_get_name(const GScanImul83AddModifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("imul83-add"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : src = séquence d'octets à traiter. * +* * +* Description : Calcule l'empreinte imul83-add d'un motif de recherche. * +* * +* Retour : Valeur entière de l'empreinte déterminée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static uint32_t compute_imul83_add(const sized_binary_t *src) +{ + uint32_t result; /* Valeur à retourner */ + size_t i; /* Boucle de parcours */ + + result = 0; + + for (i = 0; i < src->len; i++) + { + result *= 0x83; + result += src->data[i]; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_imul83_add_modifier_transform(const GScanImul83AddModifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + uint32_t hash; /* Valeur d'empreinte calculée */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + hash = compute_imul83_add(_src); + + binary->data = malloc(sizeof(hash) * sizeof(bin_t)); + binary->len = sizeof(hash); + + memcpy(binary->data, &hash, sizeof(hash)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_imul83_add_modifier_get_path(const GScanImul83AddModifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("imul83-add"); + + return result; + +} diff --git a/plugins/apihashing/custom/imul83-add.h b/plugins/apihashing/custom/imul83-add.h new file mode 100644 index 0000000..7e376ee --- /dev/null +++ b/plugins/apihashing/custom/imul83-add.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * imul83-add.h - prototypes pour la transormation en empreinte d'API imul83-add + * + * 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 _PLUGINS_APIHASHING_CUSTOM_IMUL83_ADD_H +#define _PLUGINS_APIHASHING_CUSTOM_IMUL83_ADD_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_IMUL83_ADD_MODIFIER g_scan_imul83_add_modifier_get_type() +#define G_SCAN_IMUL83_ADD_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_IMUL83_ADD_MODIFIER, GScanImul83AddModifier)) +#define G_IS_SCAN_IMUL83_ADD_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_IMUL83_ADD_MODIFIER)) +#define G_SCAN_IMUL83_ADD_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_IMUL83_ADD_MODIFIER, GScanImul83AddModifierClass)) +#define G_IS_SCAN_IMUL83_ADD_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_IMUL83_ADD_MODIFIER)) +#define G_SCAN_IMUL83_ADD_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_IMUL83_ADD_MODIFIER, GScanImul83AddModifierClass)) + + +/* Transformation en empreinte d'API imul83-add (instance) */ +typedef GApiHashModifier GScanImul83AddModifier; + +/* Transformation en empreinte d'API imul83-add (classe) */ +typedef GApiHashModifierClass GScanImul83AddModifierClass; + + +/* Indique le type défini pour une transormation en empreinte imul83-add. */ +GType g_scan_imul83_add_modifier_get_type(void); + +/* Construit un modificateur vers empreintes imul83-add. */ +GScanTokenModifier *g_scan_imul83_add_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CUSTOM_IMUL83_ADD_H */ diff --git a/plugins/apihashing/custom/sll1-add-hash32.c b/plugins/apihashing/custom/sll1-add-hash32.c new file mode 100644 index 0000000..de00f81 --- /dev/null +++ b/plugins/apihashing/custom/sll1-add-hash32.c @@ -0,0 +1,326 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sll1-add-hash32.c - transormation en empreinte d'API sll1-add-hash32 + * + * 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 "sll1-add-hash32.h" + + +#include <malloc.h> +#include <string.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en sll1-add-hash32. */ +static void g_scan_sll1_add_hash32_modifier_class_init(GScanSll1AddHash32ModifierClass *klass); + +/* Initialise une instance de transmission en sll1-add-hash32. */ +static void g_scan_sll1_add_hash32_modifier_init(GScanSll1AddHash32Modifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_sll1_add_hash32_modifier_dispose(GScanSll1AddHash32Modifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_sll1_add_hash32_modifier_finalize(GScanSll1AddHash32Modifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_sll1_add_hash32_modifier_get_name(const GScanSll1AddHash32Modifier *); + +/* Calcule l'empreinte sll1-add-hash32 d'un motif de recherche. */ +static uint32_t compute_sll1_add_hash32(const sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_sll1_add_hash32_modifier_transform(const GScanSll1AddHash32Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_sll1_add_hash32_modifier_get_path(const GScanSll1AddHash32Modifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte sll1-add-hash32. */ +G_DEFINE_TYPE(GScanSll1AddHash32Modifier, g_scan_sll1_add_hash32_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en sll1-add-hash32. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sll1_add_hash32_modifier_class_init(GScanSll1AddHash32ModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sll1_add_hash32_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_sll1_add_hash32_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_sll1_add_hash32_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_sll1_add_hash32_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_sll1_add_hash32_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en sll1-add-hash32. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sll1_add_hash32_modifier_init(GScanSll1AddHash32Modifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sll1_add_hash32_modifier_dispose(GScanSll1AddHash32Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_sll1_add_hash32_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sll1_add_hash32_modifier_finalize(GScanSll1AddHash32Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_sll1_add_hash32_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur vers empreintes sll1-add-hash32. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_sll1_add_hash32_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_sll1_add_hash32_modifier_get_name(const GScanSll1AddHash32Modifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("sll1-add-hash32"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : src = séquence d'octets à traiter. * +* * +* Description : Calcule l'empreinte sll1-add-hash32 d'un motif de recherche. * +* * +* Retour : Valeur entière de l'empreinte déterminée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static uint32_t compute_sll1_add_hash32(const sized_binary_t *src) +{ + uint32_t result; /* Valeur à retourner */ + size_t i; /* Boucle de parcours */ + + result = 0; + + for (i = 0; i < src->len; i++) + { + result += (src->data[i] | 0x60); + result <<= 1; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_sll1_add_hash32_modifier_transform(const GScanSll1AddHash32Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + uint32_t hash; /* Valeur d'empreinte calculée */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + hash = compute_sll1_add_hash32(_src); + + binary->data = malloc(sizeof(hash) * sizeof(bin_t)); + binary->len = sizeof(hash); + + memcpy(binary->data, &hash, sizeof(hash)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_sll1_add_hash32_modifier_get_path(const GScanSll1AddHash32Modifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("sll1-add-hash32"); + + return result; + +} diff --git a/plugins/apihashing/custom/sll1-add-hash32.h b/plugins/apihashing/custom/sll1-add-hash32.h new file mode 100644 index 0000000..39abee2 --- /dev/null +++ b/plugins/apihashing/custom/sll1-add-hash32.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sll1-add-hash32.h - prototypes pour la transormation en empreinte d'API sll1-add-hash32 + * + * 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 _PLUGINS_APIHASHING_CUSTOM_SLL1_ADD_HASH32_H +#define _PLUGINS_APIHASHING_CUSTOM_SLL1_ADD_HASH32_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER g_scan_sll1_add_hash32_modifier_get_type() +#define G_SCAN_SLL1_ADD_HASH32_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, GScanSll1AddHash32Modifier)) +#define G_IS_SCAN_SLL1_ADD_HASH32_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER)) +#define G_SCAN_SLL1_ADD_HASH32_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, GScanSll1AddHash32ModifierClass)) +#define G_IS_SCAN_SLL1_ADD_HASH32_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER)) +#define G_SCAN_SLL1_ADD_HASH32_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, GScanSll1AddHash32ModifierClass)) + + +/* Transormation en empreinte d'API sll1_add_hash32 (instance) */ +typedef GApiHashModifier GScanSll1AddHash32Modifier; + +/* Transormation en empreinte d'API sll1_add_hash32 (classe) */ +typedef GApiHashModifierClass GScanSll1AddHash32ModifierClass; + + +/* Indique le type défini pour une transormation en empreinte sll1-add-hash32. */ +GType g_scan_sll1_add_hash32_modifier_get_type(void); + +/* Construit un modificateur vers empreintes sll1-add-hash32. */ +GScanTokenModifier *g_scan_sll1_add_hash32_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CUSTOM_SLL1_ADD_HASH32_H */ diff --git a/plugins/apihashing/custom/sub-index1.c b/plugins/apihashing/custom/sub-index1.c new file mode 100644 index 0000000..79eafd8 --- /dev/null +++ b/plugins/apihashing/custom/sub-index1.c @@ -0,0 +1,291 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sub-index1.c - transormation en empreinte d'API sub-index1 + * + * 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 "sub-index1.h" + + +#include <malloc.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en sub-index1. */ +static void g_scan_sub_index1_modifier_class_init(GScanSubIndex1ModifierClass *); + +/* Initialise une instance de transmission en sub-index1. */ +static void g_scan_sub_index1_modifier_init(GScanSubIndex1Modifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_sub_index1_modifier_dispose(GScanSubIndex1Modifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_sub_index1_modifier_finalize(GScanSubIndex1Modifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_sub_index1_modifier_get_name(const GScanSubIndex1Modifier *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_sub_index1_modifier_transform(const GScanSubIndex1Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_sub_index1_modifier_get_path(const GScanSubIndex1Modifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte sub-index1. */ +G_DEFINE_TYPE(GScanSubIndex1Modifier, g_scan_sub_index1_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en sub-index1. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sub_index1_modifier_class_init(GScanSubIndex1ModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sub_index1_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_sub_index1_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_sub_index1_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_sub_index1_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_sub_index1_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en sub-index1. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sub_index1_modifier_init(GScanSubIndex1Modifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sub_index1_modifier_dispose(GScanSubIndex1Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_sub_index1_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sub_index1_modifier_finalize(GScanSubIndex1Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_sub_index1_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur livrant des empreintes sub-index1. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_sub_index1_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_SUB_INDEX1_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_sub_index1_modifier_get_name(const GScanSubIndex1Modifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("sub-index1"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_sub_index1_modifier_transform(const GScanSubIndex1Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + size_t k; /* Boucle de parcours #2 */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + binary->len = _src->len; + binary->data = malloc(binary->len); + + for (k = 0; k < _src->len; k++) + binary->data[k] = _src->data[k] + k + 1; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_sub_index1_modifier_get_path(const GScanSubIndex1Modifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("sub-index1"); + + return result; + +} diff --git a/plugins/apihashing/custom/sub-index1.h b/plugins/apihashing/custom/sub-index1.h new file mode 100644 index 0000000..b2acc06 --- /dev/null +++ b/plugins/apihashing/custom/sub-index1.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sub-index1.h - prototypes pour la transormation en empreinte d'API sub-index1 + * + * 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 _PLUGINS_APIHASHING_CUSTOM_SUB_INDEX1_H +#define _PLUGINS_APIHASHING_CUSTOM_SUB_INDEX1_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_SUB_INDEX1_MODIFIER g_scan_sub_index1_modifier_get_type() +#define G_SCAN_SUB_INDEX1_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SUB_INDEX1_MODIFIER, GScanSubIndex1Modifier)) +#define G_IS_SCAN_SUB_INDEX1_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SUB_INDEX1_MODIFIER)) +#define G_SCAN_SUB_INDEX1_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SUB_INDEX1_MODIFIER, GScanSubIndex1ModifierClass)) +#define G_IS_SCAN_SUB_INDEX1_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SUB_INDEX1_MODIFIER)) +#define G_SCAN_SUB_INDEX1_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SUB_INDEX1_MODIFIER, GScanSubIndex1ModifierClass)) + + +/* Transormation en empreinte d'API sub-index1 (instance) */ +typedef GApiHashModifier GScanSubIndex1Modifier; + +/* Transormation en empreinte d'API sub-index1 (classe) */ +typedef GApiHashModifierClass GScanSubIndex1ModifierClass; + + +/* Indique le type défini pour une transormation en empreinte sub-index1. */ +GType g_scan_sub_index1_modifier_get_type(void); + +/* Construit un modificateur livrant des empreintes sub-index1. */ +GScanTokenModifier *g_scan_sub_index1_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CUSTOM_SUB_INDEX1_H */ diff --git a/plugins/apihashing/custom/sub42.c b/plugins/apihashing/custom/sub42.c new file mode 100644 index 0000000..95bd49d --- /dev/null +++ b/plugins/apihashing/custom/sub42.c @@ -0,0 +1,291 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sub42.c - transormation en empreinte d'API sub42 + * + * 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 "sub42.h" + + +#include <malloc.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en empreintes sub42. */ +static void g_scan_sub42_modifier_class_init(GScanSub42ModifierClass *); + +/* Initialise une instance de transmission en empreinte sub42. */ +static void g_scan_sub42_modifier_init(GScanSub42Modifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_sub42_modifier_dispose(GScanSub42Modifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_sub42_modifier_finalize(GScanSub42Modifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_sub42_modifier_get_name(const GScanSub42Modifier *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_sub42_modifier_transform(const GScanSub42Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_sub42_modifier_get_path(const GScanSub42Modifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en empreinte sub42. */ +G_DEFINE_TYPE(GScanSub42Modifier, g_scan_sub42_modifier, G_TYPE_API_HASH_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en empreintes sub42. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sub42_modifier_class_init(GScanSub42ModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_sub42_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_sub42_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_sub42_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_sub42_modifier_transform; + modifier->get_path = (get_modifier_path)g_scan_sub42_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en empreinte sub42. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sub42_modifier_init(GScanSub42Modifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sub42_modifier_dispose(GScanSub42Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_sub42_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_sub42_modifier_finalize(GScanSub42Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_sub42_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur livrant des empreintes sub42. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_sub42_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_SUB42_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_sub42_modifier_get_name(const GScanSub42Modifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("sub42"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_sub42_modifier_transform(const GScanSub42Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + size_t k; /* Boucle de parcours #2 */ + + result = true; + + *dcount = scount; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; + + binary->len = _src->len; + binary->data = malloc(binary->len); + + for (k = 0; k < _src->len; k++) + binary->data[k] = _src->data[k] + 0x42; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_sub42_modifier_get_path(const GScanSub42Modifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 0) + { + result = NULL; + (*index)--; + } + + else + result = strdup("sub42"); + + return result; + +} diff --git a/plugins/apihashing/custom/sub42.h b/plugins/apihashing/custom/sub42.h new file mode 100644 index 0000000..8a11741 --- /dev/null +++ b/plugins/apihashing/custom/sub42.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sub42.h - prototypes pour la transormation en empreinte d'API sub42 + * + * 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 _PLUGINS_APIHASHING_CUSTOM_SUB42_H +#define _PLUGINS_APIHASHING_CUSTOM_SUB42_H + + +#include <glib-object.h> + + +#include "../apihash.h" + + + +#define G_TYPE_SCAN_SUB42_MODIFIER g_scan_sub42_modifier_get_type() +#define G_SCAN_SUB42_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_SUB42_MODIFIER, GScanSub42Modifier)) +#define G_IS_SCAN_SUB42_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_SUB42_MODIFIER)) +#define G_SCAN_SUB42_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_SUB42_MODIFIER, GScanSub42ModifierClass)) +#define G_IS_SCAN_SUB42_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_SUB42_MODIFIER)) +#define G_SCAN_SUB42_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_SUB42_MODIFIER, GScanSub42ModifierClass)) + + +/* Transormation en empreinte d'API sub42 (instance) */ +typedef GApiHashModifier GScanSub42Modifier; + +/* Transormation en empreinte d'API sub42 (classe) */ +typedef GApiHashModifierClass GScanSub42ModifierClass; + + +/* Indique le type défini pour une transormation en empreinte sub42. */ +GType g_scan_sub42_modifier_get_type(void); + +/* Construit un modificateur livrant des empreintes sub42. */ +GScanTokenModifier *g_scan_sub42_modifier_new(void); + + + +#endif /* _PLUGINS_APIHASHING_CUSTOM_SUB42_H */ diff --git a/plugins/apihashing/python/Makefile.am b/plugins/apihashing/python/Makefile.am new file mode 100644 index 0000000..d94218d --- /dev/null +++ b/plugins/apihashing/python/Makefile.am @@ -0,0 +1,20 @@ + +noinst_LTLIBRARIES = libapihashingpython.la + +libapihashingpython_la_SOURCES = \ + apihash.h apihash.c \ + module.h module.c + +libapihashingpython_la_LIBADD = \ + classics/libapihashingpythonclassics.la + +libapihashingpython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libapihashingpython_la_SOURCES:%c=) + + +SUBDIRS = classics diff --git a/plugins/apihashing/python/apihash.c b/plugins/apihashing/python/apihash.c new file mode 100644 index 0000000..a3ae519 --- /dev/null +++ b/plugins/apihashing/python/apihash.c @@ -0,0 +1,212 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.c - équivalent Python du fichier "plugins/encodings/rost/base64.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "apihash.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/scan/patterns/modifier.h> + + +#include "../apihash.h" + + + +CREATE_DYN_CONSTRUCTOR(api_hash_modifier, G_TYPE_API_HASH_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_api_hash_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_api_hash_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define API_HASH_MODIFIER_DOC \ + "The *ApiHashModifier* class is the base object for all algorithms" \ + " involed in malwares and revolving API functions to call from" \ + " a hash value.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " ApiHashModifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_api_hash_modifier_type(void) +{ + static PyMethodDef py_api_hash_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_api_hash_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_api_hash_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.apihashing.ApiHashModifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = API_HASH_MODIFIER_DOC, + + .tp_methods = py_api_hash_modifier_methods, + .tp_getset = py_api_hash_modifier_getseters, + + .tp_init = py_api_hash_modifier_init, + .tp_new = py_api_hash_modifier_new, + + }; + + return &py_api_hash_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide.....ApiHashModifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_api_hash_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Python Base64Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_api_hash_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.apihashing"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_scan_token_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_API_HASH_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transformation par empreinte d'API. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_api_hash_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_api_hash_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to API hash modifier"); + break; + + case 1: + *((GApiHashModifier **)dst) = G_API_HASH_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/apihash.h b/plugins/apihashing/python/apihash.h new file mode 100644 index 0000000..5474d49 --- /dev/null +++ b/plugins/apihashing/python/apihash.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.h - équivalent Python du fichier "plugins/encodings/rost/base64.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H +#define _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_api_hash_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.apihashing.ApiHashModifier'. */ +bool ensure_python_api_hash_modifier_is_registered(void); + +/* Tente de convertir en transformation par empreinte d'API. */ +int convert_to_api_hash_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H */ diff --git a/plugins/apihashing/python/classics/Makefile.am b/plugins/apihashing/python/classics/Makefile.am new file mode 100644 index 0000000..316e13f --- /dev/null +++ b/plugins/apihashing/python/classics/Makefile.am @@ -0,0 +1,16 @@ + +noinst_LTLIBRARIES = libapihashingpythonclassics.la + +libapihashingpythonclassics_la_SOURCES = \ + crc32.h crc32.c \ + djb2.h djb2.c \ + module.h module.c \ + ror13.h ror13.c + +libapihashingpythonclassics_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libapihashingpythonclassics_la_SOURCES:%c=) diff --git a/plugins/apihashing/python/classics/crc32.c b/plugins/apihashing/python/classics/crc32.c new file mode 100644 index 0000000..d7c6f7c --- /dev/null +++ b/plugins/apihashing/python/classics/crc32.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * crc32.c - équivalent Python du fichier "plugins/apihashing/classics/crc32.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "crc32.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../classics/crc32.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_crc32_modifier, G_TYPE_SCAN_CRC32_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_crc32_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_crc32_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_CRC32_MODIFIER_DOC \ + "The *Crc32Modifier* class transforms a byte pattern into its" \ + " crc32 encoded form.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Crc32Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_crc32_modifier_type(void) +{ + static PyMethodDef py_scan_crc32_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_crc32_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_crc32_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Crc32Modifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_CRC32_MODIFIER_DOC, + + .tp_methods = py_scan_crc32_modifier_methods, + .tp_getset = py_scan_crc32_modifier_getseters, + + .tp_init = py_scan_crc32_modifier_init, + .tp_new = py_scan_crc32_modifier_new, + + }; + + return &py_scan_crc32_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....Crc32Modifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_crc32_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Python Crc32Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_crc32_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_CRC32_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transformation en empreinte crc32. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_crc32_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_crc32_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to crc32 modifier"); + break; + + case 1: + *((GScanCrc32Modifier **)dst) = G_SCAN_CRC32_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/classics/crc32.h b/plugins/apihashing/python/classics/crc32.h new file mode 100644 index 0000000..118a916 --- /dev/null +++ b/plugins/apihashing/python/classics/crc32.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * crc32.h - équivalent Python du fichier "plugins/apihashing/classics/crc32.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CLASSICS_CRC32_H +#define _PLUGINS_APIHASHING_PYTHON_CLASSICS_CRC32_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_crc32_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Crc32Modifier'. */ +bool ensure_python_scan_crc32_modifier_is_registered(void); + +/* Tente de convertir en transformation en empreinte crc32. */ +int convert_to_scan_crc32_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CLASSICS_CRC32_H */ diff --git a/plugins/apihashing/python/classics/djb2.c b/plugins/apihashing/python/classics/djb2.c new file mode 100644 index 0000000..f3d0844 --- /dev/null +++ b/plugins/apihashing/python/classics/djb2.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * djb2.c - équivalent Python du fichier "plugins/apihashing/classics/djb2.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "djb2.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../classics/djb2.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_djb2_modifier, G_TYPE_SCAN_DJB2_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_djb2_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_djb2_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_DJB2_MODIFIER_DOC \ + "The *Djb2Modifier* class transforms a byte pattern into its" \ + " djb2 encoded form.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Djb2Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_djb2_modifier_type(void) +{ + static PyMethodDef py_scan_djb2_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_djb2_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_djb2_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Djb2Modifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_DJB2_MODIFIER_DOC, + + .tp_methods = py_scan_djb2_modifier_methods, + .tp_getset = py_scan_djb2_modifier_getseters, + + .tp_init = py_scan_djb2_modifier_init, + .tp_new = py_scan_djb2_modifier_new, + + }; + + return &py_scan_djb2_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....Djb2Modifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_djb2_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Python Djb2Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_djb2_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_DJB2_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transformation en empreinte djb2. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_djb2_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_djb2_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to djb2 modifier"); + break; + + case 1: + *((GScanDjb2Modifier **)dst) = G_SCAN_DJB2_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/classics/djb2.h b/plugins/apihashing/python/classics/djb2.h new file mode 100644 index 0000000..b4086f8 --- /dev/null +++ b/plugins/apihashing/python/classics/djb2.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * djb2.h - équivalent Python du fichier "plugins/apihashing/classics/djb2.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CLASSICS_DJB2_H +#define _PLUGINS_APIHASHING_PYTHON_CLASSICS_DJB2_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_djb2_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Djb2Modifier'. */ +bool ensure_python_scan_djb2_modifier_is_registered(void); + +/* Tente de convertir en transformation en empreinte djb2. */ +int convert_to_scan_djb2_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CLASSICS_DJB2_H */ diff --git a/plugins/apihashing/python/classics/module.c b/plugins/apihashing/python/classics/module.c new file mode 100644 index 0000000..b00757a --- /dev/null +++ b/plugins/apihashing/python/classics/module.c @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire classics en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <assert.h> +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "crc32.h" +#include "djb2.h" +#include "ror13.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les modificateurs d'empreintes classiques pour ROST. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_apihashing_classics_modifiers(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_scan_crc32_modifier_is_registered(); + if (result) result = ensure_python_scan_djb2_modifier_is_registered(); + if (result) result = ensure_python_scan_ror13_modifier_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/apihashing/python/classics/module.h b/plugins/apihashing/python/classics/module.h new file mode 100644 index 0000000..10c817d --- /dev/null +++ b/plugins/apihashing/python/classics/module.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire classics en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CLASSICS_MODULE_H +#define _PLUGINS_APIHASHING_PYTHON_CLASSICS_MODULE_H + + +#include <stdbool.h> + + + +/* Intègre les modificateurs d'empreintes classiques pour ROST. */ +bool register_apihashing_classics_modifiers(void); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CLASSICS_MODULE_H */ diff --git a/plugins/apihashing/python/classics/ror13.c b/plugins/apihashing/python/classics/ror13.c new file mode 100644 index 0000000..429f7da --- /dev/null +++ b/plugins/apihashing/python/classics/ror13.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * ror13.c - équivalent Python du fichier "plugins/apihashing/classics/ror13.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "ror13.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../classics/ror13.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_ror13_modifier, G_TYPE_SCAN_ROR13_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_ror13_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_ror13_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_ROR13_MODIFIER_DOC \ + "The *Ror13Modifier* class transforms a byte pattern into its" \ + " ror13 encoded form.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Ror13Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_ror13_modifier_type(void) +{ + static PyMethodDef py_scan_ror13_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_ror13_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_ror13_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Ror13Modifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_ROR13_MODIFIER_DOC, + + .tp_methods = py_scan_ror13_modifier_methods, + .tp_getset = py_scan_ror13_modifier_getseters, + + .tp_init = py_scan_ror13_modifier_init, + .tp_new = py_scan_ror13_modifier_new, + + }; + + return &py_scan_ror13_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....Ror13Modifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_ror13_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Python Ror13Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_ror13_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_ROR13_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transformation en empreinte ror13. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_ror13_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_ror13_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ror13 modifier"); + break; + + case 1: + *((GScanRor13Modifier **)dst) = G_SCAN_ROR13_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/classics/ror13.h b/plugins/apihashing/python/classics/ror13.h new file mode 100644 index 0000000..021a516 --- /dev/null +++ b/plugins/apihashing/python/classics/ror13.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * ror13.h - équivalent Python du fichier "plugins/apihashing/classics/ror13.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CLASSICS_ROR13_H +#define _PLUGINS_APIHASHING_PYTHON_CLASSICS_ROR13_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_ror13_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Ror13Modifier'. */ +bool ensure_python_scan_ror13_modifier_is_registered(void); + +/* Tente de convertir en transformation en empreinte ror13. */ +int convert_to_scan_ror13_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CLASSICS_ROR13_H */ diff --git a/plugins/apihashing/python/custom/Makefile.am b/plugins/apihashing/python/custom/Makefile.am new file mode 100644 index 0000000..5fbb11f --- /dev/null +++ b/plugins/apihashing/python/custom/Makefile.am @@ -0,0 +1,20 @@ + +noinst_LTLIBRARIES = libapihashingpythoncustom.la + +libapihashingpythoncustom_la_SOURCES = \ + add1505-shl5.h add1505-shl5.c \ + enigma-murmur.h enigma-murmur.c \ + imul21-add.h imul21-add.c \ + imul83-add.h imul83-add.c \ + module.h module.c \ + sll1-add-hash32.h sll1-add-hash32.c \ + sub-index1.h sub-index1.c \ + sub42.h sub42.c + +libapihashingpythoncustom_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libapihashingpythoncustom_la_SOURCES:%c=) diff --git a/plugins/apihashing/python/custom/add1505-shl5.c b/plugins/apihashing/python/custom/add1505-shl5.c new file mode 100644 index 0000000..f70323c --- /dev/null +++ b/plugins/apihashing/python/custom/add1505-shl5.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * add1505-shl5.c - équivalent Python du fichier "plugins/apihashing/custom/add1505-shl5.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "add1505-shl5.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../custom/add1505-shl5.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_add1505_shl5_modifier, G_TYPE_SCAN_ADD1505_SHL5_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_add1505_shl5_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_add1505_shl5_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_ADD1505_SHL5_MODIFIER_DOC \ + "The *Add1505Shl5Modifier* class transforms a byte pattern" \ + " using a add1505-shl5 hash.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Add1505Shl5Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_add1505_shl5_modifier_type(void) +{ + static PyMethodDef py_scan_add1505_shl5_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_add1505_shl5_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_add1505_shl5_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Add1505Shl5Modifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_ADD1505_SHL5_MODIFIER_DOC, + + .tp_methods = py_scan_add1505_shl5_modifier_methods, + .tp_getset = py_scan_add1505_shl5_modifier_getseters, + + .tp_init = py_scan_add1505_shl5_modifier_init, + .tp_new = py_scan_add1505_shl5_modifier_new, + + }; + + return &py_scan_add1505_shl5_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet '...Add1505Shl5Modifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_add1505_shl5_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Add1505Shl5Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_add1505_shl5_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_ADD1505_SHL5_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en empreinte add1505-shl5. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_add1505_shl5_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_add1505_shl5_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to add1505-shl5 modifier"); + break; + + case 1: + *((GScanAdd1505Shl5Modifier **)dst) = G_SCAN_ADD1505_SHL5_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/custom/add1505-shl5.h b/plugins/apihashing/python/custom/add1505-shl5.h new file mode 100644 index 0000000..941d6ce --- /dev/null +++ b/plugins/apihashing/python/custom/add1505-shl5.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * add1505-shl5.h - équivalent Python du fichier "plugins/apihashing/custom/add1505-shl5.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_ADD1505_SHL5_H +#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_ADD1505_SHL5_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_add1505_shl5_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Add1505Shl5Modifier'. */ +bool ensure_python_scan_add1505_shl5_modifier_is_registered(void); + +/* Tente de convertir en empreinte add1505-shl5. */ +int convert_to_scan_add1505_shl5_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_ADD1505_SHL5_H */ diff --git a/plugins/apihashing/python/custom/enigma-murmur.c b/plugins/apihashing/python/custom/enigma-murmur.c new file mode 100644 index 0000000..f544f1a --- /dev/null +++ b/plugins/apihashing/python/custom/enigma-murmur.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * enigma-murmur.c - équivalent Python du fichier "plugins/apihashing/custom/enigma-murmur.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "enigma-murmur.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../custom/enigma-murmur.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_enigma_murmur_modifier, G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_enigma_murmur_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_enigma_murmur_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_ENIGMA_MURMUR_MODIFIER_DOC \ + "The *EnigmaMurmurModifier* class transforms a byte pattern" \ + " using a enigma-murmur hash.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " EnigmaMurmurModifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_enigma_murmur_modifier_type(void) +{ + static PyMethodDef py_scan_enigma_murmur_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_enigma_murmur_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_enigma_murmur_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.EnigmaMurmurModifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_ENIGMA_MURMUR_MODIFIER_DOC, + + .tp_methods = py_scan_enigma_murmur_modifier_methods, + .tp_getset = py_scan_enigma_murmur_modifier_getseters, + + .tp_init = py_scan_enigma_murmur_modifier_init, + .tp_new = py_scan_enigma_murmur_modifier_new, + + }; + + return &py_scan_enigma_murmur_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet '...EnigmaMurmurModifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_enigma_murmur_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type EnigmaMurmurModifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_enigma_murmur_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_ENIGMA_MURMUR_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en empreinte enigma-murmur. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_enigma_murmur_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_enigma_murmur_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to enigma-murmur modifier"); + break; + + case 1: + *((GScanEnigmaMurmurModifier **)dst) = G_SCAN_ENIGMA_MURMUR_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/custom/enigma-murmur.h b/plugins/apihashing/python/custom/enigma-murmur.h new file mode 100644 index 0000000..8435dae --- /dev/null +++ b/plugins/apihashing/python/custom/enigma-murmur.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * enigma-murmur.h - équivalent Python du fichier "plugins/apihashing/custom/enigma-murmur.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_ENIGMA_MURMUR_H +#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_ENIGMA_MURMUR_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_enigma_murmur_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.EnigmaMurmurModifier'. */ +bool ensure_python_scan_enigma_murmur_modifier_is_registered(void); + +/* Tente de convertir en empreinte enigma-murmur. */ +int convert_to_scan_enigma_murmur_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_ENIGMA_MURMUR_H */ diff --git a/plugins/apihashing/python/custom/imul21-add.c b/plugins/apihashing/python/custom/imul21-add.c new file mode 100644 index 0000000..aadc6cc --- /dev/null +++ b/plugins/apihashing/python/custom/imul21-add.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * imul21-add.c - équivalent Python du fichier "plugins/apihashing/custom/imul21-add.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "imul21-add.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../custom/imul21-add.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_imul21_add_modifier, G_TYPE_SCAN_IMUL21_ADD_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_imul21_add_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_imul21_add_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_IMUL21_ADD_MODIFIER_DOC \ + "The *Sll1AddHash32Modifier* class transforms a byte pattern" \ + " using a variation of the sll1 algorithm.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Sll1AddHash32Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_imul21_add_modifier_type(void) +{ + static PyMethodDef py_scan_imul21_add_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_imul21_add_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_imul21_add_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Imul21AddModifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_IMUL21_ADD_MODIFIER_DOC, + + .tp_methods = py_scan_imul21_add_modifier_methods, + .tp_getset = py_scan_imul21_add_modifier_getseters, + + .tp_init = py_scan_imul21_add_modifier_init, + .tp_new = py_scan_imul21_add_modifier_new, + + }; + + return &py_scan_imul21_add_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet '...Imul21AddModifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_imul21_add_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Sll1AddHash32Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_imul21_add_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_IMUL21_ADD_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en empreinte imul21-add. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_imul21_add_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_imul21_add_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to imul21-add modifier"); + break; + + case 1: + *((GScanImul21AddModifier **)dst) = G_SCAN_IMUL21_ADD_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/custom/imul21-add.h b/plugins/apihashing/python/custom/imul21-add.h new file mode 100644 index 0000000..3fcc053 --- /dev/null +++ b/plugins/apihashing/python/custom/imul21-add.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * imul21-add.h - équivalent Python du fichier "plugins/apihashing/custom/imul21-add.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL21_ADD_H +#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL21_ADD_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_imul21_add_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Imul21AddModifier'. */ +bool ensure_python_scan_imul21_add_modifier_is_registered(void); + +/* Tente de convertir en empreinte imul21-add. */ +int convert_to_scan_imul21_add_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL21_ADD_H */ diff --git a/plugins/apihashing/python/custom/imul83-add.c b/plugins/apihashing/python/custom/imul83-add.c new file mode 100644 index 0000000..5e2d929 --- /dev/null +++ b/plugins/apihashing/python/custom/imul83-add.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * imul83-add.c - équivalent Python du fichier "plugins/apihashing/custom/imul83-add.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "imul83-add.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../custom/imul83-add.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_imul83_add_modifier, G_TYPE_SCAN_IMUL83_ADD_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_imul83_add_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_imul83_add_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_IMUL83_ADD_MODIFIER_DOC \ + "The *Sll1AddHash32Modifier* class transforms a byte pattern" \ + " using a variation of the sll1 algorithm.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Sll1AddHash32Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_imul83_add_modifier_type(void) +{ + static PyMethodDef py_scan_imul83_add_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_imul83_add_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_imul83_add_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Imul83AddModifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_IMUL83_ADD_MODIFIER_DOC, + + .tp_methods = py_scan_imul83_add_modifier_methods, + .tp_getset = py_scan_imul83_add_modifier_getseters, + + .tp_init = py_scan_imul83_add_modifier_init, + .tp_new = py_scan_imul83_add_modifier_new, + + }; + + return &py_scan_imul83_add_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet '...Imul83AddModifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_imul83_add_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Sll1AddHash32Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_imul83_add_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_IMUL83_ADD_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en empreinte imul83-add. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_imul83_add_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_imul83_add_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to imul83-add modifier"); + break; + + case 1: + *((GScanImul83AddModifier **)dst) = G_SCAN_IMUL83_ADD_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/custom/imul83-add.h b/plugins/apihashing/python/custom/imul83-add.h new file mode 100644 index 0000000..fd05136 --- /dev/null +++ b/plugins/apihashing/python/custom/imul83-add.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * imul83-add.h - équivalent Python du fichier "plugins/apihashing/custom/imul83-add.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL83_ADD_H +#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL83_ADD_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_imul83_add_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Imul83AddModifier'. */ +bool ensure_python_scan_imul83_add_modifier_is_registered(void); + +/* Tente de convertir en empreinte imul83-add. */ +int convert_to_scan_imul83_add_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_IMUL83_ADD_H */ diff --git a/plugins/apihashing/python/custom/module.c b/plugins/apihashing/python/custom/module.c new file mode 100644 index 0000000..07107dd --- /dev/null +++ b/plugins/apihashing/python/custom/module.c @@ -0,0 +1,76 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire custom en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <assert.h> +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "add1505-shl5.h" +#include "enigma-murmur.h" +#include "imul21-add.h" +#include "imul83-add.h" +#include "sll1-add-hash32.h" +#include "sub-index1.h" +#include "sub42.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les modificateurs d'empreintes particulières à ROST. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_apihashing_custom_modifiers(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_scan_add1505_shl5_modifier_is_registered(); + if (result) result = ensure_python_scan_enigma_murmur_modifier_is_registered(); + if (result) result = ensure_python_scan_imul21_add_modifier_is_registered(); + if (result) result = ensure_python_scan_imul83_add_modifier_is_registered(); + if (result) result = ensure_python_scan_sll1_add_hash32_modifier_is_registered(); + if (result) result = ensure_python_scan_sub42_modifier_is_registered(); + if (result) result = ensure_python_scan_sub_index1_modifier_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/apihashing/python/custom/module.h b/plugins/apihashing/python/custom/module.h new file mode 100644 index 0000000..9073651 --- /dev/null +++ b/plugins/apihashing/python/custom/module.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire custom en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_MODULE_H +#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_MODULE_H + + +#include <stdbool.h> + + + +/* Intègre les modificateurs d'empreintes particulières à ROST. */ +bool register_apihashing_custom_modifiers(void); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_MODULE_H */ diff --git a/plugins/apihashing/python/custom/sll1-add-hash32.c b/plugins/apihashing/python/custom/sll1-add-hash32.c new file mode 100644 index 0000000..c63fcf3 --- /dev/null +++ b/plugins/apihashing/python/custom/sll1-add-hash32.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sll1-add-hash32.c - équivalent Python du fichier "plugins/apihashing/custom/sll1-add-hash32.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "sll1-add-hash32.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../custom/sll1-add-hash32.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_sll1_add_hash32_modifier, G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_sll1_add_hash32_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_sll1_add_hash32_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_SLL1_ADD_HASH32_MODIFIER_DOC \ + "The *Sll1AddHash32Modifier* class transforms a byte pattern" \ + " using a variation of the sll1 algorithm.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Sll1AddHash32Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_sll1_add_hash32_modifier_type(void) +{ + static PyMethodDef py_scan_sll1_add_hash32_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_sll1_add_hash32_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_sll1_add_hash32_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Sll1AddHash32Modifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_SLL1_ADD_HASH32_MODIFIER_DOC, + + .tp_methods = py_scan_sll1_add_hash32_modifier_methods, + .tp_getset = py_scan_sll1_add_hash32_modifier_getseters, + + .tp_init = py_scan_sll1_add_hash32_modifier_init, + .tp_new = py_scan_sll1_add_hash32_modifier_new, + + }; + + return &py_scan_sll1_add_hash32_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet '...Sll1AddHash32Modifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_sll1_add_hash32_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Sll1AddHash32Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_sll1_add_hash32_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_SLL1_ADD_HASH32_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en empreinte sll1-add-hash32. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_sll1_add_hash32_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_sll1_add_hash32_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to sll1-add-hash32 modifier"); + break; + + case 1: + *((GScanSll1AddHash32Modifier **)dst) = G_SCAN_SLL1_ADD_HASH32_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/custom/sll1-add-hash32.h b/plugins/apihashing/python/custom/sll1-add-hash32.h new file mode 100644 index 0000000..bf11c34 --- /dev/null +++ b/plugins/apihashing/python/custom/sll1-add-hash32.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sll1-add-hash32.h - équivalent Python du fichier "plugins/apihashing/custom/sll1-add-hash32.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_SLL1_ADD_HASH32_H +#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_SLL1_ADD_HASH32_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_sll1_add_hash32_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Sll1AddHash32Modifier'. */ +bool ensure_python_scan_sll1_add_hash32_modifier_is_registered(void); + +/* Tente de convertir en empreinte sll1-add-hash32. */ +int convert_to_scan_sll1_add_hash32_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_SLL1_ADD_HASH32_H */ diff --git a/plugins/apihashing/python/custom/sub-index1.c b/plugins/apihashing/python/custom/sub-index1.c new file mode 100644 index 0000000..e5c1487 --- /dev/null +++ b/plugins/apihashing/python/custom/sub-index1.c @@ -0,0 +1,213 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sub-index1.c - équivalent Python du fichier "plugins/apihashing/custom/sub-index1.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "sub-index1.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../custom/sub-index1.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_sub_index1_modifier, G_TYPE_SCAN_SUB_INDEX1_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_sub_index1_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_sub_index1_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_SUB_INDEX1_MODIFIER_DOC \ + "The *SubIndex1Modifier* class produces the encrypted version" \ + " of a byte pattern where the index of a byte is added to its" \ + " value.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Sub-Index1Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_sub_index1_modifier_type(void) +{ + static PyMethodDef py_scan_sub_index1_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_sub_index1_modifier_getseters[] = { + + { NULL } + }; + + static PyTypeObject py_scan_sub_index1_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.SubIndex1Modifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_SUB_INDEX1_MODIFIER_DOC, + + .tp_methods = py_scan_sub_index1_modifier_methods, + .tp_getset = py_scan_sub_index1_modifier_getseters, + + .tp_init = py_scan_sub_index1_modifier_init, + .tp_new = py_scan_sub_index1_modifier_new, + + }; + + return &py_scan_sub_index1_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....SubIndex1Modifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_sub_index1_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Python Sub-Index1Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_sub_index1_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_SUB_INDEX1_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transformation en empreinte sub-index1.* +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_sub_index1_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_sub_index1_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to sub-index1 modifier"); + break; + + case 1: + *((GScanSubIndex1Modifier **)dst) = G_SCAN_SUB_INDEX1_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/custom/sub-index1.h b/plugins/apihashing/python/custom/sub-index1.h new file mode 100644 index 0000000..65186f3 --- /dev/null +++ b/plugins/apihashing/python/custom/sub-index1.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sub-index1.h - équivalent Python du fichier "plugins/apihashing/custom/sub-index1.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB_INDEX1_H +#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB_INDEX1_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_sub_index1_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.SubIndex1Modifier'. */ +bool ensure_python_scan_sub_index1_modifier_is_registered(void); + +/* Tente de convertir en transformation en empreinte sub-index1. */ +int convert_to_scan_sub_index1_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB_INDEX1_H */ diff --git a/plugins/apihashing/python/custom/sub42.c b/plugins/apihashing/python/custom/sub42.c new file mode 100644 index 0000000..238496d --- /dev/null +++ b/plugins/apihashing/python/custom/sub42.c @@ -0,0 +1,212 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sub42.c - équivalent Python du fichier "plugins/apihashing/custom/sub42.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "sub42.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../apihash.h" +#include "../../custom/sub42.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_sub42_modifier, G_TYPE_SCAN_SUB42_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_sub42_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_sub42_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_SUB42_MODIFIER_DOC \ + "The *Sub42Modifier* class produces the encrypted version of a" \ + " byte pattern where 0x42 is added to each byte.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Sub42Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_sub42_modifier_type(void) +{ + static PyMethodDef py_scan_sub42_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_sub42_modifier_getseters[] = { + + { NULL } + }; + + static PyTypeObject py_scan_sub42_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Sub42Modifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_SUB42_MODIFIER_DOC, + + .tp_methods = py_scan_sub42_modifier_methods, + .tp_getset = py_scan_sub42_modifier_getseters, + + .tp_init = py_scan_sub42_modifier_init, + .tp_new = py_scan_sub42_modifier_new, + + }; + + return &py_scan_sub42_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....Sub42Modifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_sub42_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Python Sub42Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_sub42_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_api_hash_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_SUB42_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transformation en empreinte sub42. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_sub42_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_sub42_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to sub42 modifier"); + break; + + case 1: + *((GScanSub42Modifier **)dst) = G_SCAN_SUB42_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/apihashing/python/custom/sub42.h b/plugins/apihashing/python/custom/sub42.h new file mode 100644 index 0000000..ce3660a --- /dev/null +++ b/plugins/apihashing/python/custom/sub42.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sub42.h - équivalent Python du fichier "plugins/apihashing/custom/sub42.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB42_H +#define _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB42_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_sub42_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Sub42Modifier'. */ +bool ensure_python_scan_sub42_modifier_is_registered(void); + +/* Tente de convertir en transformation en empreinte sub42. */ +int convert_to_scan_sub42_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_CUSTOM_SUB42_H */ diff --git a/plugins/apihashing/python/module.c b/plugins/apihashing/python/module.c new file mode 100644 index 0000000..588a0d8 --- /dev/null +++ b/plugins/apihashing/python/module.c @@ -0,0 +1,87 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire apihashing en tant que module + * + * Copyright (C) 2020 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <assert.h> +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "apihash.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Ajoute le module 'plugins.apihashing' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_apihashing_module_to_python_module(void) +{ + bool result; /* Bilan à retourner */ + PyObject *super; /* Module à compléter */ + PyObject *module; /* Sous-module mis en place */ + +#define PYCHRYSALIDE_PLUGINS_APIHASHING_DOC \ + "apihashing is a module providing a few implementations" \ + " of algorithms used to resolve API functions by hash." + + static PyModuleDef py_chrysalide_apihashing_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.plugins.apihashing", + .m_doc = PYCHRYSALIDE_PLUGINS_APIHASHING_DOC, + + .m_size = -1, + + }; + + result = false; + + super = get_access_to_python_module("pychrysalide.plugins"); + + module = build_python_module(super, &py_chrysalide_apihashing_module); + + result = (module != NULL); + + if (result) result = ensure_python_api_hash_modifier_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/apihashing/python/module.h b/plugins/apihashing/python/module.h new file mode 100644 index 0000000..fe628b9 --- /dev/null +++ b/plugins/apihashing/python/module.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire apihashing en tant que module + * + * Copyright (C) 2020 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_APIHASHING_PYTHON_MODULE_H +#define _PLUGINS_APIHASHING_PYTHON_MODULE_H + + +#include <stdbool.h> + + + +/* Ajoute le module 'plugins.apihashing' au module Python. */ +bool add_apihashing_module_to_python_module(void); + + + +#endif /* _PLUGINS_APIHASHING_PYTHON_MODULE_H */ diff --git a/plugins/dalvik/context.c b/plugins/dalvik/context.c index b08678c..9cf878b 100644 --- a/plugins/dalvik/context.c +++ b/plugins/dalvik/context.c @@ -373,7 +373,7 @@ bool g_dalvik_context_register_array_data_padding(GDalvikContext *ctx, const vmp * * ******************************************************************************/ -GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, const GBinContent *content, vmpa2t *pos) +GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, GBinContent *content, vmpa2t *pos) { GArchInstruction *result; /* Instruction à retourner */ raw_data_area *found; /* Zone de couverture trouvée */ @@ -390,7 +390,7 @@ GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *ctx, const GBinC if (found) { - restricted = g_restricted_content_new_ro(content, &found->range); + restricted = g_restricted_content_new(content, &found->range); length = get_mrange_length(&found->range); count = length / found->item_len; diff --git a/plugins/dalvik/context.h b/plugins/dalvik/context.h index bfa2757..f09cfa6 100644 --- a/plugins/dalvik/context.h +++ b/plugins/dalvik/context.h @@ -67,7 +67,7 @@ bool g_dalvik_context_register_array_data(GDalvikContext *, const vmpa2t *, uint bool g_dalvik_context_register_array_data_padding(GDalvikContext *, const vmpa2t *); /* Place une donnée en tant qu'instruction si besoin est. */ -GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *, const GBinContent *, vmpa2t *); +GArchInstruction *g_dalvik_context_get_raw_data(GDalvikContext *, GBinContent *, vmpa2t *); diff --git a/plugins/encodings/Makefile.am b/plugins/encodings/Makefile.am new file mode 100644 index 0000000..6dd71fb --- /dev/null +++ b/plugins/encodings/Makefile.am @@ -0,0 +1,64 @@ + +lib_LTLIBRARIES = libencodings.la + +libdir = $(pluginslibdir) + + +if BUILD_PYTHON_PACKAGE + +RUN_PATH = -Wl,-rpath,'$$ORIGIN/../chrysalide-libs:$$ORIGIN' + +else + +RUN_PATH = -Wl,-rpath,'$$ORIGIN' + +endif + +if BUILD_PYTHON3_BINDINGS + +PYTHON3_LIBADD = python/libencodingspython.la + +if BUILD_DISCARD_LOCAL + +if BUILD_PYTHON_PACKAGE +PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN/..' +else +PYTHON3_RUN_PATH = -Wl,-rpath,'$$ORIGIN' +endif + +else + +PYTHON3_RUN_PATH = -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs + +endif + +PYTHON3_LDFLAGS = $(PYTHON3_RUN_PATH) -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so + +PYTHON3_SUBDIRS = python + +endif + + +libencodings_la_SOURCES = \ + base64.h base64.c \ + core.h core.c + +libencodings_la_LIBADD = \ + $(PYTHON3_LIBADD) \ + rost/libencodingsrost.la + +libencodings_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + +libencodings_la_LDFLAGS = \ + -avoid-version \ + -L$(top_srcdir)/src/.libs -lchrysacore \ + -L$(top_srcdir)/plugins/pe/.libs -lpe \ + $(RUN_PATH) $(PYTHON3_LDFLAGS) + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libencodings_la_SOURCES:%c=) + + +SUBDIRS = $(PYTHON3_SUBDIRS) rost diff --git a/plugins/encodings/base64.c b/plugins/encodings/base64.c new file mode 100644 index 0000000..c749a87 --- /dev/null +++ b/plugins/encodings/base64.c @@ -0,0 +1,139 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.c - calculs d'encodages en base 64 + * + * Copyright (C) 2020 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "base64.h" + + + +/****************************************************************************** +* * +* Paramètres : input = données d'entrée à traiter. * +* output = données sortantes constituées. [OUT] * +* alphabet = alphabet d'encodage mis à disposition. * +* * +* Description : Procède à l'encodage d'un contenu en base 64. * +* * +* Retour : Bilan de l'opération : true en cas de réussite, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _base64_encode(const sized_binary_t *input, sized_string_t *output, const sized_string_t *alphabet) +{ + bool result; /* Bilan à retourner */ + const bin_t *src; /* Tête de lecture #1 */ + const bin_t *alpha; /* Tête de lecture #2 */ + bin_t *iter; /* Tête d'écriture */ + size_t i; /* Boucle de parcours */ + + result = (alphabet->len == 64); + if (!result) goto exit; + + /* Création du réceptacle */ + + output->len = input->len * 4 / 3; + + if (output->len % 4 != 0) + output->len += (4 - output->len % 4); + + output->data = malloc((output->len + 1) * sizeof(bin_t)); + + /* Encodage du corps du message */ + + src = input->static_bin_data; + alpha = alphabet->static_bin_data; + + iter = output->bin_data; + + if (input->len > 2) + for (i = 0; i < (input->len - 2); i += 3) + { + *iter++ = alpha[(src[i] >> 2) & 0x3f]; + + *iter++ = alpha[((src[i] & 0x03) << 4) | ((src[i + 1] & 0xf0) >> 4)]; + + *iter++ = alpha[((src[i + 1] & 0x0f) << 2) | ((src[i + 2] & 0xc0) >> 6)]; + + *iter++ = alpha[src[i + 2] & 0x3f]; + + } + else + i = 0; + + /* Bourrage final ? */ + + if (i < input->len) + { + *iter++ = alpha[(src[i] >> 2) & 0x3f]; + + if (i == (input->len - 1)) + { + *iter++ = alpha[((src[i] & 0x03) << 4)]; + *iter++ = '='; + } + else + { + *iter++ = alpha[((src[i] & 0x03) << 4) | ((src[i + 1] & 0xf0) >> 4)]; + *iter++ = alpha[((src[i + 1] & 0x0f) << 2)]; + } + + *iter++ = '='; + } + + *iter = 0x00; + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : input = données d'entrée à traiter. * +* output = données sortantes constituées. [OUT] * +* * +* Description : Procède à l'encodage par défaut d'un contenu en base 64. * +* * +* Retour : Bilan de l'opération : true en cas de réussite, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool base64_encode(const sized_binary_t *input, sized_string_t *output) +{ + bool result; /* Bilan à retourner */ + + const sized_string_t alphabet = { + .static_data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + .len = 64 + }; + + result = _base64_encode(input, output, &alphabet); + + return result; + +} diff --git a/plugins/encodings/base64.h b/plugins/encodings/base64.h new file mode 100644 index 0000000..64ddccd --- /dev/null +++ b/plugins/encodings/base64.h @@ -0,0 +1,43 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.h - prototypes pour les calculs d'encodages en base 64 + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ENCODINGS_BASE64_H +#define _PLUGINS_ENCODINGS_BASE64_H + + +#include <stdbool.h> + + +#include <common/szstr.h> + + + +/* Procède à l'encodage d'un contenu en base 64. */ +bool _base64_encode(const sized_binary_t *, sized_string_t *, const sized_string_t *); + +/* Procède à l'encodage par défaut d'un contenu en base 64. */ +bool base64_encode(const sized_binary_t *, sized_string_t *); + + + +#endif /* _PLUGINS_ENCODINGS_BASE64_H */ diff --git a/plugins/encodings/core.c b/plugins/encodings/core.c new file mode 100644 index 0000000..2ece208 --- /dev/null +++ b/plugins/encodings/core.c @@ -0,0 +1,89 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.c - prototypes pour le calcul d'encodages + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "core.h" + + +#include <analysis/scan/core.h> +#include <plugins/self.h> + + +#ifdef INCLUDE_PYTHON3_BINDINGS +# include "python/module.h" +# include "python/rost/module.h" +#endif +#include "rost/base64.h" + + +#ifdef INCLUDE_PYTHON3_BINDINGS_ +# define PG_REQ RL("PyChrysalide") +#else +# define PG_REQ NO_REQ +#endif + + + +DEFINE_CHRYSALIDE_PLUGIN("Encodings", "Special encoding methods for binaries", + PACKAGE_VERSION, CHRYSALIDE_WEBSITE("doc/formats"), + PG_REQ, AL(PGA_PLUGIN_INIT)); + + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* * +* Description : Prend acte du chargement du greffon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) +{ + bool result; /* Bilan à retourner */ + GScanTokenModifier *modifier; /* Modificateur à enregistrer */ + + modifier = g_scan_base64_modifier_new(); + + result = register_scan_token_modifier(modifier); + + g_object_unref(G_OBJECT(modifier)); + + if (!result) goto exit; + +#ifdef INCLUDE_PYTHON3_BINDINGS + + result = add_encodings_module_to_python_module(); + + if (result) + result = register_encodings_rost_modifiers(); +#endif + + exit: + + return result; + +} diff --git a/plugins/encodings/core.h b/plugins/encodings/core.h new file mode 100644 index 0000000..75a6e73 --- /dev/null +++ b/plugins/encodings/core.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.h - prototypes pour le calcul d'encodages + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ENCODINGS_CORE_H +#define _PLUGINS_ENCODINGS_CORE_H + + +#include <plugins/plugin.h> +#include <plugins/plugin-int.h> + + + +/* Prend acte du chargement du greffon. */ +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *); + + + +#endif /* _PLUGINS_ENCODINGS_CORE_H */ diff --git a/plugins/encodings/python/Makefile.am b/plugins/encodings/python/Makefile.am new file mode 100644 index 0000000..523a6f4 --- /dev/null +++ b/plugins/encodings/python/Makefile.am @@ -0,0 +1,21 @@ + +noinst_LTLIBRARIES = libencodingspython.la + +libencodingspython_la_SOURCES = \ + base64.h base64.c \ + module.h module.c + +libencodingspython_la_LIBADD = \ + rost/libencodingspythonrost.la + +libencodingspython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) \ + $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libencodingspython_la_SOURCES:%c=) + + +SUBDIRS = rost diff --git a/plugins/encodings/python/base64.c b/plugins/encodings/python/base64.c new file mode 100644 index 0000000..3bc84a2 --- /dev/null +++ b/plugins/encodings/python/base64.c @@ -0,0 +1,139 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.c - équivalent Python du fichier "plugins/encodings/base64.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "base64.h" + + +#include <pygobject.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "../base64.h" + + + +/* Procède à l'encodage d'un contenu en base 64. */ +static PyObject *py_encodings_base64_encode(PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* args = paramètre à récupérer pour le traitement. * +* * +* Description : Procède à l'encodage d'un contenu en base 64. * +* * +* Retour : None ou données sortantes constituées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_encodings_base64_encode(PyObject *self, PyObject *args) +{ + PyObject *result; /* Valeur à retourner */ + sized_string_t alphabet; /* Alphabet de traitement ? */ + Py_ssize_t alen; /* Taille de cet alphabet */ + sized_binary_t input; /* Données à traiter */ + Py_ssize_t ilen; /* Quantité de ces données */ + int ret; /* Bilan de lecture des args. */ + sized_string_t output; /* Données encodées à exporter */ + bool status; /* Bilan de l'opération */ + +#define ENCODINGS_BASE64_ENCODE_METHOD PYTHON_METHOD_DEF \ +( \ + base64_encode, "input, /, alphabet=None", \ + METH_VARARGS, py_encodings, \ + "Encode a given content using Base64.\n" \ + "\n" \ + "The *input* argument has to be provided as bytes. The optional" \ + " *alphabet* is expected to be a 64-byte array if defined.\n" \ + "\n" \ + "The returned value is bytes or *None* in case of error." \ +) + + result = NULL; + + alphabet.data = NULL; + alen = 0; + + ret = PyArg_ParseTuple(args, "s#|s#", &input.static_data, &ilen, &alphabet.static_data, &alen); + if (!ret) goto exit; + + alphabet.len = alen; + input.len = ilen; + + if (alphabet.len > 0) + status = _base64_encode(&input, &output, &alphabet); + else + status = base64_encode(&input, &output); + + if (status) + { + result = PyBytes_FromStringAndSize(output.data, output.len); + exit_szstr(&output); + } + else + { + result = Py_None; + Py_INCREF(result); + } + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : super = module dont la définition est à compléter. * +* * +* Description : Définit une extension du module 'encodings' à compléter. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool populate_encodings_module_with_base64(PyObject *super) +{ + bool result; /* Bilan à retourner */ + + static PyMethodDef py_base64_methods[] = { + ENCODINGS_BASE64_ENCODE_METHOD, + { NULL } + }; + + result = register_python_module_methods(super, py_base64_methods); + + return result; + +} diff --git a/plugins/encodings/python/base64.h b/plugins/encodings/python/base64.h new file mode 100644 index 0000000..1e08cf6 --- /dev/null +++ b/plugins/encodings/python/base64.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.h - équivalent Python du fichier "plugins/encodings/base64.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_ENCODINGS_PYTHON_BASE64_H +#define _PLUGINS_ENCODINGS_PYTHON_BASE64_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Définit une extension du module 'encodings' à compléter. */ +bool populate_encodings_module_with_base64(PyObject *); + + + +#endif /* _PLUGINS_ENCODINGS_PYTHON_BASE64_H */ diff --git a/plugins/encodings/python/module.c b/plugins/encodings/python/module.c new file mode 100644 index 0000000..454159b --- /dev/null +++ b/plugins/encodings/python/module.c @@ -0,0 +1,87 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire encodings en tant que module + * + * Copyright (C) 2020 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <assert.h> +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "base64.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Ajoute le module 'plugins.encodings' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_encodings_module_to_python_module(void) +{ + bool result; /* Bilan à retourner */ + PyObject *super; /* Module à compléter */ + PyObject *module; /* Sous-module mis en place */ + +#define PYCHRYSALIDE_PLUGINS_ENCODINGS_DOC \ + "encodings is a module providing a few implementations" \ + " of algorithms used to encode data." + + static PyModuleDef py_chrysalide_encodings_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.plugins.encodings", + .m_doc = PYCHRYSALIDE_PLUGINS_ENCODINGS_DOC, + + .m_size = -1, + + }; + + result = false; + + super = get_access_to_python_module("pychrysalide.plugins"); + + module = build_python_module(super, &py_chrysalide_encodings_module); + + result = (module != NULL); + + if (result) result = populate_encodings_module_with_base64(module); + + assert(result); + + return result; + +} diff --git a/plugins/encodings/python/module.h b/plugins/encodings/python/module.h new file mode 100644 index 0000000..e7dd812 --- /dev/null +++ b/plugins/encodings/python/module.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire encodings en tant que module + * + * Copyright (C) 2020 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_ENCODINGS_PYTHON_MODULE_H +#define _PLUGINS_ENCODINGS_PYTHON_MODULE_H + + +#include <stdbool.h> + + + +/* Ajoute le module 'plugins.encodings' au module Python. */ +bool add_encodings_module_to_python_module(void); + + + +#endif /* _PLUGINS_ENCODINGS_PYTHON_MODULE_H */ diff --git a/plugins/encodings/python/rost/Makefile.am b/plugins/encodings/python/rost/Makefile.am new file mode 100644 index 0000000..531fb26 --- /dev/null +++ b/plugins/encodings/python/rost/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libencodingspythonrost.la + +libencodingspythonrost_la_SOURCES = \ + base64.h base64.c \ + module.h module.c + +libencodingspythonrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) \ + $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libencodingspythonrost_la_SOURCES:%c=) diff --git a/plugins/encodings/python/rost/base64.c b/plugins/encodings/python/rost/base64.c new file mode 100644 index 0000000..57bba76 --- /dev/null +++ b/plugins/encodings/python/rost/base64.c @@ -0,0 +1,211 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.c - équivalent Python du fichier "plugins/encodings/rost/base64.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "base64.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/scan/patterns/modifier.h> + + +#include "../../rost/base64.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_base64_modifier, G_TYPE_SCAN_BASE64_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_base64_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_base64_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_BASE64_MODIFIER_DOC \ + "The *Base64Modifier* class transforms a byte pattern into its" \ + " base64 encoded form.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " Base64Modifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_base64_modifier_type(void) +{ + static PyMethodDef py_scan_base64_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_base64_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_base64_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.Base64Modifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_BASE64_MODIFIER_DOC, + + .tp_methods = py_scan_base64_modifier_methods, + .tp_getset = py_scan_base64_modifier_getseters, + + .tp_init = py_scan_base64_modifier_init, + .tp_new = py_scan_base64_modifier_new, + + }; + + return &py_scan_base64_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....Base64Modifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_base64_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Python Base64Modifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_base64_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_scan_token_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_BASE64_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transformation par encodage en Base64. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_base64_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_base64_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Base64 modifier"); + break; + + case 1: + *((GScanBase64Modifier **)dst) = G_SCAN_BASE64_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/encodings/python/rost/base64.h b/plugins/encodings/python/rost/base64.h new file mode 100644 index 0000000..0ef0834 --- /dev/null +++ b/plugins/encodings/python/rost/base64.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.h - équivalent Python du fichier "plugins/encodings/rost/base64.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H +#define _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_base64_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.Base64Modifier'. */ +bool ensure_python_scan_base64_modifier_is_registered(void); + +/* Tente de convertir en transformation par encodage en Base64. */ +int convert_to_scan_base64_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_ENCODINGS_PYTHON_ROST_BASE64_H */ diff --git a/plugins/encodings/python/rost/module.c b/plugins/encodings/python/rost/module.c new file mode 100644 index 0000000..4812bb5 --- /dev/null +++ b/plugins/encodings/python/rost/module.c @@ -0,0 +1,64 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire rost en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <assert.h> +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "base64.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les modificateurs pour ROST. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_encodings_rost_modifiers(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_scan_base64_modifier_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/encodings/python/rost/module.h b/plugins/encodings/python/rost/module.h new file mode 100644 index 0000000..ba021cb --- /dev/null +++ b/plugins/encodings/python/rost/module.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire rost en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_ENCODINGS_PYTHON_ROST_MODULE_H +#define _PLUGINS_ENCODINGS_PYTHON_ROST_MODULE_H + + +#include <stdbool.h> + + + +/* Intègre les modificateurs pour ROST. */ +bool register_encodings_rost_modifiers(void); + + + +#endif /* _PLUGINS_ENCODINGS_PYTHON_ROST_MODULE_H */ diff --git a/plugins/encodings/rost/Makefile.am b/plugins/encodings/rost/Makefile.am new file mode 100644 index 0000000..efca690 --- /dev/null +++ b/plugins/encodings/rost/Makefile.am @@ -0,0 +1,12 @@ + +noinst_LTLIBRARIES = libencodingsrost.la + +libencodingsrost_la_SOURCES = \ + base64.h base64.c + +libencodingsrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libencodingsrost_la_SOURCES:%c=) diff --git a/plugins/encodings/rost/base64.c b/plugins/encodings/rost/base64.c new file mode 100644 index 0000000..adbb2fb --- /dev/null +++ b/plugins/encodings/rost/base64.c @@ -0,0 +1,555 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.c - transormation en encodage Base64 + * + * 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 "base64.h" + + +#include <assert.h> +#include <malloc.h> +#include <stdint.h> +#include <string.h> + + +#include <analysis/scan/patterns/modifier-int.h> + + +#include "../base64.h" + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions en encodage Base64. */ +static void g_scan_base64_modifier_class_init(GScanBase64ModifierClass *klass); + +/* Initialise une instance de transmission en encodage Base64. */ +static void g_scan_base64_modifier_init(GScanBase64Modifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_base64_modifier_dispose(GScanBase64Modifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_base64_modifier_finalize(GScanBase64Modifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_base64_modifier_get_name(const GScanBase64Modifier *); + +/* Finalise l'encoddage en Base64 d'un motif transformé. */ +static void strip_base64_modifier_output(const sized_binary_t *, const sized_binary_t *, size_t, sized_binary_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_base64_modifier_transform(const GScanBase64Modifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Détermine si un argument est bien toléré par un modificateur. */ +static bool g_scan_base64_modifier_can_handle_arg(const GScanBase64Modifier *, const modifier_arg_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_base64_modifier_transform_with_arg(const GScanBase64Modifier *, const sized_binary_t *, size_t, const modifier_arg_t *, sized_binary_t **, size_t *); + +/* Retrouve l'origine d'une correspondance à partir d'un indice. */ +static char *g_scan_base64_modifier_get_path(const GScanBase64Modifier *, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation en encodage Base64. */ +G_DEFINE_TYPE(GScanBase64Modifier, g_scan_base64_modifier, G_TYPE_SCAN_TOKEN_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions en encodage Base64. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_base64_modifier_class_init(GScanBase64ModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_base64_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_base64_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_base64_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_base64_modifier_transform; + modifier->can_handle = (can_token_modifier_handle_arg)g_scan_base64_modifier_can_handle_arg; + modifier->transform_with = (transform_scan_token_with_fc)g_scan_base64_modifier_transform_with_arg; + modifier->get_path = (get_modifier_path)g_scan_base64_modifier_get_path; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission en encodage Base64. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_base64_modifier_init(GScanBase64Modifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_base64_modifier_dispose(GScanBase64Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_base64_modifier_parent_class)->dispose(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_base64_modifier_finalize(GScanBase64Modifier *modifier) +{ + G_OBJECT_CLASS(g_scan_base64_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur livrant des encodages en Base64. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_base64_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_BASE64_MODIFIER, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* * +* Description : Fournit le nom d'appel d'un modificateur pour motif. * +* * +* Retour : Désignation humaine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_base64_modifier_get_name(const GScanBase64Modifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("base64"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : input = contenu brut d'origine. * +* tmpput = encodage en Base64 intermédiaire obtenu. * +* skip = nombre de caractères initiaux à sauter. * +* output = encodage en Base64 final à conserver. * +* * +* Description : Finalise l'encoddage en Base64 d'un motif transformé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void strip_base64_modifier_output(const sized_binary_t *input, const sized_binary_t *tmpput, size_t skip, sized_binary_t *output) +{ + size_t keep; /* Nombre d'octets immuables */ + + keep = (input->len * 8) / 6; + + assert(keep >= skip); + + if (skip > 0) + skip++; + + keep -= skip; + + output->len = keep; + output->bin_data = malloc(keep * sizeof(bin_t)); + + memcpy(output->bin_data, tmpput->static_bin_data + skip, keep); + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_base64_modifier_transform(const GScanBase64Modifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + sized_binary_t tmp_in; /* Manipulation des variations */ + sized_binary_t tmp_out; /* Manipulation des variations */ + + result = true; + + *dcount = scount * 3; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount && result; i++) + { + _src = src + i; + + tmp_in.data = malloc((_src->len + 2) * sizeof(bin_t)); + + /** + * Explications sur la définition des modifications sur les + * encodages produits : https://www.leeholmes.com/searching-for-content-in-base-64-strings/ + */ + + /* Encodage premier */ + + result = base64_encode(_src, &tmp_out); + if (!result) goto exit; + + strip_base64_modifier_output(_src, &tmp_out, 0, binary++); + + exit_szstr(&tmp_out); + + /* Variante 1 */ + + tmp_in.data[0] = ' '; + memcpy(&tmp_in.data[1], _src->static_bin_data, _src->len); + + tmp_in.len = _src->len + 1; + + result = base64_encode(&tmp_in, &tmp_out); + if (!result) goto exit; + + strip_base64_modifier_output(&tmp_in, &tmp_out, 1, binary); + + /** + * Lors qu'un unique octet est encodé, cet octet ne produit aucun + * caractère que ne dépend que de lui : + * + * | X | + * 1 2 3 4 5 6 | 7 8 1 2 3 4 | 5 6 7 8 1 2 | 3 4 5 6 7 8 + * + * Les compteurs sont alors diminués. + */ + + if (binary->len == 0) + (*dcount)--; + else + binary++; + + exit_szstr(&tmp_out); + + /* Variante 2 */ + + tmp_in.data[0] = ' '; + tmp_in.data[2] = ' '; + memcpy(&tmp_in.data[2], _src->static_bin_data, _src->len); + + tmp_in.len = _src->len + 2; + + result = base64_encode(&tmp_in, &tmp_out); + if (!result) goto exit; + + strip_base64_modifier_output(&tmp_in, &tmp_out, 2, binary++); + + exit_szstr(&tmp_out); + + exit: + + exit_szstr(&tmp_in); + + } + + if (!result) + { + for (i = 0; i < *dcount; i++) + exit_szstr(&(*dest)[i]); + + free(*dest); + + *dcount = 0; + *dest = NULL; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* arg = argument de personnalisation. * +* * +* Description : Détermine si un argument est bien toléré par un modificateur.* +* * +* Retour : Bilan de la consultation : support ou non. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_base64_modifier_can_handle_arg(const GScanBase64Modifier *modifier, const modifier_arg_t *arg) +{ + bool result; /* Bilan d'opération à renvoyer*/ + + switch (arg->type) + { + case MAT_STRING: + result = (arg->value.string.len == 64); + break; + + default: + result = false; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquences d'octets à traiter. * +* scount = quantité de ces séquences. * +* arg = argument de personnalisation. * +* dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * +* dcount = quantité de ces séquences. * +* * +* Description : Transforme une séquence d'octets pour motif de recherche. * +* * +* Retour : Bilan de l'opération : succès ou échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_scan_base64_modifier_transform_with_arg(const GScanBase64Modifier *modifier, const sized_binary_t *src, size_t scount, const modifier_arg_t *arg, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + sized_binary_t *binary; /* Raccourci vers le stockage */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* Source courante */ + sized_binary_t tmp_in; /* Manipulation des variations */ + sized_binary_t tmp_out; /* Manipulation des variations */ + + result = (arg->type == MAT_STRING); + if (!result) goto bad_arg; + + *dcount = scount * 3; + *dest = calloc(*dcount, sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount && result; i++) + { + _src = src + i; + + tmp_in.data = malloc((_src->len + 2) * sizeof(bin_t)); + + /** + * Explications sur la définition des modifications sur les + * encodages produits : https://www.leeholmes.com/searching-for-content-in-base-64-strings/ + */ + + /* Encodage premier */ + + result = _base64_encode(_src, &tmp_out, &arg->value.string); + if (!result) goto exit; + + strip_base64_modifier_output(_src, &tmp_out, 0, binary++); + + exit_szstr(&tmp_out); + + /* Variante 1 */ + + tmp_in.data[0] = ' '; + memcpy(&tmp_in.data[1], _src->static_bin_data, _src->len); + + tmp_in.len = _src->len + 1; + + result = _base64_encode(&tmp_in, &tmp_out, &arg->value.string); + if (!result) goto exit; + + strip_base64_modifier_output(&tmp_in, &tmp_out, 1, binary++); + + exit_szstr(&tmp_out); + + /* Variante 2 */ + + tmp_in.data[0] = ' '; + tmp_in.data[2] = ' '; + memcpy(&tmp_in.data[2], _src->static_bin_data, _src->len); + + tmp_in.len = _src->len + 2; + + result = _base64_encode(&tmp_in, &tmp_out, &arg->value.string); + if (!result) goto exit; + + strip_base64_modifier_output(&tmp_in, &tmp_out, 2, binary++); + + exit_szstr(&tmp_out); + + exit: + + exit_szstr(&tmp_in); + + } + + if (!result) + { + for (i = 0; i < *dcount; i++) + exit_szstr(&(*dest)[i]); + + free(*dest); + + *dcount = 0; + *dest = NULL; + + } + + bad_arg: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à consulter. * +* index = indice de la combinaison ciblée. [OUT] * +* * +* Description : Retrouve l'origine d'une correspondance à partir d'un indice.* +* * +* Retour : Version humainement lisible de la combinaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_scan_base64_modifier_get_path(const GScanBase64Modifier *modifier, size_t *index) +{ + char *result; /* Combinaison à retourner */ + + if (*index > 3) + { + result = NULL; + (*index) -= 3; + } + + else + result = strdup("base64"); + + return result; + +} diff --git a/plugins/encodings/rost/base64.h b/plugins/encodings/rost/base64.h new file mode 100644 index 0000000..646b945 --- /dev/null +++ b/plugins/encodings/rost/base64.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * base64.h - prototypes pour la transormation en encodage Base64 + * + * 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 _PLUGINS_ENCODINGS_ROST_BASE64_H +#define _PLUGINS_ENCODINGS_ROST_BASE64_H + + +#include <glib-object.h> + + +#include <analysis/scan/patterns/modifier.h> + + + +#define G_TYPE_SCAN_BASE64_MODIFIER g_scan_base64_modifier_get_type() +#define G_SCAN_BASE64_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_BASE64_MODIFIER, GScanBase64Modifier)) +#define G_IS_SCAN_BASE64_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_BASE64_MODIFIER)) +#define G_SCAN_BASE64_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_BASE64_MODIFIER, GScanBase64ModifierClass)) +#define G_IS_SCAN_BASE64_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_BASE64_MODIFIER)) +#define G_SCAN_BASE64_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_BASE64_MODIFIER, GScanBase64ModifierClass)) + + +/* Transormation en encodage Base64 (instance) */ +typedef GScanTokenModifier GScanBase64Modifier; + +/* Transormation en encodage Base64 (classe) */ +typedef GScanTokenModifierClass GScanBase64ModifierClass; + + +/* Indique le type défini pour une transormation en encodage Base64. */ +GType g_scan_base64_modifier_get_type(void); + +/* Construit un modificateur livrant des encodages en Base64. */ +GScanTokenModifier *g_scan_base64_modifier_new(void); + + + +#endif /* _PLUGINS_ENCODINGS_ROST_BASE64_H */ diff --git a/plugins/kaitai/Makefile.am b/plugins/kaitai/Makefile.am index cbc0f25..9a4e112 100644 --- a/plugins/kaitai/Makefile.am +++ b/plugins/kaitai/Makefile.am @@ -54,6 +54,7 @@ libkaitai_la_SOURCES = \ array.h array.c \ core.h core.c \ expression.h \ + import.h import.c \ parser-int.h \ parser.h parser.c \ record-int.h \ @@ -67,6 +68,7 @@ libkaitai_la_SOURCES = \ libkaitai_la_LIBADD = \ parsers/libkaitaiparsers.la \ records/libkaitairecords.la \ + rost/libkaitairost.la \ $(PYTHON3_LIBADD) libkaitai_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src @@ -88,5 +90,4 @@ CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h EXTRA_DIST = tokens.h -# misc -SUBDIRS = parsers records $(PYTHON3_SUBDIRS) +SUBDIRS = parsers records rost $(PYTHON3_SUBDIRS) diff --git a/plugins/kaitai/core.c b/plugins/kaitai/core.c index 7483fbc..c41d96d 100644 --- a/plugins/kaitai/core.c +++ b/plugins/kaitai/core.c @@ -30,6 +30,8 @@ #ifdef INCLUDE_PYTHON3_BINDINGS # include "python/module.h" #endif +#include "rost/core.h" + #ifdef INCLUDE_PYTHON3_BINDINGS @@ -62,7 +64,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) { bool result; /* Bilan à retourner */ - result = true; + result = add_kaitai_support_to_rost(); #ifdef INCLUDE_PYTHON3_BINDINGS diff --git a/plugins/kaitai/grammar.y b/plugins/kaitai/grammar.y index 9e31113..9745dc8 100644 --- a/plugins/kaitai/grammar.y +++ b/plugins/kaitai/grammar.y @@ -31,9 +31,10 @@ typedef void *yyscan_t; #include "expression.h" #include "record.h" +#include "records/bits.h" +#include "records/delayed.h" #include "records/item.h" #include "records/list.h" -#include "records/value.h" } @@ -580,7 +581,9 @@ YY_DECL; %token ROOT "_root" %token PARENT "_parent" %token LAST "_" +%token IO "_io" %token METH_IO "._io" +%token IO_EOF ".eof" %token TRUE_CONST "true" %token FALSE_CONST "false" @@ -622,6 +625,7 @@ YY_DECL; %type <value> field %type <value> enumeration %type <value> stream +%type <value> stream_meths @@ -714,6 +718,7 @@ YY_DECL; | field { $$ = $1; } | enumeration { $$ = $1; } | stream { $$ = $1; } + | stream_meths { $$ = $1; } | arithmetic_expr { $$ = $1; } | relational_expr { $$ = $1; } | logical_expr { $$ = $1; } @@ -1487,7 +1492,35 @@ YY_DECL; } - stream : any_expr "._io" + stream : "_io" + { + GBinContent *__content; + mrange_t __range; + vmpa2t __next; + + if (locals->last == NULL) + { + __content = g_match_record_get_content(locals->root); + + g_binary_content_compute_start_pos(__content, &__next); + + } + else + { + __content = g_match_record_get_content(locals->last); + + g_match_record_get_range(locals->last, &__range); + compute_mrange_end_addr(&__range, &__next); + + } + + $$.stream = g_kaitai_stream_new(__content, &__next); + $$.type = GVT_STREAM; + + g_object_unref(G_OBJECT(__content)); + + } + | any_expr "._io" { GBinContent *__content; mrange_t __range; @@ -1508,6 +1541,15 @@ YY_DECL; } ; + stream_meths : stream ".eof" + { + $$.status = g_kaitai_stream_has_reached_eof($1.stream);; + $$.type = GVT_BOOLEAN; + + EXIT_RESOLVED_VALUE($1); + + } + ; %% @@ -1656,8 +1698,11 @@ static bool reduce_resolved_kaitai_expression(resolved_value_t *in_out) while (result && in_out->type == GVT_RECORD) { - if (G_IS_RECORD_VALUE(in_out->record)) - result = g_record_value_compute_value(G_RECORD_VALUE(in_out->record), &deeper); + if (G_IS_RECORD_BIT_FIELD(in_out->record)) + result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(in_out->record), &deeper); + + else if (G_IS_RECORD_DELAYED(in_out->record)) + result = g_record_delayed_compute_value(G_RECORD_DELAYED(in_out->record), &deeper); else if (G_IS_RECORD_ITEM(in_out->record)) result = g_record_item_get_value(G_RECORD_ITEM(in_out->record), &deeper); @@ -1734,6 +1779,26 @@ bool resolve_kaitai_expression_as_boolean(const kaitai_scope_t *locals, const ch if (result) result = reduce_resolved_kaitai_expression(out); + if (result) + { + if (out->type == GVT_UNSIGNED_INTEGER) + { + out->status = (out->unsigned_integer != 0); + out->type = GVT_BOOLEAN; + } + else if (out->type == GVT_SIGNED_INTEGER) + { + out->status = (out->signed_integer != 0); + out->type = GVT_BOOLEAN; + } + else if (out->type == GVT_FLOAT) + { + out->status = (out->floating_number != 0); + out->type = GVT_BOOLEAN; + } + + } + if (result && out->type != GVT_BOOLEAN) { EXIT_RESOLVED_VALUE(*out); diff --git a/plugins/kaitai/import.c b/plugins/kaitai/import.c new file mode 100644 index 0000000..0412ff7 --- /dev/null +++ b/plugins/kaitai/import.c @@ -0,0 +1,300 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * import.c - localisation de fichiers de définitions externes + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "import.h" + + +#include <libgen.h> +#include <malloc.h> +#include <string.h> + + +#include <common/environment.h> +#include <core/logs.h> + + + +/* Charge un type Kaitai à partir d'une définition voisine. */ +static GKaitaiType *import_relative_kaitai_definition(const char *, const char *); + +/* Charge un type Kaitai depuis un emplacement de $KSPATH. */ +static GKaitaiType *import_kaitai_definition_from_env(const char *); + +/* Charge un interpréteur pour une définition voisine. */ +static GKaitaiStruct *load_relative_kaitai_definition(const char *, const char *); + +/* Charge un interpréteur depuis un emplacement de $KSPATH. */ +static GKaitaiStruct *load_kaitai_definition_from_env(const char *); + + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* reference = éventuel fichier pour les positions relatives. * +* * +* Description : Charge un type Kaitai à partir d'une définition voisine. * +* * +* Retour : Type valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GKaitaiType *import_relative_kaitai_definition(const char *target, const char *reference) +{ + GKaitaiType *result; /* Structure chargée à renvoyer*/ + char *tmp; /* Zone de travail temporaire */ + char *base; /* Base de recherche */ + char *filename; /* Nom de fichier à tester */ + int ret; /* Bilan d'une construction */ + + result = NULL; + + tmp = strdup(reference); + base = dirname(tmp); + + ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target); + if (ret == -1) goto build_error; + + result = g_kaitai_type_new_as_import(target, filename); + + free(filename); + + build_error: + + free(tmp); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* * +* Description : Charge un type Kaitai depuis un emplacement de $KSPATH. * +* * +* Retour : Type valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GKaitaiType *import_kaitai_definition_from_env(const char *target) +{ + GKaitaiType *result; /* Structure chargée à renvoyer*/ + char *paths; /* Emplacements de greffons */ + char *save; /* Sauvegarde pour ré-entrance */ + char *path; /* Chemin à fouiller */ + char *filename; /* Nom de fichier à tester */ + int ret; /* Bilan d'une construction */ + + result = NULL; + + paths = get_env_var("KSPATH"); + + save = NULL; /* gcc... */ + + for (path = strtok_r(paths, ":", &save); + path != NULL; + path = strtok_r(NULL, ":", &save)) + { + ret = asprintf(&filename, "%s%c%s.ksy", path, G_DIR_SEPARATOR, target); + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + continue; + } + + result = g_kaitai_type_new_as_import(target, filename); + + if (result != NULL) + log_variadic_message(LMT_PROCESS, _("Found a required Kaitai definition to import: %s"), filename); + + free(filename); + + } + + free(paths); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* reference = éventuel fichier pour les positions relatives. * +* * +* Description : Met en place un type Kaitai pour une définition désignée. * +* * +* Retour : Type valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiType *import_kaitai_definition(const char *target, const char *reference) +{ + GKaitaiType *result; /* Structure chargée à renvoyer*/ + + result = NULL; + + if (reference != NULL) + result = import_relative_kaitai_definition(target, reference); + + if (result == NULL) + result = import_kaitai_definition_from_env(target); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* reference = éventuel fichier pour les positions relatives. * +* * +* Description : Charge un interpréteur pour une définition voisine. * +* * +* Retour : Interprétateur valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GKaitaiStruct *load_relative_kaitai_definition(const char *target, const char *reference) +{ + GKaitaiStruct *result; /* Structure chargée à renvoyer*/ + char *tmp; /* Zone de travail temporaire */ + char *base; /* Base de recherche */ + char *filename; /* Nom de fichier à tester */ + int ret; /* Bilan d'une construction */ + + result = NULL; + + tmp = strdup(reference); + base = dirname(tmp); + + ret = asprintf(&filename, "%s%c%s.ksy", base, G_DIR_SEPARATOR, target); + if (ret == -1) goto build_error; + + result = g_kaitai_structure_new_from_file(filename); + + free(filename); + + build_error: + + free(tmp); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* * +* Description : Charge un interpréteur depuis un emplacement de $KSPATH. * +* * +* Retour : Interprétateur valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GKaitaiStruct *load_kaitai_definition_from_env(const char *target) +{ + GKaitaiStruct *result; /* Structure chargée à renvoyer*/ + char *paths; /* Emplacements de greffons */ + char *save; /* Sauvegarde pour ré-entrance */ + char *path; /* Chemin à fouiller */ + char *filename; /* Nom de fichier à tester */ + int ret; /* Bilan d'une construction */ + + result = NULL; + + paths = get_env_var("KSPATH"); + + save = NULL; /* gcc... */ + + for (path = strtok_r(paths, ":", &save); + path != NULL; + path = strtok_r(NULL, ":", &save)) + { + ret = asprintf(&filename, "%s%c%s.ksy", path, G_DIR_SEPARATOR, target); + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + continue; + } + + result = g_kaitai_structure_new_from_file(filename); + + if (result != NULL) + log_variadic_message(LMT_PROCESS, _("Found a required Kaitai definition: %s"), filename); + + free(filename); + + } + + free(paths); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de la définition à retrouver. * +* reference = éventuel fichier pour les positions relatives. * +* * +* Description : Met en place un interpréteur pour une définition désignée. * +* * +* Retour : Interprétateur valide en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiStruct *load_kaitai_definition(const char *target, const char *reference) +{ + GKaitaiStruct *result; /* Structure chargée à renvoyer*/ + + result = NULL; + + if (reference != NULL) + result = load_relative_kaitai_definition(target, reference); + + if (result == NULL) + result = load_kaitai_definition_from_env(target); + + return result; + +} diff --git a/plugins/kaitai/import.h b/plugins/kaitai/import.h new file mode 100644 index 0000000..66a0f5a --- /dev/null +++ b/plugins/kaitai/import.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * import.h - prototypes pour la localisation de fichiers de définitions externes + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_IMPORT_H +#define _PLUGINS_KAITAI_IMPORT_H + + +#include "parsers/struct.h" +#include "parsers/type.h" + + + +/* Met en place un type Kaitai pour une définition désignée. */ +GKaitaiType *import_kaitai_definition(const char *, const char *); + +/* Met en place un interpréteur pour une définition désignée. */ +GKaitaiStruct *load_kaitai_definition(const char *, const char *); + + + +#endif /* _PLUGINS_KAITAI_IMPORT_H */ diff --git a/plugins/kaitai/parser-int.h b/plugins/kaitai/parser-int.h index 4ddb0f9..8bac523 100644 --- a/plugins/kaitai/parser-int.h +++ b/plugins/kaitai/parser-int.h @@ -30,7 +30,7 @@ /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +typedef bool (* parse_kaitai_fc) (GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); diff --git a/plugins/kaitai/parser.c b/plugins/kaitai/parser.c index 77c15b3..cfe1aa1 100644 --- a/plugins/kaitai/parser.c +++ b/plugins/kaitai/parser.c @@ -24,6 +24,9 @@ #include "parser.h" +#include <assert.h> + + #include "parser-int.h" @@ -131,7 +134,7 @@ static void g_kaitai_parser_finalize(GKaitaiParser *parser) * Paramètres : parser = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -142,18 +145,22 @@ static void g_kaitai_parser_finalize(GKaitaiParser *parser) * * ******************************************************************************/ -bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +bool g_kaitai_parser_parse_content(GKaitaiParser *parser, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ GKaitaiParserClass *class; /* Classe de l'instance */ + *record = NULL; + class = G_KAITAI_PARSER_GET_CLASS(parser); - result = class->parse(parser, locals, content, pos, record); + result = class->parse(parser, locals, content, epos, record); - if (result) + if (result && *record != NULL) remember_last_record(locals, *record); + assert((!result && *record == NULL) || result); + return result; } diff --git a/plugins/kaitai/parser.h b/plugins/kaitai/parser.h index 4c17087..64d759d 100644 --- a/plugins/kaitai/parser.h +++ b/plugins/kaitai/parser.h @@ -56,7 +56,7 @@ typedef struct _GKaitaiParserClass GKaitaiParserClass; GType g_kaitai_parser_get_type(void); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -bool g_kaitai_parser_parse_content(GKaitaiParser *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +bool g_kaitai_parser_parse_content(GKaitaiParser *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); diff --git a/plugins/kaitai/parsers/attribute-int.h b/plugins/kaitai/parsers/attribute-int.h index ef64089..7d37af3 100644 --- a/plugins/kaitai/parsers/attribute-int.h +++ b/plugins/kaitai/parsers/attribute-int.h @@ -51,6 +51,9 @@ struct _GKaitaiAttribute /* KAP_FIXED_CONTENT */ sized_string_t fixed_content; /* Données brutes attendues */ + /* KAP_BIT_FIELD_TYPE */ + uint8_t bf_size; /* Nombre de bits visés */ + /* KAP_BASIC_TYPE */ struct { diff --git a/plugins/kaitai/parsers/attribute.c b/plugins/kaitai/parsers/attribute.c index c61fe99..6050bb1 100644 --- a/plugins/kaitai/parsers/attribute.c +++ b/plugins/kaitai/parsers/attribute.c @@ -25,6 +25,7 @@ #include <assert.h> +#include <stdlib.h> #include <string.h> @@ -35,6 +36,7 @@ #include "attribute-int.h" #include "../expression.h" #include "../scope.h" +#include "../records/bits.h" #include "../records/empty.h" #include "../records/item.h" #include "../records/list.h" @@ -56,6 +58,9 @@ static void g_kaitai_attribute_dispose(GKaitaiAttribute *); /* Procède à la libération totale de la mémoire. */ static void g_kaitai_attribute_finalize(GKaitaiAttribute *); +/* Traduit en champ de bits une chaîne de caractères. */ +static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *, const char *); + /* Traduit en type concret une chaîne de caractères. */ static bool g_kaitai_attribute_resolve_type(GKaitaiAttribute *, const char *); @@ -71,7 +76,7 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); /* Extrait d'un contenu une série d'octets avec terminaison. */ static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); @@ -80,7 +85,7 @@ static bool g_kaitai_attribute_parse_terminated_bytes(GKaitaiAttribute *, const static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttribute *, const kaitai_scope_t *, const GBinContent *, const vmpa2t *, phys_t *, mrange_t *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -243,7 +248,7 @@ GKaitaiAttribute *g_kaitai_attribute_new(GYamlNode *parent) result = g_object_new(G_TYPE_KAITAI_ATTRIBUTE, NULL); - if (!g_kaitai_attribute_create(result, parent, true)) + if (!g_kaitai_attribute_create(result, parent, false /* TODO : REMME ? */)) g_clear_object(&result); return result; @@ -399,7 +404,10 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool if (value != NULL) { - if (g_kaitai_attribute_resolve_type(attrib, value)) + if (g_kaitai_attribute_resolve_bit_field(attrib, value)) + attrib->payload |= KAP_BIT_FIELD_TYPE; + + else if (g_kaitai_attribute_resolve_type(attrib, value)) attrib->payload |= KAP_BASIC_TYPE; else @@ -701,6 +709,54 @@ bool g_kaitai_attribute_create(GKaitaiAttribute *attrib, GYamlNode *parent, bool * Paramètres : attrib = attribut Kaitai en cours de constitution. * * desc = chaîne de caractère à interpréter en type. * * * +* Description : Traduit en champ de bits une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_attribute_resolve_bit_field(GKaitaiAttribute *attrib, const char *desc) +{ + bool result; /* Bilan à retourner */ + size_t len; /* Taille de la chaîne à lire */ + char *end; /* Prochain caractère à lire */ + unsigned long size; /* Taille du champ de bits */ + + result = false; + + if (desc[0] == 'b') + { + len = strlen(desc); + + size = strtoul(&desc[1], &end, 10); + + if (size > 64) + { + printf("Unsupported size for bit field: %lu\n", size); + goto exit; + } + + result = ((desc + len) == end); + + if (result) + attrib->bf_size = size; + + } + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : attrib = attribut Kaitai en cours de constitution. * +* desc = chaîne de caractère à interpréter en type. * +* * * Description : Traduit en type concret une chaîne de caractères. * * * * Retour : Bilan de l'opération. * @@ -930,7 +986,7 @@ static bool g_kaitai_attribute_check(const GKaitaiAttribute *attrib) } /** - * Si une séquence d'octets finaux est spécifiées, alors l'attribut + * Si une séquence d'octets finaux est spécifiée, alors l'attribut * doit correspondre à un type str[z] (lecture) ou de taille fixée * (validation post-lecture). */ @@ -1018,7 +1074,8 @@ static GKaitaiAttribute *g_kaitai_attribute_dup_for(const GKaitaiAttribute *attr * Les travaux de copie ne portent ainsi que sur le présent attribut. */ - result->raw_id = strdup(attrib->raw_id); + if (attrib->raw_id != NULL) + result->raw_id = strdup(attrib->raw_id); if (attrib->orig_id != NULL) result->orig_id = strdup(attrib->orig_id); @@ -1428,6 +1485,50 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon } +/****************************************************************************** +* * +* Paramètres : attrib = lecteur d'attribut Kaitai à consulter. * +* content = contenu binaire à venir lire. * +* epos = tête de lecture avec granularité en bits. * +* size = quantité de bits à prendre en compte. * +* endian = boustime des données à respecter. * +* out = valeur à sauvegarder sous une forme générique.[OUT]* +* * +* Description : Lit la valeur d'un champ de bits Kaitai représenté. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *attrib, const GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian, resolved_value_t *out) +{ + bool result; /* Bilan à retourner */ + ext_vmpa_t tmpepos; /* Localisation modifiable */ + uint64_t tmp64; /* Valeur de 64 bits lue */ + + result = false; + + if (attrib->payload & KAP_BIT_FIELD_TYPE) + { + copy_evmpa(&tmpepos, epos); + + result = g_binary_content_read_bits(content, &tmpepos, size, endian, &tmp64); + + if (result) + { + out->type = GVT_UNSIGNED_INTEGER; + out->unsigned_integer = tmp64; + } + + } + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* IMPLEMENTATION DES FONCTIONS DE CLASSE */ @@ -1439,7 +1540,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon * Paramètres : attrib = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -1450,7 +1551,7 @@ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *attrib, const GBinCon * * ******************************************************************************/ -static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ resolved_value_t authorized; /* Validation des traitements */ @@ -1499,7 +1600,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s /* Zone de travail restreinte */ g_binary_content_compute_end_pos(content, &tmp); - diff = compute_vmpa_diff(pos, &tmp); + diff = compute_vmpa_diff(&epos->base, &tmp); + + if (epos->consumed_extra_bits > 0 && diff > 0) + diff--; if (attrib->payload & KAP_SIZED) { @@ -1537,8 +1641,10 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (!result) goto exit; - init_mrange(&work_range, pos, diff); - work_area = g_restricted_content_new_ro(content, &work_range); + align_evmpa_on_byte(epos); + + init_mrange(&work_range, &epos->base, diff); + work_area = g_restricted_content_new(content, &work_range); has_empty_size = (diff == 0); @@ -1555,13 +1661,18 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s assert(false); else if (attrib->payload & KAP_SIZED_EOS) + { + align_evmpa_on_byte(epos); result = true; + } else if (attrib->payload & KAP_FIXED_CONTENT) { if (diff >= attrib->fixed_content.len) { - copy_vmpa(&tmp, pos); + align_evmpa_on_byte(epos); + + copy_vmpa(&tmp, &epos->base); data = g_binary_content_get_raw_access(work_area, &tmp, attrib->fixed_content.len); assert(data != NULL); @@ -1575,8 +1686,26 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s } + else if (attrib->payload & KAP_BIT_FIELD_TYPE) + { + if (attrib->has_endian) + endian = attrib->endian; + else + endian = g_kaitai_meta_get_endian(locals->meta); + + *record = g_record_bit_field_new(attrib, work_area, epos, attrib->bf_size, endian); + + result = (*record != NULL); + + if (result) + advance_evmpa_bits(epos, attrib->bf_size); + + } + else if (attrib->payload & KAP_BASIC_TYPE) { + align_evmpa_on_byte(epos); + switch (attrib->basic) { case BTP_CHAR: @@ -1584,7 +1713,8 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (attrib->is_string) { if ((attrib->payload & KAP_SIZED) == 0) - result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, work_area, pos, record); + result = g_kaitai_attribute_parse_terminated_bytes(attrib, locals, + work_area, &epos->base, record); } else { @@ -1627,7 +1757,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (user_type != NULL) { result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(user_type), - locals, work_area, pos, record); + locals, work_area, epos, record); if (result) /** @@ -1647,7 +1777,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s } else if (attrib->payload & KAP_DYNAMIC_TYPE) - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, pos, record); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib->switchon), locals, work_area, epos, record); else if (attrib->payload & KAP_SIZED) { @@ -1660,6 +1790,11 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (result && *record == NULL) { /** + * A ce stade, la granularité des travaux est l'octet. + */ + assert(epos->consumed_extra_bits == 0); + + /** * On choisit de laisser la création de correspondances nulles. * * Cela permet de disposer de la présence de champs valides, même vides @@ -1668,12 +1803,13 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s /* if (diff > 0) */ { - result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, pos, &diff, &range); + result = g_kaitai_attribute_compute_maybe_terminated_range(attrib, locals, content, + &epos->base, &diff, &range); if (result) { if (has_empty_size) - *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, pos)); + *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(attrib), content, &epos->base)); else { @@ -1685,7 +1821,7 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s *record = G_MATCH_RECORD(g_record_item_new(attrib, work_area, &range, endian)); if (*record != NULL) - advance_vmpa(pos, diff); + advance_vmpa(&epos->base, diff); else result = false; @@ -1701,13 +1837,16 @@ static bool _g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_s if (attrib->payload & KAP_SIZED) { - cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), pos); + /* Réalignement éventuel suite aux lectures dans la zone périmétrée... */ + align_evmpa_on_byte(epos); + + cur_diff = compute_vmpa_diff(get_mrange_addr(&work_range), &epos->base); /* Pour GCC... */ max_size = get_mrange_length(&work_range); if (cur_diff < max_size) - advance_vmpa(pos, max_size - cur_diff); + advance_vmpa(&epos->base, max_size - cur_diff); assert(work_area != content); g_object_unref(G_OBJECT(work_area)); @@ -1932,7 +2071,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri * Paramètres : attrib = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -1943,7 +2082,7 @@ static bool g_kaitai_attribute_compute_maybe_terminated_range(const GKaitaiAttri * * ******************************************************************************/ -static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ resolved_value_t authorized; /* Validation des traitements */ @@ -1957,7 +2096,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc resolved_value_t loop; /* Poursuite des lectures ? */ if (attrib->repetition == KAR_NO_REPETITION) - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, record); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, record); else { @@ -1975,7 +2114,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc } - list = g_record_list_new(attrib, content, pos); + list = g_record_list_new(attrib, content, &epos->base); switch (attrib->repetition) { @@ -1984,17 +2123,17 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc result = true; g_binary_content_compute_end_pos(content, &end); - diff = compute_vmpa_diff(pos, &end); + diff = compute_vmpa_diff(&epos->base, &end); while (diff > 0) { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); remember_last_record(locals, child); - diff = compute_vmpa_diff(pos, &end); + diff = compute_vmpa_diff(&epos->base, &end); } @@ -2025,7 +2164,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc for (i = 0; i < count; i++) { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); @@ -2039,7 +2178,7 @@ static bool g_kaitai_attribute_parse_content(GKaitaiAttribute *attrib, kaitai_sc do { - result = _g_kaitai_attribute_parse_content(attrib, locals, content, pos, &child); + result = _g_kaitai_attribute_parse_content(attrib, locals, content, epos, &child); if (!result) break; g_record_list_add_record(list, child); diff --git a/plugins/kaitai/parsers/attribute.h b/plugins/kaitai/parsers/attribute.h index 38b78d7..9b43936 100644 --- a/plugins/kaitai/parsers/attribute.h +++ b/plugins/kaitai/parsers/attribute.h @@ -56,18 +56,19 @@ typedef struct _GKaitaiAttributeClass GKaitaiAttributeClass; /* Type de charge associée à un attribut */ typedef enum _KaitaiAttributePayload { - KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */ + KAP_UNINITIALIZED = (0 << 0), /* Type non initialisé */ - KAP_FIXED_CONTENT = (1 << 0), /* Contenu brut attendu */ - KAP_BASIC_TYPE = (1 << 1), /* Type prédéfini */ - KAP_USER_TYPE = (1 << 2), /* Type personnalisé */ - KAP_DYNAMIC_TYPE = (1 << 3), /* Type dynmatique */ - KAP_SIZED = (1 << 4), /* Bourrage dimensionné */ - KAP_SIZED_EOS = (1 << 5), /* Bourrage final */ + KAP_FIXED_CONTENT = (1 << 0), /* Contenu brut attendu */ + KAP_BIT_FIELD_TYPE = (1 << 1), /* Champ d'un ou plusieurs bits*/ + KAP_BASIC_TYPE = (1 << 2), /* Type prédéfini */ + KAP_USER_TYPE = (1 << 3), /* Type personnalisé */ + KAP_DYNAMIC_TYPE = (1 << 4), /* Type dynmatique */ + KAP_SIZED = (1 << 5), /* Bourrage dimensionné */ + KAP_SIZED_EOS = (1 << 6), /* Bourrage final */ } KaitaiAttributePayload; -/* Types de base reconnus par Kaitai */ +/* Types de base reconnus par Kaitai */ /* TODO : REMME ? (car non utilisé) */ typedef enum _KaitaiBasicType { KBT_U1, /* Octet non signé */ @@ -149,6 +150,9 @@ bool g_kaitai_attribute_handle_signed_integer(const GKaitaiAttribute *); /* Lit la valeur d'un élément Kaitai entier représenté. */ bool g_kaitai_attribute_read_value(const GKaitaiAttribute *, const GBinContent *, const mrange_t *, SourceEndian, resolved_value_t *); +/* Lit la valeur d'un champ de bits Kaitai représenté. */ +bool g_kaitai_attribute_read_bit_field_value(const GKaitaiAttribute *, const GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian, resolved_value_t *); + #endif /* _PLUGINS_KAITAI_PARSERS_ATTRIBUTE_H */ diff --git a/plugins/kaitai/parsers/instance.c b/plugins/kaitai/parsers/instance.c index 63db224..d62c1f6 100644 --- a/plugins/kaitai/parsers/instance.c +++ b/plugins/kaitai/parsers/instance.c @@ -34,7 +34,7 @@ #include "instance-int.h" #include "../expression.h" -#include "../records/value.h" +#include "../records/delayed.h" @@ -59,7 +59,7 @@ static void g_kaitai_instance_finalize(GKaitaiInstance *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_instance_parse_content(GKaitaiInstance *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -349,74 +349,30 @@ const char *g_kaitai_instance_get_name(const GKaitaiInstance *inst) * * * Paramètres : inst = lecteur d'instance Kaitai à consulter. * * locals = variables locales pour les résolutions de types. * -* value = valeur à sauvegarder sous une forme générique. [OUT]* +* content = contenu binaire lié à la correspondance. * * * -* Description : Détermine la valeur d'un élément Kaitai entier calculé. * +* Description : Détermine la valeur effective d'un élément Kaitai dynamique. * * * -* Retour : Bilan de l'opération. * +* Retour : valeur à sauvegarder sous une forme générique. * * * * Remarques : - * * * ******************************************************************************/ -bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value) +GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content) { - bool result; /* Bilan à retourner */ - - if (inst->value == NULL) - result = false; - - else - result = resolve_kaitai_expression_as_any(locals, - inst->value, - strlen(inst->value), - value); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : inst = structure Kaitai en cours de parcours. * -* locals = variables locales pour les résolutions de types. * -* content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * -* record = noeud d'arborescence d'éléments rencontrés. [OUT] * -* * -* Description : Parcourt un contenu binaire selon des spécifications Kaitai. * -* * -* Retour : Bilan de l'opératon : true pour continuer, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) -{ - bool result; /* Bilan à retourner */ + GMatchRecord *result; /* Enregistrement à retourner */ GBinContent *work_area; /* Aire de travail */ GKaitaiStream *stream; /* Flux de données pour Kaitai */ - resolved_value_t offset; /* Position à adopter */ + bool status; /* Bilan intermédiaire */ vmpa2t forced_pos; /* Tete de lecture constituée */ + resolved_value_t offset; /* Position à adopter */ GKaitaiParserClass *class; /* Classe parente à solliciter */ + ext_vmpa_t epos; /* Tête de lecture complète */ - if (inst->value != NULL) - { - *record = G_MATCH_RECORD(g_record_value_new(inst, locals)); + result = NULL; - result = (*record != NULL); - - } - - else + if (inst->value == NULL) { /* Contenu particulier */ @@ -425,8 +381,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ else { - result = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream); - if (!result) goto exit; + status = resolve_kaitai_expression_as_stream(locals, inst->io, strlen(inst->io), &stream); + if (!status) goto exit; work_area = g_kaitai_stream_get_content(stream); @@ -438,8 +394,8 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ g_binary_content_compute_start_pos(work_area, &forced_pos); - result = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset); - if (!result) goto exit_with_content; + status = resolve_kaitai_expression_as_integer(locals, inst->pos, strlen(inst->pos), &offset); + if (!status) goto exit_with_content; if (offset.type == GVT_UNSIGNED_INTEGER) advance_vmpa(&forced_pos, offset.unsigned_integer); @@ -450,7 +406,7 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ if (offset.signed_integer < 0) { - result = false; + status = false; goto exit_with_content; } @@ -462,7 +418,9 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ class = G_KAITAI_PARSER_CLASS(g_kaitai_instance_parent_class); - result = class->parse(G_KAITAI_PARSER(inst), locals, work_area, &forced_pos, record); + init_evmpa_from_vmpa(&epos, &forced_pos); + + class->parse(G_KAITAI_PARSER(inst), locals, work_area, &epos, &result); exit_with_content: @@ -476,3 +434,70 @@ static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_ return result; } + + +/****************************************************************************** +* * +* Paramètres : inst = lecteur d'instance Kaitai à consulter. * +* locals = variables locales pour les résolutions de types. * +* value = valeur à sauvegarder sous une forme générique. [OUT]* +* * +* Description : Détermine la valeur d'un élément Kaitai entier calculé. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_instance_compute_value(const GKaitaiInstance *inst, const kaitai_scope_t *locals, resolved_value_t *value) +{ + bool result; /* Bilan à retourner */ + + if (inst->value == NULL) + result = false; + + else + result = resolve_kaitai_expression_as_any(locals, + inst->value, + strlen(inst->value), + value); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : inst = structure Kaitai en cours de parcours. * +* locals = variables locales pour les résolutions de types. * +* content = données binaires à analyser et traduire. * +* epos = tête de lecture courante. [OUT] * +* record = noeud d'arborescence d'éléments rencontrés. [OUT] * +* * +* Description : Parcourt un contenu binaire selon des spécifications Kaitai. * +* * +* Retour : Bilan de l'opératon : true pour continuer, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_instance_parse_content(GKaitaiInstance *inst, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) +{ + bool result; /* Bilan à retourner */ + + *record = G_MATCH_RECORD(g_record_delayed_new(inst, locals, inst->value == NULL ? content : NULL)); + + result = (*record != NULL); + + return result; + +} diff --git a/plugins/kaitai/parsers/instance.h b/plugins/kaitai/parsers/instance.h index a9aee9a..4594137 100644 --- a/plugins/kaitai/parsers/instance.h +++ b/plugins/kaitai/parsers/instance.h @@ -60,6 +60,9 @@ GKaitaiInstance *g_kaitai_instance_new(GYamlNode *); /* Indique le nom attribué à une instance Kaitai. */ const char *g_kaitai_instance_get_name(const GKaitaiInstance *); +/* Détermine la valeur effective d'un élément Kaitai dynamique. */ +GMatchRecord *g_kaitai_instance_compute_real_record(const GKaitaiInstance *, const kaitai_scope_t *, GBinContent *); + /* Détermine la valeur d'un élément Kaitai entier calculé. */ bool g_kaitai_instance_compute_value(const GKaitaiInstance *, const kaitai_scope_t *, resolved_value_t *); diff --git a/plugins/kaitai/parsers/meta-int.h b/plugins/kaitai/parsers/meta-int.h index 7d847ef..5fe9174 100644 --- a/plugins/kaitai/parsers/meta-int.h +++ b/plugins/kaitai/parsers/meta-int.h @@ -39,6 +39,9 @@ struct _GKaitaiMeta SourceEndian endian; /* Boutisme par défaut */ + char **dependencies; /* Définitions à importer */ + size_t dep_count; /* Nombre de ces définitions */ + }; /* Description globale d'une définition Kaitai (classe) */ diff --git a/plugins/kaitai/parsers/meta.c b/plugins/kaitai/parsers/meta.c index dc30c73..132eefd 100644 --- a/plugins/kaitai/parsers/meta.c +++ b/plugins/kaitai/parsers/meta.c @@ -97,6 +97,9 @@ static void g_kaitai_meta_init(GKaitaiMeta *meta) meta->endian = SRE_LITTLE; + meta->dependencies = NULL; + meta->dep_count = 0; + } @@ -133,12 +136,20 @@ static void g_kaitai_meta_dispose(GKaitaiMeta *meta) static void g_kaitai_meta_finalize(GKaitaiMeta *meta) { + size_t i; /* Boucle de parcours */ + if (meta->id != NULL) free(meta->id); if (meta->title != NULL) free(meta->title); + for (i = 0; i < meta->dep_count; i++) + free(meta->dependencies[i]); + + if (meta->dependencies != NULL) + free(meta->dependencies); + G_OBJECT_CLASS(g_kaitai_meta_parent_class)->finalize(G_OBJECT(meta)); } @@ -188,6 +199,9 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent) bool result; /* Bilan à retourner */ GYamlNode *node; /* Noeud particulier présent */ const char *value; /* Valeur Yaml particulière */ + GYamlNode **nodes; /* Eventuels noeuds trouvés */ + size_t count; /* Quantité de ces noeuds */ + size_t i; /* Boucle de parcours */ result = true; @@ -245,6 +259,45 @@ bool g_kaitai_meta_create(GKaitaiMeta *meta, GYamlNode *parent) } + /* Imports */ + + node = g_yaml_node_find_first_by_path(parent, "/meta/imports/"); + + if (node != NULL) + { + result = G_IS_YAML_COLLEC(node); + + if (result) + { + nodes = g_yaml_collection_get_nodes(G_YAML_COLLEC(node), &count); + + for (i = 0; i < count; i++) + { + if (!G_IS_YAML_PAIR(nodes[i])) + break; + + value = g_yaml_pair_get_key(G_YAML_PAIR(nodes[i])); + + meta->dependencies = realloc(meta->dependencies, ++meta->dep_count * sizeof(char *)); + + meta->dependencies[meta->dep_count - 1] = strdup(value); + + g_object_unref(G_OBJECT(nodes[i])); + + } + + result = (i == count); + + for (; i < count; i++) + g_object_unref(G_OBJECT(nodes[i])); + + if (nodes != NULL) + free(nodes); + + } + + } + return result; } @@ -279,7 +332,7 @@ const char *g_kaitai_meta_get_id(const GKaitaiMeta *meta) * * * Description : Fournit la désignation humaine d'une définiton Kaitai. * * * -* Retour : Intitulé de définition OU NULL. * +* Retour : Intitulé de définition ou NULL. * * * * Remarques : - * * * @@ -317,3 +370,29 @@ SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *meta) return result; } + + +/****************************************************************************** +* * +* Paramètres : meta = description globale à consulter. * +* count = quantité de définitions à importer. [OUT] * +* * +* Description : Indique la liste des définitions à importer. * +* * +* Retour : Liste de désignations de définitions ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *meta, size_t *count) +{ + const char * const *result; /* Liste à retourner */ + + result = (const char * const *)meta->dependencies; + + *count = meta->dep_count; + + return result; + +} diff --git a/plugins/kaitai/parsers/meta.h b/plugins/kaitai/parsers/meta.h index 3797823..b8b685d 100644 --- a/plugins/kaitai/parsers/meta.h +++ b/plugins/kaitai/parsers/meta.h @@ -63,6 +63,9 @@ const char *g_kaitai_meta_get_title(const GKaitaiMeta *); /* Indique le boustime observé par défaut par une définiton. */ SourceEndian g_kaitai_meta_get_endian(const GKaitaiMeta *); +/* Indique la liste des définitions à importer. */ +const char * const *g_kaitai_meta_get_dependencies(const GKaitaiMeta *, size_t *); + #endif /* _PLUGINS_KAITAI_PARSERS_META_H */ diff --git a/plugins/kaitai/parsers/struct-int.h b/plugins/kaitai/parsers/struct-int.h index f34be32..6eb6e53 100644 --- a/plugins/kaitai/parsers/struct-int.h +++ b/plugins/kaitai/parsers/struct-int.h @@ -37,6 +37,8 @@ struct _GKaitaiStruct { GKaitaiParser parent; /* A laisser en premier */ + char *filename; /* Eventuelle source de données*/ + GKaitaiMeta *meta; /* Description globale */ GKaitaiAttribute **seq_items; /* Sous-attributs présents */ diff --git a/plugins/kaitai/parsers/struct.c b/plugins/kaitai/parsers/struct.c index 128a788..d447cf3 100644 --- a/plugins/kaitai/parsers/struct.c +++ b/plugins/kaitai/parsers/struct.c @@ -33,6 +33,7 @@ #include "struct-int.h" +#include "../import.h" #include "../parser.h" #include "../records/empty.h" #include "../records/group.h" @@ -54,13 +55,16 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *); /* Procède à la libération totale de la mémoire. */ static void g_kaitai_structure_finalize(GKaitaiStruct *); +/* Charge les éventuelles dépendances de la définition. */ +static bool g_kaitai_structure_load_imports(GKaitaiStruct *); + /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_structure_parse_content(GKaitaiStruct *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -116,6 +120,8 @@ static void g_kaitai_structure_class_init(GKaitaiStructClass *klass) static void g_kaitai_structure_init(GKaitaiStruct *kstruct) { + kstruct->filename = NULL; + kstruct->meta = NULL; kstruct->seq_items = NULL; @@ -182,6 +188,9 @@ static void g_kaitai_structure_dispose(GKaitaiStruct *kstruct) static void g_kaitai_structure_finalize(GKaitaiStruct *kstruct) { + if (kstruct->filename != NULL) + free(kstruct->filename); + if (kstruct->seq_items != NULL) free(kstruct->seq_items); @@ -305,6 +314,8 @@ bool g_kaitai_structure_create_from_file(GKaitaiStruct *kstruct, const char *fil bool result; /* Bilan à retourner */ GYamlNode *root; /* Noeud racine YAML */ + kstruct->filename = strdup(filename); + root = parse_yaml_from_file(filename); if (root != NULL) @@ -343,6 +354,7 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) GYamlNode **nodes; /* Eventuels noeuds trouvés */ size_t count; /* Quantité de ces noeuds */ size_t i; /* Boucle de parcours */ + size_t first; /* Premier emplacement dispo. */ bool failed; /* Détection d'un échec */ result = false; @@ -352,6 +364,9 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) kstruct->meta = g_kaitai_meta_new(parent); assert(kstruct->meta != NULL); + result = g_kaitai_structure_load_imports(kstruct); + if (!result) goto bad_loading; + /* Séquence */ collec = g_yaml_node_find_first_by_path(parent, "/seq/"); @@ -406,13 +421,15 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) if (count > 0) { - kstruct->types = calloc(count, sizeof(GKaitaiType *)); - kstruct->types_count = count; + first = kstruct->types_count; + + kstruct->types_count += count; + kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *)); for (i = 0; i < count; i++) { - kstruct->types[i] = g_kaitai_type_new(nodes[i]); - if (kstruct->types[i] == NULL) break; + kstruct->types[first + i] = g_kaitai_type_new(nodes[i]); + if (kstruct->types[first + i] == NULL) break; g_object_unref(G_OBJECT(nodes[i])); @@ -529,6 +546,49 @@ bool g_kaitai_structure_create(GKaitaiStruct *kstruct, GYamlNode *parent) /****************************************************************************** * * +* Paramètres : kstruct = lecteur de définition à initialiser pleinement. * +* * +* Description : Charge les éventuelles dépendances de la définition. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_structure_load_imports(GKaitaiStruct *kstruct) +{ + bool result; /* Bilan d'opération à renvoyer*/ + const char * const *dependencies; /* Liste d'imports requis */ + size_t count; /* Quantité de ces imports */ + size_t i; /* Boucle de parcours */ + GKaitaiType *imported; /* Structure importée */ + + result = true; + + dependencies = g_kaitai_meta_get_dependencies(kstruct->meta, &count); + + for (i = 0; i < count; i++) + { + imported = import_kaitai_definition(dependencies[i], kstruct->filename); + if (imported == NULL) break; + + kstruct->types_count++; + kstruct->types = realloc(kstruct->types, kstruct->types_count * sizeof(GKaitaiType *)); + + kstruct->types[kstruct->types_count - 1] = imported; + + } + + result = (i == count); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : kstruct = structure Kaitai à consulter. * * * * Description : Fournit la description globale d'une définition Kaitai. * @@ -624,6 +684,9 @@ GKaitaiType *g_kaitai_structure_find_sub_type(const GKaitaiStruct *kstruct, cons break; } + result = g_kaitai_structure_find_sub_type(G_KAITAI_STRUCT(kstruct->types[i]), name); + if (result != NULL) break; + } return result; @@ -649,13 +712,15 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont GMatchRecord *result; /* Arborescence à retourner */ vmpa2t pos; /* Tête de lecture */ kaitai_scope_t locals; /* Variables locales */ - bool status; /* Bilan de l'analyse */ + ext_vmpa_t epos; /* Tête de lecture complète */ g_binary_content_compute_start_pos(content, &pos); init_record_scope(&locals, kstruct->meta); - status = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &pos, &result); + init_evmpa_from_vmpa(&epos, &pos); + + g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct), &locals, content, &epos, &result); return result; @@ -673,7 +738,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont * Paramètres : kstruct = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -684,7 +749,7 @@ GMatchRecord *g_kaitai_structure_parse(GKaitaiStruct *kstruct, GBinContent *cont * * ******************************************************************************/ -static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ GRecordGroup *group; /* Ensemble à constituer */ @@ -697,7 +762,7 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop /* Si le groupe est vide */ if ((kstruct->seq_items_count + kstruct->instances_count) == 0) { - *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, pos)); + *record = G_MATCH_RECORD(g_record_empty_new(G_KAITAI_PARSER(kstruct), content, &epos->base)); if (locals->root == NULL) locals->root = *record; @@ -716,10 +781,18 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop old = locals->parent; locals->parent = *record; - for (i = 0; i < kstruct->seq_items_count; i++) + /** + * Les instances sont à charger avant les éléments fixes car + * des références au premières peuvent être attendues dans ces derniers. + * + * Les évolutions de la tête de lecture n'ont en revanche normalement + * pas d'incidence sur le chargement des éléments fixes. + */ + + for (i = 0; i < kstruct->instances_count; i++) { - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]), - locals, content, pos, &child); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]), + locals, content, epos, &child); if (!result) goto exit; if (child != NULL) @@ -730,10 +803,16 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop } - for (i = 0; i < kstruct->instances_count; i++) + /** + * Seconde phase. + */ + + locals->parent = *record; + + for (i = 0; i < kstruct->seq_items_count; i++) { - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->instances[i]), - locals, content, pos, &child); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(kstruct->seq_items[i]), + locals, content, epos, &child); if (!result) goto exit; if (child != NULL) @@ -748,6 +827,9 @@ static bool g_kaitai_structure_parse_content(GKaitaiStruct *kstruct, kaitai_scop locals->parent = old; + if (!result) + g_clear_object(record); + } return result; diff --git a/plugins/kaitai/parsers/switch.c b/plugins/kaitai/parsers/switch.c index c823f27..6cfc96b 100644 --- a/plugins/kaitai/parsers/switch.c +++ b/plugins/kaitai/parsers/switch.c @@ -83,7 +83,7 @@ static void g_kaitai_switch_finalize(GKaitaiSwitch *); /* Parcourt un contenu binaire selon des spécifications Kaitai. */ -static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, vmpa2t *, GMatchRecord **); +static bool g_kaitai_switch_parse_content(GKaitaiSwitch *, kaitai_scope_t *, GBinContent *, ext_vmpa_t *, GMatchRecord **); @@ -285,7 +285,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca { if (value->type == GVT_UNSIGNED_INTEGER) { - unsigned_conv = strtoull(swcase->value, NULL, 10); + unsigned_conv = strtoull(swcase->value, NULL, 0); valid = (errno != ERANGE && errno != EINVAL); @@ -295,7 +295,7 @@ static const char *is_suitable_switch_case_for_integer(const switch_case_t *swca } else { - signed_conv = strtoll(swcase->value, NULL, 10); + signed_conv = strtoll(swcase->value, NULL, 0); valid = (errno != ERANGE && errno != EINVAL); @@ -569,7 +569,7 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt * Paramètres : kswitch = structure Kaitai en cours de parcours. * * locals = variables locales pour les résolutions de types. * * content = données binaires à analyser et traduire. * -* pos = tête de lecture courante. [OUT] * +* epos = tête de lecture courante. [OUT] * * record = noeud d'arborescence d'éléments rencontrés. [OUT] * * * * Description : Parcourt un contenu binaire selon des spécifications Kaitai. * @@ -580,127 +580,65 @@ bool g_kaitai_switch_create(GKaitaiSwitch *kswitch, GYamlNode *parent, GKaitaiAt * * ******************************************************************************/ -static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, vmpa2t *pos, GMatchRecord **record) +static bool g_kaitai_switch_parse_content(GKaitaiSwitch *kswitch, kaitai_scope_t *locals, GBinContent *content, ext_vmpa_t *epos, GMatchRecord **record) { bool result; /* Bilan à retourner */ - GMatchRecord *reference; /* Correspondance à utiliser */ - GKaitaiParser *creator; /* Lecteur d'origine */ - KaitaiAttributePayload payload; /* Type de charge supportée */ - BaseType basic; /* Type de base reconnu */ - bool is_string; /* Type lié à une chaîne ? */ -#ifndef NDEBUG - bool status; /* Bilan d'une consultation */ -#endif const char *final_type; /* Type à utiliser au final */ resolved_value_t value; /* Valeur de cible entière */ + bool status; /* Bilan intermédiaire */ size_t i; /* Boucle de parcours */ GKaitaiAttribute *attrib; /* Lecteur approprié */ - result = false; - - /* Détermination de la forme de comparaison */ - - reference = g_match_record_find_by_name(locals->parent, - kswitch->target, strlen(kswitch->target), - DIRECT_SEARCH_DEEP_LEVEL); - - if (reference == NULL) - goto exit; - - creator = g_match_record_get_creator(reference); - - if (creator == NULL) - goto exit_with_ref; - - if (!G_IS_KAITAI_ATTRIBUTE(creator)) - goto exit_with_creator; - - payload = g_kaitai_attribute_get_payload(G_KAITAI_ATTRIBUTE(creator)); - - if ((payload & KAP_BASIC_TYPE) == 0) - goto exit_with_creator; - -#ifndef NDEBUG - status = g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string); - assert(status); -#else - g_kaitai_attribute_get_basic_type(G_KAITAI_ATTRIBUTE(creator), &basic, &is_string); -#endif - - /* Détermination du type visé */ + result = true; final_type = NULL; - if (is_string) - { - result = resolve_kaitai_expression_as_bytes(locals, - kswitch->target, - strlen(kswitch->target), - &value); - if (!result) goto exit_with_creator; + /* Tenative n°1 : version "entier" */ + + status = resolve_kaitai_expression_as_integer(locals, kswitch->target, strlen(kswitch->target), &value); + if (status) for (i = 0; i < kswitch->count; i++) { - final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value); + final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value); if (final_type != NULL) - break; + goto next_step; } - } - - else - { - if (basic == BTP_UCHAR || basic == BTP_USHORT || basic == BTP_UINT || basic == BTP_ULONG_LONG) - { - result = resolve_kaitai_expression_as_integer(locals, - kswitch->target, - strlen(kswitch->target), - &value); - if (!result) goto exit_with_creator; + status = resolve_kaitai_expression_as_bytes(locals, kswitch->target, strlen(kswitch->target), &value); - for (i = 0; i < kswitch->count; i++) - { - final_type = is_suitable_switch_case_for_integer(kswitch->cases[i], locals, &value); + /* Tenative n°1 : version "chaîne" */ - if (final_type != NULL) - break; + if (status) + for (i = 0; i < kswitch->count; i++) + { + final_type = is_suitable_switch_case_for_bytes(kswitch->cases[i], &value); - } + if (final_type != NULL) + goto next_step; } - else - printf("other type: %u\n", basic); - - } - if (final_type == NULL && kswitch->defcase != NULL) final_type = kswitch->defcase->type; + next_step: + /* Mise en place d'un attribut et analyse */ if (final_type != NULL) { attrib = g_kaitai_attribute_dup_for_user_type(kswitch->generic, final_type); - result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, pos, record); + result = g_kaitai_parser_parse_content(G_KAITAI_PARSER(attrib), locals, content, epos, record); g_object_unref(G_OBJECT(attrib)); } - exit_with_creator: - - g_object_unref(G_OBJECT(creator)); - - exit_with_ref: - - g_object_unref(G_OBJECT(reference)); - - exit: - + return true; return result; } diff --git a/plugins/kaitai/parsers/type-int.h b/plugins/kaitai/parsers/type-int.h index 4a4d939..535ce57 100644 --- a/plugins/kaitai/parsers/type-int.h +++ b/plugins/kaitai/parsers/type-int.h @@ -50,6 +50,9 @@ struct _GKaitaiTypeClass /* Met en place un lecteur de type pour Kaitai. */ bool g_kaitai_type_create(GKaitaiType *, GYamlNode *); +/* Met en place un lecteur de type externe pour Kaitai. */ +bool g_kaitai_type_create_as_import(GKaitaiType *, const char *, const char *); + #endif /* PLUGINS_KAITAI_PARSERS_TYPE_INT_H */ diff --git a/plugins/kaitai/parsers/type.c b/plugins/kaitai/parsers/type.c index 30d0373..81efbeb 100644 --- a/plugins/kaitai/parsers/type.c +++ b/plugins/kaitai/parsers/type.c @@ -215,6 +215,64 @@ bool g_kaitai_type_create(GKaitaiType *type, GYamlNode *parent) /****************************************************************************** * * +* Paramètres : name = nom à attribuer au futur type. * +* filename = chemin vers une définition Kaitai à charger. * +* * +* Description : Construit un lecteur de type externe pour Kaitai. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiType *g_kaitai_type_new_as_import(const char *name, const char *filename) +{ + GKaitaiType *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_TYPE, NULL); + + if (!g_kaitai_type_create_as_import(result, name, filename)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = lecteur de type Kaitai à initialiser pleinement. * +* name = nom à attribuer au futur type. * +* filename = chemin vers une définition Kaitai à charger. * +* * +* Description : Met en place un lecteur de type externe pour Kaitai. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_type_create_as_import(GKaitaiType *type, const char *name, const char *filename) +{ + bool result; /* Bilan à retourner */ + + /* Extraction du nom */ + + type->name = strdup(name); + + /* Extraction des bases du type */ + + result = g_kaitai_structure_create_from_file(G_KAITAI_STRUCT(type), filename); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : type = définition de type particulier à consulter. * * * * Description : Indique le nom de scène du type représenté. * diff --git a/plugins/kaitai/parsers/type.h b/plugins/kaitai/parsers/type.h index 0656c64..d19ab90 100644 --- a/plugins/kaitai/parsers/type.h +++ b/plugins/kaitai/parsers/type.h @@ -54,6 +54,9 @@ GType g_kaitai_type_get_type(void); /* Construit un lecteur de type pour Kaitai. */ GKaitaiType *g_kaitai_type_new(GYamlNode *); +/* Construit un lecteur de type externe pour Kaitai. */ +GKaitaiType *g_kaitai_type_new_as_import(const char *, const char *); + /* Indique le nom de scène du type représenté. */ const char *g_kaitai_type_get_name(const GKaitaiType *); diff --git a/plugins/kaitai/python/Makefile.am b/plugins/kaitai/python/Makefile.am index ab40744..f222a66 100644 --- a/plugins/kaitai/python/Makefile.am +++ b/plugins/kaitai/python/Makefile.am @@ -11,7 +11,8 @@ libkaitaipython_la_SOURCES = \ libkaitaipython_la_LIBADD = \ parsers/libkaitaipythonparsers.la \ - records/libkaitaipythonrecords.la + records/libkaitaipythonrecords.la \ + rost/libkaitaipythonrost.la libkaitaipython_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT @@ -22,4 +23,4 @@ devdir = $(includedir)/chrysalide-$(subdir) dev_HEADERS = $(libkaitaipython_la_SOURCES:%c=) -SUBDIRS = parsers records +SUBDIRS = parsers records rost diff --git a/plugins/kaitai/python/module.c b/plugins/kaitai/python/module.c index fa1f9c2..07fb962 100644 --- a/plugins/kaitai/python/module.c +++ b/plugins/kaitai/python/module.c @@ -39,6 +39,7 @@ #include "stream.h" #include "parsers/module.h" #include "records/module.h" +#include "rost/module.h" @@ -89,6 +90,7 @@ bool add_kaitai_module_to_python_module(void) if (result) result = add_kaitai_parsers_module(); if (result) result = add_kaitai_records_module(); + if (result) result = add_kaitai_rost_module(); if (!result) Py_XDECREF(module); @@ -124,6 +126,7 @@ bool populate_kaitai_module(void) if (result) result = populate_kaitai_parsers_module(); if (result) result = populate_kaitai_records_module(); + if (result) result = populate_kaitai_rost_module(); assert(result); diff --git a/plugins/kaitai/python/parsers/attribute.c b/plugins/kaitai/python/parsers/attribute.c index c8ea314..c2f3db6 100644 --- a/plugins/kaitai/python/parsers/attribute.c +++ b/plugins/kaitai/python/parsers/attribute.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * attribute.h - équivalent Python du fichier "plugins/kaitai/parsers/attribute.h" + * attribute.c - équivalent Python du fichier "plugins/kaitai/parsers/attribute.c" * * Copyright (C) 2019 Cyrille Bagard * @@ -149,9 +149,14 @@ static PyObject *py_kaitai_attribute_get_raw_id(PyObject *self, void *closure) attrib = G_KAITAI_ATTRIBUTE(pygobject_get(self)); value = g_kaitai_attribute_get_raw_id(attrib); - assert(value != NULL); - result = PyUnicode_FromString(value); + if (value == NULL) + { + result = Py_None; + Py_INCREF(result); + } + else + result = PyUnicode_FromString(value); return result; diff --git a/plugins/kaitai/python/parsers/meta.c b/plugins/kaitai/python/parsers/meta.c index 3432640..0bd7bf9 100644 --- a/plugins/kaitai/python/parsers/meta.c +++ b/plugins/kaitai/python/parsers/meta.c @@ -50,6 +50,9 @@ static PyObject *py_kaitai_meta_get_id(PyObject *, void *); /* Fournit la désignation humaine d'une définiton Kaitai. */ static PyObject *py_kaitai_meta_get_title(PyObject *, void *); +/* Indique la liste des définitions à importer. */ +static PyObject *py_kaitai_meta_get_dependencies(PyObject *, void *); + /****************************************************************************** @@ -162,7 +165,7 @@ static PyObject *py_kaitai_meta_get_id(PyObject *self, void *closure) * * * Description : Fournit la désignation humaine d'une définiton Kaitai. * * * -* Retour : Intitulé de définition OU None. * +* Retour : Intitulé de définition ou None. * * * * Remarques : - * * * @@ -206,7 +209,7 @@ static PyObject *py_kaitai_meta_get_title(PyObject *self, void *closure) * * * Description : Fournit la désignation humaine d'une définiton Kaitai. * * * -* Retour : Intitulé de définition OU None. * +* Retour : Intitulé de définition ou None. * * * * Remarques : - * * * @@ -238,6 +241,50 @@ static PyObject *py_kaitai_meta_get_endian(PyObject *self, void *closure) /****************************************************************************** * * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique la liste des définitions à importer. * +* * +* Retour : Liste de désignations de définitions, vide ou non. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_kaitai_meta_get_dependencies(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GKaitaiMeta *meta; /* Version native de l'objet */ + const char * const *dependencies; /* Liste d'imports requis */ + size_t count; /* Quantité de ces imports */ + size_t i; /* Boucle de parcours */ + +#define KAITAI_META_DEPENDENCIES_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + dependencies, py_kaitai_meta, \ + "Tuple of all definitions to import for the current" \ + " definition.\n" \ + "\n" \ + "The result may be an empty string list." \ +) + + meta = G_KAITAI_META(pygobject_get(self)); + + dependencies = g_kaitai_meta_get_dependencies(meta, &count); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + PyTuple_SetItem(result, i, PyUnicode_FromString(dependencies[i])); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -258,6 +305,7 @@ PyTypeObject *get_python_kaitai_meta_type(void) KAITAI_META_ID_ATTRIB, KAITAI_META_TITLE_ATTRIB, KAITAI_META_ENDIAN_ATTRIB, + KAITAI_META_DEPENDENCIES_ATTRIB, { NULL } }; diff --git a/plugins/kaitai/python/records/Makefile.am b/plugins/kaitai/python/records/Makefile.am index 1413228..3a3c672 100644 --- a/plugins/kaitai/python/records/Makefile.am +++ b/plugins/kaitai/python/records/Makefile.am @@ -2,12 +2,13 @@ noinst_LTLIBRARIES = libkaitaipythonrecords.la libkaitaipythonrecords_la_SOURCES = \ + bits.h bits.c \ + delayed.h delayed.c \ empty.h empty.c \ group.h group.c \ item.h item.c \ list.h list.c \ - module.h module.c \ - value.h value.c + module.h module.c libkaitaipythonrecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT diff --git a/plugins/kaitai/python/records/bits.c b/plugins/kaitai/python/records/bits.c new file mode 100644 index 0000000..f94148b --- /dev/null +++ b/plugins/kaitai/python/records/bits.c @@ -0,0 +1,318 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits.h - équivalent Python du fichier "plugins/kaitai/parsers/bits.h" + * + * Copyright (C) 2019 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "bits.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/content.h> +#include <plugins/pychrysalide/arch/vmpa.h> + + +#include "../record.h" +#include "../parsers/attribute.h" +#include "../../records/bits-int.h" + + + +CREATE_DYN_CONSTRUCTOR(record_bit_field, G_TYPE_RECORD_BIT_FIELD); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_record_bit_field_init(PyObject *, PyObject *, PyObject *); + +/* Lit la valeur d'un élément Kaitai entier représenté. */ +static PyObject *py_record_bit_field_get_value(PyObject *, void *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_record_bit_field_init(PyObject *self, PyObject *args, PyObject *kwds) +{ +#if 0 + GKaitaiAttribute *attrib; /* Attribut défini créateur */ + GBinContent *content; /* Contenu binaire analysé */ + mrange_t range; /* Espace couvert */ + SourceEndian endian; /* Boutisme à observer */ + int ret; /* Bilan de lecture des args. */ + GRecordBitField *field; /* Création GLib à transmettre */ +#endif + +#define RECORD_BIT_FIELD_DOC \ + "The RecordItem class remembers a match between a described attribute and" \ + " its concret value read from parsed binary data." \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " RecordItem(content, range, endian, attrib)" \ + "\n" \ + "Where the *attrib* arguments refers to a" \ + " pychrysalide.plugins.kaitai.parsers.KaitaiAttribute instance as the" \ + " creator of the newly created object, *content* points to a" \ + " pychrysalide.analysis.BinContent instance, *range* is a" \ + " pychrysalide.arch.mrange object, *endian* states with a" \ + " pychrysalide.analysis.BinContent.SourceEndian hint the endianness used" \ + " to read integer values." + + /* Récupération des paramètres */ + +#if 0 /* FIXME */ + + ret = PyArg_ParseTuple(args, "O&O&O&", + convert_to_kaitai_attribute, &attrib, + convert_to_binary_content, &content, + convert_any_to_mrange, &range, + convert_to_binary_content, &endian); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + field = G_RECORD_BIT_FIELD(pygobject_get(self)); + + if (!g_record_bit_field_create(field, attrib, content, &range, endian)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create record bit field.")); + return -1; + } + + return 0; + +#endif + + PyErr_SetString(PyExc_ValueError, _("Unable to create record bit field at the moment.")); + return -1; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Lit la valeur d'un élément Kaitai entier représenté. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_record_bit_field_get_value(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GRecordBitField *field; /* Version native de l'élément */ + resolved_value_t resolved; /* Valeur sous forme générique */ + bool status; /* Bilan d'opération */ + +#define RECORD_BIT_FIELD_VALUE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + value, py_record_bit_field, \ + "Carried value (as integer), or None in case of error." \ +) + + result = NULL; + + field = G_RECORD_BIT_FIELD(pygobject_get(self)); + + status = g_record_bit_field_get_value(field, &resolved); + + if (status) + switch (resolved.type) + { + case GVT_UNSIGNED_INTEGER: + result = PyLong_FromUnsignedLongLong(resolved.unsigned_integer); + break; + + default: + assert(false); + result = Py_None; + Py_INCREF(result); + break; + + } + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_record_bit_field_type(void) +{ + static PyMethodDef py_record_bit_field_methods[] = { + { NULL } + }; + + static PyGetSetDef py_record_bit_field_getseters[] = { + RECORD_BIT_FIELD_VALUE_ATTRIB, + { NULL } + }; + + static PyTypeObject py_record_bit_field_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.records.RecordBitField", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = RECORD_BIT_FIELD_DOC, + + .tp_methods = py_record_bit_field_methods, + .tp_getset = py_record_bit_field_getseters, + + .tp_init = py_record_bit_field_init, + .tp_new = py_record_bit_field_new, + + }; + + return &py_record_bit_field_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide.....RecordBitField. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_record_bit_field_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'RecordItem' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_record_bit_field_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.records"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_match_record_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_RECORD_BIT_FIELD, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en correspondance attribut/binaire. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_record_bit_field(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_record_bit_field_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record bit field"); + break; + + case 1: + *((GRecordBitField **)dst) = G_RECORD_BIT_FIELD(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/records/bits.h b/plugins/kaitai/python/records/bits.h new file mode 100644 index 0000000..6c833bb --- /dev/null +++ b/plugins/kaitai/python/records/bits.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/bits.h" + * + * Copyright (C) 2019 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H +#define _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_record_bit_field_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordBitField'. */ +bool ensure_python_record_bit_field_is_registered(void); + +/* Tente de convertir en correspondance attribut/binaire. */ +int convert_to_record_bit_field(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_BITS_H */ diff --git a/plugins/kaitai/python/records/value.c b/plugins/kaitai/python/records/delayed.c index bd4ad74..32e3db1 100644 --- a/plugins/kaitai/python/records/value.c +++ b/plugins/kaitai/python/records/delayed.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value.c - équivalent Python du fichier "plugins/kaitai/parsers/value.c" + * delayed.c - équivalent Python du fichier "plugins/kaitai/parsers/delayed.c" * * Copyright (C) 2019 Cyrille Bagard * @@ -22,7 +22,7 @@ */ -#include "value.h" +#include "delayed.h" #include <assert.h> @@ -40,17 +40,17 @@ #include "../record.h" #include "../scope.h" #include "../parsers/instance.h" -#include "../../records/value-int.h" +#include "../../records/delayed-int.h" -CREATE_DYN_CONSTRUCTOR(record_value, G_TYPE_RECORD_VALUE); +CREATE_DYN_CONSTRUCTOR(record_delayed, G_TYPE_RECORD_DELAYED); /* Initialise une instance sur la base du dérivé de GObject. */ -static int py_record_value_init(PyObject *, PyObject *, PyObject *); +static int py_record_delayed_init(PyObject *, PyObject *, PyObject *); /* Lit la valeur d'un élément Kaitai entier représenté. */ -static PyObject *py_record_value_get_value(PyObject *, void *); +static PyObject *py_record_delayed_get_value(PyObject *, void *); @@ -68,31 +68,37 @@ static PyObject *py_record_value_get_value(PyObject *, void *); * * ******************************************************************************/ -static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds) +static int py_record_delayed_init(PyObject *self, PyObject *args, PyObject *kwds) { GKaitaiInstance *inst; /* Instance définie créatrice */ kaitai_scope_t *locals; /* Environnement local */ + GBinContent *content; /* Contenu binaire analysé */ int ret; /* Bilan de lecture des args. */ - GRecordValue *value; /* Création GLib à transmettre */ + GRecordDelayed *delayed; /* Création GLib à transmettre */ -#define RECORD_VALUE_DOC \ - "The RecordValue class stores a link to an instance used to compute a" \ +#define RECORD_DELAYED_DOC \ + "The RecordDelayed class stores a link to an instance used to compute a" \ " given value." \ "\n" \ "Instances can be created using the following constructor:\n" \ "\n" \ - " RecordValue(inst, locals)" \ + " RecordDelayed(inst, locals, content)" \ "\n" \ "Where the *inst* arguments refers to a" \ " pychrysalide.plugins.kaitai.parsers.KaitaiInstance instance as the" \ " creator of the newly created object, *locals* points to a" \ - " pychrysalide.plugins.kaitai.KaitaiScope structure used as current scope." + " pychrysalide.plugins.kaitai.KaitaiScope structure used as current scope." \ + " The *content* argument is a pychrysalide.analysis.BinContent instance if" \ + " the delayed instance does not define a direct value." /* Récupération des paramètres */ - ret = PyArg_ParseTuple(args, "O&O&", + content = NULL; + + ret = PyArg_ParseTuple(args, "O&O&|O&", convert_to_kaitai_instance, &inst, - convert_to_kaitai_scope, &locals); + convert_to_kaitai_scope, &locals, + convert_to_binary_content_or_none, &content); if (!ret) return -1; /* Initialisation d'un objet GLib */ @@ -102,11 +108,11 @@ static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds) /* Eléments de base */ - value = G_RECORD_VALUE(pygobject_get(self)); + delayed = G_RECORD_DELAYED(pygobject_get(self)); - if (!g_record_value_create(value, inst, locals)) + if (!g_record_delayed_create(delayed, inst, locals, content)) { - PyErr_SetString(PyExc_ValueError, _("Unable to create record value.")); + PyErr_SetString(PyExc_ValueError, _("Unable to create record delayed.")); return -1; } @@ -128,24 +134,24 @@ static int py_record_value_init(PyObject *self, PyObject *args, PyObject *kwds) * * ******************************************************************************/ -static PyObject *py_record_value_get_value(PyObject *self, void *closure) +static PyObject *py_record_delayed_get_value(PyObject *self, void *closure) { PyObject *result; /* Valeur à retourner */ - GRecordValue *value; /* Version native de l'élément */ + GRecordDelayed *delayed; /* Version native de l'élément */ resolved_value_t resolved; /* Valeur sous forme générique */ bool status; /* Bilan d'opération */ -#define RECORD_VALUE_VALUE_ATTRIB PYTHON_GET_DEF_FULL \ +#define RECORD_DELAYED_VALUE_ATTRIB PYTHON_GET_DEF_FULL \ ( \ - value, py_record_value, \ + value, py_record_delayed, \ "Carried value (as integer, bytes), or None in case of error." \ ) result = NULL; - value = G_RECORD_VALUE(pygobject_get(self)); + delayed = G_RECORD_DELAYED(pygobject_get(self)); - status = g_record_value_compute_and_aggregate_value(value, &resolved); + status = g_record_delayed_compute_and_aggregate_value(delayed, &resolved); if (status) switch (resolved.type) @@ -216,37 +222,37 @@ static PyObject *py_record_value_get_value(PyObject *self, void *closure) * * ******************************************************************************/ -PyTypeObject *get_python_record_value_type(void) +PyTypeObject *get_python_record_delayed_type(void) { - static PyMethodDef py_record_value_methods[] = { + static PyMethodDef py_record_delayed_methods[] = { { NULL } }; - static PyGetSetDef py_record_value_getseters[] = { - RECORD_VALUE_VALUE_ATTRIB, + static PyGetSetDef py_record_delayed_getseters[] = { + RECORD_DELAYED_VALUE_ATTRIB, { NULL } }; - static PyTypeObject py_record_value_type = { + static PyTypeObject py_record_delayed_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.plugins.kaitai.records.RecordValue", + .tp_name = "pychrysalide.plugins.kaitai.records.RecordDelayed", .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = RECORD_VALUE_DOC, + .tp_doc = RECORD_DELAYED_DOC, - .tp_methods = py_record_value_methods, - .tp_getset = py_record_value_getseters, + .tp_methods = py_record_delayed_methods, + .tp_getset = py_record_delayed_getseters, - .tp_init = py_record_value_init, - .tp_new = py_record_value_new, + .tp_init = py_record_delayed_init, + .tp_new = py_record_delayed_new, }; - return &py_record_value_type; + return &py_record_delayed_type; } @@ -255,7 +261,7 @@ PyTypeObject *get_python_record_value_type(void) * * * Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide...records.RecordValue. * +* Description : Prend en charge l'objet 'pychrysalide..records.RecordDelayed.* * * * Retour : Bilan de l'opération. * * * @@ -263,13 +269,13 @@ PyTypeObject *get_python_record_value_type(void) * * ******************************************************************************/ -bool ensure_python_record_value_is_registered(void) +bool ensure_python_record_delayed_is_registered(void) { - PyTypeObject *type; /* Type Python 'RecordValue' */ + PyTypeObject *type; /* Type Python 'RecordDelayed' */ PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ - type = get_python_record_value_type(); + type = get_python_record_delayed_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) { @@ -280,7 +286,7 @@ bool ensure_python_record_value_is_registered(void) if (!ensure_python_match_record_is_registered()) return false; - if (!register_class_for_pygobject(dict, G_TYPE_RECORD_VALUE, type)) + if (!register_class_for_pygobject(dict, G_TYPE_RECORD_DELAYED, type)) return false; } @@ -303,11 +309,11 @@ bool ensure_python_record_value_is_registered(void) * * ******************************************************************************/ -int convert_to_record_value(PyObject *arg, void *dst) +int convert_to_record_delayed(PyObject *arg, void *dst) { int result; /* Bilan à retourner */ - result = PyObject_IsInstance(arg, (PyObject *)get_python_record_value_type()); + result = PyObject_IsInstance(arg, (PyObject *)get_python_record_delayed_type()); switch (result) { @@ -317,11 +323,11 @@ int convert_to_record_value(PyObject *arg, void *dst) break; case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record value"); + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to record delayed"); break; case 1: - *((GRecordValue **)dst) = G_RECORD_VALUE(pygobject_get(arg)); + *((GRecordDelayed **)dst) = G_RECORD_DELAYED(pygobject_get(arg)); break; default: diff --git a/plugins/kaitai/python/records/value.h b/plugins/kaitai/python/records/delayed.h index 16cadcb..ba2d23a 100644 --- a/plugins/kaitai/python/records/value.h +++ b/plugins/kaitai/python/records/delayed.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/value.h" + * delayed.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/records/delayed.h" * * Copyright (C) 2019 Cyrille Bagard * @@ -22,8 +22,8 @@ */ -#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H -#define _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H +#ifndef _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H +#define _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H #include <Python.h> @@ -32,14 +32,14 @@ /* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_record_value_type(void); +PyTypeObject *get_python_record_delayed_type(void); -/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordValue'. */ -bool ensure_python_record_value_is_registered(void); +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.records.RecordDelayed'. */ +bool ensure_python_record_delayed_is_registered(void); /* Tente de convertir en valeur calculée. */ -int convert_to_record_value(PyObject *, void *); +int convert_to_record_delayed(PyObject *, void *); -#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_VALUE_H */ +#endif /* _PLUGINS_KAITAI_PYTHON_RECORDS_DELAYED_H */ diff --git a/plugins/kaitai/python/records/module.c b/plugins/kaitai/python/records/module.c index ea33c31..af97434 100644 --- a/plugins/kaitai/python/records/module.c +++ b/plugins/kaitai/python/records/module.c @@ -32,11 +32,12 @@ #include <plugins/pychrysalide/helpers.h> +#include "bits.h" +#include "delayed.h" #include "empty.h" #include "group.h" #include "item.h" #include "list.h" -#include "value.h" @@ -109,11 +110,12 @@ bool populate_kaitai_records_module(void) result = true; + if (result) result = ensure_python_record_bit_field_is_registered(); + if (result) result = ensure_python_record_delayed_is_registered(); if (result) result = ensure_python_record_empty_is_registered(); if (result) result = ensure_python_record_group_is_registered(); if (result) result = ensure_python_record_item_is_registered(); if (result) result = ensure_python_record_list_is_registered(); - if (result) result = ensure_python_record_value_is_registered(); assert(result); diff --git a/plugins/kaitai/python/rost/Makefile.am b/plugins/kaitai/python/rost/Makefile.am new file mode 100644 index 0000000..cae0419 --- /dev/null +++ b/plugins/kaitai/python/rost/Makefile.am @@ -0,0 +1,14 @@ + +noinst_LTLIBRARIES = libkaitaipythonrost.la + +libkaitaipythonrost_la_SOURCES = \ + module.h module.c \ + trigger.h trigger.c + +libkaitaipythonrost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libkaitaipythonrost_la_SOURCES:%c=) diff --git a/plugins/kaitai/python/rost/module.c b/plugins/kaitai/python/rost/module.c new file mode 100644 index 0000000..66a5a82 --- /dev/null +++ b/plugins/kaitai/python/rost/module.c @@ -0,0 +1,115 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire rost en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "trigger.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Ajoute le module 'plugins.kaitai.rost' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_kaitai_rost_module(void) +{ + bool result; /* Bilan à retourner */ + PyObject *super; /* Module à compléter */ + PyObject *module; /* Sous-module mis en place */ + +#define PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC \ + "This module creates some glue to extend the ROST features" \ + " using Kaitai definitions for analyzing and filtering" \ + " contents." + + static PyModuleDef py_chrysalide_kaitai_rost_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.plugins.kaitai.rost", + .m_doc = PYCHRYSALIDE_PLUGINS_KAITAI_ROST_DOC, + + .m_size = -1, + + }; + + result = false; + + super = get_access_to_python_module("pychrysalide.plugins.kaitai"); + + module = build_python_module(super, &py_chrysalide_kaitai_rost_module); + + result = (module != NULL); + + assert(result); + + if (!result) + Py_XDECREF(module); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les objets du module 'plugins.kaitai.rost'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool populate_kaitai_rost_module(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_kaitai_trigger_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/kaitai/python/rost/module.h b/plugins/kaitai/python/rost/module.h new file mode 100644 index 0000000..8415c2e --- /dev/null +++ b/plugins/kaitai/python/rost/module.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire rost en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H +#define _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H + + +#include <stdbool.h> + + + +/* Ajoute le module 'plugins.kaitai.rost' au module Python. */ +bool add_kaitai_rost_module(void); + +/* Intègre les objets du module 'plugins.kaitai.rost'. */ +bool populate_kaitai_rost_module(void); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_ROST_MODULE_H */ diff --git a/plugins/kaitai/python/rost/trigger.c b/plugins/kaitai/python/rost/trigger.c new file mode 100644 index 0000000..180ef6e --- /dev/null +++ b/plugins/kaitai/python/rost/trigger.c @@ -0,0 +1,236 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger.c - équivalent Python du fichier "plugins/kaitai/rost/trigger.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "trigger.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/scan/item.h> + + +#include "../parsers/struct.h" +#include "../../parsers/struct.h" +#include "../../rost/trigger-int.h" + + + +CREATE_DYN_CONSTRUCTOR(kaitai_trigger, G_TYPE_KAITAI_TRIGGER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_kaitai_trigger_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_kaitai_trigger_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GKaitaiStruct *kstruct; /* Définition Kaitai en place */ + int ret; /* Bilan de lecture des args. */ + GKaitaiTrigger *trigger; /* Création GLib à transmettre */ + +#define KAITAI_TRIGGER_DOC \ + "The KaitaiTrigger object store an access to a loaded Kaitai definition" \ + " creates as many as required instances from it when ROST filters contents" \ + " with the help of the Kaitai module.\n" \ + "\n" \ + "Instances can be created using following constructor:\n" \ + "\n" \ + " KaitaiTrigger(kstruct)" \ + "\n" \ + "Where *kstruct* is a pychrysalide.plugins.kaitai.parsers.KaitaiStruct" \ + " instance loaded with a valid Kaitai definition." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_kaitai_structure, &kstruct); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + trigger = G_KAITAI_TRIGGER(pygobject_get(self)); + + if (!g_kaitai_trigger_create(trigger, kstruct)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create Kaitai stream.")); + return -1; + + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_kaitai_trigger_type(void) +{ + static PyMethodDef py_kaitai_trigger_methods[] = { + { NULL } + }; + + static PyGetSetDef py_kaitai_trigger_getseters[] = { + { NULL } + }; + + static PyTypeObject py_kaitai_trigger_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.plugins.kaitai.rost.KaitaiTrigger", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = KAITAI_TRIGGER_DOC, + + .tp_methods = py_kaitai_trigger_methods, + .tp_getset = py_kaitai_trigger_getseters, + + .tp_init = py_kaitai_trigger_init, + .tp_new = py_kaitai_trigger_new, + + }; + + return &py_kaitai_trigger_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....rost.KaitaiTrigger. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_kaitai_trigger_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'RecordEmpty' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_kaitai_trigger_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.plugins.kaitai.rost"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_scan_registered_item_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_KAITAI_TRIGGER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en accès à une définition Kaitai. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_kaitai_trigger(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_kaitai_trigger_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Kaitai trigger"); + break; + + case 1: + *((GKaitaiTrigger **)dst) = G_KAITAI_TRIGGER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/kaitai/python/rost/trigger.h b/plugins/kaitai/python/rost/trigger.h new file mode 100644 index 0000000..44776f7 --- /dev/null +++ b/plugins/kaitai/python/rost/trigger.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger.h - prototypes pour l'équivalent Python du fichier "plugins/kaitai/rost/trigger.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H +#define _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_kaitai_trigger_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.kaitai.rost.KaitaiTrigger'. */ +bool ensure_python_kaitai_trigger_is_registered(void); + +/* Tente de convertir en accès à une définition Kaitai. */ +int convert_to_kaitai_trigger(PyObject *, void *); + + + +#endif /* _PLUGINS_KAITAI_PYTHON_ROST_TRIGGER_H */ diff --git a/plugins/kaitai/record.c b/plugins/kaitai/record.c index 5717b17..de1e80d 100644 --- a/plugins/kaitai/record.c +++ b/plugins/kaitai/record.c @@ -115,6 +115,10 @@ static void g_match_record_init(GMatchRecord *record) static void g_match_record_dispose(GMatchRecord *record) { + g_clear_object(&record->creator); + + g_clear_object(&record->content); + G_OBJECT_CLASS(g_match_record_parent_class)->dispose(G_OBJECT(record)); } @@ -331,12 +335,16 @@ static GMatchRecord *_g_match_record_find_by_name(GMatchRecord *record, const ch { label = g_kaitai_attribute_get_label(G_KAITAI_ATTRIBUTE(record->creator)); - label_len = strlen(label); - - if (label_len == len && strncmp(label, name, len) == 0) + if (label != NULL) { - result = record; - g_object_ref(G_OBJECT(result)); + label_len = strlen(label); + + if (label_len == len && strncmp(label, name, len) == 0) + { + result = record; + g_object_ref(G_OBJECT(result)); + } + } } diff --git a/plugins/kaitai/records/Makefile.am b/plugins/kaitai/records/Makefile.am index c11e823..3884bfb 100644 --- a/plugins/kaitai/records/Makefile.am +++ b/plugins/kaitai/records/Makefile.am @@ -2,6 +2,10 @@ noinst_LTLIBRARIES = libkaitairecords.la libkaitairecords_la_SOURCES = \ + bits-int.h \ + bits.h bits.c \ + delayed-int.h \ + delayed.h delayed.c \ empty-int.h \ empty.h empty.c \ group-int.h \ @@ -9,9 +13,7 @@ libkaitairecords_la_SOURCES = \ item-int.h \ item.h item.c \ list-int.h \ - list.h list.c \ - value-int.h \ - value.h value.c + list.h list.c libkaitairecords_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src diff --git a/plugins/kaitai/records/bits-int.h b/plugins/kaitai/records/bits-int.h new file mode 100644 index 0000000..7b03911 --- /dev/null +++ b/plugins/kaitai/records/bits-int.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits-int.h - prototypes internes pour la conservation d'un champ de bits entre attribut et binaire + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_RECORDS_BITS_INT_H +#define _PLUGINS_KAITAI_RECORDS_BITS_INT_H + + +#include "bits.h" + + +#include "../record-int.h" + + + +/* Correspondance de bits établie entre un attribut et du binaire (instance) */ +struct _GRecordBitField +{ + GMatchRecord parent; /* A laisser en premier */ + + ext_vmpa_t epos; /* Point de départ */ + uint8_t size; /* Quantité de bits concernés */ + SourceEndian endian; /* Boutisme des données imposé */ + +}; + +/* Correspondance de bits établie entre un attribut et du binaire (classe) */ +struct _GRecordBitFieldClass +{ + GMatchRecordClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une correspondance entre attribut et binaire. */ +bool g_record_bit_field_create(GRecordBitField *, GKaitaiAttribute *, GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian); + + + +#endif /* _PLUGINS_KAITAI_RECORDS_BITS_INT_H */ diff --git a/plugins/kaitai/records/bits.c b/plugins/kaitai/records/bits.c new file mode 100644 index 0000000..d224112 --- /dev/null +++ b/plugins/kaitai/records/bits.c @@ -0,0 +1,283 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits.c - conservation d'un champ de bits entre attribut et binaire + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "bits.h" + + +#include <assert.h> +#include <string.h> + + +#include "bits-int.h" + + + +/* -------------------- DEFINITION D'UNE CORRESPONDANCE UNITAIRE -------------------- */ + + +/* Initialise la classe des correspondances attribut/binaire. */ +static void g_record_bit_field_class_init(GRecordBitFieldClass *); + +/* Initialise une correspondance entre attribut et binaire. */ +static void g_record_bit_field_init(GRecordBitField *); + +/* Supprime toutes les références externes. */ +static void g_record_bit_field_dispose(GRecordBitField *); + +/* Procède à la libération totale de la mémoire. */ +static void g_record_bit_field_finalize(GRecordBitField *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Calcule ou fournit la zone couverte par une correspondance. */ +static void g_record_bit_field_get_range(const GRecordBitField *, mrange_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UNE CORRESPONDANCE UNITAIRE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une correspondance entre un attribut et du binaire. */ +G_DEFINE_TYPE(GRecordBitField, g_record_bit_field, G_TYPE_MATCH_RECORD); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des correspondances attribut/binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_class_init(GRecordBitFieldClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GMatchRecordClass *record; /* Version parente de la classe*/ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_record_bit_field_dispose; + object->finalize = (GObjectFinalizeFunc)g_record_bit_field_finalize; + + record = G_MATCH_RECORD_CLASS(klass); + + record->get_range = (get_record_range_fc)g_record_bit_field_get_range; + +} + + +/****************************************************************************** +* * +* Paramètres : field = instance à initialiser. * +* * +* Description : Initialise une correspondance entre attribut et binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_init(GRecordBitField *field) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : field = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_dispose(GRecordBitField *field) +{ + G_OBJECT_CLASS(g_record_bit_field_parent_class)->dispose(G_OBJECT(field)); + +} + + +/****************************************************************************** +* * +* Paramètres : field = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_finalize(GRecordBitField *field) +{ + G_OBJECT_CLASS(g_record_bit_field_parent_class)->finalize(G_OBJECT(field)); + +} + + +/****************************************************************************** +* * +* Paramètres : attrib = analyseur à l'origine de la correspondance. * +* content = contenu binaire lié à la correspondance. * +* epos = tête de lecture avec granularité en bits. * +* size = quantité de bits à prendre en compte. * +* endian = boustime des données à respecter. * +* * +* Description : Crée une nouvelle correspondance entre attribut et binaire. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GMatchRecord *g_record_bit_field_new(GKaitaiAttribute *attrib, GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian) +{ + GMatchRecord *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_RECORD_BIT_FIELD, NULL); + + if (!g_record_bit_field_create(G_RECORD_BIT_FIELD(result), attrib, content, epos, size, endian)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : field = correspondance à initialiser pleinement. * +* attrib = analyseur à l'origine de la correspondance. * +* content = contenu binaire lié à la correspondance. * +* epos = tête de lecture avec granularité en bits. * +* size = quantité de bits à prendre en compte. * +* endian = boustime des données à respecter. * +* * +* Description : Met en place une correspondance entre attribut et binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_record_bit_field_create(GRecordBitField *field, GKaitaiAttribute *attrib, GBinContent *content, const ext_vmpa_t *epos, uint8_t size, SourceEndian endian) +{ + bool result; /* Bilan à retourner */ + + result = g_match_record_create(G_MATCH_RECORD(field), G_KAITAI_PARSER(attrib), content); + + if (result) + { + copy_evmpa(&field->epos, epos); + field->size = size; + field->endian = endian; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : field = correspondance à consulter. * +* out = valeur à sauvegarder sous une forme générique. [OUT] * +* * +* Description : Lit la valeur d'un élément Kaitai entier représenté. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_record_bit_field_get_value(const GRecordBitField *field, resolved_value_t *out) +{ + bool result; /* Bilan à retourner */ + GKaitaiParser *parser; /* Attribut associé à l'élément*/ + + parser = g_match_record_get_creator(G_MATCH_RECORD(field)); + assert(G_IS_KAITAI_ATTRIBUTE(parser)); + + result = g_kaitai_attribute_read_bit_field_value(G_KAITAI_ATTRIBUTE(parser), + G_MATCH_RECORD(field)->content, + &field->epos, field->size, + field->endian, out); + + g_object_unref(G_OBJECT(parser)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : record = correspondance à consulter. * +* range = zone de couverture déterminée. [OUT] * +* * +* Description : Calcule ou fournit la zone couverte par une correspondance. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_record_bit_field_get_range(const GRecordBitField *record, mrange_t *range) +{ + phys_t len; /* Taille en octets */ + + len = record->size / 8; + + if (record->size % 8 > 0) + len ++; + + init_mrange(range, &record->epos.base, len); + +} diff --git a/plugins/kaitai/records/bits.h b/plugins/kaitai/records/bits.h new file mode 100644 index 0000000..923e8e3 --- /dev/null +++ b/plugins/kaitai/records/bits.h @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bits.h - prototypes pour la conservation d'un champ de bits entre attribut et binaire + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_RECORDS_BITS_H +#define _PLUGINS_KAITAI_RECORDS_BITS_H + + +#include <glib-object.h> + + +#include "../record.h" +#include "../parsers/attribute.h" + + + +#define G_TYPE_RECORD_BIT_FIELD g_record_bit_field_get_type() +#define G_RECORD_BIT_FIELD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_BIT_FIELD, GRecordBitField)) +#define G_IS_RECORD_BIT_FIELD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_BIT_FIELD)) +#define G_RECORD_BIT_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_BIT_FIELD, GRecordBitFieldClass)) +#define G_IS_RECORD_BIT_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_BIT_FIELD)) +#define G_RECORD_BIT_FIELD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_BIT_FIELD, GRecordBitFieldClass)) + + +/* Correspondance de bits établie entre un attribut et du binaire (instance) */ +typedef struct _GRecordBitField GRecordBitField; + +/* Correspondance de bits établie entre un attribut et du binaire (classe) */ +typedef struct _GRecordBitFieldClass GRecordBitFieldClass; + + +/* Indique le type défini pour une correspondance entre un attribut et du binaire. */ +GType g_record_bit_field_get_type(void); + +/* Crée une nouvelle correspondance entre attribut et binaire. */ +GMatchRecord *g_record_bit_field_new(GKaitaiAttribute *, GBinContent *, const ext_vmpa_t *, uint8_t, SourceEndian); + +/* Lit la valeur d'un élément Kaitai entier représenté. */ +bool g_record_bit_field_get_value(const GRecordBitField *, resolved_value_t *); + + + +#endif /* _PLUGINS_KAITAI_RECORDS_BITS_H */ diff --git a/plugins/kaitai/records/value-int.h b/plugins/kaitai/records/delayed-int.h index 6a84a7f..9275500 100644 --- a/plugins/kaitai/records/value-int.h +++ b/plugins/kaitai/records/delayed-int.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value-int.h - prototypes internes pour la conservation d'une instance virtuelle + * delayed-int.h - prototypes internes pour la conservation d'une instance virtuelle * * Copyright (C) 2019 Cyrille Bagard * @@ -21,11 +21,11 @@ */ -#ifndef _PLUGINS_KAITAI_RECORDS_VALUE_INT_H -#define _PLUGINS_KAITAI_RECORDS_VALUE_INT_H +#ifndef _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H +#define _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H -#include "value.h" +#include "delayed.h" #include "../record-int.h" @@ -33,16 +33,19 @@ /* Valeur calculée selon des correspondances parallèles (instance) */ -struct _GRecordValue +struct _GRecordDelayed { GMatchRecord parent; /* A laisser en premier */ kaitai_scope_t locals; /* Sauvegarde de contexte */ + bool has_value; /* Port d'une valeur directe ? */ + GMatchRecord *real_record; /* Enregistrement effectif */ + }; /* Valeur calculée selon des correspondances parallèles (classe) */ -struct _GRecordValueClass +struct _GRecordDelayedClass { GMatchRecordClass parent; /* A laisser en premier */ @@ -50,8 +53,8 @@ struct _GRecordValueClass /* Met en place une valeur calculée selon des correspondances. */ -bool g_record_value_create(GRecordValue *, GKaitaiInstance *, const kaitai_scope_t *); +bool g_record_delayed_create(GRecordDelayed *, GKaitaiInstance *, const kaitai_scope_t *, GBinContent *); -#endif /* _PLUGINS_KAITAI_RECORDS_VALUE_INT_H */ +#endif /* _PLUGINS_KAITAI_RECORDS_DELAYED_INT_H */ diff --git a/plugins/kaitai/records/value.c b/plugins/kaitai/records/delayed.c index cafe5c3..8c1395c 100644 --- a/plugins/kaitai/records/value.c +++ b/plugins/kaitai/records/delayed.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value.c - conservation d'une correspondance entre attribut et binaire + * delayed.c - conservation d'une correspondance entre attribut et binaire * * Copyright (C) 2019 Cyrille Bagard * @@ -21,7 +21,7 @@ */ -#include "value.h" +#include "delayed.h" #include <assert.h> @@ -29,7 +29,8 @@ #include <string.h> -#include "value-int.h" +#include "delayed-int.h" +#include "item.h" #include "../parsers/attribute.h" @@ -38,16 +39,16 @@ /* Initialise la classe des valeurs purement calculées. */ -static void g_record_value_class_init(GRecordValueClass *); +static void g_record_delayed_class_init(GRecordDelayedClass *); /* Initialise une correspondance entre attribut et binaire. */ -static void g_record_value_init(GRecordValue *); +static void g_record_delayed_init(GRecordDelayed *); /* Supprime toutes les références externes. */ -static void g_record_value_dispose(GRecordValue *); +static void g_record_delayed_dispose(GRecordDelayed *); /* Procède à la libération totale de la mémoire. */ -static void g_record_value_finalize(GRecordValue *); +static void g_record_delayed_finalize(GRecordDelayed *); @@ -55,7 +56,7 @@ static void g_record_value_finalize(GRecordValue *); /* Calcule ou fournit la zone couverte par une correspondance. */ -static void g_record_value_get_range(const GRecordValue *, mrange_t *); +static void g_record_delayed_get_range(const GRecordDelayed *, mrange_t *); @@ -65,7 +66,7 @@ static void g_record_value_get_range(const GRecordValue *, mrange_t *); /* Indique le type défini pour une valeur calculée selon des correspondances établies. */ -G_DEFINE_TYPE(GRecordValue, g_record_value, G_TYPE_MATCH_RECORD); +G_DEFINE_TYPE(GRecordDelayed, g_record_delayed, G_TYPE_MATCH_RECORD); /****************************************************************************** @@ -80,26 +81,26 @@ G_DEFINE_TYPE(GRecordValue, g_record_value, G_TYPE_MATCH_RECORD); * * ******************************************************************************/ -static void g_record_value_class_init(GRecordValueClass *klass) +static void g_record_delayed_class_init(GRecordDelayedClass *klass) { GObjectClass *object; /* Autre version de la classe */ GMatchRecordClass *record; /* Version parente de la classe*/ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_record_value_dispose; - object->finalize = (GObjectFinalizeFunc)g_record_value_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_record_delayed_dispose; + object->finalize = (GObjectFinalizeFunc)g_record_delayed_finalize; record = G_MATCH_RECORD_CLASS(klass); - record->get_range = (get_record_range_fc)g_record_value_get_range; + record->get_range = (get_record_range_fc)g_record_delayed_get_range; } /****************************************************************************** * * -* Paramètres : value = instance à initialiser. * +* Paramètres : delayed = instance à initialiser. * * * * Description : Initialise une correspondance entre attribut et binaire. * * * @@ -109,16 +110,18 @@ static void g_record_value_class_init(GRecordValueClass *klass) * * ******************************************************************************/ -static void g_record_value_init(GRecordValue *value) +static void g_record_delayed_init(GRecordDelayed *delayed) { - init_record_scope(&value->locals, NULL); + init_record_scope(&delayed->locals, NULL); + + delayed->real_record = NULL; } /****************************************************************************** * * -* Paramètres : value = instance d'objet GLib à traiter. * +* Paramètres : delayed = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -128,18 +131,18 @@ static void g_record_value_init(GRecordValue *value) * * ******************************************************************************/ -static void g_record_value_dispose(GRecordValue *value) +static void g_record_delayed_dispose(GRecordDelayed *delayed) { - reset_record_scope(&value->locals); + reset_record_scope(&delayed->locals); - G_OBJECT_CLASS(g_record_value_parent_class)->dispose(G_OBJECT(value)); + G_OBJECT_CLASS(g_record_delayed_parent_class)->dispose(G_OBJECT(delayed)); } /****************************************************************************** * * -* Paramètres : value = instance d'objet GLib à traiter. * +* Paramètres : delayed = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -149,17 +152,18 @@ static void g_record_value_dispose(GRecordValue *value) * * ******************************************************************************/ -static void g_record_value_finalize(GRecordValue *value) +static void g_record_delayed_finalize(GRecordDelayed *delayed) { - G_OBJECT_CLASS(g_record_value_parent_class)->finalize(G_OBJECT(value)); + G_OBJECT_CLASS(g_record_delayed_parent_class)->finalize(G_OBJECT(delayed)); } /****************************************************************************** * * -* Paramètres : inst = analyseur à l'origine de la correspondance. * -* locals = correspondances courantes pour résolutions. * +* Paramètres : inst = analyseur à l'origine de la correspondance. * +* locals = correspondances courantes pour résolutions. * +* content = contenu binaire lié à la correspondance. * * * * Description : Crée une nouvelle valeur calculée à partir d'une instance. * * * @@ -169,13 +173,13 @@ static void g_record_value_finalize(GRecordValue *value) * * ******************************************************************************/ -GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *locals) +GRecordDelayed *g_record_delayed_new(GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content) { - GRecordValue *result; /* Structure à retourner */ + GRecordDelayed *result; /* Structure à retourner */ - result = g_object_new(G_TYPE_RECORD_VALUE, NULL); + result = g_object_new(G_TYPE_RECORD_DELAYED, NULL); - if (!g_record_value_create(result, inst, locals)) + if (!g_record_delayed_create(result, inst, locals, content)) g_clear_object(&result); return result; @@ -185,9 +189,10 @@ GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *lo /****************************************************************************** * * -* Paramètres : value = correspondance à initialiser pleinement. * -* inst = analyseur à l'origine de la correspondance. * -* locals = correspondances courantes pour résolutions. * +* Paramètres : delayed = correspondance à initialiser pleinement. * +* inst = analyseur à l'origine de la correspondance. * +* locals = correspondances courantes pour résolutions. * +* content = contenu binaire lié à la correspondance. * * * * Description : Met en place une valeur calculée à partir d'une instance. * * * @@ -197,14 +202,14 @@ GRecordValue *g_record_value_new(GKaitaiInstance *inst, const kaitai_scope_t *lo * * ******************************************************************************/ -bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kaitai_scope_t *locals) +bool g_record_delayed_create(GRecordDelayed *delayed, GKaitaiInstance *inst, const kaitai_scope_t *locals, GBinContent *content) { bool result; /* Bilan à retourner */ - result = g_match_record_create(G_MATCH_RECORD(value), G_KAITAI_PARSER(inst), NULL); + result = g_match_record_create(G_MATCH_RECORD(delayed), G_KAITAI_PARSER(inst), content); if (result) - copy_record_scope(&value->locals, locals); + copy_record_scope(&delayed->locals, locals); return result; @@ -213,8 +218,8 @@ bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kai /****************************************************************************** * * -* Paramètres : value = correspondance à consulter. * -* value = valeur à sauvegarder sous une forme générique. [OUT] * +* Paramètres : delayed = correspondance à consulter. * +* out = valeur à sauvegarder sous forme générique. [OUT] * * * * Description : Détermine la valeur d'un élément Kaitai calculé. * * * @@ -224,17 +229,36 @@ bool g_record_value_create(GRecordValue *value, GKaitaiInstance *inst, const kai * * ******************************************************************************/ -bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *out) +bool g_record_delayed_compute_value(GRecordDelayed *delayed, resolved_value_t *out) { bool result; /* Bilan à retourner */ GKaitaiParser *parser; /* Instance liée à l'élément */ - parser = g_match_record_get_creator(G_MATCH_RECORD(value)); + parser = g_match_record_get_creator(G_MATCH_RECORD(delayed)); assert(G_IS_KAITAI_ATTRIBUTE(parser)); - result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser), - &value->locals, - out); + if (G_MATCH_RECORD(delayed)->content == NULL) + result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser), + &delayed->locals, + out); + + else + { + if (delayed->real_record == NULL) + delayed->real_record = g_kaitai_instance_compute_real_record(G_KAITAI_INSTANCE(parser), + &delayed->locals, + G_MATCH_RECORD(delayed)->content); + + if (delayed->real_record == NULL) + result = false; + + else + { + assert(G_IS_RECORD_ITEM(delayed->real_record)); + result = g_record_item_get_value(G_RECORD_ITEM(delayed->real_record), out); + } + + } g_object_unref(G_OBJECT(parser)); @@ -245,8 +269,8 @@ bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *o /****************************************************************************** * * -* Paramètres : value = correspondance à consulter. * -* value = valeur à sauvegarder sous une forme générique. [OUT] * +* Paramètres : delayed = correspondance à consulter. * +* out = valeur à sauvegarder sous forme générique. [OUT] * * * * Description : Détermine et ajuste la valeur d'un élément Kaitai calculé. * * * @@ -256,20 +280,12 @@ bool g_record_value_compute_value(const GRecordValue *value, resolved_value_t *o * * ******************************************************************************/ -bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resolved_value_t *out) +bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *delayed, resolved_value_t *out) { bool result; /* Bilan à retourner */ - GKaitaiParser *parser; /* Instance liée à l'élément */ sized_string_t converted; /* Conversion finale ? */ - parser = g_match_record_get_creator(G_MATCH_RECORD(value)); - assert(G_IS_KAITAI_ATTRIBUTE(parser)); - - result = g_kaitai_instance_compute_value(G_KAITAI_INSTANCE(parser), - &value->locals, - out); - - g_object_unref(G_OBJECT(parser)); + result = g_record_delayed_compute_value(delayed, out); if (result) { @@ -318,7 +334,7 @@ bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resol /****************************************************************************** * * -* Paramètres : value = correspondance à consulter. * +* Paramètres : delayed = correspondance à consulter. * * range = zone de couverture déterminée. [OUT] * * * * Description : Calcule ou fournit la zone couverte par une correspondance. * @@ -329,7 +345,7 @@ bool g_record_value_compute_and_aggregate_value(const GRecordValue *value, resol * * ******************************************************************************/ -static void g_record_value_get_range(const GRecordValue *value, mrange_t *range) +static void g_record_delayed_get_range(const GRecordDelayed *delayed, mrange_t *range) { copy_mrange(range, UNUSED_MRANGE_PTR); diff --git a/plugins/kaitai/records/value.h b/plugins/kaitai/records/delayed.h index 8ee9cdd..e88bb6c 100644 --- a/plugins/kaitai/records/value.h +++ b/plugins/kaitai/records/delayed.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * value.h - prototypes pour la conservation d'une correspondance entre attribut et binaire + * delayed.h - prototypes pour la conservation d'une correspondance entre attribut et binaire * * Copyright (C) 2019 Cyrille Bagard * @@ -21,8 +21,8 @@ */ -#ifndef _PLUGINS_KAITAI_RECORDS_VALUE_H -#define _PLUGINS_KAITAI_RECORDS_VALUE_H +#ifndef _PLUGINS_KAITAI_RECORDS_DELAYED_H +#define _PLUGINS_KAITAI_RECORDS_DELAYED_H #include <glib-object.h> @@ -33,33 +33,33 @@ -#define G_TYPE_RECORD_VALUE g_record_value_get_type() -#define G_RECORD_VALUE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_VALUE, GRecordValue)) -#define G_IS_RECORD_VALUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_VALUE)) -#define G_RECORD_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_VALUE, GRecordValueClass)) -#define G_IS_RECORD_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_VALUE)) -#define G_RECORD_VALUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_VALUE, GRecordValueClass)) +#define G_TYPE_RECORD_DELAYED g_record_delayed_get_type() +#define G_RECORD_DELAYED(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RECORD_DELAYED, GRecordDelayed)) +#define G_IS_RECORD_DELAYED(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RECORD_DELAYED)) +#define G_RECORD_DELAYED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RECORD_DELAYED, GRecordDelayedClass)) +#define G_IS_RECORD_DELAYED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RECORD_DELAYED)) +#define G_RECORD_DELAYED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RECORD_DELAYED, GRecordDelayedClass)) /* Valeur calculée selon des correspondances parallèles (instance) */ -typedef struct _GRecordValue GRecordValue; +typedef struct _GRecordDelayed GRecordDelayed; /* Valeur calculée selon des correspondances parallèles (classe) */ -typedef struct _GRecordValueClass GRecordValueClass; +typedef struct _GRecordDelayedClass GRecordDelayedClass; /* Indique le type défini pour une valeur calculée selon des correspondances établies. */ -GType g_record_value_get_type(void); +GType g_record_delayed_get_type(void); /* Crée une nouvelle valeur calculée à partir d'une instance. */ -GRecordValue *g_record_value_new(GKaitaiInstance *, const kaitai_scope_t *); +GRecordDelayed *g_record_delayed_new(GKaitaiInstance *, const kaitai_scope_t *, GBinContent *); /* Détermine la valeur d'un élément Kaitai entier calculé. */ -bool g_record_value_compute_value(const GRecordValue *, resolved_value_t *); +bool g_record_delayed_compute_value(GRecordDelayed *, resolved_value_t *); /* Détermine et ajuste la valeur d'un élément Kaitai calculé. */ -bool g_record_value_compute_and_aggregate_value(const GRecordValue *, resolved_value_t *); +bool g_record_delayed_compute_and_aggregate_value(GRecordDelayed *, resolved_value_t *); -#endif /* _PLUGINS_KAITAI_RECORDS_VALUE_H */ +#endif /* _PLUGINS_KAITAI_RECORDS_DELAYED_H */ diff --git a/plugins/kaitai/rost/Makefile.am b/plugins/kaitai/rost/Makefile.am new file mode 100644 index 0000000..c7ea84a --- /dev/null +++ b/plugins/kaitai/rost/Makefile.am @@ -0,0 +1,18 @@ + +noinst_LTLIBRARIES = libkaitairost.la + +libkaitairost_la_SOURCES = \ + browser-int.h \ + browser.h browser.c \ + core.h core.c \ + space-int.h \ + space.h space.c \ + trigger-int.h \ + trigger.h trigger.c + +libkaitairost_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libkaitairost_la_SOURCES:%c=) diff --git a/plugins/kaitai/rost/browser-int.h b/plugins/kaitai/rost/browser-int.h new file mode 100644 index 0000000..4b49680 --- /dev/null +++ b/plugins/kaitai/rost/browser-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * browser-int.h - prototypes internes pour le parcours des résultats d'analyse Kaitai pour ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef PLUGINS_KAITAI_ROST_BROWSER_INT_H +#define PLUGINS_KAITAI_ROST_BROWSER_INT_H + + +#include <analysis/scan/item-int.h> + + +#include "browser.h" + + + +/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */ +struct _GKaitaiBrowser +{ + GScanRegisteredItem parent; /* A laisser en premier */ + + char *path; /* Chamin vers l'enregistrement*/ + GMatchRecord *record; /* Correspondance à parcourir */ + +}; + +/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */ +struct _GKaitaiBrowserClass +{ + GScanRegisteredItemClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un nouveau parcours de correspondances Kaitai. */ +bool g_kaitai_browser_create(GKaitaiBrowser *, const char *, GMatchRecord *); + + + +#endif /* PLUGINS_KAITAI_ROST_BROWSER_INT_H */ diff --git a/plugins/kaitai/rost/browser.c b/plugins/kaitai/rost/browser.c new file mode 100644 index 0000000..159915b --- /dev/null +++ b/plugins/kaitai/rost/browser.c @@ -0,0 +1,478 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * browser.c - accès à des définitions Kaitai depuis ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "browser.h" + + +#include <assert.h> +#include <string.h> + + +#include <analysis/scan/exprs/literal.h> + + +#include "browser-int.h" +#include "../records/bits.h" +#include "../records/delayed.h" +#include "../records/item.h" +#include "../records/list.h" + + + +/* ---------------------- PARCOURS DE CORRESPONDANCES ETABLIES ---------------------- */ + + +/* Initialise la classe des parcours de correspondances Kaitai. */ +static void g_kaitai_browser_class_init(GKaitaiBrowserClass *); + +/* Initialise un parcours de correspondances Kaitai. */ +static void g_kaitai_browser_init(GKaitaiBrowser *); + +/* Supprime toutes les références externes. */ +static void g_kaitai_browser_dispose(GKaitaiBrowser *); + +/* Procède à la libération totale de la mémoire. */ +static void g_kaitai_browser_finalize(GKaitaiBrowser *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_kaitai_browser_get_name(const GKaitaiBrowser *); + +/* Lance une résolution d'élément à solliciter. */ +static bool g_kaitai_browser_resolve(GKaitaiBrowser *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + +/* Réduit une expression à une forme plus simple. */ +static bool g_kaitai_browser_reduce(GKaitaiBrowser *, GScanContext *, GScanScope *, GScanExpression **); + +/* Effectue une extraction d'élément à partir d'une série. */ +static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *, const GScanExpression *, GScanContext *, GScanScope *); + + + +/* ---------------------------------------------------------------------------------- */ +/* PARCOURS DE CORRESPONDANCES ETABLIES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */ +G_DEFINE_TYPE(GKaitaiBrowser, g_kaitai_browser, G_TYPE_SCAN_REGISTERED_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des parcours de correspondances Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_browser_class_init(GKaitaiBrowserClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanRegisteredItemClass *registered; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_browser_dispose; + object->finalize = (GObjectFinalizeFunc)g_kaitai_browser_finalize; + + registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + + registered->get_name = (get_registered_item_name_fc)g_kaitai_browser_get_name; + registered->resolve = (resolve_registered_item_fc)g_kaitai_browser_resolve; + registered->reduce = (reduce_registered_item_fc)g_kaitai_browser_reduce; + registered->extract = (extract_registered_item_at)g_kaitai_browser_extract_at; + +} + + +/****************************************************************************** +* * +* Paramètres : browser = instance à initialiser. * +* * +* Description : Initialise un parcours de correspondances Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_browser_init(GKaitaiBrowser *browser) +{ + browser->path = NULL; + browser->record = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : browser = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_browser_dispose(GKaitaiBrowser *browser) +{ + g_clear_object(&browser->record); + + G_OBJECT_CLASS(g_kaitai_browser_parent_class)->dispose(G_OBJECT(browser)); + +} + + +/****************************************************************************** +* * +* Paramètres : browser = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_browser_finalize(GKaitaiBrowser *browser) +{ + if (browser->path != NULL) + free(browser->path); + + G_OBJECT_CLASS(g_kaitai_browser_parent_class)->finalize(G_OBJECT(browser)); + +} + + +/****************************************************************************** +* * +* Paramètres : path = chemin vers l'enregistrement fourni. * +* record = correspondance racine à considérer. * +* * +* Description : Crée un nouveau parcours de correspondances Kaitai. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GKaitaiBrowser *g_kaitai_browser_new(const char *path, GMatchRecord *record) +{ + GKaitaiBrowser *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_BROWSER, NULL); + + if (!g_kaitai_browser_create(result, path, record)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : browser = encadrement d'un parcours de correspondances. * +* path = chemin vers l'enregistrement fourni. * +* record = correspondance racine à considérer. * +* * +* Description : Met en place un nouveau parcours de correspondances Kaitai. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_browser_create(GKaitaiBrowser *browser, const char *path, GMatchRecord *record) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (path != NULL) + browser->path = strdup(path); + + browser->record = record; + g_object_ref(G_OBJECT(browser->record)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_kaitai_browser_get_name(const GKaitaiBrowser *item) +{ + char *result; /* Désignation à retourner */ + int ret; /* Statut de construction */ + + if (item->path == NULL) + result = strdup("kaitai://"); + + else + { + ret = asprintf(&result, "kaitai://%s", item->path); + assert(ret > 0); + + if (ret <= 0) + result = strdup("kaitai://???"); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* target = désignation de l'objet d'appel à identifier. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* +* * +* Description : Lance une résolution d'élément à solliciter. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_browser_resolve(GKaitaiBrowser *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ + bool result; /* Bilan à retourner */ + GMatchRecord *found; /* Correspondance trouvée */ + char *path; + int ret; /* Statut de construction */ + + found = g_match_record_find_by_name(item->record, target, strlen(target), 1); + result = (found != NULL); + + if (result) + { + ret = asprintf(&path, "%s.%s", item->path, target); + assert(ret > 0); + + if (ret <= 0) + path = strdup("!?"); + + *out = G_SCAN_REGISTERED_ITEM(g_kaitai_browser_new(path, found)); + + free(path); + g_object_unref(G_OBJECT(found)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_browser_reduce(GKaitaiBrowser *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ + size_t count; /* Décompte total à considérer */ + resolved_value_t value; /* Valeur brute à transformer */ + + if (G_IS_RECORD_LIST(item->record)) + { + count = g_record_list_count_records(G_RECORD_LIST(item->record)); + + *out = g_scan_literal_expression_new(LVT_BOOLEAN, (bool []){ count > 0 }); + + result = true; + + } + + else + { + if (G_IS_RECORD_BIT_FIELD(item->record)) + result = g_record_bit_field_get_value(G_RECORD_BIT_FIELD(item->record), &value); + + else if (G_IS_RECORD_DELAYED(item->record)) + result = g_record_delayed_compute_and_aggregate_value(G_RECORD_DELAYED(item->record), &value); + + else if (G_IS_RECORD_ITEM(item->record)) + result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value); + + else + result = false; + + if (result) + { + switch (value.type) + { + case GVT_UNSIGNED_INTEGER: + *out = g_scan_literal_expression_new(LVT_UNSIGNED_INTEGER, &value.unsigned_integer); + break; + + case GVT_SIGNED_INTEGER: + *out = g_scan_literal_expression_new(LVT_SIGNED_INTEGER, &value.signed_integer); + break; + + case GVT_FLOAT: + /* TODO */ + break; + + case GVT_BOOLEAN: + *out = g_scan_literal_expression_new(LVT_BOOLEAN, &value.status); + break; + + case GVT_BYTES: + *out = g_scan_literal_expression_new(LVT_STRING, &value.bytes); + break; + + default: + break; + + } + + EXIT_RESOLVED_VALUE(value); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* index = indice de l'élément à cibler. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* * +* Description : Effectue une extraction d'élément à partir d'une série. * +* * +* Retour : Elément de série obtenu ou NULL si erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GObject *g_kaitai_browser_extract_at(GKaitaiBrowser *item, const GScanExpression *index, GScanContext *ctx, GScanScope *scope) +{ + GObject *result; /* Elément récupéré à renvoyer */ + GScanLiteralExpression *literal; /* Accès direct à l'indice */ + LiteralValueType vtype; /* Type de valeur portée */ + unsigned long long at; /* Valeur concrète du point */ + bool status; /* Bilan d'obtention d'indice */ + GRecordList *list; /* Accès direct à la liste */ + size_t count; /* Décompte total à considérer */ + GMatchRecord *found; /* Correspondance trouvée */ + char *path; + int ret; /* Statut de construction */ + + result = NULL; + + /* Validations préliminaires */ + + if (!G_IS_RECORD_LIST(item->record)) goto exit; + if (!G_IS_SCAN_LITERAL_EXPRESSION(index)) goto exit; + + literal = G_SCAN_LITERAL_EXPRESSION(index); + + vtype = g_scan_literal_expression_get_value_type(literal); + if (vtype != LVT_UNSIGNED_INTEGER) goto exit; + + status = g_scan_literal_expression_get_unsigned_integer_value(literal, &at); + if (!status) goto exit; + + list = G_RECORD_LIST(item->record); + + count = g_record_list_count_records(list); + if (at >= count) goto exit; + + /* Récupération de l'élément visé */ + + found = g_record_list_get_record(list, at); + if (found == NULL) goto exit; + + ret = asprintf(&path, "%s[%llu]", item->path, at); + assert(ret > 0); + + if (ret <= 0) + path = strdup("!?"); + + result = G_OBJECT(g_kaitai_browser_new(path, found)); + + free(path); + g_object_unref(G_OBJECT(found)); + + exit: + + return result; + +} diff --git a/plugins/kaitai/rost/browser.h b/plugins/kaitai/rost/browser.h new file mode 100644 index 0000000..89b9f6f --- /dev/null +++ b/plugins/kaitai/rost/browser.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * browser.h - prototypes pour le parcours des résultats d'analyse Kaitai pour ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef PLUGINS_KAITAI_ROST_BROWSER_H +#define PLUGINS_KAITAI_ROST_BROWSER_H + + +#include <glib-object.h> + + +#include "../record.h" + + + +#define G_TYPE_KAITAI_BROWSER g_kaitai_browser_get_type() +#define G_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowser)) +#define G_IS_KAITAI_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_BROWSER)) +#define G_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass)) +#define G_IS_KAITAI_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_BROWSER)) +#define G_KAITAI_BROWSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_BROWSER, GKaitaiBrowserClass)) + + +/* Parcours des résultats d'une analyse Kaitai pour ROST (instance) */ +typedef struct _GKaitaiBrowser GKaitaiBrowser; + +/* Parcours des résultats d'une analyse Kaitai pour ROST (classe) */ +typedef struct _GKaitaiBrowserClass GKaitaiBrowserClass; + + +/* Indique le type défini pour un parcours de correspondances Kaitai pour ROST. */ +GType g_kaitai_browser_get_type(void); + +/* Crée un nouveau parcours de correspondances Kaitai. */ +GKaitaiBrowser *g_kaitai_browser_new(const char *, GMatchRecord *); + + + +#endif /* PLUGINS_KAITAI_ROST_BROWSER_H */ diff --git a/plugins/kaitai/rost/core.c b/plugins/kaitai/rost/core.c new file mode 100644 index 0000000..8271389 --- /dev/null +++ b/plugins/kaitai/rost/core.c @@ -0,0 +1,66 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.c - mise à disposition d'un support Kaitai pour ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "core.h" + + +#include <core/global.h> + + +#include "space.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre un support de Kaitai pour ROST. * +* * +* Retour : Bilan du chargement mené. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_kaitai_support_to_rost(void) +{ + bool result; /* Bilan à retourner */ + GScanNamespace *root_ns; /* Espace de noms ROST racine */ + GScanNamespace *kaitai_ns; /* Espace de noms pour Kaitai */ + + result = true; + + root_ns = get_rost_root_namespace(); + + kaitai_ns = g_kaitai_namespace_new(); + + result = g_scan_namespace_register_item(root_ns, G_SCAN_REGISTERED_ITEM(kaitai_ns)); + + g_object_unref(G_OBJECT(kaitai_ns)); + + g_object_unref(G_OBJECT(root_ns)); + + return result; + +} diff --git a/plugins/kaitai/rost/core.h b/plugins/kaitai/rost/core.h new file mode 100644 index 0000000..6f810eb --- /dev/null +++ b/plugins/kaitai/rost/core.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.h - prototypes pour la mise à disposition d'un support Kaitai pour ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_ROST_CORE_H +#define _PLUGINS_KAITAI_ROST_CORE_H + + +#include <stdbool.h> + + + +/* Intègre un support de Kaitai pour ROST. */ +bool add_kaitai_support_to_rost(void); + + + +#endif /* _PLUGINS_KAITAI_ROST_CORE_H */ diff --git a/plugins/kaitai/rost/space-int.h b/plugins/kaitai/rost/space-int.h new file mode 100644 index 0000000..47ec707 --- /dev/null +++ b/plugins/kaitai/rost/space-int.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * space-int.h - prototypes internes pour la définition d'un espace de noms pour les fonctions de scan + * + * 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/>. + */ + + +#ifndef _PLUGINS_KAITAI_ROST_SPACE_INT_H +#define _PLUGINS_KAITAI_ROST_SPACE_INT_H + + +#include "space.h" + + +#include <analysis/scan/space-int.h> + + + +/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */ +struct _GKaitaiNamespace +{ + GScanNamespace parent; /* A laisser en premier */ + +}; + +/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */ +struct _GKaitaiNamespaceClass +{ + GScanNamespaceClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un nouvel espace de noms pour scan. */ +bool g_kaitai_namespace_create(GKaitaiNamespace *); + + + +#endif /* _PLUGINS_KAITAI_ROST_SPACE_INT_H */ diff --git a/plugins/kaitai/rost/space.c b/plugins/kaitai/rost/space.c new file mode 100644 index 0000000..ee922d2 --- /dev/null +++ b/plugins/kaitai/rost/space.c @@ -0,0 +1,254 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * space.c - définition d'un espace de noms pour les fonctions de scan + * + * 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 "space.h" + + +#include <string.h> + + +#include "trigger.h" +#include "space-int.h" +#include "../import.h" + + + +/* ------------------------- SOCLE POUR LES ESPACES DE NOMS ------------------------- */ + + +/* Initialise la classe des espaces de noms dynamiques Kaitai. */ +static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *); + +/* Initialise une instance d'espace de noms dynamiques Kaitai. */ +static void g_kaitai_namespace_init(GKaitaiNamespace *); + +/* Supprime toutes les références externes. */ +static void g_kaitai_namespace_dispose(GKaitaiNamespace *); + +/* Procède à la libération totale de la mémoire. */ +static void g_kaitai_namespace_finalize(GKaitaiNamespace *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Lance une résolution d'élément à solliciter. */ +static bool g_kaitai_namespace_resolve(GKaitaiNamespace *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + + + +/* ---------------------------------------------------------------------------------- */ +/* SOCLE POUR LES ESPACES DE NOMS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */ +G_DEFINE_TYPE(GKaitaiNamespace, g_kaitai_namespace, G_TYPE_SCAN_NAMESPACE); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des espaces de noms dynamiques Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_namespace_class_init(GKaitaiNamespaceClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanRegisteredItemClass *registered; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_namespace_dispose; + object->finalize = (GObjectFinalizeFunc)g_kaitai_namespace_finalize; + + registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + + registered->resolve = (resolve_registered_item_fc)g_kaitai_namespace_resolve; + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance à initialiser. * +* * +* Description : Initialise une instance d'espace de noms dynamiques Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_namespace_init(GKaitaiNamespace *space) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_namespace_dispose(GKaitaiNamespace *space) +{ + G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->dispose(G_OBJECT(space)); + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_namespace_finalize(GKaitaiNamespace *space) +{ + G_OBJECT_CLASS(g_kaitai_namespace_parent_class)->finalize(G_OBJECT(space)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un nouvel espace de noms dynamique pour Kaitai. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanNamespace *g_kaitai_namespace_new(void) +{ + GScanNamespace *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_KAITAI_NAMESPACE, NULL); + + if (!g_kaitai_namespace_create(G_KAITAI_NAMESPACE(result))) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : space = instance d'espace de noms à initialiser. * +* name = désignation du futur espace de noms. * +* * +* Description : Met en place un nouvel espace de noms pour scan. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_namespace_create(GKaitaiNamespace *space) +{ + bool result; /* Bilan à retourner */ + + result = g_scan_namespace_create(G_SCAN_NAMESPACE(space), "kaitai"); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* target = désignation de l'objet d'appel à identifier. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* +* * +* Description : Lance une résolution d'élément à solliciter. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_namespace_resolve(GKaitaiNamespace *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ + bool result; /* Bilan à retourner */ + GScanRegisteredItemClass *parent; /* Version de classe parente */ + GKaitaiStruct *kstruct; /* Lecteur de définition */ + + parent = G_SCAN_REGISTERED_ITEM_CLASS(g_kaitai_namespace_parent_class); + + result = parent->resolve(G_SCAN_REGISTERED_ITEM(item), target, ctx, scope, out); + + if (!result) + { + kstruct = load_kaitai_definition(target, NULL); + + if (kstruct != NULL) + { + *out = g_kaitai_trigger_new(kstruct); + result = true; + + g_object_unref(G_OBJECT(kstruct)); + + } + + } + + return result; + +} diff --git a/plugins/kaitai/rost/space.h b/plugins/kaitai/rost/space.h new file mode 100644 index 0000000..5dcea5e --- /dev/null +++ b/plugins/kaitai/rost/space.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * space.h - prototypes pour la définition d'un espace de noms pour les fonctions de scan + * + * 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/>. + */ + + +#ifndef _PLUGINS_KAITAI_ROST_SPACE_H +#define _PLUGINS_KAITAI_ROST_SPACE_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include <analysis/scan/space.h> + + + +#define G_TYPE_KAITAI_NAMESPACE g_kaitai_namespace_get_type() +#define G_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespace)) +#define G_IS_KAITAI_NAMESPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_NAMESPACE)) +#define G_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass)) +#define G_IS_KAITAI_NAMESPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_NAMESPACE)) +#define G_KAITAI_NAMESPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_NAMESPACE, GKaitaiNamespaceClass)) + + +/* Espace de noms avec chargement dynamique de définitions Kaitai (instance) */ +typedef struct _GKaitaiNamespace GKaitaiNamespace; + +/* Espace de noms avec chargement dynamique de définitions Kaitai (classe) */ +typedef struct _GKaitaiNamespaceClass GKaitaiNamespaceClass; + + +/* Indique le type défini pour une définition d'espace de noms dynamique Kaitai. */ +GType g_kaitai_namespace_get_type(void); + +/* Construit un nouvel espace de noms dynamique pour Kaitai. */ +GScanNamespace *g_kaitai_namespace_new(void); + + + +#endif /* _PLUGINS_KAITAI_ROST_SPACE_H */ diff --git a/plugins/kaitai/rost/trigger-int.h b/plugins/kaitai/rost/trigger-int.h new file mode 100644 index 0000000..6830cd7 --- /dev/null +++ b/plugins/kaitai/rost/trigger-int.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger-int.h - prototypes internes pour l'accès à des définitions Kaitai depuis ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_KAITAI_ROST_TRIGGER_INT_H +#define _PLUGINS_KAITAI_ROST_TRIGGER_INT_H + + +#include <analysis/scan/item-int.h> + + +#include "trigger.h" + + + +/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */ +struct _GKaitaiTrigger +{ + GScanRegisteredItem parent; /* A laisser en premier */ + + char *name; /* Désignation arbitraire */ + + GKaitaiStruct *kstruct; /* Définition à décliner */ + +}; + +/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */ +struct _GKaitaiTriggerClass +{ + GScanRegisteredItemClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un accès à une définition Kaitai pour ROST. */ +bool g_kaitai_trigger_create(GKaitaiTrigger *, GKaitaiStruct *); + + + +#endif /* _PLUGINS_KAITAI_ROST_TRIGGER_INT_H */ diff --git a/plugins/kaitai/rost/trigger.c b/plugins/kaitai/rost/trigger.c new file mode 100644 index 0000000..6bb6e5d --- /dev/null +++ b/plugins/kaitai/rost/trigger.c @@ -0,0 +1,320 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger.c - accès à des définitions Kaitai depuis ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "trigger.h" + + +#include <string.h> + + +#include "browser.h" +#include "trigger-int.h" + + + +/* ---------------------- ACCES ET DECLENCHEMENT D'UNE ANALYSE ---------------------- */ + + +/* Initialise la classe des accès aux définitions Kaitai. */ +static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *); + +/* Initialise un accès à une définition Kaitai. */ +static void g_kaitai_trigger_init(GKaitaiTrigger *); + +/* Supprime toutes les références externes. */ +static void g_kaitai_trigger_dispose(GKaitaiTrigger *); + +/* Procède à la libération totale de la mémoire. */ +static void g_kaitai_trigger_finalize(GKaitaiTrigger *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Indique le nom associé à une expression d'évaluation. */ +static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *); + +/* Lance une résolution d'élément à solliciter. */ +static bool g_kaitai_trigger_resolve(GKaitaiTrigger *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + + + +/* ---------------------------------------------------------------------------------- */ +/* ACCES ET DECLENCHEMENT D'UNE ANALYSE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */ +G_DEFINE_TYPE(GKaitaiTrigger, g_kaitai_trigger, G_TYPE_SCAN_REGISTERED_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des accès aux définitions Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_trigger_class_init(GKaitaiTriggerClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanRegisteredItemClass *registered; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_kaitai_trigger_dispose; + object->finalize = (GObjectFinalizeFunc)g_kaitai_trigger_finalize; + + registered = G_SCAN_REGISTERED_ITEM_CLASS(klass); + + registered->get_name = (get_registered_item_name_fc)g_kaitai_trigger_get_name; + registered->resolve = (resolve_registered_item_fc)g_kaitai_trigger_resolve; + +} + + +/****************************************************************************** +* * +* Paramètres : trigger = instance à initialiser. * +* * +* Description : Initialise un accès à une définition Kaitai. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_trigger_init(GKaitaiTrigger *trigger) +{ + trigger->name = NULL; + + trigger->kstruct = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : trigger = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_trigger_dispose(GKaitaiTrigger *trigger) +{ + g_clear_object(&trigger->kstruct); + + G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->dispose(G_OBJECT(trigger)); + +} + + +/****************************************************************************** +* * +* Paramètres : trigger = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_kaitai_trigger_finalize(GKaitaiTrigger *trigger) +{ + if (trigger->name != NULL) + free(trigger->name); + + G_OBJECT_CLASS(g_kaitai_trigger_parent_class)->finalize(G_OBJECT(trigger)); + +} + + +/****************************************************************************** +* * +* Paramètres : kstruct = définition Kaitai à manipuler avec du contenu. * +* * +* Description : Crée un nouvel accès à une définition Kaitai à instancier. * +* * +* Retour : Instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanRegisteredItem *g_kaitai_trigger_new(GKaitaiStruct *kstruct) +{ + GScanRegisteredItem *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_TRIGGER, NULL); + + if (!g_kaitai_trigger_create(G_KAITAI_TRIGGER(result), kstruct)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : trigger = lien vers une définition Kaitai à instancier. * +* kstruct = définition Kaitai à manipuler avec du contenu. * +* * +* Description : Met en place un accès à une définition Kaitai pour ROST. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_kaitai_trigger_create(GKaitaiTrigger *trigger, GKaitaiStruct *kstruct) +{ + bool result; /* Bilan à retourner */ + + result = true; + + trigger->kstruct = kstruct; + g_object_ref(G_OBJECT(trigger->kstruct)); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : trigger = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_kaitai_trigger_get_name(const GKaitaiTrigger *trigger) +{ + char *result; /* Désignation à retourner */ + GKaitaiMeta *meta; /* Eventuelles métadonnées */ + const char *id; /* Identifiant de définition */ + + if (trigger->name != NULL) + result = strdup(trigger->name); + + else + { + result = NULL; + + meta = g_kaitai_structure_get_meta(trigger->kstruct); + if (meta == NULL) goto done; + + id = g_kaitai_meta_get_id(meta); + if (id == NULL) goto done; + + result = strdup(id); + + g_object_unref(G_OBJECT(meta)); + + done: + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* target = désignation de l'objet d'appel à identifier. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* +* * +* Description : Lance une résolution d'élément à solliciter. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_kaitai_trigger_resolve(GKaitaiTrigger *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ + bool result; /* Bilan à retourner */ + GKaitaiBrowser *browser; /* Navigateur pour résultats */ + GBinContent *content; /* Contenu binaire à analyser */ + GMatchRecord *record; /* Premier niveau de résultats */ + + browser = g_object_get_data(G_OBJECT(item), "kaitai_browser"); + + if (browser == NULL) + { + content = g_scan_context_get_content(ctx); + + record = g_kaitai_structure_parse(item->kstruct, content); + + g_object_unref(G_OBJECT(content)); + + if (record != NULL) + { + browser = g_kaitai_browser_new(NULL, record); + + g_object_set_data_full(G_OBJECT(item), "kaitai_browser", browser, g_object_unref); + + } + + } + + if (browser == NULL) + result = false; + + else + result = g_scan_registered_item_resolve(G_SCAN_REGISTERED_ITEM(browser), target, ctx, scope, out); + + return result; + +} diff --git a/plugins/kaitai/rost/trigger.h b/plugins/kaitai/rost/trigger.h new file mode 100644 index 0000000..f55e998 --- /dev/null +++ b/plugins/kaitai/rost/trigger.h @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * trigger.h - prototypes pour l'accès à des définitions Kaitai depuis ROST + * + * 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef PLUGINS_KAITAI_ROST_TRIGGER_H +#define PLUGINS_KAITAI_ROST_TRIGGER_H + + +#include <glib-object.h> + + +#include <analysis/scan/item.h> + + +#include "../parsers/struct.h" + + + +#define G_TYPE_KAITAI_TRIGGER g_kaitai_trigger_get_type() +#define G_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTrigger)) +#define G_IS_KAITAI_TRIGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KAITAI_TRIGGER)) +#define G_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass)) +#define G_IS_KAITAI_TRIGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KAITAI_TRIGGER)) +#define G_KAITAI_TRIGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KAITAI_TRIGGER, GKaitaiTriggerClass)) + + +/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (instance) */ +typedef struct _GKaitaiTrigger GKaitaiTrigger; + +/* Accès à une définition et déclenchement d'une analyse Kaitai depuis ROST (classe) */ +typedef struct _GKaitaiTriggerClass GKaitaiTriggerClass; + + +/* Indique le type défini pour un accès à une définition Kaitai pour ROST. */ +GType g_kaitai_trigger_get_type(void); + +/* Crée un nouvel accès à une définition Kaitai à instancier. */ +GScanRegisteredItem *g_kaitai_trigger_new(GKaitaiStruct *); + + + +#endif /* PLUGINS_KAITAI_ROST_TRIGGER_H */ diff --git a/plugins/kaitai/scope.c b/plugins/kaitai/scope.c index 6d1d47a..fad8890 100644 --- a/plugins/kaitai/scope.c +++ b/plugins/kaitai/scope.c @@ -231,7 +231,7 @@ GKaitaiType *find_sub_type(const kaitai_scope_t *locals, const char *name) size_t i; /* Boucle de parcours */ GKaitaiParser *parser; /* Lecteur d'origine */ - GMatchRecord *list[] = { locals->root, locals->parent, locals->last }; + GMatchRecord *list[] = { locals->last, locals->parent, locals->root }; result = NULL; diff --git a/plugins/kaitai/tokens.l b/plugins/kaitai/tokens.l index 3ddf40d..8c93299 100644 --- a/plugins/kaitai/tokens.l +++ b/plugins/kaitai/tokens.l @@ -91,7 +91,9 @@ "_root" { return ROOT; } "_parent" { return PARENT; } "_" { return LAST; } +"_io" { return IO; } "._io" { return METH_IO; } +".eof" { return IO_EOF; } "true" { return TRUE_CONST; } "false" { return FALSE_CONST; } diff --git a/plugins/pychrysalide/analysis/content.c b/plugins/pychrysalide/analysis/content.c index f94e3f7..c30cdd8 100644 --- a/plugins/pychrysalide/analysis/content.c +++ b/plugins/pychrysalide/analysis/content.c @@ -40,6 +40,7 @@ #include "cattribs.h" #include "constants.h" +#include "storage/serialize.h" #include "../access.h" #include "../helpers.h" #include "../arch/vmpa.h" @@ -49,8 +50,13 @@ /* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ -/* Procède à l'initialisation de l'interface de génération. */ -static void py_binary_content_interface_init(GBinContentIface *, gpointer *); +/* Initialise la classe générique des contenus de binaire. */ +static void py_binary_content_init_gclass(GBinContentClass *, gpointer); + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(binary_content, G_TYPE_BIN_CONTENT, py_binary_content_init_gclass); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_binary_content_init(PyObject *, PyObject *, PyObject *); /* Fournit le nom associé au contenu binaire. */ static char *py_binary_content_describe_wrapper(const GBinContent *, bool); @@ -126,10 +132,10 @@ static PyObject *py_binary_content_get_data(PyObject *, void *); /****************************************************************************** * * -* Paramètres : iface = interface GLib à initialiser. * -* unused = adresse non utilisée ici. * +* Paramètres : class = classe à initialiser. * +* unused = données non utilisées ici. * * * -* Description : Procède à l'initialisation de l'interface de génération. * +* Description : Initialise la classe générique des contenus de binaire. * * * * Retour : - * * * @@ -137,21 +143,45 @@ static PyObject *py_binary_content_get_data(PyObject *, void *); * * ******************************************************************************/ -static void py_binary_content_interface_init(GBinContentIface *iface, gpointer *unused) +static void py_binary_content_init_gclass(GBinContentClass *class, gpointer unused) { + class->describe = py_binary_content_describe_wrapper; + + class->read_raw = py_binary_content_read_raw_wrapper; + class->read_u8 = py_binary_content_read_u8_wrapper; + class->read_u16 = py_binary_content_read_u16_wrapper; + class->read_u32 = py_binary_content_read_u32_wrapper; + class->read_u64 = py_binary_content_read_u64_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_binary_content_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + #define BINARY_CONTENT_DOC \ - "The BinContent is an interface which handles access to a given binary" \ - " content.\n" \ + "A BinContent is an abstract object which handles access to a given" \ + " binary content.\n" \ "\n" \ "All of its implementations are located in the" \ " pychrysalide.analysis.contents module. The main implemantation is" \ " the pychrysalide.analysis.contents.FileContent class.\n" \ "\n" \ - "A typical class declaration for a new implementation looks like:\n" \ - "\n" \ - " class NewImplem(GObject.Object, BinContent):\n" \ - " ...\n" \ - "\n" \ "The following methods have to be defined for new implementations:\n" \ "* pychrysalide.analysis.BinContent._describe();\n" \ "* pychrysalide.analysis.BinContent._read_raw();\n" \ @@ -161,13 +191,12 @@ static void py_binary_content_interface_init(GBinContentIface *iface, gpointer * "* pychrysalide.analysis.BinContent._read_u32();\n" \ "* pychrysalide.analysis.BinContent._read_u64();\n" - iface->describe = py_binary_content_describe_wrapper; + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - iface->read_raw = py_binary_content_read_raw_wrapper; - iface->read_u8 = py_binary_content_read_u8_wrapper; - iface->read_u16 = py_binary_content_read_u16_wrapper; - iface->read_u32 = py_binary_content_read_u32_wrapper; - iface->read_u64 = py_binary_content_read_u64_wrapper; + return 0; } @@ -1406,14 +1435,17 @@ PyTypeObject *get_python_binary_content_type(void) PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.analysis.BinContent", - .tp_basicsize = sizeof(PyObject), + .tp_basicsize = sizeof(PyGObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_doc = BINARY_CONTENT_DOC, .tp_methods = py_binary_content_methods, - .tp_getset = py_binary_content_getseters + .tp_getset = py_binary_content_getseters, + + .tp_init = py_binary_content_init, + .tp_new = py_binary_content_new, }; @@ -1440,23 +1472,18 @@ bool ensure_python_binary_content_is_registered(void) PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ - static GInterfaceInfo info = { /* Paramètres d'inscription */ - - .interface_init = (GInterfaceInitFunc)py_binary_content_interface_init, - .interface_finalize = NULL, - .interface_data = NULL, - - }; - type = get_python_binary_content_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) { + if (!ensure_python_serializable_object_is_registered()) + return false; + module = get_access_to_python_module("pychrysalide.analysis"); dict = PyModule_GetDict(module); - if (!register_interface_for_pygobject(dict, G_TYPE_BIN_CONTENT, type, &info)) + if (!register_class_for_pygobject(dict, G_TYPE_BIN_CONTENT, type)) return false; if (!define_analysis_content_constants(type)) diff --git a/plugins/pychrysalide/analysis/contents/encapsulated.c b/plugins/pychrysalide/analysis/contents/encapsulated.c index a818bab..e9583e6 100644 --- a/plugins/pychrysalide/analysis/contents/encapsulated.c +++ b/plugins/pychrysalide/analysis/contents/encapsulated.c @@ -28,18 +28,20 @@ #include <pygobject.h> -#include <analysis/contents/encapsulated.h> +#include <i18n.h> +#include <analysis/contents/encapsulated-int.h> #include "../content.h" -#include "../storage/serialize.h" #include "../../access.h" #include "../../helpers.h" -/* Crée un nouvel objet Python de type 'BinContent'. */ -static PyObject *py_encaps_content_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(encaps_content, G_TYPE_ENCAPS_CONTENT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_encaps_content_init(PyObject *, PyObject *, PyObject *); /* Indique la base d'un contenu binaire encapsulé. */ static PyObject *py_encaps_content_get_base(PyObject *, void *); @@ -54,26 +56,25 @@ static PyObject *py_encaps_content_get_endpoint(PyObject *, void *); /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * +* Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * * * -* Description : Crée un nouvel objet Python de type 'BinContent'. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : Instance Python mise en place. * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_encaps_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_encaps_content_init(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *result; /* Instance à retourner */ GBinContent *base; /* Base de l'extraction */ const char *path; /* Chemin vers le contenu final*/ GBinContent *endpoint; /* Contenu accessible au final */ int ret; /* Bilan de lecture des args. */ - GBinContent *content; /* Version GLib du contenu */ + GEncapsContent *content; /* Version GLib du contenu */ #define ENCAPS_CONTENT_DOC \ "EncapsulatedContent gathers items relative to a binary encapsulated" \ @@ -94,20 +95,30 @@ static PyObject *py_encaps_content_new(PyTypeObject *type, PyObject *args, PyObj " pychrysalide.analysis.BinContent instances and the access path must" \ " be provided as a string." + /* Récupération des paramètres */ + ret = PyArg_ParseTuple(args, "O&sO&", convert_to_binary_content, &base, &path, convert_to_binary_content, &endpoint); - if (!ret) return NULL; + if (!ret) return -1; - content = g_encaps_content_new(base, path, endpoint); + /* Initialisation d'un objet GLib */ - result = pygobject_new(G_OBJECT(content)); + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - if (content != NULL) - g_object_unref(content); + /* Eléments de base */ - return result; + content = G_ENCAPS_CONTENT(pygobject_get(self)); + + if (!g_encaps_content_create(content, base, path, endpoint)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create encapsulated content.")); + return -1; + } + + return 0; } @@ -276,7 +287,9 @@ PyTypeObject *get_python_encaps_content_type(void) .tp_methods = py_encaps_content_methods, .tp_getset = py_encaps_content_getseters, - .tp_new = py_encaps_content_new + + .tp_init = py_encaps_content_init, + .tp_new = py_encaps_content_new, }; @@ -311,9 +324,6 @@ bool ensure_python_encaps_content_is_registered(void) dict = PyModule_GetDict(module); - if (!ensure_python_serializable_object_is_registered()) - return false; - if (!ensure_python_binary_content_is_registered()) return false; diff --git a/plugins/pychrysalide/analysis/contents/file.c b/plugins/pychrysalide/analysis/contents/file.c index 9552b6c..5bef069 100644 --- a/plugins/pychrysalide/analysis/contents/file.c +++ b/plugins/pychrysalide/analysis/contents/file.c @@ -28,18 +28,20 @@ #include <pygobject.h> -#include <analysis/contents/file.h> +#include <i18n.h> +#include <analysis/contents/file-int.h> #include "memory.h" -#include "../storage/serialize.h" #include "../../access.h" #include "../../helpers.h" -/* Crée un nouvel objet Python de type 'BinContent'. */ -static PyObject *py_file_content_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(file_content, G_TYPE_FILE_CONTENT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_file_content_init(PyObject *, PyObject *, PyObject *); /* Fournit le nom de fichier associé au contenu binaire. */ static PyObject *py_file_content_get_filename(PyObject *, void *); @@ -48,24 +50,23 @@ static PyObject *py_file_content_get_filename(PyObject *, void *); /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * +* Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * * * -* Description : Crée un nouvel objet Python de type 'BinContent'. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : Instance Python mise en place. * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_file_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_file_content_init(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *result; /* Instance à retourner */ const char *filename; /* Nom du fichier à charger */ int ret; /* Bilan de lecture des args. */ - GBinContent *content; /* Version GLib du contenu */ + GFileContent *content; /* Version GLib du contenu */ #define FILE_CONTENT_DOC \ "FileContent handles binary content loaded from a file.\n" \ @@ -76,17 +77,27 @@ static PyObject *py_file_content_new(PyTypeObject *type, PyObject *args, PyObjec "\n" \ "Where filename is a path to an existing file." + /* Récupération des paramètres */ + ret = PyArg_ParseTuple(args, "s", &filename); - if (!ret) return NULL; + if (!ret) return -1; - content = g_file_content_new(filename); + /* Initialisation d'un objet GLib */ - result = pygobject_new(G_OBJECT(content)); + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - if (content != NULL) - g_object_unref(content); + /* Eléments de base */ - return result; + content = G_FILE_CONTENT(pygobject_get(self)); + + if (!g_file_content_create(content, filename)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create file content.")); + return -1; + } + + return 0; } @@ -163,7 +174,9 @@ PyTypeObject *get_python_file_content_type(void) .tp_methods = py_file_content_methods, .tp_getset = py_file_content_getseters, - .tp_new = py_file_content_new + + .tp_init = py_file_content_init, + .tp_new = py_file_content_new, }; @@ -201,9 +214,6 @@ bool ensure_python_file_content_is_registered(void) if (!ensure_python_memory_content_is_registered()) return false; - if (!ensure_python_serializable_object_is_registered()) - return false; - if (!register_class_for_pygobject(dict, G_TYPE_FILE_CONTENT, type)) return false; diff --git a/plugins/pychrysalide/analysis/contents/memory.c b/plugins/pychrysalide/analysis/contents/memory.c index b5448f0..7464779 100644 --- a/plugins/pychrysalide/analysis/contents/memory.c +++ b/plugins/pychrysalide/analysis/contents/memory.c @@ -28,42 +28,43 @@ #include <pygobject.h> -#include <analysis/contents/memory.h> +#include <i18n.h> +#include <analysis/contents/memory-int.h> #include "../content.h" -#include "../storage/serialize.h" #include "../../access.h" #include "../../helpers.h" -/* Crée un nouvel objet Python de type 'BinContent'. */ -static PyObject *py_memory_content_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(memory_content, G_TYPE_MEMORY_CONTENT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_memory_content_init(PyObject *, PyObject *, PyObject *); /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * +* Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * * * -* Description : Crée un nouvel objet Python de type 'BinContent'. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : Instance Python mise en place. * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_memory_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_memory_content_init(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *result; /* Instance à retourner */ const char *data; /* Tampon interne de Python */ Py_ssize_t length; /* Taille utilisé de ce tampon */ int ret; /* Bilan de lecture des args. */ - GBinContent *content; /* Version GLib du contenu */ + GMemoryContent *content; /* Version GLib du contenu */ #define MEMORY_CONTENT_DOC \ "MemoryContent builds a binary content from memory data only." \ @@ -76,22 +77,32 @@ static PyObject *py_memory_content_new(PyTypeObject *type, PyObject *args, PyObj "Where data is provided as string or read-only bytes-like object." \ " The string may contain embedded null bytes." + /* Récupération des paramètres */ + /** * La taille doit être de type 'int' et non 'Py_ssize_t', sinon les 32 bits * de poids fort ne sont pas initialisés ! */ ret = PyArg_ParseTuple(args, "s#", &data, &length); - if (!ret) return NULL; + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ - content = g_memory_content_new((const bin_t *)data, length); + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - result = pygobject_new(G_OBJECT(content)); + /* Eléments de base */ - if (content != NULL) - g_object_unref(content); + content = G_MEMORY_CONTENT(pygobject_get(self)); - return result; + if (!g_memory_content_create(content, (const bin_t *)data, length)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create memory content.")); + return -1; + } + + return 0; } @@ -131,7 +142,9 @@ PyTypeObject *get_python_memory_content_type(void) .tp_methods = py_memory_content_methods, .tp_getset = py_memory_content_getseters, - .tp_new = py_memory_content_new + + .tp_init = py_memory_content_init, + .tp_new = py_memory_content_new, }; @@ -166,9 +179,6 @@ bool ensure_python_memory_content_is_registered(void) dict = PyModule_GetDict(module); - if (!ensure_python_serializable_object_is_registered()) - return false; - if (!ensure_python_binary_content_is_registered()) return false; diff --git a/plugins/pychrysalide/analysis/contents/restricted.c b/plugins/pychrysalide/analysis/contents/restricted.c index 2609bb4..4521578 100644 --- a/plugins/pychrysalide/analysis/contents/restricted.c +++ b/plugins/pychrysalide/analysis/contents/restricted.c @@ -31,19 +31,21 @@ #include <i18n.h> -#include <analysis/contents/restricted.h> +#include <i18n.h> +#include <analysis/contents/restricted-int.h> #include "../content.h" -#include "../storage/serialize.h" #include "../../access.h" #include "../../helpers.h" #include "../../arch/vmpa.h" -/* Crée un nouvel objet Python de type 'BinContent'. */ -static PyObject *py_restricted_content_new(PyTypeObject *, PyObject *, PyObject *); +CREATE_DYN_CONSTRUCTOR(restricted_content, G_TYPE_RESTRICTED_CONTENT); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_restricted_content_init(PyObject *, PyObject *, PyObject *); /* Indique l'espace de restriction appliqué à un contenu. */ static PyObject *py_restricted_content_get_range(PyObject *, void *); @@ -52,25 +54,24 @@ static PyObject *py_restricted_content_get_range(PyObject *, void *); /****************************************************************************** * * -* Paramètres : type = type de l'objet à instancier. * +* Paramètres : self = objet à initialiser (théoriquement). * * args = arguments fournis à l'appel. * * kwds = arguments de type key=val fournis. * * * -* Description : Crée un nouvel objet Python de type 'BinContent'. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : Instance Python mise en place. * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_restricted_content_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_restricted_content_init(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *result; /* Instance à retourner */ - GBinContent *content; /* Instance GLib correspondante*/ + GBinContent *internal; /* Instance GLib correspondante*/ mrange_t range; /* Restriction à appliquer */ int ret; /* Bilan de lecture des args. */ - GBinContent *restricted; /* Création GLib à transmettre */ + GRestrictedContent *content; /* Version GLib du contenu */ #define RESTRICTED_CONTENT_DOC \ "RestrictedContent restricts access to a given area for a binary content." \ @@ -82,14 +83,27 @@ static PyObject *py_restricted_content_new(PyTypeObject *type, PyObject *args, P "Where content is a pychrysalide.analysis.BinContent instance and range" \ " a Python object which can be converted into pychrysalide.arch.mrange." - ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &content, convert_any_to_mrange, &range); - if (!ret) return NULL; + /* Récupération des paramètres */ - restricted = g_restricted_content_new(content, &range); + ret = PyArg_ParseTuple(args, "O&O&", convert_to_binary_content, &internal, convert_any_to_mrange, &range); + if (!ret) return -1; - result = pygobject_new(G_OBJECT(restricted)); + /* Initialisation d'un objet GLib */ - return result; + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + content = G_RESTRICTED_CONTENT(pygobject_get(self)); + + if (!g_restricted_content_create(content, internal, &range)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create restricted content.")); + return -1; + } + + return 0; } @@ -166,7 +180,9 @@ PyTypeObject *get_python_restricted_content_type(void) .tp_methods = py_restricted_content_methods, .tp_getset = py_restricted_content_getseters, - .tp_new = py_restricted_content_new + + .tp_init = py_restricted_content_init, + .tp_new = py_restricted_content_new, }; @@ -201,9 +217,6 @@ bool ensure_python_restricted_content_is_registered(void) dict = PyModule_GetDict(module); - if (!ensure_python_serializable_object_is_registered()) - return false; - if (!ensure_python_binary_content_is_registered()) return false; diff --git a/plugins/pychrysalide/analysis/scan/Makefile.am b/plugins/pychrysalide/analysis/scan/Makefile.am index 32bf1e3..8c9fb77 100644 --- a/plugins/pychrysalide/analysis/scan/Makefile.am +++ b/plugins/pychrysalide/analysis/scan/Makefile.am @@ -13,9 +13,10 @@ libpychrysaanalysisscan_la_SOURCES = \ space.h space.c libpychrysaanalysisscan_la_LIBADD = \ + exprs/libpychrysaanalysisscanexprs.la \ patterns/libpychrysaanalysisscanpatterns.la -libpychrysaanalysisscan_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \ +libpychrysaanalysisscan_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT @@ -24,4 +25,4 @@ devdir = $(includedir)/chrysalide/$(subdir) dev_HEADERS = $(libpychrysaanalysisscan_la_SOURCES:%c=) -SUBDIRS = patterns +SUBDIRS = exprs patterns diff --git a/plugins/pychrysalide/analysis/scan/constants.c b/plugins/pychrysalide/analysis/scan/constants.c index 7ada8d3..d030df2 100644 --- a/plugins/pychrysalide/analysis/scan/constants.c +++ b/plugins/pychrysalide/analysis/scan/constants.c @@ -51,7 +51,7 @@ bool define_expression_value_type_constants(PyTypeObject *type) values = PyDict_New(); - result = add_const_to_group(values, "SRS_PENDING", SRS_PENDING); + result = add_const_to_group(values, "PENDING", SRS_PENDING); if (result) result = add_const_to_group(values, "REDUCED", SRS_REDUCED); if (result) result = add_const_to_group(values, "WAIT_FOR_SCAN", SRS_WAIT_FOR_SCAN); if (result) result = add_const_to_group(values, "UNRESOLVABLE", SRS_UNRESOLVABLE); diff --git a/plugins/pychrysalide/analysis/scan/context.c b/plugins/pychrysalide/analysis/scan/context.c index 8f29457..9becaf7 100644 --- a/plugins/pychrysalide/analysis/scan/context.c +++ b/plugins/pychrysalide/analysis/scan/context.c @@ -32,10 +32,11 @@ #include <analysis/content.h> #include <analysis/scan/context-int.h> #include <analysis/scan/expr.h> -#include <plugins/pychrysalide/access.h> -#include <plugins/pychrysalide/helpers.h> -#include <plugins/pychrysalide/analysis/content.h> -#include <plugins/pychrysalide/analysis/scan/expr.h> + +#include "expr.h" +#include "../content.h" +#include "../../access.h" +#include "../../helpers.h" @@ -50,6 +51,12 @@ static PyObject *py_scan_context_mark_scan_as_done(PyObject *, PyObject *); /* Indique si une correspondance globale a pu être établie. */ static PyObject *py_scan_context_has_match_for_rule(PyObject *, PyObject *); +/* Fournit une référence au contenu principal analysé. */ +static PyObject *py_scan_context_get_content(PyObject *, void *); + +/* Définit le contenu principal à analyser. */ +static int py_scan_context_set_content(PyObject *, PyObject *, void *); + /* Indique si la phase d'analyse de contenu est terminée. */ static PyObject *py_scan_context_is_scan_done(PyObject *, void *); @@ -183,6 +190,79 @@ static PyObject *py_scan_context_has_match_for_rule(PyObject *self, PyObject *ar /****************************************************************************** * * +* Paramètres : self = classe représentant une routine binaire. * +* closure = adresse non utilisée ici. * +* * +* Description : Fournit une référence au contenu principal analysé. * +* * +* Retour : Content binaire associé au context. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_scan_context_get_content(PyObject *self, void *closure) +{ + PyObject *result; /* Eléments à retourner */ + GScanContext *context; /* Version native */ + GBinContent *content; /* Contenu binaire à référencer*/ + +#define SCAN_CONTEXT_CONTENT_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + content, py_scan_context, \ + "Link to the scanned binary content.\n" \ + "\n" \ + "The result is a pychrysalide.analysis.BinContent for" \ + " fully initialized context." \ +) + + context = G_SCAN_CONTEXT(pygobject_get(self)); + content = g_scan_context_get_content(context); + + result = pygobject_new(G_OBJECT(content)); + + g_object_unref(G_OBJECT(content)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = non utilisé ici. * +* * +* Description : Définit le contenu principal à analyser. * +* * +* Retour : Content binaire associé au context. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_context_set_content(PyObject *self, PyObject *value, void *closure) +{ + GScanContext *context; /* Elément à consulter */ + int ret; /* Bilan de lecture des args. */ + GBinContent *content; /* Contenu binaire à référencer*/ + + ret = PyObject_IsInstance(value, (PyObject *)get_python_binary_content_type()); + if (!ret) return -1; + + context = G_SCAN_CONTEXT(pygobject_get(self)); + content = G_BIN_CONTENT(pygobject_get(value)); + + // FIXME g_scan_context_set_content(context, content); + + return 0; + +} + + +/****************************************************************************** +* * * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * @@ -242,6 +322,7 @@ PyTypeObject *get_python_scan_context_type(void) }; static PyGetSetDef py_scan_context_getseters[] = { + SCAN_CONTEXT_CONTENT_ATTRIB, SCAN_CONTEXT_IS_SCAN_DONE_ATTRIB, { NULL } }; diff --git a/plugins/pychrysalide/analysis/scan/core.c b/plugins/pychrysalide/analysis/scan/core.c index f609f7d..16df9a9 100644 --- a/plugins/pychrysalide/analysis/scan/core.c +++ b/plugins/pychrysalide/analysis/scan/core.c @@ -37,18 +37,6 @@ -/* #include <malloc.h> */ - -/* #include <i18n.h> */ -/* #include <arch/processor.h> */ -/* #include <core/processors.h> */ - -/* #include "../core.h" */ - -/* #include "../arch/processor.h" */ - - - /* Inscrit un modificateur dans la liste des disponibles. */ static PyObject *py_scan_register_token_modifier(PyObject *, PyObject *); @@ -119,7 +107,8 @@ static PyObject *py_scan_register_token_modifier(PyObject *self, PyObject *args) static PyObject *py_scan_find_token_modifiers_for_name(PyObject *self, PyObject *args) { PyObject *result; /* Bilan à retourner */ - const char *name; /* Nom d'appel à rechercher */ + sized_string_t name; /* Nom d'appel à rechercher */ + Py_ssize_t len; /* Taille de ce nom */ int ret; /* Bilan de lecture des args. */ GScanTokenModifier *modifier; /* Instance mise en place */ @@ -135,10 +124,12 @@ static PyObject *py_scan_find_token_modifiers_for_name(PyObject *self, PyObject " if no instance was found for the provided name." \ ) - ret = PyArg_ParseTuple(args, "s", &name); + ret = PyArg_ParseTuple(args, "s#", &name.static_data, &len); if (!ret) return NULL; - modifier = find_scan_token_modifiers_for_name(name); + name.len = len; + + modifier = find_scan_token_modifiers_for_name(&name); if (modifier != NULL) { diff --git a/plugins/pychrysalide/analysis/scan/expr.c b/plugins/pychrysalide/analysis/scan/expr.c index 3622e9b..2d8245a 100644 --- a/plugins/pychrysalide/analysis/scan/expr.c +++ b/plugins/pychrysalide/analysis/scan/expr.c @@ -107,7 +107,7 @@ static int py_scan_expression_init(PyObject *self, PyObject *args, PyObject *kwd " the following arguments as keyword parameters:\n" \ "* *state*: initial state of reduction for the expression, as a" \ " pychrysalide.analysis.scan.ScanExpression.ScanReductionState" \ - " value." \ + " value." \ "\n" \ "The following methods have to be defined for new classes:\n" \ "* pychrysalide.analysis.scan.ScanExpression._cmp_rich().\n" diff --git a/plugins/pychrysalide/analysis/scan/expr.h b/plugins/pychrysalide/analysis/scan/expr.h index 00ab28d..42f5350 100644 --- a/plugins/pychrysalide/analysis/scan/expr.h +++ b/plugins/pychrysalide/analysis/scan/expr.h @@ -37,7 +37,7 @@ PyTypeObject *get_python_scan_expression_type(void); /* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanExpression'. */ bool ensure_python_scan_expression_is_registered(void); -/* Tente de convertir en fonction d'analyse pour scan. */ +/* Tente de convertir en expression d'évaluation généraliste. */ int convert_to_scan_expression(PyObject *, void *); diff --git a/plugins/pychrysalide/analysis/scan/exprs/Makefile.am b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am new file mode 100644 index 0000000..e40d4de --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/Makefile.am @@ -0,0 +1,15 @@ + +noinst_LTLIBRARIES = libpychrysaanalysisscanexprs.la + +libpychrysaanalysisscanexprs_la_SOURCES = \ + constants.h constants.c \ + literal.h literal.c \ + module.h module.c + +libpychrysaanalysisscanexprs_la_CFLAGS = $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + $(TOOLKIT_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libpychrysaanalysisscanexprs_la_SOURCES:%c=) diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.c b/plugins/pychrysalide/analysis/scan/exprs/constants.c new file mode 100644 index 0000000..b11ac4c --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/constants.c @@ -0,0 +1,128 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.c - ajout des constantes de base pour les expressions + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "constants.h" + + +#include <analysis/scan/exprs/literal.h> + + +#include "../../../helpers.h" + + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes relatives aux expressions de scan. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_literal_expression_value_type_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + values = PyDict_New(); + + result = add_const_to_group(values, "LVT_BOOLEAN", LVT_BOOLEAN); + if (result) result = add_const_to_group(values, "SIGNED_INTEGER", LVT_SIGNED_INTEGER); + if (result) result = add_const_to_group(values, "UNSIGNED_INTEGER", LVT_UNSIGNED_INTEGER); + if (result) result = add_const_to_group(values, "STRING", LVT_STRING); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, false, "LiteralValueType", values, + "Type of value carried by a literal scan expression."); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en constante LiteralValueType. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_literal_expression_value_type(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + unsigned long value; /* Valeur transcrite */ + + result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to LiteralValueType"); + break; + + case 1: + value = PyLong_AsUnsignedLong(arg); + + if (value > LVT_REG_EXPR) + { + PyErr_SetString(PyExc_TypeError, "invalid value for LiteralValueType"); + result = 0; + } + + else + *((LiteralValueType *)dst) = value; + + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/exprs/constants.h b/plugins/pychrysalide/analysis/scan/exprs/constants.h new file mode 100644 index 0000000..e5b8e8c --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/constants.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.h - prototypes pour l'ajout des constantes de base pour les expressions + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Définit les constantes relatives aux expressions litérales. */ +bool define_literal_expression_value_type_constants(PyTypeObject *); + +/* Tente de convertir en constante LiteralValueType. */ +int convert_to_literal_expression_value_type(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_CONSTANTS_H */ diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.c b/plugins/pychrysalide/analysis/scan/exprs/literal.c new file mode 100644 index 0000000..d7ae002 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/literal.c @@ -0,0 +1,281 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * literal.c - équivalent Python du fichier "analysis/scan/exprs/literal.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "literal.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/exprs/literal-int.h> + + +#include "constants.h" +#include "../expr.h" +#include "../../../access.h" +#include "../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_literal_expression, G_TYPE_SCAN_LITERAL_EXPRESSION); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_literal_expression_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_literal_expression_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *py_value; /* Valeur en version Python */ + int ret; /* Bilan de lecture des args. */ + LiteralValueType vtype; /* Valeur à porter */ + bool arg_boolean; /* Argument natif booléen */ + unsigned long long arg_uinteger; /* Argument natif entier */ + sized_string_t arg_string; /* Argument natif textuel */ + Py_ssize_t arg_str_length; /* Taille de ce texte */ + void *arg_ptr; /* Pointeur vers un argument */ + GScanLiteralExpression *expr; /* Création GLib à transmettre */ + +#define SCAN_LITERAL_EXPRESSION_DOC \ + "A ScanLiteralExpression object defines expression carrying" \ + " literal values available for scan match conditions.\n" \ + "\n" \ + "Instances can be created using one of the following" \ + " constructors:\n" \ + "\n" \ + " ScanLiteralExpression(value)" \ + "\n" \ + "\n" \ + "Where *value* is either a boolean, an integer or bytes." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O", &py_value); + if (!ret) return -1; + + if (PyBool_Check(py_value)) + { + vtype = LVT_BOOLEAN; + + arg_boolean = (py_value == Py_True); + arg_ptr = &arg_boolean; + + } + + else if (PyLong_Check(py_value)) + { + if (1 /* sign - TODO */) + ; + + vtype = LVT_UNSIGNED_INTEGER; + + arg_uinteger = PyLong_AsUnsignedLongLong(py_value); + arg_ptr = &arg_uinteger; + + } + + else if (PyBytes_Check(py_value)) + { + vtype = LVT_STRING; + + ret = PyBytes_AsStringAndSize(py_value, &arg_string.data, &arg_str_length); + if (ret == -1) return -1; + + arg_string.len = arg_str_length; + arg_ptr = &arg_string; + + } + + else + { + PyErr_SetString(PyExc_ValueError, _("Unsupported Python value for a literal scan expression.")); + return -1; + } + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + expr = G_SCAN_LITERAL_EXPRESSION(pygobject_get(self)); + + if (!g_scan_literal_expression_create(expr, vtype, arg_ptr)) + { + PyErr_SetString(PyExc_ValueError, _("Unable to create literal expression.")); + return -1; + } + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_literal_expression_type(void) +{ + static PyMethodDef py_scan_literal_expression_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_literal_expression_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_literal_expression_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.exprs.ScanLiteralExpression", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_LITERAL_EXPRESSION_DOC, + + .tp_methods = py_scan_literal_expression_methods, + .tp_getset = py_scan_literal_expression_getseters, + + .tp_init = py_scan_literal_expression_init, + .tp_new = py_scan_literal_expression_new, + + }; + + return &py_scan_literal_expression_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....PlainModifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_literal_expression_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'PlainModifier' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_literal_expression_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.exprs"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_scan_expression_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_LITERAL_EXPRESSION, type)) + return false; + + if (!define_literal_expression_value_type_constants(type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transmission d'octets à l'identique. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_literal_expression(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_literal_expression_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to scan literal expression"); + break; + + case 1: + *((GScanLiteralExpression **)dst) = G_SCAN_LITERAL_EXPRESSION(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/exprs/literal.h b/plugins/pychrysalide/analysis/scan/exprs/literal.h new file mode 100644 index 0000000..8e7ea70 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/literal.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * literal.h - équivalent Python du fichier "analysis/scan/exprs/literal.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_literal_expression_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.exprs.ScanLiteralExpression'. */ +bool ensure_python_scan_literal_expression_is_registered(void); + +/* Tente de convertir en transmission d'octets à l'identique. */ +int convert_to_scan_literal_expression(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_LITERAL_H */ diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.c b/plugins/pychrysalide/analysis/scan/exprs/module.c new file mode 100644 index 0000000..4f38430 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/module.c @@ -0,0 +1,103 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire exprs en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <assert.h> + + +#include "literal.h" +#include "../../../helpers.h" + + + +/****************************************************************************** +* * +* Paramètres : super = module dont la définition est à compléter. * +* * +* Description : Ajoute le module 'analysis....modifiers' à un module Python. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_analysis_scan_exprs_module(PyObject *super) +{ + bool result; /* Bilan à retourner */ + PyObject *module; /* Sous-module mis en place */ + +#define PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC \ + "This module provide expressions used to build a match condition." + + static PyModuleDef py_chrysalide_analysis_scan_exprs_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.analysis.scan.exprs", + .m_doc = PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_DOC, + + .m_size = -1, + + }; + + module = build_python_module(super, &py_chrysalide_analysis_scan_exprs_module); + + result = (module != NULL); + + if (!result) + Py_XDECREF(module); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les objets du module 'analysis...patterns.modifiers'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool populate_analysis_scan_exprs_module(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_scan_literal_expression_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/exprs/module.h b/plugins/pychrysalide/analysis/scan/exprs/module.h new file mode 100644 index 0000000..ee4b8ab --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/exprs/module.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire exprs en tant que module + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Ajoute le module 'analysis.scan.exprs' à un module Python. */ +bool add_analysis_scan_exprs_module(PyObject *); + +/* Intègre les objets du module 'analysis.scan.exprs'. */ +bool populate_analysis_scan_exprs_module(void); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_EXPRS_MODULE_H */ diff --git a/plugins/pychrysalide/analysis/scan/item.c b/plugins/pychrysalide/analysis/scan/item.c index 959694e..014ae24 100644 --- a/plugins/pychrysalide/analysis/scan/item.c +++ b/plugins/pychrysalide/analysis/scan/item.c @@ -38,14 +38,68 @@ -CREATE_DYN_CONSTRUCTOR(registered_item, G_TYPE_REGISTERED_ITEM); +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Initialise la classe des éléments appelables enregistrés. */ +static void py_scan_registered_item_init_gclass(GScanRegisteredItemClass *, gpointer); + +CREATE_DYN_ABSTRACT_CONSTRUCTOR(scan_registered_item, G_TYPE_SCAN_REGISTERED_ITEM, py_scan_registered_item_init_gclass); /* Initialise une instance sur la base du dérivé de GObject. */ -static int py_registered_item_init(PyObject *, PyObject *, PyObject *); +static int py_scan_registered_item_init(PyObject *, PyObject *, PyObject *); + +/* Indique le nom associé à une expression d'évaluation. */ +static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *); + +/* Lance une résolution d'élément à solliciter. */ +static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *, const char *, GScanContext *, GScanScope *, GScanRegisteredItem **); + +/* Réduit une expression à une forme plus simple. */ +static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *, GScanContext *, GScanScope *, GScanExpression **); + +/* Effectue un appel à une fonction enregistrée. */ +static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); + + + +/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ + /* Lance une résolution d'élément à appeler. */ -static PyObject *py_registered_item_resolve(PyObject *, PyObject *); +static PyObject *py_scan_registered_item_resolve(PyObject *, PyObject *); + +/* Fournit le désignation associée à un composant nommé. */ +static PyObject *py_scan_registered_item_get_name(PyObject *, void *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* unused = données non utilisées ici. * +* * +* Description : Initialise la classe des éléments appelables enregistrés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +static void py_scan_registered_item_init_gclass(GScanRegisteredItemClass *class, gpointer unused) +{ + class->get_name = py_scan_registered_item_get_name_wrapper; + class->resolve = py_scan_registered_item_resolve_wrapper; + class->reduce = py_scan_registered_item_reduce_wrapper; + class->run_call = py_scan_registered_item_run_call_wrapper; + +} /****************************************************************************** @@ -62,17 +116,26 @@ static PyObject *py_registered_item_resolve(PyObject *, PyObject *); * * ******************************************************************************/ -static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwds) +static int py_scan_registered_item_init(PyObject *self, PyObject *args, PyObject *kwds) { int ret; /* Bilan de lecture des args. */ -#define REGISTERED_ITEM_DOC \ - "The *RegisteredItem* class defines the basics for evaluation" \ - " items involved into content scanning.\n" \ +#define SCAN_REGISTERED_ITEM_DOC \ + "The *RegisteredItem* class is an abstract definition which is" \ + " the base for all keywords involved in a match condition" \ + " expression.\n" \ "\n" \ - "Instances can be created using the following constructor:\n" \ + "Calls to the *__init__* constructor of this abstract object" \ + " expect no particular argument.\n" \ "\n" \ - " RegisteredItem()" + "The following methods have to be defined for new classes:\n" \ + "* pychrysalide.analysis.scan.RegisteredItem._resolve();\n" \ + "* pychrysalide.analysis.scan.RegisteredItem._reduce();\n" \ + "* pychrysalide.analysis.scan.RegisteredItem._call().\n" \ + "\n" \ + "One item has to be defined as class attributes in the final" \ + " class:\n" \ + "* pychrysalide.analysis.scan.RegisteredItem._name.\n" /* Initialisation d'un objet GLib */ @@ -86,6 +149,338 @@ static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwd /****************************************************************************** * * +* Paramètres : item = élément d'appel à consulter. * +* * +* Description : Indique le nom associé à une expression d'évaluation. * +* * +* Retour : Désignation humaine de l'expression d'évaluation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_scan_registered_item_get_name_wrapper(const GScanRegisteredItem *item) +{ + char *result; /* Désignation à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyname; /* Nom en objet Python */ + int ret; /* Bilan d'une conversion */ + +#define SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER PYTHON_GETTER_WRAPPER_DEF \ +( \ + _name, \ + "Provide the keyword of the expression item to be evaluated.\n" \ + "\n" \ + "The result has to be a string." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(item)); + + if (PyObject_HasAttrString(pyobj, "_name")) + { + pyname = PyObject_GetAttrString(pyobj, "_name"); + + if (pyname != NULL) + { + ret = PyUnicode_Check(pyname); + + if (ret) + result = strdup(PyUnicode_AsUTF8(pyname)); + + Py_DECREF(pyname); + + } + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* target = désignation de l'objet d'appel à identifier. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT]* +* * +* Description : Lance une résolution d'élément à solliciter. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_scan_registered_item_resolve_wrapper(GScanRegisteredItem *item, const char *target, GScanContext *ctx, GScanScope *scope, GScanRegisteredItem **out) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan de consultation */ + GObject *gobj_ret; /* Bilan natif de consultation */ + +#define SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _cmp_rich, "$self, target, ctx, scope, /", \ + METH_VARARGS, \ + "Abstract method used to resolve an item by name.\n" \ + "\n" \ + "The *target* argument provide the name of the searched item;" \ + " *ctx* is a pychrysalide.analysis.scan.ScanContext instance" \ + " providing information about the current state; *scope* is a" \ + " pychrysalide.analysis.scan.ScanScope offering a view on the" \ + " current namespace for variables.\n" \ + "\n" \ + "The result has to be a pychrysalide.analysis.scan.RegisteredItem" \ + " instance on success, or *None* in case of failure." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(item)); + + if (has_python_method(pyobj, "_resolve")) + { + args = PyTuple_New(3); + PyTuple_SetItem(args, 0, PyUnicode_FromString(target)); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(ctx))); + PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(scope))); + + pyret = run_python_method(pyobj, "_resolve", args); + + if (pyret != NULL) + { + gobj_ret = pygobject_get(pyret); + + if (G_IS_SCAN_REGISTERED_ITEM(gobj_ret)) + { + *out = G_SCAN_REGISTERED_ITEM(gobj_ret); + + g_object_ref(G_OBJECT(*out)); + result = true; + + } + + Py_DECREF(pyret); + + } + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * +* * +* Description : Réduit une expression à une forme plus simple. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_scan_registered_item_reduce_wrapper(GScanRegisteredItem *item, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan de consultation */ + GObject *gobj_ret; /* Bilan natif de consultation */ + +#define SCAN_REGISTERED_ITEM_REDUCE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _cmp_rich, "$self, ctx, scope, /", \ + METH_VARARGS, \ + "Abstract method used to replace the item by an equivalent reduced" \ + " value.\n" \ + "\n" \ + "The *ctx* argument is a pychrysalide.analysis.scan.ScanContext" \ + " instance providing information about the current state; *scope*" \ + " is a pychrysalide.analysis.scan.ScanScope offering a view on the" \ + " current namespace for variables.\n" \ + "\n" \ + "The result has to be a pychrysalide.analysis.scan.ScanExpression" \ + " instance on success, or *None* in case of failure." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(item)); + + if (has_python_method(pyobj, "_reduce")) + { + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(ctx))); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(scope))); + + pyret = run_python_method(pyobj, "_reduce", args); + + if (pyret != NULL) + { + gobj_ret = pygobject_get(pyret); + + if (G_IS_SCAN_EXPRESSION(gobj_ret)) + { + *out = G_SCAN_EXPRESSION(gobj_ret); + + g_object_ref(G_OBJECT(*out)); + result = true; + + } + + Py_DECREF(pyret); + + } + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = élément d'appel à consulter. * +* args = liste d'éventuels arguments fournis. * +* count = taille de cette liste. * +* ctx = contexte de suivi de l'analyse courante. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la résolution opérée. [OUT] * +* * +* Description : Effectue un appel à une fonction enregistrée. * +* * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_scan_registered_item_run_call_wrapper(GScanRegisteredItem *item, GScanExpression **args, size_t count, GScanContext *ctx, GScanScope *scope, GObject **out) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *sub_args; /* Sous-arguments pour l'appel */ + size_t i; /* Boucle de parcours */ + PyObject *py_args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan de consultation */ + GObject *gobj_ret; /* Bilan natif de consultation */ + +#define SCAN_REGISTERED_ITEM_CALL_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _cmp_rich, "$self, args, ctx, scope, /", \ + METH_VARARGS, \ + "Abstract method used to replace the item and its arguments by an" \ + " equivalent reduced value.\n" \ + "\n" \ + "The *args* argument is a tuple of already reduced" \ + " pychrysalide.analysis.scan.ScanExpression objects; ctx* argument" \ + " is a pychrysalide.analysis.scan.ScanContext instance providing" \ + " information about the current state; *scope* is a" \ + " pychrysalide.analysis.scan.ScanScope offering a view on the" \ + " current namespace for variables.\n" \ + "\n" \ + "The result has to be a pychrysalide.analysis.scan.ScanExpression" \ + " instance on success, or *None* in case of failure." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(item)); + + if (has_python_method(pyobj, "_call")) + { + sub_args = PyTuple_New(count); + + for (i = 0; i < count; i++) + PyTuple_SetItem(sub_args, 1, pygobject_new(G_OBJECT(args[i]))); + + py_args = PyTuple_New(3); + PyTuple_SetItem(py_args, 0, sub_args); + PyTuple_SetItem(py_args, 1, pygobject_new(G_OBJECT(ctx))); + PyTuple_SetItem(py_args, 2, pygobject_new(G_OBJECT(scope))); + + pyret = run_python_method(pyobj, "_call", py_args); + + if (pyret != NULL) + { + gobj_ret = pygobject_get(pyret); + + if (G_IS_OBJECT(gobj_ret)) + { + *out = gobj_ret; + + g_object_ref(G_OBJECT(*out)); + result = true; + + } + + Py_DECREF(pyret); + + } + + Py_DECREF(py_args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CONNEXION AVEC L'API DE PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * * Paramètres : self = élément d'appel à consulter. * * args = arguments fournis pour l'opération. * * * @@ -99,21 +494,21 @@ static int py_registered_item_init(PyObject *self, PyObject *args, PyObject *kwd * * ******************************************************************************/ -static PyObject *py_registered_item_resolve(PyObject *self, PyObject *args) +static PyObject *py_scan_registered_item_resolve(PyObject *self, PyObject *args) { PyObject *result; /* Bilan à retourner */ const char *target; /* Désignation de la cible */ GScanContext *ctx; /* Contexte d'analyse */ GScanScope *scope; /* Portée de variables locales */ int ret; /* Bilan de lecture des args. */ - GRegisteredItem *item; /* Version native */ + GScanRegisteredItem *item; /* Version native */ bool status; /* Bilan d'exécution */ - GRegisteredItem *resolved; /* Elément trouvé */ + GScanRegisteredItem *resolved; /* Elément trouvé */ -#define REGISTERED_ITEM_RESOLVE_METHOD PYTHON_METHOD_DEF \ +#define SCAN_REGISTERED_ITEM_RESOLVE_METHOD PYTHON_METHOD_DEF \ ( \ resolve, "$self, target, /, ctx=None, scope=None", \ - METH_VARARGS, py_registered_item, \ + METH_VARARGS, py_scan_registered_item, \ "Resolve a name into a scan item." \ "\n" \ "The *target* name is the only mandatory parameter and has to point"\ @@ -137,9 +532,9 @@ static PyObject *py_registered_item_resolve(PyObject *self, PyObject *args) convert_to_scan_context, &ctx); if (!ret) return NULL; - item = G_REGISTERED_ITEM(pygobject_get(self)); + item = G_SCAN_REGISTERED_ITEM(pygobject_get(self)); - status = g_registered_item_resolve(item, target, ctx, scope, &resolved); + status = g_scan_registered_item_resolve(item, target, ctx, scope, &resolved); if (!status) { @@ -178,23 +573,23 @@ static PyObject *py_registered_item_resolve(PyObject *self, PyObject *args) * * ******************************************************************************/ -static PyObject *py_registered_item_get_name(PyObject *self, void *closure) +static PyObject *py_scan_registered_item_get_name(PyObject *self, void *closure) { PyObject *result; /* Décompte à retourner */ - GRegisteredItem *item; /* Version native */ + GScanRegisteredItem *item; /* Version native */ char *name; /* Désignation à convertir */ -#define REGISTERED_ITEM_NAME_ATTRIB PYTHON_GET_DEF_FULL \ +#define SCAN_REGISTERED_ITEM_NAME_ATTRIB PYTHON_GET_DEF_FULL \ ( \ - name, py_registered_item, \ + name, py_scan_registered_item, \ "Name linked to the registered item.\n" \ "\n" \ "The result should be a string, or *None* for the root namespace." \ ) - item = G_REGISTERED_ITEM(pygobject_get(self)); + item = G_SCAN_REGISTERED_ITEM(pygobject_get(self)); - name = g_registered_item_get_name(item); + name = g_scan_registered_item_get_name(item); if (name == NULL) { @@ -224,38 +619,42 @@ static PyObject *py_registered_item_get_name(PyObject *self, void *closure) * * ******************************************************************************/ -PyTypeObject *get_python_registered_item_type(void) +PyTypeObject *get_python_scan_registered_item_type(void) { - static PyMethodDef py_registered_item_methods[] = { - REGISTERED_ITEM_RESOLVE_METHOD, + static PyMethodDef py_scan_registered_item_methods[] = { + SCAN_REGISTERED_ITEM_RESOLVE_WRAPPER, + SCAN_REGISTERED_ITEM_REDUCE_WRAPPER, + SCAN_REGISTERED_ITEM_CALL_WRAPPER, + SCAN_REGISTERED_ITEM_RESOLVE_METHOD, { NULL } }; - static PyGetSetDef py_registered_item_getseters[] = { - REGISTERED_ITEM_NAME_ATTRIB, + static PyGetSetDef py_scan_registered_item_getseters[] = { + SCAN_REGISTERED_ITEM_NAME_ATTRIB_WRAPPER, + SCAN_REGISTERED_ITEM_NAME_ATTRIB, { NULL } }; - static PyTypeObject py_registered_item_type = { + static PyTypeObject py_scan_registered_item_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.analysis.scan.RegisteredItem", + .tp_name = "pychrysalide.analysis.scan.ScanRegisteredItem", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE, - .tp_doc = REGISTERED_ITEM_DOC, + .tp_doc = SCAN_REGISTERED_ITEM_DOC, - .tp_methods = py_registered_item_methods, - .tp_getset = py_registered_item_getseters, + .tp_methods = py_scan_registered_item_methods, + .tp_getset = py_scan_registered_item_getseters, - .tp_init = py_registered_item_init, - .tp_new = py_registered_item_new, + .tp_init = py_scan_registered_item_init, + .tp_new = py_scan_registered_item_new, }; - return &py_registered_item_type; + return &py_scan_registered_item_type; } @@ -264,7 +663,7 @@ PyTypeObject *get_python_registered_item_type(void) * * * Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide...scan.RegisteredItem'.* +* Description : Prend en charge l'objet 'pychrysalide...ScanRegisteredItem'. * * * * Retour : Bilan de l'opération. * * * @@ -272,13 +671,13 @@ PyTypeObject *get_python_registered_item_type(void) * * ******************************************************************************/ -bool ensure_python_registered_item_is_registered(void) +bool ensure_python_scan_registered_item_is_registered(void) { - PyTypeObject *type; /* Type Python 'RegisteredItem' */ + PyTypeObject *type; /* Type 'ScanRegisteredItem' */ PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ - type = get_python_registered_item_type(); + type = get_python_scan_registered_item_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) { @@ -286,7 +685,7 @@ bool ensure_python_registered_item_is_registered(void) dict = PyModule_GetDict(module); - if (!register_class_for_pygobject(dict, G_TYPE_REGISTERED_ITEM, type)) + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_REGISTERED_ITEM, type)) return false; } @@ -309,11 +708,11 @@ bool ensure_python_registered_item_is_registered(void) * * ******************************************************************************/ -int convert_to_registered_item(PyObject *arg, void *dst) +int convert_to_scan_registered_item(PyObject *arg, void *dst) { int result; /* Bilan à retourner */ - result = PyObject_IsInstance(arg, (PyObject *)get_python_registered_item_type()); + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_registered_item_type()); switch (result) { @@ -327,7 +726,7 @@ int convert_to_registered_item(PyObject *arg, void *dst) break; case 1: - *((GRegisteredItem **)dst) = G_REGISTERED_ITEM(pygobject_get(arg)); + *((GScanRegisteredItem **)dst) = G_SCAN_REGISTERED_ITEM(pygobject_get(arg)); break; default: diff --git a/plugins/pychrysalide/analysis/scan/item.h b/plugins/pychrysalide/analysis/scan/item.h index b3f1661..773908c 100644 --- a/plugins/pychrysalide/analysis/scan/item.h +++ b/plugins/pychrysalide/analysis/scan/item.h @@ -32,13 +32,13 @@ /* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_registered_item_type(void); +PyTypeObject *get_python_scan_registered_item_type(void); -/* Prend en charge l'objet 'pychrysalide.analysis.scan.RegisteredItem'. */ -bool ensure_python_registered_item_is_registered(void); +/* Prend en charge l'objet 'pychrysalide.analysis.scan.ScanRegisteredItem'. */ +bool ensure_python_scan_registered_item_is_registered(void); /* Tente de convertir en expression d'évaluation généraliste. */ -int convert_to_registered_item(PyObject *, void *); +int convert_to_scan_registered_item(PyObject *, void *); diff --git a/plugins/pychrysalide/analysis/scan/module.c b/plugins/pychrysalide/analysis/scan/module.c index ff19d92..9ae0e52 100644 --- a/plugins/pychrysalide/analysis/scan/module.c +++ b/plugins/pychrysalide/analysis/scan/module.c @@ -35,6 +35,7 @@ #include "options.h" #include "scanner.h" #include "space.h" +#include "exprs/module.h" #include "patterns/module.h" #include "../../helpers.h" @@ -76,6 +77,7 @@ bool add_analysis_scan_module(PyObject *super) result = (module != NULL); + if (result) result = add_analysis_scan_exprs_module(module); if (result) result = add_analysis_scan_patterns_module(module); if (!result) @@ -107,12 +109,13 @@ bool populate_analysis_scan_module(void) if (result) result = ensure_python_content_scanner_is_registered(); if (result) result = ensure_python_scan_context_is_registered(); if (result) result = ensure_python_scan_expression_is_registered(); - if (result) result = ensure_python_registered_item_is_registered(); + if (result) result = ensure_python_scan_registered_item_is_registered(); if (result) result = ensure_python_scan_options_is_registered(); if (result) result = ensure_python_scan_namespace_is_registered(); if (result) result = populate_scan_module_with_core_methods(); + if (result) result = populate_analysis_scan_exprs_module(); if (result) result = populate_analysis_scan_patterns_module(); assert(result); diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifier.c b/plugins/pychrysalide/analysis/scan/patterns/modifier.c index 4cae011..6547d91 100644 --- a/plugins/pychrysalide/analysis/scan/patterns/modifier.c +++ b/plugins/pychrysalide/analysis/scan/patterns/modifier.c @@ -91,19 +91,27 @@ static int py_scan_token_modifier_init(PyObject *self, PyObject *args, PyObject static PyObject *py_scan_token_modifier_transform(PyObject *self, PyObject *args) { PyObject *result; /* Bilan à faire remonter */ - const char *data; /* Séquence d'octets à traiter */ + PyObject *py_src; /* Motifs Python en entrée */ + PyObject *py_arg; /* Eventuel paramètre de config*/ + sized_binary_t src; /* Entrée au format adapté */ Py_ssize_t len; /* Quantité de ces données */ int ret; /* Bilan de lecture des args. */ - sized_binary_t src; /* Entrée au format adapté */ + sized_binary_t *src_list; /* Entrées au format adapté */ + size_t scount; /* Taille de cette liste */ + bool dyn_src; /* Allocation dynamique ? */ + Py_ssize_t size; /* Taille d'une séquence */ + Py_ssize_t k; /* Boucle de parcours #1 */ + PyObject *item; /* Elément de liste de motifs */ + modifier_arg_t arg; /* Eventuelle précision */ GScanTokenModifier *modifier; /* Version native de l'instance*/ sized_binary_t *dest; /* Liste des nouvelles chaînes */ - size_t count; /* Taille de cette liste */ + size_t dcount; /* Taille de cette liste */ bool status; /* Bilan de l'opération */ - size_t i; /* Boucle de parcours */ + size_t i; /* Boucle de parcours #2 */ #define SCAN_TOKEN_MODIFIER_TRANSFORM_METHOD PYTHON_METHOD_DEF \ ( \ - transform, "$self, data", \ + transform, "$self, data, /, arg", \ METH_VARARGS, py_scan_token_modifier, \ "Transform data from a byte pattern for an incoming scan.\n" \ "\n" \ @@ -113,21 +121,105 @@ static PyObject *py_scan_token_modifier_transform(PyObject *self, PyObject *args " *None* in case of error." \ ) - ret = PyArg_ParseTuple(args, "s#", &data, &len); + py_arg = NULL; + + ret = PyArg_ParseTuple(args, "O|O", &py_src, &py_arg); if (!ret) return NULL; - src.data = (char *)data; - src.len = len; + /* Constitution des motifs d'entrée */ + + if (PyBytes_Check(py_src)) + { + ret = PyBytes_AsStringAndSize(py_src, &src.data, &len); + if (ret == -1) return NULL; + + src.len = len; + + src_list = &src; + scount = 1; + + dyn_src = false; + + } + + else if (PySequence_Check(py_src)) + { + size = PySequence_Size(py_src); + + src_list = malloc(size * sizeof(sized_binary_t)); + scount = size; + + dyn_src = true; + + for (k = 0; k < size; k++) + { + item = PySequence_ITEM(py_src, k); + + if (PyBytes_Check(item)) + { + ret = PyBytes_AsStringAndSize(item, &src_list[k].data, &len); + if (ret == -1) return NULL; + + src_list[k].len = len; + + } + else + { + free(src_list); + + PyErr_SetString(PyExc_TypeError, "lists of items other than bytes are not supported"); + return NULL; + } + + } + + } + + else + { + PyErr_SetString(PyExc_TypeError, "only bytes and lists of bytes are expected as input for modifiers"); + return NULL; + } + + /* Récupération d'une éventuelle précision opérationnelle */ + + if (py_arg != NULL) + { + if (PyLong_Check(py_arg)) + { + arg.type = MAT_UNSIGNED_INTEGER; + arg.value.u_integer = PyLong_AsUnsignedLongLong(py_arg); + } + + else + { + if (dyn_src) + free(src_list); + + PyErr_SetString(PyExc_TypeError, "unable to handle the argument type for calling a modifier"); + return NULL; + + } + + } + + /* Création des nouveaux motifs */ modifier = G_SCAN_TOKEN_MODIFIER(pygobject_get(self)); - status = g_scan_token_modifier_transform(modifier, &src, &dest, &count); + if (py_arg == NULL) + status = g_scan_token_modifier_transform(modifier, src_list, scount, &dest, &dcount); + else + status = g_scan_token_modifier_transform_with_arg(modifier, src_list, scount, &arg, &dest, &dcount); + + if (dyn_src) + free(src_list); if (status) { - result = PyTuple_New(count); + result = PyTuple_New(dcount); - for (i = 0; i < count; i++) + for (i = 0; i < dcount; i++) { PyTuple_SetItem(result, i, PyBytes_FromStringAndSize(dest[i].data, dest[i].len)); exit_szstr(&dest[i]); @@ -226,7 +318,7 @@ PyTypeObject *get_python_scan_token_modifier_type(void) .tp_name = "pychrysalide.analysis.scan.patterns.TokenModifier", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_doc = SCAN_TOKEN_MODIFIER_DOC, diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am index baf7ed5..ae53e45 100644 --- a/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/Makefile.am @@ -6,7 +6,8 @@ libpychrysaanalysisscanpatternsmodifiers_la_SOURCES = \ list.h list.c \ module.h module.c \ plain.h plain.c \ - rev.h rev.c + rev.h rev.c \ + xor.h xor.c libpychrysaanalysisscanpatternsmodifiers_la_CFLAGS = $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) $(TOOLKIT_CFLAGS) \ -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c index d0d1e1f..503580d 100644 --- a/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/hex.c @@ -131,7 +131,7 @@ PyTypeObject *get_python_scan_hex_modifier_type(void) * * * Paramètres : - * * * -* Description : Prend en charge l'objet 'pychrysalide....HexModifier'. * +* Description : Prend en charge l'objet 'pychrysalide....HexModifier'. * * * * Retour : Bilan de l'opération. * * * @@ -141,7 +141,7 @@ PyTypeObject *get_python_scan_hex_modifier_type(void) bool ensure_python_scan_hex_modifier_is_registered(void) { - PyTypeObject *type; /* Type Python 'HexModifier' */ + PyTypeObject *type; /* Type Python 'HexModifier' */ PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c index 1e9bda7..ae450dc 100644 --- a/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/module.c @@ -32,6 +32,7 @@ #include "list.h" #include "plain.h" #include "rev.h" +#include "xor.h" #include "../../../../helpers.h" @@ -102,6 +103,7 @@ bool populate_analysis_scan_patterns_modifiers_module(void) if (result) result = ensure_python_scan_modifier_list_is_registered(); if (result) result = ensure_python_scan_plain_modifier_is_registered(); if (result) result = ensure_python_scan_reverse_modifier_is_registered(); + if (result) result = ensure_python_scan_xor_modifier_is_registered(); assert(result); diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c index 6ee350c..841e929 100644 --- a/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/rev.c @@ -141,7 +141,7 @@ PyTypeObject *get_python_scan_reverse_modifier_type(void) bool ensure_python_scan_reverse_modifier_is_registered(void) { - PyTypeObject *type; /* Type Python 'HexModifier' */ + PyTypeObject *type; /* Type Python ReverseModifier */ PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c new file mode 100644 index 0000000..17a32f4 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c @@ -0,0 +1,210 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * xor.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/xor.c" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "xor.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <analysis/scan/patterns/modifiers/xor.h> + + +#include "../modifier.h" +#include "../../../../access.h" +#include "../../../../helpers.h" + + + +CREATE_DYN_CONSTRUCTOR(scan_xor_modifier, G_TYPE_SCAN_XOR_MODIFIER); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_scan_xor_modifier_init(PyObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_scan_xor_modifier_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define SCAN_XOR_MODIFIER_DOC \ + "The *XorModifier* class transforms a byte pattern by XORing bytes.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " XorModifier()" + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_scan_xor_modifier_type(void) +{ + static PyMethodDef py_scan_xor_modifier_methods[] = { + { NULL } + }; + + static PyGetSetDef py_scan_xor_modifier_getseters[] = { + { NULL } + }; + + static PyTypeObject py_scan_xor_modifier_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.scan.patterns.modifiers.XorModifier", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SCAN_XOR_MODIFIER_DOC, + + .tp_methods = py_scan_xor_modifier_methods, + .tp_getset = py_scan_xor_modifier_getseters, + + .tp_init = py_scan_xor_modifier_init, + .tp_new = py_scan_xor_modifier_new, + + }; + + return &py_scan_xor_modifier_type; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prend en charge l'objet 'pychrysalide....XorModifier'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_scan_xor_modifier_is_registered(void) +{ + PyTypeObject *type; /* Type Python XorModifier */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_scan_xor_modifier_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.scan.patterns.modifiers"); + + dict = PyModule_GetDict(module); + + if (!ensure_python_scan_token_modifier_is_registered()) + return false; + + if (!register_class_for_pygobject(dict, G_TYPE_SCAN_XOR_MODIFIER, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en transformation d'octets par inverse. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_scan_xor_modifier(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_scan_xor_modifier_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to XOR modifier"); + break; + + case 1: + *((GScanXorModifier **)dst) = G_SCAN_XOR_MODIFIER(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h new file mode 100644 index 0000000..7b9bb69 --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * xor.h - équivalent Python du fichier "analysis/scan/patterns/modifiers/xor.h" + * + * 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_scan_xor_modifier_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.scan.patterns.modifiers.XorModifier'. */ +bool ensure_python_scan_xor_modifier_is_registered(void); + +/* Tente de convertir en transformation d'octets par inverse. */ +int convert_to_scan_xor_modifier(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H */ diff --git a/plugins/pychrysalide/analysis/scan/scanner.c b/plugins/pychrysalide/analysis/scan/scanner.c index e2d5a18..bc58c9a 100644 --- a/plugins/pychrysalide/analysis/scan/scanner.c +++ b/plugins/pychrysalide/analysis/scan/scanner.c @@ -76,6 +76,7 @@ static PyObject *py_content_scanner_get_filename(PyObject *, void *); static int py_content_scanner_init(PyObject *self, PyObject *args, PyObject *kwds) { const char *text; /* Contenu de règles à traiter */ + Py_ssize_t len; /* Taille de ce nom */ const char *filename; /* Fichier de définitions */ int ret; /* Bilan de lecture des args. */ GContentScanner *scanner; /* Création GLib à transmettre */ @@ -100,9 +101,10 @@ static int py_content_scanner_init(PyObject *self, PyObject *args, PyObject *kwd /* Récupération des paramètres */ text = NULL; + len = 0; filename = NULL; - ret = PyArg_ParseTupleAndKeywords(args, kwds, "|ss", kwlist, &text, &filename); + ret = PyArg_ParseTupleAndKeywords(args, kwds, "|s#s", kwlist, &text, &len, &filename); if (!ret) return -1; /* Initialisation d'un objet GLib */ @@ -116,7 +118,7 @@ static int py_content_scanner_init(PyObject *self, PyObject *args, PyObject *kwd if (text != NULL) { - if (!g_content_scanner_create_from_text(scanner, text)) + if (!g_content_scanner_create_from_text(scanner, text, len)) { PyErr_SetString(PyExc_ValueError, _("Unable to create content scanner.")); return -1; diff --git a/plugins/pychrysalide/analysis/scan/space.c b/plugins/pychrysalide/analysis/scan/space.c index 79e0c28..6ea87b8 100644 --- a/plugins/pychrysalide/analysis/scan/space.c +++ b/plugins/pychrysalide/analysis/scan/space.c @@ -122,7 +122,7 @@ static int py_scan_namespace_init(PyObject *self, PyObject *args, PyObject *kwds static PyObject *py_scan_namespace_register_item(PyObject *self, PyObject *args) { PyObject *result; /* Bilan à retourner */ - GRegisteredItem *item; /* Elément d'évaluation à lier */ + GScanRegisteredItem *item; /* Elément d'évaluation à lier */ int ret; /* Bilan de lecture des args. */ GScanNamespace *space; /* Version native */ bool status; /* Bilan de l'opération */ @@ -140,7 +140,7 @@ static PyObject *py_scan_namespace_register_item(PyObject *self, PyObject *args) " *True* in case of success, *False* for a failure.\n" \ ) - ret = PyArg_ParseTuple(args, "O&", convert_to_registered_item, &item); + ret = PyArg_ParseTuple(args, "O&", convert_to_scan_registered_item, &item); if (!ret) return NULL; space = G_SCAN_NAMESPACE(pygobject_get(self)); @@ -185,7 +185,7 @@ PyTypeObject *get_python_scan_namespace_type(void) .tp_name = "pychrysalide.analysis.scan.ScanNamespace", .tp_basicsize = sizeof(PyGObject), - .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_doc = SCAN_NAMESPACE_DOC, diff --git a/plugins/pychrysalide/common/bits.c b/plugins/pychrysalide/common/bits.c index 9275996..a127251 100644 --- a/plugins/pychrysalide/common/bits.c +++ b/plugins/pychrysalide/common/bits.c @@ -98,6 +98,9 @@ static PyObject *py_bitfield_test_zeros_with(PyObject *, PyObject *); /* Teste l'état à 1 de bits selon un masque de bits. */ static PyObject *py_bitfield_test_ones_with(PyObject *, PyObject *); +/* Recherche un prochain bit défini dans un champ de bits. */ +static PyObject *py_bitfield_find_next_set(PyObject *, PyObject *); + /* Indique la taille d'un champ de bits donné. */ static PyObject *py_bitfield_get_size(PyObject *, void *); @@ -891,6 +894,58 @@ static PyObject *py_bitfield_test_ones_with(PyObject *self, PyObject *args) /****************************************************************************** * * +* Paramètres : self = champ de bits à consulter. * +* args = arguments fournis pour la conduite de l'opération. * +* * +* Description : Recherche un prochain bit défini dans un champ de bits. * +* * +* Retour : Position d'un bit à 1 ou taille du champ si plus aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_bitfield_find_next_set(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à faire remonter */ + unsigned long prev; /* Indice d'un bit à écarter */ + int ret; /* Bilan de lecture des args. */ + py_bitfield_t *bf; /* Instance à manipuler */ + size_t found; /* Indice de bit trouvé */ + +#define BITFIELD_FIND_NEXT_SET_METHOD PYTHON_METHOD_DEF \ +( \ + find_next_set, "$self, /, prev=None", \ + METH_VARARGS, py_bitfield, \ + "Find the index of the next set bit in the bit field.\n"\ + "\n" \ + "If provided, the *prev* argument is the position of" \ + " a previously found bit, which gets discarded for the" \ + " current call.\n" \ + "\n" \ + "The result is a integer value: a valid index inside" \ + " the bit field, or the bit field size if no set bit" \ + " is found." \ +) + + prev = (unsigned long)-1; + + ret = PyArg_ParseTuple(args, "|k", &prev); + if (!ret) return NULL; + + bf = (py_bitfield_t *)self; + + found = find_next_set_in_bit_field(bf->native, prev == (unsigned long)-1 ? NULL : (size_t []) { prev }); + + result = PyLong_FromSize_t(found); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : self = classe représentant une instruction. * * closure = adresse non utilisée ici. * * * @@ -998,6 +1053,7 @@ PyTypeObject *get_python_bitfield_type(void) BITFIELD_TEST_ALL_METHOD, BITFIELD_TEST_ZEROS_WITH_METHOD, BITFIELD_TEST_ONES_WITH_METHOD, + BITFIELD_FIND_NEXT_SET_METHOD, { NULL } }; diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c index 771d129..08f570f 100644 --- a/plugins/pychrysalide/core.c +++ b/plugins/pychrysalide/core.c @@ -64,8 +64,10 @@ #include "debug/module.h" #include "format/module.h" #include "glibext/module.h" -#include "gtkext/module.h" -#include "gui/module.h" +#ifdef INCLUDE_GTK_SUPPORT +# include "gtkext/module.h" +# include "gui/module.h" +#endif #include "mangling/module.h" #include "plugins/module.h" #include "plugins/plugin.h" @@ -101,7 +103,9 @@ static bool is_current_abi_suitable(void); static bool install_metaclass_for_python_gobjects(void); /* Définit la version attendue de GTK à charger dans Python. */ +#ifdef INCLUDE_GTK_SUPPORT static bool set_version_for_gtk_namespace(const char *); +#endif /* Point de sortie pour l'initialisation de Python. */ static void PyExit_pychrysalide(void); @@ -423,7 +427,7 @@ static bool install_metaclass_for_python_gobjects(void) * Remarques : - * * * ******************************************************************************/ - +#ifdef INCLUDE_GTK_SUPPORT static bool set_version_for_gtk_namespace(const char *version) { bool result; /* Bilan à retourner */ @@ -459,6 +463,7 @@ static bool set_version_for_gtk_namespace(const char *version) return result; } +#endif /****************************************************************************** @@ -584,8 +589,10 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) if (!install_metaclass_for_python_gobjects()) goto exit; +#ifdef INCLUDE_GTK_SUPPORT if (!set_version_for_gtk_namespace("3.0")) goto exit; +#endif if (!load_all_core_components(true)) { @@ -800,11 +807,11 @@ static void load_python_plugins(GPluginModule *plugin) if (dir != NULL) { - closedir(dir); + closedir(dir); - edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "python"); - extend_python_path(edir); - free(edir); + edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "python"); + extend_python_path(edir); + free(edir); } @@ -821,7 +828,7 @@ static void load_python_plugins(GPluginModule *plugin) save = NULL; /* gcc... */ for (path = strtok_r(paths, ":", &save); - path != NULL; + path != NULL; path = strtok_r(NULL, ":", &save)) { dir = opendir(path); @@ -900,7 +907,7 @@ static void load_python_plugins(GPluginModule *plugin) } - closedir(dir); + closedir(dir); } @@ -944,8 +951,6 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) gstate = PyGILState_Ensure(); - PySys_SetArgv(0, (wchar_t *[]) { NULL }); - _chrysalide_module = PyImport_ImportModule("pychrysalide"); /** diff --git a/plugins/pychrysalide/plugins/plugin.c b/plugins/pychrysalide/plugins/plugin.c index 340c617..b013345 100644 --- a/plugins/pychrysalide/plugins/plugin.c +++ b/plugins/pychrysalide/plugins/plugin.c @@ -1796,8 +1796,6 @@ GPluginModule *create_python_plugin(const char *modname, const char *filename) if (class == NULL) goto no_class; if (!PyType_Check(class->ob_type)) goto no_class; - Py_INCREF(class); - instance = PyObject_CallFunction(class, NULL); if (instance == NULL) goto no_instance; diff --git a/plugins/python/scripting/core.py b/plugins/python/scripting/core.py index ff912ed..135edb4 100644 --- a/plugins/python/scripting/core.py +++ b/plugins/python/scripting/core.py @@ -1,4 +1,7 @@ +import gi +gi.require_version('Gtk', '3.0') + from gi.repository import GLib, Gtk import os |
