def _in6_getifaddr(ifname): # type: (str) -> List[Tuple[str, int, str]] """ Returns a list of IPv6 addresses configured on the interface ifname. """ # Get the output of ifconfig try: f = os.popen("%s %s" % (conf.prog.ifconfig, ifname)) except OSError: log_runtime.warning("Failed to execute ifconfig.") return [] # Iterate over lines and extract IPv6 addresses ret = [] for line in f: if "inet6" in line: addr = line.rstrip().split(None, 2)[1] # The second element is the IPv6 address # noqa: E501 else: continue if '%' in line: # Remove the interface identifier if present addr = addr.split("%", 1)[0] # Check if it is a valid IPv6 address try: inet_pton(socket.AF_INET6, addr) except (socket.error, ValueError): continue # Get the scope and keep the address scope = in6_getscope(addr) ret.append((addr, scope, ifname)) f.close() return ret
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, replay_args=None, # noqa: E501 parse_results=False): """Send packets at layer 2 using tcpreplay for performance :param pps: packets per second :param mpbs: MBits per second :param realtime: use packet's timestamp, bending time with real-time value :param loop: number of times to process the packet list :param file_cache: cache packets in RAM instead of reading from disk at each iteration :param iface: output interface :param replay_args: List of additional tcpreplay args (List[str]) :param parse_results: Return a dictionary of information outputted by tcpreplay (default=False) :returns: stdout, stderr, command used """ if iface is None: iface = conf.iface argv = [conf.prog.tcpreplay, "--intf1=%s" % network_name(iface)] if pps is not None: argv.append("--pps=%i" % pps) elif mbps is not None: argv.append("--mbps=%f" % mbps) elif realtime is not None: argv.append("--multiplier=%f" % realtime) else: argv.append("--topspeed") if loop: argv.append("--loop=%i" % loop) if file_cache: argv.append("--preload-pcap") # Check for any additional args we didn't cover. if replay_args is not None: argv.extend(replay_args) f = get_temp_file() argv.append(f) wrpcap(f, x) results = None with ContextManagerSubprocess(conf.prog.tcpreplay): try: cmd = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except KeyboardInterrupt: log_interactive.info("Interrupted by user") except Exception: os.unlink(f) raise else: stdout, stderr = cmd.communicate() if stderr: log_runtime.warning(stderr.decode()) if parse_results: results = _parse_tcpreplay_result(stdout, stderr, argv) elif conf.verb > 2: log_runtime.info(stdout.decode()) os.unlink(f) return results
def _recv_raw(self, sock, x): """Internal function to receive a Packet, and process ancillary data. """ flags_len = socket.CMSG_LEN(4096) timestamp = None pkt, ancdata, flags, sa_ll = sock.recvmsg(x, flags_len) if not pkt: return pkt, sa_ll for cmsg_lvl, cmsg_type, cmsg_data in ancdata: # Check available ancillary data if (cmsg_lvl == SOL_PACKET and cmsg_type == PACKET_AUXDATA): # Parse AUXDATA auxdata = tpacket_auxdata.from_buffer_copy(cmsg_data) if auxdata.tp_vlan_tci != 0 or \ auxdata.tp_status & TP_STATUS_VLAN_VALID: # Insert VLAN tag tag = struct.pack("!HH", ETH_P_8021Q, auxdata.tp_vlan_tci) pkt = pkt[:12] + tag + pkt[12:] elif cmsg_lvl == socket.SOL_SOCKET and \ cmsg_type == SO_TIMESTAMPNS: length = len(cmsg_data) if length == 16: # __kernel_timespec tmp = struct.unpack("ll", cmsg_data) elif length == 8: # timespec tmp = struct.unpack("ii", cmsg_data) else: log_runtime.warning("Unknown timespec format.. ?!") continue timestamp = tmp[0] + tmp[1] * 1e-9 return pkt, sa_ll, timestamp
def check_arp_reply(self, pkt): data = parse_data_pkt(pkt, self.tk) try: data_clear = check_MIC_ICV(data, self.mic_sta_to_ap, pkt.addr2, pkt.addr3) except (ICVError, MICError): return decoded_pkt = LLC(data_clear) log_runtime.debug(hexdump(decoded_pkt, dump=True)) log_runtime.debug(repr(decoded_pkt)) self.deal_common_pkt(decoded_pkt) if ARP not in decoded_pkt: return # ARP.op 2: is-at if decoded_pkt[ARP].op == 2 and \ decoded_pkt[ARP].psrc == self.arp_target_ip and \ decoded_pkt[ARP].pdst == self.arp_source_ip: # Got the expected ARP if self.krack_state & 4 == 0: # First time, normal behavior log_runtime.info("Got ARP reply, this is normal") self.krack_state |= 4 log_runtime.info("Trying to trigger CVE-2017-13080") raise self.RENEW_GTK() else: # Second time, the packet has been accepted twice! log_runtime.warning("Broadcast packet accepted twice!! " "(CVE-2017-13080)")
def prn_send(pkt): try: sendsock = peers[pkt.sniffed_on] except KeyError: return if pkt.sniffed_on in xfrms: try: newpkt = xfrms[pkt.sniffed_on](pkt) except: log_runtime.warning( 'Exception in transformation function for packet [%s] ' 'received on %s -- dropping', pkt.summary(), pkt.sniffed_on, exc_info=True ) return else: if newpkt is True: newpkt = pkt.original elif not newpkt: return else: newpkt = pkt.original try: sendsock.send(newpkt) except: log_runtime.warning('Cannot forward packet [%s] received on %s', pkt.summary(), pkt.sniffed_on, exc_info=True)
def prn_send(pkt): try: sendsock = peers[pkt.sniffed_on] except KeyError: return if pkt.sniffed_on in xfrms: try: newpkt = xfrms[pkt.sniffed_on](pkt) except: log_runtime.warning( 'Exception in transformation function for packet [%s] ' 'received on %s -- dropping', pkt.summary(), pkt.sniffed_on, exc_info=True ) return else: if newpkt is True: newpkt = pkt.original elif not newpkt: return else: newpkt = pkt.original try: sendsock.send(newpkt) except: log_runtime.warning('Cannot forward packet [%s] received on %s', pkt.summary(), pkt.sniffed_on, exc_info=True)
def prn_send(pkt): # type: (Packet) -> None try: sendsock = peers[pkt.sniffed_on or ""] except KeyError: return if pkt.sniffed_on in xfrms: try: _newpkt = xfrms[pkt.sniffed_on](pkt) except Exception: log_runtime.warning( 'Exception in transformation function for packet [%s] ' 'received on %s -- dropping', pkt.summary(), pkt.sniffed_on, exc_info=True ) return else: if isinstance(_newpkt, bool): if not _newpkt: return newpkt = pkt else: newpkt = _newpkt else: newpkt = pkt try: sendsock.send(newpkt) except Exception: log_runtime.warning('Cannot forward packet [%s] received on %s', pkt.summary(), pkt.sniffed_on, exc_info=True)
def check_arp_reply(self, pkt): data = parse_data_pkt(pkt, self.tk) try: data_clear = check_MIC_ICV(data, self.mic_sta_to_ap, pkt.addr2, pkt.addr3) except (ICVError, MICError): return decoded_pkt = LLC(data_clear) log_runtime.debug(hexdump(decoded_pkt, dump=True)) log_runtime.debug(repr(decoded_pkt)) self.deal_common_pkt(decoded_pkt) if ARP not in decoded_pkt: return # ARP.op 2: is-at if decoded_pkt[ARP].op == 2 and \ decoded_pkt[ARP].psrc == self.arp_target_ip and \ decoded_pkt[ARP].pdst == self.arp_source_ip: # Got the expected ARP if self.krack_state & 4 == 0: # First time, normal behavior log_runtime.info("Got ARP reply, this is normal") self.krack_state |= 4 log_runtime.info("Trying to trigger CVE-2017-13080") raise self.RENEW_GTK() else: # Second time, the packet has been accepted twice! log_runtime.warning("Broadcast packet accepted twice!! " "(CVE-2017-13080)")
def l2_register_l3_arp(l2, l3): # type: (Type[Packet], Type[Packet]) -> Optional[str] # TODO: support IPv6? if l3.plen == 4: return getmacbyip(l3.pdst) log_runtime.warning( "Unable to guess L2 MAC address from an ARP packet with a " "non-IPv4 pdst. Provide it manually !") return None
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, replay_args=None, # noqa: E501 parse_results=False): """Send packets at layer 2 using tcpreplay for performance pps: packets per second mpbs: MBits per second realtime: use packet's timestamp, bending time with real-time value loop: number of times to process the packet list file_cache: cache packets in RAM instead of reading from disk at each iteration # noqa: E501 iface: output interface replay_args: List of additional tcpreplay args (List[str]) parse_results: Return a dictionary of information outputted by tcpreplay (default=False) # noqa: E501 :returns stdout, stderr, command used""" if iface is None: iface = conf.iface argv = [conf.prog.tcpreplay, "--intf1=%s" % iface] if pps is not None: argv.append("--pps=%i" % pps) elif mbps is not None: argv.append("--mbps=%f" % mbps) elif realtime is not None: argv.append("--multiplier=%f" % realtime) else: argv.append("--topspeed") if loop: argv.append("--loop=%i" % loop) if file_cache: argv.append("--preload-pcap") # Check for any additional args we didn't cover. if replay_args is not None: argv.extend(replay_args) f = get_temp_file() argv.append(f) wrpcap(f, x) results = None try: log_runtime.info(argv) with subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as cmd: # noqa: E501 stdout, stderr = cmd.communicate() log_runtime.info(stdout) log_runtime.warning(stderr) if parse_results: results = _parse_tcpreplay_result(stdout, stderr, argv) except KeyboardInterrupt: log_interactive.info("Interrupted by user") except Exception: if conf.interactive: log_interactive.error("Cannot execute [%s]", argv[0], exc_info=True) # noqa: E501 else: raise finally: os.unlink(f) return results
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, replay_args=None, # noqa: E501 parse_results=False): """Send packets at layer 2 using tcpreplay for performance pps: packets per second mpbs: MBits per second realtime: use packet's timestamp, bending time with real-time value loop: number of times to process the packet list file_cache: cache packets in RAM instead of reading from disk at each iteration # noqa: E501 iface: output interface replay_args: List of additional tcpreplay args (List[str]) parse_results: Return a dictionary of information outputted by tcpreplay (default=False) # noqa: E501 :returns stdout, stderr, command used""" if iface is None: iface = conf.iface argv = [conf.prog.tcpreplay, "--intf1=%s" % iface] if pps is not None: argv.append("--pps=%i" % pps) elif mbps is not None: argv.append("--mbps=%f" % mbps) elif realtime is not None: argv.append("--multiplier=%f" % realtime) else: argv.append("--topspeed") if loop: argv.append("--loop=%i" % loop) if file_cache: argv.append("--preload-pcap") # Check for any additional args we didn't cover. if replay_args is not None: argv.extend(replay_args) f = get_temp_file() argv.append(f) wrpcap(f, x) results = None with ContextManagerSubprocess("sendpfast()", conf.prog.tcpreplay): try: cmd = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except KeyboardInterrupt: log_interactive.info("Interrupted by user") except Exception: os.unlink(f) raise else: stdout, stderr = cmd.communicate() if stderr: log_runtime.warning(stderr.decode()) if parse_results: results = _parse_tcpreplay_result(stdout, stderr, argv) elif conf.verb > 2: log_runtime.info(stdout.decode()) os.unlink(f) return results
def prn_send(pkt): try: sendsock = peers[pkt.sniffed_on] except KeyError: return try: sendsock.send(pkt.original) except: log_runtime.warning('Cannot forward packet [%s] received from %s', pkt.summary(), pkt.sniffed_on, exc_info=True)
def _recv_raw(self, sock, x): # type: (socket.socket, int) -> Tuple[bytes, Any, Optional[float]] """Internal function to receive a Packet, and process ancillary data. """ timestamp = None if not self.auxdata_available: pkt, _, _, sa_ll = sock.recvmsg(x) return pkt, sa_ll, timestamp flags_len = socket.CMSG_LEN(4096) pkt, ancdata, flags, sa_ll = sock.recvmsg(x, flags_len) if not pkt: return pkt, sa_ll, timestamp for cmsg_lvl, cmsg_type, cmsg_data in ancdata: # Check available ancillary data if (cmsg_lvl == SOL_PACKET and cmsg_type == PACKET_AUXDATA): # Parse AUXDATA try: auxdata = tpacket_auxdata.from_buffer_copy(cmsg_data) except ValueError: # Note: according to Python documentation, recvmsg() # can return a truncated message. A ValueError # exception likely indicates that Auxiliary # Data is not supported by the Linux kernel. return pkt, sa_ll, timestamp if auxdata.tp_vlan_tci != 0 or \ auxdata.tp_status & TP_STATUS_VLAN_VALID: # Insert VLAN tag tpid = ETH_P_8021Q if auxdata.tp_status & TP_STATUS_VLAN_TPID_VALID: tpid = auxdata.tp_vlan_tpid tag = struct.pack( "!HH", tpid, auxdata.tp_vlan_tci ) pkt = pkt[:12] + tag + pkt[12:] elif cmsg_lvl == socket.SOL_SOCKET and \ cmsg_type == SO_TIMESTAMPNS: length = len(cmsg_data) if length == 16: # __kernel_timespec tmp = struct.unpack("ll", cmsg_data) elif length == 8: # timespec tmp = struct.unpack("ii", cmsg_data) else: log_runtime.warning("Unknown timespec format.. ?!") continue timestamp = tmp[0] + tmp[1] * 1e-9 return pkt, sa_ll, timestamp
def send_auth_response(self, pkt): # Save client MAC for later self.client = pkt.addr2 log_runtime.warning("Client %s connected!", self.client) # Launch DHCP Server self.dhcp_server.run() rep = RadioTap() rep /= Dot11(addr1=self.client, addr2=self.mac, addr3=self.mac) rep /= Dot11Auth(seqnum=2, algo=pkt[Dot11Auth].algo, status=pkt[Dot11Auth].status) self.send(rep)
def bridge_and_sniff(if1, if2, prn=None, L2socket=None, *args, **kargs): """Forward traffic between interfaces if1 and if2, sniff and return the exchanged packets. Arguments: if1, if2: the interfaces to use The other arguments are the same than for the function sniff(), except for opened_socket, offline and iface that are ignored. See help(sniff) for more. """ for arg in ['opened_socket', 'offline', 'iface']: if arg in kargs: log_runtime.warning( "Argument %s cannot be used in " "bridge_and_sniff() -- ignoring it.", arg) del kargs[arg] if L2socket is None: L2socket = conf.L2socket s1 = L2socket(iface=if1) s2 = L2socket(iface=if2) peers = {if1: s2, if2: s1} def prn_send(pkt): try: sendsock = peers[pkt.sniffed_on] except KeyError: return try: sendsock.send(pkt.original) except: log_runtime.warning('Cannot forward packet [%s] received from %s', pkt.summary(), pkt.sniffed_on, exc_info=True) if prn is None: prn = prn_send else: prn_orig = prn def prn(pkt): prn_send(pkt) return prn_orig(pkt) return sniff(opened_socket={s1: if1, s2: if2}, prn=prn, *args, **kargs)
def in6_getifaddr(): # type: () -> List[Tuple[str, int, str]] """ Returns a list of 3-tuples of the form (addr, scope, iface) where 'addr' is the address of scope 'scope' associated to the interface 'iface'. This is the list of all addresses of all interfaces available on the system. """ # List all network interfaces if OPENBSD or SOLARIS: if SOLARIS: cmd = "%s -a6" else: cmd = "%s" try: f = os.popen(cmd % conf.prog.ifconfig) except OSError: log_runtime.warning("Failed to execute ifconfig.") return [] # Get the list of network interfaces splitted_line = [] for line in f: if "flags" in line: iface = line.split()[0].rstrip(':') splitted_line.append(iface) else: # FreeBSD, NetBSD or Darwin try: f = os.popen("%s -l" % conf.prog.ifconfig) except OSError: log_runtime.warning("Failed to execute ifconfig.") return [] # Get the list of network interfaces splitted_line = f.readline().rstrip().split() ret = [] for i in splitted_line: ret += _in6_getifaddr(i) f.close() return ret
def send(self, x): sx = raw(x) if hasattr(x, "sent_time"): x.sent_time = time.time() if self.mode_tun: try: proto = conf.l3types[type(x)] except KeyError: log_runtime.warning( "Cannot find layer 3 protocol value to send %s in " "conf.l3types, using 0", x.name if hasattr(x, "name") else type(x).__name__ ) proto = 0 sx = struct.pack('!HH', 0, proto) + sx try: os.write(self.outs.fileno(), sx) except socket.error: log_runtime.error("%s send", self.__class__.__name__, exc_info=True) # noqa: E501
def send(self, x): sx = raw(x) if hasattr(x, "sent_time"): x.sent_time = time.time() if self.mode_tun: try: proto = conf.l3types[type(x)] except KeyError: log_runtime.warning( "Cannot find layer 3 protocol value to send %s in " "conf.l3types, using 0", x.name if hasattr(x, "name") else type(x).__name__ ) proto = 0 sx = struct.pack('!HH', 0, proto) + sx try: os.write(self.outs.fileno(), sx) except socket.error: log_runtime.error("%s send", self.__class__.__name__, exc_info=True)
def send_arp_req(self): if self.krack_state & 4 == 0: # Set the address for future uses self.arp_target_ip = self.dhcp_server.leases.get(self.client, self.arp_target_ip) assert self.arp_target_ip is not None # Send the first ARP requests, for control test log_runtime.info("Send ARP who-was from '%s' to '%s'", self.arp_source_ip, self.arp_target_ip) arp_pkt = self.send_wpa_to_group( LLC()/SNAP()/ARP(op="who-has", psrc=self.arp_source_ip, pdst=self.arp_target_ip, hwsrc=self.mac), dest='ff:ff:ff:ff:ff:ff', ) self.arp_sent.append(arp_pkt) else: if self.arp_to_send < len(self.arp_sent): # Re-send the ARP requests already sent self.send(self.arp_sent[self.arp_to_send]) self.arp_to_send += 1 else: # Re-send GTK self.arp_to_send = 0 self.arp_retry += 1 log_runtime.info("Trying to trigger CVE-2017-13080 %d/%d", self.arp_retry, self.ARP_MAX_RETRY) if self.arp_retry > self.ARP_MAX_RETRY: # We retries 100 times to send GTK, then already sent ARPs log_runtime.warning("Client is likely not vulnerable to " "CVE-2017-13080") raise self.EXIT() raise self.RENEW_GTK()
def extract_iv(self, pkt): # Get IV TSC, _, _ = parse_TKIP_hdr(pkt) iv = TSC[0] | (TSC[1] << 8) | (TSC[2] << 16) | (TSC[3] << 24) | \ (TSC[4] << 32) | (TSC[5] << 40) log_runtime.info("Got a packet with IV: %s", hex(iv)) if self.last_iv is None: self.last_iv = iv else: if iv <= self.last_iv: log_runtime.warning("IV re-use!! Client seems to be " "vulnerable to handshake 3/4 replay " "(CVE-2017-13077)" ) data_clear = None # Normal decoding data = parse_data_pkt(pkt, self.tk) try: data_clear = check_MIC_ICV(data, self.mic_sta_to_ap, pkt.addr2, pkt.addr3) except (ICVError, MICError): pass # Decoding with a 0's TK if data_clear is None: data = parse_data_pkt(pkt, "\x00" * len(self.tk)) try: mic_key = "\x00" * len(self.mic_sta_to_ap) data_clear = check_MIC_ICV(data, mic_key, pkt.addr2, pkt.addr3) log_runtime.warning("Client has installed an all zero " "encryption key (TK)!!") except (ICVError, MICError): pass if data_clear is None: log_runtime.warning("Unable to decode the packet, something went " "wrong") log_runtime.debug(hexdump(pkt, dump=True)) self.deal_common_pkt(pkt) return log_runtime.debug(hexdump(data_clear, dump=True)) pkt = LLC(data_clear) log_runtime.debug(repr(pkt)) self.deal_common_pkt(pkt)
def warning(x): log_runtime.warning(x)
def warning(x): log_runtime.warning(x)
def sniff(count=0, store=True, offline=None, prn=None, lfilter=None, L2socket=None, timeout=None, opened_socket=None, stop_filter=None, iface=None, started_callback=None, *arg, **karg): """Sniff packets and return a list of packets. Args: count: number of packets to capture. 0 means infinity. store: whether to store sniffed packets or discard them prn: function to apply to each packet. If something is returned, it is displayed. --Ex: prn = lambda x: x.summary() filter: BPF filter to apply. lfilter: Python function applied to each packet to determine if further action may be done. --Ex: lfilter = lambda x: x.haslayer(Padding) offline: PCAP file (or list of PCAP files) to read packets from, instead of sniffing them timeout: stop sniffing after a given time (default: None). L2socket: use the provided L2socket (default: use conf.L2listen). opened_socket: provide an object (or a list of objects) ready to use .recv() on. stop_filter: Python function applied to each packet to determine if we have to stop the capture after this packet. --Ex: stop_filter = lambda x: x.haslayer(TCP) iface: interface or list of interfaces (default: None for sniffing on all interfaces). monitor: use monitor mode. May not be available on all OS started_callback: called as soon as the sniffer starts sniffing (default: None). The iface, offline and opened_socket parameters can be either an element, a list of elements, or a dict object mapping an element to a label (see examples below). Examples: >>> sniff(filter="arp") >>> sniff(lfilter=lambda pkt: ARP in pkt) >>> sniff(iface="eth0", prn=Packet.summary) >>> sniff(iface=["eth0", "mon0"], ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, ... pkt.summary())) >>> sniff(iface={"eth0": "Ethernet", "mon0": "Wifi"}, ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, ... pkt.summary())) """ c = 0 sniff_sockets = {} # socket: label dict 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): sniff_sockets.update((PcapReader( fname if flt is None else tcpdump(fname, args=["-w", "-", 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], getfd=True) ), label) for fname, label in six.iteritems(offline)) else: sniff_sockets[PcapReader( offline if flt is None else tcpdump(offline, args=["-w", "-", flt], getfd=True) )] = 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 lst = [] if timeout is not None: stoptime = time.time() + timeout remain = None # Get select information from the sockets _main_socket = next(iter(sniff_sockets)) read_allowed_exceptions = _main_socket.read_allowed_exceptions select_func = _main_socket.select # 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") # Now let's build the select function, used later on _select = lambda sockets, remain: select_func(sockets, remain)[0] try: if started_callback: started_callback() while sniff_sockets: if timeout is not None: remain = stoptime - time.time() if remain <= 0: break for s in _select(sniff_sockets, remain): try: p = s.recv() except socket.error as ex: log_runtime.warning("Socket %s failed with '%s' and thus" " will be ignored" % (s, ex)) del sniff_sockets[s] continue except read_allowed_exceptions: continue if p is None: try: if s.promisc: continue except AttributeError: pass del sniff_sockets[s] break if lfilter and not lfilter(p): continue p.sniffed_on = sniff_sockets[s] if store: lst.append(p) c += 1 if prn: r = prn(p) if r is not None: print(r) if stop_filter and stop_filter(p): sniff_sockets = [] break if 0 < count <= c: sniff_sockets = [] break except KeyboardInterrupt: pass if opened_socket is None: for s in sniff_sockets: s.close() return plist.PacketList(lst, "Sniffed")
def bridge_and_sniff(if1, # type: _GlobInterfaceType if2, # type: _GlobInterfaceType xfrm12=None, # type: Optional[Callable[[Packet], Union[Packet, bool]]] # noqa: E501 xfrm21=None, # type: Optional[Callable[[Packet], Union[Packet, bool]]] # noqa: E501 prn=None, # type: Optional[Callable[[Packet], Any]] L2socket=None, # type: Optional[Type[SuperSocket]] *args, # type: Any **kargs # type: Any ): # type: (...) -> PacketList """Forward traffic between interfaces if1 and if2, sniff and return the exchanged packets. :param if1: the interfaces to use (interface names or opened sockets). :param if2: :param xfrm12: a function to call when forwarding a packet from if1 to if2. If it returns True, the packet is forwarded as it. If it returns False or None, the packet is discarded. If it returns a packet, this packet is forwarded instead of the original packet one. :param xfrm21: same as xfrm12 for packets forwarded from if2 to if1. The other arguments are the same than for the function sniff(), except for offline, opened_socket and iface that are ignored. See help(sniff) for more. """ for arg in ['opened_socket', 'offline', 'iface']: if arg in kargs: log_runtime.warning("Argument %s cannot be used in " "bridge_and_sniff() -- ignoring it.", arg) del kargs[arg] 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 sckt1, if1 = _init_socket(if1, 1) sckt2, if2 = _init_socket(if2, 2) peers = {if1: sckt2, if2: sckt1} xfrms = {} if xfrm12 is not None: xfrms[if1] = xfrm12 if xfrm21 is not None: xfrms[if2] = xfrm21 def prn_send(pkt): # type: (Packet) -> None try: sendsock = peers[pkt.sniffed_on or ""] except KeyError: return if pkt.sniffed_on in xfrms: try: _newpkt = xfrms[pkt.sniffed_on](pkt) except Exception: log_runtime.warning( 'Exception in transformation function for packet [%s] ' 'received on %s -- dropping', pkt.summary(), pkt.sniffed_on, exc_info=True ) return else: if isinstance(_newpkt, bool): if not _newpkt: return newpkt = pkt else: newpkt = _newpkt else: newpkt = pkt try: sendsock.send(newpkt) except Exception: log_runtime.warning('Cannot forward packet [%s] received on %s', pkt.summary(), pkt.sniffed_on, exc_info=True) if prn is None: prn = prn_send else: prn_orig = prn def prn(pkt): # type: (Packet) -> Any prn_send(pkt) return prn_orig(pkt) return sniff(opened_socket={sckt1: if1, sckt2: if2}, prn=prn, *args, **kargs)
def run(self, *args, **kwargs): log_runtime.warning("AP started with ESSID: %s, BSSID: %s", self.ssid, self.mac) super(KrackAP, self).run(*args, **kwargs)
def bridge_and_sniff(if1, if2, xfrm12=None, xfrm21=None, prn=None, L2socket=None, *args, **kargs): """Forward traffic between interfaces if1 and if2, sniff and return the exchanged packets. Arguments: if1, if2: the interfaces to use (interface names or opened sockets). xfrm12: a function to call when forwarding a packet from if1 to if2. If it returns True, the packet is forwarded as it. If it returns False or None, the packet is discarded. If it returns a packet, this packet is forwarded instead of the original packet one. xfrm21: same as xfrm12 for packets forwarded from if2 to if1. The other arguments are the same than for the function sniff(), except for offline, opened_socket and iface that are ignored. See help(sniff) for more. """ for arg in ['opened_socket', 'offline', 'iface']: if arg in kargs: log_runtime.warning("Argument %s cannot be used in " "bridge_and_sniff() -- ignoring it.", arg) del kargs[arg] def _init_socket(iface, count): if isinstance(iface, SuperSocket): return iface, "iface%d" % count else: return (L2socket or conf.L2socket)(iface=iface), iface sckt1, if1 = _init_socket(if1, 1) sckt2, if2 = _init_socket(if2, 2) peers = {if1: sckt2, if2: sckt1} xfrms = {} if xfrm12 is not None: xfrms[if1] = xfrm12 if xfrm21 is not None: xfrms[if2] = xfrm21 def prn_send(pkt): try: sendsock = peers[pkt.sniffed_on] except KeyError: return if pkt.sniffed_on in xfrms: try: newpkt = xfrms[pkt.sniffed_on](pkt) except: log_runtime.warning( 'Exception in transformation function for packet [%s] ' 'received on %s -- dropping', pkt.summary(), pkt.sniffed_on, exc_info=True ) return else: if newpkt is True: newpkt = pkt.original elif not newpkt: return else: newpkt = pkt.original try: sendsock.send(newpkt) except: log_runtime.warning('Cannot forward packet [%s] received on %s', pkt.summary(), pkt.sniffed_on, exc_info=True) if prn is None: prn = prn_send else: prn_orig = prn def prn(pkt): prn_send(pkt) return prn_orig(pkt) return sniff(opened_socket={sckt1: if1, sckt2: if2}, prn=prn, *args, **kargs)
def sniff(count=0, store=True, offline=None, prn=None, lfilter=None, L2socket=None, timeout=None, opened_socket=None, stop_filter=None, iface=None, started_callback=None, *arg, **karg): """Sniff packets and return a list of packets. Args: count: number of packets to capture. 0 means infinity. store: whether to store sniffed packets or discard them prn: function to apply to each packet. If something is returned, it is displayed. --Ex: prn = lambda x: x.summary() filter: BPF filter to apply. lfilter: Python function applied to each packet to determine if further action may be done. --Ex: lfilter = lambda x: x.haslayer(Padding) offline: PCAP file (or list of PCAP files) to read packets from, instead of sniffing them timeout: stop sniffing after a given time (default: None). L2socket: use the provided L2socket (default: use conf.L2listen). opened_socket: provide an object (or a list of objects) ready to use .recv() on. stop_filter: Python function applied to each packet to determine if we have to stop the capture after this packet. --Ex: stop_filter = lambda x: x.haslayer(TCP) iface: interface or list of interfaces (default: None for sniffing on all interfaces). monitor: use monitor mode. May not be available on all OS started_callback: called as soon as the sniffer starts sniffing (default: None). The iface, offline and opened_socket parameters can be either an element, a list of elements, or a dict object mapping an element to a label (see examples below). Examples: >>> sniff(filter="arp") >>> sniff(lfilter=lambda pkt: ARP in pkt) >>> sniff(iface="eth0", prn=Packet.summary) >>> sniff(iface=["eth0", "mon0"], ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, ... pkt.summary())) >>> sniff(iface={"eth0": "Ethernet", "mon0": "Wifi"}, ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, ... pkt.summary())) """ c = 0 sniff_sockets = {} # socket: label dict 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): sniff_sockets.update((PcapReader(fname if flt is None else tcpdump( fname, args=["-w", "-", 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], getfd=True)), label) for fname, label in six.iteritems(offline)) else: sniff_sockets[PcapReader(offline if flt is None else tcpdump( offline, args=["-w", "-", flt], getfd=True))] = 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 lst = [] if timeout is not None: stoptime = time.time() + timeout remain = None # Get select information from the sockets _main_socket = next(iter(sniff_sockets)) read_allowed_exceptions = _main_socket.read_allowed_exceptions select_func = _main_socket.select # 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") # Now let's build the select function, used later on _select = lambda sockets, remain: select_func(sockets, remain)[0] try: if started_callback: started_callback() while sniff_sockets: if timeout is not None: remain = stoptime - time.time() if remain <= 0: break for s in _select(sniff_sockets, remain): try: p = s.recv() except socket.error as ex: log_runtime.warning("Socket %s failed with '%s' and thus" " will be ignored" % (s, ex)) del sniff_sockets[s] continue except read_allowed_exceptions: continue if p is None: try: if s.promisc: continue except AttributeError: pass del sniff_sockets[s] break if lfilter and not lfilter(p): continue p.sniffed_on = sniff_sockets[s] if store: lst.append(p) c += 1 if prn: r = prn(p) if r is not None: print(r) if stop_filter and stop_filter(p): sniff_sockets = [] break if 0 < count <= c: sniff_sockets = [] break except KeyboardInterrupt: pass if opened_socket is None: for s in sniff_sockets: s.close() return plist.PacketList(lst, "Sniffed")
def bridge_and_sniff(if1, if2, xfrm12=None, xfrm21=None, prn=None, L2socket=None, *args, **kargs): """Forward traffic between interfaces if1 and if2, sniff and return the exchanged packets. Arguments: if1, if2: the interfaces to use (interface names or opened sockets). xfrm12: a function to call when forwarding a packet from if1 to if2. If it returns True, the packet is forwarded as it. If it returns False or None, the packet is discarded. If it returns a packet, this packet is forwarded instead of the original packet one. xfrm21: same as xfrm12 for packets forwarded from if2 to if1. The other arguments are the same than for the function sniff(), except for offline, opened_socket and iface that are ignored. See help(sniff) for more. """ for arg in ['opened_socket', 'offline', 'iface']: if arg in kargs: log_runtime.warning("Argument %s cannot be used in " "bridge_and_sniff() -- ignoring it.", arg) del kargs[arg] def _init_socket(iface, count): if isinstance(iface, SuperSocket): return iface, "iface%d" % count else: return (L2socket or conf.L2socket)(iface=iface), iface sckt1, if1 = _init_socket(if1, 1) sckt2, if2 = _init_socket(if2, 2) peers = {if1: sckt2, if2: sckt1} xfrms = {} if xfrm12 is not None: xfrms[if1] = xfrm12 if xfrm21 is not None: xfrms[if2] = xfrm21 def prn_send(pkt): try: sendsock = peers[pkt.sniffed_on] except KeyError: return if pkt.sniffed_on in xfrms: try: newpkt = xfrms[pkt.sniffed_on](pkt) except: log_runtime.warning( 'Exception in transformation function for packet [%s] ' 'received on %s -- dropping', pkt.summary(), pkt.sniffed_on, exc_info=True ) return else: if newpkt is True: newpkt = pkt.original elif not newpkt: return else: newpkt = pkt.original try: sendsock.send(newpkt) except: log_runtime.warning('Cannot forward packet [%s] received on %s', pkt.summary(), pkt.sniffed_on, exc_info=True) if prn is None: prn = prn_send else: prn_orig = prn def prn(pkt): prn_send(pkt) return prn_orig(pkt) return sniff(opened_socket={sckt1: if1, sckt2: if2}, prn=prn, *args, **kargs)
def log_warning(): if conf.conf.interactive: log_runtime.warning( "Function not available (winpcap is not installed)") else: raise ImportError("Function not available (winpcap is not installed)")
def log_warning(): if conf.conf.interactive: log_runtime.warning("Function not available (winpcap is not installed)") else: raise ImportError("Function not available (winpcap is not installed)")
def run(self, *args, **kwargs): log_runtime.warning("AP started with ESSID: %s, BSSID: %s", self.ssid, self.mac) super(KrackAP, self).run(*args, **kwargs)