def parse_packet(packet): try: off, rt = radiotap.radiotap_parse(packet) except: global packets_dropped packets_dropped = packets_dropped + 1 # TODO Why this happening? return if packet[off] == '\x80': # beacon frame return mac = packet[off + 4:off + 10] now = strftime("%Y-%m-%d %H:%M:%S") address = radiotap.macstr(mac) if not address or address == 'ff:ff:ff:ff:ff:ff': return if address not in all_devices: all_devices[address] = { 'mac_address': address, 'first_seen': now, 'last_seen': now, 'packets': 0, } # Use dBm: http://stackoverflow.com/questions/14777114/what-is-rssi-value-in-802-11-packet all_devices[address].update({ 'power': rt.get('dbm_antsignal', 0), 'noise': rt.get('dbm_antnoise', 0), 'last_seen': now, 'packets': all_devices[address]['packets'] + 1, }) # Only active devices matter # We do that because so much fake mac is appearing, wasn't happening only in C # Probably the python radiotap is not working well... # TODO why? if all_devices[address]['packets'] > 20: if address not in devices: global devices_count devices_count = devices_count + 1 try: r = requests.get('http://www.macvendorlookup.com/api/v2/' + address) if r.status_code == 200: vendor = r.json()[0]['company'] else: vendor = 'Unknown' except: vendor = 'Unknown' devices[address] = { 'vendor': vendor } devices[address].update(all_devices[address]) global packets_count packets_count = packets_count + 1
def packet_parse(packet): off, radiotap = radiotap_parse(packet) off, i80211 = ieee80211_parse(packet, off) # TODO fix ahead, better clean it! # note: this is done to remove the frame check sequence from packet_data i80211_detail = i80211_info(i80211, packet[0:len(packet) - 4], off) parsed = radiotap parsed.update(i80211) parsed.update(i80211_detail) return parsed
def handle(self, *args, **options): pc = pcap.pcap(name='mon0') pc.setnonblock(True) w = we.WirelessExtension('mon0') while 1: with transaction.atomic(): while (time.time() < self.queue): result = pc.next() if not result: continue tstamp, pkt = result off, radiotap = r.radiotap_parse(pkt) off, pkt = r.ieee80211_parse(pkt, off) if not pkt: continue if pkt['from_ds']: if pkt['to_ds']: device, create = Device.objects.get_or_create( src_mac=pkt['addr4']) else: device, create = Device.objects.get_or_create( src_mac=pkt['addr2']) else: device, create = Device.objects.get_or_create( src_mac=pkt['addr2']) if pkt['to_ds']: if pkt['addr3'] != 'ff:ff:ff:ff:ff:ff': device.dst_mac = pkt['addr3'] else: if pkt['addr1'] != 'ff:ff:ff:ff:ff:ff': device.dst_mac = pkt['addr1'] device.signal = radiotap['dbm_antsignal'] device.lastseen = timezone.now() device.save() if pkt['type'] == 0 and pkt['subtype'] == 4: if pkt['data'][0] != '\x01': Probe.objects.get_or_create( device=device, probe=pkt['data'].split('\x01')[0]) if pkt['type'] == 0 and pkt['subtype'] == 8: essid = pkt['data'][12:] if essid != '\x01': Probe.objects.get_or_create( device=device, probe=essid.split('\x01')[0]) self.queue = time.time() + 10 self.channel += 1 if (self.channel > len(self.channels)): self.channel = 0 print self.channel w.set_channel(self.channels[self.channel])
def parse_file(fn): pkt = open(fn, 'rb').read() while len(pkt): off, radiotap = r.radiotap_parse(pkt, valuelist=True) for row in radiotap: if 'oui' in row: print_vendor(row) for k, v in row.items(): if k in fields_to_print: lbl, fmt = fields_to_print[k] print('\t%s: %s' % (lbl, fmt(v))) pkt = pkt[off:]
def parse_file(fn): pkt = open(fn).read() while len(pkt): off, radiotap = r.radiotap_parse(pkt, valuelist=True) for row in radiotap: if 'oui' in row: print_vendor(row) for k,v in row.items(): if k in fields_to_print: lbl, fmt = fields_to_print[k] print '\t%s: %s' % (lbl, fmt(v)) pkt = pkt[off:]
def test_ac_rate_1(): """ Frame 1: 4865 bytes on wire (38920 bits), 188 bytes captured (1504 bits) Radiotap Header v0, Length 38 Header revision: 0 Header pad: 0 Header length: 38 Present flags MAC timestamp: 270036265 Flags: 0x40 Channel frequency: 5180 [A 36] Channel flags: 0x0140, Orthogonal Frequency-Division Multiplexing (OFDM), 5 GHz spectrum SSI Signal: -76 dBm Antenna: 0 RX flags: 0x0000 VHT information Known VHT information: 0x44 .... .1.. = Guard interval: short (1) Bandwidth: 80 MHz (4) User 0: MCS 9 1001 .... = MCS index 0: 9 (256-QAM 5/6) .... 0011 = Spatial streams 0: 3 Coding 0: BCC (0) [Data Rate: 1299.9 Mb/s] 802.11 radio information PHY type: 802.11ac (8) Short GI: True Bandwidth: 80 MHz (4) User 0: MCS 9 Channel: 36 Frequency: 5180 MHz Signal strength (dBm): -76 dBm TSF timestamp: 270036265 IEEE 802.11 Unrecognized (Reserved frame), Flags: o.m.R..T IEEE 802.11 wireless LAN extension frame """ buf = ( """\x00\x00&\x00+H \x00)m\x18\x10\x00\x00\x00\x00@\x00<\x14@\x01\xb4\x00\x00\x00D\x00\x04\x04\x93""" "\x00\x00\x00\x00\x00\x00\x00\x8c\xa9z\xa8\'\xda\x8c.\xeaD$l\x95\x16\xa9>\xd5\x8eo\xdb\xb7$\xceIF" """\xa1\x19\xd38\x0b\xc4%\xce\xb5.\xbaM\'\xad\xc9\x8a.\x83\'\xa9\xab\xe1<\xe8B\x0c\x1dE\x08@"\xf7""" """\x06Bb\xdf\xf2\xf7\x11\xd8\xf2\xd6[\x98Lv\xa9{\x07Ph~\xa1\x8a\x96\xf7o\xff\xb9\x1c\xc3\xf0\xd3\x04""" """\xfb\xfe\xbc\xa5\x16\xbd;l\xb1\xa7l\xc5\xf3\x84\xdf\xdd`Vn\xeb\xac\xbf\x04\x9by\x91T"`\xbb\xbbl\n""" """\xfd\xd77\'_\x91\x1d_\xb8\xa6\\0S\xf9q\xd8\x18O\xb7\xf0G\xc0\x9e\x0e|\xa8 \x14""") off, radiotap = r.radiotap_parse(buf) assert radiotap assert len(radiotap['vht_user'])==1 assert radiotap['vht_user'][0] == {'vht_rate_mbps': 1300.0, 'vht_coding': 0, 'vht_mcs_index': 9, 'vht_mcs_descr': ('256QAM', '5/6')}
def test_ac_rate_2(): """ Frame 1: 1615 bytes on wire (12920 bits), 188 bytes captured (1504 bits) Radiotap Header v0, Length 38 Header revision: 0 Header pad: 0 Header length: 38 Present flags MAC timestamp: 254101463 Flags: 0x40 Channel frequency: 5180 [A 36] Channel flags: 0x0140, Orthogonal Frequency-Division Multiplexing (OFDM), 5 GHz spectrum SSI Signal: -76 dBm Antenna: 0 RX flags: 0x0000 VHT information Known VHT information: 0x44 .... .0.. = Guard interval: long (0) Bandwidth: 80 MHz (4) User 0: MCS 8 1000 .... = MCS index 0: 8 (256-QAM 3/4) .... 0011 = Spatial streams 0: 3 Coding 0: BCC (0) [Data Rate: 1053.0 Mb/s] 802.11 radio information PHY type: 802.11ac (8) Short GI: False Bandwidth: 80 MHz (4) User 0: MCS 8 Channel: 36 Frequency: 5180 MHz Signal strength (dBm): -76 dBm TSF timestamp: 254101463 IEEE 802.11 QoS Null function (No data), Flags: ....R.F. """ buf = ( """\x00\x00&\x00+H \x00\xd7G%\x0f\x00\x00\x00\x00@\x00<\x14@\x01\xb4\x00\x00\x00D\x00\x00\x04\x83\x00\x00""" """\x00\x00\x00\x00\x00\xc9\n\xacT\x9d\x0b#T\xe6]\xa3p\xdfN\x98\xfdyR_\x8a=~\xb7\x90\x07\x10_2\x95\xa6\xa3""" """\xf2\x06\xa9/E\xa5?\xcbg\xac\x11Y]\xcb\\\xd8-\n\xc8\xb6|}0[S\x8d\xac\xcc\xafmT%\xd2\xa7\xdep\xfb\xe2\x0f""" """\xf1\x0e\xd8hF\xcb\xf6\x92t\xd5\n\xed\xb4y\xf2qj\x8a\x04\xbc\xf3C\x93]\xd9n\xa0\xfa{l\xff\xa3=MC\xb0""" """\xd2\xf6\x0f\xb8\x87\xf2T\xdf#}\xfe\xe1\x8f\xe1\xa1\xd5zI\x1f6\xceZ\xa0\xae\x14\x01\xfeb\xce\xa3@\xa4""" """\xe2M\x13\n\xb9\x99\x1f\n\x88p\xcb\xb8""") off, radiotap = r.radiotap_parse(buf) assert radiotap assert len(radiotap['vht_user'])==1 assert radiotap['vht_user'] == {0: {'vht_rate_mbps': 1053.0, 'vht_mcs_index': 8, 'vht_coding': 0, 'vht_mcs_descr': ('256QAM', '3/4')}}
def handle(self, *args, **options): pc = pcap.pcap(name='mon0') pc.setnonblock(True) w = we.WirelessExtension('mon0') while 1: with transaction.atomic(): while (time.time() < self.queue): result = pc.next() if not result: continue tstamp, pkt = result off, radiotap = r.radiotap_parse(pkt) off, pkt = r.ieee80211_parse(pkt, off) if not pkt: continue if pkt['from_ds']: if pkt['to_ds']: device, create = Device.objects.get_or_create(src_mac=pkt['addr4']) else: device, create = Device.objects.get_or_create(src_mac=pkt['addr2']) else: device, create = Device.objects.get_or_create(src_mac=pkt['addr2']) if pkt['to_ds']: if pkt['addr3'] != 'ff:ff:ff:ff:ff:ff': device.dst_mac = pkt['addr3'] else: if pkt['addr1'] != 'ff:ff:ff:ff:ff:ff': device.dst_mac = pkt['addr1'] device.signal = radiotap['dbm_antsignal'] device.lastseen = timezone.now() device.save() if pkt['type'] == 0 and pkt['subtype'] == 4: if pkt['data'][0] != '\x01': Probe.objects.get_or_create(device=device, probe=pkt['data'].split('\x01')[0]) if pkt['type'] == 0 and pkt['subtype'] == 8: essid = pkt['data'][12:] if essid != '\x01': Probe.objects.get_or_create(device=device, probe=essid.split('\x01')[0]) self.queue = time.time()+10 self.channel += 1 if (self.channel > len(self.channels)): self.channel = 0 print self.channel w.set_channel(self.channels[self.channel])
def build_packet_cb(db, stdout, ignored): def packet_callback(packet): now = time.time() # look up vendor from OUI value in MAC address try: parsed_mac = netaddr.EUI(packet.addr2) vendor = parsed_mac.oui.registration().org except netaddr.core.NotRegisteredError, e: vendor = u'UNKNOWN' except IndexError: vendor = u'UNKNOWN' # parse radiotap headers to get RSSI value offset, headers = radiotap_parse(str(packet)) rssi = headers['dbm_antsignal'] try: ssid = packet.info.decode('utf-8') except UnicodeDecodeError: # encode the SSID in base64 because it will fail # to be inserted into the db otherwise ssid = u'b64_%s' % base64.b64encode(packet.info) fields = [now, packet.addr2, vendor, ssid, rssi] if packet.addr2 not in ignored: insert_into_db(fields, db) if stdout: # convert time to iso
def beacon_ts(mac, fixed): ts, = struct.unpack_from('<Q', fixed, 0) return ts fn = sys.argv[1] pc = pcap.pcap(fn) count = 0 sta_files = {} window_files = {} nstas = 0 windows = {} for ts, pkt in pc: rofs, rtap = radiotap.radiotap_parse(pkt) ofs, mac = radiotap.ieee80211_parse(pkt, rofs) if not rtap.has_key('TSFT'): continue ts = rtap['TSFT'] # check for expiry of any windows, if so write them to window_files for sta in windows.keys(): window = windows[sta] if ts > window['end']: print >>window_files[sta], '%d %d' % (window['start'], window['end']) windows.pop(sta) count += 1
'RADIOTAP_NAMESPACE', 'VENDOR_NAMESPACE', 'EXT' ] def parse_radiotap_index(present_bytes): present_bits = '{:032b}'.format( int.from_bytes(present_bytes, byteorder='little'))[::-1] field_list = [] for i, b in enumerate(present_bits): if b == '1': field_list.append((i, RADIOTAP_FIELD_TABLE[i])) return field_list radiotap_bga = (b'\x00\x00' b'\x0d\x00' b'\x04\x80\x02\x00' b'\x02' b'\x00\x00\x00' b'\x00') radiotap_ht = (b'\x00\x00' b'\x0e\x00' b'\x00\x80\x0a\x00' b'\x00\x00' b'\x00' b'\x07\x00\x01') r_hdr_len, r_hdr_parsed = radiotap.radiotap_parse(radiotap_ht) print(parse_radiotap_index(b'\x00\x80\x0a\x00')) print(r_hdr_len, r_hdr_parsed)
import radiotap as r import pcap from scapy.all import * pc = pcap.pcap(name='variable_rate_attack02_mon_VP') pkt = pc[0] off, radiotap = r.radiotap_parse(pkt) print(radiotap) off, mac = r.ieee80211_parse(pkt, off) print(mac)
def packet_callback(packet): if not packet.haslayer(Dot11): return with open('/proc/uptime', 'r') as f: uptime = f.readline().split()[0] now = datetime.now() address = None ap_address = None if packet.type == 0: if sta and packet.subtype == 0: sender = 'STA_AssoReq' ap_address = packet.addr1 address = packet.addr2 elif sta and packet.subtype == 1: sender = 'AP_AssoResp' address = packet.addr1 ap_address = packet.addr2 elif sta and packet.subtype == 2: sender = 'STA_ReassoResp' ap_address = packet.addr1 address = packet.addr2 elif sta and packet.subtype == 3: sender = 'AP_ReassoResp' address = packet.addr1 ap_address = packet.addr2 elif sta and packet.subtype == 4: sender = 'STA_ProbeReq' address = packet.addr2 elif sta and packet.subtype == 5: sender = 'AP_ProbeResp' address = packet.addr1 ap_address = packet.addr2 elif not sta and packet.subtype == 8: sender = 'AP_Beacon' ap_address = packet.addr2 elif sta and packet.subtype == 9: sender = 'AP_ATIM' address = packet.addr1 ap_address = packet.addr2 elif sta and packet.subtype == 10: sender = 'AP_Disas' address = packet.addr1 ap_address = packet.addr2 elif sta and packet.subtype == 11: sender = 'STA_Auth' ap_address = packet.addr1 address = packet.addr2 elif sta and packet.subtype == 12: sender = 'STA_Deauth' ap_address = packet.addr1 address = packet.addr2 else: return elif sta and packet.type == 2 and packet.subtype == 0: ds = packet.FCfield & 0x3 # to_ds = (ds & 0x1) != 0 # from_ds = (ds & 0x2) != 0 if ds == 1: # STA to AP sender = 'STA_Data' ap_address = packet.addr1 address = packet.addr2 elif ds == 2: # AP to STA address = packet.addr1 sender = 'AP_Data' ap_address = packet.addr2 else: return else: return global last_address, last_ap_address if address == last_address and ap_address == last_ap_address: return last_address = address last_ap_address = ap_address content = { 'uptime': uptime, 'date': now.strftime("%Y/%m/%d %H:%M:%S"), 'sender': sender, 'channel': channel } if address: content['address'] = address.upper() content['vendor'] = get_vendor(address) if ap_address: content['ap_address'] = ap_address.upper() content['ap_vendor'] = get_vendor(ap_address) try: content['ap_name'] = packet.info.decode('utf-8', errors='replace') except UnicodeDecodeError: content['ap_name'] = packet.info except AttributeError: pass offset, headers = radiotap_parse(str(packet)) if sender.startswith('STA_'): content['rssi'] = headers['dbm_antsignal'] else: content['ap_rssi'] = headers['dbm_antsignal'] output(queue, content)