diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2017-10-01 17:32:12 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2017-10-01 17:32:12 (GMT) |
commit | 208abfe4182c0dafc230e0377b3efcc6c24be0f9 (patch) | |
tree | 4e084364b0a211ee36a5e8e55b70367f01d720d5 /plugins/elf/strings.c | |
parent | 593aee561015251dfd042dc5e00388f63232c45f (diff) |
Defined the ELF support as plugin.
Diffstat (limited to 'plugins/elf/strings.c')
-rw-r--r-- | plugins/elf/strings.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/plugins/elf/strings.c b/plugins/elf/strings.c new file mode 100644 index 0000000..3bec414 --- /dev/null +++ b/plugins/elf/strings.c @@ -0,0 +1,250 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * strings.c - recherche des chaînes contenues dans un ELF + * + * Copyright (C) 2008-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 <http://www.gnu.org/licenses/>. + */ + + +#include "strings.h" + + +#include <assert.h> +#include <ctype.h> +#include <malloc.h> +#include <string.h> +#include <sys/param.h> + + +#include <arch/raw.h> + + +#include "elf-int.h" +#include "section.h" + + + +/* Enregistre toutes les chaînes de caractères trouvées. */ +static bool parse_elf_string_data(GElfFormat *, phys_t, phys_t, virt_t); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à analyser. * +* * +* Description : Charge en mémoire toutes les chaînes trouvées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool find_all_elf_strings(GElfFormat *format) +{ + bool got_string; /* Indique un remplissage */ + phys_t str_start; /* Début de section */ + phys_t str_size; /* Taille de section */ + virt_t str_addr; /* Adresse virtuelle associée */ + elf_shdr *sections; /* Groupe de sections trouvées */ + size_t count; /* Quantité de données */ + size_t i; /* Boucle de parcours #1 */ + phys_t max; /* Borne à ne pas dépasser */ + phys_t iter; /* Boucle de parcours #2 */ + elf_phdr phdr; /* En-tête de programme ELF */ + + got_string = false; + + /* Données en lecture seule */ + + if (find_elf_section_content_by_name(format, ".rodata", &str_start, &str_size, &str_addr)) + got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); + + else + { + if (find_elf_sections_by_type(format, SHT_PROGBITS, §ions, &count)) + { + for (i = 0; i < count; i++) + if (ELF_SHDR(format, sections[i], sh_flags) == SHF_ALLOC + || (ELF_SHDR(format, sections[i], sh_flags) & SHF_STRINGS)) + { + get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_addr); + got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); + } + + free(sections); + + } + + } + + /* Chaîne de caractères déclarées */ + + if (find_elf_sections_by_type(format, SHT_STRTAB, §ions, &count)) + { + for (i = 0; i < count; i++) + { + get_elf_section_content(format, §ions[i], &str_start, &str_size, &str_addr); + got_string |= parse_elf_string_data(format, str_start, str_size, str_addr); + } + + free(sections); + + } + + /* En désespoir de cause, on se rabbat sur les parties de programme directement */ + + if (!got_string) + { + max = ELF_HDR(format, format->header, e_phoff) + + ELF_HDR(format, format->header, e_phnum) * ELF_SIZEOF_PHDR(format); + + for (iter = ELF_HDR(format, format->header, e_phoff); iter < max; iter += ELF_SIZEOF_PHDR(format)) + { + if (!read_elf_program_header(format, iter, &phdr)) + continue; + + if (ELF_PHDR(format, phdr, p_flags) & PF_R + && !(ELF_PHDR(format, phdr, p_flags) & PF_X)) + parse_elf_string_data(format, + ELF_PHDR(format, phdr, p_offset), + ELF_PHDR(format, phdr, p_filesz), + ELF_PHDR(format, phdr, p_vaddr)); + + } + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* start = début de la zone à parcourir. * +* size = taille de l'espace à parcourir. * +* address = adresse virtuelle du début de la section. * +* * +* Description : Enregistre toutes les chaînes de caractères trouvées. * +* * +* Retour : true si des chaînes ont été ajoutées sans erreur, ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool parse_elf_string_data(GElfFormat *format, phys_t start, phys_t size, virt_t address) +{ + bool result; /* Bilan à faire remonter */ + GBinFormat *base; /* Autre version du format */ + GBinContent *content; /* Contenu binaire à lire */ + const bin_t *data; /* Contenu complet et original */ + vmpa2t pos; /* Tête de lecture */ + 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 */ + bool inserted; /* Bilan d'une insertion */ + const mrange_t *range; /* Espace occupé par une chaîne*/ + GBinSymbol *symbol; /* Symbole à intégrer */ + char *label; /* Désignation de la chaîne */ + + if (address == 0) + return false; + + result = false; + + /* Préparation des accès */ + + base = G_BIN_FORMAT(format); + + content = g_binary_format_get_content(base); + + init_vmpa(&pos, start, address); + + data = g_binary_content_get_raw_access(content, &pos, size); + + if (data == NULL) + goto pesd_error; + + /* Boucle de parcours */ + + cut = true; + + for (i = 0; i < size; i++) + if (isprint(data[i])) + { + for (end = i + 1; end < size; end++) + if (!isprint(data[end])) break; + + if (end < size && isspace(data[end])) + end++; + + if (end < size && data[end] == '\0') + end++; + + init_vmpa(&pos, start + i, address + i); + + instr = g_raw_instruction_new_array(content, MDS_8_BITS, end - i, &pos, format->endian); + assert(instr != NULL); + + g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true); + + inserted = g_preload_info_add_instruction(base->info, instr); + + if (inserted) + { + range = g_arch_instruction_get_range(instr); + + symbol = g_binary_symbol_new(range, STP_RO_STRING); + g_binary_format_add_symbol(base, symbol); + + /* Jointure avec la chaîne précédente ? */ + + if (cut) + { + label = create_string_label(base, get_mrange_addr(range), end - i); + + g_binary_symbol_set_alt_label(symbol, label); + + free(label); + + } + + } + + /* Conclusion */ + + cut = (data[end - 1] == '\0'); + + i = end - 1; + result = true; + + } + else cut = true; + + pesd_error: + + g_object_unref(G_OBJECT(content)); + + return result; + +} |