def __init__(self): """ Setup and build the bunny model and starts the read_packet_thread() """ self.inandout = SendRec() self.cryptor = AEScrypt() self.model = TrafficModel() # each item should be an full bunny message that can be passed to the .decrypt() method # TODO: put a upper bound of number of messages or a cleanup thread to clear out old messages # if not consumed. self.msg_queue = Queue.LifoQueue() # The out queue is a FiFo Queue because it maintaines the ordering of the bunny data # format: [data, Bool (relay or not)] self.out_queue = Queue.Queue() # The Deque is used because it is a thread safe iterable that can be filled with 'seen' # messages between the send and recv threads. self.msg_deque = [] # init the threads and name them self.workers = [BunnyReadThread(self.msg_queue, self.out_queue, self.inandout, self.model, self.cryptor), \ BroadCaster(self.out_queue, self.inandout, self.model)] self.workers[0].name = "BunnyReadThread" self.workers[1].name = "BroadCasterThread" # spin up the threads for worker in self.workers: worker.daemon = True worker.start()
def __init__(self): """ Starts up the model, collects data and inserts it into its respective lists """ # clear any old data self.mac_addresses = [] self.type_ranges = [] self.data = [] # spin up and build the model self.interface = SendRec() self.collectData() self.stripRadioTap() self.extractModel() self.insertTemplates()
class TrafficModel(): """ Builds a model of current traffic that can be used at a later time to make packets. """ # In network byte order # If you do a lookup on this table and dont find a match it is probly # a 'reserved' type. Dot11_Types = { # management "assocReq": "\x00", "assocRes": "\x10", "reAssocReq": "\x20", "reAssocRes": "\x30", "probeReq": "\x40", "probeRes": "\x50", "beacon": "\x80", "ATIM": "\x90", "disAssoc": "\xa0", "auth": "\xb0", "deAuth": "\xc0", "action": "\xd0", # control "blockAckReq": "\x81", "blockAck": "\x91", "PSPoll": "\xa1", "RTS": "\xb1", "CTS": "\xc1", "ACK": "\xd1", "ACK2": "\xd4", "CFend": "\xe1", "CFendCFack": "\xf1", # data "data": "\x02", "data-CFAck": "\x12", "data-CFPoll": "\x22", "data-CFAckPoll": "\x32", "dataNULL": "\x42", "dataNULLfunc": "\x48", "data-CFAckNULL": "\x52", "data-CFPollNULL": "\x62", "data-CFAckPollNULL": "\x72", "dataQOS": "\x82", "dataQOS2": "\x88", "dataQOS-CFAck": "\x92", "dataQOS-CFPoll": "\xa2", "dataQOS-CFAckPoll": "\xb2", "dataQOSNULL": "\x82", # wtf why? "dataQOS-CFPollNULL": "\xe2", "dataQOS-CFAckPollNULL": "\xf2", } # Model attributes: # -Type ranges # -MAC addresses # - # raw packets data = [] # [type, freq, template, injectlen] type_ranges = [] # [addr, freq, AP(bool)] mac_addresses = [] # FCS is the number of bytes for the Checksum if it is found in stripRadioTap() FCS = 0 def __init__(self): """ Starts up the model, collects data and inserts it into its respective lists """ # clear any old data self.mac_addresses = [] self.type_ranges = [] self.data = [] # spin up and build the model self.interface = SendRec() self.collectData() self.stripRadioTap() self.extractModel() self.insertTemplates() def collectData(self): """ Collect packets for the pre determined amount of time. """ start_time = time.time() current_time = start_time # caplength is a glocal var from config. while ( (current_time - start_time) < CAPLENGTH): packet = self.interface.recvRaw() self.data.append(packet) current_time = time.time() def stripRadioTap(self): """ Strips the RadioTap header info out of the packets are replaces the data list with the new packets. It also checks if this hardware has FCS (Frame Check sums's) at the end """ temp_data = [] # Check for FCS flag in the radiotap header flags = self.data[0][4:8] flags = struct.unpack("i", flags)[0] # bval idx if ((flags & (1 << 0)) != 0): subflags = self.data[0][16:17] subflags = struct.unpack("B", subflags)[0] else: subflags = self.data[0][8:9] subflags = struct.unpack("B", subflags)[0] if ((flags & (1 << 1)) != 0): if ((subflags & (1 << 4)) != 0): self.FCS = 4 if DEBUG: print "FCS: %s" % (self.FCS) # now strip the headers. for packet in self.data: sizeHead = struct.unpack("<H", packet[2:4]) temp_data.append(packet[sizeHead[0]:]) self.data = temp_data def rawToType(self, type_raw): """ input the byte and return a string of the 802.11 type """ for k,v in self.Dot11_Types.iteritems(): if (v == type_raw[0]): return k return "reserved (" + binascii.hexlify(type_raw[0]) + ")" def buildModelTypes(self, graphs): """ Adds the extracted types and %'s to the model """ count = 0.0 for type in graphs: count += type[1] for type in graphs: type[1] = (type[1] / count) self.type_ranges.append(type) def buildModelAddresses(self, addresses): """" Adds the extracted addresses and %'s to the model """ count = 0.0 for addr in addresses: count += addr[1] for addr in addresses: addr[1] = (addr[1] / count) self.mac_addresses.append(addr) def extractModel(self): """ Loops through all collected packets and creates different aspects of the model """ graphs = [] addresses = [] # loop through all packets, then loop through all types, # append if the type is not found, # inrement count if it is. for packet in self.data: beacon = False # graphs[type, count] type = packet[:1] # check if its a beacon packet if(type == self.Dot11_Types['beacon']): beacon = True found = False for types in graphs: if (type == types[0]): types[1] = types[1] + 1 found = True if(found == False): graphs.append([type, 1, packet, 0]) # addresses[addr, count, AP?] # model common mac addresses used mac = packet[10:15] found = False for addr in addresses: if (mac == addr[0]): addr[1] = addr[1] + 1 found = True if(found == False): if (beacon == True): addresses.append([mac, 1, True]) else: addresses.append([mac, 1, False]) # sort by count graphs.sort(key=operator.itemgetter(1), reverse=True) addresses.sort(key=operator.itemgetter(1), reverse=True) self.buildModelTypes(graphs) self.buildModelAddresses(addresses) def insertTemplates(self): """ loops through the type_ranges list and replaces the raw packet data with template objects type_ranges becomes: [type, freq, templateObject, injectLen] """ for entry in self.type_ranges: if entry[0] is None: continue type = self.rawToType(entry[0]) if (type == "beacon"): # replace raw data with object of template type, then append the injection length entry[2] = Templates.Beacon(entry[2]) entry[3] = entry[2].injectable elif (type == "data" or type == "dataQOS" or type == "dataQOS2"): entry[2] = Templates.DataQOS(entry[2]) entry[3] = entry[2].injectable elif (type == "probeReq"): entry[2] = Templates.ProbeRequest(entry[2]) entry[3] = entry[2].injectable # add more def insertNewTemplate(self, raw_packet): """ This is a copy past of the insertTemplate() func but does not loop through, instead a raw_packet is passed in as an argument then, then this function finds its type and inserts it, if an corresponding Template exists returns false if the packet type does not have a template returns the entry in type_ranges[] if found TODO: Currently only lets this bunny instance READ with this packet type because there is zero frequency. """ entry = [0, 0, 0, 0] raw_type = raw_packet[:1] type = self.rawToType(raw_type) if (type == "beacon"): # replace raw data with object of template type, then append the injection length entry[0] = raw_type entry[2] = Templates.Beacon(raw_packet) entry[3] = entry[2].injectable elif (type == "data" or type == "dataQOS" or type == "dataQOS2"): entry[0] = raw_type entry[2] = Templates.DataQOS(raw_packet) entry[3] = entry[2].injectable elif (type == "probeReq"): entry[0] = raw_type entry[2] = Templates.ProbeRequest(raw_packet) entry[3] = entry[2].injectable else: entry = False return entry # debugging: def printTypes(self): """ Prints out a list of the packet types and percentages in the model """ print "%-15s%s" % ("Type", "Percent") print "-" * 20 for entry in self.type_ranges: print "%-15s%f" % (self.rawToType(entry[0]), entry[1]) def printTypesWithPackets(self): """ Prints out a list of the packet types and percentages in the model """ print "%-15s%-10s%s" % ("Type", "Percent", "Template") print "-" * 30 for entry in self.type_ranges: print "%-15s%-10f%s" % (self.rawToType(entry[0]), entry[1], binascii.hexlify(entry[2])) def printMacs(self): """ Prints out a list of src mac address and percentages in the model """ print "\n%-15s%-10s%s" % ("Addr", "Percent", "AP") print "-" * 30 for entry in self.mac_addresses: print "%-15s%-10f%s" % (binascii.hexlify(entry[0]), entry[1], entry[2]) def getEntryFrom(self, array): """ Returns a frequency adjusted random entry from an array such as type_ranges Follows the [name, freq, ...] structure. """ num = random.random() count = 0.0 for entry in array: count += entry[1] if count > num: break return entry
class TrafficModel(): """ Builds a model of current traffic that can be used at a later time to make packets. """ # In network byte order # If you do a lookup on this table and dont find a match it is probly # a 'reserved' type. Dot11_Types = { # management "assocReq": "\x00", "assocRes": "\x10", "reAssocReq": "\x20", "reAssocRes": "\x30", "probeReq": "\x40", "probeRes": "\x50", "beacon": "\x80", "ATIM": "\x90", "disAssoc": "\xa0", "auth": "\xb0", "deAuth": "\xc0", "action": "\xd0", # control "blockAckReq": "\x81", "blockAck": "\x91", "PSPoll": "\xa1", "RTS": "\xb1", "CTS": "\xc1", "ACK": "\xd1", "ACK2": "\xd4", "CFend": "\xe1", "CFendCFack": "\xf1", # data "data": "\x02", "data-CFAck": "\x12", "data-CFPoll": "\x22", "data-CFAckPoll": "\x32", "dataNULL": "\x42", "dataNULLfunc": "\x48", "data-CFAckNULL": "\x52", "data-CFPollNULL": "\x62", "data-CFAckPollNULL": "\x72", "dataQOS": "\x82", "dataQOS2": "\x88", "dataQOS-CFAck": "\x92", "dataQOS-CFPoll": "\xa2", "dataQOS-CFAckPoll": "\xb2", "dataQOSNULL": "\x82", # wtf why? "dataQOS-CFPollNULL": "\xe2", "dataQOS-CFAckPollNULL": "\xf2", } # Model attributes: # -Type ranges # -MAC addresses # - # raw packets data = [] # [type, freq, template, injectlen] type_ranges = [] # [addr, freq, AP(bool)] mac_addresses = [] # FCS is the number of bytes for the Checksum if it is found in stripRadioTap() FCS = 0 def __init__(self): """ Starts up the model, collects data and inserts it into its respective lists """ # clear any old data self.mac_addresses = [] self.type_ranges = [] self.data = [] # spin up and build the model self.interface = SendRec() self.collectData() self.stripRadioTap() self.extractModel() self.insertTemplates() def collectData(self): """ Collect packets for the pre determined amount of time. """ start_time = time.time() current_time = start_time # caplength is a glocal var from config. while ((current_time - start_time) < CAPLENGTH): packet = self.interface.recvRaw() self.data.append(packet) current_time = time.time() def stripRadioTap(self): """ Strips the RadioTap header info out of the packets are replaces the data list with the new packets. It also checks if this hardware has FCS (Frame Check sums's) at the end """ temp_data = [] # Check for FCS flag in the radiotap header flags = self.data[0][4:8] flags = struct.unpack("i", flags)[0] # bval idx if ((flags & (1 << 0)) != 0): subflags = self.data[0][16:17] subflags = struct.unpack("B", subflags)[0] else: subflags = self.data[0][8:9] subflags = struct.unpack("B", subflags)[0] if ((flags & (1 << 1)) != 0): if ((subflags & (1 << 4)) != 0): self.FCS = 4 if DEBUG: print "FCS: %s" % (self.FCS) # now strip the headers. for packet in self.data: sizeHead = struct.unpack("<H", packet[2:4]) temp_data.append(packet[sizeHead[0]:]) self.data = temp_data def rawToType(self, type_raw): """ input the byte and return a string of the 802.11 type """ for k, v in self.Dot11_Types.iteritems(): if (v == type_raw[0]): return k return "reserved (" + binascii.hexlify(type_raw[0]) + ")" def buildModelTypes(self, graphs): """ Adds the extracted types and %'s to the model """ count = 0.0 for type in graphs: count += type[1] for type in graphs: type[1] = (type[1] / count) self.type_ranges.append(type) def buildModelAddresses(self, addresses): """" Adds the extracted addresses and %'s to the model """ count = 0.0 for addr in addresses: count += addr[1] for addr in addresses: addr[1] = (addr[1] / count) self.mac_addresses.append(addr) def extractModel(self): """ Loops through all collected packets and creates different aspects of the model """ graphs = [] addresses = [] # loop through all packets, then loop through all types, # append if the type is not found, # inrement count if it is. for packet in self.data: beacon = False # graphs[type, count] type = packet[:1] # check if its a beacon packet if (type == self.Dot11_Types['beacon']): beacon = True found = False for types in graphs: if (type == types[0]): types[1] = types[1] + 1 found = True if (found == False): graphs.append([type, 1, packet, 0]) # addresses[addr, count, AP?] # model common mac addresses used mac = packet[10:15] found = False for addr in addresses: if (mac == addr[0]): addr[1] = addr[1] + 1 found = True if (found == False): if (beacon == True): addresses.append([mac, 1, True]) else: addresses.append([mac, 1, False]) # sort by count graphs.sort(key=operator.itemgetter(1), reverse=True) addresses.sort(key=operator.itemgetter(1), reverse=True) self.buildModelTypes(graphs) self.buildModelAddresses(addresses) def insertTemplates(self): """ loops through the type_ranges list and replaces the raw packet data with template objects type_ranges becomes: [type, freq, templateObject, injectLen] """ for entry in self.type_ranges: type = self.rawToType(entry[0]) if (type == "beacon"): # replace raw data with object of template type, then append the injection length entry[2] = Templates.Beacon(entry[2]) entry[3] = entry[2].injectable elif (type == "data" or type == "dataQOS" or type == "dataQOS2"): entry[2] = Templates.DataQOS(entry[2]) entry[3] = entry[2].injectable elif (type == "probeReq"): entry[2] = Templates.ProbeRequest(entry[2]) entry[3] = entry[2].injectable # add more def insertNewTemplate(self, raw_packet): """ This is a copy past of the insertTemplate() func but does not loop through, instead a raw_packet is passed in as an argument then, then this function finds its type and inserts it, if an corresponding Template exists returns false if the packet type does not have a template returns the entry in type_ranges[] if found TODO: Currently only lets this bunny instance READ with this packet type because there is zero frequency. """ entry = [0, 0, 0, 0] raw_type = raw_packet[:1] type = self.rawToType(raw_type) if (type == "beacon"): # replace raw data with object of template type, then append the injection length entry[0] = raw_type entry[2] = Templates.Beacon(raw_packet) entry[3] = entry[2].injectable elif (type == "data" or type == "dataQOS" or type == "dataQOS2"): entry[0] = raw_type entry[2] = Templates.DataQOS(raw_packet) entry[3] = entry[2].injectable elif (type == "probeReq"): entry[0] = raw_type entry[2] = Templates.ProbeRequest(raw_packet) entry[3] = entry[2].injectable else: entry = False return entry # debugging: def printTypes(self): """ Prints out a list of the packet types and percentages in the model """ print "%-15s%s" % ("Type", "Percent") print "-" * 20 for entry in self.type_ranges: print "%-15s%f" % (self.rawToType(entry[0]), entry[1]) def printTypesWithPackets(self): """ Prints out a list of the packet types and percentages in the model """ print "%-15s%-10s%s" % ("Type", "Percent", "Template") print "-" * 30 for entry in self.type_ranges: print "%-15s%-10f%s" % (self.rawToType( entry[0]), entry[1], binascii.hexlify(entry[2])) def printMacs(self): """ Prints out a list of src mac address and percentages in the model """ print "\n%-15s%-10s%s" % ("Addr", "Percent", "AP") print "-" * 30 for entry in self.mac_addresses: print "%-15s%-10f%s" % (binascii.hexlify( entry[0]), entry[1], entry[2]) def getEntryFrom(self, array): """ Returns a frequency adjusted random entry from an array such as type_ranges Follows the [name, freq, ...] structure. """ num = random.random() count = 0.0 for entry in array: count += entry[1] if count > num: break return entry
import SendRec as sr while True: try: sr.receive() #sr.send() except KeyboardInterrupt: break sr.close_connection()
import SendRec as sr while True: try: #sr.receive() sr.send() except KeyboardInterrupt: break sr.close_connection()