/* Chrysalide - Outil d'analyse de fichiers binaires * header.c - annotation des en-têtes de section de binaires ELF * * Copyright (C) 2015 Cyrille Bagard * * This file is part of Chrysalide. * * 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 . */ #include "section.h" #include #include #include #include #include #include /* Charge tous les symboles liés à un en-tête de section ELF. */ static bool annotate_elf_section_header(GElfFormat *, SourceEndian, const elf_shdr *, vmpa2t *); /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * endian = boutisme présentement utilisé. * * strings = section renvoyant vers des chaînes de caractères. * * pos = tête de lecture à déplacer. [OUT] * * * * Description : Charge tous les symboles liés à un en-tête de section ELF. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool annotate_elf_section_header(GElfFormat *format, SourceEndian endian, const elf_shdr *strings, vmpa2t *pos) { elf_shdr shdr; /* En-tête de programme ELF */ GBinContent *content; /* Contenu binaire à lire */ const char *secname; /* Nom d'une section analysée */ ImmOperandDisplay disp; /* Afficahge de valeur */ const char *text; /* Texte constant à insérer */ vmpa2t start; /* Localisation des symboles */ GArchInstruction *instr; /* Instruction décodée */ GArchOperand *operand; /* Opérande à venir modifier */ GDbComment *comment; /* Définition de commentaire */ GBinSymbol *symbol; /* Symbole à intégrer */ char *dtext; /* Texte dynamique à créer */ bool filled; /* Suivi de mise en place */ if (!read_elf_section_header(format, get_phy_addr(pos), &shdr)) return false; content = g_binary_format_get_content(G_BIN_FORMAT(format)); /* Champ "sh_name" */ secname = extract_name_from_elf_string_section(format, strings, ELF_SHDR(format, shdr, sh_name)); if (secname == NULL) dtext = strdup(_("Section name: ")); else { dtext = strdup(_("Section name: '")); dtext = stradd(dtext, secname); dtext = stradd(dtext, "'"); } copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, dtext); free(dtext); /* Champ "sh_type" */ disp = IOD_DEC; switch (ELF_SHDR(format, shdr, sh_type)) { case SHT_NULL: text = _("Section type: unused"); break; case SHT_PROGBITS: text = _("Section type: program data"); break; case SHT_SYMTAB: text = _("Section type: symbol table"); break; case SHT_STRTAB: text = _("Section type: string table"); break; case SHT_RELA: text = _("Section type: relocation entries with addends"); break; case SHT_HASH: text = _("Section type: symbol hash table"); break; case SHT_DYNAMIC: text = _("Section type: dynamic linking information"); break; case SHT_NOTE: text = _("Section type: notes"); break; case SHT_NOBITS: text = _("Section type: program space with no data (bss)"); break; case SHT_REL: text = _("Section type: relocation entries, no addends"); break; case SHT_SHLIB: text = _("Section type: reserved"); break; case SHT_DYNSYM: text = _("Section type: dynamic linker symbol table"); break; case SHT_INIT_ARRAY: text = _("Section type: array of constructors"); break; case SHT_FINI_ARRAY: text = _("Section type: array of destructors"); break; case SHT_PREINIT_ARRAY: text = _("Section type: array of pre-constructors"); break; case SHT_GROUP: text = _("Section type: section group"); break; case SHT_SYMTAB_SHNDX: text = _("Section type: extended section indeces"); break; case SHT_LOOS ... SHT_HIOS: disp = IOD_HEX; switch (ELF_SHDR(format, shdr, sh_type)) { case SHT_GNU_ATTRIBUTES: text = _("Section type: object attributes"); break; case SHT_GNU_HASH: text = _("Section type: GNU-style hash table"); break; case SHT_GNU_LIBLIST: text = _("Section type: prelink library list"); break; case SHT_CHECKSUM: text = _("Section type: checksum for DSO content"); break; case SHT_LOSUNW ... SHT_HISUNW: switch (ELF_SHDR(format, shdr, sh_type)) { case SHT_SUNW_move: text = _("Section type: SHT_SUNW_move"); break; case SHT_SUNW_COMDAT: text = _("Section type: SHT_SUNW_COMDAT"); break; case SHT_SUNW_syminfo: text = _("Section type: SHT_SUNW_syminfo"); break; case SHT_GNU_verdef: text = _("Section type: version definition section"); break; case SHT_GNU_verneed: text = _("Section type: version needs section"); break; case SHT_GNU_versym: text = _("Section type: version symbol table"); break; default: text = _("Section type: Sun-specific"); break; } break; default: text = _("Section type: OS-specific"); break; } break; case SHT_LOPROC ... SHT_HIPROC: disp = IOD_HEX; text = _("Section type: processor-specific"); break; case SHT_LOUSER ... SHT_HIUSER: disp = IOD_HEX; text = _("Section type: application-specific"); break; default: disp = IOD_HEX; text = _("Section type: unknown"); break; } copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, disp); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, text); /* Champ "sh_flags"... */ dtext = strdup(_("Section flags: ")); filled = false; if (ELF_SHDR(format, shdr, sh_type) & SHF_WRITE) { dtext = stradd(dtext, "W"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_ALLOC) { dtext = stradd(dtext, "A"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_EXECINSTR) { dtext = stradd(dtext, "X"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_MERGE) { dtext = stradd(dtext, "M"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_LINK_ORDER) { dtext = stradd(dtext, "L"); filled = true; } if (ELF_SHDR(format, shdr, sh_type) & SHF_TLS) { dtext = stradd(dtext, "T"); filled = true; } if (!filled) dtext = stradd(dtext, _("none")); if (format->is_32b) { /* Champ "sh_flags" (suite) */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, dtext); free(dtext); /* Champ "sh_addr" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Section virtual addr at execution")); /* Champ "sh_offset" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Section file offset")); /* Champ "sh_size" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Section size in bytes")); } else { /* Champ "sh_flags" (suite) */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, dtext); free(dtext); /* Champ "sh_addr" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Section virtual addr at execution")); /* Champ "sh_offset" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Section file offset")); /* Champ "sh_size" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Section size in bytes")); } /* Champ "sh_link" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Link to another section")); /* Champ "sh_info" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Additional section information")); if (format->is_32b) { /* Champ "sh_addralign" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Section alignment")); /* Champ "sh_entsize" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_32_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Entry size if section holds table")); } else { /* Champ "sh_addralign" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Section alignment")); /* Champ "sh_entsize" */ copy_vmpa(&start, pos); instr = g_raw_instruction_new_array(content, MDS_64_BITS, 1, pos, endian); SET_IMM_DISPLAY(instr, operand, 0, IOD_DEC); ADD_RAW_AS_SYM(format, symbol, &start, instr, comment, _("Entry size if section holds table")); } g_object_unref(G_OBJECT(content)); return true; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * status = barre de statut à tenir informée. * * * * Description : Charge tous les symboles liés aux en-têtes de section ELF. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool annotate_elf_section_header_table(GElfFormat *format, GtkStatusStack *status) { bool result; /* Bilan à retourner */ const elf_header *header; /* En-tête principale */ SourceEndian endian; /* Boutisme utilisé */ elf_shdr strings; /* Section des descriptions */ off_t offset; /* Tête de lecture du binaire */ vmpa2t pos; /* Localisation des symboles */ uint16_t e_shnum; /* Nombre d'éléments 'Program' */ activity_id_t msg; /* Message de progression */ uint16_t i; /* Boucle de parcours */ result = true; header = g_elf_format_get_header(format); endian = g_binary_format_get_endianness(G_BIN_FORMAT(format)); if (!find_elf_section_by_index(format, ELF_HDR(format, *header, e_shstrndx), &strings)) return false; offset = ELF_HDR(format, *header, e_shoff); init_vmpa(&pos, offset, 0x9900); e_shnum = ELF_HDR(format, *header, e_shnum); msg = gtk_status_stack_add_activity(status, _("Writing annotations for all Elf section headers..."), e_shnum); for (i = 0; i < e_shnum && result; i++) { result = annotate_elf_section_header(format, endian, &strings, &pos); gtk_status_stack_update_activity_value(status, msg, 1); } gtk_status_stack_remove_activity(status, msg); return true; }