示例#1
0
def _update_strings_dst(self, tb, dst, size, instruction):
    # Create labels.
    forward_lbl = ReilLabel('forward')
    backward_lbl = ReilLabel('backward')

    end_addr = ReilImmediateOperand((instruction.address + instruction.size) << 8, self._arch_info.address_size + 8)

    # Define immediate registers.
    imm_one = tb.immediate(1, 1)

    # Define temporary registers.
    df_zero = tb.temporal(1)
    imm_tmp = tb.immediate(size // 8, dst.size)
    dst_tmp = tb.temporal(dst.size)

    # Update destination pointer.
    tb.add(self._builder.gen_bisz(self._flags.df, df_zero))
    tb.add(self._builder.gen_jcc(df_zero, forward_lbl))

    # Update backwards.
    tb.add(backward_lbl)
    tb.add(self._builder.gen_sub(dst, imm_tmp, dst_tmp))
    tb.add(self._builder.gen_str(dst_tmp, dst))

    # Jump to next instruction.
    tb.add(self._builder.gen_jcc(imm_one, end_addr))

    # Update forwards.
    tb.add(forward_lbl)
    tb.add(self._builder.gen_add(dst, imm_tmp, dst_tmp))
    tb.add(self._builder.gen_str(dst_tmp, dst))
示例#2
0
def _translate_cmpxchg(self, tb, instruction):
    # Flags Affected
    # The ZF flag is set if the values in the destination operand
    # and register AL, AX, or EAX are equal; otherwise it is
    # cleared. The CF, PF, AF, SF, and OF flags are set according
    # to the results of the comparison operation.

    # Accumulator = AL, AX, EAX, or RAX depending on whether a byte,
    # word, doubleword, or quadword comparison is being performed
    # IF accumulator = DEST
    # THEN
    #   ZF <- 1;
    #   DEST <- SRC;
    # ELSE
    #   ZF <- 0;
    #   accumulator <- DEST;
    # FI;

    oprnd0 = self._reg_acc_translator.read(tb, instruction.operands[0])
    oprnd1 = self._reg_acc_translator.read(tb, instruction.operands[1])

    accum_x86 = __get_cmpxchg_implicit_operand(oprnd0.size)

    accum = self._reg_acc_translator.read(tb, accum_x86)

    # Define immediate registers
    end_addr = ReilImmediateOperand(
        (instruction.address + instruction.size) << 8,
        self._arch_info.address_size + 8)

    tmp0 = tb.temporal(oprnd0.size * 2)

    one = tb.immediate(1, 1)

    change_dst_lbl = ReilLabel('change_dst')
    change_accum_lbl = ReilLabel('change_accum')

    # Compare.
    tb.add(self._builder.gen_sub(accum, oprnd0, tmp0))

    # Update flags : CF, OF, SF, ZF, AF, PF
    self._flag_translator.update_cf(tb, accum, tmp0)
    self._flag_translator.update_of(tb, accum, oprnd0, tmp0, subtraction=True)
    self._flag_translator.update_sf(tb, accum, tmp0)
    self._flag_translator.update_zf(tb, accum, tmp0)
    self._flag_translator.update_af(tb, accum, oprnd0, subtraction=True)
    self._flag_translator.update_pf(tb, tmp0)

    # Exchange
    tb.add(self._builder.gen_jcc(tmp0, change_accum_lbl))
    tb.add(change_dst_lbl)
    self._reg_acc_translator.write(tb, instruction.operands[0], oprnd1)
    tb.add(self._builder.gen_jcc(one, end_addr))
    tb.add(change_accum_lbl)
    # tb.add(self._builder.gen_str(oprnd0, accum))
    self._reg_acc_translator.write(tb, accum_x86, oprnd0)
示例#3
0
def _translate_cmovcc(self, tb, instruction, condition_code):
    # Move if condition (condition_code) is met.
    # Flags Affected
    # None.

    oprnd0 = self._reg_acc_translator.read(tb, instruction.operands[0])
    oprnd1 = self._reg_acc_translator.read(tb, instruction.operands[1])

    # NOTE: CMOV pseudocode (not its description) specifies that in 32-bit
    # registers, even if the condition is not met, the upper 32 bits of the
    # destination are set to zero (DEST[63:32] <- 0). So oprnd0 (dst) is
    # assigned to itself, in 32 bits that doesn't change anything, in 64 it
    # sets the upper 32 bits to zero. Then, if the condition is met, the mov
    # is performed and the previous assignment has no effect (oprnd0 <-
    # oprnd0.)
    tmp = tb.temporal(oprnd0.size)
    tb.add(self._builder.gen_str(oprnd0, tmp))
    self._reg_acc_translator.write(tb, instruction.operands[0], tmp)

    cond_not_met = ReilLabel('cond_not_met')

    neg_cond = negate_reg(
        tb, X86ConditionCodeHelper.evaluate_cc(self._flags, tb,
                                               condition_code))

    tb.add(self._builder.gen_jcc(neg_cond, cond_not_met))

    self._reg_acc_translator.write(tb, instruction.operands[0], oprnd1)

    tb.add(cond_not_met)
    tb.add(self._builder.gen_nop())
示例#4
0
def _translate_psrldq(self, tb, instruction):
    # Flags Affected
    # None.

    # Operation
    # PSRLDQ(128-bit Legacy SSE version)
    # TEMP <- COUNT
    # IF (TEMP > 15) THEN TEMP <- 16; FI
    # DEST <- DEST >> (TEMP * 8)
    # DEST[MAX_VL-1:128] (Unmodified)

    # NOTE Only supports xmm registers.

    oprnd0 = self._reg_acc_translator.read(tb, instruction.operands[0])
    oprnd1 = self._reg_acc_translator.read(tb, instruction.operands[1])

    count = tb.temporal(oprnd0.size)
    count_tmp = tb.temporal(oprnd1.size)
    count_tmp_2 = tb.temporal(oprnd1.size)
    tmp0 = tb.temporal(oprnd1.size)
    cmp_result = tb.temporal(1)
    dst = tb.temporal(oprnd0.size)

    imm0 = tb.immediate(~0x7fff, oprnd1.size)

    # Create labels.
    count_ok_lbl = ReilLabel('count_ok_lbl')

    # Check if count <= 16
    tb.add(self._builder.gen_str(oprnd1, count_tmp))
    tb.add(self._builder.gen_and(count_tmp, imm0, tmp0))
    tb.add(self._builder.gen_bisz(tmp0, cmp_result))
    tb.add(self._builder.gen_jcc(cmp_result, count_ok_lbl))

    # Set count to 16.
    tb.add(self._builder.gen_str(imm0, count_tmp))

    # Count ok.
    tb.add(count_ok_lbl)

    # Extend count to the size of oprnd0 and multiply by 8.
    tb.add(
        self._builder.gen_mul(count_tmp, tb.immediate(8, oprnd1.size),
                              count_tmp_2))

    # Negate
    tb.add(
        self._builder.gen_sub(tb.immediate(0, oprnd1.size), count_tmp_2,
                              count))

    # Do the shift.
    tb.add(self._builder.gen_bsh(oprnd0, count, dst))

    # Save the result.
    self._reg_acc_translator.write(tb, instruction.operands[0], dst)
示例#5
0
def _update_strings_src_and_dst(self, tb, src, dst, size):
    # Create labels.
    forward_lbl = ReilLabel('forward')
    backward_lbl = ReilLabel('backward')
    continue_lbl = ReilLabel('continue')

    # Define immediate registers.
    imm_one = tb.immediate(1, 1)

    # Define temporary registers.
    df_zero = tb.temporal(1)
    imm_tmp = tb.immediate(size // 8, src.size)
    src_tmp = tb.temporal(src.size)
    dst_tmp = tb.temporal(dst.size)

    # Update destination pointer.
    tb.add(self._builder.gen_bisz(self._flags.df, df_zero))
    tb.add(self._builder.gen_jcc(df_zero, forward_lbl))

    # Update backwards.
    tb.add(backward_lbl)
    # src
    tb.add(self._builder.gen_sub(src, imm_tmp, src_tmp))
    tb.add(self._builder.gen_str(src_tmp, src))
    # dst
    tb.add(self._builder.gen_sub(dst, imm_tmp, dst_tmp))
    tb.add(self._builder.gen_str(dst_tmp, dst))

    # Jump to next instruction.
    tb.add(self._builder.gen_jcc(imm_one, continue_lbl))

    # Update forwards.
    tb.add(forward_lbl)
    # src
    tb.add(self._builder.gen_add(src, imm_tmp, src_tmp))
    tb.add(self._builder.gen_str(src_tmp, src))
    # dst
    tb.add(self._builder.gen_add(dst, imm_tmp, dst_tmp))
    tb.add(self._builder.gen_str(dst_tmp, dst))

    # Continuation label.
    tb.add(continue_lbl)
示例#6
0
def _rep_prefix_begin(self, tb, instruction):
    # Define counter register.
    counter_x86 = __get_counter_register(self._arch_info.address_size)

    counter = self._reg_acc_translator.read(tb, counter_x86)

    # Create labels.
    loop_start_lbl = ReilLabel('loop_start')

    # Define immediate registers.
    end_addr = ReilImmediateOperand((instruction.address + instruction.size) << 8, self._arch_info.address_size + 8)

    # Define temporary registers.
    counter_zero = tb.temporal(1)

    tb.add(loop_start_lbl)

    tb.add(self._builder.gen_bisz(counter, counter_zero))
    tb.add(self._builder.gen_jcc(counter_zero, end_addr))

    return counter, loop_start_lbl
示例#7
0
def _translate_setcc(self, tb, instruction, condition_code):
    # Set if condition (condition_code) is met.
    # Flags Affected
    # None.

    self._reg_acc_translator.write(tb, instruction.operands[0],
                                   tb.immediate(0, 1))

    cond_not_met = ReilLabel('cond_not_met')

    neg_cond = negate_reg(
        tb, X86ConditionCodeHelper.evaluate_cc(self._flags, tb,
                                               condition_code))

    tb.add(self._builder.gen_jcc(neg_cond, cond_not_met))

    self._reg_acc_translator.write(
        tb, instruction.operands[0],
        tb.immediate(1, instruction.operands[0].size))

    tb.add(cond_not_met)
    tb.add(self._builder.gen_nop())
示例#8
0
 def label(self, name):
     return ReilLabel(name)
示例#9
0
def _translate_shrd(self, tb, instruction):
    # Flags Affected
    # If the count is 1 or greater, the CF flag is filled with the last
    # bit shifted out of the destination operand and the SF, ZF, and PF
    # flags are set according to the value of the result. For a 1-bit
    # shift, the OF flag is set if a sign change occurred; otherwise, it
    # is cleared. For shifts greater than 1 bit, the OF flag is undefined.
    # If a shift occurs, the AF flag is undefined. If the count operand is
    # 0, the flags are not affected. If the count is greater than the
    # operand size, the flags are undefined.

    # Operation
    # IF (In 64-Bit Mode and REX.W = 1)
    #     THEN COUNT <- COUNT MOD 64;
    #     ELSE COUNT <- COUNT MOD 32;
    # FI
    # SIZE <- OperandSize;
    # IF COUNT = 0
    #     THEN
    #         No operation;
    #     ELSE
    #         IF COUNT > SIZE
    #             THEN (* Bad parameters *)
    #                 DEST is undefined;
    #                 CF, OF, SF, ZF, AF, PF are undefined;
    #             ELSE (* Perform the shift *)
    #                 CF <- BIT[DEST, COUNT - 1]; (* Last bit shifted out on exit *)
    #                 FOR i <- 0 TO SIZE - 1 - COUNT
    #                     DO
    #                         BIT[DEST, i] <- BIT[DEST, i + COUNT];
    #                     OD;
    #                 FOR i <- SIZE - COUNT TO SIZE - 1
    #                     DO
    #                         BIT[DEST,i] <- BIT[SRC, i + COUNT - SIZE];
    #                     OD;
    #             FI;
    # FI;

    oprnd0 = self._reg_acc_translator.read(tb, instruction.operands[0])
    oprnd1 = self._reg_acc_translator.read(tb, instruction.operands[1])
    oprnd2 = self._reg_acc_translator.read(tb, instruction.operands[2])

    if self._arch_info.architecture_mode == ARCH_X86_MODE_32:
        mod_const = tb.immediate(32, oprnd2.size)
    elif self._arch_info.architecture_mode == ARCH_X86_MODE_64:
        mod_const = tb.immediate(64, oprnd2.size)
    else:
        raise Exception('Invalid architecture mode.')

    size = tb.immediate(self._arch_info.operand_size, oprnd2.size)
    end_addr = ReilImmediateOperand((instruction.address + instruction.size) << 8, self._arch_info.address_size + 8)
    count = tb.temporal(oprnd2.size)
    count_zero = tb.temporal(1)
    count_ext = tb.temporal(oprnd2.size * 2)
    size_ext = tb.temporal(oprnd2.size * 2)
    count_check = tb.temporal(oprnd2.size * 2)
    count_check_sign = tb.temporal(1)
    dst = tb.temporal(oprnd0.size)

    bad_parameters_lbl = ReilLabel('bad_parameters_lbl')
    shift_lbl = ReilLabel('shift_lbl')

    tb.add(self._builder.gen_mod(oprnd2, mod_const, count))
    tb.add(self._builder.gen_bisz(count, count_zero))
    tb.add(self._builder.gen_jcc(count_zero, end_addr))

    tb.add(self._builder.gen_str(count, count_ext))
    tb.add(self._builder.gen_str(size, size_ext))
    tb.add(self._builder.gen_sub(size_ext, count_ext, count_check))  # count_check = size_ext - count_ext

    # count_check_sign == 1 => count > size
    tb.add(self._builder.gen_bsh(count_check, tb.immediate(-count.size, count_check.size), count_check_sign))

    tb.add(self._builder.gen_jcc(count_check_sign, bad_parameters_lbl))
    tb.add(self._builder.gen_jcc(tb.immediate(1, 1), shift_lbl))

    tb.add(bad_parameters_lbl)
    # dst <- undefined
    tb.add(self._builder.gen_str(oprnd0, dst))
    # Set flags: CF, OF, SF, ZF, AF, PF are undefined;
    self._flag_translator.undefine_flag(tb, self._flags.cf)
    self._flag_translator.undefine_flag(tb, self._flags.of)
    self._flag_translator.undefine_flag(tb, self._flags.sf)
    self._flag_translator.undefine_flag(tb, self._flags.zf)
    self._flag_translator.undefine_flag(tb, self._flags.af)
    self._flag_translator.undefine_flag(tb, self._flags.pf)
    tb.add(self._builder.gen_jcc(tb.immediate(1, 1), end_addr))

    tb.add(shift_lbl)
    # (* Perform the shift *)
    # CF <- BIT[DEST, COUNT - 1]; (* Last bit shifted out on exit *)
    # FOR i <- 0 TO SIZE - 1 - COUNT
    #     DO
    #         BIT[DEST, i] <- BIT[DEST, i + COUNT];
    #     OD;
    # FOR i <- SIZE - COUNT TO SIZE - 1
    #     DO
    #         BIT[DEST,i] <- BIT[SRC, i + COUNT - SIZE];
    #     OD;

    zero = tb.immediate(0, count.size)
    one = tb.immediate(1, count.size)
    bit_offset = tb.temporal(oprnd0.size)
    bit_offset_tmp = tb.temporal(oprnd0.size)
    tmp0 = tb.temporal(1)
    lower = tb.temporal(oprnd0.size * 2)
    upper = tb.temporal(oprnd0.size * 2)
    dst_tmp0 = tb.temporal(oprnd0.size * 2)
    dst_tmp1 = tb.temporal(oprnd0.size * 2)
    dst_count = tb.temporal(oprnd0.size * 2)
    dst_count0 = tb.temporal(oprnd0.size * 2)

    # Compute bit offset.
    tb.add(self._builder.gen_sub(count, one, bit_offset_tmp))
    tb.add(self._builder.gen_sub(zero, bit_offset_tmp, bit_offset))  # negate

    # Extract bit.
    tb.add(self._builder.gen_bsh(oprnd0, bit_offset, tmp0))

    # Set CF.
    tb.add(self._builder.gen_and(tmp0, tb.immediate(1, 1), self._flags.cf))

    tb.add(self._builder.gen_str(oprnd0, lower))
    tb.add(self._builder.gen_bsh(oprnd1, tb.immediate(oprnd1.size, oprnd1.size), upper))
    tb.add(self._builder.gen_or(upper, lower, dst_tmp0))
    tb.add(self._builder.gen_str(count, dst_count0))
    tb.add(self._builder.gen_sub(tb.immediate(0, dst_count0.size), dst_count0, dst_count))
    tb.add(self._builder.gen_bsh(dst_tmp0, dst_count, dst_tmp1))
    tb.add(self._builder.gen_str(dst_tmp1, dst))

    # Flags : SF, ZF, PF
    self._flag_translator.update_sf(tb, oprnd0, dst)
    self._flag_translator.update_zf(tb, oprnd0, dst)
    self._flag_translator.update_pf(tb, dst)

    self._reg_acc_translator.write(tb, instruction.operands[0], dst)
示例#10
0
def _translate_bsf(self, tb, instruction):
    # Flags Affected
    # The ZF flag is set to 1 if all the source operand is 0;
    # otherwise, the ZF flag is cleared. The CF, OF, SF, AF, and PF,
    # flags are undefined.

    # Operation
    # IF SRC = 0
    #     THEN
    #         ZF <- 1;
    #         DEST is undefined;
    #     ELSE
    #         ZF <- 0;
    #         temp <- 0;
    #         WHILE Bit(SRC, temp) = 0
    #         DO
    #             temp <- temp + 1;
    #         OD;
    #         DEST <- temp;
    # FI;

    oprnd0 = self._reg_acc_translator.read(tb, instruction.operands[0])
    oprnd1 = self._reg_acc_translator.read(tb, instruction.operands[1])

    zf = self._flags.zf
    tmp = tb.temporal(oprnd1.size)
    tmp1 = tb.temporal(oprnd1.size)
    bit_curr = tb.temporal(1)
    dst = tb.temporal(oprnd0.size)
    src_is_zero = tb.temporal(1)
    bit_zero = tb.temporal(1)

    src_is_zero_lbl = ReilLabel('src_is_zero_lbl')
    loop_lbl = ReilLabel('loop_lbl')
    end_lbl = ReilLabel('end_lbl')

    tb.add(self._builder.gen_bisz(oprnd1, src_is_zero))
    tb.add(self._builder.gen_jcc(src_is_zero, src_is_zero_lbl))

    # if src != 0 ...
    tb.add(self._builder.gen_str(tb.immediate(0, 1), zf))
    tb.add(self._builder.gen_str(tb.immediate(1, tmp.size), tmp))
    tb.add(self._builder.gen_str(tb.immediate(-1, tmp1.size), tmp1))

    # while bit(src, tmp) == 0 ...
    tb.add(loop_lbl)
    tb.add(self._builder.gen_sub(tmp, tb.immediate(1, tmp.size), tmp))
    tb.add(self._builder.gen_add(tmp1, tb.immediate(1, tmp.size), tmp1))

    tb.add(self._builder.gen_bsh(oprnd1, tmp, bit_curr))
    tb.add(self._builder.gen_bisz(bit_curr, bit_zero))
    tb.add(self._builder.gen_jcc(bit_zero, loop_lbl))

    # Save result.
    tb.add(self._builder.gen_str(tmp1, dst))

    # jump to the end.
    tb.add(self._builder.gen_jcc(tb.immediate(1, 1), end_lbl))

    # If src == 0 ...
    tb.add(src_is_zero_lbl)
    tb.add(self._builder.gen_str(tb.immediate(1, 1), zf))
    # Undefine dst (set the same value).
    tb.add(self._builder.gen_str(oprnd0, dst))

    tb.add(end_lbl)

    # Set flags.
    # Flags : CF, OF, SF, AF, and PF
    self._flag_translator.undefine_flag(tb, self._flags.cf)
    self._flag_translator.undefine_flag(tb, self._flags.of)
    self._flag_translator.undefine_flag(tb, self._flags.sf)
    self._flag_translator.undefine_flag(tb, self._flags.af)
    self._flag_translator.undefine_flag(tb, self._flags.pf)

    self._reg_acc_translator.write(tb, instruction.operands[0], dst)