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