From ebe248fe406de9565c8c7787187a1d439e68cd84 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 31 Mar 2017 19:50:08 +0200 Subject: Extracted strings from some extra ELF sections. --- ChangeLog | 30 ++++++++ plugins/readelf/Makefile.am | 3 +- plugins/readelf/program.c | 4 +- plugins/readelf/program.h | 2 +- plugins/readelf/reader.c | 3 + plugins/readelf/section.c | 4 +- plugins/readelf/section.h | 2 +- plugins/readelf/strtab.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ plugins/readelf/strtab.h | 37 ++++++++++ src/format/elf/elf.c | 5 +- src/format/elf/section.c | 60 ++++++++++++++++ src/format/elf/section.h | 6 ++ src/format/elf/strings.c | 4 +- 13 files changed, 313 insertions(+), 11 deletions(-) create mode 100644 plugins/readelf/strtab.c create mode 100644 plugins/readelf/strtab.h diff --git a/ChangeLog b/ChangeLog index 2080976..b141036 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,35 @@ 17-03-31 Cyrille Bagard + * plugins/readelf/Makefile.am: + Add the 'strtab.[ch]' files to libreadelf_la_SOURCES. + + * plugins/readelf/program.c: + * plugins/readelf/program.h: + Typo. + + * plugins/readelf/reader.c: + Update code. + + * plugins/readelf/section.c: + * plugins/readelf/section.h: + Typo. + + * plugins/readelf/strtab.c: + * plugins/readelf/strtab.h: + New entries: extract strings from some extra ELF sections. + + * src/format/elf/elf.c: + Update code. + + * src/format/elf/section.c: + * src/format/elf/section.h: + Provide direct information about the range covered by a given section. + + * src/format/elf/strings.c: + Typo. + +17-03-31 Cyrille Bagard + * src/glibext/gbinportion.c: * src/glibext/gbinportion.h: Handle many special cases of binary portion inclusion to get a clean tree. diff --git a/plugins/readelf/Makefile.am b/plugins/readelf/Makefile.am index f6b3d5e..13f45f8 100644 --- a/plugins/readelf/Makefile.am +++ b/plugins/readelf/Makefile.am @@ -5,7 +5,8 @@ libreadelf_la_SOURCES = \ header.h header.c \ program.h program.c \ reader.h reader.c \ - section.h section.c + section.h section.c \ + strtab.h strtab.c libreadelf_la_CFLAGS = $(AM_CFLAGS) diff --git a/plugins/readelf/program.c b/plugins/readelf/program.c index 97c0c4e..6bf117c 100644 --- a/plugins/readelf/program.c +++ b/plugins/readelf/program.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * header.c - annotation des en-têtes de programme de binaires ELF + * program.c - annotation des en-têtes de programme de binaires ELF * * Copyright (C) 2015-2017 Cyrille Bagard * @@ -354,6 +354,6 @@ bool annotate_elf_program_header_table(GElfFormat *format, GtkStatusStack *statu gtk_status_stack_remove_activity(status, msg); - return true; + return result; } diff --git a/plugins/readelf/program.h b/plugins/readelf/program.h index 8a4e3fa..bee0fa0 100644 --- a/plugins/readelf/program.h +++ b/plugins/readelf/program.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * header.h - prototypes pour l'annotation des en-têtes de programme de binaires ELF + * program.h - prototypes pour l'annotation des en-têtes de programme de binaires ELF * * Copyright (C) 2015-2017 Cyrille Bagard * diff --git a/plugins/readelf/reader.c b/plugins/readelf/reader.c index 238b3a3..01d5d90 100644 --- a/plugins/readelf/reader.c +++ b/plugins/readelf/reader.c @@ -30,6 +30,7 @@ #include "header.h" #include "program.h" #include "section.h" +#include "strtab.h" @@ -71,6 +72,8 @@ G_MODULE_EXPORT bool handle_binary_format(const GPluginModule *plugin, PluginAct result &= annotate_elf_section_header_table(elf_fmt, status); + show_elf_section_string_table(elf_fmt, status); + hbf_exit: return result; diff --git a/plugins/readelf/section.c b/plugins/readelf/section.c index 89b13c4..f2cae76 100644 --- a/plugins/readelf/section.c +++ b/plugins/readelf/section.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * header.c - annotation des en-têtes de section de binaires ELF + * section.c - annotation des en-têtes de section de binaires ELF * * Copyright (C) 2015-2017 Cyrille Bagard * @@ -431,6 +431,6 @@ bool annotate_elf_section_header_table(GElfFormat *format, GtkStatusStack *statu gtk_status_stack_remove_activity(status, msg); - return true; + return result; } diff --git a/plugins/readelf/section.h b/plugins/readelf/section.h index d91730d..3168dab 100644 --- a/plugins/readelf/section.h +++ b/plugins/readelf/section.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * header.h - prototypes pour l'annotation des en-têtes de section de binaires ELF + * section.h - prototypes pour l'annotation des en-têtes de section de binaires ELF * * Copyright (C) 2015-2017 Cyrille Bagard * diff --git a/plugins/readelf/strtab.c b/plugins/readelf/strtab.c new file mode 100644 index 0000000..c94deed --- /dev/null +++ b/plugins/readelf/strtab.c @@ -0,0 +1,164 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * strtab.h - présentation des chaînes liées au format des binaires ELF + * + * 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 Foobar. If not, see . + */ + + +#include "strtab.h" + + +#include + + +#include +#include + + + +/* Affiche les chaînes présentes dans une zone de données. */ +static void parse_elf_string_table(GElfFormat *, const GBinContent *, const mrange_t *, GtkStatusStack *); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* content = contenu binaire à analyser. * +* range = espace à couvrir pendant l'analyse. * +* status = barre de statut à tenir informée. * +* * +* Description : Affiche les chaînes présentes dans une zone de données. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void parse_elf_string_table(GElfFormat *format, const GBinContent *content, const mrange_t *range, GtkStatusStack *status) +{ + phys_t length; /* Taille de la couverture */ + vmpa2t pos; /* Tête de lecture */ + const bin_t *data; /* Donnés à parcourir */ + bool cut; /* Séparation nette ? */ + phys_t i; /* Boucle de parcours */ + phys_t end; /* Position de fin de chaîne */ + GArchInstruction *instr; /* Instruction décodée */ + GBinSymbol *symbol; /* Symbole à intégrer */ + char *label; /* Désignation de la chaîne */ + + length = get_mrange_length(range); + + copy_vmpa(&pos, get_mrange_addr(range)); + data = g_binary_content_get_raw_access(content, &pos, length); + + cut = true; + + /* Boucle de parcours */ + + cut = true; + + for (i = 0; i < length; i++) + if (isprint(data[i])) + { + for (end = i + 1; end < length; end++) + if (!isprint(data[end])) break; + + if (end < length && isspace(data[end])) + end++; + + if (end < length && data[end] == '\0') + end++; + + copy_vmpa(&pos, get_mrange_addr(range)); + advance_vmpa(&pos, i); + + instr = g_raw_instruction_new_array(content, MDS_8_BITS, end - i, &pos, MDS_UNDEFINED); + + g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true); + + ADD_STR_AS_SYM(format, symbol, instr); + + /* Jointure avec la chaîne précédente ? */ + + if (cut) + { + copy_vmpa(&pos, get_mrange_addr(range)); + advance_vmpa(&pos, i); + + label = create_string_label(G_BIN_FORMAT(format), &pos, end - i); + + g_binary_symbol_set_alt_label(symbol, label); + + free(label); + + } + + /* Conclusion */ + + cut = (data[end - 1] == '\0'); + + i = end - 1; + + } + else cut = true; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* status = barre de statut à tenir informée. * +* * +* Description : Affiche les chaînes liées aux sections ELF. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void show_elf_section_string_table(GElfFormat *format, GtkStatusStack *status) +{ + GBinContent *content; /* Contenu binaire à lire */ + mrange_t range; /* Espace à parcourir */ + bool found; /* Détection d'une section */ + + content = g_binary_format_get_content(G_BIN_FORMAT(format)); + + found = find_elf_section_range_by_name(format, ".interp", &range); + + if (found) + parse_elf_string_table(format, content, &range, status); + + found = find_elf_section_range_by_name(format, ".shstrtab", &range); + + if (found) + parse_elf_string_table(format, content, &range, status); + + found = find_elf_section_range_by_name(format, ".strtab", &range); + + if (found) + parse_elf_string_table(format, content, &range, status); + + g_object_unref(G_OBJECT(content)); + +} diff --git a/plugins/readelf/strtab.h b/plugins/readelf/strtab.h new file mode 100644 index 0000000..a3c8c8b --- /dev/null +++ b/plugins/readelf/strtab.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * strtab.h - prototypes pour la présentation des chaînes liées au format des binaires ELF + * + * 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 Foobar. If not, see . + */ + + +#ifndef _PLUGINS_READELF_STRTAB_H +#define _PLUGINS_READELF_STRTAB_H + + +#include + + + +/* Affiche les chaînes liées aux sections ELF. */ +void show_elf_section_string_table(GElfFormat *, GtkStatusStack *); + + + +#endif /* _PLUGINS_READELF_STRTAB_H */ diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index 0ad90ff..bc48eb5 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -411,6 +411,7 @@ static void g_elf_format_refine_portions(GElfFormat *format) bool has_strings; /* Section trouvée ? */ elf_shdr shdr; /* En-tête de section ELF */ uint64_t sh_flags; /* Droits associés à une partie*/ + mrange_t range; /* Emplacement d'une section */ const char *name; /* Nom trouvé ou NULL */ exe_format = G_EXE_FORMAT(format); @@ -494,9 +495,9 @@ static void g_elf_format_refine_portions(GElfFormat *format) else if (sh_flags & SHF_WRITE) background = BPC_DATA; else background = BPC_DATA_RO; - init_vmpa(&addr, ELF_SHDR(format, shdr, sh_offset), ELF_SHDR(format, shdr, sh_addr)); + get_elf_section_range(format, &shdr, &range); - new = g_binary_portion_new(background, &addr, ELF_SHDR(format, shdr, sh_size)); + new = g_binary_portion_new(background, get_mrange_addr(&range), get_mrange_length(&range)); if (has_strings) name = extract_name_from_elf_string_section(format, &strings, diff --git a/src/format/elf/section.c b/src/format/elf/section.c index 9583927..556c0ed 100644 --- a/src/format/elf/section.c +++ b/src/format/elf/section.c @@ -207,6 +207,37 @@ void get_elf_section_content(const GElfFormat *format, const elf_shdr *section, /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * +* section = section à consulter. * +* range = emplacement de la fonction à renseigner. [OUT] * +* * +* Description : Fournit la localisation d'une section. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void get_elf_section_range(const GElfFormat *format, const elf_shdr *section, mrange_t *range) +{ + virt_t virt; /* Emplacement virtuel */ + vmpa2t tmp; /* Enregistrement intermédiaire*/ + + virt = ELF_SHDR(format, *section, sh_addr); + + if (virt == 0) + virt = VMPA_NO_VIRTUAL; + + init_vmpa(&tmp, ELF_SHDR(format, *section, sh_offset), virt); + + init_mrange(range, &tmp, ELF_SHDR(format, *section, sh_size)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * * name = nom de la section recherchée. * * offset = position de la section trouvée. [OUT] * * size = taille de la section trouvée. [OUT] * @@ -237,6 +268,35 @@ bool find_elf_section_content_by_name(const GElfFormat *format, const char *name /****************************************************************************** * * +* Paramètres : format = description de l'exécutable à consulter. * +* name = nom de la section recherchée. * +* range = emplacement de la fonction à renseigner. [OUT] * +* * +* Description : Recherche une zone donnée au sein de binaire par nom. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool find_elf_section_range_by_name(const GElfFormat *format, const char *name, mrange_t *range) +{ + bool result; /* Bilan à retourner */ + elf_shdr section; /* Section trouvée ou non */ + + result = find_elf_section_by_name(format, name, §ion); + + if (result) + get_elf_section_range(format, §ion, range); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : format = description de l'exécutable à consulter. * * section = section contenant des chaînes terminées par '\0'. * * index = indice du premier caractères à cerner. * diff --git a/src/format/elf/section.h b/src/format/elf/section.h index aed6f9e..f3be0f4 100644 --- a/src/format/elf/section.h +++ b/src/format/elf/section.h @@ -45,9 +45,15 @@ bool find_elf_sections_by_type(const GElfFormat *, uint32_t, elf_shdr **, size_t /* Fournit les adresses et taille contenues dans une section. */ void get_elf_section_content(const GElfFormat *, const elf_shdr *, phys_t *, phys_t *, virt_t *); +/* Fournit la localisation d'une section. */ +void get_elf_section_range(const GElfFormat *, const elf_shdr *, mrange_t *); + /* Recherche une zone donnée au sein de binaire par nom. */ bool find_elf_section_content_by_name(const GElfFormat *, const char *, phys_t *, phys_t *, virt_t *); +/* Recherche une zone donnée au sein de binaire par nom. */ +bool find_elf_section_range_by_name(const GElfFormat *, const char *, mrange_t *); + /* Identifie une chaîne de caractères dans une section adéquate. */ const char *extract_name_from_elf_string_section(const GElfFormat *, const elf_shdr *, off_t); diff --git a/src/format/elf/strings.c b/src/format/elf/strings.c index 9bcb87f..8901db9 100644 --- a/src/format/elf/strings.c +++ b/src/format/elf/strings.c @@ -155,8 +155,8 @@ bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t const bin_t *data; /* Contenu complet et original */ vmpa2t pos; /* Tête de lecture */ bool cut; /* Séparation nette ? */ - off_t i; /* Boucle de parcours */ - off_t end; /* Position de fin de chaîne */ + phys_t i; /* Boucle de parcours */ + phys_t end; /* Position de fin de chaîne */ GArchInstruction *instr; /* Instruction décodée */ GBinSymbol *symbol; /* Symbole à intégrer */ char *label; /* Désignation de la chaîne */ -- cgit v0.11.2-87-g4458