Package killerbee :: Package zbwardrive :: Module scanning
[hide private]
[frames] | no frames]

Source Code for Module killerbee.zbwardrive.scanning

  1  #!/usr/bin/env python 
  2   
  3  import sys 
  4  import string 
  5  import socket 
  6  import struct 
  7   
  8  from killerbee import * 
  9  from db import toHex 
 10  from capture import startCapture 
 11  try: 
 12          from scapy.all import Dot15d4, Dot15d4Beacon 
 13  except ImportError: 
 14          print 'This Requires Scapy To Be Installed.' 
 15          from sys import exit 
 16          exit(-1) 
 17   
 18  #TODO set iteration min to a sensical parameter 
 19  MIN_ITERATIONS_AGRESSIVE = 0 
 20   
 21  # doScan_processResponse 
22 -def doScan_processResponse(packet, channel, zbdb, kbscan, verbose=False, dblog=False):
23 scapyd = Dot15d4(packet['bytes']) 24 # Check if this is a beacon frame 25 if isinstance(scapyd.payload, Dot15d4Beacon): 26 if verbose: print "Received frame is a beacon." 27 try: 28 spanid = scapyd.src_panid 29 source = scapyd.src_addr 30 except Exception as e: 31 print "DEBUG: Issue fetching src panid/addr from scapy packet ({0}).".format(e) 32 print "\t{0}".format(scapyd.summary()) 33 print scapyd.show2() 34 print "-"*25 35 return None #ignore this received frame for now 36 key = '%x%x' % (spanid, source) 37 #TODO if channel already being logged, ignore it as something new to capture 38 if zbdb.channel_status_logging(channel) == False: 39 if verbose: 40 print "A network on a channel that is not currently being logged replied to our beacon request." 41 # Store the network in local database so we treat it as already discovered by this program: 42 zbdb.store_networks(key, spanid, source, channel, packet['bytes']) 43 # Log to the mysql db or to the appropriate pcap file 44 if dblog == True: 45 kbscan.dblog.add_packet(full=packet, scapy=scapyd) 46 else: 47 #TODO log this to a PPI pcap file maybe, so the packet is not lost? or print to screen? 48 pass 49 return channel 50 else: #network designated by key is already being logged 51 if verbose: 52 print 'Received frame is a beacon for a network we already found and are logging.' 53 return None 54 else: #frame doesn't look like a beacon according to scapy 55 return None
56 # --- end of doScan_processResponse --- 57 58 # doScan
59 -def doScan(zbdb, currentGPS, verbose=False, dblog=False, agressive=False, staytime=2):
60 # Choose a device for injection scanning: 61 scannerDevId = zbdb.get_devices_nextFree() 62 # log to online mysql db or to some local pcap files? 63 kbscan = KillerBee(device=scannerDevId, datasource=("Wardrive Live" if dblog else None)) 64 # we want one that can do injection 65 inspectedDevs = [] 66 while (kbscan.check_capability(KBCapabilities.INJECT) == False): 67 zbdb.update_devices_status(scannerDevId, 'Ignore') 68 inspectedDevs.append(scannerDevId) 69 kbscan.close() 70 scannerDevId = zbdb.get_devices_nextFree() 71 if scannerDevId == None: 72 raise Exception("Error: No free devices capable of injection were found.") 73 kbscan = KillerBee(device=scannerDevId, datasource=("Wardrive Live" if dblog else None)) 74 # return devices that we didn't choose to the free state 75 for inspectedDevId in inspectedDevs: 76 zbdb.update_devices_status(inspectedDevId, 'Free') 77 print 'Network discovery device is %s' % (scannerDevId) 78 zbdb.update_devices_status(scannerDevId, 'Discovery') 79 80 # Much of this code adapted from killerbee/tools/zbstumbler:main 81 # Could build this with Scapy but keeping manual construction for performance 82 beacon = "\x03\x08\x00\xff\xff\xff\xff\x07" #beacon frame 83 beaconp1 = beacon[0:2] #beacon part before seqnum field 84 beaconp2 = beacon[3:] #beacon part after seqnum field 85 seqnum = 0 #seqnum to use (will cycle) 86 channel = 11 #starting channel (will cycle) 87 iteration = 0 #how many loops have we done through the channels? 88 # Loop injecting and receiving packets 89 while 1: 90 if channel > 26: 91 channel = 11 92 iteration += 1 93 if seqnum > 255: seqnum = 0 94 try: 95 #if verbose: print 'Setting channel to %d' % channel 96 kbscan.set_channel(channel) 97 except Exception as e: 98 raise Exception('Failed to set channel to %d (%s).' % (channel,e)) 99 if verbose: 100 print 'Injecting a beacon request on channel %d.' % channel 101 try: 102 beaconinj = beaconp1 + "%c" % seqnum + beaconp2 103 kbscan.inject(beaconinj) 104 except Exception, e: 105 raise Exception('Unable to inject packet (%s).' % e) 106 107 # Process packets for staytime (default 2 seconds) looking for the beacon response frame 108 endtime = time.time() + staytime 109 nonbeacons = 0 110 while (endtime > time.time()): 111 recvpkt = kbscan.pnext() #get a packet (is non-blocking) 112 # Check for empty packet (timeout) and valid FCS 113 if recvpkt != None and recvpkt['validcrc']: 114 #if verbose: print "Received frame." 115 newNetworkChannel = doScan_processResponse(recvpkt, channel, zbdb, kbscan, verbose=verbose, dblog=dblog) 116 if newNetworkChannel != None: 117 startCapture(zbdb, newNetworkChannel, gps=currentGPS, dblog=dblog) 118 nonbeacons = 0 # forget about any non-beacons, as we don't care, we saw a beacon! 119 break # made up our mind, stop wasting time 120 elif agressive: # we may care even though it wasn't a beacon 121 nonbeacons += 1 122 if verbose: 123 print 'Received frame (# %d) is not a beacon.' % nonbeacons, toHex(recvpkt['bytes']) 124 125 # If we're in agressive mode and didn't see a beacon, we have nonbeacons > 0. 126 # If we aren't logging the channel currently, and 127 # If we have already tried a loop through without being agressive 128 if nonbeacons > 0 and iteration > MIN_ITERATIONS_AGRESSIVE and zbdb.channel_status_logging(channel) == False: 129 if verbose: 130 print "Start capture on %d as a channel without beacon." % channel 131 #TODO 132 # Maybe just increase a count and increase stay time on this channel to see if we get a few packets, thus making us care? 133 # Maybe also do at least a full loop first every so often before going after these random packets... 134 startCapture(zbdb, channel, gps=currentGPS, dblog=dblog) 135 #elif verbose: 136 # print "Had {0} nonbeacon packets on loop iteration {1} and found that channel {2} being already logged was {3}.".format( 137 # nonbeacons, iteration, channel, zbdb.channel_status_logging(channel)) 138 139 kbscan.sniffer_off() 140 seqnum += 1 141 channel += 1 142 143 #TODO currently unreachable code, but maybe add a condition to break the infinite while loop in some circumstance to free that device for capture? 144 kbscan.close() 145 zbdb.update_devices_status(scannerDevId, 'Free')
146 # --- end of doScan --- 147