示例#1
0
文件: page.py 项目: d4em0n/angrdbg
    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()
示例#2
0
    def unmap_region(self, addr, length):
        if o.TRACK_MEMORY_MAPPING not in self.state.options:
            return

        if self.state.se.symbolic(addr):
            raise SimMemoryError("cannot unmap 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

        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 xrange(pages):
                if base_page_num + page not in self._pages:
                    l.warning(
                        "unmap_region received address and length combination is not mapped"
                    )
                    return

        for page in xrange(pages):
            del self._pages[base_page_num + page]
            del self._symbolic_addrs[base_page_num + page]
示例#3
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
示例#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.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()
示例#5
0
文件: memory.py 项目: fcccode/IDAngr
    def _store_with_merge(self, req):
        req._adjust_condition(self.state)

        dst = req.addr
        cnt = req.data
        size = req.size
        endness = req.endness

        req.stored_values = [ ]

        if options.ABSTRACT_MEMORY not in self.state.options:
            raise SimMemoryError('store_with_merge is not supported without abstract memory.')

        l.debug("Doing a store with merging...")

        addrs = self.concretize_write_addr(dst)

        if len(addrs) == 1:
            l.debug("... concretized to 0x%x", addrs[0])
        else:
            l.debug("... concretized to %d values", len(addrs))

        if size is None:
            # Full length
            length = len(cnt)
        else:
            raise NotImplementedError()

        for addr in addrs:
            # First we load old values
            old_val = self._read_from(addr, length // self.state.arch.byte_width)
            assert isinstance(old_val, claripy.Bits)

            # FIXME: This is a big hack
            def is_reversed(o):
                if isinstance(o, claripy.Bits) and o.op == 'Reverse':
                    return True
                return False

            def can_be_reversed(o):
                om = o._model_vsa
                if isinstance(om, claripy.vsa.StridedInterval) and om.is_integer:
                    return True
                return False

            if endness == 'Iend_LE': cnt = cnt.reversed

            reverse_it = False
            if is_reversed(cnt):
                if is_reversed(old_val):
                    cnt = cnt.args[0]
                    old_val = old_val.args[0]
                    reverse_it = True
                elif can_be_reversed(old_val):
                    cnt = cnt.args[0]
                    reverse_it = True
            if isinstance(old_val, (int, long, claripy.bv.BVV)):
                merged_val = self.state.se.SI(bits=len(old_val), to_conv=old_val)
            else:
                merged_val = old_val
            merged_val = merged_val.union(cnt)
            if reverse_it:
                merged_val = merged_val.reversed

            # Write the new value
            self.store(addr, merged_val, size=size)

            req.stored_values.append(merged_val)

        req.completed = True

        # TODO: revisit the following lines
        req.constraints = [ ]

        return req
示例#6
0
文件: memory.py 项目: fcccode/IDAngr
    def _store(self, req):
        l.debug("Doing a store...")
        req._adjust_condition(self.state)

        max_bytes = req.data.length//self.state.arch.byte_width

        if req.size is None:
            req.size = max_bytes

        if self.state.solver.symbolic(req.size):
            if options.AVOID_MULTIVALUED_WRITES in self.state.options:
                return req
            if options.CONCRETIZE_SYMBOLIC_WRITE_SIZES in self.state.options:
                new_size = self.state.solver.eval(req.size)
                self.state.add_constraints(req.size == new_size)
                req.size = new_size

        if self.state.solver.symbolic(req.addr) and options.AVOID_MULTIVALUED_WRITES in self.state.options:
            return req

        if not self.state.solver.symbolic(req.size) and self.state.solver.eval(req.size) > req.data.length//self.state.arch.byte_width:
            raise SimMemoryError("Not enough data for requested storage size (size: {}, data: {})".format(req.size, req.data))

        if self.state.solver.symbolic(req.size):
            self.state.add_constraints(self.state.solver.ULE(req.size, max_bytes))


        #
        # First, resolve the addresses
        #

        try:
            req.actual_addresses = sorted(self.concretize_write_addr(req.addr))
        except SimMemoryError:
            if options.CONSERVATIVE_WRITE_STRATEGY in self.state.options:
                return req
            else:
                raise

        if type(req.addr) not in (int, long) and req.addr.symbolic:
            conditional_constraint = self.state.solver.Or(*[ req.addr == a for a in req.actual_addresses ])
            if (conditional_constraint.symbolic or  # if the constraint is symbolic
                    conditional_constraint.is_false()):  # if it makes the state go unsat
                req.constraints.append(conditional_constraint)

        #
        # Prepare memory objects
        #
        # If we have only one address to write to we handle it as concrete, disregarding symbolic or not
        is_size_symbolic = self.state.solver.symbolic(req.size)
        is_addr_symbolic = self.state.solver.symbolic(req.addr)
        if not is_size_symbolic and len(req.actual_addresses) == 1:
            store_list = self._store_fully_concrete(req.actual_addresses[0], req.size, req.data, req.endness, req.condition)
        elif not is_addr_symbolic:
            store_list = self._store_symbolic_size(req.addr, req.size, req.data, req.endness, req.condition)
        elif not is_size_symbolic:
            store_list = self._store_symbolic_addr(req.addr, req.actual_addresses, req.size, req.data, req.endness, req.condition)
        else:
            store_list = self._store_fully_symbolic(req.addr, req.actual_addresses, req.size, req.data, req.endness, req.condition)

        #
        # store it!!!
        #
        req.stored_values = []
        if (self.category == 'mem' and options.SIMPLIFY_MEMORY_WRITES in self.state.options) or \
           (self.category == 'reg' and options.SIMPLIFY_REGISTER_WRITES in self.state.options):
            for store_item in store_list:
                store_item['value'] = self.state.solver.simplify(store_item['value'])

                if req.endness == "Iend_LE" or (req.endness is None and self.endness == "Iend_LE"):
                    store_item['value'] = store_item['value'].reversed

                req.stored_values.append(store_item['value'])
                self._insert_memory_object(store_item['value'], store_item['addr'], store_item['size'])
        else:
            for store_item in store_list:
                if req.endness == "Iend_LE" or (req.endness is None and self.endness == "Iend_LE"):
                    store_item['value'] = store_item['value'].reversed

                req.stored_values.append(store_item['value'])
                self._insert_memory_object(store_item['value'], store_item['addr'], store_item['size'])

        l.debug("... done")
        req.completed = True
        return req
示例#7
0
文件: page.py 项目: fcccode/IDAngr
    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