class LinearStreamingInterpolator(StreamingInterpolatorBase):
    """ Linear streaming interpolator """

    def __init__(self):
        self._history = AVLTree()

    def insert(self, x, val):
        """
        Register a datapoint

        x (float) : the x coordinate of the datapoint
        val (float): the rest of the datapoint
        """
        self._history.insert(x, val)

    def getInterpolatedVal(self, x):
        """
        Get the interpolated value for the given x

        x (float) : the x coordinate of the datapoint
        returns (float) : interpolated value
        """
        if self._history.is_empty():
            return None

        leftX, leftVal = None, None
        rightX, rightVal = None, None
        if self._history.min_key() <= x:
            leftX, leftVal = self._history.floor_item(x)
            if leftX == x:
                return leftVal
        if self._history.max_key() >= x:
            rightX, rightVal = self._history.ceiling_item(x)
            if rightX == x:
                return rightVal

        # check if on edge
        if leftVal == None:
            return rightVal
        elif rightVal == None:
            return leftVal

        # find weighted average of the vals of the closest enclosing data
        # points
        intervalLength = abs(x - leftX) + abs(x - rightX)
        value = float(abs(x - rightX) * leftVal + abs(x - leftX) * rightVal) / intervalLength
        return value
class NearestNeighborStreamingInterpolator(StreamingInterpolatorBase):
    """ Nearest Neighbor 1D Streaming Interpolator """

    def __init__(self):
        self._history = AVLTree()

    def insert(self, x, val):
        """
        Register a datapoint

        x (float) : the x coordinate of the datapoint
        val (float): the rest of the datapoint
        """
        self._history.insert(x, val)

    def getInterpolatedVal(self, x):
        """
        Get the interpolated value for the given x

        x (float) : the x coordinate of the datapoint
        returns (float) : interpolated value
        """
        if self._history.is_empty():
            return None

        # find the nearest point to the left and right
        leftX, leftVal = None, None
        rightX, rightVal = None, None
        if self._history.min_key() <= x:
            leftX, leftVal = self._history.floor_item(x)
        if self._history.max_key() >= x:
            rightX, rightVal = self._history.ceiling_item(x)

        # if there is only one neighbor, return it
        if leftVal == None:
            return rightVal
        elif rightVal == None:
            return leftVal

        # return the nearest neighbor
        if abs(x - leftX) < abs(x - rightX):
            return leftVal
        else:
            return rightVal
Example #3
0
class LineMapper(object):
    def __init__(self, series):
        self.__x_tree = AVLTree()
        self.__y_tree = AVLTree()
        self.__mapping = {}

        for (line, (xs, ys)) in enumerate(series):
            for (point, (x, y)) in enumerate(zip(xs, ys)):
                self.__x_tree.insert(x, x)
                self.__y_tree.insert(y, y)

                if self.__mapping.get(x) is None:
                    self.__mapping[x] = {}

                if self.__mapping[x].get(y) is None:
                    self.__mapping[x][y] = []

                self.__mapping[x][y].append((line, point, x, y))

    def __euclidean_distance(self, x1, y1, x2, y2):
        return sqrt((x2 - x1)**2 + (y2 - y1)**2)

    def get_closests(self, x, y, radius=None):
        try:
            x_floor = self.__x_tree.floor_item(x)[0]
        except KeyError:
            x_floor = None

        try:
            y_floor = self.__y_tree.floor_item(y)[0]
        except KeyError:
            y_floor = None

        try:
            x_ceiling = self.__x_tree.ceiling_item(x)[0]
        except KeyError:
            x_ceiling = None

        try:
            y_ceiling = self.__y_tree.ceiling_item(y)[0]
        except KeyError:
            y_ceiling = None

        points = [
            (x_floor, y_floor),
            (x_floor, y_ceiling),
            (x_ceiling, y_floor),
            (x_ceiling, y_ceiling),
        ]
        points = filter(lambda p: p[0] is not None and p[1] is not None,
                        points)
        points = filter(lambda p: self.__mapping.get(p[0]) != None, points)
        points = filter(lambda p: self.__mapping[p[0]].get(p[1]) != None,
                        points)

        distances = [(self.__euclidean_distance(x, y, *p), *p) for p in points]
        if radius is not None:
            distances = filter(lambda d: d[0] < radius, distances)

        distances = list(distances)
        if len(distances) == 0:
            return None

        (x, y) = min(distances, key=lambda p: p[0])[1:]
        return self.__mapping[x][y]
