From 22c06200eca1ecda455a8d68bf73ec4fc458f59f Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 8 Oct 2023 01:27:24 +0200 Subject: Create some glue between ROST and Kaitai. --- configure.ac | 2 + plugins/kaitai/Makefile.am | 4 +- plugins/kaitai/core.c | 4 +- plugins/kaitai/python/Makefile.am | 5 +- plugins/kaitai/python/module.c | 3 + plugins/kaitai/python/rost/Makefile.am | 14 + plugins/kaitai/python/rost/module.c | 115 +++++++ plugins/kaitai/python/rost/module.h | 41 +++ plugins/kaitai/python/rost/trigger.c | 236 ++++++++++++++ plugins/kaitai/python/rost/trigger.h | 45 +++ plugins/kaitai/rost/Makefile.am | 18 ++ plugins/kaitai/rost/browser-int.h | 58 ++++ plugins/kaitai/rost/browser.c | 474 +++++++++++++++++++++++++++++ plugins/kaitai/rost/browser.h | 58 ++++ plugins/kaitai/rost/core.c | 66 ++++ plugins/kaitai/rost/core.h | 37 +++ plugins/kaitai/rost/space-int.h | 55 ++++ plugins/kaitai/rost/space.c | 240 +++++++++++++++ plugins/kaitai/rost/space.h | 59 ++++ plugins/kaitai/rost/trigger-int.h | 59 ++++ plugins/kaitai/rost/trigger.c | 320 +++++++++++++++++++ plugins/kaitai/rost/trigger.h | 58 ++++ plugins/pychrysalide/analysis/scan/space.c | 2 +- src/analysis/scan/exprs/Makefile.am | 2 + src/analysis/scan/exprs/call.c | 2 +- src/analysis/scan/exprs/extract-int.h | 57 ++++ src/analysis/scan/exprs/extract.c | 396 ++++++++++++++++++++++++ src/analysis/scan/exprs/extract.h | 56 ++++ src/analysis/scan/grammar.y | 139 +++++---- src/analysis/scan/item-int.h | 5 + src/analysis/scan/item.c | 33 ++ src/analysis/scan/item.h | 3 + src/analysis/scan/space.c | 1 - tests/plugins/kaitai/__init__.py | 0 tests/plugins/kaitai/rost.py | 170 +++++++++++ 35 files changed, 2766 insertions(+), 71 deletions(-) create mode 100644 plugins/kaitai/python/rost/Makefile.am create mode 100644 plugins/kaitai/python/rost/module.c create mode 100644 plugins/kaitai/python/rost/module.h create mode 100644 plugins/kaitai/python/rost/trigger.c create mode 100644 plugins/kaitai/python/rost/trigger.h create mode 100644 plugins/kaitai/rost/Makefile.am create mode 100644 plugins/kaitai/rost/browser-int.h create mode 100644 plugins/kaitai/rost/browser.c create mode 100644 plugins/kaitai/rost/browser.h create mode 100644 plugins/kaitai/rost/core.c create mode 100644 plugins/kaitai/rost/core.h create mode 100644 plugins/kaitai/rost/space-int.h create mode 100644 plugins/kaitai/rost/space.c create mode 100644 plugins/kaitai/rost/space.h create mode 100644 plugins/kaitai/rost/trigger-int.h create mode 100644 plugins/kaitai/rost/trigger.c create mode 100644 plugins/kaitai/rost/trigger.h create mode 100644 src/analysis/scan/exprs/extract-int.h create mode 100644 src/analysis/scan/exprs/extract.c create mode 100644 src/analysis/scan/exprs/extract.h create mode 100644 tests/plugins/kaitai/__init__.py create mode 100644 tests/plugins/kaitai/rost.py diff --git a/configure.ac b/configure.ac index 7673a96..3ecd8de 100644 --- a/configure.ac +++ b/configure.ac @@ -680,9 +680,11 @@ AC_CONFIG_FILES([Makefile plugins/kaitai/Makefile plugins/kaitai/parsers/Makefile plugins/kaitai/records/Makefile + plugins/kaitai/rost/Makefile plugins/kaitai/python/Makefile plugins/kaitai/python/parsers/Makefile plugins/kaitai/python/records/Makefile + plugins/kaitai/python/rost/Makefile plugins/libcsem/Makefile plugins/lnxsyscalls/Makefile plugins/mobicore/Makefile diff --git a/plugins/kaitai/Makefile.am b/plugins/kaitai/Makefile.am index cbc0f25..6c612ba 100644 --- a/plugins/kaitai/Makefile.am +++ b/plugins/kaitai/Makefile.am @@ -67,6 +67,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 +89,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/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/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 + + +#include +#include + + +#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 + + + +/* 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 +#include + + +#include +#include +#include +#include + + +#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 +#include + + + +/* 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/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 . + */ + + +#ifndef PLUGINS_KAITAI_ROST_BROWSER_INT_H +#define PLUGINS_KAITAI_ROST_BROWSER_INT_H + + +#include + + +#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..075c5ff --- /dev/null +++ b/plugins/kaitai/rost/browser.c @@ -0,0 +1,474 @@ + +/* 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 . + */ + + +#include "browser.h" + + +#include +#include + + +#include + + +#include "browser-int.h" +#include "../records/item.h" +#include "../records/list.h" +#include "../records/value.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_ITEM(item->record)) + result = g_record_item_get_value(G_RECORD_ITEM(item->record), &value); + + else if (G_IS_RECORD_VALUE(item->record)) + result = g_record_value_compute_and_aggregate_value(G_RECORD_VALUE(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 . + */ + + +#ifndef PLUGINS_KAITAI_ROST_BROWSER_H +#define PLUGINS_KAITAI_ROST_BROWSER_H + + +#include + + +#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 . + */ + + +#include "core.h" + + +#include + + +#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 . + */ + + +#ifndef _PLUGINS_KAITAI_ROST_CORE_H +#define _PLUGINS_KAITAI_ROST_CORE_H + + +#include + + + +/* 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 . + */ + + +#ifndef _PLUGINS_KAITAI_ROST_SPACE_INT_H +#define _PLUGINS_KAITAI_ROST_SPACE_INT_H + + +#include "space.h" + + +#include + + + +/* 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..ed24562 --- /dev/null +++ b/plugins/kaitai/rost/space.c @@ -0,0 +1,240 @@ + +/* 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 . + */ + + +#include "space.h" + + +#include + + +#include "space-int.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 */ + + 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) + printf("NEED external def!!!!\n"); + + 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 . + */ + + +#ifndef _PLUGINS_KAITAI_ROST_SPACE_H +#define _PLUGINS_KAITAI_ROST_SPACE_H + + +#include +#include + + +#include + + + +#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 . + */ + + +#ifndef _PLUGINS_KAITAI_ROST_TRIGGER_INT_H +#define _PLUGINS_KAITAI_ROST_TRIGGER_INT_H + + +#include + + +#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..64e6fe4 --- /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 . + */ + + +#include "trigger.h" + + +#include + + +#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 : - * +* * +******************************************************************************/ + +GKaitaiTrigger *g_kaitai_trigger_new(GKaitaiStruct *kstruct) +{ + GKaitaiTrigger *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_KAITAI_TRIGGER, NULL); + + if (!g_kaitai_trigger_create(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..3de2e8d --- /dev/null +++ b/plugins/kaitai/rost/trigger.h @@ -0,0 +1,58 @@ + +/* 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 . + */ + + +#ifndef PLUGINS_KAITAI_ROST_TRIGGER_H +#define PLUGINS_KAITAI_ROST_TRIGGER_H + + +#include + + +#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. */ +GKaitaiTrigger *g_kaitai_trigger_new(GKaitaiStruct *); + + + +#endif /* PLUGINS_KAITAI_ROST_TRIGGER_H */ diff --git a/plugins/pychrysalide/analysis/scan/space.c b/plugins/pychrysalide/analysis/scan/space.c index c901cd9..6ea87b8 100644 --- a/plugins/pychrysalide/analysis/scan/space.c +++ b/plugins/pychrysalide/analysis/scan/space.c @@ -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/src/analysis/scan/exprs/Makefile.am b/src/analysis/scan/exprs/Makefile.am index a0b2f3d..37f4133 100644 --- a/src/analysis/scan/exprs/Makefile.am +++ b/src/analysis/scan/exprs/Makefile.am @@ -11,6 +11,8 @@ libanalysisscanexprs_la_SOURCES = \ call.h call.c \ counter-int.h \ counter.h counter.c \ + extract-int.h \ + extract.h extract.c \ handler-int.h \ handler.h handler.c \ intersect-int.h \ diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c index 74e0cba..e335933 100644 --- a/src/analysis/scan/exprs/call.c +++ b/src/analysis/scan/exprs/call.c @@ -271,9 +271,9 @@ static ScanReductionState g_scan_pending_call_reduce(const GScanPendingCall *exp ScanReductionState state; /* Etat synthétisé d'un élément*/ size_t k; /* Boucle de parcours #2 */ GScanExpression **new_args; /* Nouvelle séquence d'args. */ - GScanExpression *new_next; /* Nouvelle version du suivant */ GObject *final; /* Expression ou élément ? */ bool valid; /* Validité de l'élément */ + GScanExpression *new_next; /* Nouvelle version du suivant */ access = G_SCAN_NAMED_ACCESS(expr); diff --git a/src/analysis/scan/exprs/extract-int.h b/src/analysis/scan/exprs/extract-int.h new file mode 100644 index 0000000..562e537 --- /dev/null +++ b/src/analysis/scan/exprs/extract-int.h @@ -0,0 +1,57 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract-int.h - prototypes internes pour l'organisation d'une extraction d'un élément d'une série interne + * + * 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_EXPRS_EXTRACT_INT_H +#define _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H + + +#include "extract.h" + + +#include "access-int.h" + + + +/* Extraction d'un élément donné au sein d'une série interne (instance) */ +struct _GScanPendingExtraction +{ + GScanNamedAccess parent; /* A laisser en premier */ + + GScanExpression *index; /* Arguments d'appel fournis */ + +}; + +/* Extraction d'un élément donné au sein d'une série interne (classe) */ +struct _GScanPendingExtractionClass +{ + GScanNamedAccessClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une expression d'extraction d'élément interne. */ +bool g_scan_pending_extraction_create(GScanPendingExtraction *, const sized_string_t *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_INT_H */ diff --git a/src/analysis/scan/exprs/extract.c b/src/analysis/scan/exprs/extract.c new file mode 100644 index 0000000..b140ed9 --- /dev/null +++ b/src/analysis/scan/exprs/extract.c @@ -0,0 +1,396 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract.c - organisation d'une extraction d'un élément d'une série interne + * + * 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 "extract.h" + + +#include +#include + + +#include "extract-int.h" +#include "../../../core/global.h" + + + +/* --------------------- INTRODUCTION D'UNE NOUVELLE EXPRESSION --------------------- */ + + +/* Initialise la classe des extractions d'éléments internes. */ +static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *); + +/* Initialise une instance d'extraction d'élément interne. */ +static void g_scan_pending_extraction_init(GScanPendingExtraction *); + +/* Supprime toutes les références externes. */ +static void g_scan_pending_extraction_dispose(GScanPendingExtraction *); + +/* Procède à la libération totale de la mémoire. */ +static void g_scan_pending_extraction_finalize(GScanPendingExtraction *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Réduit une expression à une forme plus simple. */ +static ScanReductionState g_scan_pending_extraction_reduce(const GScanPendingExtraction *, GScanContext *, GScanScope *, GScanExpression **); + +/* Reproduit un accès en place dans une nouvelle instance. */ +static void g_scan_pending_extraction_copy(GScanPendingExtraction *, const GScanPendingExtraction *); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTRODUCTION D'UNE NOUVELLE EXPRESSION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une extraction d'élément de série interne. */ +G_DEFINE_TYPE(GScanPendingExtraction, g_scan_pending_extraction, G_TYPE_SCAN_NAMED_ACCESS); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des extractions d'éléments internes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_class_init(GScanPendingExtractionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GScanExpressionClass *expr; /* Version de classe parente */ + GScanNamedAccessClass *access; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_scan_pending_extraction_dispose; + object->finalize = (GObjectFinalizeFunc)g_scan_pending_extraction_finalize; + + expr = G_SCAN_EXPRESSION_CLASS(klass); + + expr->cmp_rich = (compare_expr_rich_fc)NULL; + expr->reduce = (reduce_expr_fc)g_scan_pending_extraction_reduce; + + access = G_SCAN_NAMED_ACCESS_CLASS(klass); + + access->copy = (copy_scan_access_fc)g_scan_pending_extraction_copy; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance à initialiser. * +* * +* Description : Initialise une instance d'extraction d'élément interne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_init(GScanPendingExtraction *extract) +{ + extract->index = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_dispose(GScanPendingExtraction *extract) +{ + g_clear_object(&extract->index); + + G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->dispose(G_OBJECT(extract)); + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_finalize(GScanPendingExtraction *extract) +{ + G_OBJECT_CLASS(g_scan_pending_extraction_parent_class)->finalize(G_OBJECT(extract)); + +} + + +/****************************************************************************** +* * +* Paramètres : target = désignation de l'objet d'appel à identifier. * +* index = indice de l'élément à extraire. * +* * +* Description : Organise l'extraction d'un élément d'une série interne. * +* * +* Retour : Fonction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GScanExpression *g_scan_pending_extraction_new(const sized_string_t *target, GScanExpression *index) +{ + GScanExpression *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_SCAN_PENDING_EXTRACTION, NULL); + + if (!g_scan_pending_extraction_create(G_SCAN_PENDING_EXTRACTION(result), target, index)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : extract = instance à initialiser pleinement. * +* target = désignation de l'objet d'appel à identifier. * +* index = indice de l'élément à extraire. * +* * +* Description : Met en place une expression d'extraction d'élément interne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_scan_pending_extraction_create(GScanPendingExtraction *extract, const sized_string_t *target, GScanExpression *index) +{ + bool result; /* Bilan à retourner */ + + result = g_scan_named_access_create(G_SCAN_NAMED_ACCESS(extract), target); + if (!result) goto exit; + + extract->index = index; + g_object_ref(G_OBJECT(index)); + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : expr = expression à 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 ScanReductionState g_scan_pending_extraction_reduce(const GScanPendingExtraction *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) +{ + ScanReductionState result; /* Etat synthétisé à retourner */ + GScanNamedAccess *access; /* Autre vision de l'expression*/ + GScanRegisteredItem *resolved; /* Cible concrète obtenue */ + GScanExpression *new; /* Nouvelle réduction obtenue */ + GObject *final; /* Expression ou élément ? */ + GScanExpression *new_next; /* Nouvelle version du suivant */ + + access = G_SCAN_NAMED_ACCESS(expr); + + resolved = _g_scan_named_access_prepare_reduction(access, ctx, scope); + + if (resolved == NULL) + result = SRS_UNRESOLVABLE; + + else + { + /* Actualisation nécessaire des arguments ? */ + + result = g_scan_expression_reduce(expr->index, ctx, scope, &new); + + /* Suite des traitements */ + + if (result == SRS_WAIT_FOR_SCAN) + { + /** + * Si changement il y a eu... + */ + if (new != expr->index) + { + *out = g_scan_pending_extraction_new(NULL, new); + + /** + * Fonctionnement équivalent de : + * g_scan_named_access_set_base(G_SCAN_NAMED_ACCESS(*out), resolved); + */ + G_SCAN_NAMED_ACCESS(*out)->resolved = resolved; + g_object_ref(G_OBJECT(resolved)); + + if (G_SCAN_NAMED_ACCESS(expr)->next != NULL) + g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS(*out), G_SCAN_NAMED_ACCESS(expr)->next); + + } + + } + + else if (result == SRS_REDUCED) + { + final = g_scan_registered_item_extract_at(resolved, new, ctx, scope); + + if (final != NULL) + { + /** + * Si le produit de l'appel à la fonction est une expression d'évaluation + * classique, alors ce produit constitue la réduction finale de la chaîne. + * + * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne. + */ + if (!G_IS_SCAN_REGISTERED_ITEM(final)) + { + if (access->next != NULL) + result = SRS_UNRESOLVABLE; + + else + { + *out = G_SCAN_EXPRESSION(final); + g_object_ref(G_OBJECT(final)); + + result = SRS_REDUCED; + + } + + } + else + { + if (access->next != NULL) + { + new_next = g_scan_named_access_duplicate(access->next, G_SCAN_REGISTERED_ITEM(final)); + + result = g_scan_expression_reduce(new_next, ctx, scope, out); + + g_object_unref(G_OBJECT(new_next)); + + } + + /** + * Le cas ci-après est typique de l'extension Kaitai : field[n] + * renvoie vers une instance GScanRegisteredItem (GKaitaiBrowser). + * + * Il n'y a donc pas d'expression en jeu, et l'élément est le dernier + * de la liste. + */ + else + { + if (g_scan_registered_item_reduce(G_SCAN_REGISTERED_ITEM(final), ctx, scope, out)) + result = SRS_REDUCED; + else + result = SRS_UNRESOLVABLE; + + } + + } + + } + + else + result = SRS_UNRESOLVABLE; + + g_clear_object(&final); + + } + + /* Libération locale des arguments reconstruits */ + + g_clear_object(&new); + + g_object_unref(G_OBJECT(resolved)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * +* * +* Description : Reproduit un accès en place dans une nouvelle instance. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_scan_pending_extraction_copy(GScanPendingExtraction *dest, const GScanPendingExtraction *src) +{ + GScanNamedAccessClass *class; /* Classe parente à solliciter */ + + class = G_SCAN_NAMED_ACCESS_CLASS(g_scan_pending_extraction_parent_class); + + class->copy(G_SCAN_NAMED_ACCESS(dest), G_SCAN_NAMED_ACCESS(src)); + + dest->index = src->index; + g_object_ref(G_OBJECT(src->index)); + +} diff --git a/src/analysis/scan/exprs/extract.h b/src/analysis/scan/exprs/extract.h new file mode 100644 index 0000000..8ed1cfa --- /dev/null +++ b/src/analysis/scan/exprs/extract.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * extract.h - prototypes pour l'organisation d'une extraction d'un élément d'une série interne + * + * 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_EXPRS_EXTRACT_H +#define _ANALYSIS_SCAN_EXPRS_EXTRACT_H + + +#include "../expr.h" +#include "../../../common/szstr.h" + + + +#define G_TYPE_SCAN_PENDING_EXTRACTION g_scan_pending_extraction_get_type() +#define G_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtraction)) +#define G_IS_SCAN_PENDING_EXTRACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SCAN_PENDING_EXTRACTION)) +#define G_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass)) +#define G_IS_SCAN_PENDING_EXTRACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SCAN_PENDING_EXTRACTION)) +#define G_SCAN_PENDING_EXTRACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SCAN_PENDING_EXTRACTION, GScanPendingExtractionClass)) + + +/* Extraction d'un élément donné au sein d'une série interne (instance) */ +typedef struct _GScanPendingExtraction GScanPendingExtraction; + +/* Extraction d'un élément donné au sein d'une série interne (classe) */ +typedef struct _GScanPendingExtractionClass GScanPendingExtractionClass; + + +/* Indique le type défini pour une extraction d'élément de série interne. */ +GType g_scan_pending_extraction_get_type(void); + +/* Organise l'extraction d'un élément d'une série interne. */ +GScanExpression *g_scan_pending_extraction_new(const sized_string_t *, GScanExpression *); + + + +#endif /* _ANALYSIS_SCAN_EXPRS_EXTRACT_H */ diff --git a/src/analysis/scan/grammar.y b/src/analysis/scan/grammar.y index c63dda7..2863e21 100644 --- a/src/analysis/scan/grammar.y +++ b/src/analysis/scan/grammar.y @@ -31,6 +31,7 @@ typedef void *yyscan_t; #include "exprs/arithmetic.h" #include "exprs/call.h" #include "exprs/counter.h" +#include "exprs/extract.h" #include "exprs/handler.h" #include "exprs/intersect.h" #include "exprs/item.h" @@ -274,7 +275,8 @@ YY_DECL; %type cexpression _cexpression %type literal -%type item_chain +%type chain_items +%type chain_item %type call_args %type logical_expr %type relational_expr @@ -285,9 +287,9 @@ YY_DECL; %type pattern_set_items %type set %type set_items -%type set_access %type intersection %type pattern_handler +%type _pattern_handler @@ -942,14 +944,13 @@ YY_DECL; cexpression : _cexpression { $$ = $1; if ($$ == NULL) { printf("ERROR !!!\n"); YYERROR; } } _cexpression : literal { $$ = $1; } - | item_chain { $$ = $1; } + | chain_items { $$ = $1; } | logical_expr { $$ = $1; } | relational_expr { $$ = $1; } | string_op { $$ = $1; } | arithm_expr { $$ = $1; } | set_match_counter { $$ = $1; } | set { $$ = $1; } - | set_access { $$ = $1; } | intersection { $$ = $1; } | pattern_handler { $$ = $1; } | "(" cexpression ")" { $$ = $2; } @@ -993,42 +994,48 @@ YY_DECL; { $$ = g_scan_literal_expression_new(LVT_STRING, &$1); } + | STRING "[" cexpression "]" + { + GScanExpression *__src; + __src = g_scan_literal_expression_new(LVT_STRING, &$1); + $$ = g_scan_set_item_new(__src, $3); + g_object_unref(G_OBJECT(__src)); + g_object_unref(G_OBJECT($3)); + } ; - item_chain : NAME { $$ = g_scan_named_access_new(&$1); } - | NAME "(" ")" { $$ = g_scan_pending_call_new(&$1, NULL, 0); } - | NAME "(" call_args ")" + + chain_items : chain_item { - size_t __i; - $$ = g_scan_pending_call_new(&$1, $3.args, $3.count); - for (__i = 0; __i < $3.count; __i++) - g_object_unref(G_OBJECT($3.args[__i])); - free($3.args); + $$ = $1; } - | item_chain "." NAME + | chain_items "." chain_item { - GScanExpression *__next; - __next = g_scan_named_access_new(&$3); - g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); + g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS($3)); $$ = $1; } - | item_chain "." NAME "(" ")" + ; + + chain_item : NAME + { + $$ = g_scan_named_access_new(&$1); + } + | NAME "(" ")" { - GScanExpression *__next; - __next = g_scan_pending_call_new(&$3, NULL, 0); - g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); - $$ = $1; + $$ = g_scan_pending_call_new(&$1, NULL, 0); } - | item_chain "." NAME "(" call_args ")" + | NAME "(" call_args ")" { - GScanExpression *__next; size_t __i; - __next = g_scan_pending_call_new(&$3, $5.args, $5.count); - for (__i = 0; __i < $5.count; __i++) - g_object_unref(G_OBJECT($5.args[__i])); - free($5.args); - g_scan_named_access_attach_next(G_SCAN_NAMED_ACCESS($1), G_SCAN_NAMED_ACCESS(__next)); - $$ = $1; + $$ = g_scan_pending_call_new(&$1, $3.args, $3.count); + for (__i = 0; __i < $3.count; __i++) + g_object_unref(G_OBJECT($3.args[__i])); + free($3.args); + } + | NAME "[" cexpression "]" + { + $$ = g_scan_pending_extraction_new(&$1, $3); + g_object_unref(G_OBJECT($3)); } ; @@ -1307,46 +1314,39 @@ relational_expr : cexpression "<" cexpression { $$ = g_scan_relational_operatio ; - set : "(" ")" - { - $$ = g_scan_generic_set_new(); - } - | "(" cexpression "," ")" - { - $$ = g_scan_generic_set_new(); - g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $2); - g_object_unref(G_OBJECT($2)); - } - | "(" set_items ")" - { - $$ = $2; - } - ; - - set_items : cexpression "," cexpression - { - $$ = g_scan_generic_set_new(); - g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $1); - g_object_unref(G_OBJECT($1)); - g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); - g_object_unref(G_OBJECT($3)); - } - | set_items "," cexpression - { - $$ = $1; - g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); - g_object_unref(G_OBJECT($3)); - } - ; + set : "(" ")" + { + $$ = g_scan_generic_set_new(); + } + | "(" cexpression "," ")" + { + $$ = g_scan_generic_set_new(); + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $2); + g_object_unref(G_OBJECT($2)); + } + | "(" set_items ")" + { + $$ = $2; + } + ; - set_access : cexpression "[" cexpression "]" + set_items : cexpression "," cexpression { - $$ = g_scan_set_item_new($1, $3); + $$ = g_scan_generic_set_new(); + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $1); g_object_unref(G_OBJECT($1)); + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); + g_object_unref(G_OBJECT($3)); + } + | set_items "," cexpression + { + $$ = $1; + g_scan_generic_set_add_item(G_SCAN_GENERIC_SET($$), $3); g_object_unref(G_OBJECT($3)); } ; + intersection : cexpression "in" cexpression { $$ = g_scan_sets_intersection_new($1, $3); @@ -1355,7 +1355,20 @@ relational_expr : cexpression "<" cexpression { $$ = g_scan_relational_operatio } ; - pattern_handler : BYTES_ID + + pattern_handler : _pattern_handler + { + $$ = $1; + } + | pattern_handler "[" cexpression "]" + { + $$ = g_scan_set_item_new($1, $3); + g_object_unref(G_OBJECT($1)); + g_object_unref(G_OBJECT($3)); + } + ; + + _pattern_handler : BYTES_ID { GSearchPattern *__pat; __pat = g_scan_rule_get_local_variable(*built_rule, $1.data); diff --git a/src/analysis/scan/item-int.h b/src/analysis/scan/item-int.h index 76431c9..a04b861 100644 --- a/src/analysis/scan/item-int.h +++ b/src/analysis/scan/item-int.h @@ -44,6 +44,9 @@ typedef bool (* reduce_registered_item_fc) (GScanRegisteredItem *, GScanContext /* Effectue un appel à une fonction enregistrée. */ typedef bool (* run_registered_item_call_fc) (GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); +/* Effectue une extraction d'élément à partir d'une série. */ +typedef GObject * (* extract_registered_item_at) (GScanRegisteredItem *, GScanExpression *, GScanContext *, GScanScope *); + /* Expression d'évaluation généraliste (instance) */ struct _GScanRegisteredItem @@ -58,9 +61,11 @@ struct _GScanRegisteredItemClass GObjectClass parent; /* A laisser en premier */ get_registered_item_name_fc get_name; /* Obtention du nom associé */ + resolve_registered_item_fc resolve; /* Opération de résolution */ reduce_registered_item_fc reduce; /* Opération de réduction */ run_registered_item_call_fc run_call; /* Appel à une fonction connue */ + extract_registered_item_at extract; /* Extraction d'un élément */ }; diff --git a/src/analysis/scan/item.c b/src/analysis/scan/item.c index 930a334..509ad28 100644 --- a/src/analysis/scan/item.c +++ b/src/analysis/scan/item.c @@ -290,3 +290,36 @@ bool g_scan_registered_item_run_call(GScanRegisteredItem *item, GScanExpression 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 : - * +* * +******************************************************************************/ + +GObject *g_scan_registered_item_extract_at(GScanRegisteredItem *item, GScanExpression *index, GScanContext *ctx, GScanScope *scope) +{ + GObject *result; /* Elément récupéré à renvoyer */ + GScanRegisteredItemClass *class; /* Classe à activer */ + + class = G_SCAN_REGISTERED_ITEM_GET_CLASS(item); + + if (class->extract == NULL) + result = NULL; + + else + result = class->extract(item, index, ctx, scope); + + return result; + +} diff --git a/src/analysis/scan/item.h b/src/analysis/scan/item.h index 904064e..a6c56c3 100644 --- a/src/analysis/scan/item.h +++ b/src/analysis/scan/item.h @@ -64,6 +64,9 @@ bool g_scan_registered_item_reduce(GScanRegisteredItem *, GScanContext *, GScanS /* Effectue un appel à une fonction enregistrée. */ bool g_scan_registered_item_run_call(GScanRegisteredItem *, GScanExpression **, size_t, GScanContext *, GScanScope *, GObject **); +/* Effectue une extraction d'élément à partir d'une série. */ +GObject *g_scan_registered_item_extract_at(GScanRegisteredItem *, GScanExpression *, GScanContext *, GScanScope *); + #endif /* _ANALYSIS_SCAN_ITEM_H */ diff --git a/src/analysis/scan/space.c b/src/analysis/scan/space.c index e4d5049..909b96d 100644 --- a/src/analysis/scan/space.c +++ b/src/analysis/scan/space.c @@ -24,7 +24,6 @@ #include "space.h" -#include #include diff --git a/tests/plugins/kaitai/__init__.py b/tests/plugins/kaitai/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/plugins/kaitai/rost.py b/tests/plugins/kaitai/rost.py new file mode 100644 index 0000000..1950222 --- /dev/null +++ b/tests/plugins/kaitai/rost.py @@ -0,0 +1,170 @@ +#!/usr/bin/python3-dbg +# -*- coding: utf-8 -*- + +import locale + +from chrysacase import ChrysalideTestCase +from pychrysalide.analysis.contents import MemoryContent +from pychrysalide.analysis.scan import ContentScanner +from pychrysalide.analysis.scan import ScanOptions +from pychrysalide.analysis.scan.patterns.backends import AcismBackend +from pychrysalide import core +from pychrysalide.plugins.kaitai.parsers import KaitaiStruct +from pychrysalide.plugins.kaitai.rost import KaitaiTrigger + + +class TestScansWithKaitai(ChrysalideTestCase): + """TestCase for ROST scan with the KaitaiStruct parsing.""" + + @classmethod + def setUpClass(cls): + + super(TestScansWithKaitai, cls).setUpClass() + + cls._options = ScanOptions() + cls._options.backend_for_data = AcismBackend + + + def ZZZtestSimpleKaitaiDefinitionForScanning(self): + """Rely on basic Kaitai simple definition for scanning.""" + + definitions = ''' +meta: + id: basic_test +seq: + - id: field0 + type: u1 +''' + + kstruct = KaitaiStruct(definitions) + + trigger = KaitaiTrigger(kstruct) + + root_ns = core.get_rost_root_namespace() + + ns = root_ns.resolve('kaitai') + ns.register_item(trigger) + + ns = ns.resolve('basic_test') + self.assertEqual(ns, trigger) + + cnt = MemoryContent(b'\x01\x02\x03') + + rule = ''' +rule testing { + + condition: + kaitai.basic_test.field0 == 1 + +} +''' + + scanner = ContentScanner(rule) + ctx = scanner.analyze(self._options, cnt) + + self.assertIsNotNone(ctx) + + self.assertFalse(ctx.has_match_for_rule('no_such_rule')) + + self.assertTrue(ctx.has_match_for_rule('testing')) + + + definitions = ''' +meta: + id: other_basic_test +seq: + - id: field0 + type: u1 + - id: field1 + type: u1 +''' + + kstruct = KaitaiStruct(definitions) + + trigger = KaitaiTrigger(kstruct) + + root_ns = core.get_rost_root_namespace() + + ns = root_ns.resolve('kaitai') + ns.register_item(trigger) + + ns = ns.resolve('other_basic_test') + self.assertEqual(ns, trigger) + + cnt = MemoryContent(b'\x01\x02\x03') + + rule = ''' +rule testing { + + condition: + kaitai.other_basic_test.field0 == 1 and kaitai.other_basic_test.field1 == 2 + +} +''' + + scanner = ContentScanner(rule) + ctx = scanner.analyze(self._options, cnt) + + self.assertIsNotNone(ctx) + + self.assertTrue(ctx.has_match_for_rule('testing')) + + + rule = ''' +rule testing { + + condition: + kaitai.other_basic_test.field0 == 1 and kaitai.other_basic_testXXXX.field1 == 2 + +} +''' + + scanner = ContentScanner(rule) + ctx = scanner.analyze(self._options, cnt) + + self.assertIsNotNone(ctx) + + self.assertFalse(ctx.has_match_for_rule('testing')) + + + def testKaitaiDefinitionWithListForScanning(self): + """Access list items from Kaitai definition when scanning with ROST.""" + + definitions = ''' +meta: + id: test_with_list +seq: + - id: field0 + type: u1 + repeat: eos +''' + + kstruct = KaitaiStruct(definitions) + + trigger = KaitaiTrigger(kstruct) + + root_ns = core.get_rost_root_namespace() + + ns = root_ns.resolve('kaitai') + ns.register_item(trigger) + + ns = ns.resolve('test_with_list') + self.assertEqual(ns, trigger) + + cnt = MemoryContent(b'\x01\x02\x03') + + rule = ''' +rule testing { + + condition: + kaitai.test_with_list.field0[0] == 1 and kaitai.test_with_list.field0[1] == 2 and kaitai.test_with_list.field0[2] == 3 + +} +''' + + scanner = ContentScanner(rule) + ctx = scanner.analyze(self._options, cnt) + + self.assertIsNotNone(ctx) + + self.assertTrue(ctx.has_match_for_rule('testing')) -- cgit v0.11.2-87-g4458