Example #1
0
/* -----------------------------------------------------------------------------
 * decode_operands() - Disassembles Operands.
 * -----------------------------------------------------------------------------
 */
static int
decode_operand(struct ud           *u, 
               struct ud_operand   *operand,
               enum ud_operand_code type,
               unsigned int         size)
{
  operand->_oprcode = type;

  switch (type) {
    case OP_A :
      decode_a(u, operand);
      break;
    case OP_MR:
      decode_modrm_rm(u, operand, REGCLASS_GPR, 
                      MODRM_MOD(modrm(u)) == 3 ? 
                        Mx_reg_size(size) : Mx_mem_size(size));
      break;
    case OP_F:
      u->br_far  = 1;
      /* intended fall through */
    case OP_M:
      if (MODRM_MOD(modrm(u)) == 3) {
        UDERR(u, "expected modrm.mod != 3\n");
      }
      /* intended fall through */
    case OP_E:
      decode_modrm_rm(u, operand, REGCLASS_GPR, size);
      break;
    case OP_G:
      decode_modrm_reg(u, operand, REGCLASS_GPR, size);
      break;
    case OP_sI:
    case OP_I:
      decode_imm(u, size, operand);
      break;
    case OP_I1:
      operand->type = UD_OP_CONST;
      operand->lval.udword = 1;
      break;
    case OP_N:
      if (MODRM_MOD(modrm(u)) != 3) {
        UDERR(u, "expected modrm.mod == 3\n");
      }
      /* intended fall through */
    case OP_Q:
      decode_modrm_rm(u, operand, REGCLASS_MMX, size);
      break;
    case OP_P:
      decode_modrm_reg(u, operand, REGCLASS_MMX, size);
      break;
    case OP_U:
      if (MODRM_MOD(modrm(u)) != 3) {
        UDERR(u, "expected modrm.mod == 3\n");
      }
      /* intended fall through */
    case OP_W:
      decode_modrm_rm(u, operand, REGCLASS_XMM, size);
      break;
    case OP_V:
      decode_modrm_reg(u, operand, REGCLASS_XMM, size);
      break;
    case OP_MU:
      decode_modrm_rm(u, operand, REGCLASS_XMM, 
                      MODRM_MOD(modrm(u)) == 3 ? 
                        Mx_reg_size(size) : Mx_mem_size(size));
      break;
    case OP_S:
      decode_modrm_reg(u, operand, REGCLASS_SEG, size);
      break;
    case OP_O:
      decode_moffset(u, size, operand);
      break;
    case OP_R0: 
    case OP_R1: 
    case OP_R2: 
    case OP_R3: 
    case OP_R4: 
    case OP_R5: 
    case OP_R6: 
    case OP_R7:
      decode_reg(u, operand, REGCLASS_GPR, 
                 (REX_B(u->pfx_rex) << 3) | (type - OP_R0), size);
      break;
    case OP_AL:
    case OP_AX:
    case OP_eAX:
    case OP_rAX:
      decode_reg(u, operand, REGCLASS_GPR, 0, size);
      break;
    case OP_CL:
    case OP_CX:
    case OP_eCX:
      decode_reg(u, operand, REGCLASS_GPR, 1, size);
      break;
    case OP_DL:
    case OP_DX:
    case OP_eDX:
      decode_reg(u, operand, REGCLASS_GPR, 2, size);
      break;
    case OP_ES: 
    case OP_CS: 
    case OP_DS:
    case OP_SS: 
    case OP_FS: 
    case OP_GS:
      /* in 64bits mode, only fs and gs are allowed */
      if (u->dis_mode == 64) {
        if (type != OP_FS && type != OP_GS) {
          UDERR(u, "invalid segment register in 64bits\n");
        }
      }
      operand->type = UD_OP_REG;
      operand->base = (type - OP_ES) + UD_R_ES;
      operand->size = 16;
      break;
    case OP_J :
      decode_imm(u, size, operand);
      operand->type = UD_OP_JIMM;
      break ;
    case OP_R :
      if (MODRM_MOD(modrm(u)) != 3) {
        UDERR(u, "expected modrm.mod == 3\n");
      }
      decode_modrm_rm(u, operand, REGCLASS_GPR, size);
      break;
    case OP_C:
      decode_modrm_reg(u, operand, REGCLASS_CR, size);
      break;
    case OP_D:
      decode_modrm_reg(u, operand, REGCLASS_DB, size);
      break;
    case OP_I3 :
      operand->type = UD_OP_CONST;
      operand->lval.sbyte = 3;
      break;
    case OP_ST0: 
    case OP_ST1: 
    case OP_ST2: 
    case OP_ST3:
    case OP_ST4:
    case OP_ST5: 
    case OP_ST6: 
    case OP_ST7:
      operand->type = UD_OP_REG;
      operand->base = (type - OP_ST0) + UD_R_ST0;
      operand->size = 80;
      break;
    default :
      break;
  }
  return 0;
}
Example #2
0
/* -----------------------------------------------------------------------------
 * decode_operands() - Disassembles Operands.
 * -----------------------------------------------------------------------------
 */
