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}")
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)
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)
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)