diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/operand-int.h | 1 | ||||
-rw-r--r-- | src/arch/operand.c | 79 | ||||
-rw-r--r-- | src/arch/operand.h | 3 | ||||
-rw-r--r-- | src/arch/processor-int.h | 3 | ||||
-rw-r--r-- | src/arch/processor.c | 13 | ||||
-rw-r--r-- | src/arch/processor.h | 2 | ||||
-rw-r--r-- | src/arch/x86/Makefile.am | 1 | ||||
-rw-r--r-- | src/arch/x86/instruction.h | 6 | ||||
-rw-r--r-- | src/arch/x86/op_call.c | 83 | ||||
-rw-r--r-- | src/arch/x86/op_dec.c | 19 | ||||
-rw-r--r-- | src/arch/x86/op_hlt.c | 10 | ||||
-rw-r--r-- | src/arch/x86/op_inc.c | 19 | ||||
-rw-r--r-- | src/arch/x86/op_int.c | 10 | ||||
-rw-r--r-- | src/arch/x86/op_mov.c | 21 | ||||
-rw-r--r-- | src/arch/x86/op_nop.c | 10 | ||||
-rw-r--r-- | src/arch/x86/op_pop.c | 19 | ||||
-rw-r--r-- | src/arch/x86/op_push.c | 72 | ||||
-rw-r--r-- | src/arch/x86/opcodes.h | 24 | ||||
-rw-r--r-- | src/arch/x86/processor.c | 138 | ||||
-rw-r--r-- | src/arch/x86/processor.h | 8 |
20 files changed, 425 insertions, 116 deletions
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h index 49470a4..92fc9bf 100644 --- a/src/arch/operand-int.h +++ b/src/arch/operand-int.h @@ -52,7 +52,6 @@ struct _asm_operand uint32_t val32; /* Valeur sur 32 bits */ uint64_t val64; /* Valeur sur 64 bits */ - } value; }; diff --git a/src/arch/operand.c b/src/arch/operand.c index 33807bc..e24a3e0 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -156,6 +156,85 @@ bool fill_imm_operand(asm_operand *operand, AsmOperandSize size, const uint8_t * /****************************************************************************** * * +* Paramètres : operand = structure dont le contenu est à définir. * +* size = taille de l'opérande souhaitée. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* ref = adresse de référence. * +* * +* Description : Crée une opérande contenant une valeur relative sur x bits. * +* * +* Retour : true si l'opération s'est effectuée avec succès, false sinon.* +* * +* Remarques : - * +* * +******************************************************************************/ + +bool fill_relimm_operand(asm_operand *operand, AsmOperandSize size, const uint8_t *data, off_t *pos, off_t len, uint64_t ref) +{ + bool result; /* Bilan à retourner */ + off_t old_pos; /* Sauvegarde de l'évolution */ + int8_t val8; /* Valeur sur 8 bits */ + int16_t val16; /* Valeur sur 16 bits */ + uint32_t val32; /* Valeur sur 32 bits */ + int64_t val64; /* Valeur sur 64 bits */ + + old_pos = *pos; + result = fill_imm_operand(operand, size, data, pos, len); + + if (result) + switch (size) + { + case AOS_8_BITS: + if (operand->value.val8 & 0x80) + { + val8 = operand->value.val8 - 1; + val8 = ~val8; + operand->value.val8 = ref + (*pos - old_pos); + operand->value.val8 -= val8; + } + else operand->value.val8 += ref + (*pos - old_pos); + break; + case AOS_16_BITS: + if (operand->value.val16 & 0x8000) + { + val16 = operand->value.val16 - 1; + val16 = ~val16; + operand->value.val16 = ref + (*pos - old_pos); + operand->value.val16 -= val16; + } + else operand->value.val16 += ref + (*pos - old_pos); + break; + case AOS_32_BITS: + if (operand->value.val32 & 0x80000000) + { + val32 = operand->value.val32 - 1; + val32 = ~val32; + operand->value.val32 = ref + (*pos - old_pos); + operand->value.val32 -= val32; + } + else operand->value.val32 += ref + (*pos - old_pos); + break; + case AOS_64_BITS: + if (operand->value.val64 & 0x8000000000000000ull) + { + val64 = operand->value.val64 - 1; + val64 = ~val64; + operand->value.val64 = ref + (*pos - old_pos); + operand->value.val64 -= val64; + } + else operand->value.val64 += ref + (*pos - old_pos); + break; + } + + 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 1b5b33f..1067518 100644 --- a/src/arch/operand.h +++ b/src/arch/operand.h @@ -65,6 +65,9 @@ void print_db_operand(const asm_operand *, char *, size_t, AsmSyntax); /* Crée une opérande contenant une valeur sur x bits. */ bool fill_imm_operand(asm_operand *, AsmOperandSize, const uint8_t *, off_t *, off_t); +/* 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); + /* 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-int.h b/src/arch/processor-int.h index a4f983c..50837e1 100644 --- a/src/arch/processor-int.h +++ b/src/arch/processor-int.h @@ -25,6 +25,7 @@ #define _ARCH_PROCESSOR_INT_H +#include <stdint.h> #include <sys/types.h> @@ -37,7 +38,7 @@ /* Décode une instruction dans un flux de données. */ -typedef asm_instr * (* fetch_instruction) (const asm_processor *, const uint8_t *, off_t *, off_t); +typedef asm_instr * (* fetch_instruction) (const asm_processor *, const uint8_t *, off_t *, off_t, uint64_t); /* Traduit une instruction en version humainement lisible. */ typedef void (* print_instruction) (const asm_processor *, const asm_instr *, char *, size_t, AsmSyntax); diff --git a/src/arch/processor.c b/src/arch/processor.c index a8efb60..31cfb3e 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -32,10 +32,11 @@ /****************************************************************************** * * -* Paramètres : proc = architecture visée par la procédure. * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* Paramètres : proc = architecture visée par la procédure. * +* 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. * * * * Description : Décode une instruction dans un flux de données. * * * @@ -45,14 +46,14 @@ * * ******************************************************************************/ -asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, off_t *pos, off_t len) +asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, off_t *pos, off_t len, uint64_t offset) { asm_instr *result; /* Représentation à renvoyer */ - result = proc->fetch_instr(proc, data, pos, len); + result = proc->fetch_instr(proc, data, pos, len, offset); #define NULL ((void *)0) diff --git a/src/arch/processor.h b/src/arch/processor.h index 9ad4be0..e147f38 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -39,7 +39,7 @@ typedef struct _asm_processor asm_processor; /* Décode une instruction dans un flux de données. */ -asm_instr *decode_instruction(const asm_processor *, const uint8_t *, off_t *, off_t); +asm_instr *decode_instruction(const asm_processor *, const uint8_t *, off_t *, off_t, uint64_t); /* Traduit une instruction en version humainement lisible. */ void print_hinstruction(const asm_processor *, const asm_instr *, char *, size_t, AsmSyntax); diff --git a/src/arch/x86/Makefile.am b/src/arch/x86/Makefile.am index c610592..da03534 100644 --- a/src/arch/x86/Makefile.am +++ b/src/arch/x86/Makefile.am @@ -3,6 +3,7 @@ lib_LIBRARIES = libarchx86.a libarchx86_a_SOURCES = \ instruction.h \ + op_call.c \ op_dec.c \ op_hlt.c \ op_inc.c \ diff --git a/src/arch/x86/instruction.h b/src/arch/x86/instruction.h index 83f8cf0..d88e971 100644 --- a/src/arch/x86/instruction.h +++ b/src/arch/x86/instruction.h @@ -74,6 +74,8 @@ typedef enum _X86Opcodes X86_OP_POP_ESI, /* pop (0x5e) */ X86_OP_POP_EDI, /* pop (0x5f) */ + X86_OP_PUSH_IMM32, /* push (0x68) */ + X86_OP_NOP, /* nop (0x90) */ X86_OP_MOV_AX, /* mov (0xb8) */ @@ -87,6 +89,8 @@ typedef enum _X86Opcodes X86_OP_INT, /* int (0xcd) */ + X86_OP_CALL, /* call (0xe8) */ + X86_OP_HLT, /* hlt (0xf4) */ X86_OP_INC_AX, /* inc (0x66 0x40) */ @@ -125,6 +129,8 @@ typedef enum _X86Opcodes X86_OP_POP_SI, /* pop (0x66 0x5e) */ X86_OP_POP_DI, /* pop (0x66 0x5f) */ + X86_OP_PUSH_IMM16, /* push (0x66 0x68) */ + X86_OP_MOV_EAX, /* mov (0x66 0xb8) */ X86_OP_MOV_ECX, /* mov (0x66 0xb9) */ X86_OP_MOV_EDX, /* mov (0x66 0xba) */ diff --git a/src/arch/x86/op_call.c b/src/arch/x86/op_call.c new file mode 100644 index 0000000..61d9874 --- /dev/null +++ b/src/arch/x86/op_call.c @@ -0,0 +1,83 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_call.c - décodage des appels + * + * Copyright (C) 2008 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 <malloc.h> + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* 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 'call' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_call(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 */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + offset++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + value = create_new_x86_operand(); + if (!fill_relimm_operand(ASM_OPERAND(value), oprsize, data, pos, len, ++offset)) + { + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(1, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 1; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_dec.c b/src/arch/x86/op_dec.c index 9bdbf74..e6add37 100644 --- a/src/arch/x86/op_dec.c +++ b/src/arch/x86/op_dec.c @@ -32,9 +32,11 @@ /****************************************************************************** * * -* Paramètres : data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* 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 'inc' (16 ou 32 bits). * * * @@ -44,24 +46,25 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_dec_1632(const uint8_t *data, off_t *pos, off_t len) +asm_x86_instr *read_instr_dec_1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; /* Instruction à retourner */ - bool is_reg32; /* Implique un registre 32 bits*/ + AsmOperandSize oprsize; /* Taille des opérandes */ asm_x86_operand *reg; /* Registre de destination */ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); /* Utilisation des registres 32 bits ? */ - is_reg32 = (data[*pos] != 0x66); - if (!is_reg32) + if (data[*pos] == 0x66) { + oprsize = switch_x86_operand_size(proc); (*pos)++; } + else oprsize = get_x86_current_operand_size(proc); ASM_INSTRUCTION(result)->opcode = data[*pos]; - reg = x86_create_reg1632_operand(data[(*pos)++], is_reg32, 0x48); + reg = x86_create_reg1632_operand(data[(*pos)++], oprsize == AOS_32_BITS, 0x48); if (reg == NULL) { free(result); diff --git a/src/arch/x86/op_hlt.c b/src/arch/x86/op_hlt.c index ddb5882..9443e7d 100644 --- a/src/arch/x86/op_hlt.c +++ b/src/arch/x86/op_hlt.c @@ -31,9 +31,11 @@ /****************************************************************************** * * -* Paramètres : data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* 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 'hlt'. * * * @@ -43,7 +45,7 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_hlt(const uint8_t *data, off_t *pos, off_t len) +asm_x86_instr *read_instr_hlt(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; diff --git a/src/arch/x86/op_inc.c b/src/arch/x86/op_inc.c index dd21471..aa05d04 100644 --- a/src/arch/x86/op_inc.c +++ b/src/arch/x86/op_inc.c @@ -32,9 +32,11 @@ /****************************************************************************** * * -* Paramètres : data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* 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 'inc' (16 ou 32 bits). * * * @@ -44,24 +46,25 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_inc_1632(const uint8_t *data, off_t *pos, off_t len) +asm_x86_instr *read_instr_inc_1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; /* Instruction à retourner */ - bool is_reg32; /* Implique un registre 32 bits*/ + AsmOperandSize oprsize; /* Taille des opérandes */ asm_x86_operand *reg; /* Registre de destination */ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); /* Utilisation des registres 32 bits ? */ - is_reg32 = (data[*pos] != 0x66); - if (!is_reg32) + if (data[*pos] == 0x66) { + oprsize = switch_x86_operand_size(proc); (*pos)++; } + else oprsize = get_x86_current_operand_size(proc); ASM_INSTRUCTION(result)->opcode = data[*pos]; - reg = x86_create_reg1632_operand(data[(*pos)++], is_reg32, 0x40); + reg = x86_create_reg1632_operand(data[(*pos)++], oprsize == AOS_32_BITS, 0x40); if (reg == NULL) { free(result); diff --git a/src/arch/x86/op_int.c b/src/arch/x86/op_int.c index 3c621d6..69e49ff 100644 --- a/src/arch/x86/op_int.c +++ b/src/arch/x86/op_int.c @@ -32,9 +32,11 @@ /****************************************************************************** * * -* Paramètres : data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* 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 'int'. * * * @@ -44,7 +46,7 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_int(const uint8_t *data, off_t *pos, off_t len) +asm_x86_instr *read_instr_int(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; /* Instruction à retourner */ asm_x86_operand *syscall; /* Indice de l'appel système */ diff --git a/src/arch/x86/op_mov.c b/src/arch/x86/op_mov.c index 2ce8464..e14a2f7 100644 --- a/src/arch/x86/op_mov.c +++ b/src/arch/x86/op_mov.c @@ -32,9 +32,11 @@ /****************************************************************************** * * -* Paramètres : data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* 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 'mov' (16 ou 32 bits). * * * @@ -44,25 +46,26 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_mov_to_1632(const uint8_t *data, off_t *pos, off_t len) +asm_x86_instr *read_instr_mov_to_1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; /* Instruction à retourner */ - bool is_reg32; /* Implique un registre 32 bits*/ + AsmOperandSize oprsize; /* Taille des opérandes */ asm_x86_operand *reg; /* Registre de destination */ asm_x86_operand *value; /* Valeur portée */ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); /* Utilisation des registres 32 bits ? */ - is_reg32 = (data[*pos] == 0x66); - if (is_reg32) + if (data[*pos] == 0x66) { + oprsize = switch_x86_operand_size(proc); (*pos)++; } + else oprsize = get_x86_current_operand_size(proc); ASM_INSTRUCTION(result)->opcode = data[*pos]; - reg = x86_create_reg1632_operand(data[(*pos)++], is_reg32, 0xb8); + reg = x86_create_reg1632_operand(data[(*pos)++], oprsize == AOS_32_BITS, 0xb8); if (reg == NULL) { free(result); @@ -70,7 +73,7 @@ asm_x86_instr *read_instr_mov_to_1632(const uint8_t *data, off_t *pos, off_t len } value = create_new_x86_operand(); - if (!fill_imm_operand(ASM_OPERAND(value), is_reg32 ? AOS_32_BITS : AOS_16_BITS, data, pos, len)) + if (!fill_imm_operand(ASM_OPERAND(value), oprsize, data, pos, len)) { free(reg); free(value); diff --git a/src/arch/x86/op_nop.c b/src/arch/x86/op_nop.c index 0062186..438e034 100644 --- a/src/arch/x86/op_nop.c +++ b/src/arch/x86/op_nop.c @@ -31,9 +31,11 @@ /****************************************************************************** * * -* Paramètres : data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* 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 'nop'. * * * @@ -43,7 +45,7 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_nop(const uint8_t *data, off_t *pos, off_t len) +asm_x86_instr *read_instr_nop(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; diff --git a/src/arch/x86/op_pop.c b/src/arch/x86/op_pop.c index 3e725eb..4d7f520 100644 --- a/src/arch/x86/op_pop.c +++ b/src/arch/x86/op_pop.c @@ -32,9 +32,11 @@ /****************************************************************************** * * -* Paramètres : data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* 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 'pop' (16 ou 32 bits). * * * @@ -44,24 +46,25 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_pop_1632(const uint8_t *data, off_t *pos, off_t len) +asm_x86_instr *read_instr_pop_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; /* Instruction à retourner */ - bool is_reg32; /* Implique un registre 32 bits*/ + AsmOperandSize oprsize; /* Taille des opérandes */ asm_x86_operand *reg; /* Registre de destination */ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); /* Utilisation des registres 32 bits ? */ - is_reg32 = (data[*pos] != 0x66); - if (!is_reg32) + if (data[*pos] == 0x66) { + oprsize = switch_x86_operand_size(proc); (*pos)++; } + else oprsize = get_x86_current_operand_size(proc); ASM_INSTRUCTION(result)->opcode = data[*pos]; - reg = x86_create_reg1632_operand(data[(*pos)++], is_reg32, 0x58); + reg = x86_create_reg1632_operand(data[(*pos)++], oprsize == AOS_32_BITS, 0x58); if (reg == NULL) { free(result); diff --git a/src/arch/x86/op_push.c b/src/arch/x86/op_push.c index ac5319d..0edd9bc 100644 --- a/src/arch/x86/op_push.c +++ b/src/arch/x86/op_push.c @@ -27,14 +27,17 @@ #include "../instruction-int.h" #include "opcodes.h" #include "operand.h" +#include "processor.h" /****************************************************************************** * * -* Paramètres : data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* 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 'push' (16 ou 32 bits). * * * @@ -44,24 +47,77 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_push_1632(const uint8_t *data, off_t *pos, off_t len) +asm_x86_instr *read_instr_push_imm1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) { asm_x86_instr *result; /* Instruction à retourner */ - bool is_reg32; /* Implique un registre 32 bits*/ + AsmOperandSize oprsize; /* Taille des opérandes */ + asm_x86_operand *value; /* Valeur empilée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + /* Utilisation des registres 32 bits ? */ + if (data[*pos] == 0x66) + { + oprsize = switch_x86_operand_size(proc); + (*pos)++; + } + else oprsize = get_x86_current_operand_size(proc); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), oprsize, data, pos, len)) + { + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(1, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 1; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(value); + + 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 'push' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_push_reg1632(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 */ asm_x86_operand *reg; /* Registre de destination */ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); /* Utilisation des registres 32 bits ? */ - is_reg32 = (data[*pos] != 0x66); - if (!is_reg32) + if (data[*pos] == 0x66) { + oprsize = switch_x86_operand_size(proc); (*pos)++; } + else oprsize = get_x86_current_operand_size(proc); ASM_INSTRUCTION(result)->opcode = data[*pos]; - reg = x86_create_reg1632_operand(data[(*pos)++], is_reg32, 0x50); + reg = x86_create_reg1632_operand(data[(*pos)++], oprsize == AOS_32_BITS, 0x50); if (reg == NULL) { free(result); diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h index f847b48..3efefaf 100644 --- a/src/arch/x86/opcodes.h +++ b/src/arch/x86/opcodes.h @@ -25,36 +25,44 @@ #define _ARCH_X86_OPCODES_H +#include <stdint.h> #include <sys/types.h> +#include "processor.h" #include "instruction.h" +/* Décode une instruction de type 'call'. */ +asm_x86_instr *read_instr_call(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'dec'. */ -asm_x86_instr *read_instr_dec_1632(const uint8_t *, off_t *, off_t); +asm_x86_instr *read_instr_dec_1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'hlt'. */ -asm_x86_instr *read_instr_hlt(const uint8_t *, off_t *, off_t); +asm_x86_instr *read_instr_hlt(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'inc'. */ -asm_x86_instr *read_instr_inc_1632(const uint8_t *, off_t *, off_t); +asm_x86_instr *read_instr_inc_1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'int'. */ -asm_x86_instr *read_instr_int(const uint8_t *, off_t *, off_t); +asm_x86_instr *read_instr_int(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'mov' (16 ou 32 bits). */ -asm_x86_instr *read_instr_mov_to_1632(const uint8_t *, off_t *, off_t); +asm_x86_instr *read_instr_mov_to_1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'nop'. */ -asm_x86_instr *read_instr_nop(const uint8_t *, off_t *, off_t); +asm_x86_instr *read_instr_nop(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'pop' (16 ou 32 bits). */ -asm_x86_instr *read_instr_pop_1632(const uint8_t *, off_t *, off_t); +asm_x86_instr *read_instr_pop_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'push' (16 ou 32 bits). */ +asm_x86_instr *read_instr_push_imm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'push' (16 ou 32 bits). */ -asm_x86_instr *read_instr_push_1632(const uint8_t *, off_t *, off_t); +asm_x86_instr *read_instr_push_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c index 9c7f2bd..94f2a51 100644 --- a/src/arch/x86/processor.c +++ b/src/arch/x86/processor.c @@ -35,7 +35,7 @@ -typedef asm_x86_instr * (* read_instr) (const uint8_t *, off_t *, off_t); +typedef asm_x86_instr * (* read_instr) (const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Carte d'identité d'un opcode */ @@ -59,13 +59,15 @@ target.read = func; \ /* Définition générique d'une architecture */ -typedef struct _asm_x86_processor +struct _asm_x86_processor { asm_processor base; /* A laisser en premier... */ + AsmOperandSize operand_size; /* Taille par défaut */ + x86_opcode opcodes[X86_OP_COUNT]; /* Liste des opcodes supportés */ -} asm_x86_processor; +}; @@ -76,7 +78,7 @@ void x86_register_instructions(asm_x86_processor *); /* Décode une instruction dans un flux de données. */ -asm_instr *x86_fetch_instruction(const asm_x86_processor *, const uint8_t *, off_t *, off_t); +asm_instr *x86_fetch_instruction(const asm_x86_processor *, const uint8_t *, off_t *, off_t, uint64_t); /* Traduit une instruction en version humainement lisible. */ void x86_print_instruction(const asm_x86_processor *, const asm_x86_instr *, char *, size_t, AsmSyntax); @@ -103,17 +105,54 @@ asm_processor *create_x86_processor(void) result = (asm_x86_processor *)calloc(1, sizeof(asm_x86_processor)); + result->operand_size = AOS_32_BITS; + x86_register_instructions(result); - ASM_PROCESSOR(result)->fetch_instr = x86_fetch_instruction; - ASM_PROCESSOR(result)->print_instr = x86_print_instruction; + ASM_PROCESSOR(result)->fetch_instr = (fetch_instruction)x86_fetch_instruction; + ASM_PROCESSOR(result)->print_instr = (print_instruction)x86_print_instruction; return ASM_PROCESSOR(result); } +/****************************************************************************** +* * +* Paramètres : proc = architecture visée par la consultation. * +* * +* Description : Fournit la taille courante des opérandes pour x86. * +* * +* Retour : Taille d'opérande (16 ou 32 bits). * +* * +* Remarques : - * +* * +******************************************************************************/ + +AsmOperandSize get_x86_current_operand_size(const asm_x86_processor *proc) +{ + return proc->operand_size; + +} + + +/****************************************************************************** +* * +* Paramètres : proc = architecture visée par la consultation. * +* * +* Description : Fournit la taille supplantée des opérandes pour x86. * +* * +* Retour : Taille d'opérande (16 ou 32 bits). * +* * +* Remarques : - * +* * +******************************************************************************/ +AsmOperandSize switch_x86_operand_size(const asm_x86_processor *proc) +{ + return (proc->operand_size == AOS_32_BITS ? AOS_16_BITS : AOS_32_BITS); + +} /****************************************************************************** @@ -150,23 +189,25 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_DEC_ESI], 0x00, 0x4e, "dec", read_instr_dec_1632); register_opcode(proc->opcodes[X86_OP_DEC_EDI], 0x00, 0x4f, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EAX], 0x00, 0x50, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_ECX], 0x00, 0x51, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EDX], 0x00, 0x52, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EBX], 0x00, 0x53, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_ESP], 0x00, 0x54, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EBP], 0x00, 0x55, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_ESI], 0x00, 0x56, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_EDI], 0x00, 0x57, "push", read_instr_push_1632); - - register_opcode(proc->opcodes[X86_OP_POP_EAX], 0x00, 0x58, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_ECX], 0x00, 0x59, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_EDX], 0x00, 0x5a, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_EBX], 0x00, 0x5b, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_ESP], 0x00, 0x5c, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_EBP], 0x00, 0x5d, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_ESI], 0x00, 0x5e, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_EDI], 0x00, 0x5f, "pop", read_instr_pop_1632); + register_opcode(proc->opcodes[X86_OP_PUSH_EAX], 0x00, 0x50, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_ECX], 0x00, 0x51, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_EDX], 0x00, 0x52, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_EBX], 0x00, 0x53, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_ESP], 0x00, 0x54, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_EBP], 0x00, 0x55, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_ESI], 0x00, 0x56, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_EDI], 0x00, 0x57, "push", read_instr_push_reg1632); + + register_opcode(proc->opcodes[X86_OP_POP_EAX], 0x00, 0x58, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_ECX], 0x00, 0x59, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_EDX], 0x00, 0x5a, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_EBX], 0x00, 0x5b, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_ESP], 0x00, 0x5c, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_EBP], 0x00, 0x5d, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_ESI], 0x00, 0x5e, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_EDI], 0x00, 0x5f, "pop", read_instr_pop_reg1632); + + register_opcode(proc->opcodes[X86_OP_PUSH_IMM32], 0x00, 0x68, "push", read_instr_push_imm1632); register_opcode(proc->opcodes[X86_OP_NOP], 0x00, 0x90, "nop", read_instr_nop); @@ -185,6 +226,8 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_INT], 0x00, 0xcd, "int", read_instr_int); + register_opcode(proc->opcodes[X86_OP_CALL], 0x00, 0xe8, "call", read_instr_call); + register_opcode(proc->opcodes[X86_OP_HLT], 0x00, 0xf4, "hlt", read_instr_hlt); @@ -206,23 +249,25 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_DEC_SI], 0x66, 0x4e, "dec", read_instr_dec_1632); register_opcode(proc->opcodes[X86_OP_DEC_DI], 0x66, 0x4f, "dec", read_instr_dec_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_AX], 0x66, 0x50, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_CX], 0x66, 0x51, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_DX], 0x66, 0x52, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_BX], 0x66, 0x53, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_SP], 0x66, 0x54, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_BP], 0x66, 0x55, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_SI], 0x66, 0x56, "push", read_instr_push_1632); - register_opcode(proc->opcodes[X86_OP_PUSH_DI], 0x66, 0x57, "push", read_instr_push_1632); - - register_opcode(proc->opcodes[X86_OP_POP_AX], 0x66, 0x58, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_CX], 0x66, 0x59, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_DX], 0x66, 0x5a, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_BX], 0x66, 0x5b, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_SP], 0x66, 0x5c, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_BP], 0x66, 0x5d, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_SI], 0x66, 0x5e, "pop", read_instr_pop_1632); - register_opcode(proc->opcodes[X86_OP_POP_DI], 0x66, 0x5f, "pop", read_instr_pop_1632); + register_opcode(proc->opcodes[X86_OP_PUSH_AX], 0x66, 0x50, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_CX], 0x66, 0x51, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_DX], 0x66, 0x52, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_BX], 0x66, 0x53, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_SP], 0x66, 0x54, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_BP], 0x66, 0x55, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_SI], 0x66, 0x56, "push", read_instr_push_reg1632); + register_opcode(proc->opcodes[X86_OP_PUSH_DI], 0x66, 0x57, "push", read_instr_push_reg1632); + + register_opcode(proc->opcodes[X86_OP_POP_AX], 0x66, 0x58, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_CX], 0x66, 0x59, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_DX], 0x66, 0x5a, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_BX], 0x66, 0x5b, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_SP], 0x66, 0x5c, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_BP], 0x66, 0x5d, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_SI], 0x66, 0x5e, "pop", read_instr_pop_reg1632); + register_opcode(proc->opcodes[X86_OP_POP_DI], 0x66, 0x5f, "pop", read_instr_pop_reg1632); + + register_opcode(proc->opcodes[X86_OP_PUSH_IMM16], 0x66, 0x68, "push", read_instr_push_imm1632); register_opcode(proc->opcodes[X86_OP_MOV_EAX], 0x66, 0xb8, "mov", read_instr_mov_to_1632); register_opcode(proc->opcodes[X86_OP_MOV_ECX], 0x66, 0xb9, "mov", read_instr_mov_to_1632); @@ -241,10 +286,11 @@ void x86_register_instructions(asm_x86_processor *proc) /****************************************************************************** * * -* Paramètres : proc = architecture visée par la procédure. * -* data = flux de données à analyser. * -* pos = position courante dans ce flux. [OUT] * -* len = taille totale des données à analyser. * +* Paramètres : proc = architecture visée par la procédure. * +* 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. * * * * Description : Décode une instruction dans un flux de données. * * * @@ -254,7 +300,7 @@ void x86_register_instructions(asm_x86_processor *proc) * * ******************************************************************************/ -asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *data, off_t *pos, off_t len) +asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *data, off_t *pos, off_t len, uint64_t offset) { asm_x86_instr *result; /* Résultat à faire remonter */ X86Opcodes i; /* Boucle de parcours */ @@ -266,7 +312,7 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d if ((proc->opcodes[i].prefix > 0 && data[*pos] == proc->opcodes[i].prefix && data[*pos + 1] == proc->opcodes[i].opcode) || (proc->opcodes[i].prefix == 0 && data[*pos] == proc->opcodes[i].opcode)) { - result = proc->opcodes[i].read(data, pos, len); + result = proc->opcodes[i].read(data, pos, len, offset, proc); if (result != NULL) result->type = i; printf("err while decoding :: [0x%02hhx] 0x%02hhx\n", proc->opcodes[i].prefix, proc->opcodes[i].opcode); break; diff --git a/src/arch/x86/processor.h b/src/arch/x86/processor.h index 0bd587d..c898d80 100644 --- a/src/arch/x86/processor.h +++ b/src/arch/x86/processor.h @@ -30,10 +30,18 @@ +/* Définition générique d'une architecture */ +typedef struct _asm_x86_processor asm_x86_processor; + + /* Crée le support de l'architecture x86. */ asm_processor *create_x86_processor(void); +/* Fournit la taille courante des opérandes pour x86. */ +AsmOperandSize get_x86_current_operand_size(const asm_x86_processor *); +/* Fournit la taille supplantée des opérandes pour x86. */ +AsmOperandSize switch_x86_operand_size(const asm_x86_processor *); |