diff options
Diffstat (limited to 'src/arch/x86')
-rw-r--r-- | src/arch/x86/instruction.h | 4 | ||||
-rw-r--r-- | src/arch/x86/op_add.c | 35 | ||||
-rw-r--r-- | src/arch/x86/op_jump.c | 86 | ||||
-rw-r--r-- | src/arch/x86/op_push.c | 6 | ||||
-rw-r--r-- | src/arch/x86/opcodes.h | 9 | ||||
-rw-r--r-- | src/arch/x86/operand.c | 26 | ||||
-rw-r--r-- | src/arch/x86/processor.c | 18 |
7 files changed, 175 insertions, 9 deletions
diff --git a/src/arch/x86/instruction.h b/src/arch/x86/instruction.h index 8ef603f..baf911d 100644 --- a/src/arch/x86/instruction.h +++ b/src/arch/x86/instruction.h @@ -38,6 +38,8 @@ typedef struct _asm_x86_instr asm_x86_instr; /* Enumération de tous les opcodes */ typedef enum _X86Opcodes { + X86_OP_ADD_RM8_R8, /* add (0x00) */ + X86_OP_SUB_R1632_RM1632, /* sub ([0x66] 0x29) */ X86_OP_XOR_RM8_R8, /* xor (0x30) */ @@ -145,12 +147,14 @@ typedef enum _X86Opcodes X86_OP_INT, /* int (0xcd) */ X86_OP_CALL_REL1632, /* call ([0x66] 0xe8) */ + X86_OP_JMP_REL1632, /* jmp ([0x66] 0xe9) */ X86_OP_JMP_8, /* jmp (0xeb) */ X86_OP_HLT, /* hlt (0xf4) */ X86_OP_CALL_RM1632, /* call ([0x66] 0xff 2) */ + X86_OP_JMP_RM1632, /* jmp ([0x66] 0xff 4) */ X86_OP_PUSH_RM1632, /* push ([0x66] 0xff 6) */ X86_OP_COUNT diff --git a/src/arch/x86/op_add.c b/src/arch/x86/op_add.c index 52b998f..f42c8f9 100644 --- a/src/arch/x86/op_add.c +++ b/src/arch/x86/op_add.c @@ -104,3 +104,38 @@ asm_x86_instr *x86_read_instr_add_imm1632_to_rm1632(const uint8_t *data, off_t * return result; } + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'add' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_add_rm8_r8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + if (!x86_read_two_operands(result, data, pos, len, X86_OTP_RM8, X86_OTP_R8)) + { + free(result); + return NULL; + } + + return result; + +} diff --git a/src/arch/x86/op_jump.c b/src/arch/x86/op_jump.c index b301b10..3739b24 100644 --- a/src/arch/x86/op_jump.c +++ b/src/arch/x86/op_jump.c @@ -54,6 +54,8 @@ asm_x86_instr *x86_read_instr_je_8(const uint8_t *data, off_t *pos, off_t len, u ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + ASM_INSTRUCTION(result)->type = AIT_JUMP; + if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset)) { free(result); @@ -89,6 +91,8 @@ asm_x86_instr *x86_read_instr_jne_8(const uint8_t *data, off_t *pos, off_t len, ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + ASM_INSTRUCTION(result)->type = AIT_JUMP; + if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset)) { free(result); @@ -124,6 +128,8 @@ asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *data, off_t *pos, off_t len, ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + ASM_INSTRUCTION(result)->type = AIT_JUMP; + if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset)) { free(result); @@ -133,3 +139,83 @@ asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *data, off_t *pos, off_t len, return result; } + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'jmp' (grand saut relatif). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_jmp_rel1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + oprsize = switch_x86_operand_size_if_needed(proc, data, pos); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + ASM_INSTRUCTION(result)->type = AIT_JUMP; + + if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL1632, oprsize, offset)) + { + free(result); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* offset = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'jmp' (saut en mémoire). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +asm_x86_instr *x86_read_instr_jmp_rm1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc) +{ + asm_x86_instr *result; /* Instruction à retourner */ + AsmOperandSize oprsize; /* Taille des opérandes */ + + result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr)); + + oprsize = switch_x86_operand_size_if_needed(proc, data, pos); + + ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + + ASM_INSTRUCTION(result)->type = AIT_JUMP; + + if (!x86_read_one_operand(result, data, pos, len, X86_OTP_RM1632, oprsize)) + { + free(result); + return NULL; + } + + return result; + +} diff --git a/src/arch/x86/op_push.c b/src/arch/x86/op_push.c index ce76919..f51bd6f 100644 --- a/src/arch/x86/op_push.c +++ b/src/arch/x86/op_push.c @@ -58,6 +58,8 @@ asm_x86_instr *x86_read_instr_push_imm1632(const uint8_t *data, off_t *pos, off_ ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + ASM_INSTRUCTION(result)->type = AIT_PUSH; + if (!x86_read_one_operand(result, data, pos, len, X86_OTP_IMM1632, oprsize)) { free(result); @@ -96,6 +98,8 @@ asm_x86_instr *x86_read_instr_push_r1632(const uint8_t *data, off_t *pos, off_t ASM_INSTRUCTION(result)->opcode = data[*pos]; + ASM_INSTRUCTION(result)->type = AIT_PUSH; + if (!x86_read_one_operand(result, data, pos, len, X86_OTP_OP_R1632, oprsize, 0x50)) { free(result); @@ -134,6 +138,8 @@ asm_x86_instr *x86_read_instr_push_rm1632(const uint8_t *data, off_t *pos, off_t ASM_INSTRUCTION(result)->opcode = data[(*pos)++]; + ASM_INSTRUCTION(result)->type = AIT_PUSH; + if (!x86_read_one_operand(result, data, pos, len, X86_OTP_RM1632, oprsize)) { free(result); diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h index cbadcf5..70d41b8 100644 --- a/src/arch/x86/opcodes.h +++ b/src/arch/x86/opcodes.h @@ -43,6 +43,9 @@ asm_x86_instr *x86_read_instr_add_imm8_to_rm1632(const uint8_t *, off_t *, off_t /* Décode une instruction de type 'add' (16 ou 32 bits). */ asm_x86_instr *x86_read_instr_add_imm1632_to_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* Décode une instruction de type 'add' (8 bits). */ +asm_x86_instr *x86_read_instr_add_rm8_r8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'and' (16 ou 32 bits). */ asm_x86_instr *x86_read_instr_and_rm1632_with_imm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); @@ -82,6 +85,12 @@ asm_x86_instr *x86_read_instr_jne_8(const uint8_t *, off_t *, off_t, uint64_t, c /* Décode une instruction de type 'jump' (petit saut). */ asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); +/* Décode une instruction de type 'jmp' (grand saut relatif). */ +asm_x86_instr *x86_read_instr_jmp_rel1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + +/* Décode une instruction de type 'jmp' (saut en mémoire). */ +asm_x86_instr *x86_read_instr_jmp_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); + /* Décode une instruction de type 'lea' (16 ou 32 bits). */ asm_x86_instr *x86_read_instr_lea(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *); diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c index 375b0a5..e13c793 100644 --- a/src/arch/x86/operand.c +++ b/src/arch/x86/operand.c @@ -1300,7 +1300,8 @@ asm_x86_operand *x86_create_rel1632_operand_in_32b(uint64_t base, const uint8_t { asm_x86_operand *result; /* Emplacement à retourner */ off_t init_pos; /* Position avant lecture */ - int8_t offset; /* Décallage à appliquer */ + int32_t offset32; /* Décallage 32b à appliquer */ + int16_t offset16; /* Décallage 16b à appliquer */ uint32_t address; /* Adresse finale visée */ result = create_new_x86_operand(); @@ -1308,13 +1309,28 @@ asm_x86_operand *x86_create_rel1632_operand_in_32b(uint64_t base, const uint8_t init_pos = *pos; address = base; - if (!read_imm_value(is_reg32 ? AOS_32_BITS : AOS_16_BITS, data, pos, len, &offset)) + if (is_reg32) { - free(result); - return NULL; + if (!read_imm_value(AOS_32_BITS, data, pos, len, &offset32)) + { + free(result); + return NULL; + } + + address = base + (*pos - init_pos) + offset32; + } + else + { + if (!read_imm_value(AOS_16_BITS, data, pos, len, &offset16)) + { + free(result); + return NULL; + } - address = base + (*pos - init_pos) + offset; + address = base + (*pos - init_pos) + offset16; + + } if (!fill_imm_operand_with_value(ASM_OPERAND(result), AOS_32_BITS, &address)) { diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c index 0b81a8c..5694d9e 100644 --- a/src/arch/x86/processor.c +++ b/src/arch/x86/processor.c @@ -61,7 +61,7 @@ typedef struct _x86_opcode do { \ target.prefix = _prefix; \ target.opcode = _opcode; \ - target.opt_prefix = true; \ + target.opt_prefix = (_prefix != 0x00); \ target.has_op_ext = false; \ target.name = _name; \ target.read = _read; \ @@ -72,7 +72,7 @@ typedef struct _x86_opcode target.prefix = _prefix; \ target.opcode = _opcode; \ target.op_ext = _ext << 3; \ - target.opt_prefix = true; \ + target.opt_prefix = (_prefix != 0x00); \ target.has_op_ext = true; \ target.name = _name; \ target.read = _read; \ @@ -205,6 +205,8 @@ AsmOperandSize switch_x86_operand_size_if_needed(const asm_x86_processor *proc, void x86_register_instructions(asm_x86_processor *proc) { + register_opcode(proc->opcodes[X86_OP_ADD_RM8_R8], 0x00, 0x00, "add", x86_read_instr_add_rm8_r8); + register_opcode(proc->opcodes[X86_OP_SUB_R1632_RM1632], 0x66, 0x29, "sub", x86_read_instr_sub_r1632_from_rm1632); register_opcode(proc->opcodes[X86_OP_XOR_RM8_R8], 0x00, 0x30, "xor", x86_read_instr_xor_rm8_with_r8); @@ -314,12 +316,14 @@ void x86_register_instructions(asm_x86_processor *proc) register_opcode(proc->opcodes[X86_OP_CALL_REL1632], 0x66, 0xe8, "call", x86_read_instr_call_rel1632); + register_opcode(proc->opcodes[X86_OP_JMP_REL1632], 0x66, 0xe9, "jmp", x86_read_instr_jmp_rel1632); register_opcode(proc->opcodes[X86_OP_JMP_8], 0x00, 0xeb, "jmp", x86_read_instr_jmp_8); register_opcode(proc->opcodes[X86_OP_HLT], 0x00, 0xf4, "hlt", x86_read_instr_hlt); register_opcode_with_ext(proc->opcodes[X86_OP_CALL_RM1632], 0x66, 0xff, 2, "call", x86_read_instr_call_rm1632); + register_opcode_with_ext(proc->opcodes[X86_OP_JMP_RM1632], 0x66, 0xff, 4, "jmp", x86_read_instr_jmp_rm1632); register_opcode_with_ext(proc->opcodes[X86_OP_PUSH_RM1632], 0x66, 0xff, 6, "push", x86_read_instr_push_rm1632); @@ -367,6 +371,12 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d goto find_instr; } + if (proc->opcodes[i].prefix == 0x00 && data[*pos] == proc->opcodes[i].opcode) + { + tmp = *pos + 1; + goto find_instr; + } + continue; find_instr: @@ -381,7 +391,7 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d else { *pos = old_pos; - printf("err while decoding at 0x%08llx :: [0x%02hhx] 0x%02hhx\n", offset, proc->opcodes[i].prefix, proc->opcodes[i].opcode); + printf("err while x86 decoding at 0x%08llx :: [0x%02hhx] 0x%02hhx\n", offset, proc->opcodes[i].prefix, proc->opcodes[i].opcode); } break; @@ -456,7 +466,7 @@ void x86_print_instruction(const asm_x86_processor *proc, const exe_format *form /* Impression globale finale */ - if (ASM_INSTRUCTION(instr)->opcode == DB_OPCODE) + if (ASM_INSTRUCTION(instr)->type == AIT_DB) snprintf(buffer, len, "db\t%s", opbuffer[0]); else |