diff options
Diffstat (limited to 'plugins/elf/program.c')
-rw-r--r-- | plugins/elf/program.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/plugins/elf/program.c b/plugins/elf/program.c new file mode 100644 index 0000000..3016feb --- /dev/null +++ b/plugins/elf/program.c @@ -0,0 +1,217 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * program.c - gestion des en-têtes de programme d'un ELF + * + * Copyright (C) 2010-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 "program.h" + + +#include "elf-int.h" +#include "helper_arm.h" + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* p_type = type associé à un en-tête de programme. * +* * +* Description : Fournit la description humaine d'un type de segment ELF. * +* * +* Retour : Désignation prête à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *get_elf_program_type_desc(const GElfFormat *format, uint32_t p_type) +{ + const char *result; /* Description à renvoyer */ + +#define MAKE_STRING_FROM_PT(pt) case pt: result = #pt; break; + + switch(p_type) + { + MAKE_STRING_FROM_PT(PT_NULL); + MAKE_STRING_FROM_PT(PT_LOAD); + MAKE_STRING_FROM_PT(PT_DYNAMIC); + MAKE_STRING_FROM_PT(PT_INTERP); + MAKE_STRING_FROM_PT(PT_NOTE); + MAKE_STRING_FROM_PT(PT_SHLIB); + MAKE_STRING_FROM_PT(PT_PHDR); + MAKE_STRING_FROM_PT(PT_TLS); + MAKE_STRING_FROM_PT(PT_NUM); + MAKE_STRING_FROM_PT(PT_LOOS); + MAKE_STRING_FROM_PT(PT_GNU_EH_FRAME); + MAKE_STRING_FROM_PT(PT_GNU_STACK); + MAKE_STRING_FROM_PT(PT_GNU_RELRO); + MAKE_STRING_FROM_PT(PT_LOSUNW); + MAKE_STRING_FROM_PT(PT_SUNWSTACK); + MAKE_STRING_FROM_PT(PT_HIOS); + MAKE_STRING_FROM_PT(PT_LOPROC); + MAKE_STRING_FROM_PT(PT_HIPROC); + + default: + result = NULL; + break; + + } + + if (result == NULL) + switch (ELF_HDR(format, format->header, e_machine)) + { + case EM_ARM: + result = get_elf_program_arm_type_desc(p_type); + break; + + default: + break; + + } + + if (result == NULL) + switch(p_type) + { + MAKE_STRING_FROM_PT(PT_LOOS); + MAKE_STRING_FROM_PT(PT_HIOS); + MAKE_STRING_FROM_PT(PT_LOPROC); + MAKE_STRING_FROM_PT(PT_HIPROC); + + default: + result = "PT_???"; + break; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* index = indice de la section recherchée. * +* program = ensemble d'informations à faire remonter. [OUT] * +* * +* Description : Recherche un programme donné au sein de binaire par indice. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool find_elf_program_by_index(const GElfFormat *format, uint16_t index, elf_phdr *program) +{ + off_t offset; /* Emplacement à venir lire */ + + if (index >= ELF_HDR(format, format->header, e_phnum)) return false; + + offset = ELF_HDR(format, format->header, e_phoff) + + ELF_HDR(format, format->header, e_phentsize) * index; + + return read_elf_program_header(format, offset, program); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* off = position physique à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit l'emplacement correspondant à une position physique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool translate_offset_into_vmpa_using_elf_programs(const GElfFormat *format, phys_t off, vmpa2t *pos) +{ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + elf_phdr program; /* Programme à analyser */ + virt_t addr; /* Adresse virtuelle calculée */ + + 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_offset) <= off + && off < (ELF_PHDR(format, program, p_offset) + ELF_PHDR(format, program, p_filesz))) + { + addr = ELF_PHDR(format, program, p_vaddr) + ELF_PHDR(format, program, p_offset) - off; + init_vmpa(pos, off, addr); + result = true; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* addr = adresse virtuelle à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit l'emplacement correspondant à une adresse virtuelle. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool translate_address_into_vmpa_using_elf_programs(const GElfFormat *format, virt_t addr, vmpa2t *pos) +{ + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ + elf_phdr program; /* Programme à analyser */ + phys_t off; /* Position physique calculée */ + + 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_vaddr) <= addr + && addr < (ELF_PHDR(format, program, p_vaddr) + ELF_PHDR(format, program, p_filesz))) + { + off = ELF_PHDR(format, program, p_offset) + addr - ELF_PHDR(format, program, p_vaddr); + init_vmpa(pos, off, addr); + result = true; + } + + } + + return result; + +} |