diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2009-07-14 23:43:09 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2009-07-14 23:43:09 (GMT) |
commit | b5a2692820a0b85a03ff28fc2154f8d50f26d5e2 (patch) | |
tree | 9b6760ddedcb46ece3ec577f7494e40fabce7b87 /src/format/elf/helper_x86.c | |
parent | 24d7c72a124df20339a50bb61e66385352e68a1b (diff) |
Restored the code loading the ELF relocations.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@93 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format/elf/helper_x86.c')
-rw-r--r-- | src/format/elf/helper_x86.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/src/format/elf/helper_x86.c b/src/format/elf/helper_x86.c new file mode 100644 index 0000000..39bdcfc --- /dev/null +++ b/src/format/elf/helper_x86.c @@ -0,0 +1,226 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * helper_x86.c - gestion auxiliaire de l'architecture x86 + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA 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 "helper_x86.h" + + +#include <malloc.h> +#include <string.h> + + +#include "elf-int.h" +#include "section.h" +#include "../../arch/immediate.h" +#include "../../arch/processor.h" +#include "../../arch/x86/instruction.h" +#include "../../panel/log.h" + + + +/* Décode les instructions liées à la relocalisation. */ +GArchInstruction **decode_elf_relocations(elf_format *, size_t *); + +/* Déduit les adresses effectives des relocalisations. */ +void translate_elf_relocations(elf_format *, GArchInstruction **, size_t); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* dyn_start = début des informations dynamiques associées. * +* dyn_size = taille de la zone associée. * +* str_start = début de la zone de chaîne de caractères. * +* str_size = taille de la zone de chaînes de caractères. * +* * +* Description : Déduit les adresses effectives des appels externes. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_elf_format_find_x86_dynamic_symbols(elf_format *format, off_t dyn_start, off_t dyn_size, off_t str_start, off_t str_size) +{ + GArchInstruction **instructions; /* Instructions décodées */ + size_t count; /* Quantité d'instructions */ + size_t i; /* Boucle de parcours */ + + instructions = decode_elf_relocations(format, &count); + + translate_elf_relocations(format, instructions, count); + + for (i = 0; i < count; i++) + /* TODO : free instructions[i] */; + + if (instructions != NULL) + free(instructions); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* count = nombre d'instructions lues. [OUT] * +* * +* Description : Décode les instructions liées à la relocalisation. * +* * +* Retour : Liste des instructions décodées ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction **decode_elf_relocations(elf_format *format, size_t *count) +{ + GArchInstruction **result; /* Liste à renvoyer */ + off_t plt_start; /* Début de section */ + off_t plt_size; /* Taille de section */ + vmpa_t plt_address; /* Adresse virtuelle associée */ + Elf_Shdr *sections; /* Groupe de sections trouvées */ + size_t sec_count; /* Quantité de données */ + size_t i; /* Boucle de parcours */ + GArchProcessor *proc; /* Processeur pour le décodage */ + off_t pos; /* Tête de lecture */ + vmpa_t address; /* Adresse virtuelle courante */ + GArchInstruction *instr; /* Instruction décodée */ + + result = NULL; + *count = 0; + + if (!find_elf_section_content_by_name(format, ".plt", &plt_start, &plt_size, &plt_address)) + { + log_simple_message(LMT_BAD_BINARY, _("No .plt section found ! Trying to guess it...")); + + /* FIXME : 64 bits ! */ + + find_elf_section_by_type(format, SHT_PROGBITS, §ions, &sec_count); + + for (i = 0; i < sec_count; i++) + if (ELF_SHDR(format, §ions[i], sh_entsize) > 0) + { + get_elf_section_content(format, §ions[i], &plt_start, &plt_size, &plt_address); + break; + } + + free(sections); + + if (i == sec_count) return NULL; + + } + + proc = get_arch_processor_for_type(APT_386); + + for (pos = 0; pos < plt_size; ) + { + address = plt_address + pos; + + instr = g_arch_processor_decode_instruction(proc, &EXE_FORMAT(format)->content[plt_start], + &pos, plt_size, 0/* FIXME*/, address); + + result = (GArchInstruction **)realloc(result, ++(*count) * sizeof(GArchInstruction *)); + result[*count - 1] = instr; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* instructions = listes des instructions à interpréter. * +* count = nombre d'instructions lues. * +* * +* Description : Déduit les adresses effectives des relocalisations. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void translate_elf_relocations(elf_format *format, GArchInstruction **instructions, size_t count) +{ + size_t i; /* Boucle de parcours #1 */ + X86Opcodes opcode_n0; /* Opcode de l'instruction n */ + X86Opcodes opcode_n1; /* Opcode de l'instruction n+1 */ + X86Opcodes opcode_n2; /* Opcode de l'instruction n+2 */ + GArchOperand *operand; /* Valeur du saut */ + vmpa_t address; /* Adresse virtuelle finale */ + size_t j; /* Boucle de parcours #2 */ + size_t new_len; /* Taille du nouveau nom */ + char *new_name; /* Nom avec suffixe @plt */ + GBinRoutine *routine; /* Nouvelle routine déduite */ + + for (i = 0; (i + 2) < count; ) + { + opcode_n0 = g_x86_instruction_get_opcode(G_X86_INSTRUCTION(instructions[i])); + opcode_n1 = g_x86_instruction_get_opcode(G_X86_INSTRUCTION(instructions[i + 1])); + opcode_n2 = g_x86_instruction_get_opcode(G_X86_INSTRUCTION(instructions[i + 2])); + + if (opcode_n0 == XOP_JMP_RM1632 + && opcode_n1 == XOP_PUSH_IMM1632 + && opcode_n2 == XOP_JMP_REL1632) + { + operand = g_arch_instruction_get_operand(instructions[i], 0); + + + g_imm_operand_to_vmpa_t(G_IMM_OPERAND(operand), &address); + + if (g_imm_operand_to_vmpa_t(G_IMM_OPERAND(operand), &address)) + for (j = 0; j < format->rel_count; j++) + if (format->relocations[j].address == address) + { + new_len = strlen(format->relocations[j].name) + 4 + 1; + new_name = calloc(new_len, sizeof(char)); + snprintf(new_name, new_len, "%s@plt", format->relocations[j].name); + + g_arch_instruction_get_location(instructions[i], NULL, NULL, &address); + + routine = g_binary_routine_new(); + + g_binary_routine_set_name(routine, new_name); + g_binary_routine_set_address(routine, address); + + format->routines = (GBinRoutine **)realloc(format->routines, + ++format->routines_count * sizeof(GBinRoutine *)); + + format->routines[format->routines_count - 1] = routine; + + } + + i += 3; + + } + else i++; + + } + +} |