Example #1
0
    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
Example #2
0
    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
Example #3
0
    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)
Example #4
0
    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()
Example #5
0
    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
Example #6
0
    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
Example #7
0
    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
Example #8
0
 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
Example #9
0
    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
Example #10
0
 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
Example #11
0
 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
Example #12
0
 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
Example #13
0
    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()
Example #14
0
 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))]
Example #15
0
    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
Example #16
0
 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)
Example #17
0
    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
Example #18
0
    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
Example #19
0
    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
Example #20
0
    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
Example #21
0
    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