static int
decode_operand(struct ud           *u, 
               struct ud_operand   *operand,
               enum ud_operand_code type,
               unsigned int         size)
{
  switch (type) {
    case OP_A :
      decode_a(u, operand);
      break;
    case OP_MR:
      if (MODRM_MOD(modrm(u)) == 3) {
        decode_modrm_rm(u, operand, T_GPR, 
                        size == SZ_DY ? SZ_MDQ : SZ_V);
      } else if (size == SZ_WV) {
        decode_modrm_rm( u, operand, T_GPR, SZ_W);
      } else if (size == SZ_BV) {
        decode_modrm_rm( u, operand, T_GPR, SZ_B);
      } else if (size == SZ_DY) {
        decode_modrm_rm( u, operand, T_GPR, SZ_D);
      } else {
        assert(!"unexpected size");
      }
      break;
    case OP_M:
      if (MODRM_MOD(modrm(u)) == 3) {
          u->error = 1;
      }
      /* intended fall through */
    case OP_E:
      decode_modrm_rm(u, operand, T_GPR, size);
      break;
      break;
    case OP_G:
      decode_modrm_reg(u, operand, T_GPR, size);
      break;
    case OP_I:
      decode_imm(u, size, operand);
      break;
    case OP_I1:
      operand->type = UD_OP_CONST;
      operand->lval.udword = 1;
      break;
    case OP_PR:
      if (MODRM_MOD(modrm(u)) != 3) {
          u->error = 1;
      }
      decode_modrm_rm(u, operand, T_MMX, size);
      break;
    case OP_P:
      decode_modrm_reg(u, operand, T_MMX, size);
      break;
    case OP_VR:
      if (MODRM_MOD(modrm(u)) != 3) {
          u->error = 1;
      }
      /* intended fall through */
    case OP_W:
      decode_modrm_rm(u, operand, T_XMM, size);
      break;
    case OP_V:
      decode_modrm_reg(u, operand, T_XMM, size);
      break;
    case OP_S:
      decode_modrm_reg(u, operand, T_SEG, size);
      break;
    case OP_AL:
    case OP_CL:
    case OP_DL:
    case OP_BL:
    case OP_AH:
    case OP_CH:
    case OP_DH:
    case OP_BH:
      operand->type = UD_OP_REG;
      operand->base = UD_R_AL + (type - OP_AL);
      operand->size = 8;
      break;
    case OP_DX:
      operand->type = UD_OP_REG;
      operand->base = UD_R_DX;
      operand->size = 16;
      break;
    case OP_O:
      decode_o(u, size, operand);
      break;
    case OP_rAXr8: 
    case OP_rCXr9: 
    case OP_rDXr10: 
    case OP_rBXr11:
    case OP_rSPr12: 
    case OP_rBPr13: 
    case OP_rSIr14: 
    case OP_rDIr15:
    case OP_rAX: 
    case OP_rCX: 
    case OP_rDX: 
    case OP_rBX:
    case OP_rSP: 
    case OP_rBP: 
    case OP_rSI: 
    case OP_rDI:
      operand->type = UD_OP_REG;
      operand->base = resolve_gpr64(u, type, &operand->size);
      break;
    case OP_ALr8b:
    case OP_CLr9b: 
    case OP_DLr10b: 
    case OP_BLr11b:
    case OP_AHr12b:
    case OP_CHr13b:
    case OP_DHr14b:
    case OP_BHr15b: {
      ud_type_t gpr = (type - OP_ALr8b) + UD_R_AL
                        + (REX_B(u->pfx_rex) << 3);
      if (UD_R_AH <= gpr && u->pfx_rex) {
        gpr = gpr + 4;
      }
      operand->type = UD_OP_REG;
      operand->base = gpr;
      break;
    }
    case OP_eAX: 
    case OP_eCX: 
    case OP_eDX: 
    case OP_eBX:
    case OP_eSP: 
    case OP_eBP: 
    case OP_eSI: 
    case OP_eDI:
      operand->type = UD_OP_REG;
      operand->base = resolve_gpr32(u, type);
      operand->size = u->opr_mode == 16 ? 16 : 32;
      break;
    case OP_ES: 
    case OP_CS: 
    case OP_DS:
    case OP_SS: 
    case OP_FS: 
    case OP_GS:
      /* in 64bits mode, only fs and gs are allowed */
      if (u->dis_mode == 64) {
        if (type != OP_FS && type != OP_GS) {
          u->error= 1;
        }
      }
      operand->type = UD_OP_REG;
      operand->base = (type - OP_ES) + UD_R_ES;
      operand->size = 16;
      break;
    case OP_J :
      decode_imm(u, size, operand);
      operand->type = UD_OP_JIMM;
      break ;
    case OP_Q:
      decode_modrm_rm(u, operand, T_MMX, size);
      break;
    case OP_R :
      decode_modrm_rm(u, operand, T_GPR, size);
      break;
    case OP_C:
      decode_modrm_reg(u, operand, T_CRG, size);
      break;
    case OP_D:
      decode_modrm_reg(u, operand, T_DBG, size);
      break;
    case OP_I3 :
      operand->type = UD_OP_CONST;
      operand->lval.sbyte = 3;
      break;
    case OP_ST0: 
    case OP_ST1: 
    case OP_ST2: 
    case OP_ST3:
    case OP_ST4:
    case OP_ST5: 
    case OP_ST6: 
    case OP_ST7:
      operand->type = UD_OP_REG;
      operand->base = (type - OP_ST0) + UD_R_ST0;
      operand->size = 0;
      break;
    case OP_AX:
      operand->type = UD_OP_REG;
      operand->base = UD_R_AX;
      operand->size = 16;
      break;
    default :
      operand->type = UD_NONE;
      break;
  }
  return 0;
}
Example #3
0
    virtual void handle_mov(UByte opcode, size_t word_size) {

        switch (opcode) {
        case 0x88:
        case 0x8A:
        case 0x89:
        case 0x8E:
        {
            //
            // Modify R/M and REG fields in the MOD R/M byte
            //

            UByte fault;
            UByte modrm;

            _scanner.get(&modrm);

            switch (decode_modrm_mod(modrm)) {
            case 0:
                if (word_size == 4 && decode_modrm_rm(modrm) == 4) {
                    fault = modify_reg(modrm);
                }
                else if (decode_modrm_rm(modrm) == 5) {
                    fault = modify_reg(modrm);
                }
                else {
                    fault = modify_rm_reg(modrm);
                }
                break;
            case 1:
                if (word_size == 4 && decode_modrm_rm(modrm) == 4) {
                    fault = modify_reg(modrm);
                }
                else {
                    fault = modify_rm_reg(modrm);
                }
                break;
            case 2:
                if (word_size == 4 && decode_modrm_rm(modrm) == 4) {
                    fault = modify_reg(modrm);
                }
                else {
                    fault = modify_rm_reg(modrm);
                }
                break;
            case 3:
                fault = modify_rm_reg(modrm);
                break;
            default:
                System.Print(System.WARN, "Unknown modrm");
                return;
            }

            // Inject a fault
            _scanner.seek(-1, scanner::SEEK_CUR);
            _scanner.put(fault);

            // OK. Let's work on the next instruction.
            skip_modrm(fault, word_size);

            break;
        }
        // [SKIP] Segment registers
        case 0x8B:
        case 0x8C:
        {
            UByte   next;
            _scanner.get(&next);
            skip_modrm(next, word_size);
            break;
        }
        // [SKIP] Immediate
        case 0xC6:
        {
            UByte   next;
            _scanner.get(&next);
            skip_modrm(next, word_size);
            skip_one();
            break;
        }
        // [SKIP] Immediate
        case 0xC7:
        {
            UByte   next;
            _scanner.get(&next);
            skip_modrm(next, word_size);
            skip_word(word_size);
            break;
        }
        // [SKIP] 'A' register (i.e. al, ax, eax)
        case 0xA0:
        case 0xA1:
        case 0xA2:
        case 0xA3:
        {
            skip_word(word_size);
            break;
        }
        default:
        {
            // Move imm8 to r8
            if (0xB0 <= opcode && opcode <= 0xB7) {
                UByte fault = opcode;
                while (fault == opcode) {
                    fault = 0xB0 | (static_cast<UByte>(rand()) & 0xF);
                }

                // Inject a fault
                _scanner.seek(-1, scanner::SEEK_CUR);
                _scanner.put(fault);

                // OK. Work on the next instruction.
                skip_one();

                System.Print("FI: MOV(%.2X): Change opcode %.2X\n",
                             opcode, fault);
            }
            // Move imm16/32 to r16/32
            else if (0xB8 <= opcode && opcode <= 0xBF) {
                UByte fault = opcode;
                while (fault == opcode) {
                    fault = 0xB8 | (static_cast<UByte>(rand()) & 0xF);
                }

                // Inject a fault
                _scanner.seek(-1, scanner::SEEK_CUR);
                _scanner.put(fault);

                // OK. Work on the next instruction.
                skip_word(word_size);

                System.Print("FI: MOV(%.2X): Change opcode %.2X\n",
                             opcode, fault);
            }
        }
        } // switch
    }