From e0ab9498f78ee6b4fbbba25400d78436db682899 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 31 Dec 2017 14:42:25 +0100 Subject: Provided access to Elf structures from Python. --- ChangeLog | 30 +++ plugins/elf/elf_def.h | 1 - plugins/elf/python/Makefile.am | 5 +- plugins/elf/python/format.c | 68 ++++++ plugins/elf/python/program.c | 119 ++++++++++ plugins/elf/python/program.h | 41 ++++ plugins/elf/python/section.c | 210 ++++++++++++++++++ plugins/elf/python/section.h | 47 ++++ plugins/elf/python/translate.c | 478 +++++++++++++++++++++++++++++++++++++++++ plugins/elf/python/translate.h | 59 +++++ plugins/pychrysa/Makefile.am | 1 + plugins/pychrysa/pychrysa.c | 5 +- plugins/pychrysa/struct.c | 161 ++++++++++++++ plugins/pychrysa/struct.h | 42 ++++ 14 files changed, 1264 insertions(+), 3 deletions(-) create mode 100644 plugins/elf/python/program.c create mode 100644 plugins/elf/python/program.h create mode 100644 plugins/elf/python/section.c create mode 100644 plugins/elf/python/section.h create mode 100644 plugins/elf/python/translate.c create mode 100644 plugins/elf/python/translate.h create mode 100644 plugins/pychrysa/struct.c create mode 100644 plugins/pychrysa/struct.h diff --git a/ChangeLog b/ChangeLog index fd451b2..41fb56a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +17-12-31 Cyrille Bagard + + * plugins/elf/elf_def.h: + Typo. + + * plugins/elf/python/Makefile.am: + Add the 'program.[ch]', 'section.[ch]' and 'translate.[ch]' files to + libelfpython_la_SOURCES. + + * plugins/elf/python/format.c: + Provide access to Elf structures from Python. Update the Python bindings. + + * plugins/elf/python/program.c: + * plugins/elf/python/program.h: + * plugins/elf/python/section.c: + * plugins/elf/python/section.h: + * plugins/elf/python/translate.c: + * plugins/elf/python/translate.h: + New entries: provide access to Elf structures from Python. + + * plugins/pychrysa/Makefile.am: + Add the 'struct.[ch]' files to pychrysalide_la_SOURCES. + + * plugins/pychrysa/pychrysa.c: + Update code. + + * plugins/pychrysa/struct.c: + * plugins/pychrysa/struct.h: + New entries: create a generic object providing dynamic fields. + 17-12-29 Cyrille Bagard * plugins/ropgadgets/select.c: diff --git a/plugins/elf/elf_def.h b/plugins/elf/elf_def.h index 8c2bb45..06adff7 100644 --- a/plugins/elf/elf_def.h +++ b/plugins/elf/elf_def.h @@ -243,7 +243,6 @@ typedef union _elf_header /* Version 32 et 64 bits */ - typedef struct _elf32_phdr { uint32_t p_type; /* Type de segment */ diff --git a/plugins/elf/python/Makefile.am b/plugins/elf/python/Makefile.am index bcb739e..6080e86 100644 --- a/plugins/elf/python/Makefile.am +++ b/plugins/elf/python/Makefile.am @@ -5,7 +5,10 @@ libelfpython_la_SOURCES = \ constants.h constants.c \ dynamic.h dynamic.c \ format.h format.c \ - module.h module.c + module.h module.c \ + program.h program.c \ + section.h section.c \ + translate.h translate.c libelfpython_la_LDFLAGS = diff --git a/plugins/elf/python/format.c b/plugins/elf/python/format.c index a5e93d7..f1cf8d6 100644 --- a/plugins/elf/python/format.c +++ b/plugins/elf/python/format.c @@ -38,6 +38,9 @@ #include "constants.h" #include "dynamic.h" +#include "program.h" +#include "section.h" +#include "translate.h" #include "../format.h" @@ -45,6 +48,9 @@ /* Crée un nouvel objet Python de type 'ElfFormat'. */ static PyObject *py_elf_format_new(PyTypeObject *, PyObject *, PyObject *); +/* Fournit l'en-tête Elf correspondant au format. */ +static PyObject *py_elf_format_get_header(PyObject *, PyObject *); + /****************************************************************************** @@ -138,6 +144,33 @@ static PyObject *py_elf_format_new(PyTypeObject *type, PyObject *args, PyObject /****************************************************************************** * * +* Paramètres : self = contenu binaire à manipuler. * +* args = argument non utilisé ici. * +* * +* Description : Fournit l'en-tête Elf correspondant au format. * +* * +* Retour : Structure Python créée pour l'occasion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_elf_format_get_header(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvaille à retourner */ + GElfFormat *format; /* Version GLib du format */ + + format = G_ELF_FORMAT(pygobject_get(self)); + + result = translate_elf_header_to_python(format, g_elf_format_get_header(format)); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -151,6 +184,41 @@ static PyObject *py_elf_format_new(PyTypeObject *type, PyObject *args, PyObject PyTypeObject *get_python_elf_format_type(void) { static PyMethodDef py_elf_format_methods[] = { + { + "get_header", py_elf_format_get_header, + METH_NOARGS, + "get_header($self, /)\n--\n\nGet the Elf header." + }, + { + "find_program_by_index", py_elf_format_find_program_by_index, + METH_VARARGS, + "find_program_by_index($self, index, /)\n--\n\nFind a segment using a given index." + }, + { + "find_program_by_type", py_elf_format_find_program_by_type, + METH_VARARGS, + "find_program_by_type($self, type, /)\n--\n\nFind a segment using a given type." + }, + { + "find_section_by_index", py_elf_format_find_section_by_index, + METH_VARARGS, + "find_section_by_index($self, index, /)\n--\n\nFind a section using a given index." + }, + { + "find_section_by_name", py_elf_format_find_section_by_name, + METH_VARARGS, + "find_section_by_name($self, name, /)\n--\n\nFind a section using a given name." + }, + { + "find_section_by_virtual_address", py_elf_format_find_section_by_virtual_address, + METH_VARARGS, + "find_section_by_virtual_address($self, addr, /)\n--\n\nFind a section using a given virtual address." + }, + { + "find_sections_by_type", py_elf_format_find_sections_by_type, + METH_VARARGS, + "find_sections_by_type($self, type, /)\n--\n\nFind sections using a given type." + }, { NULL } }; diff --git a/plugins/elf/python/program.c b/plugins/elf/python/program.c new file mode 100644 index 0000000..198a76b --- /dev/null +++ b/plugins/elf/python/program.c @@ -0,0 +1,119 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * program.c - prototypes pour l'équivalent Python du fichier "plugins/elf/program.c" + * + * 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 + */ + + +#include "program.h" + + +#include + + +#include "translate.h" +#include "../program.h" + + + +/****************************************************************************** +* * +* Paramètres : self = format Elf à manipuler. * +* args = indice du segment visé. * +* * +* Description : Retrouve un segment par son indice. * +* * +* Retour : Elément trouvé ou rien (None). * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *py_elf_format_find_program_by_index(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvaille à retourner */ + GElfFormat *format; /* Version GLib du format */ + unsigned short int index; /* Indice du segment visé */ + int ret; /* Bilan de lecture des args. */ + elf_phdr program; /* Informations remontées */ + bool found; /* Recherches concluantes ? */ + + format = G_ELF_FORMAT(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "H", &index); + if (!ret) return NULL; + + found = find_elf_program_by_index(format, index, &program); + + if (found) + result = translate_elf_program_to_python(format, &program); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format Elf à manipuler. * +* args = type du segment visé. * +* * +* Description : Retrouve un segment par son type. * +* * +* Retour : Elément trouvé ou rien (None). * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *py_elf_format_find_program_by_type(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvaille à retourner */ + GElfFormat *format; /* Version GLib du format */ + unsigned int type; /* Type de segment visé */ + int ret; /* Bilan de lecture des args. */ + elf_phdr program; /* Informations remontées */ + bool found; /* Recherches concluantes ? */ + + format = G_ELF_FORMAT(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "I", &type); + if (!ret) return NULL; + + found = find_elf_program_by_type(format, type, &program); + + if (found) + result = translate_elf_program_to_python(format, &program); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} diff --git a/plugins/elf/python/program.h b/plugins/elf/python/program.h new file mode 100644 index 0000000..20736c9 --- /dev/null +++ b/plugins/elf/python/program.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * program.h - prototypes pour l'équivalent Python du fichier "plugins/elf/program.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_ELF_PYTHON_PROGRAM_H +#define _PLUGINS_ELF_PYTHON_PROGRAM_H + + +#include + + + +/* Retrouve un segment par son indice. */ +PyObject *py_elf_format_find_program_by_index(PyObject *, PyObject *); + +/* Retrouve un segment par son type. */ +PyObject *py_elf_format_find_program_by_type(PyObject *, PyObject *); + + + +#endif /* _PLUGINS_ELF_PYTHON_PROGRAM_H */ diff --git a/plugins/elf/python/section.c b/plugins/elf/python/section.c new file mode 100644 index 0000000..537babc --- /dev/null +++ b/plugins/elf/python/section.c @@ -0,0 +1,210 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * section.c - prototypes pour l'équivalent Python du fichier "plugins/elf/section.c" + * + * 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 + */ + + +#include "section.h" + + +#include +#include + + +#include "translate.h" +#include "../section.h" + + + +/****************************************************************************** +* * +* Paramètres : self = format Elf à manipuler. * +* args = indice de la section visée. * +* * +* Description : Retrouve une section par son indice. * +* * +* Retour : Elément trouvé ou rien (None). * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *py_elf_format_find_section_by_index(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvaille à retourner */ + GElfFormat *format; /* Version GLib du format */ + unsigned short int index; /* Indice de section visée */ + int ret; /* Bilan de lecture des args. */ + elf_shdr section; /* Informations remontées */ + bool found; /* Recherches concluantes ? */ + + format = G_ELF_FORMAT(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "H", &index); + if (!ret) return NULL; + + found = find_elf_section_by_index(format, index, §ion); + + if (found) + result = translate_elf_section_to_python(format, §ion); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format Elf à manipuler. * +* args = désignation de la section visée. * +* * +* Description : Retrouve une section par son nom. * +* * +* Retour : Elément trouvé ou rien (None). * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *py_elf_format_find_section_by_name(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvaille à retourner */ + GElfFormat *format; /* Version GLib du format */ + PyObject *name; /* Etiquette à retrouver */ + int ret; /* Bilan de lecture des args. */ + elf_shdr section; /* Informations remontées */ + bool found; /* Recherches concluantes ? */ + + format = G_ELF_FORMAT(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "O!", &PyUnicode_Type, &name); + if (!ret) return NULL; + + found = find_elf_section_by_name(format, PyUnicode_DATA(name), §ion); + + if (found) + result = translate_elf_section_to_python(format, §ion); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format Elf à manipuler. * +* args = adresse en mémoire de la section visée. * +* * +* Description : Retrouve une section par son adresse en mémoire. * +* * +* Retour : Elément trouvé ou rien (None). * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *py_elf_format_find_section_by_virtual_address(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvaille à retourner */ + GElfFormat *format; /* Version GLib du format */ + unsigned long long addr; /* Adresse en mémoire virtuelle*/ + int ret; /* Bilan de lecture des args. */ + elf_shdr section; /* Informations remontées */ + bool found; /* Recherches concluantes ? */ + + format = G_ELF_FORMAT(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "K", &addr); + if (!ret) return NULL; + + found = find_elf_section_by_virtual_address(format, addr, §ion); + + if (found) + result = translate_elf_section_to_python(format, §ion); + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = format Elf à manipuler. * +* args = type des sections visées. * +* * +* Description : Retrouve des sections par leur type. * +* * +* Retour : Liste d'éléments trouvés, éventuellement vide. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *py_elf_format_find_sections_by_type(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvaille à retourner */ + GElfFormat *format; /* Version GLib du format */ + unsigned int type; /* Type de section visée */ + int ret; /* Bilan de lecture des args. */ + elf_shdr *sections; /* Liste des sections trouvées */ + size_t count; /* Taille de cette liste */ + size_t i; /* Boucle de parcours */ + PyObject *section; /* Traduction d'une section */ + + format = G_ELF_FORMAT(pygobject_get(self)); + + ret = PyArg_ParseTuple(args, "I", &type); + if (!ret) return NULL; + + find_elf_sections_by_type(format, type, §ions, &count); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + section = translate_elf_section_to_python(format, §ions[i]); + PyTuple_SetItem(result, i, section); + } + + if (sections != NULL) + free(sections); + + return result; + +} diff --git a/plugins/elf/python/section.h b/plugins/elf/python/section.h new file mode 100644 index 0000000..f5cc402 --- /dev/null +++ b/plugins/elf/python/section.h @@ -0,0 +1,47 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * section.h - prototypes pour l'équivalent Python du fichier "plugins/elf/section.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_ELF_PYTHON_SECTION_H +#define _PLUGINS_ELF_PYTHON_SECTION_H + + +#include + + + +/* Retrouve une section par son indice. */ +PyObject *py_elf_format_find_section_by_index(PyObject *, PyObject *); + +/* Retrouve une section par son nom. */ +PyObject *py_elf_format_find_section_by_name(PyObject *, PyObject *); + +/* Retrouve une section par son adresse en mémoire. */ +PyObject *py_elf_format_find_section_by_virtual_address(PyObject *, PyObject *); + +/* Retrouve des sections par leur type. */ +PyObject *py_elf_format_find_sections_by_type(PyObject *, PyObject *); + + + +#endif /* _PLUGINS_ELF_PYTHON_SECTION_H */ diff --git a/plugins/elf/python/translate.c b/plugins/elf/python/translate.c new file mode 100644 index 0000000..2450e1a --- /dev/null +++ b/plugins/elf/python/translate.c @@ -0,0 +1,478 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * translate.c - conversion de structures ELF en objets Python + * + * 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 + */ + + +#include "translate.h" + + +#include + + +#include + + +#include "../elf-int.h" +#include "../section.h" + + + +/****************************************************************************** +* * +* Paramètres : format = format Elf chargé sur lequel s'appuyer. * +* header = en-tête Elf à décrire en Python. * +* * +* Description : Traduit un en-tête Elf en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_elf_header_to_python(GElfFormat *format, const elf_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 */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Signature et propriétés générales */ + + attrib = PyByteArray_FromStringAndSize((char *)ELF_HDR(format, *header, e_ident), EI_NIDENT); + + ret = PyDict_SetItemString(result, "e_ident", attrib); + if (ret != 0) goto tehtp_failed; + + /* Champs réguliers */ + +#define TRANSLATE_HEADER_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(ELF_HDR(format, *header, e_ ## _f)); \ + ret = PyDict_SetItemString(result, "e_" #_f, attrib); \ + if (ret != 0) goto tehtp_failed; \ + } \ + while (0); + + TRANSLATE_HEADER_FIELD(type); + TRANSLATE_HEADER_FIELD(machine); + TRANSLATE_HEADER_FIELD(version); + TRANSLATE_HEADER_FIELD(entry); + TRANSLATE_HEADER_FIELD(phoff); + TRANSLATE_HEADER_FIELD(shoff); + TRANSLATE_HEADER_FIELD(flags); + TRANSLATE_HEADER_FIELD(ehsize); + TRANSLATE_HEADER_FIELD(phentsize); + TRANSLATE_HEADER_FIELD(phnum); + TRANSLATE_HEADER_FIELD(shentsize); + TRANSLATE_HEADER_FIELD(shnum); + TRANSLATE_HEADER_FIELD(shstrndx); + + return result; + + tehtp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format Elf chargé sur lequel s'appuyer. * +* program = segment Elf à décrire en Python. * +* * +* Description : Traduit un segment Elf en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_elf_program_to_python(GElfFormat *format, const elf_phdr *program) +{ + 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_PROGRAM_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(ELF_PHDR(format, *program, p_ ## _f)); \ + ret = PyDict_SetItemString(result, "p_" #_f, attrib); \ + if (ret != 0) goto teptp_failed; \ + } \ + while (0); + + TRANSLATE_PROGRAM_FIELD(type); + TRANSLATE_PROGRAM_FIELD(offset); + TRANSLATE_PROGRAM_FIELD(vaddr); + TRANSLATE_PROGRAM_FIELD(paddr); + TRANSLATE_PROGRAM_FIELD(filesz); + TRANSLATE_PROGRAM_FIELD(memsz); + TRANSLATE_PROGRAM_FIELD(flags); + TRANSLATE_PROGRAM_FIELD(align); + + return result; + + teptp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format Elf chargé sur lequel s'appuyer. * +* section = section Elf à décrire en Python. * +* * +* Description : Traduit une section Elf en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_elf_section_to_python(GElfFormat *format, const elf_shdr *section) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + elf_shdr strings; /* Section des descriptions */ + const char *name; /* Nom d'une section analysée */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Champs réguliers */ + +#define TRANSLATE_SECTION_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(ELF_SHDR(format, *section, sh_ ## _f)); \ + ret = PyDict_SetItemString(result, "sh_" #_f, attrib); \ + if (ret != 0) goto testp_failed; \ + } \ + while (0); + + TRANSLATE_SECTION_FIELD(name); + TRANSLATE_SECTION_FIELD(type); + TRANSLATE_SECTION_FIELD(flags); + TRANSLATE_SECTION_FIELD(addr); + TRANSLATE_SECTION_FIELD(offset); + TRANSLATE_SECTION_FIELD(size); + TRANSLATE_SECTION_FIELD(link); + TRANSLATE_SECTION_FIELD(info); + TRANSLATE_SECTION_FIELD(addralign); + TRANSLATE_SECTION_FIELD(entsize); + + /* Liberté supplémentaire */ + + if (find_elf_section_by_index(format, ELF_HDR(format, format->header, e_shstrndx), &strings)) + { + name = extract_name_from_elf_string_section(format, &strings, + ELF_SHDR(format, *section, sh_name)); + + if (name == NULL) + { + attrib = Py_None; + Py_INCREF(attrib); + } + + else + attrib = PyUnicode_FromString(name); + + ret = PyDict_SetItemString(result, "name", attrib); + if (ret != 0) goto testp_failed; + + } + + return result; + + testp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format Elf chargé sur lequel s'appuyer. * +* dyn = information du dynamisme Elf à décrire en Python. * +* * +* Description : Traduit une information du dynamisme Elf en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_elf_dyn_to_python(GElfFormat *format, const elf_dyn *dyn) +{ + 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_DYN_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(ELF_DYN(format, *dyn, d_ ## _f)); \ + ret = PyDict_SetItemString(result, "d_" #_f, attrib); \ + if (ret != 0) goto tedtp_failed; \ + } \ + while (0); + + TRANSLATE_DYN_FIELD(tag); + TRANSLATE_DYN_FIELD(un.d_val); + TRANSLATE_DYN_FIELD(un.d_ptr); + + return result; + + tedtp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format Elf chargé sur lequel s'appuyer. * +* symbol = symbole Elf à décrire en Python. * +* * +* Description : Traduit un symbole Elf en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_elf_symbol_to_python(GElfFormat *format, const elf_sym *symbol) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + elf_shdr strings; /* Section des descriptions */ + const char *name; /* Nom d'une section analysée */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Champs réguliers */ + +#define TRANSLATE_SYMBOL_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(ELF_SYM(format, *symbol, st_ ## _f)); \ + ret = PyDict_SetItemString(result, "st_" #_f, attrib); \ + if (ret != 0) goto testp_failed; \ + } \ + while (0); + + TRANSLATE_SYMBOL_FIELD(name); + TRANSLATE_SYMBOL_FIELD(value); + TRANSLATE_SYMBOL_FIELD(size); + TRANSLATE_SYMBOL_FIELD(info); + TRANSLATE_SYMBOL_FIELD(other); + TRANSLATE_SYMBOL_FIELD(shndx); + + /* Liberté supplémentaire */ + + if (find_elf_section_by_index(format, ELF_HDR(format, format->header, e_shstrndx), &strings)) + { + name = extract_name_from_elf_string_section(format, &strings, + ELF_SYM(format, *symbol, st_name)); + + if (name == NULL) + { + attrib = Py_None; + Py_INCREF(attrib); + } + + else + attrib = PyUnicode_FromString(name); + + ret = PyDict_SetItemString(result, "name", attrib); + if (ret != 0) goto testp_failed; + + } + + return result; + + testp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format Elf chargé sur lequel s'appuyer. * +* rel = relocalisation Elf à décrire en Python. * +* * +* Description : Traduit une information de relocalisation Elf en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_elf_rel_to_python(GElfFormat *format, const elf_rel *rel) +{ + 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_REL_FIELD(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(ELF_REL(format, *rel, r_ ## _f)); \ + ret = PyDict_SetItemString(result, "r_" #_f, attrib); \ + if (ret != 0) goto tertp_failed; \ + } \ + while (0); + + TRANSLATE_REL_FIELD(offset); + TRANSLATE_REL_FIELD(info); + + return result; + + tertp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format Elf chargé sur lequel s'appuyer. * +* note = note Elf à décrire en Python. * +* * +* Description : Traduit une note Elf en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_elf_note_to_python(GElfFormat *format, const elf_note *note) +{ + 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); + + attrib = PyLong_FromUnsignedLongLong(note->type); + + ret = PyDict_SetItemString(result, "type", attrib); + if (ret != 0) goto tentp_failed; + + if (note->name == NULL) + { + attrib = Py_None; + Py_INCREF(attrib); + } + + else + attrib = PyUnicode_FromString(note->name); + + ret = PyDict_SetItemString(result, "name", attrib); + if (ret != 0) goto tentp_failed; + + if (note->desc == NULL) + { + attrib = Py_None; + Py_INCREF(attrib); + } + + else + attrib = PyUnicode_FromString(note->desc); + + ret = PyDict_SetItemString(result, "desc", attrib); + if (ret != 0) goto tentp_failed; + + return result; + + tentp_failed: + + Py_DECREF(result); + + return NULL; + +} diff --git a/plugins/elf/python/translate.h b/plugins/elf/python/translate.h new file mode 100644 index 0000000..02ddf2d --- /dev/null +++ b/plugins/elf/python/translate.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * translate.h - prototypes pour la conversion de structures ELF en objets Python + * + * 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_ELF_PYTHON_TRANSLATE_H +#define _PLUGINS_ELF_PYTHON_TRANSLATE_H + + +#include + + +#include "../format.h" + + + +/* Traduit un en-tête Elf en Python. */ +PyObject *translate_elf_header_to_python(GElfFormat *, const elf_header *); + +/* Traduit un segment Elf en Python. */ +PyObject *translate_elf_program_to_python(GElfFormat *, const elf_phdr *); + +/* Traduit une section Elf en Python. */ +PyObject *translate_elf_section_to_python(GElfFormat *, const elf_shdr *); + +/* Traduit une information du dynamisme Elf en Python. */ +PyObject *translate_elf_dyn_to_python(GElfFormat *, const elf_dyn *); + +/* Traduit un symbole Elf en Python. */ +PyObject *translate_elf_symbol_to_python(GElfFormat *, const elf_sym *); + +/* Traduit une information de relocalisation Elf en Python. */ +PyObject *translate_elf_rel_to_python(GElfFormat *, const elf_rel *); + +/* Traduit une note Elf en Python. */ +PyObject *translate_elf_note_to_python(GElfFormat *, const elf_note *); + + + +#endif /* _PLUGINS_ELF_PYTHON_TRANSLATE_H */ diff --git a/plugins/pychrysa/Makefile.am b/plugins/pychrysa/Makefile.am index e8c2bed..0648bb3 100644 --- a/plugins/pychrysa/Makefile.am +++ b/plugins/pychrysa/Makefile.am @@ -8,6 +8,7 @@ pychrysalide_la_SOURCES = \ helpers.h helpers.c \ plugin.h plugin.c \ pychrysa.h pychrysa.c \ + struct.h struct.c \ weak.h weak.c pychrysalide_la_LIBADD = \ diff --git a/plugins/pychrysa/pychrysa.c b/plugins/pychrysa/pychrysa.c index 7629132..35d14f4 100644 --- a/plugins/pychrysa/pychrysa.c +++ b/plugins/pychrysa/pychrysa.c @@ -45,6 +45,7 @@ #include "helpers.h" #include "plugin.h" +#include "struct.h" #include "analysis/module.h" #include "arch/module.h" #include "common/module.h" @@ -386,8 +387,10 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) result = PyModule_Create(&py_chrysalide_module); + status = register_python_py_struct(result); + /* Interface 'LineGenerator' en premier... */ - status = add_glibext_module_to_python_module(result); + if (status) status = add_glibext_module_to_python_module(result); /* BinRoutine hérite de BinSymbol... */ if (status) status = add_format_module_to_python_module(result); diff --git a/plugins/pychrysa/struct.c b/plugins/pychrysa/struct.c new file mode 100644 index 0000000..33b58b8 --- /dev/null +++ b/plugins/pychrysa/struct.c @@ -0,0 +1,161 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * struct.c - prototypes pour la conversion de structures C en équivalent Python + * + * 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 + */ + + +#include "struct.h" + + + +/* Objet à vocation abstraite */ +typedef struct _PyStructObject +{ + PyDictObject base; /* A laisser en premier */ + +} PyStructObject; + + +/* Assure l'encadrement des accès aux champs d'une structure. */ +static PyObject *py_struct_getattr(PyObject *, char *); + + + +/****************************************************************************** +* * +* Paramètres : self = structure C convertie en Python. * +* name = nom du champ auquel un accès est demandé. * +* * +* Description : Assure l'encadrement des accès aux champs d'une structure. * +* * +* Retour : Valeur du champ demandé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_struct_getattr(PyObject *self, char *name) +{ + PyObject *result; /* Elément à retourner */ + PyObject *w; /* Conversion du nom de champ */ + PyTypeObject *tp; /* Type de l'objet manipulé */ + + result = PyDict_GetItemString(self, name); + + if (result != NULL) + Py_INCREF(result); + + else + { + w = PyUnicode_InternFromString(name); + if (w == NULL) return NULL; + + tp = Py_TYPE(self); + + if (tp->tp_base->tp_getattro != NULL) + result = tp->tp_base->tp_getattro(self, w); + + Py_DECREF(w); + + } + + 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_py_struct_type(void) +{ + static PyMethodDef py_struct_methods[] = { + { NULL } + }; + + static PyGetSetDef py_struct_getseters[] = { + { NULL } + }; + + static PyTypeObject py_struct_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.PyStructObject", + .tp_basicsize = sizeof(PyStructObject), + + .tp_getattr = py_struct_getattr, + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = "PyChrysalide structure", + + .tp_methods = py_struct_methods, + .tp_getset = py_struct_getseters, + .tp_base = &PyDict_Type, + + }; + + return &py_struct_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.PyStructObject'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_py_struct(PyObject *module) +{ + PyTypeObject *py_struct_type; /* Type Python 'PyStructObject'*/ + int ret; /* Bilan des préparatifs */ + + py_struct_type = get_python_py_struct_type(); + + ret = PyType_Ready(py_struct_type); + + if (ret != 0) + return false; + + Py_INCREF(py_struct_type); + + PyModule_AddObject(module, "PyStructObject", (PyObject *)py_struct_type);; + + return true; + +} diff --git a/plugins/pychrysa/struct.h b/plugins/pychrysa/struct.h new file mode 100644 index 0000000..cca00b8 --- /dev/null +++ b/plugins/pychrysa/struct.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * struct.h - prototypes pour la conversion de structures C en équivalent Python + * + * 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_PYCHRYSA_STRUCT_H +#define _PLUGINS_PYCHRYSA_STRUCT_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_py_struct_type(void); + +/* Prend en charge l'objet 'pychrysalide.PyStructObject'. */ +bool register_python_py_struct(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSA_STRUCT_H */ -- cgit v0.11.2-87-g4458