Exemplo n.º 1
0
    def value(self, value):
        """Set the data the variable is pointing to."""
        data_type = self.data_type

        if data_type in ("char", "tbyte"):
            self.data = value

        elif data_type in ("byte", "word", "dword", "qword", "oword"):
            width = self.data_type_size
            if isinstance(value, list):
                self.data = b''.join(
                    utils.struct_pack(_value, width=width) for _value in value)
            else:
                self.data = utils.struct_pack(value, width=width)

        elif data_type in ("float", "double"):
            width = self.data_type_size
            if isinstance(value, list):
                self.data = b''.join(
                    utils.struct_pack(utils.float_to_int(_value), width=width)
                    for _value in value)
            else:
                self.data = utils.struct_pack(utils.float_to_int(value),
                                              width=width)

        else:
            raise NotImplementedError(f"Unsupported data type: {data_type}")
Exemplo n.º 2
0
    def write_data(self, addr, value, data_type=None):
        """
        Writes memory at the specified address after converting the value
        into data based on the specified data type.

        :param int addr: address to write data to
        :param value: integer or byte string to write
        :param data_type: type of data to convert value from.
            (defaults to BYTE_STRING, STRING, or DWORD based on input data)
        """
        if not data_type:
            if isinstance(value, str):
                data_type = STRING
            elif isinstance(value, bytes):
                data_type = BYTE_STRING
            elif isinstance(value, int):
                data_type = DWORD
            else:
                raise ValueError(f"Invalid data type: {type(value)}")

        if data_type == BYTE_STRING:
            data = value

        elif data_type == STRING:
            data = value
            if isinstance(data, str):
                data = data.encode("utf8")
            data += b"\0"

        elif data_type == WIDE_STRING:
            data = value
            if isinstance(data, str):
                data = data.encode("utf-16-le")
            data += b"\0\0"

        elif data_type == BYTE:
            data = bytes([value])

        elif data_type == WORD:
            data = utils.struct_pack(value, width=2)

        elif data_type == DWORD:
            data = utils.struct_pack(value, width=4)

        elif data_type == QWORD:
            data = utils.struct_pack(value, width=8)

        else:
            raise ValueError(f"Invalid data_type: {repr(data_type)}")

        self.mem_write(addr, data)
Exemplo n.º 3
0
    def value(self, value):
        """
        Set the operand to the specified value within the cpu_context.
        """
        # Value may be signed.
        if isinstance(value, int) and value < 0:
            value = utils.unsigned(value, bit_width=self.width * 8)

        # If we are writing to an immediate, I believe they want to write to the memory at the immediate.
        # TODO: Should we fail instead?
        if self.is_immediate:
            offset = self.value
            if idaapi.is_loaded(offset):
                self._cpu_context.mem_write(offset, value)
            return

        if self.is_register:
            # Convert the value from string to integer...
            if isinstance(value, str):
                value = utils.struct_unpack(value)
            self._cpu_context.registers[self.text] = value
            return

        if self.is_memory_reference:
            # FIXME: Usage of numpy is most likely symptomatic of a bug in an opcode
            #   implementation passing in bad data.
            #   Update this to just is "isinstance" and then fix the buggy opcode.
            # For data written to the frame or memory, this data MUST be a byte string.
            if numpy.issubdtype(type(value), numpy.integer):
                value = utils.struct_pack(value, width=self.width)
            self._cpu_context.mem_write(self.addr, value)
            return

        raise FunctionTracingError(f"Invalid operand type: {self.type}",
                                   ip=self.ip)
Exemplo n.º 4
0
    def value(self, value):
        """
        Set the operand to the specified value within the cpu_context.
        """
        # If we are writing to an immediate, I believe they want to write to the memory at the immediate.
        # TODO: Should we fail instead?
        if self.is_immediate:
            offset = self.value
            if idaapi.is_loaded(offset):
                self._cpu_context.mem_write(offset, value)
            return

        if self.is_register:
            # Convert the value from string to integer...
            if isinstance(value, str):
                value = utils.struct_unpack(value)

            # On 64-bit, the destination register must be set to 0 first (per documentation)
            # TODO: Check if this happens regardless of the source size
            if idc.__EA64__ and self.width == 4:  # Only do this for 32-bit setting
                reg64 = utils.convert_reg(self.text, 8)
                self._cpu_context.registers[reg64] = 0

            self._cpu_context.registers[self.text] = value
            return

        # TODO: Determine if this is still necessary.
        # FS, GS (at least) registers are identified as memory addresses.  We need to identify them as registers
        # and handle them as such
        if self.type == idc.o_mem:
            if "fs" in self.text:
                self._cpu_context.registers.fs = value
                return
            elif "gs" in self.text:
                self._cpu_context.registers.gs = value
                return

        if self.is_memory_reference:
            # For data written to the frame or memory, this data MUST be a byte string.
            if numpy.issubdtype(type(value), numpy.integer):
                value = utils.struct_pack(value, width=self.width)
            self._cpu_context.mem_write(self.addr, value)
            return

        raise FunctionTracingError('Invalid operand type: {}'.format(
            self.type),
                                   ip=self.ip)