-
Notifications
You must be signed in to change notification settings - Fork 87
/
probemon.py
96 lines (75 loc) · 3.1 KB
/
probemon.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/python
import time
import datetime
import argparse
import netaddr
import sys
import logging
from scapy.all import *
from pprint import pprint
from logging.handlers import RotatingFileHandler
NAME = 'probemon'
DESCRIPTION = "a command line tool for logging 802.11 probe request frames"
DEBUG = False
def build_packet_callback(time_fmt, logger, delimiter, mac_info, ssid, rssi):
def packet_callback(packet):
if not packet.haslayer(Dot11):
return
# we are looking for management frames with a probe subtype
# if neither match we are done here
if packet.type != 0 or packet.subtype != 0x04:
return
# list of output fields
fields = []
# determine preferred time format
log_time = str(int(time.time()))
if time_fmt == 'iso':
log_time = datetime.datetime.now().isoformat()
fields.append(log_time)
# append the mac address itself
fields.append(packet.addr2)
# parse mac address and look up the organization from the vendor octets
if mac_info:
try:
parsed_mac = netaddr.EUI(packet.addr2)
fields.append(parsed_mac.oui.registration().org)
except netaddr.core.NotRegisteredError, e:
fields.append('UNKNOWN')
# include the SSID in the probe frame
if ssid:
fields.append(packet.info)
if rssi:
rssi_val = -(256-ord(packet.notdecoded[-4:-3]))
fields.append(str(rssi_val))
logger.info(delimiter.join(fields))
return packet_callback
def main():
parser = argparse.ArgumentParser(description=DESCRIPTION)
parser.add_argument('-i', '--interface', help="capture interface")
parser.add_argument('-t', '--time', default='iso', help="output time format (unix, iso)")
parser.add_argument('-o', '--output', default='probemon.log', help="logging output location")
parser.add_argument('-b', '--max-bytes', default=5000000, help="maximum log size in bytes before rotating")
parser.add_argument('-c', '--max-backups', default=99999, help="maximum number of log files to keep")
parser.add_argument('-d', '--delimiter', default='\t', help="output field delimiter")
parser.add_argument('-f', '--mac-info', action='store_true', help="include MAC address manufacturer")
parser.add_argument('-s', '--ssid', action='store_true', help="include probe SSID in output")
parser.add_argument('-r', '--rssi', action='store_true', help="include rssi in output")
parser.add_argument('-D', '--debug', action='store_true', help="enable debug output")
parser.add_argument('-l', '--log', action='store_true', help="enable scrolling live view of the logfile")
args = parser.parse_args()
if not args.interface:
print "error: capture interface not given, try --help"
sys.exit(-1)
DEBUG = args.debug
# setup our rotating logger
logger = logging.getLogger(NAME)
logger.setLevel(logging.INFO)
handler = RotatingFileHandler(args.output, maxBytes=args.max_bytes, backupCount=args.max_backups)
logger.addHandler(handler)
if args.log:
logger.addHandler(logging.StreamHandler(sys.stdout))
built_packet_cb = build_packet_callback(args.time, logger,
args.delimiter, args.mac_info, args.ssid, args.rssi)
sniff(iface=args.interface, prn=built_packet_cb, store=0)
if __name__ == '__main__':
main()