diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2021-04-05 22:59:31 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2021-04-05 23:11:48 (GMT) |
commit | b0347ca45a08ac63bc6dd6f244b046c6d19a6cdd (patch) | |
tree | 9af1ec9901ddcf696bd3297633faf9fb46712396 /plugins/pe/python | |
parent | cf0b5d5f07e8102f2c9a04012bf29cabda9d85e4 (diff) |
Build a partial working support for the PE format.
Diffstat (limited to 'plugins/pe/python')
-rw-r--r-- | plugins/pe/python/Makefile.am | 23 | ||||
-rw-r--r-- | plugins/pe/python/constants.c | 143 | ||||
-rw-r--r-- | plugins/pe/python/constants.h | 42 | ||||
-rw-r--r-- | plugins/pe/python/format.c | 595 | ||||
-rw-r--r-- | plugins/pe/python/format.h | 45 | ||||
-rw-r--r-- | plugins/pe/python/module.c | 93 | ||||
-rw-r--r-- | plugins/pe/python/module.h | 38 | ||||
-rw-r--r-- | plugins/pe/python/routine.c | 472 | ||||
-rw-r--r-- | plugins/pe/python/routine.h | 62 | ||||
-rw-r--r-- | plugins/pe/python/translate.c | 213 | ||||
-rw-r--r-- | plugins/pe/python/translate.h | 48 |
11 files changed, 1774 insertions, 0 deletions
diff --git a/plugins/pe/python/Makefile.am b/plugins/pe/python/Makefile.am new file mode 100644 index 0000000..18634a3 --- /dev/null +++ b/plugins/pe/python/Makefile.am @@ -0,0 +1,23 @@ + +noinst_LTLIBRARIES = libpepython.la + +libpepython_la_SOURCES = \ + constants.h constants.c \ + format.h format.c \ + module.h module.c \ + routine.h routine.c \ + translate.h translate.c + + +libpepython_la_LDFLAGS = + + +devdir = $(includedir)/chrysalide/$(subdir) + +dev_HEADERS = $(libpepython_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/pe/python/constants.c b/plugins/pe/python/constants.c new file mode 100644 index 0000000..9b4942d --- /dev/null +++ b/plugins/pe/python/constants.c @@ -0,0 +1,143 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.c - équivalent Python partiel du fichier "plugins/pe/pe_def.h" + * + * Copyright (C) 2020 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "constants.h" + + +#include <plugins/pychrysalide/helpers.h> + + +#include "../pe_def.h" +#include "../routine.h" + + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour le format PE. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_python_pe_format_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + result = true; + + /** + * Indices des répertoires PE + */ + + values = PyDict_New(); + + if (result) result = add_const_to_group(values, "EXPORT", IMAGE_DIRECTORY_ENTRY_EXPORT); + if (result) result = add_const_to_group(values, "IMPORT", IMAGE_DIRECTORY_ENTRY_IMPORT); + if (result) result = add_const_to_group(values, "RESOURCE", IMAGE_DIRECTORY_ENTRY_RESOURCE); + if (result) result = add_const_to_group(values, "EXCEPTION", IMAGE_DIRECTORY_ENTRY_EXCEPTION); + if (result) result = add_const_to_group(values, "SECURITY", IMAGE_DIRECTORY_ENTRY_SECURITY); + if (result) result = add_const_to_group(values, "BASERELOC", IMAGE_DIRECTORY_ENTRY_BASERELOC); + if (result) result = add_const_to_group(values, "DEBUG", IMAGE_DIRECTORY_ENTRY_DEBUG); + if (result) result = add_const_to_group(values, "ARCHITECTURE", IMAGE_DIRECTORY_ENTRY_ARCHITECTURE); + if (result) result = add_const_to_group(values, "GLOBALPTR", IMAGE_DIRECTORY_ENTRY_GLOBALPTR); + if (result) result = add_const_to_group(values, "TLS", IMAGE_DIRECTORY_ENTRY_TLS); + if (result) result = add_const_to_group(values, "LOAD_CONFIG", IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG); + if (result) result = add_const_to_group(values, "BOUND_IMPORT", IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT); + if (result) result = add_const_to_group(values, "IAT", IMAGE_DIRECTORY_ENTRY_IAT); + if (result) result = add_const_to_group(values, "DELAY_IMPORT", IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); + if (result) result = add_const_to_group(values, "COM_DESCRIPTOR", IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, false, "ImageDirectoryEntry", values, + "Index number for a kind of data directory entry."); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les routines du format PE. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_python_pe_exported_routine_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + result = true; + + values = PyDict_New(); + + if (result) result = add_const_to_group(values, "HAS_ORDINAL", PSF_HAS_ORDINAL); + if (result) result = add_const_to_group(values, "FORWARDED", PSF_FORWARDED); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, true, "PeSymbolFlag", values, + "Extra indications for exported PE routine symbols."); + + values = PyDict_New(); + + if (result) result = add_const_to_group(values, "UNDEF_PE_ORDINAL", UNDEF_PE_ORDINAL); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, false, "OrdinalValue", values, + "Extra value for exported PE routine ordinals."); + + exit: + + return result; + +} diff --git a/plugins/pe/python/constants.h b/plugins/pe/python/constants.h new file mode 100644 index 0000000..25b0adb --- /dev/null +++ b/plugins/pe/python/constants.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.h - prototypes pour l'équivalent Python partiel du fichier "plugins/pe/pe_def.h" + * + * Copyright (C) 2020 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PE_PYTHON_CONSTANTS_H +#define _PLUGINS_PE_PYTHON_CONSTANTS_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Définit les constantes pour le format PE. */ +bool define_python_pe_format_constants(PyTypeObject *); + +/* Définit les constantes pour les routines du format PE. */ +bool define_python_pe_exported_routine_constants(PyTypeObject *); + + + +#endif /* _PLUGINS_PE_PYTHON_CONSTANTS_H */ diff --git a/plugins/pe/python/format.c b/plugins/pe/python/format.c new file mode 100644 index 0000000..d295da4 --- /dev/null +++ b/plugins/pe/python/format.c @@ -0,0 +1,595 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * format.c - équivalent Python du fichier "plugins/pe/format.c" + * + * Copyright (C) 2017-2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "format.h" + + +#include <pygobject.h> + + +#include <format/known.h> +#include <plugins/dt.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/content.h> +#include <plugins/pychrysalide/format/executable.h> + + +#include "constants.h" +#include "translate.h" +#include "../format.h" +#include "../rich.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_pe_format_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_pe_format_init(PyObject *, PyObject *, PyObject *); + + + +/* ------------------------------ DEFINITION DE FORMAT ------------------------------ */ + + +/* Présente l'en-tête MS-DOS du format chargé. */ +static PyObject *py_pe_format_get_dos_header(PyObject *, void *); + +/* Offre un raccourci vers les répertoires du format PE. */ +static PyObject *py_pe_format_get_directories(PyObject *, void *); + +/* Présente l'en-tête enrichi du format chargé. */ +static PyObject *py_pe_format_get_rich_header(PyObject *, void *); + +/* Présente l'empreinte d'un en-tête enrichi du format chargé. */ +static PyObject *py_pe_format_get_rich_header_checksum(PyObject *, void *); + +/* Présente les identifiants contenues dans l'en-tête enrichi. */ +static PyObject *py_pe_format_get_comp_ids(PyObject *, void *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_pe_format_type(); + + if (type == base) + goto simple_way; + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_PE_FORMAT, type->tp_name, NULL, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type, base); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + simple_way: + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_pe_format_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GBinContent *content; /* Instance GLib du contenu */ + int ret; /* Bilan de lecture des args. */ + GPeFormat *format; /* Création GLib à transmettre */ + +#define PE_FORMAT_DOC \ + "The PeFormat class handles executables with a Portable Executable" \ + " structure.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " PeFormat(content)" \ + "\n" \ + "Where content points to data as a pychrysalide.analysis.BinContent" \ + " instance." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + format = G_PE_FORMAT(pygobject_get(self)); + + g_known_format_set_content(G_KNOWN_FORMAT(format), content); + + return 0; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DE FORMAT */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = format en place à consulter. * +* closure = non utilisé ici. * +* * +* Description : Présente l'en-tête MS-DOS du format chargé. * +* * +* Retour : Structure Python créée pour l'occasion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_format_get_dos_header(PyObject *self, void *closure) +{ + PyObject *result; /* Trouvaille à retourner */ + GPeFormat *format; /* Version GLib du format */ + +#define PE_FORMAT_DOS_HEADER_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + dos_header, py_pe_format, \ + "MS-DOS header of the file format.\n" \ + "\n" \ + "This property is a pychrysalide.StructObject instance." \ + "\n" \ + "The provided information is composed of the following" \ + " properties :\n" \ + "\n" \ + "* e_magic;\n" \ + "* e_cblp;\n" \ + "* e_cp;\n" \ + "* e_crlc;\n" \ + "* e_cparhdr;\n" \ + "* e_minalloc;\n" \ + "* e_maxalloc;\n" \ + "* e_ss;\n" \ + "* e_sp;\n" \ + "* e_csum;\n" \ + "* e_ip;\n" \ + "* e_cs;\n" \ + "* e_lfarlc;\n" \ + "* e_ovno;\n" \ + "* e_res;\n" \ + "* e_oemid;\n" \ + "* e_oeminfo;\n" \ + "* e_res2;\n" \ + "* e_lfanew." \ +) + + format = G_PE_FORMAT(pygobject_get(self)); + + result = translate_pe_dos_header_to_python(format, g_pe_format_get_dos_header(format)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format en place à consulter. * +* closure = non utilisé ici. * +* * +* Description : Offre un raccourci vers les répertoires du format PE. * +* * +* Retour : Structure Python créée pour l'occasion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_format_get_directories(PyObject *self, void *closure) +{ + PyObject *result; /* Trouvaille à retourner */ + GPeFormat *format; /* Version GLib du format */ + size_t count; /* Quantité de répertoires */ + const image_data_directory *directories; /* Répertoires à exporter */ + size_t i; /* Boucle de parcours */ + PyObject *item; /* Elément de tableau */ + int ret; /* Bilan d'une mise en place */ + +#define PE_FORMAT_DIRECTORIES_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + directories, py_pe_format, \ + "Shortcut to the PE format directories.\n" \ + "\n" \ + "This property is a pychrysalide.StructObject instance and" \ + " can also be access trough the" \ + " *self.nt_headers.data_directory* attribute.\n" \ + "\n" \ + "Each returned item is composed of the following properties :\n"\ + "\n" \ + "* virtual_address;\n" \ + "* size." \ +) + + format = G_PE_FORMAT(pygobject_get(self)); + + directories = g_pe_format_get_directories(format, &count); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + item = translate_pe_image_data_directory_to_python(format, directories + i); + + ret = PyTuple_SetItem(result, i, item); + + if (ret != 0) + { + Py_DECREF(result); + result = NULL; + break; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format en place à consulter. * +* closure = non utilisé ici. * +* * +* Description : Présente l'en-tête enrichi du format chargé. * +* * +* Retour : Tableau de valeurs brutes d'information. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_format_get_rich_header(PyObject *self, void *closure) +{ + PyObject *result; /* Trouvaille à retourner */ + GPeFormat *format; /* Version GLib du format */ + size_t count; /* Quantité de valeurs obtenues*/ + uint64_t *values; /* Valeurs brutes à transcrire */ + size_t i; /* Boucle de parcours */ + +#define PE_FORMAT_RICH_HEADER_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + rich_header, py_pe_format, \ + "Raw values from the Rich header of the file format.\n" \ + "\n" \ + "This property is a tuple of 64-bit values or an empty" \ + " tuple if no Rich header exists in the PE file." \ +) + + format = G_PE_FORMAT(pygobject_get(self)); + + values = g_pe_format_get_rich_header(format, &count); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + PyTuple_SetItem(result, i, PyLong_FromUnsignedLongLong(values[i])); + + if (values != NULL) + free(values); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format en place à consulter. * +* closure = non utilisé ici. * +* * +* Description : Présente l'empreinte d'un en-tête enrichi du format chargé. * +* * +* Retour : Valeur de l'empreinte ou None en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_format_get_rich_header_checksum(PyObject *self, void *closure) +{ + PyObject *result; /* Trouvaille à retourner */ + GPeFormat *format; /* Version GLib du format */ + uint32_t checksum; /* Valeur à transcrire */ + bool status; /* Validité de cette valeur */ + +#define PE_FORMAT_RICH_HEADER_CHECKSUM_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + rich_header_checksum, py_pe_format, \ + "Checksum used as XOR value for the Rich header of the file" \ + " format.\n" \ + "\n" \ + "This property is a 32-bit integer value." \ +) + + format = G_PE_FORMAT(pygobject_get(self)); + + status = g_pe_format_get_rich_header_checksum(format, &checksum); + + if (status) + result = PyLong_FromUnsignedLong(checksum); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format en place à consulter. * +* closure = non utilisé ici. * +* * +* Description : Présente les identifiants contenues dans l'en-tête enrichi. * +* * +* Retour : Tableau de valeurs raffinées d'information. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_format_get_comp_ids(PyObject *self, void *closure) +{ + PyObject *result; /* Trouvaille à retourner */ + GPeFormat *format; /* Version GLib du format */ + size_t count; /* Quantité de valeurs obtenues*/ + comp_id_t *ids; /* Valeurs raffinées à émettre */ + size_t i; /* Boucle de parcours */ + +#define PE_FORMAT_COMP_IDS_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + comp_ids, py_pe_format, \ + "Compiler identifiers carried by the Rich header of the file" \ + " format.\n" \ + "\n" \ + "This property is a tuple of" \ + " pychrysalide.StructObject items or an empty tuple if no" \ + " information is found.\n" \ + "\n" \ + "Each item contains the the following properties :\n" \ + "\n" \ + "* minor_cv;\n" \ + "* prod_id;\n" \ + "* count." \ +) + + format = G_PE_FORMAT(pygobject_get(self)); + + ids = g_pe_format_get_comp_ids(format, &count); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + PyTuple_SetItem(result, i, translate_pe_comp_id_to_python(format, &ids[i])); + + if (ids != NULL) + free(ids); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_pe_format_type(void) +{ + static PyMethodDef py_pe_format_methods[] = { + { NULL } + }; + + static PyGetSetDef py_pe_format_getseters[] = { + PE_FORMAT_DOS_HEADER_ATTRIB, + PE_FORMAT_DIRECTORIES_ATTRIB, + PE_FORMAT_RICH_HEADER_ATTRIB, + PE_FORMAT_RICH_HEADER_CHECKSUM_ATTRIB, + PE_FORMAT_COMP_IDS_ATTRIB, + { NULL } + }; + + static PyTypeObject py_pe_format_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.pe.PeFormat", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = PE_FORMAT_DOC, + + .tp_methods = py_pe_format_methods, + .tp_getset = py_pe_format_getseters, + + .tp_init = py_pe_format_init, + .tp_new = py_pe_format_new, + + }; + + return &py_pe_format_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.pe.PeFormat'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_pe_format(PyObject *module) +{ + PyTypeObject *type; /* Type Python 'PeFormat' */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_pe_format_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_PE_FORMAT, type, get_python_executable_format_type())) + return false; + + if (!define_python_pe_format_constants(type)) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en format PE. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_pe_format(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_format_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE format"); + break; + + case 1: + *((GPeFormat **)dst) = G_PE_FORMAT(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pe/python/format.h b/plugins/pe/python/format.h new file mode 100644 index 0000000..4f52a61 --- /dev/null +++ b/plugins/pe/python/format.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * format.h - prototypes pour l'équivalent Python du fichier "plugins/pe/format.h" + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PE_PYTHON_FORMAT_H +#define _PLUGINS_PE_PYTHON_FORMAT_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_pe_format_type(void); + +/* Prend en charge l'objet 'pychrysalide.format.pe.PeFormat'. */ +bool register_python_pe_format(PyObject *); + +/* Tente de convertir en format PE. */ +int convert_to_pe_format(PyObject *, void *); + + + +#endif /* _PLUGINS_PE_PYTHON_FORMAT_H */ diff --git a/plugins/pe/python/module.c b/plugins/pe/python/module.c new file mode 100644 index 0000000..93b1337 --- /dev/null +++ b/plugins/pe/python/module.c @@ -0,0 +1,93 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire pe en tant que module + * + * Copyright (C) 2017-2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> +#include <plugins/pychrysalide/helpers.h> + + +#include "format.h" +#include "routine.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Ajoute le module 'format.pe' au module Python. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_format_pe_module_to_python_module(void) +{ + bool result; /* Bilan à retourner */ + PyObject *super; /* Module à compléter */ + PyObject *module; /* Sous-module mis en place */ + +#define PYCHRYSALIDE_FORMAT_PE_MODULE_DOC \ + "This module provides support for the Portable Executable file format" \ + " defined by Microsoft.\n" \ + "\n" \ + "The specification for this format can be found at:" \ + "\n" \ + "* https://web.archive.org/web/20081208121446/http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx" + + static PyModuleDef py_chrysalide_pe_module = { + + .m_base = PyModuleDef_HEAD_INIT, + + .m_name = "pychrysalide.format.pe", + .m_doc = PYCHRYSALIDE_FORMAT_PE_MODULE_DOC, + + .m_size = -1, + + }; + + result = false; + + super = get_access_to_python_module("pychrysalide.format"); + + module = build_python_module(super, &py_chrysalide_pe_module); + + result = (module != NULL); + + if (result) result = register_python_pe_format(module); + if (result) result = register_python_pe_exported_routine(module); + if (result) result = register_python_pe_imported_routine(module); + + assert(result); + + return result; + +} diff --git a/plugins/pe/python/module.h b/plugins/pe/python/module.h new file mode 100644 index 0000000..9e9b33a --- /dev/null +++ b/plugins/pe/python/module.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire pe en tant que module + * + * Copyright (C) 2017-2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PE_PYTHON_MODULE_H +#define _PLUGINS_PE_PYTHON_MODULE_H + + +#include <stdbool.h> + + + +/* Ajoute le module 'format.pe' au module Python. */ +bool add_format_pe_module_to_python_module(void); + + + +#endif /* _PLUGINS_PE_PYTHON_MODULE_H */ diff --git a/plugins/pe/python/routine.c b/plugins/pe/python/routine.c new file mode 100644 index 0000000..89075ea --- /dev/null +++ b/plugins/pe/python/routine.c @@ -0,0 +1,472 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * routine.c - équivalent Python du fichier "plugins/pe/routine.c" + * + * Copyright (C) 2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "routine.h" + + +#include <pygobject.h> + + +#include <i18n.h> +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/analysis/routine.h> + + +#include "constants.h" +#include "../routine.h" + + + +/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */ + + +#define PE_EXPORTED_ROUTINE_DOC \ + "The PeExportedRoutine is a definition of a binary routine" \ + " exported for other PE file." + + +/* Fournit l'indice de la routine dans un fichier PE. */ +static PyObject *py_pe_exported_routine_get_ordinal(PyObject *, void *); + +/* Définit l'indice de la routine dans un fichier PE. */ +static int py_pe_exported_routine_set_ordinal(PyObject *, PyObject *, void *); + + + +/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */ + + +#define PE_IMPORTED_ROUTINE_DOC \ + "The PeImportedRoutine is a definition of a binary routine" \ + " imported from other PE file symbol." + + +/* Fournit le fichier DLL visé par une importation de format PE. */ +static PyObject *py_pe_imported_routine_get_library(PyObject *, void *); + +/* Définit le fichier DLL visé par une importation de format PE. */ +static int py_pe_imported_routine_set_library(PyObject *, PyObject *, void *); + + + +/* ---------------------------------------------------------------------------------- */ +/* SYMBOLES D'UN FORMAT PE EXPORTES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit l'indice de la routine dans un fichier PE. * +* * +* Retour : Numéro de la routine. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_exported_routine_get_ordinal(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GPeExportedRoutine *routine; /* Version native */ + uint16_t ordinal; /* Valeur native de l'ordinal */ + +#define PE_EXPORTED_ROUTINE_ORDINAL_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + ordinal, py_pe_exported_routine, \ + "Ordinal number linked to the symbol.\n" \ + "\n" \ + "The returned integer value is valid only if" \ + " the pychrysalide.format.pe.PeRoutine.PeSymbolFlag.HAS_ORDINAL" \ + " bit is set in the symbol flags.\n" \ + "\n" \ + "This bit is automatically set when the value is defined." \ +) + + routine = G_PE_EXPORTED_ROUTINE(pygobject_get(self)); + + ordinal = g_pe_exported_routine_get_ordinal(routine); + + //result = cast_with_constants_group_from_type(get_python_pe_exported_routine_type(), "OrdinalValue", ordinal); + + result = PyLong_FromUnsignedLong(ordinal); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = adresse non utilisée ici. * +* * +* Description : Définit l'indice de la routine dans un fichier PE. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_pe_exported_routine_set_ordinal(PyObject *self, PyObject *value, void *closure) +{ + int ret; /* Bilan d'analyse */ + GPeExportedRoutine *routine; /* Version native */ + uint16_t ordinal; /* Valeur native de l'ordinal */ + + ret = PyObject_IsInstance(value, (PyObject *)&PyLong_Type); + if (!ret) return -1; + + routine = G_PE_EXPORTED_ROUTINE(pygobject_get(self)); + + ordinal = PyLong_AsUnsignedLong(value); + + g_pe_exported_routine_set_ordinal(routine, ordinal); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_pe_exported_routine_type(void) +{ + static PyMethodDef py_pe_exported_routine_methods[] = { + { NULL } + }; + + static PyGetSetDef py_pe_exported_routine_getseters[] = { + PE_EXPORTED_ROUTINE_ORDINAL_ATTRIB, + { NULL } + }; + + static PyTypeObject py_pe_exported_routine_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.pe.PeExportedRoutine", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = PE_EXPORTED_ROUTINE_DOC, + + .tp_methods = py_pe_exported_routine_methods, + .tp_getset = py_pe_exported_routine_getseters + + }; + + return &py_pe_exported_routine_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.pe.PeRoutine'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_pe_exported_routine(PyObject *module) +{ + PyTypeObject *type; /* Type Python 'PeRoutine' */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_pe_exported_routine_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_PE_EXPORTED_ROUTINE, type, get_python_binary_routine_type())) + return false; + + if (!define_python_pe_exported_routine_constants(type)) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en routine de fichier PE. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_pe_exported_routine(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_exported_routine_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE exported routine"); + break; + + case 1: + *((GPeExportedRoutine **)dst) = G_PE_EXPORTED_ROUTINE(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* SYMBOLES D'UN FORMAT PE IMPORTES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit le fichier DLL visé par une importation de format PE.* +* * +* Retour : Désignation d'une bibliothèque Windows. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_pe_imported_routine_get_library(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GPeImportedRoutine *routine; /* Version native */ + const char *library; /* Nom de bibliothèque */ + +#define PE_IMPORTED_ROUTINE_ORDINAL_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + library, py_pe_imported_routine, \ + "Imported DLL's name for the symbol.\n" \ + "\n" \ + "The returned value is a string." \ +) + + routine = G_PE_IMPORTED_ROUTINE(pygobject_get(self)); + + library = g_pe_imported_routine_get_library(routine); + + result = PyUnicode_FromString(library); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = adresse non utilisée ici. * +* * +* Description : Définit le fichier DLL visé par une importation de format PE.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_pe_imported_routine_set_library(PyObject *self, PyObject *value, void *closure) +{ + GPeImportedRoutine *routine; /* Version native */ + + if (!PyUnicode_Check(value) && value != Py_None) + { + PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string or None.")); + return -1; + } + + routine = G_PE_IMPORTED_ROUTINE(pygobject_get(self)); + + if (value == Py_None) + g_pe_imported_routine_set_library(routine, NULL); + else + g_pe_imported_routine_set_library(routine, strdup(PyUnicode_DATA(value))); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_pe_imported_routine_type(void) +{ + static PyMethodDef py_pe_imported_routine_methods[] = { + { NULL } + }; + + static PyGetSetDef py_pe_imported_routine_getseters[] = { + PE_IMPORTED_ROUTINE_ORDINAL_ATTRIB, + { NULL } + }; + + static PyTypeObject py_pe_imported_routine_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.pe.PeImportedRoutine", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = PE_IMPORTED_ROUTINE_DOC, + + .tp_methods = py_pe_imported_routine_methods, + .tp_getset = py_pe_imported_routine_getseters + + }; + + return &py_pe_imported_routine_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.pe.PeRoutine'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_pe_imported_routine(PyObject *module) +{ + PyTypeObject *type; /* Type Python 'PeRoutine' */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_pe_imported_routine_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_PE_IMPORTED_ROUTINE, type, get_python_pe_exported_routine_type())) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en routine de fichier PE. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_pe_imported_routine(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_pe_imported_routine_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to PE imported routine"); + break; + + case 1: + *((GPeImportedRoutine **)dst) = G_PE_IMPORTED_ROUTINE(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pe/python/routine.h b/plugins/pe/python/routine.h new file mode 100644 index 0000000..71cb085 --- /dev/null +++ b/plugins/pe/python/routine.h @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * routine.h - prototypes pour l'équivalent Python du fichier "plugins/pe/routine.h" + * + * Copyright (C) 2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PE_PYTHON_ROUTINE_H +#define _PLUGINS_PE_PYTHON_ROUTINE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* ------------------------ SYMBOLES D'UN FORMAT PE EXPORTES ------------------------ */ + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_pe_exported_routine_type(void); + +/* Prend en charge l'objet 'pychrysalide.format.pe.PeExportedRoutine'. */ +bool register_python_pe_exported_routine(PyObject *); + +/* Tente de convertir en routine de fichier PE. */ +int convert_to_pe_exported_routine(PyObject *, void *); + + + +/* ------------------------ SYMBOLES D'UN FORMAT PE IMPORTES ------------------------ */ + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_pe_imported_routine_type(void); + +/* Prend en charge l'objet 'pychrysalide.format.pe.PeImportedRoutine'. */ +bool register_python_pe_imported_routine(PyObject *); + +/* Tente de convertir en routine de fichier PE. */ +int convert_to_pe_imported_routine(PyObject *, void *); + + + +#endif /* _PLUGINS_PE_PYTHON_ROUTINE_H */ diff --git a/plugins/pe/python/translate.c b/plugins/pe/python/translate.c new file mode 100644 index 0000000..c01a337 --- /dev/null +++ b/plugins/pe/python/translate.c @@ -0,0 +1,213 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * translate.c - conversion de structures PE en objets Python + * + * Copyright (C) 2020 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "translate.h" + + +#include <assert.h> + + +#include <plugins/pychrysalide/struct.h> + + + +/****************************************************************************** +* * +* Paramètres : format = format PE chargé sur lequel s'appuyer. * +* header = en-tête MS-DOS à décrire en Python. * +* * +* Description : Traduit un en-tête MS-DOS en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_pe_dos_header_to_python(GPeFormat *format, const image_dos_header *header) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + size_t i; /* Boucle de parcours */ + PyObject *item; /* Elément de tableau */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + +#define TRANSLATE_DOS_HEADER_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(header->e_ ## _f); \ + ret = PyDict_SetItemString(result, "e_" #_f, attrib); \ + if (ret != 0) goto failed; \ + } \ + while (0); + +#define TRANSLATE_DOS_HEADER_FIELD_ARRAY(_f, _n) \ + do \ + { \ + attrib = PyTuple_New(_n); \ + ret = 0; \ + for (i = 0; i < _n; i++) \ + { \ + item = PyLong_FromUnsignedLongLong(header->e_ ## _f [i]); \ + ret = PyTuple_SetItem(attrib, i, item); \ + if (ret != 0) break; \ + } \ + if (ret != 0) goto failed; \ + ret = PyDict_SetItemString(result, "e_" #_f, attrib); \ + if (ret != 0) goto failed; \ + } \ + while (0); + + TRANSLATE_DOS_HEADER_FIELD(magic); + TRANSLATE_DOS_HEADER_FIELD(cblp); + TRANSLATE_DOS_HEADER_FIELD(cp); + TRANSLATE_DOS_HEADER_FIELD(crlc); + TRANSLATE_DOS_HEADER_FIELD(cparhdr); + TRANSLATE_DOS_HEADER_FIELD(minalloc); + TRANSLATE_DOS_HEADER_FIELD(maxalloc); + TRANSLATE_DOS_HEADER_FIELD(ss); + TRANSLATE_DOS_HEADER_FIELD(sp); + TRANSLATE_DOS_HEADER_FIELD(csum); + TRANSLATE_DOS_HEADER_FIELD(ip); + TRANSLATE_DOS_HEADER_FIELD(cs); + TRANSLATE_DOS_HEADER_FIELD(lfarlc); + TRANSLATE_DOS_HEADER_FIELD(ovno); + TRANSLATE_DOS_HEADER_FIELD_ARRAY(res, 4); + TRANSLATE_DOS_HEADER_FIELD(oemid); + TRANSLATE_DOS_HEADER_FIELD(oeminfo); + TRANSLATE_DOS_HEADER_FIELD_ARRAY(res2, 10); + TRANSLATE_DOS_HEADER_FIELD(lfanew); + + return result; + + failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format PE chargé sur lequel s'appuyer. * +* dir = répertoire PE à décrire en Python. * +* * +* Description : Traduit un répertoire PE en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_pe_image_data_directory_to_python(GPeFormat *format, const image_data_directory *dir) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + +#define TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(dir->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + if (ret != 0) goto failed; \ + } \ + while (0); + + TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(virtual_address); + TRANSLATE_IMAGE_DATA_DIRECTORY_FIELD(size); + + return result; + + failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format PE chargé sur lequel s'appuyer. * +* id = ensemble d'informations à décrire en Python. * +* * +* Description : Traduit une série d'informations enrichies en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_pe_comp_id_to_python(GPeFormat *format, const comp_id_t *id) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + +#define TRANSLATE_COMP_ID_VALUE(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(id->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + if (ret != 0) goto failed; \ + } \ + while (0); + + TRANSLATE_COMP_ID_VALUE(minor_cv); + TRANSLATE_COMP_ID_VALUE(prod_id); + TRANSLATE_COMP_ID_VALUE(count); + + return result; + + failed: + + Py_DECREF(result); + + return NULL; + +} diff --git a/plugins/pe/python/translate.h b/plugins/pe/python/translate.h new file mode 100644 index 0000000..dbde6c8 --- /dev/null +++ b/plugins/pe/python/translate.h @@ -0,0 +1,48 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * translate.h - prototypes pour la conversion de structures PE en objets Python + * + * Copyright (C) 2020 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PE_PYTHON_TRANSLATE_H +#define _PLUGINS_PE_PYTHON_TRANSLATE_H + + +#include <Python.h> + + +#include "../format.h" +#include "../rich.h" + + + +/* Traduit un en-tête MS-DOS en Python. */ +PyObject *translate_pe_dos_header_to_python(GPeFormat *, const image_dos_header *); + +/* Traduit un répertoire PE en Python. */ +PyObject *translate_pe_image_data_directory_to_python(GPeFormat *, const image_data_directory *); + +/* Traduit une série d'informations enrichies en Python. */ +PyObject *translate_pe_comp_id_to_python(GPeFormat *, const comp_id_t *); + + + +#endif /* _PLUGINS_PE_PYTHON_TRANSLATE_H */ |