diff options
Diffstat (limited to 'plugins/pychrysalide/analysis')
| -rw-r--r-- | plugins/pychrysalide/analysis/Makefile.am | 17 | ||||
| -rw-r--r-- | plugins/pychrysalide/analysis/content.c | 832 | ||||
| -rw-r--r-- | plugins/pychrysalide/analysis/contents/encapsulated.c | 8 | ||||
| -rw-r--r-- | plugins/pychrysalide/analysis/contents/file.c | 2 | ||||
| -rw-r--r-- | plugins/pychrysalide/analysis/contents/memory.c | 2 | ||||
| -rw-r--r-- | plugins/pychrysalide/analysis/contents/restricted.c | 4 | ||||
| -rw-r--r-- | plugins/pychrysalide/analysis/module.c | 14 | 
7 files changed, 833 insertions, 46 deletions
diff --git a/plugins/pychrysalide/analysis/Makefile.am b/plugins/pychrysalide/analysis/Makefile.am index 43e8ed2..dea825c 100644 --- a/plugins/pychrysalide/analysis/Makefile.am +++ b/plugins/pychrysalide/analysis/Makefile.am @@ -1,5 +1,5 @@ -noinst_LTLIBRARIES = libpychrysaanalysis.la +noinst_LTLIBRARIES = libpychrysaanalysis4.la # libpychrysaanalysis.la  libpychrysaanalysis_la_SOURCES =			\  	binary.h binary.c						\ @@ -23,7 +23,17 @@ libpychrysaanalysis_la_LIBADD =				\  	storage/libpychrysaanalysisstorage.la	\  	types/libpychrysaanalysistypes.la -libpychrysaanalysis_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + +libpychrysaanalysis4_la_SOURCES =			\ +	content.h content.c						\ +	module.h module.c + +libpychrysaanalysis4_la_LIBADD =			\ +	contents/libpychrysaanalysiscontents.la + +libpychrysaanalysis4_la_CFLAGS = \ +    $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ +	$(TOOLKIT_CFLAGS) \  	-I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT @@ -32,4 +42,5 @@ devdir = $(includedir)/chrysalide/$(subdir)  dev_HEADERS = $(libpychrysaanalysis_la_SOURCES:%c=) -SUBDIRS = contents db disass scan storage types +#SUBDIRS = contents db disass scan storage types +SUBDIRS = contents diff --git a/plugins/pychrysalide/analysis/content.c b/plugins/pychrysalide/analysis/content.c index c30cdd8..dd9c1c1 100644 --- a/plugins/pychrysalide/analysis/content.c +++ b/plugins/pychrysalide/analysis/content.c @@ -35,13 +35,12 @@  #include <analysis/content-int.h> -#include <common/endianness.h> -#include "cattribs.h" -#include "constants.h" -#include "storage/serialize.h" +//#include "cattribs.h" +//#include "storage/serialize.h"  #include "../access.h" +#include "../constants.h"  #include "../helpers.h"  #include "../arch/vmpa.h" @@ -61,6 +60,21 @@ static int py_binary_content_init(PyObject *, PyObject *, PyObject *);  /* Fournit le nom associé au contenu binaire. */  static char *py_binary_content_describe_wrapper(const GBinContent *, bool); +/* Calcule une empreinte unique (SHA256) pour les données. */ +static void py_binary_content_compute_checksum_wrapper(const GBinContent *, GChecksum *); + +/* Détermine le nombre d'octets lisibles. */ +static phys_t py_binary_content_compute_size_wrapper(const GBinContent *); + +/* Détermine la position initiale d'un contenu. */ +static bool py_binary_content_compute_start_pos_wrapper(const GBinContent *, vmpa2t *); + +/* Détermine la position finale d'un contenu. */ +static bool py_binary_content_compute_end_pos_wrapper(const GBinContent *, vmpa2t *); + +/* Avance la tête de lecture d'une certaine quantité de données. */ +static bool py_binary_content_seek_wrapper(const GBinContent *, vmpa2t *, phys_t); +  /* Fournit une portion des données représentées. */  static bool py_binary_content_read_raw_wrapper(const GBinContent *, vmpa2t *, phys_t, bin_t *);; @@ -76,6 +90,12 @@ static bool py_binary_content_read_u32_wrapper(const GBinContent *, vmpa2t *, So  /* Lit un nombre non signé sur huit octets. */  static bool py_binary_content_read_u64_wrapper(const GBinContent *, vmpa2t *, SourceEndian, uint64_t *); +/* Lit un nombre non signé encodé au format LEB128. */ +static bool py_binary_content_read_uleb128_wrapper(const GBinContent *, vmpa2t *, uleb128_t *); + +/* Lit un nombre signé encodé au format LEB128. */ +static bool py_binary_content_read_leb128_wrapper(const GBinContent *, vmpa2t *, leb128_t *); +  /* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ @@ -84,6 +104,9 @@ static bool py_binary_content_read_u64_wrapper(const GBinContent *, vmpa2t *, So  /* Fournit le nom associé au contenu binaire. */  static PyObject *py_binary_content_describe(PyObject *, PyObject *); +/* Avance la tête de lecture d'une certaine quantité de données. */ +static PyObject *py_binary_content_seek(PyObject *, PyObject *); +  /* Fournit une portion des données représentées. */  static PyObject *py_binary_content_read_raw(PyObject *, PyObject *); @@ -99,11 +122,19 @@ static PyObject *py_binary_content_read_u32(PyObject *, PyObject *);  /* Lit un nombre non signé sur huit octets. */  static PyObject *py_binary_content_read_u64(PyObject *, PyObject *); +/* Lit un nombre non signé encodé au format LEB128. */ +static PyObject *py_binary_content_read_uleb128(PyObject *, PyObject *); + +/* Lit un nombre signé encodé au format LEB128. */ +static PyObject *py_binary_content_read_leb128(PyObject *, PyObject *); + +#if 0  /* Associe un ensemble d'attributs au contenu binaire. */  static int py_binary_content_set_attributes(PyObject *, PyObject *, void *);  /* Fournit l'ensemble des attributs associés à un contenu. */  static PyObject *py_binary_content_get_attributes(PyObject *, void *); +#endif  /* Donne l'origine d'un contenu binaire. */  static PyObject *py_binary_content_get_root(PyObject *, void *); @@ -147,12 +178,23 @@ static void py_binary_content_init_gclass(GBinContentClass *class, gpointer unus  {      class->describe = py_binary_content_describe_wrapper; +    class->compute_checksum = py_binary_content_compute_checksum_wrapper; + +    class->compute_size = py_binary_content_compute_size_wrapper; +    class->compute_start_pos = py_binary_content_compute_start_pos_wrapper; +    class->compute_end_pos = py_binary_content_compute_end_pos_wrapper; + +    class->seek = py_binary_content_seek_wrapper; +      class->read_raw = py_binary_content_read_raw_wrapper;      class->read_u8 = py_binary_content_read_u8_wrapper;      class->read_u16 = py_binary_content_read_u16_wrapper;      class->read_u32 = py_binary_content_read_u32_wrapper;      class->read_u64 = py_binary_content_read_u64_wrapper; +    class->read_uleb128 = py_binary_content_read_uleb128_wrapper; +    class->read_leb128 = py_binary_content_read_leb128_wrapper; +  } @@ -184,12 +226,19 @@ static int py_binary_content_init(PyObject *self, PyObject *args, PyObject *kwds      "\n"                                                                    \      "The following methods have to be defined for new implementations:\n"   \      "* pychrysalide.analysis.BinContent._describe();\n"                     \ +    "* pychrysalide.analysis.BinContent._compute_checksum();\n"             \ +    "* pychrysalide.analysis.BinContent._compute_size();\n"                 \ +    "* pychrysalide.analysis.BinContent._compute_start_pos();\n"            \ +    "* pychrysalide.analysis.BinContent._compute_end_pos();\n"              \ +    "* pychrysalide.analysis.BinContent._seek();\n"                         \      "* pychrysalide.analysis.BinContent._read_raw();\n"                     \      "* pychrysalide.analysis.BinContent._read_u4();\n"                      \      "* pychrysalide.analysis.BinContent._read_u8();\n"                      \      "* pychrysalide.analysis.BinContent._read_u16();\n"                     \      "* pychrysalide.analysis.BinContent._read_u32();\n"                     \ -    "* pychrysalide.analysis.BinContent._read_u64();\n" +    "* pychrysalide.analysis.BinContent._read_u64();\n"                     \ +    "* pychrysalide.analysis.BinContent._read_uleb128();\n"                 \ +    "* pychrysalide.analysis.BinContent._read_leb128();\n"      /* Initialisation d'un objet GLib */ @@ -276,6 +325,349 @@ static char *py_binary_content_describe_wrapper(const GBinContent *content, bool  /******************************************************************************  *                                                                             * +*  Paramètres  : content  = contenu binaire à venir lire.                     * +*                checksum = empreinte de zone mémoire à compléter.            * +*                                                                             * +*  Description : Calcule une empreinte unique (SHA256) pour les données.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void py_binary_content_compute_checksum_wrapper(const GBinContent *content, GChecksum *checksum) +{ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *pyret;                        /* Bilan de consultation       */ + +#define BINARY_CONTENT_COMPUTE_CHECKSUM_WRAPPER PYTHON_WRAPPER_DEF  \ +(                                                                   \ +    _compute_checksum, "$self, checksum",                           \ +    METH_VARARGS,                                                   \ +    "Abstract method used to build a fingerprint of the current"    \ +    " content.\n"                                                   \ +    "\n"                                                            \ +    "The *checksum* argument is a Glib.Checksum instance to update."\ +) + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(content)); + +    if (has_python_method(pyobj, "_compute_checksum")) +    { +        args = PyTuple_New(1); +        PyTuple_SetItem(args, 0, pyg_boxed_new(G_TYPE_CHECKSUM, checksum, FALSE, FALSE)); + +        pyret = run_python_method(pyobj, "_compute_checksum", args); + +        if (pyret != NULL) +        { +            assert(pyret == Py_None); + +            Py_DECREF(pyret); + +        } + +        Py_DECREF(args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : content = contenu binaire à venir lire.                      * +*                                                                             * +*  Description : Détermine le nombre d'octets lisibles.                       * +*                                                                             * +*  Retour      : Quantité représentée.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static phys_t py_binary_content_compute_size_wrapper(const GBinContent *content) +{ +    phys_t result;                          /* Quantité à remonter         */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    int ret;                                /* Validité d'une conversion   */ + +#define BINARY_CONTENT_COMPUTE_SIZE_WRAPPER PYTHON_WRAPPER_DEF          \ +(                                                                       \ +    _compute_size, "$self",                                             \ +    METH_NOARGS,                                                        \ +    "Abstract method used to provide the quantity of available bytes.\n"\ +    "\n"                                                                \ +    "The returned value should greater than 0."                         \ +) + +    result = 0; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(content)); + +    if (has_python_method(pyobj, "_compute_size")) +    { +        pyret = run_python_method(pyobj, "_compute_size", NULL); + +        if (pyret != NULL) +        { +            ret = PyLong_Check(pyret); + +            if (ret) +                result = PyLong_AsUnsignedLong(pyret); + +            Py_DECREF(pyret); + +        } + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : content = contenu binaire à venir lire.                      * +*                pos     = position initiale. [OUT]                           * +*                                                                             * +*  Description : Détermine la position initiale d'un contenu.                 * +*                                                                             * +*  Retour      : Validité finale de la position fournie.                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_binary_content_compute_start_pos_wrapper(const GBinContent *content, vmpa2t *pos) +{ +    bool result;                            /* Bilan à remonter            */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    vmpa2t *pypos;                          /* Position retournée          */ + +#define BINARY_CONTENT_COMPUTE_START_POS_WRAPPER PYTHON_WRAPPER_DEF \ +(                                                                   \ +    _compute_start_pos, "$self",                                    \ +    METH_NOARGS,                                                    \ +    "Abstract method computing the effective position at the"       \ +    " beginning of the binary content.\n"                           \ +    "\n"                                                            \ +    "The computed position has to get returned as a"                \ +    " pychrysalide.arch.vmpa instance."                             \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(content)); + +    if (has_python_method(pyobj, "_compute_start_pos")) +    { +        pyret = run_python_method(pyobj, "_compute_start_pos", NULL); + +        if (pyret != NULL) +        { +            pypos = get_internal_vmpa(pyret); + +            if (pypos != NULL) +            { +                copy_vmpa(pos, pypos); +                result = true; +            } + +            Py_DECREF(pyret); + +        } + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : content = contenu binaire à venir lire.                      * +*                pos     = position finale (exclusive). [OUT]                 * +*                                                                             * +*  Description : Détermine la position finale d'un contenu.                   * +*                                                                             * +*  Retour      : Validité finale de la position fournie.                      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_binary_content_compute_end_pos_wrapper(const GBinContent *content, vmpa2t *pos) +{ +    bool result;                            /* Bilan à remonter            */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    vmpa2t *pypos;                          /* Position retournée          */ + +#define BINARY_CONTENT_COMPUTE_END_POS_WRAPPER PYTHON_WRAPPER_DEF \ +(                                                                   \ +    _compute_end_pos, "$self",                                    \ +    METH_NOARGS,                                                    \ +    "Abstract method computing the effective position at the"       \ +    " beginning of the binary content.\n"                           \ +    "\n"                                                            \ +    "The computed position has to get returned as a"                \ +    " pychrysalide.arch.vmpa instance."                             \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(content)); + +    if (has_python_method(pyobj, "_compute_end_pos")) +    { +        pyret = run_python_method(pyobj, "_compute_end_pos", NULL); + +        if (pyret != NULL) +        { +            pypos = get_internal_vmpa(pyret); + +            if (pypos != NULL) +            { +                copy_vmpa(pos, pypos); +                result = true; +            } + +            Py_DECREF(pyret); + +        } + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : content = contenu binaire à venir lire.                      * +*                addr    = position de la tête de lecture.                    * +*                length  = quantité d'octets à provisionner.                  * +*                                                                             * +*  Description : Avance la tête de lecture d'une certaine quantité de données.* +*                                                                             * +*  Retour      : Bilan de l'opération : true en cas de succès, false sinon.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_binary_content_seek_wrapper(const GBinContent *content, vmpa2t *addr, phys_t length) +{ +    bool result;                            /* Bilan à remonter            */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *addr_obj;                     /* Position en version Python  */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    int ret;                                /* Validité d'une conversion   */ + +#define BINARY_CONTENT_SEEK_WRAPPER PYTHON_WRAPPER_DEF          \ +(                                                               \ +    _read_raw, "$self, addr, length",                           \ +    METH_VARARGS,                                               \ +    "Abstract method used to move a given location.\n"          \ +    "\n"                                                        \ +    "The *addr* argument is a pychrysalide.arch.vmpa object,"   \ +    " and *length* is the offset for the expected move.\n"      \ +    "\n"                                                        \ +    "The returned value provide the status of the operation:"   \ +    " *True* if *addr* has been update to a valid position,"    \ +    " *False* otherwise."                                       \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(content)); + +    if (has_python_method(pyobj, "_seek")) +    { +        addr_obj = build_from_internal_vmpa(addr); + +        args = PyTuple_New(2); +        PyTuple_SetItem(args, 0, addr_obj); +        PyTuple_SetItem(args, 1, PyLong_FromUnsignedLongLong(length)); + +        pyret = run_python_method(pyobj, "_seek", args); + +        if (pyret != NULL) +        { +            ret = PyBool_Check(pyret); + +            if (ret) +            { +                /* Bilan à retenir */ + +                result = (pyret == Py_True); + +                /* Avancement de la tête de lecture */ + +                if (result) +                    copy_vmpa(addr, get_internal_vmpa(addr_obj)); + +            } + +            Py_DECREF(pyret); + +        } + +        Py_DECREF(args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : content = contenu binaire à venir lire.                      *  *                addr    = position de la tête de lecture.                    *  *                length  = quantité d'octets à lire.                          * @@ -401,8 +793,9 @@ static bool py_binary_content_read_u8_wrapper(const GBinContent *content, vmpa2t      "Abstract method used to read an unsigned bytes from a given"       \      " position.\n"                                                      \      "\n"                                                                \ -    "The location of the data to read is a pychrysalide.arch.vmpa"      \ -    " instance.\n"                                                      \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument needs"  \ +    " to get updated in order to reflect the read progress.\n"          \      "\n"                                                                \      "The returned value is the read data or None is case of error."     \  ) @@ -492,8 +885,10 @@ static bool py_binary_content_read_u16_wrapper(const GBinContent *content, vmpa2      "Abstract method used to read two unsigned bytes from a given"      \      " position.\n"                                                      \      "\n"                                                                \ -    "The location of the data to read is a pychrysalide.arch.vmpa"      \ -    " instance. The endianness of the data can be provided using"       \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument needs"  \ +    " to get updated in order to reflect the read progress. The"        \ +    " endianness of the data can be provided using"                     \      " pychrysalide.analysis.BinContent.SourceEndian values.\n"          \      "\n"                                                                \      "The returned value is the read data or None is case of error."     \ @@ -508,8 +903,7 @@ static bool py_binary_content_read_u16_wrapper(const GBinContent *content, vmpa2      if (has_python_method(pyobj, "_read_u16"))      {          addr_obj = build_from_internal_vmpa(addr); -        endianness_obj = cast_with_constants_group_from_type(get_python_binary_content_type(), -                                                             "SourceEndian", endian); +        endianness_obj = cast_source_endian_to_python(endian);          args = PyTuple_New(2);          PyTuple_SetItem(args, 0, addr_obj); @@ -587,8 +981,10 @@ static bool py_binary_content_read_u32_wrapper(const GBinContent *content, vmpa2      "Abstract method used to read four unsigned bytes from a given"     \      " position.\n"                                                      \      "\n"                                                                \ -    "The location of the data to read is a pychrysalide.arch.vmpa"      \ -    " instance. The endianness of the data can be provided using"       \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument needs"  \ +    " to get updated in order to reflect the read progress. The"        \ +    " endianness of the data can be provided using"                     \      " pychrysalide.analysis.BinContent.SourceEndian values.\n"          \      "\n"                                                                \      "The returned value is the read data or None is case of error."     \ @@ -603,8 +999,7 @@ static bool py_binary_content_read_u32_wrapper(const GBinContent *content, vmpa2      if (has_python_method(pyobj, "_read_u32"))      {          addr_obj = build_from_internal_vmpa(addr); -        endianness_obj = cast_with_constants_group_from_type(get_python_binary_content_type(), -                                                             "SourceEndian", endian); +        endianness_obj = cast_source_endian_to_python(endian);          args = PyTuple_New(2);          PyTuple_SetItem(args, 0, addr_obj); @@ -682,8 +1077,10 @@ static bool py_binary_content_read_u64_wrapper(const GBinContent *content, vmpa2      "Abstract method used to read eight unsigned bytes from a given"    \      " position.\n"                                                      \      "\n"                                                                \ -    "The location of the data to read is a pychrysalide.arch.vmpa"      \ -    " instance. The endianness of the data can be provided using"       \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument needs"  \ +    " to get updated in order to reflect the read progress. The"        \ +    " endianness of the data can be provided using"                     \      " pychrysalide.analysis.BinContent.SourceEndian values.\n"          \      "\n"                                                                \      "The returned value is the read data or None is case of error."     \ @@ -698,8 +1095,7 @@ static bool py_binary_content_read_u64_wrapper(const GBinContent *content, vmpa2      if (has_python_method(pyobj, "_read_u64"))      {          addr_obj = build_from_internal_vmpa(addr); -        endianness_obj = cast_with_constants_group_from_type(get_python_binary_content_type(), -                                                             "SourceEndian", endian); +        endianness_obj = cast_source_endian_to_python(endian);          args = PyTuple_New(2);          PyTuple_SetItem(args, 0, addr_obj); @@ -744,6 +1140,186 @@ static bool py_binary_content_read_u64_wrapper(const GBinContent *content, vmpa2  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : content = contenu binaire à venir lire.                      * +*                addr    = position de la tête de lecture.                    * +*                val     = lieu d'enregistrement de la lecture. [OUT]         * +*                                                                             * +*  Description : Lit un nombre non signé encodé au format LEB128.             * +*                                                                             * +*  Retour      : Bilan de l'opération : true en cas de succès, false sinon.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_binary_content_read_uleb128_wrapper(const GBinContent *content, vmpa2t *addr, uleb128_t *val) +{ +    bool result;                            /* Bilan à remonter            */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *addr_obj;                     /* Position en version Python  */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    int ret;                                /* Validité d'une conversion   */ + +#define BINARY_CONTENT_READ_ULEB128_WRAPPER PYTHON_WRAPPER_DEF          \ +(                                                                       \ +    _read_uleb128, "$self, addr",                                       \ +    METH_VARARGS,                                                       \ +    "Abstract method used to read an unsigned LEB128-encoded number"    \ +    " from a given position.\n"                                         \ +    "\n"                                                                \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument needs"  \ +    " to get updated in order to reflect the read progress.\n"          \ +    "\n"                                                                \ +    "The returned value is the read data or None is case of error."     \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(content)); + +    if (has_python_method(pyobj, "_read_uleb128")) +    { +        addr_obj = build_from_internal_vmpa(addr); + +        args = PyTuple_New(1); +        PyTuple_SetItem(args, 0, addr_obj); + +        pyret = run_python_method(pyobj, "_read_uleb128", args); + +        if (pyret != NULL) +        { +            ret = PyLong_Check(pyret); + +            if (ret) +            { +                /* Avancement de la tête de lecture */ + +                copy_vmpa(addr, get_internal_vmpa(addr_obj)); + +                /* Récupération des données */ + +                *val = PyLong_AsUnsignedLongLong(pyret); + +                /* Bilan à retenir */ + +                result = true; + +            } + +            Py_DECREF(pyret); + +        } + +        Py_DECREF(args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : content = contenu binaire à venir lire.                      * +*                addr    = position de la tête de lecture.                    * +*                val     = lieu d'enregistrement de la lecture. [OUT]         * +*                                                                             * +*  Description : Lit un nombre signé encodé au format LEB128.                 * +*                                                                             * +*  Retour      : Bilan de l'opération : true en cas de succès, false sinon.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool py_binary_content_read_leb128_wrapper(const GBinContent *content, vmpa2t *addr, leb128_t *val) +{ +    bool result;                            /* Bilan à remonter            */ +    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */ +    PyObject *pyobj;                        /* Objet Python concerné       */ +    PyObject *addr_obj;                     /* Position en version Python  */ +    PyObject *args;                         /* Arguments pour l'appel      */ +    PyObject *pyret;                        /* Bilan de consultation       */ +    int ret;                                /* Validité d'une conversion   */ + +#define BINARY_CONTENT_READ_LEB128_WRAPPER PYTHON_WRAPPER_DEF           \ +(                                                                       \ +    _read_leb128, "$self, addr",                                        \ +    METH_VARARGS,                                                       \ +    "Abstract method used to read an unsigned LEB128-encoded number"    \ +    " from a given position.\n"                                         \ +    "\n"                                                                \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument needs"  \ +    " to get updated in order to reflect the read progress.\n"          \ +    "\n"                                                                \ +    "The returned value is the read data or None is case of error."     \ +) + +    result = false; + +    gstate = PyGILState_Ensure(); + +    pyobj = pygobject_new(G_OBJECT(content)); + +    if (has_python_method(pyobj, "_read_leb128")) +    { +        addr_obj = build_from_internal_vmpa(addr); + +        args = PyTuple_New(1); +        PyTuple_SetItem(args, 0, addr_obj); + +        pyret = run_python_method(pyobj, "_read_leb128", args); + +        if (pyret != NULL) +        { +            ret = PyLong_Check(pyret); + +            if (ret) +            { +                /* Avancement de la tête de lecture */ + +                copy_vmpa(addr, get_internal_vmpa(addr_obj)); + +                /* Récupération des données */ + +                *val = PyLong_AsLongLong(pyret); + +                /* Bilan à retenir */ + +                result = true; + +            } + +            Py_DECREF(pyret); + +        } + +        Py_DECREF(args); + +    } + +    Py_DECREF(pyobj); + +    PyGILState_Release(gstate); + +    return result; + +} + +  /* ---------------------------------------------------------------------------------- */  /*                           CONNEXION AVEC L'API DE PYTHON                           */ @@ -801,6 +1377,53 @@ static PyObject *py_binary_content_describe(PyObject *self, PyObject *args)  *  Paramètres  : self = contenu binaire à manipuler.                          *  *                args = non utilisé ici.                                      *  *                                                                             * +*  Description : Avance la tête de lecture d'une certaine quantité de données.* +*                                                                             * +*  Retour      : Bilan de l'opération : true en cas de succès, false sinon.   * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_binary_content_seek(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Instance à retourner        */ +    vmpa2t *addr;                           /* Position interne associée   */ +    unsigned long long length;              /* Quantité de données à lire  */ +    int ret;                                /* Bilan de lecture des args.  */ +    GBinContent *content;                   /* Version GLib du format      */ +    bool valid;                             /* Validité de la position     */ + +#define BINARY_CONTENT_SEEK_METHOD PYTHON_METHOD_DEF        \ +(                                                           \ +    seek, "$self, addr, length, /",                         \ +    METH_VARARGS, py_binary_content,                        \ +    "Move the current position into a new one.\n"           \ +    "\n"                                                    \ +) + +    ret = PyArg_ParseTuple(args, "O&K", convert_any_to_vmpa, &addr, &length); +    if (!ret) return NULL; + +    content = G_BIN_CONTENT(pygobject_get(self)); + +    valid = g_binary_content_seek(content, addr, length); + +    result = (valid ? Py_True : Py_False); +    Py_INCREF(result); + +    clean_vmpa_arg(addr); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = contenu binaire à manipuler.                          * +*                args = non utilisé ici.                                      * +*                                                                             *  *  Description : Fournit une portion des données représentées.                *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        * @@ -877,8 +1500,9 @@ static PyObject *py_binary_content_read_u8(PyObject *self, PyObject *args)      METH_VARARGS, py_binary_content,                                    \      "Read an unsigned byte from a given position."                      \      "\n"                                                                \ -    "The location of the data to read is a pychrysalide.arch.vmpa"      \ -    " instance.\n"                                                      \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument gets"   \ +    " updated in order to reflect the read progress.\n"                 \      "\n"                                                                \      "The returned value is the read data or None is case of error."     \  ) @@ -936,8 +1560,10 @@ static PyObject *py_binary_content_read_u16(PyObject *self, PyObject *args)      METH_VARARGS, py_binary_content,                                    \      "Read two unsigned bytes from a given position."                    \      "\n"                                                                \ -    "The location of the data to read is a pychrysalide.arch.vmpa"      \ -    " instance. The endianness of the data can be provided using"       \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument gets"   \ +    " updated in order to reflect the read progress. The endianness"    \ +    " of the data can be provided using"                                \      " pychrysalide.analysis.BinContent.SourceEndian values.\n"          \      "\n"                                                                \      "The returned value is the read data or None is case of error."     \ @@ -996,8 +1622,10 @@ static PyObject *py_binary_content_read_u32(PyObject *self, PyObject *args)      METH_VARARGS, py_binary_content,                                    \      "Read four unsigned bytes from a given position."                   \      "\n"                                                                \ -    "The location of the data to read is a pychrysalide.arch.vmpa"      \ -    " instance. The endianness of the data can be provided using"       \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument gets"   \ +    " updated in order to reflect the read progress. The endianness"    \ +    " of the data can be provided using"                                \      " pychrysalide.analysis.BinContent.SourceEndian values.\n"          \      "\n"                                                                \      "The returned value is the read data or None is case of error."     \ @@ -1026,6 +1654,7 @@ static PyObject *py_binary_content_read_u32(PyObject *self, PyObject *args)  } +  /******************************************************************************  *                                                                             *  *  Paramètres  : self = contenu binaire à manipuler.                          * @@ -1055,8 +1684,10 @@ static PyObject *py_binary_content_read_u64(PyObject *self, PyObject *args)      METH_VARARGS, py_binary_content,                                    \      "Read eight unsigned bytes from a given position.\n"                \      "\n"                                                                \ -    "The location of the data to read is a pychrysalide.arch.vmpa"      \ -    " instance. The endianness of the data can be provided using"       \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument gets"   \ +    " updated in order to reflect the read progress. The endianness"    \ +    " of the data can be provided using"                                \      " pychrysalide.analysis.BinContent.SourceEndian values.\n"          \      "\n"                                                                \      "The returned value is the read data or None is case of error."     \ @@ -1088,6 +1719,127 @@ static PyObject *py_binary_content_read_u64(PyObject *self, PyObject *args)  /******************************************************************************  *                                                                             * +*  Paramètres  : self = contenu binaire à manipuler.                          * +*                args = non utilisé ici.                                      * +*                                                                             * +*  Description : Lit un nombre non signé encodé au format LEB128.             * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_binary_content_read_uleb128(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Instance à retourner        */ +    vmpa2t *addr;                           /* Position interne associée   */ +    int ret;                                /* Bilan de lecture des args.  */ +    GBinContent *content;                   /* Version GLib du format      */ +    uleb128_t val;                          /* Valeur lue à faire suivre   */ +    bool status;                            /* Bilan de l'opération        */ + +#define BINARY_CONTENT_READ_ULEB128_METHOD PYTHON_METHOD_DEF            \ +(                                                                       \ +    read_uleb128, "$self, addr, /",                                     \ +    METH_VARARGS, py_binary_content,                                    \ +    "Read an unsigned LEB128-encoded number from a given position.\n"   \ +    "\n"                                                                \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument gets"   \ +    " updated in order to reflect the read progress.\n"                 \ +    "\n"                                                                \ +    "The returned value is the read data in case of success, or an"     \ +    " exception is raised otherwise."                                   \ +) + +    ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr); +    if (!ret) return NULL; + +    content = G_BIN_CONTENT(pygobject_get(self)); + +    status = g_binary_content_read_uleb128(content, addr, &val); +    if (!status) +    { +        clean_vmpa_arg(addr); + +        PyErr_SetString(PyExc_Exception, _("Invalid read access.")); +        return NULL; + +    } + +    result = PyLong_FromUnsignedLongLong(val); + +    clean_vmpa_arg(addr); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = contenu binaire à manipuler.                          * +*                args = non utilisé ici.                                      * +*                                                                             * +*  Description : Lit un nombre signé encodé au format LEB128.                 * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_binary_content_read_leb128(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Instance à retourner        */ +    vmpa2t *addr;                           /* Position interne associée   */ +    int ret;                                /* Bilan de lecture des args.  */ +    GBinContent *content;                   /* Version GLib du format      */ +    leb128_t val;                           /* Valeur lue à faire suivre   */ +    bool status;                            /* Bilan de l'opération        */ + +#define BINARY_CONTENT_READ_LEB128_METHOD PYTHON_METHOD_DEF             \ +(                                                                       \ +    read_leb128, "$self, addr, /",                                      \ +    METH_VARARGS, py_binary_content,                                    \ +    "Read an unsigned LEB128-encoded number from a given position.\n"   \ +    "\n"                                                                \ +    "The location *addr* of the data to read is a"                      \ +    " pychrysalide.arch.vmpa instance, and this *addr* argument gets"   \ +    " updated in order to reflect the read progress.\n"                 \ +    "\n"                                                                \ +    "The returned value is the read data in case of success, or an"     \ +    " exception is raised otherwise."                                   \ +) + +    ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr); +    if (!ret) return NULL; + +    content = G_BIN_CONTENT(pygobject_get(self)); + +    status = g_binary_content_read_leb128(content, addr, &val); +    if (!status) +    { +        clean_vmpa_arg(addr); + +        PyErr_SetString(PyExc_Exception, _("Invalid read access.")); +        return NULL; + +    } + +    result = PyLong_FromLongLong(val); + +    clean_vmpa_arg(addr); + +    return result; + +} + + +#if 0 // FIXME +/****************************************************************************** +*                                                                             *  *  Paramètres  : self    = contenu binaire à manipuler.                       *  *                value   = jeu d'attributs à lier au contenu courant.         *  *                closure = adresse non utilisée ici.                          * @@ -1158,6 +1910,7 @@ static PyObject *py_binary_content_get_attributes(PyObject *self, void *closure)      return result;  } +#endif  /****************************************************************************** @@ -1177,7 +1930,7 @@ static PyObject *py_binary_content_get_root(PyObject *self, void *closure)  {      PyObject *result;                       /* Instance à retourner        */      GBinContent *content;                   /* Version GLib du format      */ -    GContentAttributes *attribs;            /* Attributs à transmettre     */ +    GBinContent *root;                      /* COntenu parent              */  #define BINARY_CONTENT_ROOT_ATTRIB PYTHON_GET_DEF_FULL                  \  (                                                                       \ @@ -1191,11 +1944,11 @@ static PyObject *py_binary_content_get_root(PyObject *self, void *closure)      content = G_BIN_CONTENT(pygobject_get(self)); -    attribs = g_binary_content_get_attributes(content); +    root = g_binary_content_get_root(content); -    result = pygobject_new(G_OBJECT(attribs)); +    result = pygobject_new(G_OBJECT(root)); -    g_object_unref(attribs); +    g_object_unref(root);      return result; @@ -1405,22 +2158,32 @@ PyTypeObject *get_python_binary_content_type(void)  {      static PyMethodDef py_binary_content_methods[] = {          BINARY_CONTENT_DESCRIBE_WRAPPER, +        BINARY_CONTENT_COMPUTE_CHECKSUM_WRAPPER, +        BINARY_CONTENT_COMPUTE_SIZE_WRAPPER, +        BINARY_CONTENT_COMPUTE_START_POS_WRAPPER, +        BINARY_CONTENT_COMPUTE_END_POS_WRAPPER, +        BINARY_CONTENT_SEEK_WRAPPER,          BINARY_CONTENT_READ_RAW_WRAPPER,          BINARY_CONTENT_READ_U8_WRAPPER,          BINARY_CONTENT_READ_U16_WRAPPER,          BINARY_CONTENT_READ_U32_WRAPPER,          BINARY_CONTENT_READ_U64_WRAPPER, +        BINARY_CONTENT_READ_ULEB128_WRAPPER, +        BINARY_CONTENT_READ_LEB128_WRAPPER,          BINARY_CONTENT_DESCRIBE_METHOD, +        BINARY_CONTENT_SEEK_METHOD,          BINARY_CONTENT_READ_RAW_METHOD,          BINARY_CONTENT_READ_U8_METHOD,          BINARY_CONTENT_READ_U16_METHOD,          BINARY_CONTENT_READ_U32_METHOD,          BINARY_CONTENT_READ_U64_METHOD, +        BINARY_CONTENT_READ_ULEB128_METHOD, +        BINARY_CONTENT_READ_LEB128_METHOD,          { NULL }      };      static PyGetSetDef py_binary_content_getseters[] = { -        BINARY_CONTENT_ATTRIBUTES_ATTRIB, +        //BINARY_CONTENT_ATTRIBUTES_ATTRIB,          BINARY_CONTENT_ROOT_ATTRIB,          BINARY_CONTENT_CHECKSUM_ATTRIB,          BINARY_CONTENT_SIZE_ATTRIB, @@ -1476,8 +2239,10 @@ bool ensure_python_binary_content_is_registered(void)      if (!PyType_HasFeature(type, Py_TPFLAGS_READY))      { +        /* FIXME          if (!ensure_python_serializable_object_is_registered())              return false; +        */          module = get_access_to_python_module("pychrysalide.analysis"); @@ -1486,9 +2251,6 @@ bool ensure_python_binary_content_is_registered(void)          if (!register_class_for_pygobject(dict, G_TYPE_BIN_CONTENT, type))              return false; -        if (!define_analysis_content_constants(type)) -            return false; -      }      return true; diff --git a/plugins/pychrysalide/analysis/contents/encapsulated.c b/plugins/pychrysalide/analysis/contents/encapsulated.c index e9583e6..44eee3a 100644 --- a/plugins/pychrysalide/analysis/contents/encapsulated.c +++ b/plugins/pychrysalide/analysis/contents/encapsulated.c @@ -90,10 +90,10 @@ static int py_encaps_content_init(PyObject *self, PyObject *args, PyObject *kwds      "\n"                                                                    \      "    EncapsulatedContent(base, path, endpoint)"                         \      "\n"                                                                    \ -    "Where base, path and endpoint are the previously described expected"   \ -    " properties. The base and the endpoint must be"                        \ -    " pychrysalide.analysis.BinContent instances and the access path must"  \ -    " be provided as a string." +    "Where *base*, *path* and *endpoint* are the previously described"      \ +    " expected properties. The *base* and the *endpoint* have to be"        \ +    " pychrysalide.analysis.BinContent instances and the access *path* has" \ +    " to be provided as a string."      /* Récupération des paramètres */ diff --git a/plugins/pychrysalide/analysis/contents/file.c b/plugins/pychrysalide/analysis/contents/file.c index 5bef069..aa4c5b2 100644 --- a/plugins/pychrysalide/analysis/contents/file.c +++ b/plugins/pychrysalide/analysis/contents/file.c @@ -75,7 +75,7 @@ static int py_file_content_init(PyObject *self, PyObject *args, PyObject *kwds)      "\n"                                                                    \      "    FileContent(filename)"                                             \      "\n"                                                                    \ -    "Where filename is a path to an existing file." +    "Where *filename* is a path to an existing file."      /* Récupération des paramètres */ diff --git a/plugins/pychrysalide/analysis/contents/memory.c b/plugins/pychrysalide/analysis/contents/memory.c index 7464779..9f2bc18 100644 --- a/plugins/pychrysalide/analysis/contents/memory.c +++ b/plugins/pychrysalide/analysis/contents/memory.c @@ -74,7 +74,7 @@ static int py_memory_content_init(PyObject *self, PyObject *args, PyObject *kwds      "\n"                                                                    \      "    MemoryContent(data)"                                               \      "\n"                                                                    \ -    "Where data is provided as string or read-only bytes-like object."      \ +    "Where *data* is provided as string or read-only bytes-like object."    \      " The string may contain embedded null bytes."      /* Récupération des paramètres */ diff --git a/plugins/pychrysalide/analysis/contents/restricted.c b/plugins/pychrysalide/analysis/contents/restricted.c index 4521578..629b4ff 100644 --- a/plugins/pychrysalide/analysis/contents/restricted.c +++ b/plugins/pychrysalide/analysis/contents/restricted.c @@ -80,8 +80,8 @@ static int py_restricted_content_init(PyObject *self, PyObject *args, PyObject *      "\n"                                                                        \      "    RestrictedContent(content, range)"                                     \      "\n"                                                                        \ -    "Where content is a pychrysalide.analysis.BinContent instance and range"    \ -    " a Python object which can be converted into pychrysalide.arch.mrange." +    "Where *content* is a pychrysalide.analysis.BinContent instance and *range*"\ +    " is a Python object which can be converted into pychrysalide.arch.mrange."      /* Récupération des paramètres */ diff --git a/plugins/pychrysalide/analysis/module.c b/plugins/pychrysalide/analysis/module.c index 6b8e441..3976c94 100644 --- a/plugins/pychrysalide/analysis/module.c +++ b/plugins/pychrysalide/analysis/module.c @@ -28,22 +28,28 @@  #include <assert.h> +/*  #include "binary.h"  #include "block.h"  #include "cattribs.h" +*/  #include "content.h" +/*  #include "loaded.h"  #include "loading.h"  #include "project.h"  #include "routine.h"  #include "type.h"  #include "variable.h" +*/  #include "contents/module.h" +/*  #include "db/module.h"  #include "disass/module.h"  #include "scan/module.h"  #include "storage/module.h"  #include "types/module.h" +*/  #include "../helpers.h" @@ -85,11 +91,13 @@ bool add_analysis_module(PyObject *super)      result = (module != NULL);      if (result) result = add_analysis_contents_module(module); +    /*      if (result) result = add_analysis_db_module(module);      if (result) result = add_analysis_disass_module(module);      if (result) result = add_analysis_scan_module(module);      if (result) result = add_analysis_storage_module(module);      if (result) result = add_analysis_types_module(module); +    */      if (!result)          Py_XDECREF(module); @@ -117,11 +125,14 @@ bool populate_analysis_module(void)      result = true; +    /*      if (result) result = ensure_python_loaded_binary_is_registered();      if (result) result = ensure_python_code_block_is_registered();      if (result) result = ensure_python_block_list_is_registered();      if (result) result = ensure_python_content_attributes_is_registered(); +    */      if (result) result = ensure_python_binary_content_is_registered(); +    /*      if (result) result = ensure_python_loaded_content_is_registered();      if (result) result = ensure_python_content_explorer_is_registered();      if (result) result = ensure_python_content_resolver_is_registered(); @@ -129,13 +140,16 @@ bool populate_analysis_module(void)      if (result) result = ensure_python_binary_routine_is_registered();      if (result) result = ensure_python_data_type_is_registered();      if (result) result = ensure_python_binary_variable_is_registered(); +    */      if (result) result = populate_analysis_contents_module(); +    /*      if (result) result = populate_analysis_db_module();      if (result) result = populate_analysis_disass_module();      if (result) result = populate_analysis_scan_module();      if (result) result = populate_analysis_storage_module();      if (result) result = populate_analysis_types_module(); +    */      assert(result);  | 
