Esempio n. 1
0
 def __repr__(self):
     lst = []
     for num, layer in six.iteritems(self.num2layer):
         if layer in self.layer2num and self.layer2num[layer] == num:
             dir = "<->"
         else:
             dir = " ->"
         lst.append((num, "%#6x %s %-20s (%s)" % (num, dir, layer.__name__,
                                                  layer._name)))
     for layer, num in six.iteritems(self.layer2num):
         if num not in self.num2layer or self.num2layer[num] != layer:
             lst.append((num, "%#6x <-  %-20s (%s)" % (num, layer.__name__,
                                                       layer._name)))
     lst.sort()
     return "\n".join(y for x, y in lst)
Esempio n. 2
0
 def update(self, other):
     for key, value in six.iteritems(other):
         # We only update an element from `other` either if it does
         # not exist in `self` or if the entry in `self` is older.
         if key not in self or self._timetable[key] < other._timetable[key]:
             dict.__setitem__(self, key, value)
             self._timetable[key] = other._timetable[key]
Esempio n. 3
0
def _load(module, globals_dict=None, symb_list=None):
    # type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None
    """Loads a Python module to make variables, objects and functions
available globally.

    The idea is to load the module using importlib, then copy the
symbols to the global symbol table.

    """
    if globals_dict is None:
        globals_dict = six.moves.builtins.__dict__
    try:
        mod = importlib.import_module(module)
        if '__all__' in mod.__dict__:
            # import listed symbols
            for name in mod.__dict__['__all__']:
                if symb_list is not None:
                    symb_list.append(name)
                globals_dict[name] = mod.__dict__[name]
        else:
            # only import non-private symbols
            for name, sym in six.iteritems(mod.__dict__):
                if _validate_local(name):
                    if symb_list is not None:
                        symb_list.append(name)
                    globals_dict[name] = sym
    except Exception:
        log_interactive.error("Loading module %s", module, exc_info=True)
Esempio n. 4
0
 def __getattr__(self, attr):
     try:
         return object.__getattribute__(self, attr)
     except AttributeError:
         for k, v in six.iteritems(self.__dict__):
             if self.ident(v) == attr:
                 return k
Esempio n. 5
0
 def __repr__(self):
     s = []
     if self:
         mk = max(len(k) for k in six.iterkeys(self.__dict__))
         fmt = "%%-%is %%s" % (mk + 1)
         for item in six.iteritems(self.__dict__):
             s.append(fmt % item)
     return "\n".join(s)
Esempio n. 6
0
    def multiplot(self, f, lfilter=None, plot_xy=False, **kargs):
        # type: (Callable, Optional[Callable], bool, Any) -> Line2D
        """Uses a function that returns a label and a value for this label, then
        plots all the values label by label.

        A list of matplotlib.lines.Line2D is returned.
        """

        # Python 2 backward compatibility
        f = lambda_tuple_converter(f)
        lfilter = lambda_tuple_converter(lfilter)

        # Get the list of packets
        if lfilter is None:
            lst_pkts = (f(*e) for e in self.res)
        else:
            lst_pkts = (f(*e) for e in self.res if lfilter(*e))

        # Apply the function f to the packets
        d = {}  # type: Dict[str, List[float]]
        for k, v in lst_pkts:
            d.setdefault(k, []).append(v)

        # Mimic the default gnuplot output
        if not kargs:
            kargs = MATPLOTLIB_DEFAULT_PLOT_KARGS

        if plot_xy:
            lines = [
                plt.plot(*zip(*pl), **dict(kargs, label=k))
                for k, pl in six.iteritems(d)
            ]
        else:
            lines = [
                plt.plot(pl, **dict(kargs, label=k))
                for k, pl in six.iteritems(d)
            ]
        plt.legend(loc="center right", bbox_to_anchor=(1.5, 0.5))

        # Call show() if matplotlib is not inlined
        if not MATPLOTLIB_INLINED:
            plt.show()

        return lines
