summaryrefslogtreecommitdiff
path: root/src/format/elf
diff options
context:
space:
mode:
Diffstat (limited to 'src/format/elf')
-rw-r--r--src/format/elf/Makefile.am1
-rw-r--r--src/format/elf/e_elf.c18
-rw-r--r--src/format/elf/elf-int.h14
-rw-r--r--src/format/elf/helper_mips.c2
-rw-r--r--src/format/elf/helper_x86.c226
-rw-r--r--src/format/elf/helper_x86.h41
-rw-r--r--src/format/elf/symbol.c251
7 files changed, 337 insertions, 216 deletions
diff --git a/src/format/elf/Makefile.am b/src/format/elf/Makefile.am
index fa481ca..822ea44 100644
--- a/src/format/elf/Makefile.am
+++ b/src/format/elf/Makefile.am
@@ -5,6 +5,7 @@ libformatelf_la_SOURCES = \
e_elf.h e_elf.c \
elf-int.h \
helper_mips.h helper_mips.c \
+ helper_x86.h helper_x86.c \
section.h section.c \
strings.h strings.c \
symbol.h symbol.c
diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c
index e974b51..081e245 100644
--- a/src/format/elf/e_elf.c
+++ b/src/format/elf/e_elf.c
@@ -590,22 +590,8 @@ bool resolve_elf_symbol(const elf_format *format, char **label, SymbolType *type
GBinRoutine **get_all_elf_routines(const elf_format *format, size_t *count)
{
- GBinRoutine **result; /* Tableau à retourner */
- size_t i; /* Boucle de parcours */
-
- result = (GBinRoutine **)calloc(format->sym_count, sizeof(GBinRoutine *));
- *count = format->sym_count;
-
- for (i = 0; i < format->sym_count; i++)
- {
- result[i] = g_binary_routine_new();
+ *count = format->routines_count;
- g_binary_routine_set_address(result[i], format->symbols[i].address);
- g_binary_routine_set_size(result[i], format->symbols[i].size);
- g_binary_routine_set_name(result[i], strdup(format->symbols[i].name));
-
- }
-
- return result;
+ return format->routines;
}
diff --git a/src/format/elf/elf-int.h b/src/format/elf/elf-int.h
index 65fc922..b828a88 100644
--- a/src/format/elf/elf-int.h
+++ b/src/format/elf/elf-int.h
@@ -52,6 +52,14 @@ typedef struct _elf_symbol
} elf_symbol;
+/* Relocalisation trouvée */
+typedef struct _elf_relocation
+{
+ const char *name; /* Désignation du symbole */
+ vmpa_t address; /* Adresse du symbole */
+
+} elf_relocation;
+
/* Description du format ELF */
@@ -65,6 +73,12 @@ struct _elf_format
char *sec_names; /* Noms des sections */
size_t sec_size; /* Taille de ces définitions */
+ elf_relocation *relocations; /* Liste des relocalisations */
+ size_t rel_count; /* Taille de cette liste */
+
+ GBinRoutine **routines; /* Liste des routines trouvées */
+ size_t routines_count; /* Nombre de ces routines */
+
elf_symbol *symbols; /* Liste des symboles */
size_t sym_count; /* Taille de cette liste */
diff --git a/src/format/elf/helper_mips.c b/src/format/elf/helper_mips.c
index b56db5d..7b1da76 100644
--- a/src/format/elf/helper_mips.c
+++ b/src/format/elf/helper_mips.c
@@ -41,7 +41,7 @@
* *
* Description : Déduit les adresses effectives des appels externes. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
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, &sections, &sec_count);
+
+ for (i = 0; i < sec_count; i++)
+ if (ELF_SHDR(format, &sections[i], sh_entsize) > 0)
+ {
+ get_elf_section_content(format, &sections[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++;
+
+ }
+
+}
diff --git a/src/format/elf/helper_x86.h b/src/format/elf/helper_x86.h
new file mode 100644
index 0000000..957c8c3
--- /dev/null
+++ b/src/format/elf/helper_x86.h
@@ -0,0 +1,41 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * helper_x86.h - prototypes pour la 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/>.
+ */
+
+
+#ifndef _FORMAT_ELF_HELPER_X86_H
+#define _FORMAT_ELF_HELPER_X86_H
+
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+
+#include "e_elf.h"
+
+
+
+/* Déduit les adresses effectives des appels externes. */
+bool g_elf_format_find_x86_dynamic_symbols(elf_format *, off_t, off_t, off_t, off_t);
+
+
+
+#endif /* _FORMAT_ELF_HELPER_X86_H */
diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c
index 225e032..4fd56fe 100644
--- a/src/format/elf/symbol.c
+++ b/src/format/elf/symbol.c
@@ -36,6 +36,7 @@
#include "elf-int.h"
+#include "helper_mips.h"
#include "section.h"
@@ -51,12 +52,6 @@ bool load_elf_relocation_table(elf_format *, const off_t *, const off_t *, const
/* 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);
-
@@ -102,8 +97,6 @@ bool load_elf_symbols(elf_format *format)
off_t dyn_size; /* Taille de section */
- //asm_instr **instructions; /* Instructions décodées */
-
result = true;
@@ -137,56 +130,11 @@ bool load_elf_symbols(elf_format *format)
}
- /* Liaison dynamique (si elle existe) */
-
- test = find_elf_section_by_name(format, ".dynsym", &section);
-
- if (!test)
- {
- test = find_elf_section_by_type(format, SHT_HASH, &sections, &count);
-
- if (test)
- test = find_elf_section_by_index(format, ELF_SHDR(format, &sections[0], sh_link), &section);
-
- }
-
- if (test)
- {
- get_elf_section_content(format, &section, &dyn_start, &dyn_size, NULL);
-
- result &= find_elf_section_by_index(format, ELF_SHDR(format, &section, sh_link), &section);
-
- }
-
- if (result)
- {
- get_elf_section_content(format, &section, &str_start, &str_size, NULL);
+ /* Relocalisations */
- switch (get_elf_target_machine(format))
- {
- case FTM_MIPS:
- result = g_elf_format_find_mips_dynamic_symbols(format, dyn_start, dyn_size, str_start, str_size);
- break;
- default:
- break;
-
- }
-
- }
-
-
-
-
-
-
-
-
-
-
-
-#if 0
+ /* TODO : fixme ! */
find_elf_section_by_type(format, SHT_REL, &sections, &count);
@@ -215,35 +163,59 @@ bool load_elf_symbols(elf_format *format)
result = load_elf_relocation_table(format, &rel_start, &rel_size, &dyn_start, &dyn_size, &str_start, &str_size);
-
}
}
free(sections);
- /* Récupération (seconde partie) */
+ /* TODO : fixme ! */
- /* switch ... */
- g_elf_format_translate_mips_external_calls(format);
- exit(0);
+ /* Liaison dynamique (si elle existe) */
- if (result)
+ test = find_elf_section_by_name(format, ".dynsym", &section);
+
+ if (!test)
{
-#if 0
- instructions = decode_elf_relocations(format, &count);
+ test = find_elf_section_by_type(format, SHT_HASH, &sections, &count);
- translate_elf_relocations(format, instructions, count);
+ if (test)
+ test = find_elf_section_by_index(format, ELF_SHDR(format, &sections[0], sh_link), &section);
+
+ }
+
+ if (test)
+ {
+ get_elf_section_content(format, &section, &dyn_start, &dyn_size, NULL);
+
+ result &= find_elf_section_by_index(format, ELF_SHDR(format, &section, sh_link), &section);
- /* TODO : free instructions */
-#endif
}
-#endif
+ if (result)
+ {
+ get_elf_section_content(format, &section, &str_start, &str_size, NULL);
+
+ switch (get_elf_target_machine(format))
+ {
+ case FTM_MIPS:
+ result = g_elf_format_find_mips_dynamic_symbols(format, dyn_start, dyn_size, str_start, str_size);
+ break;
+
+ case FTM_386:
+ result = g_elf_format_find_x86_dynamic_symbols(format, dyn_start, dyn_size, str_start, str_size);
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
return result;
@@ -274,6 +246,7 @@ bool load_elf_symbol_table_32(elf_format *format, const off_t *sym_start, const
{
off_t iter; /* Boucle de parcours */
Elf32_Sym symbol; /* Symbole ELF lu */
+ GBinRoutine *routine; /* Nouvelle routine trouvée */
if (*sym_size % sizeof(Elf32_Sym) != 0) return false;
@@ -293,11 +266,16 @@ bool load_elf_symbol_table_32(elf_format *format, const off_t *sym_start, const
/* Si le symbole possède un nom... */
if (strlen(&EXE_FORMAT(format)->content[*str_start + symbol.st_name]) > 0)
{
- format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol));
+ routine = g_binary_routine_new();
- format->symbols[format->sym_count - 1].name = &EXE_FORMAT(format)->content[*str_start + symbol.st_name];
- format->symbols[format->sym_count - 1].address = symbol.st_value;
- format->symbols[format->sym_count - 1].size = symbol.st_size;
+ g_binary_routine_set_name(routine, strdup(&EXE_FORMAT(format)->content[*str_start + symbol.st_name]));
+ g_binary_routine_set_address(routine, symbol.st_value);
+ g_binary_routine_set_size(routine, symbol.st_size);
+
+ format->routines = (GBinRoutine **)realloc(format->routines,
+ ++format->routines_count * sizeof(GBinRoutine *));
+
+ format->routines[format->routines_count - 1] = routine;
}
@@ -456,10 +434,10 @@ bool load_elf_relocation_table(elf_format *format, const off_t *plt_start, const
if (name != NULL)
{
- format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol));
+ format->relocations = (elf_symbol *)realloc(format->relocations, ++format->rel_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);
+ format->relocations[format->rel_count - 1].name = name;
+ format->relocations[format->rel_count - 1].address = ELF_REL(format, reloc, r_offset);
}
@@ -519,128 +497,3 @@ char *get_elf_dynamic_symbol_info(elf_format *format, const off_t *dyn_start, co
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 : - *
-* *
-******************************************************************************/
-#if 0
-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 */
- Elf_Shdr *sections; /* Groupe de sections trouvées */
- size_t sec_count; /* Quantité de données */
- size_t i; /* Boucle de parcours */
- off_t pos; /* Tête de lecture */
- uint64_t offset; /* Adresse virtuelle courante */
- asm_instr *instr; /* Instruction décodée */
-#if 0
- asm_processor *proc; /* TODO : remove me ! */
- proc = create_x86_processor();
-
- result = NULL;
- *count = 0;
-
- if (!find_elf_section_content_by_name(format, ".plt", &rel_start, &rel_size, &rel_vaddress))
- {
- printf("No .plt section found ! Trying to guess it...\n");
-
- find_elf_section_by_type(format, SHT_PROGBITS, &sections, &sec_count);
-
- for (i = 0; i < sec_count; i++)
- if (ELF_SHDR(format, &sections[i], sh_entsize) > 0)
- {
- get_elf_section_content(format, &sections[i], &rel_start, &rel_size, &rel_vaddress);
- break;
- }
-
- free(sections);
-
- if (i == sec_count) return NULL;
-
- }
-
- for (pos = 0; pos < rel_size; )
- {
- offset = rel_vaddress + pos;
-
- instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, 0/* FIXME*/, offset);
-
- result = (asm_instr **)realloc(result, ++(*count) * sizeof(asm_instr *));
- result[*count - 1] = instr;
-
- }
-#endif
-
- result = NULL;
- *count = 0;
-
- return result;
-
-}
-#endif
-#if 0
-/******************************************************************************
-* *
-* 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]->type == AIT_CALL)
- && instructions[i + 1]->type == AIT_PUSH
- && instructions[i + 2]->type == AIT_JUMP)
- {
- if (get_imm_operand_value(instructions[i]->operands[0], AOS_64_BITS_UNSIGNED, &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++;
-
- }
-
-}
-#endif