/* Chrysalide - Outil d'analyse de fichiers binaires * helper_x86.c - gestion auxiliaire de l'architecture x86 * * Copyright (C) 2009-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 "helper_x86.h" bool load_elf_x86_relocated_symbols(GElfFormat *a, const elf_shdr *b, const elf_shdr *c, const elf_shdr *d) { return false; } /* Déduit les adresses effectives des appels externes. */ bool find_elf_x86_dynamic_symbols(GElfFormat *a, const elf_shdr *b, const elf_shdr *c, const elf_shdr *d, const elf_shdr *e) { return false; } #if 0 #include #include #include #include "elf-int.h" #include "../symbol.h" #include "../mangling/demangler.h" #include "../../arch/immediate.h" #include "../../arch/processor.h" #include "../../arch/x86/instruction.h" // Désactivation #define g_x86_instruction_get_opcode(i) 0 /* symbols.c : Récupère la désignation d'un symbole donné. */ extern const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf_shdr *, off_t); /* Décode les instructions liées à la relocalisation. */ GArchInstruction **decode_elf_relocations(GElfFormat *, const elf_shdr *, size_t *); /* Déduit les adresses effectives des relocalisations. */ void translate_exe_elf_relocations(GElfFormat *, GArchInstruction **, size_t); /* Déduit les adresses effectives des relocalisations. */ void translate_dyn_elf_relocations(GElfFormat *, GArchInstruction **, size_t, const elf_shdr *, const elf_shdr *, const elf_shdr *); /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * relxxx = section .rel.xxx trouvée (zone à traiter). * * dynsym = section .dynsym trouvée (info. dynamiques). * * dynstr = section .dynstr trouvée (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_x86_relocated_symbols(GElfFormat *format, const elf_shdr *relxxx, const elf_shdr *dynsym, const elf_shdr *dynstr) { bool result; /* Bilan à retourner */ off_t rel_start; /* Début de la zone à traiter */ off_t rel_size; /* Taille de cette même zone */ off_t iter; /* Boucle de parcours */ elf_rel reloc; /* Infos de relocalisation */ off_t index; /* Indice de la portion visée */ const char *name; /* Nom du symbole trouvé */ GBinSymbol *symbol; /* Nouveau symbole construit */ result = true; get_elf_section_content(format, relxxx, &rel_start, &rel_size, NULL); printf("rel :: %d -> %d\n", rel_start, rel_start + rel_size); for (iter = rel_start; iter < (rel_start + rel_size); ) { result = false;//read_elf_relocation(format, &iter, &reloc); if (!result) break; switch (ELF_REL_TYPE(format, reloc)) { case R_386_NONE: break; case R_386_JMP_SLOT: index = ELF_REL_SYM(format, reloc); name = get_elf_symbol_name(format, dynsym, dynstr, index); //printf("got a jump ! >> %d - %s\n", index, name); if (name == NULL) { /* FIXME */ name = "unknown"; } symbol = g_binary_symbol_new(NULL, STP_ROUTINE); g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); break; default: printf("Relocation not supported (%lld) !\n", ELF_REL_TYPE(format, reloc)); break; } } return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * plt = section .plt trouvée (points d'entrées dynamiques). * * rel = section .rel.plt présentant la table des symboles. * * dynsym = section listant tous les symboles. * * dynstr = section contenant le nom de ces symboles. * * * * Description : Déduit les adresses effectives des appels externes. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool find_elf_x86_dynamic_symbols(GElfFormat *format, const elf_shdr *plt, const elf_shdr *rel, const elf_shdr *dynsym, const elf_shdr *dynstr) { GArchInstruction **instructions; /* Instructions décodées */ size_t count; /* Quantité d'instructions */ size_t i; /* Boucle de parcours */ instructions = decode_elf_relocations(format, plt, &count); switch (ELF_HDR(format, format->header, e_type)) { case ET_EXEC: translate_exe_elf_relocations(format, instructions, count); break; case ET_DYN: translate_dyn_elf_relocations(format, instructions, count, rel, dynsym, dynstr); break; } 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. * * plt = section .plt trouvée (points d'entrées dynamiques). * * 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(GElfFormat *format, const elf_shdr *plt, 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 */ 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; get_elf_section_content(format, plt, &plt_start, &plt_size, &plt_address); proc = NULL;//get_arch_processor_for_type(APT_386); for (pos = 0; pos < plt_size; ) { address = plt_address + pos; #if 0 instr = g_arch_processor_decode_instruction(proc, NULL /*FIXME*/, &G_BIN_FORMAT(format)->content[plt_start], &pos, plt_size, address, NULL /*FIXME*/); #endif 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_exe_elf_relocations(GElfFormat *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 */ const GArchOperand *operand; /* Valeur du saut */ vmpa_t address; /* Adresse virtuelle finale */ GBinSymbol **symbols; /* Liste des symboles existants*/ size_t symbols_count; /* Taille de cette liste */ 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 */ GBinSymbol *symbol; /* Nouveau symbole construit */ 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); if (g_imm_operand_to_vmpa_t(G_IMM_OPERAND(operand), &address)) { symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &symbols_count); for (j = 0; j < symbols_count; j++) if (0 /* FIXME g_binary_symbol_get_address(symbols[j]) == address*/) { /* Nom final */ new_len = strlen(g_binary_symbol_get_label(symbols[j])) + 4 + 1; new_name = calloc(new_len, sizeof(char)); snprintf(new_name, new_len, "%s@plt", g_binary_symbol_get_label(symbols[j])); g_arch_instruction_get_location(instructions[i], NULL, NULL, &address); /* Routine */ routine = try_to_demangle_routine(g_binary_symbol_get_label(symbols[j])); ///g_binary_routine_set_address(routine, address); ///// reactiver g_binary_format_add_routine(G_BIN_FORMAT(format), routine); /* Symbole uniquement */ symbol = g_binary_symbol_new(NULL, STP_ROUTINE); g_binary_symbol_attach_routine(symbol, routine); g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); break; } } i += 3; } else i++; } } /****************************************************************************** * * * 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_dyn_elf_relocations(GElfFormat *format, GArchInstruction **instructions, size_t count, const elf_shdr *rel, const elf_shdr *dynsym, const elf_shdr *dynstr) { off_t rel_start; /* Début de la zone à traiter */ off_t rel_size; /* Taille de cette même zone */ 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 */ const GArchOperand *operand; /* Valeur du saut */ off_t pos; /* Tête de lecture */ bool negative; /* Tête de lecture invalide ? */ elf_rel reloc; /* Infos de relocalisation */ off_t index; /* Indice de la portion visée */ const char *name; /* Nom du symbole trouvé */ size_t new_len; /* Taille du nouveau nom */ char *new_name; /* Nom avec suffixe @plt */ vmpa_t address; /* Adresse virtuelle finale */ GBinRoutine *routine; /* Nouvelle routine déduite */ GBinSymbol *symbol; /* Nouveau symbole construit */ get_elf_section_content(format, rel, &rel_start, &rel_size, NULL); 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 + 1], 0); if (!g_imm_operand_to_off_t(G_IMM_OPERAND(operand), &pos, &negative)) goto next_op; if ((pos + ELF_SIZEOF_REL(format)) > rel_size) goto next_op; pos += rel_start; if (!false/*read_elf_relocation(format, &pos, &reloc)*/) goto next_op; index = ELF_REL_SYM(format, reloc); name = get_elf_symbol_name(format, dynsym, dynstr, index); if (name == NULL) { /* FIXME */ name = "unknown"; } /* Nom final */ new_len = strlen(name) + 4 + 1; new_name = calloc(new_len, sizeof(char)); snprintf(new_name, new_len, "%s@plt", name); g_arch_instruction_get_location(instructions[i], NULL, NULL, &address); /* Routine */ routine = try_to_demangle_routine(name); ////g_binary_routine_set_address(routine, address); ///// reactiver g_binary_format_add_routine(G_BIN_FORMAT(format), routine); /* Symbole uniquement */ symbol = g_binary_symbol_new(NULL, STP_ROUTINE); g_binary_symbol_attach_routine(symbol, routine); g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol); next_op: i += 3; } else i++; } } #endif