diff options
Diffstat (limited to 'src')
| -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 | ||||
| -rw-r--r-- | src/format/elf/e_elf.c | 12 | ||||
| -rw-r--r-- | src/format/elf/elf-int.h | 33 | ||||
| -rw-r--r-- | src/format/elf/symbol.c | 305 | 
15 files changed, 664 insertions, 20 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 diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c index 3aa9394..03b2e82 100644 --- a/src/format/elf/e_elf.c +++ b/src/format/elf/e_elf.c @@ -137,6 +137,18 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)      if (format->sec_size > 0)      { +        if (find_elf_section(format, ".plt", &offset, &size, &voffset)) +        { +            part = create_bin_part(); + +            set_bin_part_name(part, ".plt"); +            set_bin_part_values(part, offset, size, voffset); + +            result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); +            result[*count - 1] = part; + +        } +          if (find_elf_section(format, ".init", &offset, &size, &voffset))          {              part = create_bin_part(); diff --git a/src/format/elf/elf-int.h b/src/format/elf/elf-int.h index f366c71..6e7bca1 100644 --- a/src/format/elf/elf-int.h +++ b/src/format/elf/elf-int.h @@ -84,6 +84,39 @@ typedef union _Elf_Phdr  #define ELF_PHDR(fmt, hdr, fld) (fmt->is_32b ? hdr.header32.fld : hdr.header64.fld) +/* Entrée de la table de relocalisation */ + +typedef union _Elf_Rel +{ +    Elf32_Rel rel32;                        /* Version 32 bits             */ +    Elf64_Rel rel64;                        /* Version 64 bits             */ + +} Elf_Rel; + +#define ELF_SIZEOF_REL(fmt) (fmt->is_32b ? sizeof(Elf32_Rel) : sizeof(Elf64_Rel)) + +#define ELF_REL(fmt, rl, fld) (fmt->is_32b ? rl.rel32.fld : rl.rel64.fld) + +#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM(rl.rel32.r_info) : ELF64_R_SYM(rl.rel64.r_info)) +#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE(rl.rel32.r_info) : ELF64_R_TYPE(rl.rel64.r_info)) + + +/* Information sur un symbole */ + +typedef union _Elf_Sym +{ +    Elf32_Sym sym32;                        /* Version 32 bits             */ +    Elf64_Sym sym64;                        /* Version 64 bits             */ + +} Elf_Sym; + +#define ELF_SIZEOF_SYM(fmt) (fmt->is_32b ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym)) + +#define ELF_SYM(fmt, sb, fld) (fmt->is_32b ? sb.sym32.fld : sb.sym64.fld) + + + +  #endif  /* _FORMAT_ELF_ELF_INT_H */ diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c index 729c154..8fa5690 100644 --- a/src/format/elf/symbol.c +++ b/src/format/elf/symbol.c @@ -26,9 +26,14 @@  #include <malloc.h>  #include <elf.h> +#include <stdio.h>  #include <string.h> +#include "../../arch/processor.h" /* FIXME : remove me ! */ +#include "../../arch/instruction.h" /* FIXME : remove me ! */ +#include "../../arch/instruction-int.h" /* FIXME : remove me ! */ +  #include "elf-int.h"  #include "section.h" @@ -37,6 +42,24 @@ +/* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */ + + +/* Charge en mémoire la liste des symboles dynamiques. */ +bool load_elf_relocation_table(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *); + +/* Récupère les informations d'un symbole dynamique donné. */ +char *get_elf_dynamic_symbol_info(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *); + +/* Décode les instructions liées à la relocalisation. */ +asm_instr **decode_elf_relocations(elf_format *, size_t *); + +/* Déduit les adresses effectives des relocalisations. */ +void translate_elf_relocations(elf_format *, asm_instr **, size_t); + + + +  /* Charge en mémoire la liste humaine des symboles (32 bits). */  bool load_elf_symbol_table_32(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *); @@ -69,6 +92,16 @@ bool load_elf_symbols(elf_format *format)      off_t str_size;                         /* Taille de section           */ +    off_t plt_start;                        /* Début de section            */ +    off_t plt_size;                         /* Taille de section           */ +    off_t dyn_start;                        /* Début de section            */ +    off_t dyn_size;                         /* Taille de section           */ + + +    asm_instr **instructions;               /* Instructions décodées       */ +    size_t count;                           /* Quantité d'instructions     */ + +      result = find_elf_section(format, ".symtab", &sym_start, &sym_size, NULL);      result &= find_elf_section(format, ".strtab", &str_start, &str_size, NULL); @@ -79,12 +112,46 @@ bool load_elf_symbols(elf_format *format) -        result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_start); +        result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_size);      } + + + + + + +    result = find_elf_section(format, ".rel.plt", &plt_start, &plt_size, NULL); + +    result &= find_elf_section(format, ".dynsym", &dyn_start, &dyn_size, NULL); + +    result &= find_elf_section(format, ".dynstr", &str_start, &str_size, NULL); + + + +    if (result) +    { + + + +        result = load_elf_relocation_table(format, &plt_start, &plt_size, &dyn_start, &dyn_size, &str_start, &str_size); + +        if (result) +        { +            instructions = decode_elf_relocations(format, &count); + +            translate_elf_relocations(format, instructions, count); + +            /* TODO : free instructions */ + +        } + + +    } +      return result;  } @@ -96,11 +163,11 @@ bool load_elf_symbols(elf_format *format)  /******************************************************************************  *                                                                             * -*  Paramètres  : format     = description de l'exécutable à compléter.        * -*                sym_start  = début de la zone à traiter.                     * -*                sym_size   = taille de la zone à traiter.                    * -*                str_start  = début de la zone de chaîne de caractères.       * -*                str_size   = taille de la zone de chaînes de caractères.     * +*  Paramètres  : format    = description de l'exécutable à compléter.         * +*                sym_start = début de la zone à traiter.                      * +*                sym_size  = taille de la zone à traiter.                     * +*                str_start = début de la zone de chaîne de caractères.        * +*                str_size  = taille de la zone de chaînes de caractères.      *  *                                                                             *  *  Description : Charge en mémoire la liste humaine des symboles (32 bits).   *  *                                                                             * @@ -149,11 +216,11 @@ bool load_elf_symbol_table_32(elf_format *format, const off_t *sym_start, const  /******************************************************************************  *                                                                             * -*  Paramètres  : format     = description de l'exécutable à compléter.        * -*                sym_start  = début de la zone à traiter.                     * -*                sym_size   = taille de la zone à traiter.                    * -*                str_start  = début de la zone de chaîne de caractères.       * -*                str_size   = taille de la zone de chaînes de caractères.     * +*  Paramètres  : format    = description de l'exécutable à compléter.         * +*                sym_start = début de la zone à traiter.                      * +*                sym_size  = taille de la zone à traiter.                     * +*                str_start = début de la zone de chaîne de caractères.        * +*                str_size  = taille de la zone de chaînes de caractères.      *  *                                                                             *  *  Description : Charge en mémoire la liste humaine des symboles (64 bits).   *  *                                                                             * @@ -241,3 +308,219 @@ void get_elf_symbol_comments(const elf_format *format, char ***comments, uint64_      }  } + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/*                            DETAIL DES SYMBOLES EXTERNES                            */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format    = description de l'exécutable à compléter.         * +*                plt_start = début de la zone à traiter.                      * +*                plt_size  = taille de la zone à traiter.                     * +*                dyn_start = début des informations dynamiques associées.     * +*                dyn_size  = taille de la zone associée.                      * +*                str_start = début de la zone de chaîne de caractères.        * +*                str_size  = taille de la zone de chaînes de caractères.      * +*                                                                             * +*  Description : Charge en mémoire la liste des symboles dynamiques.          * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool load_elf_relocation_table(elf_format *format, const off_t *plt_start, const off_t *plt_size, const off_t *dyn_start, const off_t *dyn_size, const off_t *str_start, const off_t *str_size) +{ +    off_t iter;                             /* Boucle de parcours          */ +    Elf_Rel reloc;                          /* Infos de relocalisation     */ +    off_t index;                            /* Indice de la portion visée  */ +    char *name;                             /* Nom du symbole trouvé       */ + +    for (iter = *plt_start; iter < (*plt_start + *plt_size); iter += ELF_SIZEOF_REL(format)) +    { +        memcpy(&reloc, &EXE_FORMAT(format)->content[iter], ELF_SIZEOF_REL(format)); + +        switch (format->header.e_machine) +        { +            case EM_386: +                switch (ELF32_R_TYPE(ELF_REL_TYPE(format, reloc))) +                { +                    case R_386_JMP_SLOT: + +                        index = ELF_REL_SYM(format, reloc); +                        name = get_elf_dynamic_symbol_info(format, dyn_start, dyn_size, &index, str_start, str_size); + +                        if (name != NULL) +                        { +                            format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol)); + +                            format->symbols[format->sym_count - 1].name = name; +                            format->symbols[format->sym_count - 1].address = ELF_REL(format, reloc, r_offset); + +                        } + +                        break; + +                    default: +                        printf("Relocation not supported (%lld) !\n", ELF_REL_TYPE(format, reloc)); +                        break; + +                } +                break; + +            default: +                printf("Machine not recognized !\n"); +                return false; +                break; + +        } + + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format    = description de l'exécutable à compléter.         * +*                dyn_start = début des informations dynamiques associées.     * +*                dyn_size  = taille de la zone associée.                      * +*                index     = indice de l'entrée à venir lire.                 * +*                str_start = début de la zone de chaîne de caractères.        * +*                str_size  = taille de la zone de chaînes de caractères.      * +*                                                                             * +*  Description : Récupère les informations d'un symbole dynamique donné.      * +*                                                                             * +*  Retour      : Nom du symbole trouvé, ou NULL si erreur ou non adapté.      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +char *get_elf_dynamic_symbol_info(elf_format *format, const off_t *dyn_start, const off_t *dyn_size, const off_t *index, const off_t *str_start, const off_t *str_size) +{ +    off_t offset;                           /* Emplacement à venir lire    */ +    Elf_Sym symbol;                         /* Symbole aux infos visées    */ + +    offset = *dyn_start + *index * ELF_SIZEOF_SYM(format); +    if ((offset + ELF_SIZEOF_SYM(format)) > (*dyn_start + *dyn_size)) return NULL; + +    memcpy(&symbol, &EXE_FORMAT(format)->content[offset], ELF_SIZEOF_SYM(format)); + +    if (ELF_SYM(format, symbol, st_name) >= *str_size) return NULL; + +    return (char *)&EXE_FORMAT(format)->content[*str_start + ELF_SYM(format, symbol, st_name)]; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = description de l'exécutable à compléter.            * +*                count  = nombre d'instructions lues. [OUT]                   * +*                                                                             * +*  Description : Décode les instructions liées à la relocalisation.           * +*                                                                             * +*  Retour      : Liste des instructions décodées ou NULL.                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +asm_instr **decode_elf_relocations(elf_format *format, size_t *count) +{ +    asm_instr **result;                     /* Liste à renvoyer            */ +    off_t rel_start;                        /* Début de section            */ +    off_t rel_size;                         /* Taille de section           */ +    uint64_t rel_vaddress;                  /* Adresse virtuelle associée  */ +    off_t pos;                              /* Tête de lecture             */ +    uint64_t offset;                        /* Adresse virtuelle courante  */ +    asm_instr *instr;                       /* Instruction décodée         */ + +    asm_processor *proc;    /* TODO : remove me ! */ +    proc = create_x86_processor(); + +    result = NULL; +    *count = 0; + +    if (find_elf_section(format, ".plt", &rel_start, &rel_size, &rel_vaddress)) +        for (pos = 0; pos < rel_size; ) +        { +            offset = rel_vaddress + pos; + +            instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, offset); + +            result = (asm_instr **)realloc(result, ++(*count) * sizeof(asm_instr *)); +            result[*count - 1] = instr; + +        } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format       = description de l'exécutable à compléter.      * +*                instructions = listes des instructions à interpréter.        * +*                count        = nombre d'instructions lues.                   * +*                                                                             * +*  Description : Déduit les adresses effectives des relocalisations.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void translate_elf_relocations(elf_format *format, asm_instr **instructions, size_t count) +{ +    size_t i;                               /* Boucle de parcours #1       */ +    uint64_t address;                       /* Adresse virtuelle finale    */ +    size_t j;                               /* Boucle de parcours #2       */ +    size_t new_len;                         /* Taille du nouveau nom       */ +    char *new_name;                         /* Nom avec suffixe @plt       */ + +    for (i = 0; (i + 2) < count; ) +    { +        if (instructions[i]->type == AIT_JUMP +            && instructions[i + 1]->type == AIT_PUSH +            && instructions[i + 2]->type == AIT_JUMP) +        { +            if (get_imm_operand_value(instructions[i]->operands[0], AOS_64_BITS, &address)) +                for (j = 0; j < format->sym_count; j++) +                    if (format->symbols[j].address == address) +                    { +                        new_len = strlen(format->symbols[j].name) + 4 + 1; +                        new_name = calloc(new_len, sizeof(char)); +                        snprintf(new_name, new_len, "%s@plt", format->symbols[j].name); + +                        format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol)); + +                        format->symbols[format->sym_count - 1].name = new_name; +                        format->symbols[format->sym_count - 1].address = instructions[i]->vaddress; + +                    } + +            i += 3; + +        } +        else i++; + +    } + +}  | 