Example #4
0
class CFBlanket(Analysis):
    """
    A Control-Flow Blanket is a representation for storing all instructions, data entries, and bytes of a full program.
    """
    def __init__(self, cfg=None):
        self._blanket = AVLTree()

        self._ffi = cffi.FFI()

        if cfg is not None:
            self._from_cfg(cfg)
        else:
            _l.debug(
                "CFG is not specified. Initialize CFBlanket from the knowledge base."
            )
            for func in self.kb.functions.values():
                self.add_function(func)

    def floor_item(self, addr):
        return self._blanket.floor_item(addr)

    def floor_items(self, addr=None):

        if addr is None:
            addr = self._blanket.min_key()
        else:
            try:
                addr = self.floor_addr(addr)
            except KeyError:
                try:
                    addr = self.ceiling_addr(addr)
                except KeyError:
                    # Nothing to yield
                    raise StopIteration

        while True:
            try:
                item = self._blanket[addr]
                yield (addr, item)
                item_size = item.size if item.size > 0 else 1  # pylint: disable=no-member
                addr = self.ceiling_addr(addr + item_size)
            except KeyError:
                break

    def floor_addr(self, addr):
        return self._blanket.floor_key(addr)

    def ceiling_item(self, addr):
        return self._blanket.ceiling_item(addr)

    def ceiling_addr(self, addr):
        return self._blanket.ceiling_key(addr)

    def __getitem__(self, addr):
        return self._blanket[addr]

    def add_obj(self, addr, obj):
        """


        :param addr:
        :param obj:
        :return:
        """

        self._blanket[addr] = obj

    def add_function(self, func):
        """
        Add a function and all blocks of this function to the blanket.

        :param angr.Function func: The function to add.
        :return:
        """

        for block in func.blocks:
            self.add_obj(block.addr, block)

    def dbg_repr(self):
        """
        The debugging representation of this CFBlanket.

        :return:    The debugging representation of this CFBlanket.
        :rtype:     str
        """

        output = []

        for obj in self.project.loader.all_objects:
            for section in obj.sections:
                if section.memsize == 0:
                    continue
                min_addr, max_addr = section.min_addr, section.max_addr
                output.append("### Object %s" % repr(section))
                output.append("### Range %#x-%#x" % (min_addr, max_addr))

                pos = min_addr
                while pos < max_addr:
                    try:
                        addr, thing = self.floor_item(pos)
                        output.append("%#x: %s" % (addr, repr(thing)))

                        if thing.size == 0: pos += 1
                        else: pos += thing.size
                    except KeyError:
                        pos += 1

                output.append("")

        return "\n".join(output)

    def _from_cfg(self, cfg):
        """
        Initialize CFBlanket from a CFG instance.

        :param cfg: A CFG instance.
        :return:    None
        """

        # Let's first add all functions first
        for func in cfg.kb.functions.values():
            self.add_function(func)

        self._mark_unknowns()

    def _mark_unknowns(self):
        """
        Mark all unmapped regions.

        :return: None
        """

        for obj in self.project.loader.all_objects:
            if isinstance(obj, cle.ELF):
                # sections?
                if obj.sections:
                    for section in obj.sections:
                        if not section.memsize or not section.vaddr:
                            continue
                        min_addr, max_addr = section.min_addr, section.max_addr
                        self._mark_unknowns_core(min_addr,
                                                 max_addr,
                                                 obj=obj,
                                                 section=section)
                elif obj.segments:
                    for segment in obj.segments:
                        if not segment.memsize:
                            continue
                        min_addr, max_addr = segment.min_addr, segment.max_addr
                        self._mark_unknowns_core(min_addr,
                                                 max_addr,
                                                 obj=obj,
                                                 segment=segment)
                else:
                    # is it empty?
                    _l.warning("Empty ELF object %s.", repr(obj))
            elif isinstance(obj, cle.PE):
                if obj.sections:
                    for section in obj.sections:
                        if not section.memsize:
                            continue
                        min_addr, max_addr = section.min_addr, section.max_addr
                        self._mark_unknowns_core(min_addr,
                                                 max_addr,
                                                 obj=obj,
                                                 section=section)
                else:
                    # is it empty?
                    _l.warning("Empty PE object %s.", repr(obj))
            else:
                min_addr, max_addr = obj.min_addr, obj.max_addr
                self._mark_unknowns_core(min_addr, max_addr, obj=obj)

    def _mark_unknowns_core(self,
                            min_addr,
                            max_addr,
                            obj=None,
                            segment=None,
                            section=None):

        try:
            addr = self.floor_addr(min_addr)
            if addr < min_addr:
                raise KeyError
        except KeyError:
            # there is no other lower address
            try:
                next_addr = self.ceiling_addr(min_addr)
                if next_addr >= max_addr:
                    raise KeyError
            except KeyError:
                next_addr = max_addr

            size = next_addr - min_addr
            if obj is None or isinstance(obj, cle.ExternObject):
                bytes_ = None
            else:
                try:
                    _l.debug(
                        "Loading bytes from object %s, section %s, segmeng %s, addresss %#x.",
                        obj, section, segment, min_addr)
                    bytes_ptr, _ = self.project.loader.memory.read_bytes_c(
                        min_addr)
                    bytes_ = self._ffi.unpack(
                        self._ffi.cast('char*', bytes_ptr), size)  # type: str
                except KeyError:
                    # The address does not exist
                    bytes_ = None
            self.add_obj(
                min_addr,
                Unknown(min_addr,
                        size,
                        bytes_=bytes_,
                        object_=obj,
                        segment=segment,
                        section=section))

        addr = min_addr
        while addr < max_addr:
            last_addr, last_item = self.floor_item(addr)
            if last_addr < min_addr:
                # impossible
                raise Exception('Impossible')

            if last_item.size == 0:
                # Make sure everything has a non-zero size
                last_item_size = 1
            else:
                last_item_size = last_item.size
            end_addr = last_addr + last_item_size
            if end_addr < max_addr:
                try:
                    next_addr = self.ceiling_addr(end_addr)
                except KeyError:
                    next_addr = max_addr
                if next_addr > end_addr:
                    # there is a gap
                    size = next_addr - end_addr
                    if obj is None or isinstance(obj, cle.ExternObject):
                        bytes_ = None
                    else:
                        try:
                            _l.debug(
                                "Loading bytes from object %s, section %s, segmeng %s, addresss %#x.",
                                obj, section, segment, next_addr)
                            bytes_ptr, _ = self.project.loader.memory.read_bytes_c(
                                next_addr)
                            bytes_ = self._ffi.unpack(
                                self._ffi.cast('char*', bytes_ptr),
                                size)  # type: str
                        except KeyError:
                            # The address does not exist
                            bytes_ = None
                    self.add_obj(
                        end_addr,
                        Unknown(end_addr,
                                size,
                                bytes_=bytes_,
                                object_=obj,
                                segment=segment,
                                section=section))
                addr = next_addr
            else:
                addr = max_addr