diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2008-09-14 20:54:43 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2008-09-14 20:54:43 (GMT) |
commit | 06cf576b280cbabb73a956161693a63ee846f57b (patch) | |
tree | 3ac4b32e869cc8aaa1d4b7429d7d4a12f9a8ae7f /src/arch/x86 | |
parent | ab1489b6a6ef1f09957f6f805f143fceb42f6a08 (diff) |
Made the program able to disassemble a simple binary completely.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@30 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/arch/x86')
-rw-r--r-- | src/arch/x86/Makefile.am | 3 | ||||
-rw-r--r-- | src/arch/x86/instruction.h | 38 | ||||
-rw-r--r-- | src/arch/x86/op_add.c | 62 | ||||
-rw-r--r-- | src/arch/x86/op_call.c | 52 | ||||
-rw-r--r-- | src/arch/x86/op_cmp.c | 210 | ||||
-rw-r--r-- | src/arch/x86/op_jump.c | 159 | ||||
-rw-r--r-- | src/arch/x86/op_mov.c | 171 | ||||
-rw-r--r-- | src/arch/x86/op_sar.c | 92 | ||||
-rw-r--r-- | src/arch/x86/op_sub.c | 65 | ||||
-rw-r--r-- | src/arch/x86/op_test.c | 266 | ||||
-rw-r--r-- | src/arch/x86/opcodes.h | 39 | ||||
-rw-r--r-- | src/arch/x86/operand.c | 55 | ||||
-rw-r--r-- | src/arch/x86/operand.h | 8 | ||||
-rw-r--r-- | src/arch/x86/processor.c | 24 |
14 files changed, 1229 insertions, 15 deletions
diff --git a/src/arch/x86/Makefile.am b/src/arch/x86/Makefile.am index b074f69..139bcde 100644 --- a/src/arch/x86/Makefile.am +++ b/src/arch/x86/Makefile.am @@ -7,10 +7,12 @@ libarchx86_a_SOURCES = \ op_add.c \ op_and.c \ op_call.c \ + op_cmp.c \ op_dec.c \ op_hlt.c \ op_inc.c \ op_int.c \ + op_jump.c \ op_lea.c \ op_leave.c \ op_nop.c \ @@ -19,6 +21,7 @@ libarchx86_a_SOURCES = \ op_pop.c \ op_push.c \ op_ret.c \ + op_sar.c \ op_sbb.c \ op_sub.c \ op_test.c \ diff --git a/src/arch/x86/instruction.h b/src/arch/x86/instruction.h index af4f7cf..68a5fff 100644 --- a/src/arch/x86/instruction.h +++ b/src/arch/x86/instruction.h @@ -38,8 +38,12 @@ typedef struct _asm_x86_instr asm_x86_instr; /* Enumération de tous les opcodes */ typedef enum _X86Opcodes { + X86_OP_SUB_R1632_RM1632, /* sub ([0x66] 0x29) */ + X86_OP_XOR_REG1632, /* xor ([0x66] 0x31) */ + X86_OP_CMP_RM1632_R1632, /* cmp ([0x66] 0x39) */ + X86_OP_INC_E_AX, /* inc ([0x66] 0x40) */ X86_OP_INC_E_CX, /* inc ([0x66] 0x41) */ X86_OP_INC_E_DX, /* inc ([0x66] 0x42) */ @@ -78,19 +82,27 @@ typedef enum _X86Opcodes X86_OP_PUSH_IMM1632, /* push ([0x66] 0x68) */ - X86_OP_MOV_REG1632, /* mov ([0x66] 0x89) */ + X86_OP_JE_8, /* je (0x74) */ + X86_OP_JNE_8, /* jne (0x75) */ + + X86_OP_CMP_RM8_IMM8, /* cmp (0x80 7) */ + + X86_OP_ADD_IMM1632_REG1632, /* add ([0x66] 0x81 0) */ - X86_OP_ADD8_REG1632, /* add ([0x66] 0x83) */ - X86_OP_OR8_REG1632, /* or ([0x66] 0x83) */ - X86_OP_ADC8_REG1632, /* adc ([0x66] 0x83) */ - X86_OP_SBB8_REG1632, /* sbb ([0x66] 0x83) */ - X86_OP_AND8_REG1632, /* and ([0x66] 0x83) */ - X86_OP_SUB8_REG1632, /* sub ([0x66] 0x83) */ - X86_OP_XOR8_REG1632, /* xor ([0x66] 0x83) */ + X86_OP_ADD8_REG1632, /* add ([0x66] 0x83 0) */ + X86_OP_OR8_REG1632, /* or ([0x66] 0x83 1) */ + X86_OP_ADC8_REG1632, /* adc ([0x66] 0x83 2) */ + X86_OP_SBB8_REG1632, /* sbb ([0x66] 0x83 3) */ + X86_OP_AND8_REG1632, /* and ([0x66] 0x83 4) */ + X86_OP_SUB8_REG1632, /* sub ([0x66] 0x83 5) */ + X86_OP_XOR8_REG1632, /* xor ([0x66] 0x83 6) */ + X86_OP_CMP_RM1632_IMM8, /* cmp ([0x66] 0x08 7) */ X86_OP_TEST_RM8, /* test ([0x66] 0x84) */ X86_OP_TEST_RM1632, /* test ([0x66] 0x85) */ + X86_OP_MOV_REG1632, /* mov ([0x66] 0x89) */ + X86_OP_MOV_FROM_CONTENT1632, /* mov ([0x66] 0x8b) */ X86_OP_LEA, /* lea ([0x66] 0x8d) */ /* 66 ? */ @@ -99,6 +111,8 @@ typedef enum _X86Opcodes X86_OP_MOV_MOFFS_TO_AL, /* mov (0xa0) */ X86_OP_MOV_MOFFS_TO_E_AX, /* mov ([0x66] 0xa1) */ + X86_OP_MOV_AL_TO_MOFFS, /* mov (0xa2) */ + X86_OP_MOV_E_AX_TO_MOFFS, /* mov ([0x66] 0xa3) */ X86_OP_TEST_AL, /* test (0xa8) */ X86_OP_TEST_E_AX, /* test ([0x66] 0xa9) */ @@ -112,8 +126,11 @@ typedef enum _X86Opcodes X86_OP_MOV_E_SI, /* mov ([0x66] 0xbe) */ X86_OP_MOV_E_DI, /* mov ([0x66] 0xbf) */ + X86_OP_SAR_RM1632_IMM8, /* sar ([0x66 0xc1 7) */ + X86_OP_RET, /* ret (0xc3) */ + X86_OP_MOV_IMM8_TO_RM8, /* mov (0xc6) */ X86_OP_MOV_TO_CONTENT1632, /* mov ([0x66] 0xc7) */ X86_OP_LEAVE, /* leave (0xc9) */ @@ -122,9 +139,12 @@ typedef enum _X86Opcodes X86_OP_CALL, /* call (0xe8) */ + X86_OP_JMP_8, /* jmp (0xeb) */ + X86_OP_HLT, /* hlt (0xf4) */ - X86_OP_PUSH_CONTENT, /* push ([0x66] 0xff) */ /* 66 ? */ + X86_OP_CALL_RM1632, /* call ([0x66] 0xff 2) */ + X86_OP_PUSH_CONTENT, /* push ([0x66] 0xff 6) */ /* 66 ? */ X86_OP_COUNT diff --git a/src/arch/x86/op_add.c b/src/arch/x86/op_add.c index 99a30fc..bab7f03 100644 --- a/src/arch/x86/op_add.c +++ b/src/arch/x86/op_add.c @@ -96,3 +96,65 @@ asm_x86_instr *read_instr_add8_with_reg1632(const uint8_t *data, off_t *pos, off 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' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_add_imm1632_to_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 */ + asm_x86_operand *reg; /* Registre de destination */ + 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)++]; + + reg = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS, true); + if (reg == NULL) + { + free(result); + return NULL; + } + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), oprsize, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_call.c b/src/arch/x86/op_call.c index 61d9874..f7330ca 100644 --- a/src/arch/x86/op_call.c +++ b/src/arch/x86/op_call.c @@ -81,3 +81,55 @@ asm_x86_instr *read_instr_call(const uint8_t *data, off_t *pos, off_t len, uint6 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 'call' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_call_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 */ + asm_x86_operand *reg; /* Elément à appeler */ + + 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)++]; + + reg = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS, true); + if (reg == NULL) + { + 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(reg); + + return result; + +} diff --git a/src/arch/x86/op_cmp.c b/src/arch/x86/op_cmp.c new file mode 100644 index 0000000..9e5bcc5 --- /dev/null +++ b/src/arch/x86/op_cmp.c @@ -0,0 +1,210 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_cmp.c - décodage des comparaisons d'opérandes + * + * 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 'cmp' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_cmp_rm8_with_imm8(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 *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur portée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + reg = x86_create_rm8_operand(data, pos, len, true); + if (reg == NULL) + { + free(result); + return NULL; + } + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = 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 'cmp' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_cmp_rm1632_with_imm8(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 */ + asm_x86_operand *value; /* Valeur porté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)++]; + + reg = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS, true); + if (reg == NULL) + { + free(result); + return NULL; + } + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = 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 'cmp' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_cmp_rm1632_with_r1632(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 */ + off_t reg1_pos; /* POsition après lecture #1 */ + asm_x86_operand *reg1; /* Registre de destination */ + asm_x86_operand *reg2; /* Registre de source */ + + 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)++]; + + reg1_pos = *pos; + reg1 = x86_create_rm1632_operand(data, ®1_pos, len, oprsize == AOS_32_BITS, true); + if (reg1 == NULL) + { + free(result); + return NULL; + } + + reg2 = x86_create_r1632_operand(data[*pos], oprsize == AOS_32_BITS, false); + if (reg2 == NULL) + { + free(result); + free(reg1); + return NULL; + } + + *pos = reg1_pos; + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg1); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg2); + + return result; + +} diff --git a/src/arch/x86/op_jump.c b/src/arch/x86/op_jump.c new file mode 100644 index 0000000..bcfcb0f --- /dev/null +++ b/src/arch/x86/op_jump.c @@ -0,0 +1,159 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_jump.c - décodage des sauts conditionnels + * + * 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 'je' (petit saut). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_je_8(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 *address; /* Adresse visée réelle */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO : 64bits */ + address = x86_create_rel8_operand_in_32b(offset + 1, data, pos, len); + if (address == NULL) + { + 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(address); + + 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 'jne' (petit saut). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_jne_8(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 *address; /* Adresse visée réelle */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO : 64bits */ + address = x86_create_rel8_operand_in_32b(offset + 1, data, pos, len); + if (address == NULL) + { + 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(address); + + 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' (petit saut). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_jmp_8(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 *address; /* Adresse visée réelle */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + /* TODO : 64bits */ + address = x86_create_rel8_operand_in_32b(offset + 1, data, pos, len); + if (address == NULL) + { + 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(address); + + return result; + +} diff --git a/src/arch/x86/op_mov.c b/src/arch/x86/op_mov.c index 388d67e..f5a8825 100644 --- a/src/arch/x86/op_mov.c +++ b/src/arch/x86/op_mov.c @@ -38,7 +38,7 @@ * offset = adresse virtuelle de l'instruction. * * proc = architecture ciblée par le désassemblage. * * * -* Description : Décode une instruction de type 'mov al, ...' (8 bits). * +* Description : Décode une instruction de type 'mov ..., al' (8 bits). * * * * Retour : Instruction mise en place ou NULL. * * * @@ -46,10 +46,175 @@ * * ******************************************************************************/ -asm_x86_instr *read_instr_mov_moffs8_to_al(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +asm_x86_instr *read_instr_mov_al_to_moffs8(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 *value; /* Valeur portée */ + asm_x86_operand *reg; /* Registre de source */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + value = x86_create_moffs8_operand(data, pos, len); + if (value == NULL) + { + free(result); + return NULL; + } + + reg = x86_create_r8_operand(0x00, true); + if (reg == NULL) + { + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(value); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg); + + 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 'mov ..., [e]ax' (16/32 bits).* +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_mov_e_ax_to_moffs1632(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 portée */ + asm_x86_operand *reg; /* Registre de source */ + + 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 = x86_create_moffs1632_operand(data, pos, len, oprsize == AOS_32_BITS); + if (value == NULL) + { + free(result); + return NULL; + } + + reg = x86_create_r1632_operand(0x00, oprsize == AOS_32_BITS, true); + if (reg == NULL) + { + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(value); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg); + + 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 'mov' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_mov_imm8_to_rm8(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 *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur portée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + reg = x86_create_rm8_operand(data, pos, len, true); + if (reg == NULL) + { + free(result); + return NULL; + } + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = 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 'mov al, ...' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_mov_moffs8_to_al(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 *reg; /* Registre de destination */ asm_x86_operand *value; /* Valeur portée */ @@ -148,6 +313,8 @@ asm_x86_instr *read_instr_mov_moffs1632_to_e_ax(const uint8_t *data, off_t *pos, + + /****************************************************************************** * * * Paramètres : data = flux de données à analyser. * diff --git a/src/arch/x86/op_sar.c b/src/arch/x86/op_sar.c new file mode 100644 index 0000000..187c2bb --- /dev/null +++ b/src/arch/x86/op_sar.c @@ -0,0 +1,92 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_cmp.c - décodage des comparaisons d'opérandes + * + * 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 'sar' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_sar_rm1632_with_imm8(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 */ + asm_x86_operand *value; /* Valeur porté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)++]; + + reg = x86_create_rm1632_operand(data, pos, len, oprsize == AOS_32_BITS, true); + if (reg == NULL) + { + free(result); + return NULL; + } + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value); + + return result; + +} diff --git a/src/arch/x86/op_sub.c b/src/arch/x86/op_sub.c index a323aa8..f14e4a9 100644 --- a/src/arch/x86/op_sub.c +++ b/src/arch/x86/op_sub.c @@ -96,3 +96,68 @@ asm_x86_instr *read_instr_sub8_with_reg1632(const uint8_t *data, off_t *pos, off 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 'sub' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_sub_r1632_to_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 */ + off_t reg1_pos; /* POsition après lecture #1 */ + asm_x86_operand *reg1; /* Registre de destination */ + asm_x86_operand *reg2; /* Registre de source */ + + 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)++]; + + reg1_pos = *pos; + reg1 = x86_create_rm1632_operand(data, ®1_pos, len, oprsize == AOS_32_BITS, true); + if (reg1 == NULL) + { + free(result); + return NULL; + } + + reg2 = x86_create_r1632_operand(data[*pos], oprsize == AOS_32_BITS, false); + if (reg2 == NULL) + { + free(result); + free(reg1); + return NULL; + } + + *pos = reg1_pos; + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg1); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg2); + + return result; + +} diff --git a/src/arch/x86/op_test.c b/src/arch/x86/op_test.c new file mode 100644 index 0000000..9231838 --- /dev/null +++ b/src/arch/x86/op_test.c @@ -0,0 +1,266 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_test.c - décodage des comparaisons logiques + * + * 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 'test al, ...' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_test_al(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 *reg; /* Registre de destination */ + asm_x86_operand *value; /* Valeur portée */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + reg = x86_create_r8_operand(0x00, true); + if (reg == NULL) + { + free(result); + return NULL; + } + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = 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 'test [e]ax, ...' (16/32b). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_test_e_ax(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 */ + asm_x86_operand *value; /* Valeur porté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)++]; + + reg = x86_create_r1632_operand(0x00, oprsize == AOS_32_BITS, true); + if (reg == NULL) + { + free(result); + return NULL; + } + + value = create_new_x86_operand(); + if (!fill_imm_operand(ASM_OPERAND(value), oprsize, data, pos, len)) + { + free(reg); + free(value); + free(result); + return NULL; + } + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg); + ASM_INSTRUCTION(result)->operands[1] = 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 'test' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_test_rm8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + off_t reg1_pos; /* POsition après lecture #1 */ + asm_x86_operand *reg1; /* Registre de destination */ + asm_x86_operand *reg2; /* Registre de source */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + reg1_pos = *pos; + reg1 = x86_create_rm8_operand(data, ®1_pos, len, true); + if (reg1 == NULL) + { + free(result); + return NULL; + } + + reg2 = x86_create_r8_operand(data[*pos], false); + if (reg2 == NULL) + { + free(result); + free(reg1); + return NULL; + } + + *pos = reg1_pos; + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg1); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg2); + + 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 'test' (16 ou 32 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *read_instr_test_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 */ + off_t reg1_pos; /* POsition après lecture #1 */ + asm_x86_operand *reg1; /* Registre de destination */ + asm_x86_operand *reg2; /* Registre de source */ + + 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)++]; + + reg1_pos = *pos; + reg1 = x86_create_rm1632_operand(data, ®1_pos, len, oprsize == AOS_32_BITS, true); + if (reg1 == NULL) + { + free(result); + return NULL; + } + + reg2 = x86_create_r1632_operand(data[*pos], oprsize == AOS_32_BITS, false); + if (reg2 == NULL) + { + free(result); + free(reg1); + return NULL; + } + + *pos = reg1_pos; + + ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *)); + ASM_INSTRUCTION(result)->operands_count = 2; + + ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg1); + ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg2); + + return result; + +} diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h index 09fed4e..ef5c66c 100644 --- a/src/arch/x86/opcodes.h +++ b/src/arch/x86/opcodes.h @@ -40,12 +40,27 @@ asm_x86_instr *read_instr_adc8_with_reg1632(const uint8_t *, off_t *, off_t, uin /* Décode une instruction de type 'add' (16 ou 32 bits). */ asm_x86_instr *read_instr_add8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* 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 'and' (16 ou 32 bits). */ asm_x86_instr *read_instr_and8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* 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 'call' (16 ou 32 bits). */ +asm_x86_instr *x86_read_instr_call_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'cmp' (8 bits). */ +asm_x86_instr *x86_read_instr_cmp_rm8_with_imm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'cmp' (8 bits). */ +asm_x86_instr *x86_read_instr_cmp_rm1632_with_imm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'cmp' (16 ou 32 bits). */ +asm_x86_instr *x86_read_instr_cmp_rm1632_with_r1632(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, uint64_t, const asm_x86_processor *); @@ -58,12 +73,30 @@ asm_x86_instr *read_instr_inc_1632(const uint8_t *, off_t *, off_t, uint64_t, co /* Décode une instruction de type 'int'. */ 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 'je' (petit saut). */ +asm_x86_instr *read_instr_je_8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'jne' (petit saut). */ +asm_x86_instr *read_instr_jne_8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'jump' (petit saut). */ +asm_x86_instr *read_instr_jmp_8(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 *read_instr_lea(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'leave'. */ asm_x86_instr *read_instr_leave(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* Décode une instruction de type 'mov ..., al' (8 bits). */ +asm_x86_instr *read_instr_mov_al_to_moffs8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'mov ..., [e]ax' (16/32 bits). */ +asm_x86_instr *read_instr_mov_e_ax_to_moffs1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'mov' (8 bits). */ +asm_x86_instr *read_instr_mov_imm8_to_rm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'mov al, ...' (8 bits). */ asm_x86_instr *read_instr_mov_moffs8_to_al(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); @@ -103,12 +136,18 @@ asm_x86_instr *read_instr_push_reg1632(const uint8_t *, off_t *, off_t, uint64_t /* Décode une instruction de type 'ret'. */ asm_x86_instr *read_instr_ret(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* Décode une instruction de type 'sar' (8 bits). */ +asm_x86_instr *x86_read_instr_sar_rm1632_with_imm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'sbb'. */ asm_x86_instr *read_instr_sbb8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); /* Décode une instruction de type 'sub'. */ asm_x86_instr *read_instr_sub8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* Décode une instruction de type 'sub' (16 ou 32 bits). */ +asm_x86_instr *x86_read_instr_sub_r1632_to_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'test al, ...' (8 bits). */ asm_x86_instr *read_instr_test_al(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 281c139..10a908e 100644 --- a/src/arch/x86/operand.c +++ b/src/arch/x86/operand.c @@ -505,7 +505,7 @@ asm_x86_operand *x86_create_rm8_operand(const uint8_t *data, off_t *pos, off_t l free(result); result = create_new_x86_operand(); - if (!fill_imm_operand(ASM_OPERAND(result), AOS_8_BITS, data, pos, len)) + if (!fill_imm_operand(ASM_OPERAND(result), AOS_32_BITS/* FIXME! 16/32 */, data, pos, len)) { free(result); return NULL; @@ -573,7 +573,7 @@ asm_x86_operand *x86_create_rm8_operand(const uint8_t *data, off_t *pos, off_t l case 0x80: result->displacement = create_new_x86_operand(); - if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_8_BITS, data, pos, len)) + if (!fill_imm_operand(ASM_OPERAND(result->displacement), AOS_32_BITS/* FIXME ! 16/32 */, data, pos, len)) { free(result->displacement); free(result); @@ -1188,3 +1188,54 @@ void x86_print_moffs_operand(const asm_x86_operand *operand, char *buffer, size_ } } + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERANDES D'ADRESSES RELATIVES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* * +* Description : Crée une opérande à partir d'une adresse relative (8 bits). * +* * +* Retour : Opérande mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_operand *x86_create_rel8_operand_in_32b(uint64_t base, const uint8_t *data, off_t *pos, off_t len) +{ + asm_x86_operand *result; /* Emplacement à retourner */ + off_t init_pos; /* Position avant lecture */ + int8_t offset; /* Décallage à appliquer */ + uint32_t address; /* Adresse finale visée */ + + result = create_new_x86_operand(); + + init_pos = *pos; + address = base; + + if (!read_imm_value(AOS_8_BITS, data, pos, len, &offset)) + { + free(result); + return NULL; + } + + address = base + (*pos - init_pos) + offset; + + if (!fill_imm_operand_with_value(ASM_OPERAND(result), AOS_32_BITS, &address)) + { + free(result); + return NULL; + } + + return result; + +} diff --git a/src/arch/x86/operand.h b/src/arch/x86/operand.h index 42e0f56..04c0cb6 100644 --- a/src/arch/x86/operand.h +++ b/src/arch/x86/operand.h @@ -86,4 +86,12 @@ void x86_print_moffs_operand(const asm_x86_operand *, char *, size_t, AsmSyntax) +/* ------------------------- OPERANDES D'ADRESSES RELATIVES ------------------------- */ + + +/* Crée une opérande à partir d'une adresse relative (8 bits). */ +asm_x86_operand *x86_create_rel8_operand_in_32b(uint64_t, const uint8_t *, off_t *, off_t); + + + #endif /* _ARCH_X86_OPERAND_H */ diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c index 7243064..e7ff753 100644 --- a/src/arch/x86/processor.c +++ b/src/arch/x86/processor.c @@ -194,8 +194,12 @@ AsmOperandSize switch_x86_operand_size(const asm_x86_processor *proc) void x86_register_instructions(asm_x86_processor *proc) { + register_opcode(proc->opcodes[X86_OP_SUB_R1632_RM1632], 0x66, 0x29, "sub", x86_read_instr_sub_r1632_to_rm1632); + register_opcode(proc->opcodes[X86_OP_XOR_REG1632], 0x00/*0x66*/, 0x31, "xor", read_instr_xor_with_reg1632); + register_opcode(proc->opcodes[X86_OP_CMP_RM1632_R1632], 0x66, 0x39, "cmp", x86_read_instr_cmp_rm1632_with_r1632); + register_opcode(proc->opcodes[X86_OP_INC_E_AX], 0x66, 0x40, "inc", read_instr_inc_1632); register_opcode(proc->opcodes[X86_OP_INC_E_CX], 0x66, 0x41, "inc", read_instr_inc_1632); register_opcode(proc->opcodes[X86_OP_INC_E_DX], 0x66, 0x42, "inc", read_instr_inc_1632); @@ -234,6 +238,10 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_PUSH_IMM1632], 0x66, 0x68, "push", read_instr_push_imm1632); + register_opcode_with_ext(proc->opcodes[X86_OP_CMP_RM8_IMM8], 0x00, 0x80, 7, "cmp", x86_read_instr_cmp_rm8_with_imm8); + + register_opcode_with_ext(proc->opcodes[X86_OP_ADD_IMM1632_REG1632], 0x66, 0x81, 0, "add", x86_read_instr_add_imm1632_to_rm1632); + register_opcode_with_ext(proc->opcodes[X86_OP_ADD8_REG1632], 0x66, 0x83, 0, "add", read_instr_add8_with_reg1632); register_opcode_with_ext(proc->opcodes[X86_OP_OR8_REG1632], 0x66, 0x83, 1, "or", read_instr_or8_with_reg1632); register_opcode_with_ext(proc->opcodes[X86_OP_ADC8_REG1632], 0x66, 0x83, 2, "adc", read_instr_adc8_with_reg1632); @@ -241,6 +249,10 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode_with_ext(proc->opcodes[X86_OP_AND8_REG1632], 0x66, 0x83, 4, "and", read_instr_and8_with_reg1632); register_opcode_with_ext(proc->opcodes[X86_OP_SUB8_REG1632], 0x66, 0x83, 5, "sub", read_instr_sub8_with_reg1632); register_opcode_with_ext(proc->opcodes[X86_OP_XOR8_REG1632], 0x66, 0x83, 6, "xor", read_instr_xor8_with_reg1632); + register_opcode_with_ext(proc->opcodes[X86_OP_CMP_RM1632_IMM8], 0x66, 0x83, 7, "cmp", x86_read_instr_cmp_rm1632_with_imm8); + + register_opcode(proc->opcodes[X86_OP_JE_8], 0x00, 0x74, "je", read_instr_je_8); + register_opcode(proc->opcodes[X86_OP_JNE_8], 0x00, 0x75, "jne", read_instr_jne_8); register_opcode(proc->opcodes[X86_OP_TEST_RM8], 0x00, 0x84, "test", read_instr_test_rm8); register_opcode(proc->opcodes[X86_OP_TEST_RM1632], 0x66, 0x85, "test", read_instr_test_rm1632); @@ -253,8 +265,10 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_NOP], 0x00, 0x90, "nop", read_instr_nop); - register_opcode(proc->opcodes[X86_OP_MOV_MOFFS_TO_AL], 0x66, 0xa0, "mov", read_instr_mov_moffs8_to_al); + register_opcode(proc->opcodes[X86_OP_MOV_MOFFS_TO_AL], 0x00, 0xa0, "mov", read_instr_mov_moffs8_to_al); register_opcode(proc->opcodes[X86_OP_MOV_MOFFS_TO_E_AX], 0x66, 0xa1, "mov", read_instr_mov_moffs1632_to_e_ax); + register_opcode(proc->opcodes[X86_OP_MOV_AL_TO_MOFFS], 0x00, 0xa2, "mov", read_instr_mov_al_to_moffs8); + register_opcode(proc->opcodes[X86_OP_MOV_E_AX_TO_MOFFS], 0x66, 0xa3, "mov", read_instr_mov_e_ax_to_moffs1632); register_opcode(proc->opcodes[X86_OP_TEST_AL], 0x00, 0xa8, "test", read_instr_test_al); register_opcode(proc->opcodes[X86_OP_TEST_E_AX], 0x66, 0xa9, "test", read_instr_test_e_ax); @@ -268,8 +282,11 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_MOV_E_SI], 0x66, 0xbe, "mov", read_instr_mov_to_1632); register_opcode(proc->opcodes[X86_OP_MOV_E_DI], 0x66, 0xbf, "mov", read_instr_mov_to_1632); + register_opcode_with_ext(proc->opcodes[X86_OP_SAR_RM1632_IMM8], 0x66, 0xc1, 7, "sar", x86_read_instr_sar_rm1632_with_imm8); + register_opcode(proc->opcodes[X86_OP_RET], 0x00, 0xc3, "ret", read_instr_ret); + register_opcode(proc->opcodes[X86_OP_MOV_IMM8_TO_RM8], 0x00, 0xc6, "mov", read_instr_mov_imm8_to_rm8); register_opcode(proc->opcodes[X86_OP_MOV_TO_CONTENT1632], 0x66, 0xc7, "mov", read_instr_mov_to_content_1632); register_opcode(proc->opcodes[X86_OP_LEAVE], 0x00, 0xc9, "leave", read_instr_leave); @@ -279,9 +296,12 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_CALL], 0x00, 0xe8, "call", read_instr_call); + register_opcode(proc->opcodes[X86_OP_JMP_8], 0x00, 0xeb, "jmp", read_instr_jmp_8); + register_opcode(proc->opcodes[X86_OP_HLT], 0x00, 0xf4, "hlt", read_instr_hlt); - register_opcode(proc->opcodes[X86_OP_PUSH_CONTENT], 0x66, 0xff, "push", read_instr_push_content); + 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_PUSH_CONTENT], 0x66, 0xff, 6, "push", read_instr_push_content); } |