summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/instruction-int.h22
-rw-r--r--src/arch/instruction.c2
-rw-r--r--src/arch/operand.c118
-rw-r--r--src/arch/operand.h3
-rw-r--r--src/arch/processor.c5
-rw-r--r--src/arch/x86/instruction.h4
-rw-r--r--src/arch/x86/op_add.c35
-rw-r--r--src/arch/x86/op_jump.c86
-rw-r--r--src/arch/x86/op_push.c6
-rw-r--r--src/arch/x86/opcodes.h9
-rw-r--r--src/arch/x86/operand.c26
-rw-r--r--src/arch/x86/processor.c18
-rw-r--r--src/format/elf/e_elf.c12
-rw-r--r--src/format/elf/elf-int.h33
-rw-r--r--src/format/elf/symbol.c305
15 files changed, 664 insertions, 20 deletions
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index 72c7914..895c29f 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -40,11 +40,33 @@
#define DB_OPCODE 0x00
+
+/* Typage des instructions rencontrées */
+typedef enum _AsmInstrType
+{
+ AIT_OTHER, /* Instruction inintéressante */
+
+ AIT_DB, /* Instruction non décodée */
+
+ AIT_PUSH, /* Empilement de valeur */
+ AIT_POP, /* Dépilement de valeur */
+ AIT_JUMP, /* Saut à une adresse */
+
+ AIT_CALL /* Appel d'une fonction */
+
+} AsmInstrType;
+
+
+
/* Définition générique d'une instruction */
struct _asm_instr
{
uint8_t opcode;
+ uint64_t vaddress; /* Adresse virtuelle associée */
+
+ AsmInstrType type; /* Type d'instruction */
+
asm_operand **operands; /* Liste des opérandes */
size_t operands_count; /* Nbre. d'opérandes utilisées */
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index e199dc5..ada3d58 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -53,6 +53,8 @@ asm_instr *create_db_instruction(const uint8_t *data, off_t *pos, off_t len)
result->opcode = DB_OPCODE;
+ result->type = AIT_DB;
+
/* TODO: check result */
result->operands = (asm_operand **)calloc(1, sizeof(asm_operand *));
result->operands[0] = (asm_operand *)calloc(1, sizeof(asm_operand));
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 53e652c..fa43416 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -367,6 +367,124 @@ bool fill_relimm_operand(asm_operand *operand, AsmOperandSize size, const uint8_
/******************************************************************************
* *
+* Paramètres : operand = structure dont le contenu est à définir. *
+* size = taille de l'opérande souhaitée. *
+* ... = zone d'enregistrement prévue. *
+* *
+* Description : Récupère la valeur d'une opérande sur x bits. *
+* *
+* Retour : true si l'opération s'est effectuée avec succès, false sinon.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool get_imm_operand_value(asm_operand *operand, AsmOperandSize size, ...)
+{
+ bool result; /* Bilan à retourner */
+ va_list ap; /* Récupération d'argument */
+ uint8_t *val8; /* Valeur sur 8 bits */
+ uint16_t *val16; /* Valeur sur 16 bits */
+ uint32_t *val32; /* Valeur sur 32 bits */
+ uint64_t *val64; /* Valeur sur 64 bits */
+
+ result = true;
+
+ va_start(ap, size);
+
+ switch (size)
+ {
+ case AOS_8_BITS:
+ val8 = va_arg(ap, uint8_t *);
+ switch (operand->size)
+ {
+ case AOS_8_BITS:
+ *val8 = operand->value.val8;
+ break;
+ case AOS_16_BITS:
+ result = false;
+ break;
+ case AOS_32_BITS:
+ result = false;
+ break;
+ case AOS_64_BITS:
+ result = false;
+ break;
+ }
+ break;
+
+ case AOS_16_BITS:
+ val16 = va_arg(ap, uint16_t *);
+ switch (operand->size)
+ {
+ case AOS_8_BITS:
+ *val16 = operand->value.val8;
+ break;
+ case AOS_16_BITS:
+ *val16 = operand->value.val16;
+ break;
+ case AOS_32_BITS:
+ result = false;
+ break;
+ case AOS_64_BITS:
+ result = false;
+ break;
+ }
+ break;
+
+ case AOS_32_BITS:
+ val32 = va_arg(ap, uint32_t *);
+ switch (operand->size)
+ {
+ case AOS_8_BITS:
+ *val32 = operand->value.val8;
+ break;
+ case AOS_16_BITS:
+ *val32 = operand->value.val16;
+ break;
+ case AOS_32_BITS:
+ *val32 = operand->value.val32;
+ break;
+ case AOS_64_BITS:
+ result = false;
+ break;
+ }
+ break;
+
+ case AOS_64_BITS:
+ val64 = va_arg(ap, uint64_t *);
+ switch (operand->size)
+ {
+ case AOS_8_BITS:
+ *val64 = operand->value.val8;
+ break;
+ case AOS_16_BITS:
+ *val64 = operand->value.val16;
+ break;
+ case AOS_32_BITS:
+ *val64 = operand->value.val32;
+ break;
+ case AOS_64_BITS:
+ *val64 = operand->value.val64;
+ break;
+ }
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ va_end(ap);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = instruction à traiter. *
* buffer = tampon de sortie mis à disposition. [OUT] *
* len = taille de ce tampon. *
diff --git a/src/arch/operand.h b/src/arch/operand.h
index a05f819..0a00d9f 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -76,6 +76,9 @@ bool fill_imm_operand_with_value(asm_operand *, AsmOperandSize, ...);
/* Crée une opérande contenant une valeur relative sur x bits. */
bool fill_relimm_operand(asm_operand *, AsmOperandSize, const uint8_t *, off_t *, off_t, uint64_t);
+/* Récupère la valeur d'une opérande sur x bits. */
+bool get_imm_operand_value(asm_operand *, AsmOperandSize, ...);
+
/* Traduit une opérande de valeur immédiate en texte. */
void print_imm_operand(const asm_operand *, char *, size_t, AsmSyntax);
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 373222f..fc9f773 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -24,12 +24,14 @@
#include "processor.h"
+#include "instruction-int.h"
#include "processor-int.h"
+
/******************************************************************************
* *
* Paramètres : proc = architecture visée par la procédure. *
@@ -66,6 +68,9 @@ asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, of
}
+ result->vaddress = offset;
+
+
return result;
diff --git a/src/arch/x86/instruction.h b/src/arch/x86/instruction.h
index 8ef603f..baf911d 100644
--- a/src/arch/x86/instruction.h
+++ b/src/arch/x86/instruction.h
@@ -38,6 +38,8 @@ typedef struct _asm_x86_instr asm_x86_instr;
/* Enumération de tous les opcodes */
typedef enum _X86Opcodes
{
+ X86_OP_ADD_RM8_R8, /* add (0x00) */
+
X86_OP_SUB_R1632_RM1632, /* sub ([0x66] 0x29) */
X86_OP_XOR_RM8_R8, /* xor (0x30) */
@@ -145,12 +147,14 @@ typedef enum _X86Opcodes
X86_OP_INT, /* int (0xcd) */
X86_OP_CALL_REL1632, /* call ([0x66] 0xe8) */
+ X86_OP_JMP_REL1632, /* jmp ([0x66] 0xe9) */
X86_OP_JMP_8, /* jmp (0xeb) */
X86_OP_HLT, /* hlt (0xf4) */
X86_OP_CALL_RM1632, /* call ([0x66] 0xff 2) */
+ X86_OP_JMP_RM1632, /* jmp ([0x66] 0xff 4) */
X86_OP_PUSH_RM1632, /* push ([0x66] 0xff 6) */
X86_OP_COUNT
diff --git a/src/arch/x86/op_add.c b/src/arch/x86/op_add.c
index 52b998f..f42c8f9 100644
--- a/src/arch/x86/op_add.c
+++ b/src/arch/x86/op_add.c
@@ -104,3 +104,38 @@ asm_x86_instr *x86_read_instr_add_imm1632_to_rm1632(const uint8_t *data, off_t *
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'add' (8 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_add_rm8_r8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ if (!x86_read_two_operands(result, data, pos, len, X86_OTP_RM8, X86_OTP_R8))
+ {
+ free(result);
+ return NULL;
+ }
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_jump.c b/src/arch/x86/op_jump.c
index b301b10..3739b24 100644
--- a/src/arch/x86/op_jump.c
+++ b/src/arch/x86/op_jump.c
@@ -54,6 +54,8 @@ asm_x86_instr *x86_read_instr_je_8(const uint8_t *data, off_t *pos, off_t len, u
ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+ ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset))
{
free(result);
@@ -89,6 +91,8 @@ asm_x86_instr *x86_read_instr_jne_8(const uint8_t *data, off_t *pos, off_t len,
ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+ ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset))
{
free(result);
@@ -124,6 +128,8 @@ asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *data, off_t *pos, off_t len,
ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+ ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset))
{
free(result);
@@ -133,3 +139,83 @@ asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *data, off_t *pos, off_t len,
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'jmp' (grand saut relatif). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_jmp_rel1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ oprsize = switch_x86_operand_size_if_needed(proc, data, pos);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
+ if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL1632, oprsize, offset))
+ {
+ free(result);
+ return NULL;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'jmp' (saut en mémoire). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_jmp_rm1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ oprsize = switch_x86_operand_size_if_needed(proc, data, pos);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
+ if (!x86_read_one_operand(result, data, pos, len, X86_OTP_RM1632, oprsize))
+ {
+ free(result);
+ return NULL;
+ }
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_push.c b/src/arch/x86/op_push.c
index ce76919..f51bd6f 100644
--- a/src/arch/x86/op_push.c
+++ b/src/arch/x86/op_push.c
@@ -58,6 +58,8 @@ asm_x86_instr *x86_read_instr_push_imm1632(const uint8_t *data, off_t *pos, off_
ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+ ASM_INSTRUCTION(result)->type = AIT_PUSH;
+
if (!x86_read_one_operand(result, data, pos, len, X86_OTP_IMM1632, oprsize))
{
free(result);
@@ -96,6 +98,8 @@ asm_x86_instr *x86_read_instr_push_r1632(const uint8_t *data, off_t *pos, off_t
ASM_INSTRUCTION(result)->opcode = data[*pos];
+ ASM_INSTRUCTION(result)->type = AIT_PUSH;
+
if (!x86_read_one_operand(result, data, pos, len, X86_OTP_OP_R1632, oprsize, 0x50))
{
free(result);
@@ -134,6 +138,8 @@ asm_x86_instr *x86_read_instr_push_rm1632(const uint8_t *data, off_t *pos, off_t
ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+ ASM_INSTRUCTION(result)->type = AIT_PUSH;
+
if (!x86_read_one_operand(result, data, pos, len, X86_OTP_RM1632, oprsize))
{
free(result);
diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h
index cbadcf5..70d41b8 100644
--- a/src/arch/x86/opcodes.h
+++ b/src/arch/x86/opcodes.h
@@ -43,6 +43,9 @@ asm_x86_instr *x86_read_instr_add_imm8_to_rm1632(const uint8_t *, off_t *, off_t
/* Décode une instruction de type 'add' (16 ou 32 bits). */
asm_x86_instr *x86_read_instr_add_imm1632_to_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+/* Décode une instruction de type 'add' (8 bits). */
+asm_x86_instr *x86_read_instr_add_rm8_r8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'and' (16 ou 32 bits). */
asm_x86_instr *x86_read_instr_and_rm1632_with_imm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
@@ -82,6 +85,12 @@ asm_x86_instr *x86_read_instr_jne_8(const uint8_t *, off_t *, off_t, uint64_t, c
/* Décode une instruction de type 'jump' (petit saut). */
asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+/* Décode une instruction de type 'jmp' (grand saut relatif). */
+asm_x86_instr *x86_read_instr_jmp_rel1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'jmp' (saut en mémoire). */
+asm_x86_instr *x86_read_instr_jmp_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'lea' (16 ou 32 bits). */
asm_x86_instr *x86_read_instr_lea(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c
index 375b0a5..e13c793 100644
--- a/src/arch/x86/operand.c
+++ b/src/arch/x86/operand.c
@@ -1300,7 +1300,8 @@ asm_x86_operand *x86_create_rel1632_operand_in_32b(uint64_t base, const uint8_t
{
asm_x86_operand *result; /* Emplacement à retourner */
off_t init_pos; /* Position avant lecture */
- int8_t offset; /* Décallage à appliquer */
+ int32_t offset32; /* Décallage 32b à appliquer */
+ int16_t offset16; /* Décallage 16b à appliquer */
uint32_t address; /* Adresse finale visée */
result = create_new_x86_operand();
@@ -1308,13 +1309,28 @@ asm_x86_operand *x86_create_rel1632_operand_in_32b(uint64_t base, const uint8_t
init_pos = *pos;
address = base;
- if (!read_imm_value(is_reg32 ? AOS_32_BITS : AOS_16_BITS, data, pos, len, &offset))
+ if (is_reg32)
{
- free(result);
- return NULL;
+ if (!read_imm_value(AOS_32_BITS, data, pos, len, &offset32))
+ {
+ free(result);
+ return NULL;
+ }
+
+ address = base + (*pos - init_pos) + offset32;
+
}
+ else
+ {
+ if (!read_imm_value(AOS_16_BITS, data, pos, len, &offset16))
+ {
+ free(result);
+ return NULL;
+ }
- address = base + (*pos - init_pos) + offset;
+ address = base + (*pos - init_pos) + offset16;
+
+ }
if (!fill_imm_operand_with_value(ASM_OPERAND(result), AOS_32_BITS, &address))
{
diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c
index 0b81a8c..5694d9e 100644
--- a/src/arch/x86/processor.c
+++ b/src/arch/x86/processor.c
@@ -61,7 +61,7 @@ typedef struct _x86_opcode
do { \
target.prefix = _prefix; \
target.opcode = _opcode; \
- target.opt_prefix = true; \
+ target.opt_prefix = (_prefix != 0x00); \
target.has_op_ext = false; \
target.name = _name; \
target.read = _read; \
@@ -72,7 +72,7 @@ typedef struct _x86_opcode
target.prefix = _prefix; \
target.opcode = _opcode; \
target.op_ext = _ext << 3; \
- target.opt_prefix = true; \
+ target.opt_prefix = (_prefix != 0x00); \
target.has_op_ext = true; \
target.name = _name; \
target.read = _read; \
@@ -205,6 +205,8 @@ AsmOperandSize switch_x86_operand_size_if_needed(const asm_x86_processor *proc,
void x86_register_instructions(asm_x86_processor *proc)
{
+ register_opcode(proc->opcodes[X86_OP_ADD_RM8_R8], 0x00, 0x00, "add", x86_read_instr_add_rm8_r8);
+
register_opcode(proc->opcodes[X86_OP_SUB_R1632_RM1632], 0x66, 0x29, "sub", x86_read_instr_sub_r1632_from_rm1632);
register_opcode(proc->opcodes[X86_OP_XOR_RM8_R8], 0x00, 0x30, "xor", x86_read_instr_xor_rm8_with_r8);
@@ -314,12 +316,14 @@ void x86_register_instructions(asm_x86_processor *proc)
register_opcode(proc->opcodes[X86_OP_CALL_REL1632], 0x66, 0xe8, "call", x86_read_instr_call_rel1632);
+ register_opcode(proc->opcodes[X86_OP_JMP_REL1632], 0x66, 0xe9, "jmp", x86_read_instr_jmp_rel1632);
register_opcode(proc->opcodes[X86_OP_JMP_8], 0x00, 0xeb, "jmp", x86_read_instr_jmp_8);
register_opcode(proc->opcodes[X86_OP_HLT], 0x00, 0xf4, "hlt", x86_read_instr_hlt);
register_opcode_with_ext(proc->opcodes[X86_OP_CALL_RM1632], 0x66, 0xff, 2, "call", x86_read_instr_call_rm1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_JMP_RM1632], 0x66, 0xff, 4, "jmp", x86_read_instr_jmp_rm1632);
register_opcode_with_ext(proc->opcodes[X86_OP_PUSH_RM1632], 0x66, 0xff, 6, "push", x86_read_instr_push_rm1632);
@@ -367,6 +371,12 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d
goto find_instr;
}
+ if (proc->opcodes[i].prefix == 0x00 && data[*pos] == proc->opcodes[i].opcode)
+ {
+ tmp = *pos + 1;
+ goto find_instr;
+ }
+
continue;
find_instr:
@@ -381,7 +391,7 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d
else
{
*pos = old_pos;
- printf("err while decoding at 0x%08llx :: [0x%02hhx] 0x%02hhx\n", offset, proc->opcodes[i].prefix, proc->opcodes[i].opcode);
+ printf("err while x86 decoding at 0x%08llx :: [0x%02hhx] 0x%02hhx\n", offset, proc->opcodes[i].prefix, proc->opcodes[i].opcode);
}
break;
@@ -456,7 +466,7 @@ void x86_print_instruction(const asm_x86_processor *proc, const exe_format *form
/* Impression globale finale */
- if (ASM_INSTRUCTION(instr)->opcode == DB_OPCODE)
+ if (ASM_INSTRUCTION(instr)->type == AIT_DB)
snprintf(buffer, len, "db\t%s", opbuffer[0]);
else
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++;
+
+ }
+
+}