예제 #1
0
    def _calc_displacement(self):
        """
        Calculate the displacement offset of the operand's text.

        e.g:
            word ptr [rdi+rbx]

        :return int: calculated value
        """
        size = 8 if idc.__EA64__ else 4
        insn = idaapi.insn_t()
        idaapi.decode_insn(insn, self.ip)
        op = insn.ops[self.idx]
        offset = utils.signed(op.addr, utils.get_bits())
        scale = utils.sib_scale(op)
        base_reg = utils.x86_base_reg(insn, op)
        indx_reg = utils.x86_index_reg(insn, op)
        base_val = self._cpu_context.registers[utils.reg2str(base_reg, size)]
        indx_val = self._cpu_context.registers[utils.reg2str(
            indx_reg, size)] if indx_reg != -1 else 0
        result = base_val + indx_val * scale + offset
        logger.debug("calc_displacement :: Displacement {} -> {}".format(
            self.text, result))

        # Before returning, record the frame_id and stack_offset for this address.
        # (This can become useful information for retrieving the original location of a variable)
        frame_id = idc.get_frame_id(self.ip)
        stack_var = ida_frame.get_stkvar(insn, op, offset)
        if stack_var:
            _, stack_offset = stack_var
            self._cpu_context.stack_variables[result] = (frame_id,
                                                         stack_offset)

        return result
예제 #2
0
 def base(self):
     """The value of the base register if operand is a displacement."""
     if not self.has_phrase:
         return None
     base_reg = utils.reg2str(utils.x86_base_reg(self._insn, self._op))
     value = self._cpu_context.registers[base_reg]
     return utils.signed(value, utils.get_bits())
 def register_list(self) -> Optional[List[str]]:
     """
     List of register names if operand is a register list.
     """
     if not self.is_register_list:
         return None
     # Register numbers are stored in a bitmap in specval.
     reg_bitmap = self._op.specval
     return [utils.reg2str(i) for i in range(16) if reg_bitmap & (1 << i)]
예제 #4
0
 def index(self):
     """The value of the index register if operand is a displacement."""
     if not self.has_phrase:
         return None
     index_reg = utils.x86_index_reg(self._insn, self._op)
     if index_reg == -1:
         return 0
     index_reg = utils.reg2str(index_reg)
     value = self._cpu_context.registers[index_reg]
     return utils.signed(value, utils.get_bits())
예제 #5
0
    def base(self) -> Optional[int]:
        """
        The value of the base register if operand is a displacement.

        e.g.
            [ebp+ecx*2+var_8] -> ebp
        """
        if not self.has_phrase:
            return None
        base_reg = ida_intel.x86_base_reg(self._insn, self._op)
        value = self._cpu_context.registers[utils.reg2str(base_reg)]
        return utils.signed(value)
예제 #6
0
    def index(self) -> Optional[int]:
        """
        The value of the index register if operand is a displacement.

        e.g.
            [ebp+ecx*2+var_8] -> ecx
        """
        if not self.has_phrase:
            return None
        index_reg = ida_intel.x86_index_reg(self._insn, self._op)
        if index_reg == -1:
            return 0
        index_reg = utils.reg2str(index_reg)
        value = self._cpu_context.registers[index_reg]
        return utils.signed(value)
    def shift_count(self) -> int:
        """The amount to shift (if a shifted register)"""
        if self.type == ida_ua.o_phrase:
            # For a phrase, shift is in op.value
            return self._op.value

        if self.type == ida_arm.o_shreg:
            # Shift can be an immediate or another register.
            # I believe we determine which one it is based on whether op.value is zero.
            count = self._op.value
            if not count:
                count = self._cpu_context.registers[utils.reg2str(
                    ida_arm.secreg(self._op))]
            return count

        return 0  # not shifted
    def offset(self) -> Optional[int]:
        """The offset value if the operand is a displacement/phrase."""
        # [R1, R2]
        if self.type == ida_ua.o_phrase:
            second_reg = ida_arm.secreg(self._op)  # pulling the R2
            offset = self._cpu_context.registers[utils.reg2str(second_reg)]
            # We could also have a shift applied in the offset.
            #   [R1, R2, LSL #3]
            offset = self._calc_shift(offset)
            return utils.signed(offset)

        # [R1, #1]
        elif self.type == ida_ua.o_displ:
            return utils.signed(self._op.addr)

        return None
    def value(self):
        # Barrel shifter
        if self.type == ida_arm.o_shreg:
            value = self._cpu_context.registers[utils.reg2str(self._op.reg)]
            value = self._calc_shift(value)
            return value

        # Register list
        if self.type == ida_arm.o_reglist:
            return [
                self._cpu_context.registers[reg] for reg in self.register_list
            ]

        value = super().value

        # If a memory reference, the final value may be signed.
        if self.is_memory_reference and self.is_signed:
            value = utils.signed(value)

        return value
 def base(self, value: int):
     """Sets the value of the base register if operand is a displacement."""
     if not self.has_phrase:
         return
     self._cpu_context.registers[utils.reg2str(self._op.reg)] = value
 def base(self) -> Optional[int]:
     """The value of the base register if operand is a displacement."""
     if not self.has_phrase:
         return None
     value = self._cpu_context.registers[utils.reg2str(self._op.reg)]
     return utils.signed(value)