From 3ab6c0c0072ae0e2abde48d60d7eac18f084a764 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 1 Oct 2023 20:08:26 +0200 Subject: Introduce parameters for scan pattern modifiers. --- plugins/pychrysalide/analysis/scan/Makefile.am | 2 +- plugins/pychrysalide/analysis/scan/core.c | 9 +- .../pychrysalide/analysis/scan/patterns/modifier.c | 114 +++++- .../analysis/scan/patterns/modifiers/Makefile.am | 3 +- .../analysis/scan/patterns/modifiers/hex.c | 4 +- .../analysis/scan/patterns/modifiers/module.c | 2 + .../analysis/scan/patterns/modifiers/rev.c | 2 +- .../analysis/scan/patterns/modifiers/xor.c | 210 +++++++++++ .../analysis/scan/patterns/modifiers/xor.h | 45 +++ src/analysis/scan/core.c | 23 +- src/analysis/scan/core.h | 2 +- src/analysis/scan/grammar.y | 76 +++- src/analysis/scan/patterns/Makefile.am | 3 + src/analysis/scan/patterns/customizer-int.h | 58 +++ src/analysis/scan/patterns/customizer.c | 374 +++++++++++++++++++ src/analysis/scan/patterns/customizer.h | 65 ++++ src/analysis/scan/patterns/modarg.h | 91 +++++ src/analysis/scan/patterns/modifier-int.h | 10 +- src/analysis/scan/patterns/modifier.c | 76 +++- src/analysis/scan/patterns/modifier.h | 10 +- src/analysis/scan/patterns/modifiers/Makefile.am | 3 +- src/analysis/scan/patterns/modifiers/hex.c | 33 +- src/analysis/scan/patterns/modifiers/list.c | 21 +- src/analysis/scan/patterns/modifiers/plain.c | 25 +- src/analysis/scan/patterns/modifiers/rev.c | 29 +- src/analysis/scan/patterns/modifiers/xor.c | 395 +++++++++++++++++++++ src/analysis/scan/patterns/modifiers/xor.h | 58 +++ src/analysis/scan/patterns/tokens/nodes/plain.c | 2 +- src/analysis/scan/tokens.l | 34 +- tests/analysis/scan/pyapi.py | 25 +- 30 files changed, 1720 insertions(+), 84 deletions(-) create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c create mode 100644 plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.h create mode 100644 src/analysis/scan/patterns/customizer-int.h create mode 100644 src/analysis/scan/patterns/customizer.c create mode 100644 src/analysis/scan/patterns/customizer.h create mode 100644 src/analysis/scan/patterns/modarg.h create mode 100644 src/analysis/scan/patterns/modifiers/xor.c create mode 100644 src/analysis/scan/patterns/modifiers/xor.h diff --git a/plugins/pychrysalide/analysis/scan/Makefile.am b/plugins/pychrysalide/analysis/scan/Makefile.am index 32bf1e3..0b20ca5 100644 --- a/plugins/pychrysalide/analysis/scan/Makefile.am +++ b/plugins/pychrysalide/analysis/scan/Makefile.am @@ -15,7 +15,7 @@ libpychrysaanalysisscan_la_SOURCES = \ libpychrysaanalysisscan_la_LIBADD = \ 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 diff --git a/plugins/pychrysalide/analysis/scan/core.c b/plugins/pychrysalide/analysis/scan/core.c index f609f7d..dcf5bf8 100644 --- a/plugins/pychrysalide/analysis/scan/core.c +++ b/plugins/pychrysalide/analysis/scan/core.c @@ -119,7 +119,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 +136,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/patterns/modifier.c b/plugins/pychrysalide/analysis/scan/patterns/modifier.c index 4cae011..0fec60c 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]); 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..1280f2f --- /dev/null +++ b/plugins/pychrysalide/analysis/scan/patterns/modifiers/xor.c @@ -0,0 +1,210 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * hex.c - équivalent Python du fichier "analysis/scan/patterns/modifiers/hex.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 + + +#include +#include + + +#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_HEX_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_HEX_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 +#include + + + +/* 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/src/analysis/scan/core.c b/src/analysis/scan/core.c index da3cf00..6316a53 100644 --- a/src/analysis/scan/core.c +++ b/src/analysis/scan/core.c @@ -46,13 +46,14 @@ #include "patterns/modifiers/hex.h" #include "patterns/modifiers/plain.h" #include "patterns/modifiers/rev.h" +#include "patterns/modifiers/xor.h" /* Liste des modificateurs disponibles */ typedef struct _available_modifier_t { - char *name; /* Désignation humaine */ + sized_string_t name; /* Désignation humaine */ GScanTokenModifier *instance; /* Mécanisme correspondant */ } available_modifier_t; @@ -76,18 +77,19 @@ static size_t __modifiers_count = 0; bool register_scan_token_modifier(GScanTokenModifier *modifier) { bool result; /* Bilan à retourner */ - char *name; /* Nom donné au modificateur */ + sized_string_t name; /* Nom donné au modificateur */ GScanTokenModifier *found; /* Alternative présente */ available_modifier_t *last; /* Emplacement disponible */ - name = g_scan_token_modifier_get_name(modifier); + name.data = g_scan_token_modifier_get_name(modifier); + name.len = strlen(name.data); - found = find_scan_token_modifiers_for_name(name); + found = find_scan_token_modifiers_for_name(&name); result = (found == NULL); if (!result) - free(name); + exit_szstr(&name); else { @@ -137,6 +139,7 @@ bool load_all_known_scan_token_modifiers(void) if (result) result = REGISTER_SCAN_MODIFIER(g_scan_hex_modifier_new()); if (result) result = REGISTER_SCAN_MODIFIER(g_scan_plain_modifier_new()); if (result) result = REGISTER_SCAN_MODIFIER(g_scan_reverse_modifier_new()); + if (result) result = REGISTER_SCAN_MODIFIER(g_scan_xor_modifier_new()); return result; @@ -160,7 +163,10 @@ void unload_all_scan_token_modifiers(void) size_t i; /* Boucle de parcours */ for (i = 0; i < __modifiers_count; i++) + { + exit_szstr(&__modifiers[i].name); g_object_unref(G_OBJECT(__modifiers[i].instance)); + } if (__modifiers != NULL) free(__modifiers); @@ -180,7 +186,7 @@ void unload_all_scan_token_modifiers(void) * * ******************************************************************************/ -GScanTokenModifier *find_scan_token_modifiers_for_name(const char *name) +GScanTokenModifier *find_scan_token_modifiers_for_name(const sized_string_t *name) { GScanTokenModifier *result; /* Instance à renvoyer */ size_t i; /* Boucle de parcours */ @@ -192,7 +198,10 @@ GScanTokenModifier *find_scan_token_modifiers_for_name(const char *name) { registered = __modifiers + i; - if (strcmp(registered->name, name) == 0) + if (registered->name.len != name->len) + continue; + + if (strncmp(registered->name.data, name->data, name->len) == 0) { result = registered->instance; g_object_ref(G_OBJECT(result)); diff --git a/src/analysis/scan/core.h b/src/analysis/scan/core.h index 86a47da..8a18a75 100644 --- a/src/analysis/scan/core.h +++ b/src/analysis/scan/core.h @@ -40,7 +40,7 @@ bool load_all_known_scan_token_modifiers(void); void unload_all_scan_token_modifiers(void); /* Fournit le modificateur correspondant à un nom. */ -GScanTokenModifier *find_scan_token_modifiers_for_name(const char *); +GScanTokenModifier *find_scan_token_modifiers_for_name(const sized_string_t *); /* Inscrit les principales fonctions dans l'espace racine. */ bool populate_main_scan_namespace(GScanNamespace *); diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y index 741b394..c63dda7 100644 --- a/src/analysis/scan/grammar.y +++ b/src/analysis/scan/grammar.y @@ -40,6 +40,7 @@ typedef void *yyscan_t; #include "exprs/setcounter.h" #include "exprs/relational.h" #include "exprs/strop.h" +#include "patterns/customizer.h" #include "patterns/modifier.h" #include "patterns/modifiers/list.h" #include "patterns/tokens/hex.h" @@ -80,6 +81,7 @@ typedef void *yyscan_t; GSearchPattern *pattern; /* Nouveau motif à considérer */ GScanTokenModifier *modifier; /* Modificateur pour texte */ + modifier_arg_t mod_arg; /* Argument pour modificateur */ ScanPlainNodeFlags str_flags; /* Fanions pour texte */ @@ -255,6 +257,8 @@ YY_DECL; %type chained_modifiers %type mod_stage %type modifier +%type modifier_args +%type modifier_arg %type str_flags @@ -512,9 +516,9 @@ YY_DECL; { $$ = $1; } - | chained_modifiers + | "(" chained_modifiers ")" { - $$ = $1; + $$ = $2; } ; @@ -550,7 +554,7 @@ YY_DECL; modifier : NAME { - $$ = find_scan_token_modifiers_for_name($1.data); + $$ = find_scan_token_modifiers_for_name(&$1); if ($$ == NULL) { char *_msg; @@ -567,9 +571,71 @@ YY_DECL; YYERROR; } } - | "(" chained_modifiers ")" + | NAME "(" modifier_args ")" { - $$ = $2; + GScanTokenModifier *_mod; + bool _status; + + $$ = $3; + + _mod = find_scan_token_modifiers_for_name(&$1); + if (_mod == NULL) + { + char *_msg; + int _ret; + + _ret = asprintf(&_msg, _("Unknown modifier: \"%.*s\""), (int)$1.len, $1.data); + + if (_ret != -1) + { + raise_error(_msg); + free(_msg); + } + + g_object_unref(G_OBJECT($$)); + + YYERROR; + } + + _status = g_scan_token_customizer_attach_modifier(G_SCAN_TOKEN_CUSTOMIZER($$), _mod); + if (!_status) + { + char *_msg; + int _ret; + + _ret = asprintf(&_msg, + _("Unsupported argument for modifier: \"%.*s\""), + (int)$1.len, $1.data); + if (_ret != -1) + { + raise_error(_msg); + free(_msg); + } + + g_object_unref(G_OBJECT($$)); + + YYERROR; + } + + } + ; + + + modifier_args : modifier_arg + { + $$ = g_scan_token_customizer_new(&$1); + } + | modifier_args "," modifier_arg + { + $$ = $1; + g_scan_token_customizer_add_extra_arg(G_SCAN_TOKEN_CUSTOMIZER($$), &$3); + } + ; + + modifier_arg : PLAIN_TEXT + { + $$.type = MAT_STRING; + $$.value.string = $1; } ; diff --git a/src/analysis/scan/patterns/Makefile.am b/src/analysis/scan/patterns/Makefile.am index c3d0994..c520321 100644 --- a/src/analysis/scan/patterns/Makefile.am +++ b/src/analysis/scan/patterns/Makefile.am @@ -5,6 +5,9 @@ noinst_LTLIBRARIES = libanalysisscanpatterns.la libanalysisscanpatterns_la_SOURCES = \ backend-int.h \ backend.h backend.c \ + customizer-int.h \ + customizer.h customizer.c \ + modarg.h \ modifier-int.h \ modifier.h modifier.c \ token-int.h \ diff --git a/src/analysis/scan/patterns/customizer-int.h b/src/analysis/scan/patterns/customizer-int.h new file mode 100644 index 0000000..9d49ab6 --- /dev/null +++ b/src/analysis/scan/patterns/customizer-int.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * customizer-int.h - prototypes internes pour la modification paramétrée d'une séquence d'octets + * + * 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 . + */ + + +#ifndef _ANALYSIS_SCAN_CUSTOMIZER_INT_H +#define _ANALYSIS_SCAN_CUSTOMIZER_INT_H + + +#include "customizer.h" +#include "modifier-int.h" + + + +/* Encadrement de transformation paramétrée d'une séquence d'octets (instance) */ +struct _GScanTokenCustomizer +{ + GScanTokenModifier parent; /* A laisser en premier */ + + GScanTokenModifier *effective; /* Modificateur effectif */ + + modifier_arg_t *args; /* Paramètres de transformation*/ + size_t count; /* Quantité de ces paramètres */ + +}; + +/* Encadrement de transformation paramétrée d'une séquence d'octets (classe) */ +struct _GScanTokenCustomizerClass +{ + GScanTokenModifierClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un encadrement de transformation de motifs. */ +bool g_scan_token_customizer_create(GScanTokenCustomizer *, const modifier_arg_t *); + + + +#endif /* _ANALYSIS_SCAN_CUSTOMIZER_INT_H */ diff --git a/src/analysis/scan/patterns/customizer.c b/src/analysis/scan/patterns/customizer.c new file mode 100644 index 0000000..59065aa --- /dev/null +++ b/src/analysis/scan/patterns/customizer.c @@ -0,0 +1,374 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * customizer.c - modification paramétrée d'une séquence d'octets + * + * 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 . + */ + + +#include "customizer.h" + + +#include + + +#include "customizer-int.h" + + + +/* --------------------- TRANSFORMATION PERSONNALISEE DE MOTIFS --------------------- */ + + +/* Initialise la classe des transformations paramétrée. */ +static void g_scan_token_customizer_class_init(GScanTokenCustomizerClass *); + +/* Initialise une instance de transformation paramétrée. */ +static void g_scan_token_customizer_init(GScanTokenCustomizer *); + +/* Supprime toutes les références externes. */ +static void g_scan_token_customizer_dispose(GScanTokenCustomizer *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_token_customizer_finalize(GScanTokenCustomizer *); + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_token_customizer_get_name(const GScanTokenCustomizer *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_token_customizer_transform(const GScanTokenCustomizer *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSFORMATION PERSONNALISEE DE MOTIFS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transformation personnalisée d'une séquence d'octets. */ +G_DEFINE_TYPE(GScanTokenCustomizer, g_scan_token_customizer, G_TYPE_SCAN_TOKEN_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transformations paramétrée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_token_customizer_class_init(GScanTokenCustomizerClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_token_customizer_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_token_customizer_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_token_customizer_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_token_customizer_transform; + +} + + +/****************************************************************************** +* * +* Paramètres : customizer = instance à initialiser. * +* * +* Description : Initialise une instance de transformation paramétrée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_token_customizer_init(GScanTokenCustomizer *customizer) +{ + customizer->effective = NULL; + + customizer->args = NULL; + customizer->count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : customizer = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_token_customizer_dispose(GScanTokenCustomizer *customizer) +{ + g_clear_object(&customizer->effective); + + G_OBJECT_CLASS(g_scan_token_customizer_parent_class)->dispose(G_OBJECT(customizer)); + +} + + +/****************************************************************************** +* * +* Paramètres : customizer = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_token_customizer_finalize(GScanTokenCustomizer *customizer) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < customizer->count; i++) + exit_mod_arg(&customizer->args[i]); + + if (customizer->args != NULL) + free(customizer->args); + + G_OBJECT_CLASS(g_scan_token_customizer_parent_class)->finalize(G_OBJECT(customizer)); + +} + + +/****************************************************************************** +* * +* Paramètres : arg = premier argument pour personnaliser l'opération. * +* * +* Description : Construit un encadrement de transformation de motifs. * +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_token_customizer_new(const modifier_arg_t *arg) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_TOKEN_CUSTOMIZER, NULL); + + if (!g_scan_token_customizer_create(G_SCAN_TOKEN_CUSTOMIZER(result), arg)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : customizer = encadrement de motif à initialiser pleinement. * +* arg = premier argument pour personnaliser l'opération.* +* * +* Description : Met en place un encadrement de transformation de motifs. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_token_customizer_create(GScanTokenCustomizer *customizer, const modifier_arg_t *arg) +{ + g_scan_token_customizer_add_extra_arg(customizer, arg); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : customizer = encadrement de motif à compléter. * +* arg = nouvel argument pour personnaliser l'opération. * +* * +* Description : Ajoute un argument à l'encadrement de transformation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_scan_token_customizer_add_extra_arg(GScanTokenCustomizer *customizer, const modifier_arg_t *arg) +{ + customizer->args = realloc(customizer->args, ++customizer->count * sizeof(modifier_arg_t)); + + copy_mod_arg(&customizer->args[customizer->count - 1], arg); + +} + + +/****************************************************************************** +* * +* Paramètres : customizer = encadrement de motif à compléter. * +* modifier = modificateur de motifs à employer en sous-main. * +* * +* Description : Définit le transformateur effectif pour les motifs. * +* * +* Retour : true si le motificateur accepte les arguments courants. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_token_customizer_attach_modifier(GScanTokenCustomizer *customizer, GScanTokenModifier *modifier) +{ + bool result; /* Validation à retourner */ + size_t i; /* Boucle de parcours */ + + result = true; + + for (i = 0; i < customizer->count && result; i++) + result = g_scan_token_modifier_can_handle_arg(modifier, &customizer->args[i]); + + if (!result) goto exit; + + customizer->effective = modifier; + g_object_ref(G_OBJECT(modifier)); + + exit: + + 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_token_customizer_get_name(const GScanTokenCustomizer *modifier) +{ + char *result; /* Désignation à retourner */ + + if (modifier->effective == NULL) + result = NULL; + + else + result = g_scan_token_modifier_get_name(modifier->effective); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquence 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_token_customizer_transform(const GScanTokenCustomizer *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) +{ + bool result; /* Bilan d'opération à renvoyer*/ + size_t i; /* Boucle de parcours #1 */ + sized_binary_t *extra; /* Motifs supplémentaires */ + size_t extra_count; /* Quantité de ces motifs */ + sized_binary_t *new; /* Nouvel emplacement libre */ + size_t k; /* Boucle de parcours #2 */ + + *dest = NULL; + *dcount = 0; + + for (i = 0; i < modifier->count; i++) + { + result = g_scan_token_modifier_transform_with_arg(modifier->effective, + src, scount, + &modifier->args[i], + &extra, &extra_count); + if (!result) goto exit; + + new = (*dest) + *dcount; + + *dcount += extra_count; + *dest = realloc(*dest, *dcount * sizeof(sized_binary_t)); + + for (k = 0; k < extra_count; k++, new++) + copy_szstr(*new, extra[k]); + + free(extra); + + } + + exit: + + if (!result) + { + for (i = 0; i < *dcount; i++) + exit_szstr(dest[i]); + + if (*dest != NULL) + free(*dest); + + *dest = NULL; + *dcount = 0; + + } + + return result; + +} diff --git a/src/analysis/scan/patterns/customizer.h b/src/analysis/scan/patterns/customizer.h new file mode 100644 index 0000000..845d9ff --- /dev/null +++ b/src/analysis/scan/patterns/customizer.h @@ -0,0 +1,65 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * customizer.h - prototypes pour la modification paramétrée d'une séquence d'octets + * + * 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 . + */ + + +#ifndef _ANALYSIS_SCAN_CUSTOMIZER_H +#define _ANALYSIS_SCAN_CUSTOMIZER_H + + +#include +#include + + +#include "modifier.h" + + + +#define G_TYPE_SCAN_TOKEN_CUSTOMIZER g_scan_token_customizer_get_type() +#define G_SCAN_TOKEN_CUSTOMIZER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_TOKEN_CUSTOMIZER, GScanTokenCustomizer)) +#define G_IS_SCAN_TOKEN_CUSTOMIZER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_TOKEN_CUSTOMIZER)) +#define G_SCAN_TOKEN_CUSTOMIZER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_TOKEN_CUSTOMIZER, GScanTokenCustomizerClass)) +#define G_IS_SCAN_TOKEN_CUSTOMIZER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_TOKEN_CUSTOMIZER)) +#define G_SCAN_TOKEN_CUSTOMIZER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_TOKEN_CUSTOMIZER, GScanTokenCustomizerClass)) + + +/* Encadrement de transformation paramétrée d'une séquence d'octets (instance) */ +typedef struct _GScanTokenCustomizer GScanTokenCustomizer; + +/* Encadrement de transformation paramétrée d'une séquence d'octets (classe) */ +typedef struct _GScanTokenCustomizerClass GScanTokenCustomizerClass; + + +/* Indique le type défini pour une transformation personnalisée d'une séquence d'octets. */ +GType g_scan_token_customizer_get_type(void); + +/* Construit un encadrement de transformation de motifs. */ +GScanTokenModifier *g_scan_token_customizer_new(const modifier_arg_t *); + +/* Ajoute un argument à l'encadrement de transformation. */ +void g_scan_token_customizer_add_extra_arg(GScanTokenCustomizer *, const modifier_arg_t *); + +/* Définit le transformateur effectif pour les motifs. */ +bool g_scan_token_customizer_attach_modifier(GScanTokenCustomizer *, GScanTokenModifier *); + + + +#endif /* _ANALYSIS_SCAN_CUSTOMIZER_H */ diff --git a/src/analysis/scan/patterns/modarg.h b/src/analysis/scan/patterns/modarg.h new file mode 100644 index 0000000..d96e137 --- /dev/null +++ b/src/analysis/scan/patterns/modarg.h @@ -0,0 +1,91 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * modarg.h - prototypes pour la conservation d'arguments pour modificateurs + * + * 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 . + */ + + +#ifndef _ANALYSIS_SCAN_MODARG_H +#define _ANALYSIS_SCAN_MODARG_H + + +#include + + +#include "../../../common/szstr.h" + + + +/* Types d'arguments pris en charge */ +typedef enum _ModifierArgType +{ + MAT_BOOLEAN, /* Valeur booléenne */ + MAT_SIGNED_INTEGER, /* Nombre entier 64 bits #1 */ + MAT_UNSIGNED_INTEGER, /* Nombre entier 64 bits #2 */ + MAT_STRING, /* Chaîne de caractères */ + MAT_RANGE, /* Séquence d'entiers */ + +} ModifierArgType; + +/* Argument pour modificateur de motif */ +typedef struct _modifier_arg_t +{ + ModifierArgType type; /* Type de valeur portée */ + + union + { + bool boolean; /* Valeur booléenne */ + long long s_integer; /* Valeur entière 64 bits */ + unsigned long long u_integer; /* Valeur entière 64 bits */ + sized_string_t string; /* Chaîne de caractères */ + + struct + { + long long start; /* Point de départ */ + long long end; /* Point d'arrivée */ + + } range; + + } value; + +} modifier_arg_t; + + +#define exit_mod_arg(a) \ + do \ + { \ + if ((a)->type == MAT_STRING) \ + exit_szstr(&(a)->value.string); \ + } \ + while (0) + +#define copy_mod_arg(d, s) \ + do \ + { \ + (d)->type = (s)->type; \ + if ((s)->type == MAT_STRING) \ + szstrdup(&(d)->value.string, &(s)->value.string); \ + else \ + *(d) = *(s); \ + } \ + while (0) + + + +#endif /* _ANALYSIS_SCAN_MODARG_H */ diff --git a/src/analysis/scan/patterns/modifier-int.h b/src/analysis/scan/patterns/modifier-int.h index 246c139..e1de2d8 100644 --- a/src/analysis/scan/patterns/modifier-int.h +++ b/src/analysis/scan/patterns/modifier-int.h @@ -33,7 +33,13 @@ typedef char * (* get_scan_modifier_name_fc) (const GScanTokenModifier *); /* Transforme une séquence d'octets pour motif de recherche. */ -typedef bool (* transform_scan_token_fc) (const GScanTokenModifier *, const sized_binary_t *, sized_binary_t **, size_t *); +typedef bool (* transform_scan_token_fc) (const GScanTokenModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Détermine si un argument est bien toléré par un modificateur. */ +typedef bool (* can_token_modifier_handle_arg) (const GScanTokenModifier *, const modifier_arg_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +typedef bool (* transform_scan_token_with_fc) (const GScanTokenModifier *, const sized_binary_t *, size_t, const modifier_arg_t *, sized_binary_t **, size_t *); /* Transformation d'une séquence d'octets en une ou plusieurs autres formes (instance) */ @@ -51,6 +57,8 @@ struct _GScanTokenModifierClass get_scan_modifier_name_fc get_name; /* Fourniture du nom d'appel */ transform_scan_token_fc transform; /* Opération de transformation */ + can_token_modifier_handle_arg can_handle; /* Support d'argument donné */ + transform_scan_token_with_fc transform_with; /* Opération encadrée */ }; diff --git a/src/analysis/scan/patterns/modifier.c b/src/analysis/scan/patterns/modifier.c index 77d8bfd..4f041b1 100644 --- a/src/analysis/scan/patterns/modifier.c +++ b/src/analysis/scan/patterns/modifier.c @@ -156,8 +156,9 @@ char *g_scan_token_modifier_get_name(const GScanTokenModifier *modifier) * * * Paramètres : modifier = modificateur à solliciter. * * src = séquence d'octets à traiter. * +* scount = quantité de ces séquences. * * dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * -* count = quantité de ces séquences. * +* dcount = quantité de ces séquences. * * * * Description : Transforme une séquence d'octets pour motif de recherche. * * * @@ -167,14 +168,83 @@ char *g_scan_token_modifier_get_name(const GScanTokenModifier *modifier) * * ******************************************************************************/ -bool g_scan_token_modifier_transform(const GScanTokenModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count) +bool g_scan_token_modifier_transform(const GScanTokenModifier *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) { bool result; /* Bilan d'opération à renvoyer*/ GScanTokenModifierClass *class; /* Classe à activer */ class = G_SCAN_TOKEN_MODIFIER_GET_CLASS(modifier); - result = class->transform(modifier, src, dest, count); + result = class->transform(modifier, src, scount, dest, dcount); + + 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 : - * +* * +******************************************************************************/ + +bool g_scan_token_modifier_can_handle_arg(const GScanTokenModifier *modifier, const modifier_arg_t *arg) +{ + bool result; /* Bilan d'opération à renvoyer*/ + GScanTokenModifierClass *class; /* Classe à activer */ + + class = G_SCAN_TOKEN_MODIFIER_GET_CLASS(modifier); + + if (class->can_handle == NULL) + result = false; + else + result = class->can_handle(modifier, arg); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquence 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 : - * +* * +******************************************************************************/ + +bool g_scan_token_modifier_transform_with_arg(const GScanTokenModifier *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*/ + GScanTokenModifierClass *class; /* Classe à activer */ + + result = false; + + if (!g_scan_token_modifier_can_handle_arg(modifier, arg)) + goto exit; + + class = G_SCAN_TOKEN_MODIFIER_GET_CLASS(modifier); + + if (class->transform_with != NULL) + result = class->transform_with(modifier, src, scount, arg, dest, dcount); + + exit: return result; diff --git a/src/analysis/scan/patterns/modifier.h b/src/analysis/scan/patterns/modifier.h index a195ca8..ce2589a 100644 --- a/src/analysis/scan/patterns/modifier.h +++ b/src/analysis/scan/patterns/modifier.h @@ -29,6 +29,8 @@ #include + +#include "modarg.h" #include "../../../common/szstr.h" @@ -55,7 +57,13 @@ GType g_scan_token_modifier_get_type(void); char *g_scan_token_modifier_get_name(const GScanTokenModifier *); /* Transforme une séquence d'octets pour motif de recherche. */ -bool g_scan_token_modifier_transform(const GScanTokenModifier *, const sized_binary_t *, sized_binary_t **, size_t *); +bool g_scan_token_modifier_transform(const GScanTokenModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); + +/* Détermine si un argument est bien toléré par un modificateur. */ +bool g_scan_token_modifier_can_handle_arg(const GScanTokenModifier *, const modifier_arg_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +bool g_scan_token_modifier_transform_with_arg(const GScanTokenModifier *, const sized_binary_t *, size_t, const modifier_arg_t *, sized_binary_t **, size_t *); diff --git a/src/analysis/scan/patterns/modifiers/Makefile.am b/src/analysis/scan/patterns/modifiers/Makefile.am index fe5263c..f66393e 100644 --- a/src/analysis/scan/patterns/modifiers/Makefile.am +++ b/src/analysis/scan/patterns/modifiers/Makefile.am @@ -7,7 +7,8 @@ libanalysisscanpatternsmodifiers_la_SOURCES = \ list-int.h \ list.h list.c \ plain.h plain.c \ - rev.h rev.c + rev.h rev.c \ + xor.h xor.c libanalysisscanpatternsmodifiers_la_CFLAGS = $(LIBGOBJ_CFLAGS) diff --git a/src/analysis/scan/patterns/modifiers/hex.c b/src/analysis/scan/patterns/modifiers/hex.c index cf1583c..da992df 100644 --- a/src/analysis/scan/patterns/modifiers/hex.c +++ b/src/analysis/scan/patterns/modifiers/hex.c @@ -56,7 +56,7 @@ static void g_scan_hex_modifier_finalize(GScanHexModifier *); static char *g_scan_hex_modifier_get_name(const GScanHexModifier *); /* Transforme une séquence d'octets pour motif de recherche. */ -static bool g_scan_hex_modifier_transform(const GScanHexModifier *, const sized_binary_t *, sized_binary_t **, size_t *); +static bool g_scan_hex_modifier_transform(const GScanHexModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); @@ -212,8 +212,9 @@ static char *g_scan_hex_modifier_get_name(const GScanHexModifier *modifier) * * * Paramètres : modifier = modificateur à solliciter. * * src = séquence d'octets à traiter. * +* scount = quantité de ces séquences. * * dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * -* count = quantité de ces séquences. * +* dcount = quantité de ces séquences. * * * * Description : Transforme une séquence d'octets pour motif de recherche. * * * @@ -223,28 +224,36 @@ static char *g_scan_hex_modifier_get_name(const GScanHexModifier *modifier) * * ******************************************************************************/ -static bool g_scan_hex_modifier_transform(const GScanHexModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count) +static bool g_scan_hex_modifier_transform(const GScanHexModifier *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 */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* SOurce courante */ + size_t k; /* Boucle de parcours #2 */ static char *alphabet = "0123456789abcdef"; result = true; - *dest = malloc(1 * sizeof(sized_binary_t)); - *count = 1; + *dcount = scount; + *dest = malloc(*dcount * sizeof(sized_binary_t)); binary = &(*dest)[0]; - binary->len = src->len * 2; - binary->data = malloc(binary->len); - - for (i = 0; i < src->len; i++) + for (i = 0; i < scount; i++, binary++) { - binary->data[i * 2 + 0] = alphabet[src->data[i] >> 4]; - binary->data[i * 2 + 1] = alphabet[src->data[i] & 0xf]; + _src = src + i; + + binary->len = _src->len * 2; + binary->data = malloc(binary->len); + + for (k = 0; k < _src->len; k++) + { + binary->data[k * 2 + 0] = alphabet[_src->data[k] >> 4]; + binary->data[k * 2 + 1] = alphabet[_src->data[k] & 0xf]; + } + } return result; diff --git a/src/analysis/scan/patterns/modifiers/list.c b/src/analysis/scan/patterns/modifiers/list.c index 141fa54..5bf0faa 100644 --- a/src/analysis/scan/patterns/modifiers/list.c +++ b/src/analysis/scan/patterns/modifiers/list.c @@ -56,7 +56,7 @@ static void g_scan_modifier_list_finalize(GScanModifierList *); static char *g_scan_modifier_list_get_name(const GScanModifierList *); /* Transforme une séquence d'octets pour motif de recherche. */ -static bool g_scan_modifier_list_transform(const GScanModifierList *, const sized_binary_t *, sized_binary_t **, size_t *); +static bool g_scan_modifier_list_transform(const GScanModifierList *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); @@ -345,8 +345,9 @@ static char *g_scan_modifier_list_get_name(const GScanModifierList *modifier) * * * Paramètres : modifier = modificateur à solliciter. * * src = séquence d'octets à traiter. * +* scount = quantité de ces séquences. * * dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * -* count = quantité de ces séquences. * +* dcount = quantité de ces séquences. * * * * Description : Transforme une séquence d'octets pour motif de recherche. * * * @@ -356,7 +357,7 @@ static char *g_scan_modifier_list_get_name(const GScanModifierList *modifier) * * ******************************************************************************/ -static bool g_scan_modifier_list_transform(const GScanModifierList *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count) +static bool g_scan_modifier_list_transform(const GScanModifierList *modifier, const sized_binary_t *src, size_t scount, sized_binary_t **dest, size_t *dcount) { bool result; /* Bilan d'opération à renvoyer*/ size_t i; /* Boucle de parcours #1 */ @@ -366,17 +367,17 @@ static bool g_scan_modifier_list_transform(const GScanModifierList *modifier, co size_t k; /* Boucle de parcours #2 */ *dest = NULL; - *count = 0; + *dcount = 0; for (i = 0; i < modifier->count; i++) { - result = g_scan_token_modifier_transform(modifier->modifiers[i], src, &extra, &extra_count); + result = g_scan_token_modifier_transform(modifier->modifiers[i], src, scount, &extra, &extra_count); if (!result) goto exit; - new = (*dest) + *count; + new = (*dest) + *dcount; - *count += extra_count; - *dest = realloc(*dest, *count * sizeof(sized_binary_t)); + *dcount += extra_count; + *dest = realloc(*dest, *dcount * sizeof(sized_binary_t)); for (k = 0; k < extra_count; k++, new++) copy_szstr(*new, extra[k]); @@ -389,14 +390,14 @@ static bool g_scan_modifier_list_transform(const GScanModifierList *modifier, co if (!result) { - for (i = 0; i < *count; i++) + for (i = 0; i < *dcount; i++) exit_szstr(dest[i]); if (*dest != NULL) free(*dest); *dest = NULL; - *count = 0; + *dcount = 0; } diff --git a/src/analysis/scan/patterns/modifiers/plain.c b/src/analysis/scan/patterns/modifiers/plain.c index 5837d46..485bb23 100644 --- a/src/analysis/scan/patterns/modifiers/plain.c +++ b/src/analysis/scan/patterns/modifiers/plain.c @@ -56,7 +56,7 @@ static void g_scan_plain_modifier_finalize(GScanPlainModifier *); static char *g_scan_plain_modifier_get_name(const GScanPlainModifier *); /* Transforme une séquence d'octets pour motif de recherche. */ -static bool g_scan_plain_modifier_transform(const GScanPlainModifier *, const sized_binary_t *, sized_binary_t **, size_t *); +static bool g_scan_plain_modifier_transform(const GScanPlainModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); @@ -212,8 +212,9 @@ static char *g_scan_plain_modifier_get_name(const GScanPlainModifier *modifier) * * * Paramètres : modifier = modificateur à solliciter. * * src = séquence d'octets à traiter. * +* scount = quantité de ces séquences. * * dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * -* count = quantité de ces séquences. * +* dcount = quantité de ces séquences. * * * * Description : Transforme une séquence d'octets pour motif de recherche. * * * @@ -223,22 +224,30 @@ static char *g_scan_plain_modifier_get_name(const GScanPlainModifier *modifier) * * ******************************************************************************/ -static bool g_scan_plain_modifier_transform(const GScanPlainModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count) +static bool g_scan_plain_modifier_transform(const GScanPlainModifier *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 */ + const sized_binary_t *_src; /* SOurce courante */ result = true; - *dest = malloc(1 * sizeof(sized_binary_t)); - *count = 1; + *dcount = scount; + *dest = malloc(*dcount * sizeof(sized_binary_t)); binary = &(*dest)[0]; - binary->len = src->len; - binary->data = malloc(binary->len); + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; - memcpy(binary->data, src->data, src->len); + binary->len = _src->len; + binary->data = malloc(binary->len); + + memcpy(binary->data, _src->data, _src->len); + + } return result; diff --git a/src/analysis/scan/patterns/modifiers/rev.c b/src/analysis/scan/patterns/modifiers/rev.c index d22b549..8b931bd 100644 --- a/src/analysis/scan/patterns/modifiers/rev.c +++ b/src/analysis/scan/patterns/modifiers/rev.c @@ -56,7 +56,7 @@ static void g_scan_reverse_modifier_finalize(GScanReverseModifier *); static char *g_scan_reverse_modifier_get_name(const GScanReverseModifier *); /* Transforme une séquence d'octets pour motif de recherche. */ -static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *, const sized_binary_t *, sized_binary_t **, size_t *); +static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *, const sized_binary_t *, size_t, sized_binary_t **, size_t *); @@ -212,8 +212,9 @@ static char *g_scan_reverse_modifier_get_name(const GScanReverseModifier *modifi * * * Paramètres : modifier = modificateur à solliciter. * * src = séquence d'octets à traiter. * +* scount = quantité de ces séquences. * * dest = nouvelle(s) séquence(s) d'octets obtenue(s) [OUT] * -* count = quantité de ces séquences. * +* dcount = quantité de ces séquences. * * * * Description : Transforme une séquence d'octets pour motif de recherche. * * * @@ -223,24 +224,32 @@ static char *g_scan_reverse_modifier_get_name(const GScanReverseModifier *modifi * * ******************************************************************************/ -static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *modifier, const sized_binary_t *src, sized_binary_t **dest, size_t *count) +static bool g_scan_reverse_modifier_transform(const GScanReverseModifier *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 */ + size_t i; /* Boucle de parcours #1 */ + const sized_binary_t *_src; /* SOurce courante */ + size_t k; /* Boucle de parcours #2 */ result = true; - *dest = malloc(1 * sizeof(sized_binary_t)); - *count = 1; + *dcount = scount; + *dest = malloc(*dcount * sizeof(sized_binary_t)); binary = &(*dest)[0]; - binary->len = src->len; - binary->data = malloc(binary->len); + for (i = 0; i < scount; i++, binary++) + { + _src = src + i; - for (i = 0; i < src->len; i++) - binary->data[src->len - i - 1] = src->data[i]; + binary->len = _src->len; + binary->data = malloc(binary->len); + + for (k = 0; k < _src->len; k++) + binary->data[_src->len - k - 1] = _src->data[k]; + + } return result; diff --git a/src/analysis/scan/patterns/modifiers/xor.c b/src/analysis/scan/patterns/modifiers/xor.c new file mode 100644 index 0000000..65194ab --- /dev/null +++ b/src/analysis/scan/patterns/modifiers/xor.c @@ -0,0 +1,395 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * xor.c - transormation via opération XOR + * + * 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 . + */ + + +#include "xor.h" + + +#include +#include +#include +#include + + +#include "../modifier-int.h" + + + +/* ----------------------- RECHERCHE D'UN MOTIF DE TEXTE BRUT ----------------------- */ + + +/* Initialise la classe des transmissions via opération XOR. */ +static void g_scan_xor_modifier_class_init(GScanXorModifierClass *klass); + +/* Initialise une instance de transmission via opération XOR. */ +static void g_scan_xor_modifier_init(GScanXorModifier *); + +/* Supprime toutes les références externes. */ +static void g_scan_xor_modifier_dispose(GScanXorModifier *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_xor_modifier_finalize(GScanXorModifier *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit le nom d'appel d'un modificateur pour motif. */ +static char *g_scan_xor_modifier_get_name(const GScanXorModifier *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_xor_modifier_transform(const GScanXorModifier *, 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_xor_modifier_can_handle_arg(const GScanXorModifier *, const modifier_arg_t *); + +/* Transforme une séquence d'octets pour motif de recherche. */ +static bool g_scan_xor_modifier_transform_with_arg(const GScanXorModifier *, const sized_binary_t *, size_t, const modifier_arg_t *, sized_binary_t **, size_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* RECHERCHE D'UN MOTIF DE TEXTE BRUT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une transormation via une opération XOR. */ +G_DEFINE_TYPE(GScanXorModifier, g_scan_xor_modifier, G_TYPE_SCAN_TOKEN_MODIFIER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des transmissions via opération XOR. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_xor_modifier_class_init(GScanXorModifierClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanTokenModifierClass *modifier; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_xor_modifier_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_xor_modifier_finalize; + + modifier = G_SCAN_TOKEN_MODIFIER_CLASS(klass); + + modifier->get_name = (get_scan_modifier_name_fc)g_scan_xor_modifier_get_name; + + modifier->transform = (transform_scan_token_fc)g_scan_xor_modifier_transform; + modifier->can_handle = (can_token_modifier_handle_arg)g_scan_xor_modifier_can_handle_arg; + modifier->transform_with = (transform_scan_token_with_fc)g_scan_xor_modifier_transform_with_arg; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance à initialiser. * +* * +* Description : Initialise une instance de transmission via opération XOR. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_xor_modifier_init(GScanXorModifier *modifier) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_xor_modifier_dispose(GScanXorModifier *modifier) +{ + G_OBJECT_CLASS(g_scan_xor_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_xor_modifier_finalize(GScanXorModifier *modifier) +{ + G_OBJECT_CLASS(g_scan_xor_modifier_parent_class)->finalize(G_OBJECT(modifier)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Construit un modificateur livrant des octets traités par XOR.* +* * +* Retour : Mécanisme mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanTokenModifier *g_scan_xor_modifier_new(void) +{ + GScanTokenModifier *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_XOR_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_xor_modifier_get_name(const GScanXorModifier *modifier) +{ + char *result; /* Désignation à retourner */ + + result = strdup("xor"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquence 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_xor_modifier_transform(const GScanXorModifier *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 */ + long long x; /* Boucle de parcours #2 */ + size_t k; /* Boucle de parcours #3 */ + + result = true; + + *dcount = scount * 256; + *dest = malloc(*dcount * sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++) + { + _src = src + i; + + for (x = 0; x <= 0xff; x++, binary++) + { + binary->len = _src->len; + binary->data = malloc(binary->len); + + for (k = 0; k < _src->len; k++) + binary->data[k] = _src->data[k] ^ x; + + } + + } + + 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_xor_modifier_can_handle_arg(const GScanXorModifier *modifier, const modifier_arg_t *arg) +{ + bool result; /* Bilan d'opération à renvoyer*/ + + switch (arg->type) + { + case MAT_UNSIGNED_INTEGER: + result = (arg->value.u_integer <= UINT8_MAX); + break; + + case MAT_RANGE: + result = (INT8_MIN <= arg->value.range.start && arg->value.range.end <= INT8_MAX); + break; + + default: + result = false; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : modifier = modificateur à solliciter. * +* src = séquence 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_xor_modifier_transform_with_arg(const GScanXorModifier *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 */ + long long x; /* Boucle de parcours #2 */ + size_t k; /* Boucle de parcours #3 */ + + result = true; + + switch (arg->type) + { + case MAT_UNSIGNED_INTEGER: + + *dcount = scount; + *dest = malloc(*dcount * sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++) + { + _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] ^ arg->value.u_integer; + + } + + break; + + case MAT_RANGE: + + *dcount = scount * (arg->value.range.end - arg->value.range.start + 1); + *dest = malloc(*dcount * sizeof(sized_binary_t)); + + binary = &(*dest)[0]; + + for (i = 0; i < scount; i++) + { + _src = src + i; + + for (x = arg->value.range.start; x <= arg->value.range.end; x++, binary++) + { + binary->len = _src->len; + binary->data = malloc(binary->len); + + for (k = 0; k < _src->len; k++) + binary->data[k] = _src->data[k] ^ x; + + } + + } + + break; + + default: + assert(false); + result = false; + + } + + return result; + +} diff --git a/src/analysis/scan/patterns/modifiers/xor.h b/src/analysis/scan/patterns/modifiers/xor.h new file mode 100644 index 0000000..1a3e7e6 --- /dev/null +++ b/src/analysis/scan/patterns/modifiers/xor.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * xor.h - prototypes pour la transormation via opération XOR + * + * 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 . + */ + + +#ifndef _ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H +#define _ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H + + +#include + + +#include "../modifier.h" + + + +#define G_TYPE_SCAN_XOR_MODIFIER g_scan_xor_modifier_get_type() +#define G_SCAN_XOR_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_XOR_MODIFIER, GScanXorModifier)) +#define G_IS_SCAN_XOR_MODIFIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_XOR_MODIFIER)) +#define G_SCAN_XOR_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_XOR_MODIFIER, GScanXorModifierClass)) +#define G_IS_SCAN_XOR_MODIFIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_XOR_MODIFIER)) +#define G_SCAN_XOR_MODIFIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_XOR_MODIFIER, GScanXorModifierClass)) + + +/* Transormation via inversement d'une séquence d'octets (instance) */ +typedef GScanTokenModifier GScanXorModifier; + +/* Transormation via inversement d'une séquence d'octets (classe) */ +typedef GScanTokenModifierClass GScanXorModifierClass; + + +/* Indique le type défini pour une transormation via une opération XOR. */ +GType g_scan_xor_modifier_get_type(void); + +/* Construit un modificateur livrant des octets traités par XOR. */ +GScanTokenModifier *g_scan_xor_modifier_new(void); + + + +#endif /* _ANALYSIS_SCAN_PATTERNS_MODIFIERS_XOR_H */ diff --git a/src/analysis/scan/patterns/tokens/nodes/plain.c b/src/analysis/scan/patterns/tokens/nodes/plain.c index 5a7f976..5d89cf8 100644 --- a/src/analysis/scan/patterns/tokens/nodes/plain.c +++ b/src/analysis/scan/patterns/tokens/nodes/plain.c @@ -344,7 +344,7 @@ static bool g_scan_token_node_plain_enroll(GScanTokenNodePlain *node, GScanConte } else - result = g_scan_token_modifier_transform(node->modifier, &node->orig, &node->raw, &node->count); + result = g_scan_token_modifier_transform(node->modifier, &node->orig, 1, &node->raw, &node->count); if (!result) goto exit; diff --git a/src/analysis/scan/tokens.l b/src/analysis/scan/tokens.l index b284128..6633975 100644 --- a/src/analysis/scan/tokens.l +++ b/src/analysis/scan/tokens.l @@ -607,6 +607,32 @@ bytes_fuzzy_id [\*A-Za-z_][\*A-Za-z0-9_]* } + +[A-Za-z_][A-Za-z0-9_]* { + yylval->sized_cstring.data = yytext; + yylval->sized_cstring.len = yyleng; + return NAME; + } + + + "(" { return PAREN_O; } + + ")" { return PAREN_C; } + + "," { return COMMA; } + + +\"{str_not_escaped}+\" { + yylval->sized_cstring.data = yytext + 1; + yylval->sized_cstring.len = yyleng - 2; + + return PLAIN_TEXT; + } + + + + + %{ /* Définition de motif en hexadécimal */ %} "{" { @@ -885,9 +911,9 @@ bytes_fuzzy_id [\*A-Za-z_][\*A-Za-z0-9_]* "/" { return DIV; } "%" { return MOD; } -"(" { return PAREN_O; } -")" { return PAREN_C; } -"," { return COMMA; } +"(" { return PAREN_O; } +")" { return PAREN_C; } +"," { return COMMA; } "[" { return HOOK_O; } @@ -946,7 +972,7 @@ bytes_fuzzy_id [\*A-Za-z_][\*A-Za-z0-9_]* -[A-Za-z_][A-Za-z0-9_]* { +[A-Za-z_][A-Za-z0-9_]* { yylval->sized_cstring.data = yytext; yylval->sized_cstring.len = yyleng; return NAME; diff --git a/tests/analysis/scan/pyapi.py b/tests/analysis/scan/pyapi.py index 4b066f3..ff3143f 100644 --- a/tests/analysis/scan/pyapi.py +++ b/tests/analysis/scan/pyapi.py @@ -28,7 +28,7 @@ class TestRostPythonAPI(ChrysalideTestCase): e = ScanExpression() - def testBooleanComparison(self): + def __TODO__testBooleanComparison(self): """Compare custom scan expressions.""" class StrLenExpr(ScanExpression): @@ -88,3 +88,26 @@ class TestRostPythonAPI(ChrysalideTestCase): transformed = mod.transform(source) self.assertEqual(source[::-1], transformed[0]) + + + def testBytePatternModifiersAPI(self): + """Validate the API for pattern modifiers.""" + + mod = find_token_modifiers_for_name('plain') + self.assertIsNotNone(mod) + + source = [ b'ABC', b'01234' ] + transformed = mod.transform(source) + + self.assertEqual(len(source), len(transformed)) + self.assertEqual(source[0], transformed[0]) + self.assertEqual(source[1], transformed[1]) + + + mod = find_token_modifiers_for_name('xor') + self.assertIsNotNone(mod) + + source = [ b'ABC' ] + transformed = mod.transform(source, 0x20) + + self.assertEqual(transformed[0], b'abc') -- cgit v0.11.2-87-g4458