From 7fd6e0b76f33de5934fad17efb75366904a3875b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 29 Nov 2017 17:24:20 +0100 Subject: Provided the list of needed shared objects for an Elf binary. --- ChangeLog | 29 ++++++++++++ plugins/elf/dynamic.c | 95 ++++++++++++++++++++++++++++++++++++++ plugins/elf/dynamic.h | 3 ++ plugins/elf/program.c | 37 ++++++++++++++- plugins/elf/program.h | 3 ++ plugins/elf/python/Makefile.am | 1 + plugins/elf/python/dynamic.c | 79 +++++++++++++++++++++++++++++++ plugins/elf/python/dynamic.h | 38 +++++++++++++++ plugins/elf/python/format.c | 5 ++ src/analysis/content-int.h | 4 ++ src/analysis/content.c | 24 ++++++++++ src/analysis/content.h | 3 ++ src/analysis/contents/file.c | 24 ++++++++++ src/analysis/contents/restricted.c | 52 +++++++++++++++++++++ 14 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 plugins/elf/python/dynamic.c create mode 100644 plugins/elf/python/dynamic.h diff --git a/ChangeLog b/ChangeLog index ba00eee..30c1bcd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +17-11-29 Cyrille Bagard + + * plugins/elf/dynamic.c: + * plugins/elf/dynamic.h: + Provide the list of needed shared objects for an Elf binary. + + * plugins/elf/program.c: + * plugins/elf/program.h: + Find program headers by type. + + * plugins/elf/python/Makefile.am: + Add the 'dynamic.[ch]' files to libelfpython_la_SOURCES. + + * plugins/elf/python/dynamic.c: + * plugins/elf/python/dynamic.h: + New entries: provide the list of needed shared objects for an Elf binary. + + * plugins/elf/python/format.c: + Update code. + + * src/analysis/content-int.h: + * src/analysis/content.c: + * src/analysis/content.h: + Provide the last position in a binary content. + + * src/analysis/contents/file.c: + * src/analysis/contents/restricted.c: + Update code. + 17-11-27 Cyrille Bagard * plugins/pychrysa/arch/vmpa.c: diff --git a/plugins/elf/dynamic.c b/plugins/elf/dynamic.c index 782167c..ed681d1 100644 --- a/plugins/elf/dynamic.c +++ b/plugins/elf/dynamic.c @@ -107,3 +107,98 @@ bool find_elf_dynamic_item_from_pheader(const GElfFormat *format, const elf_phdr return result; } + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* count = nombre d'éléments dans la liste constituée. * +* * +* Description : Fournit la liste des objets partagés requis. * +* * +* Retour : Liste de noms d'objets ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char **list_elf_needed_objects(const GElfFormat *format, size_t *count) +{ + const char **result; /* Liste à retourner */ + elf_phdr dynamic; /* Programme à analyser */ + virt_t strtab_virt; /* Adresse mémoire des chaînes */ + uint64_t max; /* Nombre d'entités présentes */ + uint64_t i; /* Boucle de parcours */ + phys_t pos; /* Position de lecture */ + elf_dyn item; /* Informations extraites */ + vmpa2t strtab_pos; /* Emplacement des chaînes */ + GBinContent *content; /* Contenu global analysé */ + vmpa2t end; /* Limite finale de contenu */ + vmpa2t str_pos; /* Emplacement d'une chaîne */ + phys_t diff; /* Données encore disponibles */ + const bin_t *string; /* Nouvelle chaîne trouvée */ + + result = NULL; + *count = 0; + + if (!find_elf_program_by_type(format, PT_DYNAMIC, &dynamic)) + goto leno_exit; + + max = ELF_PHDR(format, dynamic, p_filesz) / ELF_SIZEOF_DYN(format); + + /* Première passe : recherche des chaînes */ + + strtab_virt = VMPA_NO_VIRTUAL; + + for (i = 0; i < max; i++) + { + pos = ELF_PHDR(format, dynamic, p_offset) + i * ELF_SIZEOF_DYN(format); + + if (!read_elf_dynamic_entry(format, pos, &item)) + break; + + if (ELF_DYN(format, item, d_tag) == DT_STRTAB) + strtab_virt = ELF_DYN(format, item, d_un.d_val); + + } + + if (strtab_virt == VMPA_NO_VIRTUAL) + goto leno_exit; + + if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), strtab_virt, &strtab_pos)) + goto leno_exit; + + /* Seconde passe : recherche des objets requis */ + + content = G_BIN_FORMAT(format)->content; + + g_binary_content_compute_end_pos(content, &end); + + for (i = 0; i < max; i++) + { + pos = ELF_PHDR(format, dynamic, p_offset) + i * ELF_SIZEOF_DYN(format); + + if (!read_elf_dynamic_entry(format, pos, &item)) + break; + + if (ELF_DYN(format, item, d_tag) == DT_NEEDED) + { + copy_vmpa(&str_pos, &strtab_pos); + advance_vmpa(&str_pos, ELF_DYN(format, item, d_un.d_val)); + + diff = compute_vmpa_diff(&str_pos, &end); + + string = g_binary_content_get_raw_access(content, &str_pos, diff); + + result = (const char **)realloc(result, ++(*count) * sizeof(const char *)); + result[*count - 1] = (const char *)string; + + } + + } + + leno_exit: + + return result; + +} diff --git a/plugins/elf/dynamic.h b/plugins/elf/dynamic.h index ee5d3d8..c166712 100644 --- a/plugins/elf/dynamic.h +++ b/plugins/elf/dynamic.h @@ -36,6 +36,9 @@ bool find_elf_dynamic_program_header(const GElfFormat *, elf_phdr *); /* Retrouve un élément donné dans la section dynamique. */ bool find_elf_dynamic_item_from_pheader(const GElfFormat *, const elf_phdr *, int64_t, elf_dyn *); +/* Fournit la liste des objets partagés requis. */ +const char **list_elf_needed_objects(const GElfFormat *, size_t *); + #endif /* _PLUGINS_ELF_DYNAMIC_H */ diff --git a/plugins/elf/program.c b/plugins/elf/program.c index 3016feb..7e6f2e4 100644 --- a/plugins/elf/program.c +++ b/plugins/elf/program.c @@ -108,7 +108,7 @@ const char *get_elf_program_type_desc(const GElfFormat *format, uint32_t p_type) /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * -* index = indice de la section recherchée. * +* index = indice de la partie recherchée. * * program = ensemble d'informations à faire remonter. [OUT] * * * * Description : Recherche un programme donné au sein de binaire par indice. * @@ -135,6 +135,41 @@ bool find_elf_program_by_index(const GElfFormat *format, uint16_t index, elf_phd /****************************************************************************** * * +* Paramètres : format = description de l'exécutable à consulter. * +* type = type de la partie recherchée. * +* program = ensemble d'informations à faire remonter. [OUT] * +* * +* Description : Recherche un programme donné au sein de binaire par type. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool find_elf_program_by_type(const GElfFormat *format, uint32_t type, elf_phdr *program) +{ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + + result = false; + + for (i = 0; i < ELF_HDR(format, format->header, e_phnum) && !result; i++) + { + find_elf_program_by_index(format, i, program); + + if (ELF_PHDR(format, *program, p_type) == type) + result = true; + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : format = description de l'exécutable à consulter. * * off = position physique à retrouver. * * pos = position correspondante. [OUT] * diff --git a/plugins/elf/program.h b/plugins/elf/program.h index 91de4ec..fcb7b1a 100644 --- a/plugins/elf/program.h +++ b/plugins/elf/program.h @@ -36,6 +36,9 @@ const char *get_elf_program_type_desc(const GElfFormat *, uint32_t); /* Recherche un programme donné au sein de binaire par indice. */ bool find_elf_program_by_index(const GElfFormat *, uint16_t, elf_phdr *); +/* Recherche un programme donné au sein de binaire par type. */ +bool find_elf_program_by_type(const GElfFormat *, uint32_t, elf_phdr *); + /* Fournit l'emplacement correspondant à une position physique. */ bool translate_offset_into_vmpa_using_elf_programs(const GElfFormat *, phys_t, vmpa2t *); diff --git a/plugins/elf/python/Makefile.am b/plugins/elf/python/Makefile.am index 91e86f0..bcb739e 100644 --- a/plugins/elf/python/Makefile.am +++ b/plugins/elf/python/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libelfpython.la libelfpython_la_SOURCES = \ constants.h constants.c \ + dynamic.h dynamic.c \ format.h format.c \ module.h module.c diff --git a/plugins/elf/python/dynamic.c b/plugins/elf/python/dynamic.c new file mode 100644 index 0000000..b87cba0 --- /dev/null +++ b/plugins/elf/python/dynamic.c @@ -0,0 +1,79 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * utils.c - prototypes pour l'équivalent Python du fichier "plugins/elf/utils.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 "dynamic.h" + + +#include +#include + + +#include "../dynamic.h" + + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un format ELF. * +* closure = adresse non utilisée ici. * +* * +* Description : Fournit la liste des objets partagés requis. * +* * +* Retour : Liste de noms d'objets ou None en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *py_elf_format_get_needed(PyObject *self, void *closure) +{ + PyObject *result; /* Liste éventuelle à renvoyer */ + GElfFormat *format; /* Version native */ + size_t count; /* Taille de la liste obtenue */ + const char **needed; /* Objets nécessaires */ + size_t i; /* Boucle de parcours */ + + format = G_ELF_FORMAT(pygobject_get(self)); + + needed = list_elf_needed_objects(format, &count); + + if (count > 0) + { + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + PyTuple_SetItem(result, i, PyUnicode_FromString(needed[i])); + + free(needed); + + } + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} diff --git a/plugins/elf/python/dynamic.h b/plugins/elf/python/dynamic.h new file mode 100644 index 0000000..4656c6d --- /dev/null +++ b/plugins/elf/python/dynamic.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * utils.h - prototypes pour l'équivalent Python du fichier "plugins/elf/utils.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_UTILS_H +#define _PLUGINS_ELF_PYTHON_UTILS_H + + +#include + + + +/* Fournit la liste des objets partagés requis. */ +PyObject *py_elf_format_get_needed(PyObject *, void *); + + + +#endif /* _PLUGINS_ELF_PYTHON_UTILS_H */ diff --git a/plugins/elf/python/format.c b/plugins/elf/python/format.c index 1ff22bd..eb1bedb 100644 --- a/plugins/elf/python/format.c +++ b/plugins/elf/python/format.c @@ -37,6 +37,7 @@ #include "constants.h" +#include "dynamic.h" #include "../format.h" @@ -144,6 +145,10 @@ PyTypeObject *get_python_elf_format_type(void) }; static PyGetSetDef py_elf_format_getseters[] = { + { + "needed", py_elf_format_get_needed, NULL, + "Provide the list of requiered shared objects.", NULL + }, { NULL } }; diff --git a/src/analysis/content-int.h b/src/analysis/content-int.h index 4635047..7da78db 100644 --- a/src/analysis/content-int.h +++ b/src/analysis/content-int.h @@ -41,6 +41,9 @@ typedef void (* compute_checksum_fc) (GBinContent *, GChecksum *); /* Détermine le nombre d'octets lisibles. */ typedef phys_t (* compute_size_fc) (const GBinContent *); +/* Détermine la position finale d'un contenu. */ +typedef void (* compute_end_pos_fc) (const GBinContent *, vmpa2t *); + /* Avance la tête de lecture d'une certaine quantité de données. */ typedef bool (* seek_fc) (const GBinContent *, vmpa2t *, phys_t); @@ -84,6 +87,7 @@ struct _GBinContentIface compute_checksum_fc compute_checksum; /* Calcul de l'empreinte */ compute_size_fc compute_size; /* Calcul de la taille totale */ + compute_end_pos_fc compute_end_pos; /* Calcul de position finale */ seek_fc seek; /* Avancée de tête de lecture */ diff --git a/src/analysis/content.c b/src/analysis/content.c index 0a57972..562ec2a 100644 --- a/src/analysis/content.c +++ b/src/analysis/content.c @@ -215,6 +215,30 @@ phys_t g_binary_content_compute_size(const GBinContent *content) /****************************************************************************** * * * Paramètres : content = contenu binaire à venir lire. * +* pos = position finale (exclusive). [OUT] * +* * +* Description : Détermine la position finale d'un contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_content_compute_end_pos(const GBinContent *content, vmpa2t *pos) +{ + GBinContentIface *iface; /* Interface utilisée */ + + iface = G_BIN_CONTENT_GET_IFACE(content); + + return iface->compute_end_pos(content, pos); + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * * addr = position de la tête de lecture. * * length = quantité d'octets à provisionner. * * * diff --git a/src/analysis/content.h b/src/analysis/content.h index 4bb1dc1..a4fff20 100644 --- a/src/analysis/content.h +++ b/src/analysis/content.h @@ -69,6 +69,9 @@ const gchar *g_binary_content_get_checksum(GBinContent *); /* Détermine le nombre d'octets lisibles. */ phys_t g_binary_content_compute_size(const GBinContent *); +/* Détermine la position finale d'un contenu. */ +void g_binary_content_compute_end_pos(const GBinContent *, vmpa2t *); + /* Avance la tête de lecture d'une certaine quantité de données. */ bool g_binary_content_seek(const GBinContent *, vmpa2t *, phys_t); diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c index 8b371ab..2461017 100644 --- a/src/analysis/contents/file.c +++ b/src/analysis/contents/file.c @@ -85,6 +85,9 @@ static void g_file_content_compute_checksum(GFileContent *, GChecksum *); /* Détermine le nombre d'octets lisibles. */ static phys_t g_file_content_compute_size(const GFileContent *); +/* Détermine la position finale d'un contenu. */ +static void g_file_content_compute_end_pos(const GFileContent *, vmpa2t *); + /* Avance la tête de lecture d'une certaine quantité de données. */ static bool g_file_content_seek(const GFileContent *, vmpa2t *, phys_t); @@ -185,6 +188,7 @@ static void g_file_content_interface_init(GBinContentInterface *iface) iface->compute_checksum = (compute_checksum_fc)g_file_content_compute_checksum; iface->compute_size = (compute_size_fc)g_file_content_compute_size; + iface->compute_end_pos = (compute_end_pos_fc)g_file_content_compute_end_pos; iface->seek = (seek_fc)g_file_content_seek; @@ -493,6 +497,26 @@ static phys_t g_file_content_compute_size(const GFileContent *content) /****************************************************************************** * * * Paramètres : content = contenu binaire à venir lire. * +* pos = position finale (exclusive). [OUT] * +* * +* Description : Détermine la position finale d'un contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_file_content_compute_end_pos(const GFileContent *content, vmpa2t *pos) +{ + compute_mrange_end_addr(&content->range, pos); + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * * addr = position de la tête de lecture. * * length = quantité d'octets à provisionner. * * * diff --git a/src/analysis/contents/restricted.c b/src/analysis/contents/restricted.c index 132d60b..28949ba 100644 --- a/src/analysis/contents/restricted.c +++ b/src/analysis/contents/restricted.c @@ -69,6 +69,12 @@ static void g_restricted_content_finalize(GRestrictedContent *); /* Calcule une empreinte unique (SHA256) pour les données. */ static void g_restricted_content_compute_checksum(GRestrictedContent *, GChecksum *); +/* Détermine le nombre d'octets lisibles. */ +static phys_t g_restricted_content_compute_size(const GRestrictedContent *); + +/* Détermine la position finale d'un contenu. */ +static void g_restricted_content_compute_end_pos(const GRestrictedContent *, vmpa2t *); + /* Avance la tête de lecture d'une certaine quantité de données. */ static bool g_restricted_content_seek(const GRestrictedContent *, vmpa2t *, phys_t); @@ -164,6 +170,9 @@ static void g_restricted_content_interface_init(GBinContentInterface *iface) { iface->compute_checksum = (compute_checksum_fc)g_restricted_content_compute_checksum; + iface->compute_size = (compute_size_fc)g_restricted_content_compute_size; + iface->compute_end_pos = (compute_end_pos_fc)g_restricted_content_compute_end_pos; + iface->seek = (seek_fc)g_restricted_content_seek; iface->get_raw_access = (get_raw_access_fc)g_restricted_content_get_raw_access; @@ -319,6 +328,49 @@ static void g_restricted_content_compute_checksum(GRestrictedContent *content, G /****************************************************************************** * * * Paramètres : content = contenu binaire à venir lire. * +* * +* Description : Détermine le nombre d'octets lisibles. * +* * +* Retour : Quantité représentée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static phys_t g_restricted_content_compute_size(const GRestrictedContent *content) +{ + phys_t result; /* Quantité trouvée à retourner*/ + + result = get_mrange_length(&content->range); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* pos = position finale (exclusive). [OUT] * +* * +* Description : Détermine la position finale d'un contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_restricted_content_compute_end_pos(const GRestrictedContent *content, vmpa2t *pos) +{ + compute_mrange_end_addr(&content->range, pos); + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * * addr = position de la tête de lecture. * * length = quantité d'octets à provisionner. * * * -- cgit v0.11.2-87-g4458