Esempio n. 7
0
    def reverse_lookup(self, name, case_sensitive=False):
        """
        Find all MACs registered to a OUI

        :param name: the OUI name
        :param case_sensitive: default to False
        :returns: a dict of mac:tuples (Name, Extended Name)
        """
        if case_sensitive:
            filtr = lambda x, l: any(x == z for z in l)
        else:
            name = name.lower()
            filtr = lambda x, l: any(x == z.lower() for z in l)
        return {k: v for k, v in six.iteritems(self.__dict__)
                if filtr(name, v)}
Esempio n. 8
0
    def conversations(self, getsrcdst=None, **kargs):
        """Graphes a conversations between sources and destinations and display it
        (using graphviz and imagemagick)

        :param getsrcdst: a function that takes an element of the list and
            returns the source, the destination and optionally
            a label. By default, returns the IP source and
            destination from IP and ARP layers
        :param type: output type (svg, ps, gif, jpg, etc.), passed to dot's
            "-T" option
        :param target: filename or redirect. Defaults pipe to Imagemagick's
            display program
        :param prog: which graphviz program to use
        """
        if getsrcdst is None:

            def getsrcdst(pkt):
                """Extract src and dst addresses"""
                if 'IP' in pkt:
                    return (pkt['IP'].src, pkt['IP'].dst)
                if 'IPv6' in pkt:
                    return (pkt['IPv6'].src, pkt['IPv6'].dst)
                if 'ARP' in pkt:
                    return (pkt['ARP'].psrc, pkt['ARP'].pdst)
                raise TypeError()

        conv = {}
        for p in self.res:
            p = self._elt2pkt(p)
            try:
                c = getsrcdst(p)
            except Exception:
                # No warning here: it's OK that getsrcdst() raises an
                # exception, since it might be, for example, a
                # function that expects a specific layer in each
                # packet. The try/except approach is faster and
                # considered more Pythonic than adding tests.
                continue
            if len(c) == 3:
                conv.setdefault(c[:2], set()).add(c[2])
            else:
                conv[c] = conv.get(c, 0) + 1
        gr = 'digraph "conv" {\n'
        for (s, d), l in six.iteritems(conv):
            gr += '\t "%s" -> "%s" [label="%s"]\n' % (s, d, ', '.join(
                str(x) for x in l) if isinstance(l, set) else l)
        gr += "}\n"
        return do_graph(gr, **kargs)
    def load(self):
        if not get_if_list():
            # Try a restart
            NetworkInterfaceDict._pcap_check()

        windows_interfaces = dict()
        for i in get_windows_if_list():
            # Detect Loopback interface
            if "Loopback" in i['name']:
                i['name'] = conf.loopback_name
            if i['guid']:
                if conf.use_npcap and i['name'] == conf.loopback_name:
                    i['guid'] = NPCAP_LOOPBACK_NAME
                windows_interfaces[i['guid']] = i

        index = 0
        for pcap_name, if_data in six.iteritems(conf.cache_iflist):
            name, ips, flags = if_data
            guid = _pcapname_to_guid(pcap_name)
            data = windows_interfaces.get(guid, None)
            if data:
                # Exists in Windows registry
                data['pcap_name'] = pcap_name
                data['ips'].extend(ips)
                data['flags'] = flags
                data['invalid'] = False
            else:
                # Only in [Wi]npcap
                index -= 1
                data = {
                    'name': name,
                    'pcap_name': pcap_name,
                    'description': name,
                    'win_index': index,
                    'guid': guid,
                    'invalid': False,
                    'mac': '00:00:00:00:00:00',
                    'ipv4_metric': 0,
                    'ipv6_metric': 0,
                    'ips': list(set(ips)),
                    'flags': flags
                }
            # No KeyError will happen here, as we get it from cache
            self.data[guid] = NetworkInterface(data)
