From 8021741b20af30e9bc55c5f1b18a9ad4c142d4b8 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:28:38 +0100 Subject: [PATCH 01/16] Update capture.py The source repo didn't have the Python3 updates included in the KillerBee repo, but these files were removed from that repo and no obvious new repo was made. Just restoring these so that they don't have to be hunted for in the version history of the KillerBee repo. --- killerbee_extras_tools/openear/capture.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/killerbee_extras_tools/openear/capture.py b/killerbee_extras_tools/openear/capture.py index a237228..7c44182 100755 --- a/killerbee_extras_tools/openear/capture.py +++ b/killerbee_extras_tools/openear/capture.py @@ -10,8 +10,8 @@ # Given a database and a key into the database's networks table, # initiate a pcap and online database capture. def startCapture(dev, capChan): - timeLabel = datetime.now().strftime('%Y%m%d-%H%M') - print 'Cap%s: Launching a capture on channel %s.' % (dev, capChan) + timeLabel = datetime.utcnow().strftime('%Y%m%d-%H%M') + print('Cap%s: Launching a capture on channel %s.' % (dev, capChan)) fname = 'zb_c%s_%s.pcap' % (capChan, timeLabel) #fname is -w equiv signal.signal(signal.SIGINT, interrupt) trigger = threading.Event() @@ -39,7 +39,7 @@ def run(self): self.kb = KillerBee(device=self.devstring, datasource="Wardrive Live") self.kb.set_channel(self.channel) self.kb.sniffer_on() - print "Capturing on \'%s\' at channel %d." % (self.kb.get_dev_info()[0], self.channel) + print("Capturing on \'%s\' at channel %d." % (self.kb.get_dev_info()[0], self.channel)) # loop capturing packets to dblog and file while not self.trigger.is_set(): packet = self.kb.pnext() @@ -52,5 +52,5 @@ def run(self): self.kb.sniffer_off() self.kb.close() self.pd.close() - print "%d packets captured" % self.packetcount + print("%d packets captured" % self.packetcount) From 4142bc6d4a770ed573d264b68de777b9e07fd039 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:30:01 +0100 Subject: [PATCH 02/16] Update scanner.py The source repo didn't have the Python3 updates included in the KillerBee repo, but these files were removed from that repo and no obvious new repo was made. Just restoring these so that they don't have to be hunted for in the version history of the KillerBee repo.https://github.com/riverloopsec/beekeeperwids --- killerbee_extras_tools/openear/scanner.py | 59 ++++++++++++----------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/killerbee_extras_tools/openear/scanner.py b/killerbee_extras_tools/openear/scanner.py index becce7d..082f5ea 100644 --- a/killerbee_extras_tools/openear/scanner.py +++ b/killerbee_extras_tools/openear/scanner.py @@ -2,12 +2,16 @@ # ZBScanner # rmelgares 2011 # Promiscious capture on multiple channels at once +from __future__ import print_function -import gps, time, os, signal, sys, operator, threading -import string, socket, struct, datetime +import datetime +import queue +import signal +import threading + +import gps from killerbee import * -import Queue # Globals session = "" @@ -24,7 +28,7 @@ def broadcast_event(data): ''' Send broadcast data to all active threads ''' - print "\nShutting down threads." + print("\nShutting down threads.") for q in active_queues: q.put(data) @@ -33,7 +37,7 @@ class LocationThread(threading.Thread): def __init__(self): global active_queues threading.Thread.__init__(self) - self.mesg = Queue.Queue() + self.mesg = queue.Queue() active_queues.append(self.mesg) def run(self): @@ -41,11 +45,11 @@ def run(self): global active_queues global longitude, latitude, altitude, last_seen message = "" - last_seen = datetime.datetime.now() + last_seen = datetime.datetime.utcnow() while(1): try: message = self.mesg.get(timeout=.00001) - except Queue.Empty: + except queue.Empty: pass if message == "shutdown": break @@ -57,12 +61,12 @@ def run(self): latitude = t_latitude longitude = t_longitude altitude = t_altitude - last_seen = datetime.datetime.now() + last_seen = datetime.datetime.utcnow() else: - end_time = datetime.datetime.now() + end_time = datetime.datetime.utcnow() elapsed_time = end_time - last_seen - print chr(0x1b) + "[2;5fElapsed time since last location change: %s" % str(elapsed_time) - print chr(0x1b) + "[3;5fLat: %f, Long: %f, Alt: %f." % (latitude, longitude, altitude) + print(chr(0x1b) + "[2;5fElapsed time since last location change: %s" % str(elapsed_time)) + print(chr(0x1b) + "[3;5fLat: %f, Long: %f, Alt: %f." % (latitude, longitude, altitude)) time.sleep(1) @@ -71,7 +75,7 @@ class CaptureThread(threading.Thread): def __init__(self, dev, channel, pd): global active_queues threading.Thread.__init__(self) - self.mesg = Queue.Queue() + self.mesg = queue.Queue() active_queues.append(self.mesg) self.channel = channel self.freq = (channel - 10) * 5 + 2400 @@ -91,7 +95,7 @@ def run(self): while (True): try: message = self.mesg.get(timeout=.00001) - except Queue.Empty: + except queue.Empty: pass if message == "shutdown": break @@ -100,19 +104,19 @@ def run(self): self.packetcount+=1 if arg_gps: gpsdata = (longitude, latitude, altitude) - self.pd.pcap_dump(packet['bytes'], ant_dbm=packet['dbm'], freq_mhz=self.freq, location=map(float, gpsdata)) + self.pd.pcap_dump(packet['bytes'], ant_dbm=packet['dbm'], freq_mhz=self.freq, location=list(map(float, gpsdata))) if arg_db:self.kb.dblog.add_packet(full=packet, location=gpsdata) else: self.pd.pcap_dump(packet['bytes']) if arg_db:self.kb.dblog.add_packet(full=packet) - print chr(0x1b) + "[%d;5fChannel %d: %d packets captured." % (self.channel - 6, self.channel, self.packetcount) + print(chr(0x1b) + "[%d;5fChannel %d: %d packets captured." % (self.channel - 6, self.channel, self.packetcount)) # trigger threading.Event set to false, so shutdown thread if arg_verbose: - print "%s on channel %d shutting down..." % (threading.currentThread().getName(), self.channel) + print("%s on channel %d shutting down..." % (threading.currentThread().getName(), self.channel)) self.kb.sniffer_off() self.kb.close() self.pd.close() - print "%d packets captured on channel %d" % (self.packetcount, self.channel) + print("%d packets captured on channel %d" % (self.packetcount, self.channel)) def signal_handler(signal, frame): ''' Signal handler called on keyboard interrupt to exit threads and exit scanner script''' @@ -146,37 +150,34 @@ def main(args): else: kbdev_info = kbutils.devlist() channel = 11 - print "Found %d devices." % len(kbdev_info) + print("Found %d devices." % len(kbdev_info)) if len(kbdev_info) < 1: exit(1) if arg_gps == True: - print "Initializing GPS device %s ... "% (arg_gps_devstring), + print("Initializing GPS device %s ... "% (arg_gps_devstring), end=' ') session = gps.gps() session.poll() session.stream() - print "Waiting for fix... ", + print("Waiting for fix... ", end=' ') while(session.fix.mode == 1): session.poll() - print "Fix acquired!" + print("Fix acquired!") t = LocationThread() t.start() time.sleep(2) for i in range(0, len(kbdev_info)): if kbdev_info[i][0] == arg_gps_devstring: - print "Skipping device %s" % arg_gps_devstring + print("Skipping device %s" % arg_gps_devstring) else: - print 'Device at %s: \'%s\'' % (kbdev_info[i][0], kbdev_info[i][1]) + print('Device at %s: \'%s\'' % (kbdev_info[i][0], kbdev_info[i][1])) if channel <= 26: - print '\tAssigning to channel %d.' % channel - timeLabel = datetime.datetime.now().strftime('%Y%m%d-%H%M') + print('\tAssigning to channel %d.' % channel) + timeLabel = datetime.datetime.utcnow().strftime('%Y%m%d-%H%M') fname = 'zb_c%s_%s.pcap' % (channel, timeLabel) #fname is -w equiv pcap = PcapDumper(DLT_IEEE802_15_4, fname, ppi=arg_ppi) t = CaptureThread(kbdev_info[i][0], channel, pcap) t.start() channel += 1 os.system('clear') - print chr(0x1b) + "[1;5fLive Stats:" + print(chr(0x1b) + "[1;5fLive Stats:") while True: pass - -if __name__ == '__main__': - main(sys.argv) From b7d3b085dfe1afac82f4f1457c0a073e62906768 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:30:31 +0100 Subject: [PATCH 03/16] Update gps.py The source repo didn't have the Python3 updates included in the KillerBee repo, but these files were removed from that repo and no obvious new repo was made. Just restoring these so that they don't have to be hunted for in the version history of the KillerBee repo.https://github.com/riverloopsec/beekeeperwids --- killerbee_extras_tools/openear/gps.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/killerbee_extras_tools/openear/gps.py b/killerbee_extras_tools/openear/gps.py index 53a1656..8851eb4 100644 --- a/killerbee_extras_tools/openear/gps.py +++ b/killerbee_extras_tools/openear/gps.py @@ -1,4 +1,7 @@ -import gps, os, time +import os +import time + +import gps session = gps.gps() session.poll() @@ -10,18 +13,18 @@ # a = altitude, d = date/time, m=mode, # o=postion/fix, s=status, y=satellites - print - print ' GPS reading' - print '----------------------------------------' - print 'fix ' , ("NO_FIX","FIX","DGPS_FIX")[session.fix.mode - 1] - print 'latitude ' , session.fix.latitude - print 'longitude ' , session.fix.longitude - print 'time utc ' , session.utc, session.fix.time - print 'altitude ' , session.fix.altitude + print('') + print(' GPS reading') + print('----------------------------------------') + print('fix ' , ("NO_FIX","FIX","DGPS_FIX")[session.fix.mode - 1]) + print('latitude ' , session.fix.latitude) + print('longitude ' , session.fix.longitude) + print('time utc ' , session.utc, session.fix.time) + print('altitude ' , session.fix.altitude) - print - print ' Satellites (total of', len(session.satellites) , ' in view)' + print('') + print(' Satellites (total of', len(session.satellites) , ' in view)') for i in session.satellites: - print '\t', i + print('\t', i) time.sleep(3) From f78c6d845df25d58c6901257e590aa7e35d67078 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:31:02 +0100 Subject: [PATCH 04/16] Update client.py --- killerbee_extras_tools/openear/gps/client.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/killerbee_extras_tools/openear/gps/client.py b/killerbee_extras_tools/openear/gps/client.py index 6a62da5..3e7b64d 100644 --- a/killerbee_extras_tools/openear/gps/client.py +++ b/killerbee_extras_tools/openear/gps/client.py @@ -31,24 +31,20 @@ def connect(self, host, port): host, port = host[:i], host[i+1:] try: port = int(port) except ValueError: - raise socket.error, "nonnumeric port" - #if self.verbose > 0: - # print 'connect:', (host, port) + raise socket.error("nonnumeric port") msg = "getaddrinfo returns an empty list" self.sock = None for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res try: self.sock = socket.socket(af, socktype, proto) - #if self.debuglevel > 0: print 'connect:', (host, port) self.sock.connect(sa) - except socket.error, msg: - #if self.debuglevel > 0: print 'connect fail:', (host, port) + except socket.error as msg: self.close() continue break if not self.sock: - raise socket.error, msg + raise socket.error(msg) def close(self): if self.sock: @@ -128,14 +124,14 @@ def json_unpack(self, buf): def asciify(d): "De-Unicodify everything so we can copy dicts into Python objects." t = {} - for (k, v) in d.items(): + for (k, v) in list(d.items()): ka = k.encode("ascii") - if type(v) == type(u"x"): + if type(v) == type("x"): va = v.encode("ascii") elif type(v) == type({}): va = asciify(v) elif type(v) == type([]): - va = map(asciify, v) + va = list(map(asciify, v)) else: va = v t[ka] = va @@ -143,7 +139,7 @@ def asciify(d): self.data = dictwrapper(**asciify(json.loads(buf.strip(), encoding="ascii"))) # Should be done for any other array-valued subobjects, too. if self.data["class"] == "SKY" and hasattr(self.data, "satellites"): - self.data.satellites = map(lambda x: dictwrapper(**x), self.data.satellites) + self.data.satellites = [dictwrapper(**x) for x in self.data.satellites] def stream(self, flags=0, outfile=None): "Control streaming reports from the daemon," @@ -182,7 +178,7 @@ def __init__(self, **ddict): def get(self, k, d=None): return self.__dict__.get(k, d) def keys(self): - return self.__dict__.keys() + return list(self.__dict__.keys()) def __getitem__(self, key): "Emulate dictionary, for new-style interface." return self.__dict__[key] From b1493c11d0089281fb0662f1c3e5370d81520ee4 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:31:29 +0100 Subject: [PATCH 05/16] Update gps.py --- killerbee_extras_tools/openear/gps/gps.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/killerbee_extras_tools/openear/gps/gps.py b/killerbee_extras_tools/openear/gps/gps.py index 9b2c62f..5eb695d 100755 --- a/killerbee_extras_tools/openear/gps/gps.py +++ b/killerbee_extras_tools/openear/gps/gps.py @@ -15,7 +15,7 @@ # now live in a different module. # import time -from client import * +from .client import * NaN = float('nan') def isnan(x): return str(x) == 'nan' @@ -235,14 +235,14 @@ def default(i, vbit=0, cnv=float): d1 = int(prefix.pop()) newsats = [] for i in range(d1): - newsats.append(gps.satellite(*map(int, satellites[i].split()))) + newsats.append(gps.satellite(*list(map(int, satellites[i].split())))) self.satellites = newsats self.valid |= SATELLITE_SET def __oldstyle_shim(self): # The rest is backwards compatibility for the old interface def default(k, dflt, vbit=0): - if k not in self.data.keys(): + if k not in list(self.data.keys()): return dflt else: self.valid |= vbit @@ -283,7 +283,7 @@ def default(k, dflt, vbit=0): elif self.data.get("class") == "SKY": for attrp in "xyvhpg": setattr(self, attrp+"dop", default(attrp+"dop", NaN, DOP_SET)) - if "satellites" in self.data.keys(): + if "satellites" in list(self.data.keys()): self.satellites = [] for sat in self.data['satellites']: self.satellites.append(gps.satellite(PRN=sat['PRN'], elevation=sat['el'], azimuth=sat['az'], ss=sat['ss'], used=sat['used'])) @@ -314,7 +314,7 @@ def poll(self): self.valid |= PACKET_SET return 0 - def next(self): + def __next__(self): if self.poll() == -1: raise StopIteration if hasattr(self, "data"): @@ -356,7 +356,7 @@ def stream(self, flags=0, outfile=None): if switch == '-v': verbose = True if len(arguments) > 2: - print 'Usage: gps.py [-v] [host [port]]' + print('Usage: gps.py [-v] [host [port]]') sys.exit(1) opts = { "verbose" : verbose } @@ -369,6 +369,6 @@ def stream(self, flags=0, outfile=None): session.set_raw_hook(lambda s: sys.stdout.write(s.strip() + "\n")) session.stream(WATCH_ENABLE|WATCH_NEWSTYLE) for report in session: - print report + print(report) # gps.py ends here From c1219b6aefad5946b2e2a40500a05bd8ee66cc25 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:31:59 +0100 Subject: [PATCH 06/16] Update misc.py --- killerbee_extras_tools/openear/gps/misc.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/killerbee_extras_tools/openear/gps/misc.py b/killerbee_extras_tools/openear/gps/misc.py index 021874d..fc6fab9 100644 --- a/killerbee_extras_tools/openear/gps/misc.py +++ b/killerbee_extras_tools/openear/gps/misc.py @@ -50,8 +50,10 @@ def CalcRad(lat): r = r * 1000.0 # Convert to meters return r -def EarthDistance((lat1, lon1), (lat2, lon2)): +def EarthDistance(xxx_todo_changeme, xxx_todo_changeme1): "Distance in meters between two points specified in degrees." + (lat1, lon1) = xxx_todo_changeme + (lat2, lon2) = xxx_todo_changeme1 x1 = CalcRad(lat1) * math.cos(Deg2Rad(lon1)) * math.sin(Deg2Rad(90-lat1)) x2 = CalcRad(lat2) * math.cos(Deg2Rad(lon2)) * math.sin(Deg2Rad(90-lat2)) y1 = CalcRad(lat1) * math.sin(Deg2Rad(lon1)) * math.sin(Deg2Rad(90-lat1)) @@ -67,8 +69,10 @@ def EarthDistance((lat1, lon1), (lat2, lon2)): elif a < -1: a = -1 return CalcRad((lat1+lat2) / 2) * math.acos(a) -def MeterOffset((lat1, lon1), (lat2, lon2)): +def MeterOffset(xxx_todo_changeme2, xxx_todo_changeme3): "Return offset in meters of second arg from first." + (lat1, lon1) = xxx_todo_changeme2 + (lat2, lon2) = xxx_todo_changeme3 dx = EarthDistance((lat1, lon1), (lat1, lon2)) dy = EarthDistance((lat1, lon1), (lat2, lon1)) if lat1 < lat2: dy *= -1 @@ -83,7 +87,7 @@ def isotime(s): date = int(s) msec = s - date date = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(s)) - return date + "." + `msec`[2:] + return date + "." + repr(msec)[2:] elif type(s) == type(""): if s[-1] == "Z": s = s[:-1] @@ -98,4 +102,3 @@ def isotime(s): raise TypeError # End - From cd8f0545177ca2a85d265e4f9c3bd0020c76d0e3 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:32:36 +0100 Subject: [PATCH 07/16] Update capture.py The source repo didn't have the Python3 updates included in the KillerBee repo, but these files were removed from that repo and no obvious new repo was made. Just restoring these so that they don't have to be hunted for in the version history of the KillerBee repo.https://github.com/riverloopsec/beekeeperwids --- killerbee_extras_tools/zbwardrive/capture.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/capture.py b/killerbee_extras_tools/zbwardrive/capture.py index 239d748..60c70e7 100755 --- a/killerbee_extras_tools/zbwardrive/capture.py +++ b/killerbee_extras_tools/zbwardrive/capture.py @@ -20,9 +20,9 @@ def startCapture(zbdb, channel, dblog=False, gps=False): capChan = channel key = "CH%d" % channel if nextDev == None: - print 'Cap%s: No free device to use for capture.' % key + print('Cap%s: No free device to use for capture.' % key) return None - print 'Cap%s: Launching a capture on channel %s.' % (key, capChan) + print('Cap%s: Launching a capture on channel %s.' % (key, capChan)) signal.signal(signal.SIGINT, interrupt) trigger = threading.Event() triggers.append(trigger) @@ -49,7 +49,7 @@ def __init__(self, channel, devstring, trigger, dblog=False, gps=None): self.useDBlog = dblog self.currentGPS = gps - timeLabel = datetime.now().strftime('%Y%m%d-%H%M') + timeLabel = datetime.utcnow().strftime('%Y%m%d-%H%M') fname = 'zb_c%s_%s.pcap' % (channel, timeLabel) #fname is -w equiv self.pd = PcapDumper(DLT_IEEE802_15_4, fname, ppi=True) @@ -62,7 +62,7 @@ def run(self): self.kb = KillerBee(device=self.devstring) self.kb.set_channel(self.channel) self.kb.sniffer_on() - print "Capturing on \'%s\' at channel %d." % (self.kb.get_dev_info()[0], self.channel) + print("Capturing on \'%s\' at channel %d." % (self.kb.get_dev_info()[0], self.channel)) # loop capturing packets to dblog and file while not self.trigger.is_set(): packet = self.kb.pnext() @@ -94,5 +94,5 @@ def run(self): self.kb.sniffer_off() self.kb.close() self.pd.close() - print "%d packets captured on channel %d." % (self.packetcount, self.channel) + print("%d packets captured on channel %d." % (self.packetcount, self.channel)) From 3cd914763340f49eb9a729d16e9e66c354e1c208 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:33:12 +0100 Subject: [PATCH 08/16] Update db.py --- killerbee_extras_tools/zbwardrive/db.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/db.py b/killerbee_extras_tools/zbwardrive/db.py index a2c2051..185e7c9 100755 --- a/killerbee_extras_tools/zbwardrive/db.py +++ b/killerbee_extras_tools/zbwardrive/db.py @@ -25,7 +25,7 @@ def store_devices(self, devid, devstr, devserial): # Returns the devid of a device marked 'Free', # or None if there are no Free devices in the DB. def get_devices_nextFree(self): - for devid, dev in self.devices.items(): + for devid, dev in list(self.devices.items()): if dev[2] == 'Free': return devid @@ -51,7 +51,6 @@ def store_networks(self, key, spanid, source, channel, packet): # Return the channel of the network identified by key, # or None if it doesn't exist in the DB. def get_networks_channel(self, key): - #print "Looking up channel for network with key of %s" % (key) for chan, data in self.channels: if data[0] == key: return chan return None @@ -64,7 +63,7 @@ def channel_status_logging(self, chan): ''' if chan == None: raise Exception("None given for channel number") elif chan not in self.channels: raise Exception("Invalid channel") - for dev in self.devices.values(): + for dev in list(self.devices.values()): if dev[3] == chan and dev[2] == 'Capture': return True return False From 9617f028325dde020c7e4702be728ee61b8df2ec Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:34:05 +0100 Subject: [PATCH 09/16] Update scanning.py --- killerbee_extras_tools/zbwardrive/scanning.py | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/scanning.py b/killerbee_extras_tools/zbwardrive/scanning.py index ed415a3..946f403 100755 --- a/killerbee_extras_tools/zbwardrive/scanning.py +++ b/killerbee_extras_tools/zbwardrive/scanning.py @@ -6,9 +6,15 @@ import struct from killerbee import * -from db import toHex -from capture import startCapture -from scapy.all import Dot15d4, Dot15d4Beacon +from .db import toHex +from .capture import startCapture + +try: + from scapy.all import Dot15d4, Dot15d4Beacon +except ImportError: + print('This Requires Scapy To Be Installed.') + from sys import exit + exit(-1) #TODO set iteration min to a sensical parameter MIN_ITERATIONS_AGRESSIVE = 0 @@ -18,21 +24,21 @@ def doScan_processResponse(packet, channel, zbdb, kbscan, verbose=False, dblog=F scapyd = Dot15d4(packet['bytes']) # Check if this is a beacon frame if isinstance(scapyd.payload, Dot15d4Beacon): - if verbose: print "Received frame is a beacon." + if verbose: print("Received frame is a beacon.") try: spanid = scapyd.src_panid source = scapyd.src_addr except Exception as e: - print "DEBUG: Issue fetching src panid/addr from scapy packet ({0}).".format(e) - print "\t{0}".format(scapyd.summary()) - print scapyd.show2() - print "-"*25 + print("DEBUG: Issue fetching src panid/addr from scapy packet ({0}).".format(e)) + print("\t{0}".format(scapyd.summary())) + print(scapyd.show2()) + print("-"*25) return None #ignore this received frame for now key = '%x%x' % (spanid, source) #TODO if channel already being logged, ignore it as something new to capture if zbdb.channel_status_logging(channel) == False: if verbose: - print "A network on a channel that is not currently being logged replied to our beacon request." + print("A network on a channel that is not currently being logged replied to our beacon request.") # Store the network in local database so we treat it as already discovered by this program: zbdb.store_networks(key, spanid, source, channel, packet['bytes']) # Log to the mysql db or to the appropriate pcap file @@ -44,7 +50,7 @@ def doScan_processResponse(packet, channel, zbdb, kbscan, verbose=False, dblog=F return channel else: #network designated by key is already being logged if verbose: - print 'Received frame is a beacon for a network we already found and are logging.' + print('Received frame is a beacon for a network we already found and are logging.') return None else: #frame doesn't look like a beacon according to scapy return None @@ -69,7 +75,7 @@ def doScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False, stayti # return devices that we didn't choose to the free state for inspectedDevId in inspectedDevs: zbdb.update_devices_status(inspectedDevId, 'Free') - print 'Network discovery device is %s' % (scannerDevId) + print('Network discovery device is %s' % (scannerDevId)) zbdb.update_devices_status(scannerDevId, 'Discovery') # Much of this code adapted from killerbee/tools/zbstumbler:main @@ -87,16 +93,16 @@ def doScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False, stayti iteration += 1 if seqnum > 255: seqnum = 0 try: - #if verbose: print 'Setting channel to %d' % channel + #if verbose: print('Setting channel to %d' % channel) kbscan.set_channel(channel) except Exception as e: raise Exception('Failed to set channel to %d (%s).' % (channel,e)) if verbose: - print 'Injecting a beacon request on channel %d.' % channel + print('Injecting a beacon request on channel %d.' % channel) try: beaconinj = beaconp1 + "%c" % seqnum + beaconp2 kbscan.inject(beaconinj) - except Exception, e: + except Exception as e: raise Exception('Unable to inject packet (%s).' % e) # Process packets for staytime (default 2 seconds) looking for the beacon response frame @@ -106,7 +112,7 @@ def doScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False, stayti recvpkt = kbscan.pnext() #get a packet (is non-blocking) # Check for empty packet (timeout) and valid FCS if recvpkt != None and recvpkt['validcrc']: - #if verbose: print "Received frame." + #if verbose: print("Received frame.") newNetworkChannel = doScan_processResponse(recvpkt, channel, zbdb, kbscan, verbose=verbose, dblog=dblog) if newNetworkChannel != None: startCapture(zbdb, newNetworkChannel, gps=currentGPS, dblog=dblog) @@ -115,21 +121,21 @@ def doScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False, stayti elif agressive: # we may care even though it wasn't a beacon nonbeacons += 1 if verbose: - print 'Received frame (# %d) is not a beacon.' % nonbeacons, toHex(recvpkt['bytes']) + print('Received frame (# %d) is not a beacon.' % nonbeacons, toHex(recvpkt['bytes'])) # If we're in agressive mode and didn't see a beacon, we have nonbeacons > 0. # If we aren't logging the channel currently, and # If we have already tried a loop through without being agressive if nonbeacons > 0 and iteration > MIN_ITERATIONS_AGRESSIVE and zbdb.channel_status_logging(channel) == False: if verbose: - print "Start capture on %d as a channel without beacon." % channel + print("Start capture on %d as a channel without beacon." % channel) #TODO # Maybe just increase a count and increase stay time on this channel to see if we get a few packets, thus making us care? # Maybe also do at least a full loop first every so often before going after these random packets... startCapture(zbdb, channel, gps=currentGPS, dblog=dblog) #elif verbose: - # print "Had {0} nonbeacon packets on loop iteration {1} and found that channel {2} being already logged was {3}.".format( - # nonbeacons, iteration, channel, zbdb.channel_status_logging(channel)) + # print("Had {0} nonbeacon packets on loop iteration {1} and found that channel {2} being already logged was {3}.".format( + # nonbeacons, iteration, channel, zbdb.channel_status_logging(channel))) kbscan.sniffer_off() seqnum += 1 From 225a0b0466d41f05c04c1b023f68d7e86ad32922 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:34:18 +0100 Subject: [PATCH 10/16] Update testGPS.py --- killerbee_extras_tools/zbwardrive/testGPS.py | 27 +++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/testGPS.py b/killerbee_extras_tools/zbwardrive/testGPS.py index 53a1656..8851eb4 100644 --- a/killerbee_extras_tools/zbwardrive/testGPS.py +++ b/killerbee_extras_tools/zbwardrive/testGPS.py @@ -1,4 +1,7 @@ -import gps, os, time +import os +import time + +import gps session = gps.gps() session.poll() @@ -10,18 +13,18 @@ # a = altitude, d = date/time, m=mode, # o=postion/fix, s=status, y=satellites - print - print ' GPS reading' - print '----------------------------------------' - print 'fix ' , ("NO_FIX","FIX","DGPS_FIX")[session.fix.mode - 1] - print 'latitude ' , session.fix.latitude - print 'longitude ' , session.fix.longitude - print 'time utc ' , session.utc, session.fix.time - print 'altitude ' , session.fix.altitude + print('') + print(' GPS reading') + print('----------------------------------------') + print('fix ' , ("NO_FIX","FIX","DGPS_FIX")[session.fix.mode - 1]) + print('latitude ' , session.fix.latitude) + print('longitude ' , session.fix.longitude) + print('time utc ' , session.utc, session.fix.time) + print('altitude ' , session.fix.altitude) - print - print ' Satellites (total of', len(session.satellites) , ' in view)' + print('') + print(' Satellites (total of', len(session.satellites) , ' in view)') for i in session.satellites: - print '\t', i + print('\t', i) time.sleep(3) From 0d6152144a322d5c41d01b3f1182d51c4ed4fadc Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:34:31 +0100 Subject: [PATCH 11/16] Update zbwardrive.py --- .../zbwardrive/zbwardrive.py | 78 ++++--------------- 1 file changed, 13 insertions(+), 65 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/zbwardrive.py b/killerbee_extras_tools/zbwardrive/zbwardrive.py index 24e1160..99421fa 100644 --- a/killerbee_extras_tools/zbwardrive/zbwardrive.py +++ b/killerbee_extras_tools/zbwardrive/zbwardrive.py @@ -4,17 +4,12 @@ # rmspeers 2010-13 # ZigBee/802.15.4 WarDriving Platform -import sys -import argparse from time import sleep -from multiprocessing import Process, Manager from usb import USBError from killerbee import KillerBee, kbutils -from db import ZBScanDB -from scanning import doScan - -GPS_FREQUENCY=3 #in seconds +from .db import ZBScanDB +from .scanning import doScan # GPS Poller def gpsdPoller(currentGPS): @@ -22,7 +17,7 @@ def gpsdPoller(currentGPS): @type currentGPS multiprocessing.Manager dict manager @arg currentGPS store relavent pieces of up-to-date GPS info ''' - import gps + from . import gps gpsd = gps.gps() gpsd.poll() gpsd.stream() @@ -34,40 +29,34 @@ def gpsdPoller(currentGPS): lat = gpsd.fix.latitude lng = gpsd.fix.longitude alt = gpsd.fix.altitude - #print 'latitude ' , lat - #print 'longitude ' , lng #TODO do we want to use the GPS time in any way? - #print 'time utc ' , gpsd.utc,' + ', gpsd.fix.time - #print 'altitude (m)' , alt currentGPS['lat'] = lat currentGPS['lng'] = lng currentGPS['alt'] = alt else: - print "Waiting for a GPS fix." + print("Waiting for a GPS fix.") #TODO timeout lat/lng/alt values if too old...? - sleep(GPS_FREQUENCY) except KeyboardInterrupt: - print "Got KeyboardInterrupt in gpsdPoller, returning." + print("Got KeyboardInterrupt in gpsdPoller, returning.") return # startScan # Detects attached interfaces # Initiates scanning using doScan() -def startScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False): +def startScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False, include=[], ignore=None): try: kb = KillerBee() - except usb.USBError, e: + except USBError as e: if e.args[0].find('Operation not permitted') >= 0: - print 'Error: Permissions error, try running using sudo.' + print('Error: Permissions error, try running using sudo.') else: - print 'Error: USBError:', e + print('Error: USBError:', e) return False - except Exception, e: - #print 'Error: Missing KillerBee USB hardware:', e - print 'Error: Issue starting KillerBee instance:', e + except Exception as e: + print('Error: Issue starting KillerBee instance:', e) return False - for kbdev in kbutils.devlist(): - print 'Found device at %s: \'%s\'' % (kbdev[0], kbdev[1]) + for kbdev in kbutils.devlist(gps=ignore, include=include): + print('Found device at %s: \'%s\'' % (kbdev[0], kbdev[1])) zbdb.store_devices( kbdev[0], #devid kbdev[1], #devstr @@ -76,46 +65,5 @@ def startScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False): doScan(zbdb, currentGPS, verbose=verbose, dblog=dblog, agressive=agressive) return True -# Command line main function -if __name__=='__main__': - # Command line parsing - parser = argparse.ArgumentParser(description=""" -Use any attached KillerBee-supported capture devices to preform a wardrive, -by using a single device to iterate through channels and send beacon requests -while other devices are assigned to capture all packets on a channel after -it is selected as 'of interest' which can change based on the -a flag. -""") - parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', - help='Produce more output, for debugging') - parser.add_argument('-d', '--db', dest='dblog', action='store_true', - help='Enable KillerBee\'s log-to-database functionality') - parser.add_argument('-a', '--agressive', dest='agressive', action='store_true', - help='Initiate capture on channels where packets were seen, even if no beacon response was received') - parser.add_argument('-g', '--gps', dest='gps', action='store_true', - help='Connect to gpsd and grab location data as available to enhance PCAPs') - args = parser.parse_args() - - # try-except block to catch keyboard interrupt. - zbdb = None - gpsp = None - try: - # Some shared state for multiprocessing use - manager = Manager() - devices = manager.dict() - currentGPS = None - if args.gps: - currentGPS = manager.dict() - gpsp = Process(target=gpsdPoller, args=(currentGPS, )) - gpsp.start() - - zbdb = ZBScanDB() - #TODO check return value from startScan - startScan(zbdb, currentGPS, verbose=args.verbose, dblog=args.dblog, agressive=args.agressive) - zbdb.close() - - except KeyboardInterrupt: - print 'Shutting down' - if zbdb != None: zbdb.close() - if gpsp != None: gpsp.terminate() From 0bede1dcc3b383f819303da49a127534cb7c1af5 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:35:25 +0100 Subject: [PATCH 12/16] Update __init__.py --- killerbee_extras_tools/zbwardrive/gps/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/gps/__init__.py b/killerbee_extras_tools/zbwardrive/gps/__init__.py index 8766f7c..5d26398 100644 --- a/killerbee_extras_tools/zbwardrive/gps/__init__.py +++ b/killerbee_extras_tools/zbwardrive/gps/__init__.py @@ -6,8 +6,8 @@ api_major_version = 4 # bumped on incompatible changes api_minor_version = 1 # bumped on compatible changes -from gps import * -from misc import * +from .gps import * +from .misc import * # The 'client' module exposes some C utility functions for Python clients. # The 'packet' module exposes the packet getter via a Python interface. From ec71b758486f05b1a2e4d167601ebf06774d382b Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:35:39 +0100 Subject: [PATCH 13/16] Update client.py --- .../zbwardrive/gps/client.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/gps/client.py b/killerbee_extras_tools/zbwardrive/gps/client.py index 6a62da5..cf0cc55 100644 --- a/killerbee_extras_tools/zbwardrive/gps/client.py +++ b/killerbee_extras_tools/zbwardrive/gps/client.py @@ -31,24 +31,24 @@ def connect(self, host, port): host, port = host[:i], host[i+1:] try: port = int(port) except ValueError: - raise socket.error, "nonnumeric port" + raise socket.error("nonnumeric port") #if self.verbose > 0: - # print 'connect:', (host, port) + # print('connect:', (host, port)) msg = "getaddrinfo returns an empty list" self.sock = None for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res try: self.sock = socket.socket(af, socktype, proto) - #if self.debuglevel > 0: print 'connect:', (host, port) + #if self.debuglevel > 0: print('connect:', (host, port)) self.sock.connect(sa) - except socket.error, msg: + except socket.error as msg: #if self.debuglevel > 0: print 'connect fail:', (host, port) self.close() continue break if not self.sock: - raise socket.error, msg + raise socket.error(msg) def close(self): if self.sock: @@ -128,14 +128,14 @@ def json_unpack(self, buf): def asciify(d): "De-Unicodify everything so we can copy dicts into Python objects." t = {} - for (k, v) in d.items(): + for (k, v) in list(d.items()): ka = k.encode("ascii") - if type(v) == type(u"x"): + if type(v) == type("x"): va = v.encode("ascii") elif type(v) == type({}): va = asciify(v) elif type(v) == type([]): - va = map(asciify, v) + va = list(map(asciify, v)) else: va = v t[ka] = va @@ -143,7 +143,7 @@ def asciify(d): self.data = dictwrapper(**asciify(json.loads(buf.strip(), encoding="ascii"))) # Should be done for any other array-valued subobjects, too. if self.data["class"] == "SKY" and hasattr(self.data, "satellites"): - self.data.satellites = map(lambda x: dictwrapper(**x), self.data.satellites) + self.data.satellites = [dictwrapper(**x) for x in self.data.satellites] def stream(self, flags=0, outfile=None): "Control streaming reports from the daemon," @@ -182,7 +182,7 @@ def __init__(self, **ddict): def get(self, k, d=None): return self.__dict__.get(k, d) def keys(self): - return self.__dict__.keys() + return list(self.__dict__.keys()) def __getitem__(self, key): "Emulate dictionary, for new-style interface." return self.__dict__[key] From c2a30cfe54bf03ddac088975af694ade6d10e97e Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:35:50 +0100 Subject: [PATCH 14/16] Update gps.py --- killerbee_extras_tools/zbwardrive/gps/gps.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/gps/gps.py b/killerbee_extras_tools/zbwardrive/gps/gps.py index 9b2c62f..5eb695d 100755 --- a/killerbee_extras_tools/zbwardrive/gps/gps.py +++ b/killerbee_extras_tools/zbwardrive/gps/gps.py @@ -15,7 +15,7 @@ # now live in a different module. # import time -from client import * +from .client import * NaN = float('nan') def isnan(x): return str(x) == 'nan' @@ -235,14 +235,14 @@ def default(i, vbit=0, cnv=float): d1 = int(prefix.pop()) newsats = [] for i in range(d1): - newsats.append(gps.satellite(*map(int, satellites[i].split()))) + newsats.append(gps.satellite(*list(map(int, satellites[i].split())))) self.satellites = newsats self.valid |= SATELLITE_SET def __oldstyle_shim(self): # The rest is backwards compatibility for the old interface def default(k, dflt, vbit=0): - if k not in self.data.keys(): + if k not in list(self.data.keys()): return dflt else: self.valid |= vbit @@ -283,7 +283,7 @@ def default(k, dflt, vbit=0): elif self.data.get("class") == "SKY": for attrp in "xyvhpg": setattr(self, attrp+"dop", default(attrp+"dop", NaN, DOP_SET)) - if "satellites" in self.data.keys(): + if "satellites" in list(self.data.keys()): self.satellites = [] for sat in self.data['satellites']: self.satellites.append(gps.satellite(PRN=sat['PRN'], elevation=sat['el'], azimuth=sat['az'], ss=sat['ss'], used=sat['used'])) @@ -314,7 +314,7 @@ def poll(self): self.valid |= PACKET_SET return 0 - def next(self): + def __next__(self): if self.poll() == -1: raise StopIteration if hasattr(self, "data"): @@ -356,7 +356,7 @@ def stream(self, flags=0, outfile=None): if switch == '-v': verbose = True if len(arguments) > 2: - print 'Usage: gps.py [-v] [host [port]]' + print('Usage: gps.py [-v] [host [port]]') sys.exit(1) opts = { "verbose" : verbose } @@ -369,6 +369,6 @@ def stream(self, flags=0, outfile=None): session.set_raw_hook(lambda s: sys.stdout.write(s.strip() + "\n")) session.stream(WATCH_ENABLE|WATCH_NEWSTYLE) for report in session: - print report + print(report) # gps.py ends here From 92871e8e6e5544322fa04b74bdf5aa43c9f22bd2 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:35:58 +0100 Subject: [PATCH 15/16] Update misc.py --- killerbee_extras_tools/zbwardrive/gps/misc.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/killerbee_extras_tools/zbwardrive/gps/misc.py b/killerbee_extras_tools/zbwardrive/gps/misc.py index 021874d..45762e4 100644 --- a/killerbee_extras_tools/zbwardrive/gps/misc.py +++ b/killerbee_extras_tools/zbwardrive/gps/misc.py @@ -50,8 +50,10 @@ def CalcRad(lat): r = r * 1000.0 # Convert to meters return r -def EarthDistance((lat1, lon1), (lat2, lon2)): +def EarthDistance(xxx_todo_changeme, xxx_todo_changeme1): "Distance in meters between two points specified in degrees." + (lat1, lon1) = xxx_todo_changeme + (lat2, lon2) = xxx_todo_changeme1 x1 = CalcRad(lat1) * math.cos(Deg2Rad(lon1)) * math.sin(Deg2Rad(90-lat1)) x2 = CalcRad(lat2) * math.cos(Deg2Rad(lon2)) * math.sin(Deg2Rad(90-lat2)) y1 = CalcRad(lat1) * math.sin(Deg2Rad(lon1)) * math.sin(Deg2Rad(90-lat1)) @@ -67,8 +69,10 @@ def EarthDistance((lat1, lon1), (lat2, lon2)): elif a < -1: a = -1 return CalcRad((lat1+lat2) / 2) * math.acos(a) -def MeterOffset((lat1, lon1), (lat2, lon2)): +def MeterOffset(xxx_todo_changeme2, xxx_todo_changeme3): "Return offset in meters of second arg from first." + (lat1, lon1) = xxx_todo_changeme2 + (lat2, lon2) = xxx_todo_changeme3 dx = EarthDistance((lat1, lon1), (lat1, lon2)) dy = EarthDistance((lat1, lon1), (lat2, lon1)) if lat1 < lat2: dy *= -1 @@ -83,7 +87,7 @@ def isotime(s): date = int(s) msec = s - date date = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(s)) - return date + "." + `msec`[2:] + return date + "." + repr(msec)[2:] elif type(s) == type(""): if s[-1] == "Z": s = s[:-1] From a2f95fb04ba4ebaacad66e44aa5449ed60a165e9 Mon Sep 17 00:00:00 2001 From: You Gotta Hack That Date: Fri, 16 Sep 2022 16:40:06 +0100 Subject: [PATCH 16/16] Update zbwardrive.py Lost the __main__ function owing to the merge. Restored. --- .../zbwardrive/zbwardrive.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/killerbee_extras_tools/zbwardrive/zbwardrive.py b/killerbee_extras_tools/zbwardrive/zbwardrive.py index 99421fa..4c933a0 100644 --- a/killerbee_extras_tools/zbwardrive/zbwardrive.py +++ b/killerbee_extras_tools/zbwardrive/zbwardrive.py @@ -66,4 +66,44 @@ def startScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False, inc return True +# Command line main function +if __name__=='__main__': + # Command line parsing + parser = argparse.ArgumentParser(description=""" +Use any attached KillerBee-supported capture devices to preform a wardrive, +by using a single device to iterate through channels and send beacon requests +while other devices are assigned to capture all packets on a channel after +it is selected as 'of interest' which can change based on the -a flag. +""") + parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', + help='Produce more output, for debugging') + parser.add_argument('-d', '--db', dest='dblog', action='store_true', + help='Enable KillerBee\'s log-to-database functionality') + parser.add_argument('-a', '--agressive', dest='agressive', action='store_true', + help='Initiate capture on channels where packets were seen, even if no beacon response was received') + parser.add_argument('-g', '--gps', dest='gps', action='store_true', + help='Connect to gpsd and grab location data as available to enhance PCAPs') + args = parser.parse_args() + # try-except block to catch keyboard interrupt. + zbdb = None + gpsp = None + try: + # Some shared state for multiprocessing use + manager = Manager() + devices = manager.dict() + currentGPS = None + if args.gps: + currentGPS = manager.dict() + gpsp = Process(target=gpsdPoller, args=(currentGPS, )) + gpsp.start() + + zbdb = ZBScanDB() + #TODO check return value from startScan + startScan(zbdb, currentGPS, verbose=args.verbose, dblog=args.dblog, agressive=args.agressive) + zbdb.close() + + except KeyboardInterrupt: + print 'Shutting down' + if zbdb != None: zbdb.close() + if gpsp != None: gpsp.terminate()