diff options
Diffstat (limited to 'src/format/elf')
-rw-r--r-- | src/format/elf/e_elf.c | 12 | ||||
-rw-r--r-- | src/format/elf/elf-int.h | 33 | ||||
-rw-r--r-- | src/format/elf/symbol.c | 305 |
3 files changed, 339 insertions, 11 deletions
diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c index 3aa9394..03b2e82 100644 --- a/src/format/elf/e_elf.c +++ b/src/format/elf/e_elf.c @@ -137,6 +137,18 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count) if (format->sec_size > 0) { + if (find_elf_section(format, ".plt", &offset, &size, &voffset)) + { + part = create_bin_part(); + + set_bin_part_name(part, ".plt"); + set_bin_part_values(part, offset, size, voffset); + + result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); + result[*count - 1] = part; + + } + if (find_elf_section(format, ".init", &offset, &size, &voffset)) { part = create_bin_part(); diff --git a/src/format/elf/elf-int.h b/src/format/elf/elf-int.h index f366c71..6e7bca1 100644 --- a/src/format/elf/elf-int.h +++ b/src/format/elf/elf-int.h @@ -84,6 +84,39 @@ typedef union _Elf_Phdr #define ELF_PHDR(fmt, hdr, fld) (fmt->is_32b ? hdr.header32.fld : hdr.header64.fld) +/* Entrée de la table de relocalisation */ + +typedef union _Elf_Rel +{ + Elf32_Rel rel32; /* Version 32 bits */ + Elf64_Rel rel64; /* Version 64 bits */ + +} Elf_Rel; + +#define ELF_SIZEOF_REL(fmt) (fmt->is_32b ? sizeof(Elf32_Rel) : sizeof(Elf64_Rel)) + +#define ELF_REL(fmt, rl, fld) (fmt->is_32b ? rl.rel32.fld : rl.rel64.fld) + +#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM(rl.rel32.r_info) : ELF64_R_SYM(rl.rel64.r_info)) +#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE(rl.rel32.r_info) : ELF64_R_TYPE(rl.rel64.r_info)) + + +/* Information sur un symbole */ + +typedef union _Elf_Sym +{ + Elf32_Sym sym32; /* Version 32 bits */ + Elf64_Sym sym64; /* Version 64 bits */ + +} Elf_Sym; + +#define ELF_SIZEOF_SYM(fmt) (fmt->is_32b ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym)) + +#define ELF_SYM(fmt, sb, fld) (fmt->is_32b ? sb.sym32.fld : sb.sym64.fld) + + + + #endif /* _FORMAT_ELF_ELF_INT_H */ diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c index 729c154..8fa5690 100644 --- a/src/format/elf/symbol.c +++ b/src/format/elf/symbol.c @@ -26,9 +26,14 @@ #include <malloc.h> #include <elf.h> +#include <stdio.h> #include <string.h> +#include "../../arch/processor.h" /* FIXME : remove me ! */ +#include "../../arch/instruction.h" /* FIXME : remove me ! */ +#include "../../arch/instruction-int.h" /* FIXME : remove me ! */ + #include "elf-int.h" #include "section.h" @@ -37,6 +42,24 @@ +/* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */ + + +/* Charge en mémoire la liste des symboles dynamiques. */ +bool load_elf_relocation_table(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *); + +/* Récupère les informations d'un symbole dynamique donné. */ +char *get_elf_dynamic_symbol_info(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *); + +/* Décode les instructions liées à la relocalisation. */ +asm_instr **decode_elf_relocations(elf_format *, size_t *); + +/* Déduit les adresses effectives des relocalisations. */ +void translate_elf_relocations(elf_format *, asm_instr **, size_t); + + + + /* Charge en mémoire la liste humaine des symboles (32 bits). */ bool load_elf_symbol_table_32(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *); @@ -69,6 +92,16 @@ bool load_elf_symbols(elf_format *format) off_t str_size; /* Taille de section */ + off_t plt_start; /* Début de section */ + off_t plt_size; /* Taille de section */ + off_t dyn_start; /* Début de section */ + off_t dyn_size; /* Taille de section */ + + + asm_instr **instructions; /* Instructions décodées */ + size_t count; /* Quantité d'instructions */ + + result = find_elf_section(format, ".symtab", &sym_start, &sym_size, NULL); result &= find_elf_section(format, ".strtab", &str_start, &str_size, NULL); @@ -79,12 +112,46 @@ bool load_elf_symbols(elf_format *format) - result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_start); + result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_size); } + + + + + + + result = find_elf_section(format, ".rel.plt", &plt_start, &plt_size, NULL); + + result &= find_elf_section(format, ".dynsym", &dyn_start, &dyn_size, NULL); + + result &= find_elf_section(format, ".dynstr", &str_start, &str_size, NULL); + + + + if (result) + { + + + + result = load_elf_relocation_table(format, &plt_start, &plt_size, &dyn_start, &dyn_size, &str_start, &str_size); + + if (result) + { + instructions = decode_elf_relocations(format, &count); + + translate_elf_relocations(format, instructions, count); + + /* TODO : free instructions */ + + } + + + } + return result; } @@ -96,11 +163,11 @@ bool load_elf_symbols(elf_format *format) /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à compléter. * -* sym_start = début de la zone à traiter. * -* sym_size = taille de la zone à traiter. * -* 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. * +* Paramètres : format = description de l'exécutable à compléter. * +* sym_start = début de la zone à traiter. * +* sym_size = taille de la zone à traiter. * +* 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 : Charge en mémoire la liste humaine des symboles (32 bits). * * * @@ -149,11 +216,11 @@ bool load_elf_symbol_table_32(elf_format *format, const off_t *sym_start, const /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à compléter. * -* sym_start = début de la zone à traiter. * -* sym_size = taille de la zone à traiter. * -* 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. * +* Paramètres : format = description de l'exécutable à compléter. * +* sym_start = début de la zone à traiter. * +* sym_size = taille de la zone à traiter. * +* 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 : Charge en mémoire la liste humaine des symboles (64 bits). * * * @@ -241,3 +308,219 @@ void get_elf_symbol_comments(const elf_format *format, char ***comments, uint64_ } } + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* DETAIL DES SYMBOLES EXTERNES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* plt_start = début de la zone à traiter. * +* plt_size = taille de la zone à traiter. * +* 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 : Charge en mémoire la liste des symboles dynamiques. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_elf_relocation_table(elf_format *format, const off_t *plt_start, const off_t *plt_size, const off_t *dyn_start, const off_t *dyn_size, const off_t *str_start, const off_t *str_size) +{ + off_t iter; /* Boucle de parcours */ + Elf_Rel reloc; /* Infos de relocalisation */ + off_t index; /* Indice de la portion visée */ + char *name; /* Nom du symbole trouvé */ + + for (iter = *plt_start; iter < (*plt_start + *plt_size); iter += ELF_SIZEOF_REL(format)) + { + memcpy(&reloc, &EXE_FORMAT(format)->content[iter], ELF_SIZEOF_REL(format)); + + switch (format->header.e_machine) + { + case EM_386: + switch (ELF32_R_TYPE(ELF_REL_TYPE(format, reloc))) + { + case R_386_JMP_SLOT: + + index = ELF_REL_SYM(format, reloc); + name = get_elf_dynamic_symbol_info(format, dyn_start, dyn_size, &index, str_start, str_size); + + if (name != NULL) + { + format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol)); + + format->symbols[format->sym_count - 1].name = name; + format->symbols[format->sym_count - 1].address = ELF_REL(format, reloc, r_offset); + + } + + break; + + default: + printf("Relocation not supported (%lld) !\n", ELF_REL_TYPE(format, reloc)); + break; + + } + break; + + default: + printf("Machine not recognized !\n"); + return false; + break; + + } + + + } + + return true; + +} + + +/****************************************************************************** +* * +* 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. * +* index = indice de l'entrée à venir lire. * +* 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 : Récupère les informations d'un symbole dynamique donné. * +* * +* Retour : Nom du symbole trouvé, ou NULL si erreur ou non adapté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *get_elf_dynamic_symbol_info(elf_format *format, const off_t *dyn_start, const off_t *dyn_size, const off_t *index, const off_t *str_start, const off_t *str_size) +{ + off_t offset; /* Emplacement à venir lire */ + Elf_Sym symbol; /* Symbole aux infos visées */ + + offset = *dyn_start + *index * ELF_SIZEOF_SYM(format); + if ((offset + ELF_SIZEOF_SYM(format)) > (*dyn_start + *dyn_size)) return NULL; + + memcpy(&symbol, &EXE_FORMAT(format)->content[offset], ELF_SIZEOF_SYM(format)); + + if (ELF_SYM(format, symbol, st_name) >= *str_size) return NULL; + + return (char *)&EXE_FORMAT(format)->content[*str_start + ELF_SYM(format, symbol, st_name)]; + +} + + +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +asm_instr **decode_elf_relocations(elf_format *format, size_t *count) +{ + asm_instr **result; /* Liste à renvoyer */ + off_t rel_start; /* Début de section */ + off_t rel_size; /* Taille de section */ + uint64_t rel_vaddress; /* Adresse virtuelle associée */ + off_t pos; /* Tête de lecture */ + uint64_t offset; /* Adresse virtuelle courante */ + asm_instr *instr; /* Instruction décodée */ + + asm_processor *proc; /* TODO : remove me ! */ + proc = create_x86_processor(); + + result = NULL; + *count = 0; + + if (find_elf_section(format, ".plt", &rel_start, &rel_size, &rel_vaddress)) + for (pos = 0; pos < rel_size; ) + { + offset = rel_vaddress + pos; + + instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, offset); + + result = (asm_instr **)realloc(result, ++(*count) * sizeof(asm_instr *)); + 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, asm_instr **instructions, size_t count) +{ + size_t i; /* Boucle de parcours #1 */ + uint64_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 */ + + for (i = 0; (i + 2) < count; ) + { + if (instructions[i]->type == AIT_JUMP + && instructions[i + 1]->type == AIT_PUSH + && instructions[i + 2]->type == AIT_JUMP) + { + if (get_imm_operand_value(instructions[i]->operands[0], AOS_64_BITS, &address)) + for (j = 0; j < format->sym_count; j++) + if (format->symbols[j].address == address) + { + new_len = strlen(format->symbols[j].name) + 4 + 1; + new_name = calloc(new_len, sizeof(char)); + snprintf(new_name, new_len, "%s@plt", format->symbols[j].name); + + format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol)); + + format->symbols[format->sym_count - 1].name = new_name; + format->symbols[format->sym_count - 1].address = instructions[i]->vaddress; + + } + + i += 3; + + } + else i++; + + } + +} |