Esempio n. 10
0
    def build_graph(self):
        s = 'digraph "%s" {\n' % self.__class__.__name__

        se = ""  # Keep initial nodes at the beginning for better rendering
        for st in six.itervalues(self.states):
            if st.atmt_initial:
                se = ('\t"%s" [ style=filled, fillcolor=blue, shape=box, root=true];\n' % st.atmt_state) + se  # noqa: E501
            elif st.atmt_final:
                se += '\t"%s" [ style=filled, fillcolor=green, shape=octagon ];\n' % st.atmt_state  # noqa: E501
            elif st.atmt_error:
                se += '\t"%s" [ style=filled, fillcolor=red, shape=octagon ];\n' % st.atmt_state  # noqa: E501
        s += se

        for st in six.itervalues(self.states):
            for n in st.atmt_origfunc.__code__.co_names + st.atmt_origfunc.__code__.co_consts:  # noqa: E501
                if n in self.states:
                    s += '\t"%s" -> "%s" [ color=green ];\n' % (st.atmt_state, n)  # noqa: E501

        for c, k, v in ([("purple", k, v) for k, v in self.conditions.items()] +  # noqa: E501
                        [("red", k, v) for k, v in self.recv_conditions.items()] +  # noqa: E501
                        [("orange", k, v) for k, v in self.ioevents.items()]):
            for f in v:
                for n in f.__code__.co_names + f.__code__.co_consts:
                    if n in self.states:
                        line = f.atmt_condname
                        for x in self.actions[f.atmt_condname]:
                            line += "\\l>[%s]" % x.__name__
                        s += '\t"%s" -> "%s" [label="%s", color=%s];\n' % (k, n, line, c)  # noqa: E501
        for k, v in six.iteritems(self.timeout):
            for t, f in v:
                if f is None:
                    continue
                for n in f.__code__.co_names + f.__code__.co_consts:
                    if n in self.states:
                        line = "%s/%.1fs" % (f.atmt_condname, t)
                        for x in self.actions[f.atmt_condname]:
                            line += "\\l>[%s]" % x.__name__
                        s += '\t"%s" -> "%s" [label="%s",color=blue];\n' % (k, n, line)  # noqa: E501
        s += "}\n"
        return s
Esempio n. 11
0
 def values(self):
     if self.timeout is None:
         return list(six.itervalues(self))
     t0 = time.time()
     return [v for (k, v) in six.iteritems(self.__dict__) if t0 - self._timetable[k] < self.timeout]  # noqa: E501
Esempio n. 12
0
 def items(self):
     if self.timeout is None:
         return dict.items(self)
     t0 = time.time()
     return [(k, v) for (k, v) in six.iteritems(self.__dict__) if t0 - self._timetable[k] < self.timeout]  # noqa: E501
