From de82c8165e61e3c19be184dbc00f66bfc7479c76 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 14 Jul 2020 13:01:17 +0200 Subject: Updated the code handling binary contents. --- plugins/pychrysalide/analysis/binary.c | 37 -- plugins/pychrysalide/analysis/content.c | 687 +++++++++++++++++++++++++++++++- plugins/ropgadgets/select.c | 12 +- src/analysis/binary.c | 29 -- src/analysis/binary.h | 3 - src/analysis/content-int.h | 2 +- src/analysis/content.c | 44 +- src/analysis/content.h | 2 +- src/analysis/contents/encapsulated.c | 12 +- src/analysis/contents/file.c | 17 +- src/analysis/contents/memory.c | 8 +- src/analysis/disass/disassembler.c | 4 +- src/gui/dialogs/export_disass.c | 6 +- src/gui/panels/bintree.c | 7 +- 14 files changed, 745 insertions(+), 125 deletions(-) diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c index acc3ae5..2f8af5f 100644 --- a/plugins/pychrysalide/analysis/binary.c +++ b/plugins/pychrysalide/analysis/binary.c @@ -58,9 +58,6 @@ static PyObject *py_loaded_binary_add_to_collection(PyObject *, PyObject *); /* Active les éléments en amont d'un horodatage donné. */ static PyObject *py_loaded_binary_set_last_active(PyObject *, PyObject *); -/* Fournit le nom associé à l'élément binaire. */ -static PyObject *py_loaded_binary_get_name(PyObject *, void *); - /* Fournit l'ensemble des collections utilisées par un binaire. */ static PyObject *py_loaded_binary_get_collections(PyObject *, void *); @@ -322,36 +319,6 @@ static PyObject *py_loaded_binary_set_last_active(PyObject *self, PyObject *args * Paramètres : self = objet Python concerné par l'appel. * * closure = non utilisé ici. * * * -* Description : Fournit le nom associé à l'élément binaire. * -* * -* Retour : Nom de fichier avec chemin absolu. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_loaded_binary_get_name(PyObject *self, void *closure) -{ - PyObject *result; /* Trouvailles à retourner */ - GLoadedBinary *binary; /* Version native */ - const char *name; /* Désignation du binaire */ - - binary = G_LOADED_BINARY(pygobject_get(self)); - - name = g_loaded_binary_get_name(binary, true); - - result = PyUnicode_FromString(name); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = objet Python concerné par l'appel. * -* closure = non utilisé ici. * -* * * Description : Fournit l'ensemble des collections utilisées par un binaire. * * * * Retour : Liste de collections en place. * @@ -536,10 +503,6 @@ PyTypeObject *get_python_loaded_binary_type(void) }; static PyGetSetDef py_loaded_binary_getseters[] = { - { - "name", py_loaded_binary_get_name, NULL, - "Name of the loaded binary.", NULL - }, LOADED_BINARY_COLLECTIONS_ATTRIB, { "format", py_loaded_binary_get_format, NULL, diff --git a/plugins/pychrysalide/analysis/content.c b/plugins/pychrysalide/analysis/content.c index 8a404ed..5b5608c 100644 --- a/plugins/pychrysalide/analysis/content.c +++ b/plugins/pychrysalide/analysis/content.c @@ -26,13 +26,15 @@ #include +#include #include +#include #include -#include +#include #include @@ -44,15 +46,34 @@ -#define BINARY_CONTENT_DOC \ - "The BinContent is an interface which handles access to a given" \ - " binary content." \ - "\n" \ - "All of its implementations are located in the" \ - " pychrysalide.analysis.contents module. The main implemantation" \ - " is the pychrysalide.analysis.contents.FileContent class." +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ +/* Procède à l'initialisation de l'interface de génération. */ +static void py_binary_content_interface_init(GBinContentIface *, gpointer *); + +/* Fournit le nom associé au contenu binaire. */ +static char *py_binary_content_describe_wrapper(const GBinContent *, bool); + +/* Fournit une portion des données représentées. */ +static bool py_binary_content_read_raw_wrapper(const GBinContent *, vmpa2t *, phys_t, bin_t *);; + +/* Lit un nombre non signé sur un octet. */ +static bool py_binary_content_read_u8_wrapper(const GBinContent *, vmpa2t *, uint8_t *); + +/* Lit un nombre non signé sur deux octets. */ +static bool py_binary_content_read_u16_wrapper(const GBinContent *, vmpa2t *, SourceEndian, uint16_t *); + +/* Lit un nombre non signé sur quatre octets. */ +static bool py_binary_content_read_u32_wrapper(const GBinContent *, vmpa2t *, SourceEndian, uint32_t *); + +/* Lit un nombre non signé sur huit octets. */ +static bool py_binary_content_read_u64_wrapper(const GBinContent *, vmpa2t *, SourceEndian, uint64_t *); + + + +/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ + /* Fournit le nom associé au contenu binaire. */ static PyObject *py_binary_content_describe(PyObject *, PyObject *); @@ -95,6 +116,608 @@ static PyObject *py_binary_content_get_data(PyObject *, void *); +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* unused = adresse non utilisée ici. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_binary_content_interface_init(GBinContentIface *iface, gpointer *unused) +{ +#define BINARY_CONTENT_DOC \ + "The BinContent is an interface which handles access to a given binary" \ + " content.\n" \ + "\n" \ + "All of its implementations are located in the" \ + " pychrysalide.analysis.contents module. The main implemantation is" \ + " the pychrysalide.analysis.contents.FileContent class.\n" \ + "\n" \ + "A typical class declaration for a new implementation looks like:\n" \ + "\n" \ + " class NewImplem(GObject.Object, BinContent):\n" \ + " ...\n" \ + "\n" \ + "The following methods have to be defined for new implementations:\n" \ + "* pychrysalide.analysis.BinContent._describe();\n" \ + "* pychrysalide.analysis.BinContent._read_raw();\n" \ + "* 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" + + iface->describe = py_binary_content_describe_wrapper; + + iface->read_raw = py_binary_content_read_raw_wrapper; + iface->read_u8 = py_binary_content_read_u8_wrapper; + iface->read_u16 = py_binary_content_read_u16_wrapper; + iface->read_u32 = py_binary_content_read_u32_wrapper; + iface->read_u64 = py_binary_content_read_u64_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : content = élément chargé à consulter. * +* full = précise s'il s'agit d'une version longue ou non. * +* * +* Description : Fournit le nom associé au contenu binaire. * +* * +* Retour : Nom de fichier avec chemin absolu au besoin. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_binary_content_describe_wrapper(const GBinContent *content, bool full) +{ + char *result; /* Description à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *full_obj; /* Précision sur la longueur */ + 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_DESCRIBE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _describe, "$self, full", \ + METH_VARARGS, \ + "Abstract method used to build a (full ?) description of" \ + " the binary content.describe the loaded content.\n" \ + "\n" \ + "The description is returned as a string." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_describe")) + { + full_obj = full ? Py_True : Py_False; + Py_INCREF(full_obj); + + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, full_obj); + + pyret = run_python_method(pyobj, "_describe", args); + + if (pyret != NULL) + { + ret = PyUnicode_Check(pyret); + + if (ret) + result = strdup(PyUnicode_AsUTF8(pyret)); + + 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. * +* out = réceptacle disponible pour ces données. [OUT] * +* * +* Description : Fournit une portion des données représentées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_binary_content_read_raw_wrapper(const GBinContent *content, vmpa2t *addr, phys_t length, bin_t *out) +{ + 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 */ + const char *data; /* Données brutes à copier */ + +#define BINARY_CONTENT_READ_RAW_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _read_raw, "$self, addr, length", \ + METH_VARARGS, \ + "Abstract method used to provide the bytes read from a given position.\n" \ + "\n" \ + "The description is returned as a string." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_read_raw")) + { + 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, "_read_raw", args); + + if (pyret != NULL) + { + ret = PyUnicode_Check(pyret); + + if (ret) + { + assert((phys_t)PyBytes_Size(pyret) == length); + + if ((phys_t)PyBytes_Size(pyret) == length) + { + /* Avancement de la tête de lecture */ + + copy_vmpa(addr, get_internal_vmpa(addr_obj)); + + /* Récupération des données */ + + data = PyBytes_AsString(pyret); + + memcpy(out, data, length); + + /* 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 non signé sur un octet. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_binary_content_read_u8_wrapper(const GBinContent *content, vmpa2t *addr, uint8_t *val) +{ + 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_READ_U8_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _read_u8, "$self, addr", \ + METH_VARARGS, \ + "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" \ + "\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_u8")) + { + addr_obj = build_from_internal_vmpa(addr); + + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, addr_obj); + + pyret = run_python_method(pyobj, "_read_u8", 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_AsUnsignedLong(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. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur deux octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_binary_content_read_u16_wrapper(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint16_t *val) +{ + bool result; /* Bilan à remonter */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *addr_obj; /* Position en version Python */ + PyObject *endianness_obj; /* Boutisme 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_READ_U16_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _read_u16, "$self, addr, endian", \ + METH_VARARGS, \ + "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" \ + " pychrysalide.analysis.BinContent.SourceEndian values.\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_u16")) + { + addr_obj = build_from_internal_vmpa(addr); + endianness_obj = cast_with_constants_group_from_type(get_python_binary_content_type(), + "SourceEndian", endian); + + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, addr_obj); + PyTuple_SetItem(args, 1, endianness_obj); + + pyret = run_python_method(pyobj, "_read_u16", 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_AsUnsignedLong(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. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur quatre octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_binary_content_read_u32_wrapper(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint32_t *val) +{ + bool result; /* Bilan à remonter */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *addr_obj; /* Position en version Python */ + PyObject *endianness_obj; /* Boutisme 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_READ_U32_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _read_u32, "$self, addr, endian", \ + METH_VARARGS, \ + "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" \ + " pychrysalide.analysis.BinContent.SourceEndian values.\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_u32")) + { + addr_obj = build_from_internal_vmpa(addr); + endianness_obj = cast_with_constants_group_from_type(get_python_binary_content_type(), + "SourceEndian", endian); + + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, addr_obj); + PyTuple_SetItem(args, 1, endianness_obj); + + pyret = run_python_method(pyobj, "_read_u32", 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_AsUnsignedLong(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. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur huit octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_binary_content_read_u64_wrapper(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint64_t *val) +{ + bool result; /* Bilan à remonter */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *addr_obj; /* Position en version Python */ + PyObject *endianness_obj; /* Boutisme 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_READ_U64_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _read_u64, "$self, addr, endian", \ + METH_VARARGS, \ + "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" \ + " pychrysalide.analysis.BinContent.SourceEndian values.\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_u64")) + { + addr_obj = build_from_internal_vmpa(addr); + endianness_obj = cast_with_constants_group_from_type(get_python_binary_content_type(), + "SourceEndian", endian); + + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, addr_obj); + PyTuple_SetItem(args, 1, endianness_obj); + + pyret = run_python_method(pyobj, "_read_u64", 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; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CONNEXION AVEC L'API DE PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : self = contenu binaire à manipuler. * @@ -114,7 +737,7 @@ static PyObject *py_binary_content_describe(PyObject *self, PyObject *args) int full; /* Description complète ? */ int ret; /* Bilan de lecture des args. */ GBinContent *content; /* Version GLib du format */ - const char *desc; /* Description obtenue */ + char *desc; /* Description obtenue */ #define BINARY_CONTENT_DESCRIBE_METHOD PYTHON_METHOD_DEF \ ( \ @@ -134,6 +757,8 @@ static PyObject *py_binary_content_describe(PyObject *self, PyObject *args) result = PyUnicode_FromString(desc); + free(desc); + return result; } @@ -219,6 +844,11 @@ static PyObject *py_binary_content_read_u8(PyObject *self, PyObject *args) read_u8, "$self, addr, /", \ 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" \ + "\n" \ + "The returned value is the read data or None is case of error." \ ) ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr); @@ -274,8 +904,11 @@ 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 endianness of the data can be provided using" \ - " pychrysalide.analysis.BinContent.SourceEndian values." \ + "The location of the data to read is a pychrysalide.arch.vmpa" \ + " instance. 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." \ ) ret = PyArg_ParseTuple(args, "O&k", convert_any_to_vmpa, &addr, &endianness); @@ -331,8 +964,11 @@ 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 endianness of the data can be provided using" \ - " pychrysalide.analysis.BinContent.SourceEndian values." \ + "The location of the data to read is a pychrysalide.arch.vmpa" \ + " instance. 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." \ ) ret = PyArg_ParseTuple(args, "O&k", convert_any_to_vmpa, &addr, &endianness); @@ -385,10 +1021,13 @@ static PyObject *py_binary_content_read_u64(PyObject *self, PyObject *args) ( \ read_u64, "$self, addr, endian, /", \ METH_VARARGS, py_binary_content, \ - "Read eight unsigned bytes from a given position." \ + "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" \ + " pychrysalide.analysis.BinContent.SourceEndian values.\n" \ "\n" \ - "The endianness of the data can be provided using" \ - " pychrysalide.analysis.BinContent.SourceEndian values." \ + "The returned value is the read data or None is case of error." \ ) ret = PyArg_ParseTuple(args, "O&k", convert_any_to_vmpa, &addr, &endianness); @@ -691,6 +1330,12 @@ static PyObject *py_binary_content_get_data(PyObject *self, void *closure) PyTypeObject *get_python_binary_content_type(void) { static PyMethodDef py_binary_content_methods[] = { + BINARY_CONTENT_DESCRIBE_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_DESCRIBE_METHOD, BINARY_CONTENT_READ_RAW_METHOD, BINARY_CONTENT_READ_U8_METHOD, @@ -749,6 +1394,14 @@ bool ensure_python_binary_content_is_registered(void) PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ + static GInterfaceInfo info = { /* Paramètres d'inscription */ + + .interface_init = (GInterfaceInitFunc)py_binary_content_interface_init, + .interface_finalize = NULL, + .interface_data = NULL, + + }; + type = get_python_binary_content_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) @@ -757,7 +1410,7 @@ bool ensure_python_binary_content_is_registered(void) dict = PyModule_GetDict(module); - if (!register_interface_for_pygobject(dict, G_TYPE_BIN_CONTENT, type)) + if (!register_interface_for_pygobject_2(dict, G_TYPE_BIN_CONTENT, type, &info)) return false; if (!define_analysis_content_constants(type)) diff --git a/plugins/ropgadgets/select.c b/plugins/ropgadgets/select.c index aebe433..9df71bb 100644 --- a/plugins/ropgadgets/select.c +++ b/plugins/ropgadgets/select.c @@ -474,7 +474,7 @@ static GtkWidget *load_and_populate_current_project_binaries(GObject *ref, gint GLoadedContent **contents; /* Liste de contenus chargés */ size_t count; /* Taille de cette liste */ size_t i; /* Boucle de parcours */ - GLoadedBinary *binary; /* Contenu de code binaire */ + char *desc; /* Description de contenu */ GtkTreeIter iter; /* Point d'insertion */ GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ @@ -498,15 +498,17 @@ static GtkWidget *load_and_populate_current_project_binaries(GObject *ref, gint { if (G_IS_LOADED_BINARY(contents[i])) { - binary = G_LOADED_BINARY(contents[i]); + desc = g_loaded_content_describe(contents[i], true); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, - CPB_BINARY, binary, - CPB_FILENAME, g_loaded_binary_get_name(binary, true), + CPB_BINARY, contents[i], + CPB_FILENAME, desc, -1); - if (binary == (GLoadedBinary *)current) + free(desc); + + if (contents[i] == current) *selected = i; } diff --git a/src/analysis/binary.c b/src/analysis/binary.c index aee4499..c671827 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -400,35 +400,6 @@ GLoadedContent *g_loaded_binary_new(GExeFormat *format) } -/****************************************************************************** -* * -* Paramètres : binary = élément binaire à consulter. * -* full = précise s'il s'agit d'une version longue ou non. * -* * -* Description : Fournit le nom associé à l'élément binaire. * -* * -* Retour : Nom de fichier avec chemin absolu. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const char *g_loaded_binary_get_name(const GLoadedBinary *binary, bool full) -{ - const char *result; /* Description à retourner */ - GBinContent *content; /* Contenu binaire mannipulé */ - - content = g_known_format_get_content(G_KNOWN_FORMAT(binary->format)); - - result = g_binary_content_describe(content, full); - - g_object_unref(G_OBJECT(content)); - - return result; - -} - - /* ---------------------------------------------------------------------------------- */ /* INFORMATIONS D'ENREGISTREMENTS */ diff --git a/src/analysis/binary.h b/src/analysis/binary.h index 74c5f7f..178d186 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -76,9 +76,6 @@ GType g_loaded_binary_get_type(void); /* Interprète un contenu binaire chargé. */ GLoadedContent *g_loaded_binary_new(GExeFormat *); -/* Fournit le nom associé à l'élément binaire. */ -const char *g_loaded_binary_get_name(const GLoadedBinary *, bool); - /* ------------------------- INFORMATIONS D'ENREGISTREMENTS ------------------------- */ diff --git a/src/analysis/content-int.h b/src/analysis/content-int.h index ad13b8d..886c196 100644 --- a/src/analysis/content-int.h +++ b/src/analysis/content-int.h @@ -39,7 +39,7 @@ typedef GContentAttributes * (* get_content_attributes) (const GBinContent *); typedef GBinContent * (* get_content_root_fc) (GBinContent *); /* Fournit le nom associé au contenu binaire. */ -typedef const char * (* describe_content_fc) (const GBinContent *, bool); +typedef char * (* describe_content_fc) (const GBinContent *, bool); /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ typedef bool (* save_content_fc) (const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *); diff --git a/src/analysis/content.c b/src/analysis/content.c index 86fa490..8b83261 100644 --- a/src/analysis/content.c +++ b/src/analysis/content.c @@ -197,14 +197,14 @@ GBinContent *g_binary_content_get_root(GBinContent *content) * * ******************************************************************************/ -const char *g_binary_content_describe(const GBinContent *content, bool full) +char *g_binary_content_describe(const GBinContent *content, bool full) { char *result; /* Description à retourner */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - result = strdup(iface->describe(content, full)); + result = iface->describe(content, full); return result; @@ -418,11 +418,14 @@ const bin_t *g_binary_content_get_raw_access(const GBinContent *content, vmpa2t bool g_binary_content_read_raw(const GBinContent *content, vmpa2t *addr, phys_t length, bin_t *out) { + bool result; /* Bilan à remonter */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->read_raw(content, addr, length, out); + result = iface->read_raw(content, addr, length, out); + + return result; } @@ -444,11 +447,14 @@ bool g_binary_content_read_raw(const GBinContent *content, vmpa2t *addr, phys_t bool g_binary_content_read_u4(const GBinContent *content, vmpa2t *addr, bool *low, uint8_t *val) { + bool result; /* Bilan à remonter */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->read_u4(content, addr, low, val); + result = iface->read_u4(content, addr, low, val); + + return result; } @@ -470,11 +476,14 @@ bool g_binary_content_read_u4(const GBinContent *content, vmpa2t *addr, bool *lo bool g_binary_content_read_u8(const GBinContent *content, vmpa2t *addr, uint8_t *val) { + bool result; /* Bilan à remonter */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->read_u8(content, addr, val); + result = iface->read_u8(content, addr, val); + + return result; } @@ -496,11 +505,14 @@ bool g_binary_content_read_u8(const GBinContent *content, vmpa2t *addr, uint8_t bool g_binary_content_read_u16(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint16_t *val) { + bool result; /* Bilan à remonter */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->read_u16(content, addr, endian, val); + result = iface->read_u16(content, addr, endian, val); + + return result; } @@ -522,11 +534,14 @@ bool g_binary_content_read_u16(const GBinContent *content, vmpa2t *addr, SourceE bool g_binary_content_read_u32(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint32_t *val) { + bool result; /* Bilan à remonter */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->read_u32(content, addr, endian, val); + result = iface->read_u32(content, addr, endian, val); + + return result; } @@ -548,11 +563,14 @@ bool g_binary_content_read_u32(const GBinContent *content, vmpa2t *addr, SourceE bool g_binary_content_read_u64(const GBinContent *content, vmpa2t *addr, SourceEndian endian, uint64_t *val) { + bool result; /* Bilan à remonter */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->read_u64(content, addr, endian, val); + result = iface->read_u64(content, addr, endian, val); + + return result; } @@ -573,11 +591,14 @@ bool g_binary_content_read_u64(const GBinContent *content, vmpa2t *addr, SourceE bool g_binary_content_read_uleb128(const GBinContent *content, vmpa2t *addr, uleb128_t *val) { + bool result; /* Bilan à remonter */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->read_uleb128(content, addr, val); + result = iface->read_uleb128(content, addr, val); + + return result; } @@ -598,10 +619,13 @@ bool g_binary_content_read_uleb128(const GBinContent *content, vmpa2t *addr, ule bool g_binary_content_read_leb128(const GBinContent *content, vmpa2t *addr, leb128_t *val) { + bool result; /* Bilan à remonter */ GBinContentIface *iface; /* Interface utilisée */ iface = G_BIN_CONTENT_GET_IFACE(content); - return iface->read_leb128(content, addr, val); + result = iface->read_leb128(content, addr, val); + + return result; } diff --git a/src/analysis/content.h b/src/analysis/content.h index 9f901e7..d7f5536 100644 --- a/src/analysis/content.h +++ b/src/analysis/content.h @@ -68,7 +68,7 @@ GContentAttributes *g_binary_content_get_attributes(const GBinContent *); GBinContent *g_binary_content_get_root(GBinContent *); /* Fournit le nom associé au contenu binaire. */ -const char *g_binary_content_describe(const GBinContent *, bool); +char *g_binary_content_describe(const GBinContent *, bool); /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ bool g_binary_content_save(const GBinContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *); diff --git a/src/analysis/contents/encapsulated.c b/src/analysis/contents/encapsulated.c index 569df10..59b0c9e 100644 --- a/src/analysis/contents/encapsulated.c +++ b/src/analysis/contents/encapsulated.c @@ -74,7 +74,7 @@ static void g_encaps_content_finalize(GEncapsContent *); static GBinContent *g_encaps_content_get_root(GEncapsContent *); /* Fournit le nom associé au contenu binaire. */ -static const char *g_encaps_content_describe(const GEncapsContent *, bool); +static char *g_encaps_content_describe(const GEncapsContent *, bool); /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ static bool g_encaps_content_save(const GEncapsContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *); @@ -296,7 +296,7 @@ GBinContent *g_encaps_content_new(GBinContent *base, const char *path, GBinConte /* Description complète */ - result->full_desc = stradd(result->full_desc, g_binary_content_describe(result->base, true)); + result->full_desc = g_binary_content_describe(result->base, true); result->full_desc = stradd(result->full_desc, G_DIR_SEPARATOR_S); @@ -416,14 +416,14 @@ static GBinContent *g_encaps_content_get_root(GEncapsContent *content) * * ******************************************************************************/ -static const char *g_encaps_content_describe(const GEncapsContent *content, bool full) +static char *g_encaps_content_describe(const GEncapsContent *content, bool full) { - const char *result; /* Description à retourner */ + char *result; /* Description à retourner */ if (full) - result = content->full_desc; + result = strdup(content->full_desc); else - result = content->desc; + result = strdup(content->desc); return result; diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c index b133336..7bb0be8 100644 --- a/src/analysis/contents/file.c +++ b/src/analysis/contents/file.c @@ -86,7 +86,7 @@ static GContentAttributes *g_file_content_get_attributes(const GFileContent *); static GBinContent *g_file_content_get_root(GFileContent *); /* Fournit le nom associé au contenu binaire. */ -static const char *g_file_content_describe(const GFileContent *, bool); +static char *g_file_content_describe(const GFileContent *, bool); /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ static bool g_file_content_save(const GFileContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *); @@ -489,22 +489,23 @@ static GBinContent *g_file_content_get_root(GFileContent *content) * * ******************************************************************************/ -static const char *g_file_content_describe(const GFileContent *content, bool full) +static char *g_file_content_describe(const GFileContent *content, bool full) { - const char *result; /* Description à retourner */ + char *result; /* Description à retourner */ + const char *sep; /* Caractère de séparation */ if (full) - result = content->filename; + result = strdup(content->filename); else { - result = strrchr(content->filename, G_DIR_SEPARATOR); + sep = strrchr(content->filename, G_DIR_SEPARATOR); - if (result == NULL) - result = content->filename; + if (sep == NULL) + result = strdup(content->filename); else - result++; + result = strdup(++sep); } diff --git a/src/analysis/contents/memory.c b/src/analysis/contents/memory.c index 232a41d..a37a7d4 100644 --- a/src/analysis/contents/memory.c +++ b/src/analysis/contents/memory.c @@ -77,7 +77,7 @@ static void g_memory_content_finalize(GMemoryContent *); static GBinContent *g_memory_content_get_root(GMemoryContent *); /* Fournit le nom associé au contenu binaire. */ -static const char *g_memory_content_describe(const GMemoryContent *, bool); +static char *g_memory_content_describe(const GMemoryContent *, bool); /* Ecrit une sauvegarde de contenu binaire dans un fichier XML. */ static bool g_memory_content_save(const GMemoryContent *, xmlDocPtr, xmlXPathContextPtr, const char *, const char *); @@ -399,11 +399,11 @@ static GBinContent *g_memory_content_get_root(GMemoryContent *content) * * ******************************************************************************/ -static const char *g_memory_content_describe(const GMemoryContent *content, bool full) +static char *g_memory_content_describe(const GMemoryContent *content, bool full) { - const char *result; /* Description à retourner */ + char *result; /* Description à retourner */ - result = "In-memory content"; + result = strdup("In-memory content"); return result; diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 607f1e4..af67fdf 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -389,7 +389,7 @@ void output_disassembly(GLoadedBinary *binary, GProcContext *context, GtkStatusS GBinContent *content; /* Contenu bianire manipulé */ GCodingLanguage *lang; /* Langage de sortie préféré */ char **text; /* Contenu brute à imprimer */ - const char *desc; /* Désignation du binaire */ + char *desc; /* Désignation du binaire */ const gchar *checksum; /* Identifiant de binaire */ GIntroGenerator *generator; /* Générateur constitué */ @@ -420,6 +420,8 @@ void output_disassembly(GLoadedBinary *binary, GProcContext *context, GtkStatusS asprintf(&text[2], "%s%s", _("Source: "), desc); + free(desc); + /* Checksum SHA256 */ checksum = g_binary_content_get_checksum(content); diff --git a/src/gui/dialogs/export_disass.c b/src/gui/dialogs/export_disass.c index beaa3c8..314b9cf 100644 --- a/src/gui/dialogs/export_disass.c +++ b/src/gui/dialogs/export_disass.c @@ -875,7 +875,7 @@ static void register_output_panel(GtkAssistant *assistant) GtkWidget *entry; /* Zone de saisie de texte */ GtkWidget *button; /* Sélection de fichier */ GLoadedBinary *binary; /* Binaire chargé à parcourir */ - const char *filename; /* Chemin d'accès par défaut */ + char *filename; /* Chemin d'accès par défaut */ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); qck_set_margins(vbox, 8, 8, 8, 8); @@ -907,11 +907,13 @@ static void register_output_panel(GtkAssistant *assistant) /* Choix par défaut */ binary = G_LOADED_BINARY(g_object_get_data(G_OBJECT(assistant), "binary")); - filename = g_loaded_binary_get_name(binary, true); + filename = g_loaded_content_describe(G_LOADED_CONTENT(binary), true); gtk_entry_set_text(GTK_ENTRY(entry), filename); gtk_editable_insert_text(GTK_EDITABLE(entry), ".html", -1, (gint []) { strlen(filename) }); + free(filename); + g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(on_export_filename_changed), assistant); } diff --git a/src/gui/panels/bintree.c b/src/gui/panels/bintree.c index 220a31d..a949b0d 100644 --- a/src/gui/panels/bintree.c +++ b/src/gui/panels/bintree.c @@ -688,6 +688,7 @@ static void reload_portions_for_new_tree_view(const GBintreePanel *panel, GtkSta GBinPortion *portions; /* Couche première de portions */ size_t count; /* Compteur de portions */ GtkTreeIter top; /* Racine de l'arborescence */ + char *desc; /* Description de contenu */ gint max_depth; /* Profondeur maximale */ GtkSpinButton *depth_spin; /* Bouton de variation */ GtkTreeView *treeview; /* Arborescence constituée */ @@ -708,11 +709,15 @@ static void reload_portions_for_new_tree_view(const GBintreePanel *panel, GtkSta gtk_tree_store_append(store, &top, NULL); + desc = g_loaded_content_describe(G_LOADED_CONTENT(panel->binary), false); + gtk_tree_store_set(store, &top, BTC_ICON, NULL, - BTC_CAPTION, g_loaded_binary_get_name(panel->binary, false), + BTC_CAPTION, desc, -1); + free(desc); + data->panel = panel; data->top = ⊤ data->status = status; -- cgit v0.11.2-87-g4458