def srpflood(x, # type: _PacketIterable promisc=None, # type: Optional[bool] filter=None, # type: Optional[str] iface=None, # type: Optional[_GlobInterfaceType] iface_hint=None, # type: Optional[str] nofilter=None, # type: Optional[bool] *args, # type: Any **kargs # type: Any ): # type: (...) -> Tuple[SndRcvList, PacketList] """Flood and receive packets at layer 2 :param prn: function applied to packets received :param unique: only consider packets whose print :param nofilter: put 1 to avoid use of BPF filters :param filter: provide a BPF filter :param iface: listen answers only on the given interface """ if iface is None and iface_hint is not None: iface = conf.route.route(iface_hint)[0] iface = resolve_iface(iface or conf.iface) s = iface.l2socket()(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter) # noqa: E501 r = sndrcvflood(s, x, *args, **kargs) s.close() return r
def _send( x, # type: _PacketIterable _func, # type: Callable[[NetworkInterface], Type[SuperSocket]] inter=0, # type: int loop=0, # type: int iface=None, # type: Optional[_GlobInterfaceType] count=None, # type: Optional[int] verbose=None, # type: Optional[int] realtime=False, # type: bool return_packets=False, # type: bool socket=None, # type: Optional[SuperSocket] **kargs # type: Any ): # type: (...) -> Optional[PacketList] """Internal function used by send and sendp""" need_closing = socket is None iface = resolve_iface(iface or conf.iface) socket = socket or _func(iface)(iface=iface, **kargs) results = __gen_send(socket, x, inter=inter, loop=loop, count=count, verbose=verbose, realtime=realtime, return_packets=return_packets) if need_closing: socket.close() return results
def srp( x, # type: Packet promisc=None, # type: Optional[bool] iface=None, # type: Optional[_GlobInterfaceType] iface_hint=None, # type: Optional[str] filter=None, # type: Optional[str] nofilter=0, # type: int type=ETH_P_ALL, # type: int *args, # type: Any **kargs # type: Any ): # type: (...) -> Tuple[SndRcvList, PacketList] """ Send and receive packets at layer 2 """ if iface is None and iface_hint is not None: iface = conf.route.route(iface_hint)[0] iface = resolve_iface(iface or conf.iface) s = iface.l2socket()(promisc=promisc, iface=iface, filter=filter, nofilter=nofilter, type=type) result = sndrcv(s, x, *args, **kargs) s.close() return result
def srp1flood( x, # type: _PacketIterable promisc=None, # type: Optional[bool] filter=None, # type: Optional[str] iface=None, # type: Optional[_GlobInterfaceType] nofilter=0, # type: int *args, # type: Any **kargs # type: Any ): # type: (...) -> Optional[Packet] """Flood and receive packets at layer 2 and return only the first answer :param prn: function applied to packets received :param verbose: set verbosity level :param nofilter: put 1 to avoid use of BPF filters :param filter: provide a BPF filter :param iface: listen answers only on the given interface """ iface = resolve_iface(iface or conf.iface) s = iface.l2socket()(promisc=promisc, filter=filter, nofilter=nofilter, iface=iface) # noqa: E501 ans, _ = sndrcvflood(s, x, *args, **kargs) s.close() if len(ans) > 0: return cast(Packet, ans[0][1]) return None
def _send(x, _func, inter=0, loop=0, iface=None, count=None, verbose=None, realtime=None, return_packets=False, socket=None, **kargs): """Internal function used by send and sendp""" need_closing = socket is None iface = resolve_iface(iface or conf.iface) socket = socket or _func(iface)(iface=iface, **kargs) results = __gen_send(socket, x, inter=inter, loop=loop, count=count, verbose=verbose, realtime=realtime, return_packets=return_packets) if need_closing: socket.close() return results
def srpflood(x, promisc=None, filter=None, iface=None, iface_hint=None, nofilter=None, *args, **kargs): # noqa: E501 """Flood and receive packets at layer 2 :param prn: function applied to packets received :param unique: only consider packets whose print :param nofilter: put 1 to avoid use of BPF filters :param filter: provide a BPF filter :param iface: listen answers only on the given interface """ if iface is None and iface_hint is not None: iface = conf.route.route(iface_hint)[0] iface = resolve_iface(iface or conf.iface) s = iface.l2socket()(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter) # noqa: E501 r = sndrcvflood(s, x, *args, **kargs) s.close() return r
def _init_socket(iface, count, L2socket=L2socket): if isinstance(iface, SuperSocket): return iface, "iface%d" % count else: if not L2socket: iface = resolve_iface(iface or conf.iface) L2socket = iface.l2socket() return L2socket(iface=iface), iface
def _iface_changer(attr, val, old): """Resolves the interface in conf.iface""" if isinstance(val, str): from scapy.interfaces import resolve_iface iface = resolve_iface(val) if old and iface.dummy: warning("This interface is not specified in any provider ! " "See conf.ifaces output") return iface return val
def __repr__(self): rtlst = [] for net, msk, gw, iface, addr, metric in self.routes: if_repr = resolve_iface(iface).description rtlst.append( (ltoa(net), ltoa(msk), gw, if_repr, addr, str(metric))) return pretty_list(rtlst, [ ("Network", "Netmask", "Gateway", "Iface", "Output IP", "Metric") ]) # noqa: E501
def __repr__(self): # type: () -> str rtlst = [] # type: List[Tuple[Union[str, List[str]], ...]] for net, msk, gw, iface, addr, metric in self.routes: if_repr = cast(str, resolve_iface(iface).description) rtlst.append( (ltoa(net), ltoa(msk), gw, if_repr, addr, str(metric))) return pretty_list(rtlst, [ ("Network", "Netmask", "Gateway", "Iface", "Output IP", "Metric") ]) # noqa: E501
def _init_socket(iface, # type: _GlobInterfaceType count, # type: int L2socket=L2socket # type: Optional[Type[SuperSocket]] ): # type: (...) -> Tuple[SuperSocket, _GlobInterfaceType] if isinstance(iface, SuperSocket): return iface, "iface%d" % count else: if not L2socket: iface = resolve_iface(iface or conf.iface) L2socket = iface.l2socket() return L2socket(iface=iface), iface
def __repr__(self): rtlst = [] for net, msk, gw, iface, cset, metric in self.routes: if_repr = resolve_iface(iface).description rtlst.append( ('%s/%i' % (net, msk), gw, if_repr, cset, str(metric))) return pretty_list( rtlst, [('Destination', 'Next Hop', "Iface", "Src candidates", "Metric") ], # noqa: E501 sortBy=1)
def srp(x, promisc=None, iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args, **kargs): """ Send and receive packets at layer 2 """ if iface is None and iface_hint is not None: iface = conf.route.route(iface_hint)[0] iface = resolve_iface(iface or conf.iface) s = iface.l2socket()(promisc=promisc, iface=iface, filter=filter, nofilter=nofilter, type=type) result = sndrcv(s, x, *args, **kargs) s.close() return result
def srp1flood(x, promisc=None, filter=None, iface=None, nofilter=0, *args, **kargs): # noqa: E501 """Flood and receive packets at layer 2 and return only the first answer :param prn: function applied to packets received :param verbose: set verbosity level :param nofilter: put 1 to avoid use of BPF filters :param filter: provide a BPF filter :param iface: listen answers only on the given interface """ iface = resolve_iface(iface or conf.iface) s = iface.l2socket()(promisc=promisc, filter=filter, nofilter=nofilter, iface=iface) # noqa: E501 ans, _ = sndrcvflood(s, x, *args, **kargs) s.close() if len(ans) > 0: return ans[0][1]
def __repr__(self): # type: () -> str rtlst = [] # type: List[Tuple[Union[str, List[str]], ...]] for net, msk, gw, iface, cset, metric in self.routes: if_repr = cast(str, resolve_iface(iface).description) rtlst.append(('%s/%i' % (net, msk), gw, if_repr, cset, str(metric))) return pretty_list(rtlst, [('Destination', 'Next Hop', "Iface", "Src candidates", "Metric")], # noqa: E501 sortBy=1)
def open_pcap(iface, *args, **kargs): """open_pcap: Windows routine for creating a pcap from an interface. This function is also responsible for detecting monitor mode. """ iface = resolve_iface(iface) iface_network_name = iface.network_name if not iface: raise Scapy_Exception( "Interface is invalid (no pcap match found) !") # Only check monitor mode when manually specified. # Checking/setting for monitor mode will slow down the process, and the # common is case is not to use monitor mode kw_monitor = kargs.get("monitor", None) if conf.use_npcap and kw_monitor is not None: monitored = iface.ismonitor() if kw_monitor is not monitored: # The monitor param is specified, and not matching the current # interface state iface.setmonitor(kw_monitor) return _orig_open_pcap(iface_network_name, *args, **kargs)
def _run(self, count=0, # type: int store=True, # type: bool offline=None, # type: Any quiet=False, # type: bool prn=None, # type: Optional[Callable[[Packet], Any]] lfilter=None, # type: Optional[Callable[[Packet], bool]] L2socket=None, # type: Optional[Type[SuperSocket]] timeout=None, # type: Optional[int] opened_socket=None, # type: Optional[SuperSocket] stop_filter=None, # type: Optional[Callable[[Packet], bool]] iface=None, # type: Optional[_GlobInterfaceType] started_callback=None, # type: Optional[Callable[[], Any]] session=None, # type: Optional[_GlobSessionType] session_kwargs={}, # type: Dict[str, Any] **karg # type: Any ): # type: (...) -> None self.running = True # Start main thread # instantiate session if not isinstance(session, DefaultSession): session = session or DefaultSession session = session(prn=prn, store=store, **session_kwargs) else: session.prn = prn session.store = store # sniff_sockets follows: {socket: label} sniff_sockets = {} # type: Dict[SuperSocket, _GlobInterfaceType] 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, str): # Single file offline = [offline] if isinstance(offline, list) and \ all(isinstance(elt, str) for elt in offline): # List of files sniff_sockets.update((PcapReader( fname if flt is None else tcpdump(fname, args=["-w", "-"], flt=flt, getfd=True, quiet=quiet) ), fname) for fname in offline) elif isinstance(offline, dict): # Dict of files sniff_sockets.update((PcapReader( fname if flt is None else tcpdump(fname, args=["-w", "-"], flt=flt, getfd=True, quiet=quiet) ), label) for fname, label in six.iteritems(offline)) elif isinstance(offline, (Packet, PacketList, list)): # Iterables (list of packets, PacketList..) offline = IterSocket(offline) sniff_sockets[offline if flt is None else PcapReader( tcpdump(offline, args=["-w", "-"], flt=flt, getfd=True, quiet=quiet) )] = offline else: # Other (file descriptors...) 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: # The _RL2 function resolves the L2socket of an iface _RL2 = lambda i: L2socket or resolve_iface(i).l2listen() # type: Callable[[_GlobInterfaceType], Callable[..., SuperSocket]] # noqa: E501 if isinstance(iface, list): sniff_sockets.update( (_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg), ifname) for ifname in iface ) elif isinstance(iface, dict): sniff_sockets.update( (_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg), iflabel) for ifname, iflabel in six.iteritems(iface) ) else: iface = iface or conf.iface sniff_sockets[_RL2(iface)(type=ETH_P_ALL, iface=iface, **karg)] = iface # Get select information from the sockets _main_socket = next(iter(sniff_sockets)) select_func = _main_socket.select 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 not nonblocking_socket: # select is blocking: Add special control socket from scapy.automaton import ObjectPipe close_pipe = ObjectPipe() sniff_sockets[close_pipe] = "control_socket" def stop_cb(): # type: () -> None if self.running: close_pipe.send(None) self.continue_sniff = False self.stop_cb = stop_cb else: # select is non blocking def stop_cb(): # type: () -> None self.continue_sniff = False self.stop_cb = stop_cb close_pipe = None 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 = select_func(list(sniff_sockets.keys()), remain) dead_sockets = [] for s in sockets: if s is close_pipe: break try: p = s.recv() 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 ex2: msg = " close() failed with '%s'" % ex2 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 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()
def get_if_raw_hwaddr(iface): iface = resolve_iface(iface) return ARPHDR_ETHER, mac2str(iface.mac)
def get_if_raw_addr(iff): """Return the raw IPv4 address of interface""" iff = resolve_iface(iff) if not iff.ip: return None return inet_pton(socket.AF_INET, iff.ip)
def __init__(self, iface=None, proto=socket.IPPROTO_IP, ttl=128, ipv6=False, promisc=True, **kwargs): from scapy.layers.inet import IP from scapy.layers.inet6 import IPv6 for kwarg in kwargs: warning("Dropping unsupported option: %s" % kwarg) af = socket.AF_INET6 if ipv6 else socket.AF_INET self.proto = proto if ipv6: from scapy.arch import get_if_addr6 self.host_ip6 = get_if_addr6(conf.iface) or "::1" if proto == socket.IPPROTO_IP: # We'll restrict ourselves to UDP, as TCP isn't bindable # on AF_INET6 self.proto = socket.IPPROTO_UDP # On Windows, with promisc=False, you won't get much self.ipv6 = ipv6 self.cls = IPv6 if ipv6 else IP self.promisc = promisc # Notes: # - IPPROTO_RAW only works to send packets. # - IPPROTO_IPV6 exists in MSDN docs, but using it will result in # no packets being received. Same for its options (IPV6_HDRINCL...) # However, using IPPROTO_IP with AF_INET6 will still receive # the IPv6 packets try: self.ins = socket.socket(af, socket.SOCK_RAW, self.proto) self.outs = socket.socket(af, socket.SOCK_RAW, socket.IPPROTO_RAW) except OSError as e: if e.errno == 10013: raise OSError("Windows native L3 Raw sockets are only " "usable as administrator ! " "Install Winpcap/Npcap to workaround !") raise self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30) self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30) # IOCTL Include IP headers self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) self.outs.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # set TTL self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl) self.outs.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl) # Bind on all ports iface = resolve_iface(iface) or conf.iface host = iface.ip if iface.ip else socket.gethostname() self.ins.bind((host, 0)) self.ins.setblocking(False) # Get as much data as possible: reduce what is cropped if ipv6: try: # Not all Windows versions self.ins.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_RECVTCLASS, 1) self.ins.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, 1) except (OSError, socket.error): pass else: try: # Not Windows XP self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_RECVDSTADDR, 1) except (OSError, socket.error): pass try: # Windows 10+ recent builds only self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_RECVTTL, 1) except (OSError, socket.error): pass if promisc: # IOCTL Receive all packets self.ins.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
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: iface = resolve_iface(iface or conf.iface) if L2socket is None: L2socket = iface.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 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 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()