Esempio n. 13
0
    def _run(self,
             count=0, store=True, offline=None,
             quiet=False, prn=None, lfilter=None,
             L2socket=None, timeout=None, opened_socket=None,
             stop_filter=None, iface=None, started_callback=None,
             session=None, session_args=[], session_kwargs={},
             *arg, **karg):
        self.running = True
        # Start main thread
        # instantiate session
        if not isinstance(session, DefaultSession):
            session = session or DefaultSession
            session = session(prn=prn, store=store,
                              *session_args, **session_kwargs)
        else:
            session.prn = prn
            session.store = store
        # sniff_sockets follows: {socket: label}
        sniff_sockets = {}
        if opened_socket is not None:
            if isinstance(opened_socket, list):
                sniff_sockets.update(
                    (s, "socket%d" % i)
                    for i, s in enumerate(opened_socket)
                )
            elif isinstance(opened_socket, dict):
                sniff_sockets.update(
                    (s, label)
                    for s, label in six.iteritems(opened_socket)
                )
            else:
                sniff_sockets[opened_socket] = "socket0"
        if offline is not None:
            flt = karg.get('filter')

            if isinstance(offline, list) and \
                    all(isinstance(elt, str) for elt in offline):
                sniff_sockets.update((PcapReader(
                    fname if flt is None else
                    tcpdump(fname, args=["-w", "-"], flt=flt, getfd=True)
                ), fname) for fname in offline)
            elif isinstance(offline, dict):
                sniff_sockets.update((PcapReader(
                    fname if flt is None else
                    tcpdump(fname, args=["-w", "-"], flt=flt, getfd=True)
                ), label) for fname, label in six.iteritems(offline))
            else:
                # Write Scapy Packet objects to a pcap file
                def _write_to_pcap(packets_list):
                    filename = get_temp_file(autoext=".pcap")
                    wrpcap(filename, offline)
                    return filename, filename

                if isinstance(offline, Packet):
                    tempfile_written, offline = _write_to_pcap([offline])
                elif isinstance(offline, list) and \
                        all(isinstance(elt, Packet) for elt in offline):
                    tempfile_written, offline = _write_to_pcap(offline)

                sniff_sockets[PcapReader(
                    offline if flt is None else
                    tcpdump(offline,
                            args=["-w", "-"],
                            flt=flt,
                            getfd=True,
                            quiet=quiet)
                )] = offline
        if not sniff_sockets or iface is not None:
            if L2socket is None:
                L2socket = conf.L2listen
            if isinstance(iface, list):
                sniff_sockets.update(
                    (L2socket(type=ETH_P_ALL, iface=ifname, *arg, **karg),
                     ifname)
                    for ifname in iface
                )
            elif isinstance(iface, dict):
                sniff_sockets.update(
                    (L2socket(type=ETH_P_ALL, iface=ifname, *arg, **karg),
                     iflabel)
                    for ifname, iflabel in six.iteritems(iface)
                )
            else:
                sniff_sockets[L2socket(type=ETH_P_ALL, iface=iface,
                                       *arg, **karg)] = iface

        # Get select information from the sockets
        _main_socket = next(iter(sniff_sockets))
        select_func = _main_socket.select
        _backup_read_func = _main_socket.__class__.recv
        nonblocking_socket = _main_socket.nonblocking_socket
        # We check that all sockets use the same select(), or raise a warning
        if not all(select_func == sock.select for sock in sniff_sockets):
            warning("Warning: inconsistent socket types ! "
                    "The used select function "
                    "will be the one of the first socket")

        if nonblocking_socket:
            # select is non blocking
            def stop_cb():
                self.continue_sniff = False
            self.stop_cb = stop_cb
            close_pipe = None
        else:
            # select is blocking: Add special control socket
            from pocsuite3.thirdparty.scapy.automaton import ObjectPipe
            close_pipe = ObjectPipe()
            sniff_sockets[close_pipe] = "control_socket"

            def stop_cb():
                if self.running:
                    close_pipe.send(None)
                self.continue_sniff = False
            self.stop_cb = stop_cb

        try:
            if started_callback:
                started_callback()
            self.continue_sniff = True

            # Start timeout
            if timeout is not None:
                stoptime = time.time() + timeout
            remain = None

            while sniff_sockets and self.continue_sniff:
                if timeout is not None:
                    remain = stoptime - time.time()
                    if remain <= 0:
                        break
                sockets, read_func = select_func(sniff_sockets, remain)
                read_func = read_func or _backup_read_func
                dead_sockets = []
                for s in sockets:
                    if s is close_pipe:
                        break
                    try:
                        p = read_func(s)
                    except EOFError:
                        # End of stream
                        try:
                            s.close()
                        except Exception:
                            pass
                        dead_sockets.append(s)
                        continue
                    except Exception as ex:
                        msg = " It was closed."
                        try:
                            # Make sure it's closed
                            s.close()
                        except Exception as ex:
                            msg = " close() failed with '%s'" % ex
                        warning(
                            "Socket %s failed with '%s'." % (s, ex) + msg
                        )
                        dead_sockets.append(s)
                        if conf.debug_dissector >= 2:
                            raise
                        continue
                    if p is None:
                        continue
                    if lfilter and not lfilter(p):
                        continue
                    p.sniffed_on = sniff_sockets[s]
                    # on_packet_received handles the prn/storage
                    session.on_packet_received(p)
                    # check
                    #print("stop_filter and stop_filter(p) is ",stop_filter and stop_filter(p))
                    if (stop_filter and stop_filter(p)) or \
                            (0 < count <= session.count):
                        self.continue_sniff = False
                        break
                # Removed dead sockets
                for s in dead_sockets:
                    del sniff_sockets[s]
        except KeyboardInterrupt:
            pass
        self.running = False
        if opened_socket is None:
            for s in sniff_sockets:
                s.close()
        elif close_pipe:
            close_pipe.close()
        self.results = session.toPacketList()
