Skip to content

Instantly share code, notes, and snippets.

@dropmeaword
Forked from D4rKP01s0n/wifiscanner.py
Created June 20, 2017 22:38
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save dropmeaword/42636d180d52e52e2d8b6275e79484a0 to your computer and use it in GitHub Desktop.
Save dropmeaword/42636d180d52e52e2d8b6275e79484a0 to your computer and use it in GitHub Desktop.
A simple python script which records and logs wifi probe requests.
#########################################################################
# Wifiscanner.py - A simple python script which records and logs wifi probe requests.
# Author - D4rKP01s0n
# Requirements - Scapy and Datetime
# Inspiration - Tim Tomes (LaNMaSteR53)'s WUDS https://bitbucket.org/LaNMaSteR53/wuds/
# Reminder - Change mon0 (around line 65) to your monitor-mode enabled wifi interface
#########################################################################
from datetime import datetime
from scapy.all import sniff, Dot11
#import numpy
import logging
import time
#Devices which are known to be constantly probing
IGNORE_LIST = set(['00:00:00:00:00:00', '01:01:01:01:01:01'])
SEEN_DEVICES = set() #Devices which have had their probes recieved
d = {'00:00:00:00:00:00':'Example MAC Address'} #Dictionary of all named devices
#knownfile = open('knowndevices.txt', 'a')
#knownfile.write(str(d))
#This exports known dictionary to a text file, but should only be used if the existing file is removed and the dictionary has been updated, as otherwise it will append the list to the existing file
#class colors: # These allow for color-coded output
# HEADER = '\033[95m' # An example of using this would be as follows
# OKBLUE = '\033[94m' # print bcolors.WARNING + "Warning: No active frommets remain. Continue?" + bcolors.ENDC
# OKGREEN = '\033[92m' # Credit: Joeld of StackOverflow: http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python
# WARNING = '\033[93m'
# FAIL = '\033[91m'
# ENDC = '\033[0m' # End every colored line with this, or else everything following will be the same color
# BOLD = '\033[1m'
# UNDERLINE = '\033[4m'
def handle_packet(pkt):
if not pkt.haslayer(Dot11):
return
if pkt.type == 0 and pkt.subtype == 4: #subtype used to be 8 (APs) but is now 4 (Probe Requests)
#logging.debug('Probe Recorded with MAC ' + curmac)
curmac = pkt.addr2
curmac = curmac.upper() #Assign variable to packet mac and make it uppercase
SEEN_DEVICES.add(curmac) #Add to set of known devices (sets ignore duplicates so it is not a problem)
if curmac not in IGNORE_LIST: #If not registered as ignored
if curmac in d:
logging.info('\033[95m' + 'Probe Recorded from ' + '\033[93m' + d[curmac] + '\033[95m' + ' with MAC ' + curmac + '\033[0m') #Log to file wifiscanner.log with purple color
print('\033[95m' + 'Probe MAC Address: ' + pkt.addr2 + ' from device ' + '\033[93m' + d[curmac] + '\033[0m')
#'with SSID: {pkt.info}'.format(pkt=pkt)) #Print to command line with purple color
else:
logging.info('\033[92m' + 'Probe Recorded from MAC ' + pkt.addr2 + '\033[0m') #Log to file wifiscanner.log with green color
print('\033[95m' + 'Device MAC: {pkt.addr2} '
'with SSID: {pkt.info}'.format(pkt=pkt) + '\033[0m') #Print to command line with green color
#print SEEN_DEVICES #Just for debug, prints all known devices
#dump()
def main():
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p',filename='wifiscanner.log',level=logging.DEBUG) #setup logging to file
logging.info('\n' + '\033[93m' + 'Wifi Scanner Initialized' + '\033[0m' + '\n') #announce that it has started to log file with yellow color
print('\n' + '\033[93m' + 'Wifi Scanner Initialized' + '\033[0m' + '\n') #announce that it has started to command line with yellow color (/n is newline)
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--interface', '-i', default='mon0', # Change mon0 to your monitor-mode enabled wifi interface
help='monitor mode enabled interface')
args = parser.parse_args()
sniff(iface=args.interface, prn=handle_packet) #start sniffin
while 1:
time.sleep(1) # Supposed to make an infinite loop, but for some reason it stops after a while
if __name__ == '__main__':
main()
@muratsplat
Copy link

Is this code working on MacOSX. Did you test it on it?

@FanchenBao
Copy link

When I used this code, none of the sniffed pkt has Dot11 as layer. I don't understand why.

To resolve this issue, I had to directly check for Dot11ProbeReq. In other words, handle_packet() would look like this:

from scapy.all import sniff, Dot11ProbeReq

# other code...

def handle_packet(pkt):
	if pkt.haslayer(Dot11ProbeReq):
		# remaining code...

Strangely, if I checked whether a packet with layer Dot11ProbeReq also has layer Dot11, the answer was no. Shouldn't Dot11 be the parent layer for everything else? This is very strange behavior to me.

@nick-brady
Copy link

worked very well. Make sure you turn the wireless interface you're sniffing on into monitor mode, or you'll be stuck waiting. Had to use Dot11ProbeReq as well like @FanchenBao.

Something like this:

sudo ifconfig wlan1 down
sudo iwconfig wlan1 mode monitor
sudo ifconfig wlan1 up

to flip the interface into monitor mode.

@jnash10
Copy link

jnash10 commented Feb 9, 2022

I'm having the same issue of it stopping after ~35 minutes. Any fix anybody found?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment