def value(self): """ Retrieve the value of the operand as it is currently in the cpu_context. NOTE: We can't cache this value because the value may change based on the cpu context. :return int: An integer of the operand value. """ if self.is_hidden: return None if self.is_immediate: value = idc.get_operand_value(self.ip, self.idx) # Create variable/reference if global. if idc.is_loaded(value): self._cpu_context.variables.add(value, reference=self.ip) return value if self.is_register: value = self._cpu_context.registers[self.text] # Record reference if register is a variable address. if value in self._cpu_context.variables: self._cpu_context.variables[value].add_reference(self.ip) return value # 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: return self._cpu_context.registers.fs elif "gs" in self.text: return self._cpu_context.registers.gs # If a memory reference, return read in memory. if self.is_memory_reference: addr = self.addr # Record referenc if address is a variable address. if addr in self._cpu_context.variables: self._cpu_context.variables[addr].add_reference(self.ip) # If a function pointer, we want to return the address. # This is because a function may be seen as a memory reference, but we don't # want to dereference it in case it in a non-call instruction. # (e.g. "mov esi, ds:LoadLibraryA") # NOTE: Must use internal function to avoid recursive loop. if utils.is_func_ptr(addr): return addr # Return empty if not self.width: logger.debug("Width is zero for {}, returning empty string.".format(self.text)) return b"" # Otherwise, dereference the address. value = self._cpu_context.mem_read(addr, self.width) return utils.struct_unpack(value) raise FunctionTracingError("Invalid operand type: {}".format(self.type), ip=self.ip)
def is_func_ptr(self): return utils.is_func_ptr(self.addr)
def is_func_ptr(self): """True if the operand is a pointer to a function.""" return utils.is_func_ptr(self.addr or self.value)