def _handle_packet(packet, result): from scapy.all import RadioTap, Dot11Elt, Dot11Beacon, rdpcap, Scapy_Exception, Dot11, Dot11ProbeResp, Dot11AssoReq, \ Dot11ReassoReq, Dot11EltRSN, Dot11EltVendorSpecific, Dot11EltMicrosoftWPA """ Analyze each packet and extract the data from Dot11 layers """ if hasattr(packet, 'cap') and 'privacy' in packet.cap: # packet is encrypted if 'encryption' not in result: result['encryption'] = set() if packet.haslayer(Dot11Beacon): if packet.haslayer(Dot11Beacon)\ or packet.haslayer(Dot11ProbeResp)\ or packet.haslayer(Dot11AssoReq)\ or packet.haslayer(Dot11ReassoReq): if 'bssid' not in result and hasattr(packet[Dot11], 'addr3'): result['bssid'] = packet[Dot11].addr3 if 'essid' not in result and hasattr(packet[Dot11Elt], 'info'): result['essid'] = packet[Dot11Elt].info if 'channel' not in result and hasattr(packet[Dot11Elt:3], 'info'): result['channel'] = int(ord(packet[Dot11Elt:3].info)) if packet.haslayer(RadioTap): if 'rssi' not in result and hasattr(packet[RadioTap], 'dBm_AntSignal'): result['rssi'] = packet[RadioTap].dBm_AntSignal if 'channel' not in result and hasattr(packet[RadioTap], 'ChannelFrequency'): result['channel'] = freq_to_channel( packet[RadioTap].ChannelFrequency) # see: https://fossies.org/linux/scapy/scapy/layers/dot11.py if packet.haslayer(Dot11EltRSN): if hasattr(packet[Dot11EltRSN], 'akm_suites'): auth = AKMSUITE_TYPES.get(packet[Dot11EltRSN].akm_suites[0].suite) result['encryption'].add(f"WPA2/{auth}") else: result['encryption'].add("WPA2") if packet.haslayer(Dot11EltVendorSpecific)\ and (packet.haslayer(Dot11EltMicrosoftWPA) or packet.info.startswith(b'\x00P\xf2\x01\x01\x00')): if hasattr(packet, 'akm_suites'): auth = AKMSUITE_TYPES.get(packet.akm_suites[0].suite) result['encryption'].add(f"WPA2/{auth}") else: result['encryption'].add("WPA2") # end see return result
def _parse_identity(self, radio, dot11, dot11elt): payload = b'' while dot11elt: payload += dot11elt.info dot11elt = dot11elt.payload.getlayer(Dot11Elt) if payload != b'': adv = json.loads(payload) self._on_advertisement( \ dot11.addr3, wifi.freq_to_channel(radio.Channel), radio.dBm_AntSignal, adv)
def extract_from_pcap(path, fields): """ Search in pcap-file for specified information path: Path to pcap file fields: Array of fields that should be extracted If a field is not found, FieldNotFoundError is raised """ results = dict() for field in fields: if not isinstance(field, WifiInfo): raise TypeError("Invalid field") subtypes = set() if field == WifiInfo.BSSID: from scapy.all import Dot11Beacon, Dot11ProbeResp, Dot11AssoReq, Dot11ReassoReq, Dot11, sniff subtypes.add('beacon') bpf_filter = " or ".join([f"wlan type mgt subtype {subtype}" for subtype in subtypes]) packets = sniff(offline=path, filter=bpf_filter) try: for packet in packets: if packet.haslayer(Dot11Beacon): if hasattr(packet[Dot11], 'addr3'): results[field] = packet[Dot11].addr3 break else: # magic raise FieldNotFoundError("Could not find field [BSSID]") except Exception: raise FieldNotFoundError("Could not find field [BSSID]") elif field == WifiInfo.ESSID: from scapy.all import Dot11Beacon, Dot11ReassoReq, Dot11AssoReq, Dot11, sniff, Dot11Elt subtypes.add('beacon') subtypes.add('assoc-req') subtypes.add('reassoc-req') bpf_filter = " or ".join([f"wlan type mgt subtype {subtype}" for subtype in subtypes]) packets = sniff(offline=path, filter=bpf_filter) try: for packet in packets: if packet.haslayer(Dot11Elt) and hasattr(packet[Dot11Elt], 'info'): results[field] = packet[Dot11Elt].info.decode('utf-8') break else: # magic raise FieldNotFoundError("Could not find field [ESSID]") except Exception: raise FieldNotFoundError("Could not find field [ESSID]") elif field == WifiInfo.ENCRYPTION: from scapy.all import Dot11Beacon, sniff subtypes.add('beacon') bpf_filter = " or ".join([f"wlan type mgt subtype {subtype}" for subtype in subtypes]) packets = sniff(offline=path, filter=bpf_filter) try: for packet in packets: if packet.haslayer(Dot11Beacon) and hasattr(packet[Dot11Beacon], 'network_stats'): stats = packet[Dot11Beacon].network_stats() if 'crypto' in stats: results[field] = stats['crypto'] # set with encryption types break else: # magic raise FieldNotFoundError("Could not find field [ENCRYPTION]") except Exception: raise FieldNotFoundError("Could not find field [ENCRYPTION]") elif field == WifiInfo.CHANNEL: from scapy.all import sniff, RadioTap from pwnagotchi.mesh.wifi import freq_to_channel packets = sniff(offline=path, count=1) try: results[field] = freq_to_channel(packets[0][RadioTap].ChannelFrequency) except Exception: raise FieldNotFoundError("Could not find field [CHANNEL]") elif field == WifiInfo.RSSI: from scapy.all import sniff, RadioTap from pwnagotchi.mesh.wifi import freq_to_channel packets = sniff(offline=path, count=1) try: results[field] = packets[0][RadioTap].dBm_AntSignal except Exception: raise FieldNotFoundError("Could not find field [RSSI]") return results
def create_graph(data, channel=None): if not data: return '{}' data = json.loads(data) node_text = list() edge_x = list() edge_y = list() node_x = list() node_y = list() node_symbols = list() node_sizes = list() node_colors = list() for ap_data in data: name = ap_data['hostname'] or ap_data['vendor'] or ap_data['mac'] color = Viz.lookup_color(name) # nodes x, y = abs(ap_data['rssi']), freq_to_channel(ap_data['frequency']) node_x.append(x) node_y.append(y) node_text.append(name) node_symbols.append('square') node_sizes.append(15 + len(ap_data['clients']) * 3) node_colors.append(color) for c in ap_data['clients']: # node cname = c['hostname'] or c['vendor'] or c['mac'] xx, yy = Viz.random_pos(cname, x, y, 3) node_x.append(xx) node_y.append(yy) node_text.append(cname) node_symbols.append('circle') node_sizes.append(10) node_colors.append(color) # edge edge_x.append(x) edge_x.append(xx) edge_x.append(None) edge_y.append(y) edge_y.append(yy) edge_y.append(None) edge_trace = go.Scatter(x=edge_x, y=edge_y, line=dict(width=1, color='#888'), hoverinfo='none', mode='lines') node_trace = go.Scatter(x=node_x, y=node_y, mode='markers', marker=dict( size=node_sizes, color=node_colors, symbol=node_symbols, ), hovertext=node_text, hoverinfo='text') channel_line = go.Scatter( mode='lines', line=dict(width=15, color='#ff0000'), x=[min(node_x) - 5, max(node_x) + 5], y=[channel, channel], opacity=0.25, hoverinfo='none', ) if channel else dict() return json.dumps((channel_line, edge_trace, node_trace), cls=plotly.utils.PlotlyJSONEncoder)