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
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]
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