From 06cf576b280cbabb73a956161693a63ee846f57b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 14 Sep 2008 20:54:43 +0000 Subject: 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 --- ChangeLog | 48 ++++++++ src/arch/operand.c | 132 ++++++++++++++++++++++ src/arch/operand.h | 6 + src/arch/processor.c | 5 +- src/arch/x86/Makefile.am | 3 + src/arch/x86/instruction.h | 38 +++++-- src/arch/x86/op_add.c | 62 +++++++++++ src/arch/x86/op_call.c | 52 +++++++++ src/arch/x86/op_cmp.c | 210 +++++++++++++++++++++++++++++++++++ src/arch/x86/op_jump.c | 159 +++++++++++++++++++++++++++ src/arch/x86/op_mov.c | 171 ++++++++++++++++++++++++++++- src/arch/x86/op_sar.c | 92 ++++++++++++++++ src/arch/x86/op_sub.c | 65 +++++++++++ src/arch/x86/op_test.c | 266 +++++++++++++++++++++++++++++++++++++++++++++ src/arch/x86/opcodes.h | 39 +++++++ src/arch/x86/operand.c | 55 +++++++++- src/arch/x86/operand.h | 8 ++ src/arch/x86/processor.c | 24 +++- 18 files changed, 1418 insertions(+), 17 deletions(-) create mode 100644 src/arch/x86/op_cmp.c create mode 100644 src/arch/x86/op_jump.c create mode 100644 src/arch/x86/op_sar.c create mode 100644 src/arch/x86/op_test.c diff --git a/ChangeLog b/ChangeLog index 4955b49..5433440 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,51 @@ +2008-09-14 Cyrille Bagard + + * src/arch/operand.c: + * src/arch/operand.h: + Add an alternate function to read immediate values. + + * src/arch/processor.c: + Print a message when decoding unknown opcode. + + * src/arch/x86/instruction.h: + Register new identifiers for the following opcodes: add, call, cmp, je, + jne, jmp, mov, sar and sub. + + * src/arch/x86/Makefile.am: + Add op_cmp.c, op_jump.c and op_sar.c to libarchx86_a_SOURCES. + + * src/arch/x86/op_add.c: + * src/arch/x86/op_call.c: + Improve the support of these opcodes. + + * src/arch/x86/op_cmp.c: + New entry: handle some cmp opcodes. + + * src/arch/x86/opcodes.h: + Register new functions for the following opcodes: add, call, cmp, je, + jne, jmp, mov, sar and sub. + + * src/arch/x86/operand.c: + * src/arch/x86/operand.h: + Fix some mistakes when reading rm8 operands and add a way to read the + rel8 one. + + * src/arch/x86/op_jump.c: + New entry: handle some jump opcodes. + + * src/arch/x86/op_mov.c: + Improve the support of this opcode. + + * src/arch/x86/op_sar.c: + New entry: handle one sar opcode. + + * src/arch/x86/op_sub.c: + * src/arch/x86/op_test.c: + Improve the support of these opcodes. + + * src/arch/x86/processor.c: + Decode the new instructions. Fix a mistake for X86_OP_PUSH_CONTENT. + 2008-09-12 Cyrille Bagard * src/arch/processor.c: diff --git a/src/arch/operand.c b/src/arch/operand.c index e24a3e0..53e652c 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -24,6 +24,7 @@ #include "operand.h" +#include #include @@ -90,6 +91,83 @@ void print_db_operand(const asm_operand *operand, char *buffer, size_t len, AsmS /****************************************************************************** * * +* Paramètres : 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. * +* ... = adresse où placer la valeur lue. [OUT] * +* * +* Description : Lit une valeur (signée ou non) sur x bits. * +* * +* Retour : true si l'opération s'est effectuée avec succès, false sinon.* +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_imm_value(AsmOperandSize size, const uint8_t *data, off_t *pos, off_t len, ...) +{ + 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 */ + + /* Vérifications sanitaires */ + switch (size) + { + case AOS_8_BITS: + if ((len - *pos) < 1) return false; + break; + case AOS_16_BITS: + if ((len - *pos) < 2) return false; + break; + case AOS_32_BITS: + if ((len - *pos) < 4) return false; + break; + case AOS_64_BITS: + if ((len - *pos) < 8) return false; + break; + } + + va_start(ap, len); + + switch (size) + { + case AOS_8_BITS: + val8 = va_arg(ap, uint8_t *); + *val8 = data[*pos]; + *pos += 1; + break; + case AOS_16_BITS: + val16 = va_arg(ap, uint16_t *); + *val16 = data[*pos] | (uint16_t)data[*pos + 1] << 8; + *pos += 2; + break; + case AOS_32_BITS: + val32 = va_arg(ap, uint32_t *); + *val32 = data[*pos] | (uint32_t)data[*pos + 1] << 8 + | (uint32_t)data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24; + *pos += 4; + break; + case AOS_64_BITS: + val64 = va_arg(ap, uint64_t *); + *val64 = data[*pos] | (uint64_t)data[*pos + 1] << 8 | (uint64_t)data[*pos + 2] << 16 + | (uint64_t)data[*pos + 3] << 24 | (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40 + | (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56; + *pos += 8; + break; + } + + va_end(ap); + + return true; + +} + + +/****************************************************************************** +* * * Paramètres : operand = structure dont le contenu est à définir. * * size = taille de l'opérande souhaitée. * * data = flux de données à analyser. * @@ -158,6 +236,60 @@ 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. * +* ... = valeur à utiliser. * +* * +* Description : Crée une opérande contenant une valeur sur x bits. * +* * +* Retour : true si l'opération s'est effectuée avec succès, false sinon.* +* * +* Remarques : - * +* * +******************************************************************************/ + +bool fill_imm_operand_with_value(asm_operand *operand, AsmOperandSize size, ...) +{ + va_list ap; /* Récupération d'argument */ + const uint8_t *val8; /* Valeur sur 8 bits */ + const uint16_t *val16; /* Valeur sur 16 bits */ + const uint32_t *val32; /* Valeur sur 32 bits */ + const uint64_t *val64; /* Valeur sur 64 bits */ + + operand->type = AOT_IMM; + operand->size = size; + + va_start(ap, size); + + switch (size) + { + case AOS_8_BITS: + val8 = va_arg(ap, const uint8_t *); + operand->value.val8 = *val8; + break; + case AOS_16_BITS: + val16 = va_arg(ap, const uint16_t *); + operand->value.val16 = *val16; + break; + case AOS_32_BITS: + val32 = va_arg(ap, const uint32_t *); + operand->value.val32 = *val32; + break; + case AOS_64_BITS: + val64 = va_arg(ap, const uint64_t *); + operand->value.val64 = *val64; + break; + } + + va_end(ap); + + return true; + +} + + +/****************************************************************************** +* * +* 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. * diff --git a/src/arch/operand.h b/src/arch/operand.h index 1067518..e913059 100644 --- a/src/arch/operand.h +++ b/src/arch/operand.h @@ -62,9 +62,15 @@ bool fill_db_operand(asm_operand *, uint8_t); /* Traduit une opérande de type 'db' en texte. */ void print_db_operand(const asm_operand *, char *, size_t, AsmSyntax); +/* Lit une valeur (signée ou non) sur x bits. */ +bool read_imm_value(AsmOperandSize, const uint8_t *, off_t *, off_t, ...); + /* 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 sur x bits. */ +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); diff --git a/src/arch/processor.c b/src/arch/processor.c index 0afca2c..373222f 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -60,9 +60,10 @@ asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, of if (result == NULL) + { + printf("err while decoding opcode 0x%0hhx at 0x%08llx\n", data[*pos], offset); result = create_db_instruction(data, pos, len); - - + } 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 . + */ + + +#include + + +#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 . + */ + + +#include + + +#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 . + */ + + +#include + + +#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 . + */ + + +#include + + +#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); } -- cgit v0.11.2-87-g4458