Esempio n. 14
0
 def update(self, *args, **kwargs):
     for k, v in six.iteritems(dict(*args, **kwargs)):
         self[k] = v
Esempio n. 15
0
    def __new__(cls, name, bases, dct):
        cls = super(Automaton_metaclass, cls).__new__(cls, name, bases, dct)
        cls.states = {}
        cls.state = None
        cls.recv_conditions = {}
        cls.conditions = {}
        cls.ioevents = {}
        cls.timeout = {}
        cls.actions = {}
        cls.initial_states = []
        cls.ionames = []
        cls.iosupersockets = []

        members = {}
        classes = [cls]
        while classes:
            c = classes.pop(0)  # order is important to avoid breaking method overloading  # noqa: E501
            classes += list(c.__bases__)
            for k, v in six.iteritems(c.__dict__):
                if k not in members:
                    members[k] = v

        decorated = [v for v in six.itervalues(members)
                     if isinstance(v, types.FunctionType) and hasattr(v, "atmt_type")]  # noqa: E501

        for m in decorated:
            if m.atmt_type == ATMT.STATE:
                s = m.atmt_state
                cls.states[s] = m
                cls.recv_conditions[s] = []
                cls.ioevents[s] = []
                cls.conditions[s] = []
                cls.timeout[s] = []
                if m.atmt_initial:
                    cls.initial_states.append(m)
            elif m.atmt_type in [ATMT.CONDITION, ATMT.RECV, ATMT.TIMEOUT, ATMT.IOEVENT]:  # noqa: E501
                cls.actions[m.atmt_condname] = []

        for m in decorated:
            if m.atmt_type == ATMT.CONDITION:
                cls.conditions[m.atmt_state].append(m)
            elif m.atmt_type == ATMT.RECV:
                cls.recv_conditions[m.atmt_state].append(m)
            elif m.atmt_type == ATMT.IOEVENT:
                cls.ioevents[m.atmt_state].append(m)
                cls.ionames.append(m.atmt_ioname)
                if m.atmt_as_supersocket is not None:
                    cls.iosupersockets.append(m)
            elif m.atmt_type == ATMT.TIMEOUT:
                cls.timeout[m.atmt_state].append((m.atmt_timeout, m))
            elif m.atmt_type == ATMT.ACTION:
                for c in m.atmt_cond:
                    cls.actions[c].append(m)

        for v in six.itervalues(cls.timeout):
            v.sort(key=lambda x: x[0])
            v.append((None, None))
        for v in itertools.chain(six.itervalues(cls.conditions),
                                 six.itervalues(cls.recv_conditions),
                                 six.itervalues(cls.ioevents)):
            v.sort(key=lambda x: x.atmt_prio)
        for condname, actlst in six.iteritems(cls.actions):
            actlst.sort(key=lambda x: x.atmt_cond[condname])

        for ioev in cls.iosupersockets:
            setattr(cls, ioev.atmt_as_supersocket, _ATMT_to_supersocket(ioev.atmt_as_supersocket, ioev.atmt_ioname, cls))  # noqa: E501

        return cls
Esempio n. 16
0
 def __repr__(self):
     return "<Message %s>" % " ".join("%s=%r" % (k, v)
                                      for (k, v) in six.iteritems(self.__dict__)  # noqa: E501
                                      if not k.startswith("_"))