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); |