def changed_bytes(self, other: 'ListPage', page_addr: int = None): candidates = super().changed_bytes(other) if candidates is None: candidates: Set[int] = set() if self.sinkhole is None: candidates |= self.stored_offset else: for i in range(len(self.content)): if self._contains(i, page_addr): candidates.add(i) if other.sinkhole is None: candidates |= other.stored_offset else: for i in range(len(other.content)): if other._contains(i, page_addr): candidates.add(i) byte_width = 8 # TODO: Introduce self.state if we want to use self.state.arch.byte_width differences: Set[int] = set() for c in candidates: s_contains = self._contains(c, page_addr) o_contains = other._contains(c, page_addr) if not s_contains and o_contains: differences.add(c) elif s_contains and not o_contains: differences.add(c) else: if self.content[c] is None: self.content[c] = SimMemoryObject(self.sinkhole.bytes_at( page_addr + c, 1), page_addr + c, byte_width=byte_width, endness='Iend_BE') if other.content[c] is None: other.content[c] = SimMemoryObject(other.sinkhole.bytes_at( page_addr + c, 1), page_addr + c, byte_width=byte_width, endness='Iend_BE') if s_contains and self.content[c] != other.content[c]: same = None if self._mo_cmp is not None: same = self._mo_cmp(self.content[c], other.content[c], page_addr + c, 1) if same is None: # Try to see if the bytes are equal self_byte = self.content[c].bytes_at(page_addr + c, 1) other_byte = other.content[c].bytes_at( page_addr + c, 1) same = self_byte is other_byte if same is False: differences.add(c) else: # this means the byte is in neither memory pass return differences
def replace_memory_object(self, old, new_content): """ Replaces the memory object `old` with a new memory object containing `new_content`. :param old: A SimMemoryObject (i.e., one from :func:`memory_objects_for_hash()` or :func:` memory_objects_for_name()`). :param new_content: The content (claripy expression) for the new memory object. :returns: the new memory object """ if old.object.size() != new_content.size(): raise SimMemoryError( "memory objects can only be replaced by the same length content" ) new = SimMemoryObject(new_content, old.base, byte_width=self.byte_width) for p in self._containing_pages_mo(old): self._get_page(p / self._page_size, write=True).replace_mo(self.state, old, new) if isinstance(new.object, claripy.ast.BV): for b in range(old.base, old.base + old.length): self._update_mappings(b, new.object) return new
def _fill(self, result, addr, page_addr, endness, memory, **kwargs): """ Small utility function for behavior which is duplicated in load mutates result to generate a new memory object and replace the last entry in it, which is None. Then, it will insert the new memory object into self.content. """ global_end_addr = addr + page_addr global_start_addr = result[-1][0] size = global_end_addr - global_start_addr new_ast = self._default_value(global_start_addr, size, name='%s_%x' % (memory.id, global_start_addr), key=(self.category, global_start_addr), memory=memory, **kwargs) new_item = SimMemoryObject(new_ast, global_start_addr, endness=endness, byte_width=memory.state.arch.byte_width if memory is not None else 8) for subaddr in range(global_start_addr - page_addr, addr): self.content[subaddr] = new_item result[-1] = (global_start_addr, new_item)
def map_region(self, addr, length, permissions, init_zero=False): if o.TRACK_MEMORY_MAPPING not in self.state.options: return if self.state.se.symbolic(addr): raise SimMemoryError("cannot map region with a symbolic address") if isinstance(addr, claripy.ast.bv.BV): addr = self.state.se.max_int(addr) base_page_num = addr / self._page_size # round length pages = length / self._page_size if length % self._page_size > 0: pages += 1 if isinstance(permissions, (int, long)): permissions = claripy.BVV(permissions, 3) for page in xrange(pages): page_id = base_page_num + page self._pages[page_id] = self._create_page(page_id, permissions=permissions) self._symbolic_addrs[page_id] = set() if init_zero: if self.state is not None: self.state.scratch.push_priv(True) mo = SimMemoryObject(claripy.BVV(0, self._page_size * self.byte_width), page_id*self._page_size, byte_width=self.byte_width) self._apply_object_to_page(page_id*self._page_size, mo, page=self._pages[page_id]) if self.state is not None: self.state.scratch.pop_priv()
def _fill_missing(self, addr, num_bytes, inspect=True, events=True): name = "%s_%x" % (self.id, addr) all_missing = [ self.get_unconstrained_bytes( name, min(self.mem._page_size, num_bytes)*self.state.arch.byte_width, source=i, inspect=inspect, events=events, key=self.variable_key_prefix + (addr,), eternal=False) # :( for i in range(addr, addr+num_bytes, self.mem._page_size) ] if self.category == 'reg' and self.state.arch.register_endness == 'Iend_LE': all_missing = [ a.reversed for a in all_missing ] elif self.category != 'reg' and self.state.arch.memory_endness == 'Iend_LE': all_missing = [ a.reversed for a in all_missing ] b = self.state.se.Concat(*all_missing) if len(all_missing) > 1 else all_missing[0] if events: self.state.history.add_event('uninitialized', memory_id=self.id, addr=addr, size=num_bytes) default_mo = SimMemoryObject(b, addr, byte_width=self.state.arch.byte_width) self.state.scratch.push_priv(True) self.mem.store_memory_object(default_mo, overwrite=False) self.state.scratch.pop_priv() return default_mo
def load_slice(self, state, start, end): """ Return the memory objects overlapping with the provided slice. :param start: the start address :param end: the end address (non-inclusive) :returns: tuples of (starting_addr, memory_object) """ items = [] if start > self._page_addr + self._page_size or end < self._page_addr: l.warning("Calling load_slice on the wrong page.") return items for addr in range(max(start, self._page_addr), min(end, self._page_addr + self._page_size)): i = addr - self._page_addr mo = self._storage[i] if mo is None and hasattr(self, "from_ida_dbg"): byte_val = idc.Byte( addr) ### CHANGE TO SUPPORT OTHER DEBUGGERS mo = SimMemoryObject(claripy.BVV(byte_val, 8), addr) self._storage[i] = mo if mo is not None and (not items or items[-1][1] is not mo): items.append((addr, mo)) #print filter(lambda x: x != None, self._storage) return items
def changed_bytes(self, other: 'ListPage', page_addr: int = None): candidates: Set[int] = set() for i in range(len(self.content)): if self._contains(i, page_addr): candidates.add(i) for i in range(len(other.content)): if other._contains(i, page_addr): candidates.add(i) byte_width = 8 # TODO: Introduce self.state if we want to use self.state.arch.byte_width differences: Set[int] = set() for c in candidates: if not self._contains(c, page_addr) and other._contains( c, page_addr): differences.add(c) elif self._contains( c, page_addr) and not other._contains(c, page_addr): differences.add(c) else: if self.content[c] is None: self.content[c] = SimMemoryObject(self.sinkhole.bytes_at( page_addr + c, 1), page_addr + c, byte_width=byte_width, endness='Iend_BE') if other.content[c] is None: other.content[c] = SimMemoryObject(other.sinkhole.bytes_at( page_addr + c, 1), page_addr + c, byte_width=byte_width, endness='Iend_BE') if self._contains( c, page_addr) and self.content[c] != other.content[c]: # Try to see if the bytes are equal self_byte = self.content[c].bytes_at(page_addr + c, 1) other_byte = other.content[c].bytes_at(page_addr + c, 1) if self_byte is not other_byte: #l.debug("%s: offset %x, two different bytes %s %s from %s %s", self.id, c, # self_byte, other_byte, # self[c].object.model, other[c].object.model) differences.add(c) else: # this means the byte is in neither memory pass return differences
def load_mo(self, state, page_idx): """ Loads a memory object from memory. :param page_idx: the index into the page :returns: a tuple of the object """ mo = self._storage[page_idx - self._page_addr] #print filter(lambda x: x != None, self._storage) if mo is None and hasattr(self, "from_dbg"): byte_val = get_debugger().get_byte(page_idx) mo = SimMemoryObject(claripy.BVV(byte_val, 8), page_idx) self._storage[page_idx - self._page_addr] = mo return mo
def _decompose_objects(cls, addr, data, endness, memory=None, page_addr=0, label=None, **kwargs): # the generator model is definitely overengineered here but wouldn't be if we were working with raw BVs cur_addr = addr + page_addr if isinstance(data, MultiValues): # for MultiValues, we return sets of SimMemoryObjects assert label is None # TODO: Support labels _ = yield offset_to_mos: Dict[int,Set[SimMemoryObject]] = {} for offset, vs in data.values.items(): offset_to_mos[offset] = set() for v in vs: offset_to_mos[offset].add(SimMemoryObject( v, cur_addr + offset, endness, byte_width=memory.state.arch.byte_width if memory is not None else 0) ) sorted_offsets = list(sorted(offset_to_mos.keys())) pos = 0 while pos < len(sorted_offsets): mos = set(offset_to_mos[sorted_offsets[pos]]) size = next(iter(mos)).length cur_addr += size yield mos, size if sorted_offsets[pos] < cur_addr - addr - page_addr: pos += 1 else: if label is None: obj = SimMemoryObject(data, cur_addr, endness, byte_width=memory.state.arch.byte_width if memory is not None else 8) else: obj = SimLabeledMemoryObject(data, cur_addr, endness, byte_width=memory.state.arch.byte_width if memory is not None else 8, label=label) _ = yield while True: _ = yield { obj }, obj.length
def _decompose_objects(cls, addr, data, endness, memory=None, page_addr=0, label=None, **kwargs): # the generator model is definitely overengineered here but wouldn't be if we were working with raw BVs cur_addr = addr + page_addr if label is None: memory_object = SimMemoryObject(data, cur_addr, endness, byte_width=memory.state.arch.byte_width if memory is not None else 8) else: memory_object = SimLabeledMemoryObject(data, cur_addr, endness, byte_width=memory.state.arch.byte_width if memory is not None else 8, label=label) size = yield while True: cur_addr += size size = yield memory_object, memory_object.length
def load_mo(self, state, page_idx): """ Loads a memory object from memory. :param page_idx: the index into the page :returns: a tuple of the object """ mo = self._storage[page_idx - self._page_addr] #print filter(lambda x: x != None, self._storage) if mo is None and hasattr(self, "from_ida_dbg"): byte_val = idc.Byte( page_idx) ### CHANGE TO SUPPORT OTHER DEBUGGERS mo = SimMemoryObject(claripy.BVV(byte_val, 8), page_idx) self._storage[page_idx - self._page_addr] = mo return mo
def _decompose_objects(cls, addr, data, endness, memory=None, page_addr=0, **kwargs): # the generator model is definitely overengineered here but wouldn't be if we were working with raw BVs memory_object = SimMemoryObject(data, addr + page_addr, endness, byte_width=memory.state.arch.byte_width if memory is not None else 8) size = yield while True: size = yield memory_object
def map_region(self, addr, length, permissions, init_zero=False): if o.TRACK_MEMORY_MAPPING not in self.state.options: return if self.state.solver.symbolic(addr): raise SimMemoryError("cannot map region with a symbolic address") if isinstance(addr, claripy.ast.bv.BV): addr = self.state.solver.max_int(addr) base_page_num = addr // self._page_size # round length pages = length // self._page_size if length % self._page_size > 0: pages += 1 # this check should not be performed when constructing a CFG if self.state.mode != 'fastpath': for page in range(pages): page_id = base_page_num + page if page_id * self._page_size in self: err = "map_page received address and length combination which contained mapped page" l.warning(err) raise SimMemoryError(err) if isinstance(permissions, int): permissions = claripy.BVV(permissions, 3) for page in range(pages): page_id = base_page_num + page self._pages[page_id] = self._create_page(page_id, permissions=permissions) self._symbolic_addrs[page_id] = set() if init_zero: if self.state is not None: self.state.scratch.push_priv(True) mo = SimMemoryObject(claripy.BVV( 0, self._page_size * self.byte_width), page_id * self._page_size, byte_width=self.byte_width) self._apply_object_to_page(page_id * self._page_size, mo, page=self._pages[page_id]) if self.state is not None: self.state.scratch.pop_priv()
def _read_memory(self, offset, bytes_read, state, start, end): # MemoryForwardMsg = RemoteMemoryReadMessage(self.origin, self.id, # 0x0, # Fake PC # start, # end - start) # self.avatar.queue.put(MemoryForwardMsg) # # r_id, r_value, r_success = self.origin.response_queue.get() # # if self.id != r_id: # raise("AvatarAngrMemory received mismatching id!") # if r_success != True: # raise Exception("AvatarAngrMemory remote memory request failed!") # # self.id += 1 # # int.from_bytes(bytes_read[start, start + end], byteorder='big') r_value = struct.unpack("<L", bytes_read[start-offset:end-offset])[0] # do your stuff return [(start, SimMemoryObject(BVV(r_value, (end-start)*8), start))]
def merge(self, others: List['ListPage'], merge_conditions, common_ancestor=None, page_addr: int = None, memory=None): changed_offsets = set() for other in others: changed_offsets |= self.changed_bytes(other, page_addr) all_pages: List['ListPage'] = [self] + others if merge_conditions is None: merge_conditions = [None] * len(all_pages) merged_to = None merged_objects = set() merged_offsets = set() for b in sorted(changed_offsets): if merged_to is not None and not b >= merged_to: l.info("merged_to = %d ... already merged byte 0x%x", merged_to, b) continue l.debug("... on byte 0x%x", b) memory_objects = [] unconstrained_in = [] # first get a list of all memory objects at that location, and # all memories that don't have those bytes for sm, fv in zip(all_pages, merge_conditions): if sm._contains(b, page_addr): l.info("... present in %s", fv) memory_objects.append((sm.content[b], fv)) else: l.info("... not present in %s", fv) unconstrained_in.append((sm, fv)) mos = set(mo for mo, _ in memory_objects) mo_bases = set(mo.base for mo, _ in memory_objects) mo_lengths = set(mo.length for mo, _ in memory_objects) if not unconstrained_in and not (mos - merged_objects): continue # first, optimize the case where we are dealing with the same-sized memory objects if len(mo_bases) == 1 and len( mo_lengths) == 1 and not unconstrained_in: our_mo = self.content[b] to_merge = [(mo.object, fv) for mo, fv in memory_objects] # Update `merged_to` mo_base = list(mo_bases)[0] mo_length = memory_objects[0][0].length size = mo_length - (page_addr + b - mo_base) merged_to = b + size merged_val = self._merge_values(to_merge, mo_length, memory=memory) if merged_val is None: # merge_values() determines that we should not attempt to merge this value continue # do the replacement # TODO: Implement in-place replacement instead of calling store() # new_object = self._replace_memory_object(our_mo, merged_val, page_addr, memory.page_size) self.store(b, SimMemoryObject(merged_val, mo_base, endness='Iend_BE'), size=size, cooperate=True) # merged_objects.add(new_object) # merged_objects.update(mos) merged_offsets.add(b) else: # get the size that we can merge easily. This is the minimum of # the size of all memory objects and unallocated spaces. min_size = min([ mo.length - (b + page_addr - mo.base) for mo, _ in memory_objects ]) for um, _ in unconstrained_in: for i in range(0, min_size): if um._contains(b + i, page_addr): min_size = i break merged_to = b + min_size l.info("... determined minimum size of %d", min_size) # Now, we have the minimum size. We'll extract/create expressions of that # size and merge them extracted = [(mo.bytes_at(page_addr + b, min_size), fv) for mo, fv in memory_objects ] if min_size != 0 else [] created = [ (self._default_value(None, min_size, name="merge_uc_%s_%x" % (uc.id, b), memory=memory), fv) for uc, fv in unconstrained_in ] to_merge = extracted + created merged_val = self._merge_values(to_merge, min_size, memory=memory) if merged_val is None: continue self.store(b, SimMemoryObject(merged_val, page_addr + b, endness='Iend_BE'), size=min_size, endness='Iend_BE', cooperate=True) # do not convert endianness again merged_offsets.add(b) return merged_offsets
def _insert_memory_object(self, value, address, size): value.make_uuid() if self.category == 'mem': self.state.scratch.dirty_addrs.update(range(address, address+size)) mo = SimMemoryObject(value, address, length=size, byte_width=self.state.arch.byte_width) self.mem.store_memory_object(mo)
def __changed_bytes(self, other): """ Gets the set of changed bytes between `self` and `other`. :type other: SimPagedMemory :returns: A set of differing bytes. """ if self._page_size != other._page_size: raise SimMemoryError( "SimPagedMemory page sizes differ. This is asking for disaster." ) our_pages = set(self._pages.keys()) their_pages = set(other._pages.keys()) their_additions = their_pages - our_pages our_additions = our_pages - their_pages common_pages = our_pages & their_pages candidates = set() for p in their_additions: candidates.update(other._pages[p].keys()) for p in our_additions: candidates.update(self._pages[p].keys()) for p in common_pages: our_page = self._pages[p] their_page = other._pages[p] if our_page is their_page: continue our_keys = set(our_page.keys()) their_keys = set(their_page.keys()) changes = (our_keys - their_keys) | (their_keys - our_keys) | { i for i in (our_keys & their_keys) if our_page.load_mo( self.state, i) is not their_page.load_mo(self.state, i) } candidates.update(changes) #both_changed = our_changes & their_changes #ours_changed_only = our_changes - both_changed #theirs_changed_only = their_changes - both_changed #both_deleted = their_deletions & our_deletions #ours_deleted_only = our_deletions - both_deleted #theirs_deleted_only = their_deletions - both_deleted differences = set() for c in candidates: if c not in self and c in other: differences.add(c) elif c in self and c not in other: differences.add(c) else: if type(self[c]) is not SimMemoryObject: self[c] = SimMemoryObject(self.state.se.BVV( ord(self[c]), self.byte_width), c, byte_width=self.byte_width) if type(other[c]) is not SimMemoryObject: other[c] = SimMemoryObject(self.state.se.BVV( ord(other[c]), self.byte_width), c, byte_width=self.byte_width) if c in self and self[c] != other[c]: # Try to see if the bytes are equal self_byte = self[c].bytes_at(c, 1) other_byte = other[c].bytes_at(c, 1) if self_byte is not other_byte: #l.debug("%s: offset %x, two different bytes %s %s from %s %s", self.id, c, # self_byte, other_byte, # self[c].object.model, other[c].object.model) differences.add(c) else: # this means the byte is in neither memory pass return differences
def _initialize_page(self, n, new_page): if n in self._initialized: return False self._initialized.add(n) new_page_addr = n * self._page_size initialized = False if self.state is not None: self.state.scratch.push_priv(True) if self._memory_backer is None: pass project = load_project() #print "LOADING 0x%x" % new_page_addr if get_memory_type() == TEXT_SIMPROCS_FROM_LOADER or ( get_memory_type() == ONLY_SIMPROCS_FROM_LOADER and idc.SegName(new_page_addr) == project.arch.got_section_name): #yes this is weird if isinstance(self._memory_backer, cle.Clemory): # first, find the right clemory backer for addr, backer in self._memory_backer.cbackers if self.byte_width == 8 else ( (x, y) for x, _, y in self._memory_backer.stride_repr): start_backer = new_page_addr - addr if isinstance(start_backer, BV): continue if start_backer < 0 and abs( start_backer) >= self._page_size: continue if start_backer >= len(backer): continue # find permission backer associated with the address # fall back to read-write if we can't find any... flags = IdaPage.PROT_READ | IdaPage.PROT_WRITE for start, end in self._permission_map: if start <= new_page_addr < end: flags = self._permission_map[(start, end)] break snip_start = max(0, start_backer) write_start = max(new_page_addr, addr + snip_start) write_size = self._page_size - write_start % self._page_size if self.byte_width == 8: snip = _ffi.buffer(backer)[snip_start:snip_start + write_size] mo = SimMemoryObject(claripy.BVV(snip), write_start, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) else: for i, byte in enumerate(backer): mo = SimMemoryObject(claripy.BVV( byte, self.byte_width), write_start + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) new_page.permissions = claripy.BVV(flags, 3) initialized = True elif len(self._memory_backer) <= self._page_size: for i in self._memory_backer: if new_page_addr <= i and i <= new_page_addr + self._page_size: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True elif len(self._memory_backer) > self._page_size: for i in range(self._page_size): try: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, new_page_addr + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True except KeyError: pass # page from debugger try: seg = idaapi.getseg( new_page_addr) ### CHANGE TO SUPPORT OTHER DEBUGGERS if seg is not None: perms = 0 if seg.perm & idaapi.SEGPERM_EXEC: perms += IdaPage.PROT_EXEC if seg.perm & idaapi.SEGPERM_WRITE: perms += IdaPage.PROT_WRITE if seg.perm & idaapi.SEGPERM_READ: perms += IdaPage.PROT_READ new_page.permissions = claripy.BVV(perms, 3) #print "permissions setted %x %d" % (new_page_addr, perms) initialized = True setattr(new_page, "from_ida_dbg", True) except Exception as ee: import traceback traceback.print_exc() if self.state is not None: self.state.scratch.pop_priv() return initialized
def _initialize_page(self, n, new_page): if n in self._initialized: return False self._initialized.add(n) new_page_addr = n * self._page_size initialized = False if self.state is not None: self.state.scratch.push_priv(True) # if self._memory_backer is None: # pass project = load_project() debugger = get_debugger() # TODO handle simbolic address properly seg = None try: seg = debugger.seg_by_addr(new_page_addr) except BaseException: pass #print "LOADING 0x%x - 0x%x | 0x%x - 0x%x" % (new_page_addr, new_page_addr+self._page_size, seg.start, seg.end) if get_memory_type() == USE_CLE_MEMORY: # yes this is weird if isinstance(self._memory_backer, cle.Clemory): # first, find the right clemory backer for addr, backer in self._memory_backer.cbackers if self.byte_width == 8 else ( (x, y) for x, _, y in self._memory_backer.stride_repr): start_backer = new_page_addr - addr if isinstance(start_backer, BV): continue if start_backer < 0 and abs( start_backer) >= self._page_size: continue if start_backer >= len(backer): continue # find permission backer associated with the address # fall back to read-write if we can't find any... flags = DbgPage.PROT_READ | DbgPage.PROT_WRITE for start, end in self._permission_map: if start <= new_page_addr < end: flags = self._permission_map[(start, end)] break snip_start = max(0, start_backer) write_start = max(new_page_addr, addr + snip_start) write_size = self._page_size - write_start % self._page_size if self.byte_width == 8: snip = _ffi.buffer(backer)[snip_start:snip_start + write_size] mo = SimMemoryObject(claripy.BVV(snip), write_start, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) else: for i, byte in enumerate(backer): mo = SimMemoryObject(claripy.BVV( byte, self.byte_width), write_start + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) new_page.permissions = claripy.BVV(flags, 3) initialized = True elif len(self._memory_backer) <= self._page_size: for i in self._memory_backer: if new_page_addr <= i and i <= new_page_addr + self._page_size: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True elif len(self._memory_backer) > self._page_size: for i in range(self._page_size): try: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, new_page_addr + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True except KeyError: pass # page from debugger try: if seg is not None: perms = 0 if seg.perms & SEG_PROT_X: perms += DbgPage.PROT_EXEC if seg.perms & SEG_PROT_W: perms += DbgPage.PROT_WRITE if seg.perms & SEG_PROT_R: perms += DbgPage.PROT_READ new_page.permissions = claripy.BVV(perms, 3) #print "permissions setted %x %d" % (new_page_addr, perms) initialized = True setattr(new_page, "from_dbg", True) except Exception as ee: import traceback traceback.print_exc() if self.state is not None: self.state.scratch.pop_priv() return initialized
def _initialize_page(self, n, new_page): if n in self._initialized: return False self._initialized.add(n) new_page_addr = n * self._page_size initialized = False if self.state is not None: self.state.scratch.push_priv(True) return True if self._memory_backer is None: pass elif isinstance(self._memory_backer, cle.Clemory): # first, find the right clemory backer for addr, backer in self._memory_backer.cbackers if self.byte_width == 8 else ( (x, y) for x, _, y in self._memory_backer.stride_repr): start_backer = new_page_addr - addr if isinstance(start_backer, BV): continue if start_backer < 0 and abs(start_backer) >= self._page_size: continue if start_backer >= len(backer): continue # find permission backer associated with the address # fall back to read-write if we can't find any... flags = IdaPage.PROT_READ | IdaPage.PROT_WRITE for start, end in self._permission_map: if start <= new_page_addr < end: flags = self._permission_map[(start, end)] break snip_start = max(0, start_backer) write_start = max(new_page_addr, addr + snip_start) write_size = self._page_size - write_start % self._page_size if self.byte_width == 8: snip = _ffi.buffer(backer)[snip_start:snip_start + write_size] mo = SimMemoryObject(claripy.BVV(snip), write_start, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) else: for i, byte in enumerate(backer): mo = SimMemoryObject(claripy.BVV( byte, self.byte_width), write_start + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) new_page.permissions = claripy.BVV(flags, 3) initialized = True elif len(self._memory_backer) <= self._page_size: for i in self._memory_backer: if new_page_addr <= i and i <= new_page_addr + self._page_size: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True elif len(self._memory_backer) > self._page_size: for i in range(self._page_size): try: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, new_page_addr + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True except KeyError: pass if self.state is not None: self.state.scratch.pop_priv() return initialized
def _initialize_page(self, n, new_page): if n in self._initialized: return False self._initialized.add(n) new_page_addr = n * self._page_size initialized = False if self.state is not None: self.state.scratch.push_priv(True) # if self._memory_backer is None: # pass project = load_project() debugger = get_debugger() # TODO handle simbolic address properly seg = None try: seg = debugger.seg_by_addr(new_page_addr) except BaseException: pass #print( "LOADING 0x%x - 0x%x | 0x%x - 0x%x" % (new_page_addr, new_page_addr+self._page_size, seg.start, seg.end)) try: if get_memory_type() == USE_CLE_MEMORY: # yes this is weird if isinstance(self._memory_backer, cle.Clemory): # find permission backer associated with the address # fall back to default (read-write-maybe-exec) if can't find any for start, end in self._permission_map: if start <= new_page_addr < end: flags = self._permission_map[(start, end)] new_page.permissions = claripy.BVV(flags, 3) break # for each clemory backer which intersects with the page, apply its relevant data for backer_addr, backer in self._memory_backer.backers( new_page_addr): if backer_addr >= new_page_addr + self._page_size: break relevant_region_start = max(new_page_addr, backer_addr) relevant_region_end = min( new_page_addr + self._page_size, backer_addr + len(backer)) slice_start = relevant_region_start - backer_addr slice_end = relevant_region_end - backer_addr if self.byte_width == 8: relevant_data = bytes( memoryview(backer)[slice_start:slice_end]) mo = SimMemoryObject(claripy.BVV(relevant_data), relevant_region_start, byte_width=self.byte_width) self._apply_object_to_page(new_page_addr, mo, page=new_page) else: for i, byte in enumerate( backer[slice_start:slice_end]): mo = SimMemoryObject( claripy.BVV(byte, self.byte_width), relevant_region_start + i, byte_width=self.byte_width) self._apply_object_to_page(new_page_addr, mo, page=new_page) initialized = True elif len(self._memory_backer) <= self._page_size: for i in self._memory_backer: if new_page_addr <= i <= new_page_addr + self._page_size: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True elif len(self._memory_backer) > self._page_size: for i in range(self._page_size): try: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, new_page_addr + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True except KeyError: pass except Exception as ee: print(ee) # page from debugger try: if seg is not None: perms = 0 if seg.perms & SEG_PROT_X: perms += DbgPage.PROT_EXEC if seg.perms & SEG_PROT_W: perms += DbgPage.PROT_WRITE if seg.perms & SEG_PROT_R: perms += DbgPage.PROT_READ new_page.permissions = claripy.BVV(perms, 3) #print "permissions setted %x %d" % (new_page_addr, perms) initialized = True setattr(new_page, "from_dbg", True) except Exception as ee: import traceback traceback.print_exc() if self.state is not None: self.state.scratch.pop_priv() return initialized