def test_capture_gets_encryption_and_override_perfs(): temp_c = Capture() for valid_encryption_type in temp_c.SUPPORTED_ENCRYPTION_STANDARDS: c = Capture(decryption_key='helloworld', encryption_type=valid_encryption_type, override_prefs={'esp.enable_null_encryption_decode_heuristic': 'TRUE', 'wlan.enable_decryption': 'TRUE', 'uat:80211_keys': '"{0}","helloworld"'.format(valid_encryption_type)}) params = c.get_parameters() expected_results = ('esp.enable_null_encryption_decode_heuristic:TRUE', 'wlan.enable_decryption:TRUE', 'uat:80211_keys:"{0}","helloworld"'.format(valid_encryption_type)) start_idx = 0 actual_parameter_options = [] while True: try: override_index = params.index('-o', start_idx) except ValueError: # no more '-o' options break override_actual_value = params[override_index +1] actual_parameter_options.append(override_actual_value) assert override_actual_value in expected_results # increment index start_idx = override_index + 1 assert set(actual_parameter_options) == set(expected_results) assert len(actual_parameter_options) == len(expected_results)
def test_capture_gets_encryption_and_override_perfs(): temp_c = Capture() for valid_encryption_type in temp_c.SUPPORTED_ENCRYPTION_STANDARDS: c = Capture(decryption_key='helloworld', encryption_type=valid_encryption_type, override_prefs={ 'esp.enable_null_encryption_decode_heuristic': 'TRUE', 'wlan.enable_decryption': 'TRUE', 'uat:80211_keys': '"{0}","helloworld"'.format(valid_encryption_type) }) params = c.get_parameters() expected_results = ( 'esp.enable_null_encryption_decode_heuristic:TRUE', 'wlan.enable_decryption:TRUE', 'uat:80211_keys:"{0}","helloworld"'.format(valid_encryption_type)) start_idx = 0 actual_parameter_options = [] while True: try: override_index = params.index('-o', start_idx) except ValueError: # no more '-o' options break override_actual_value = params[override_index + 1] actual_parameter_options.append(override_actual_value) assert override_actual_value in expected_results # increment index start_idx = override_index + 1 assert set(actual_parameter_options) == set(expected_results) assert len(actual_parameter_options) == len(expected_results)
def test_capture_gets_override_perfs(): c = Capture( override_prefs={'esp.enable_null_encryption_decode_heuristic': 'TRUE'}) params = c.get_parameters() override_index = params.index('-o') override_actual_value = params[override_index + 1] assert override_actual_value == 'esp.enable_null_encryption_decode_heuristic:TRUE'
def test_capture_gets_multiple_decoding_parameters(): c = Capture(decode_as={'tcp.port==8888': 'http', 'tcp.port==6666': 'dns'}) params = c.get_parameters() decode_index = params.index('-d') possible_results = ['tcp.port==8888,http', 'tcp.port==6666,dns'] assert params[decode_index + 1] in possible_results possible_results.remove(params[decode_index + 1]) decode_index = params.index('-d', decode_index + 1) assert params[decode_index + 1] == possible_results[0]
def test_capture_gets_multiple_override_perfs(): c = Capture(override_prefs={'esp.enable_null_encryption_decode_heuristic': 'TRUE', 'tcp.ls_payload_display_len':'80'}) params = c.get_parameters() expected_results = ('esp.enable_null_encryption_decode_heuristic:TRUE', 'tcp.ls_payload_display_len:80') start_idx = 0 for count in range(len(expected_results)): override_index = params.index('-o', start_idx) override_actual_value = params[override_index +1] assert override_actual_value in expected_results # increment index start_idx = override_index + 1
def test_capture_gets_multiple_override_perfs(): c = Capture( override_prefs={ 'esp.enable_null_encryption_decode_heuristic': 'TRUE', 'tcp.ls_payload_display_len': '80' }) params = c.get_parameters() expected_results = ('esp.enable_null_encryption_decode_heuristic:TRUE', 'tcp.ls_payload_display_len:80') start_idx = 0 for count in range(len(expected_results)): override_index = params.index('-o', start_idx) override_actual_value = params[override_index + 1] assert override_actual_value in expected_results # increment index start_idx = override_index + 1
def readMACAddresses(self, mode, selectedFile=None, consoleAddress=None, runningApplication=None): Probe_Request_Type = 4 self.runningApplication = runningApplication if (mode.lower() == "file"): try: self.source = selectedFile self.packets = pyshark.FileCapture( input_file=self.source, display_filter='wlan.fc.type_subtype eq 4') except: print("Could not find packet file!") elif (mode.lower() == "live"): try: self.source = "wlan0mon" self.packets = Capture( display_filter="wlan.fc.type_subtype eq 4") self.packets.load_packets(timeout=20, packet_count=10) except Exception as e: print( "Failed to run Live Capture, error message : {}".format(e)) """ Reads probe requests packets and extracts valuable parts """ for packet in self.packets: if "wlan_mgt" in packet: if int(packet.wlan_mgt.fc_type_subtype) == Probe_Request_Type: nossid = False if not str(packet.wlan_mgt.tag )[:34] == "Tag: SSID parameter set: Broadcast": ssid = packet.wlan_mgt.ssid oui = packet.wlan_mgt.tag_oui #self.appendToDict(packet.wlan.ta, ssid,oui, packet.sniff_time) else: nossid = True else: nossid = False try: if not str(packet[3].tag )[:34] == "Tag: SSID parameter set: Broadcast": ssid = packet[3].ssid try: oui = hex(int(packet[3].tag_oui)) oui = ("0" * (8 - len(oui)) + oui[(8 - len(oui)):]).upper() except: oui = 000000 try: htCap = packet[3].ht_capabilities except: htCap = 0 """-------------------------Extraction of Extended Capabilities------------------------""" extCapField = [] tempOcts = [] for extCapBit in range(0, 64): try: if (extCapBit == 41): """This is done since bit 41-43 are merged together as one variable within Wireshark/Pyshark""" threeBits = packet[ 3].extcap_serv_int_granularity for bit in range(0, 3): exec( 'tempOcts.append(threeBits & 0x0' + str(2 ^ bit) + ')') extCapBit = 43 elif (extCapBit == 60): """This is done since Wireshark 2.6.6 has a bug where the Protected QLoad report (bit 60) is read as bit 61""" tempOcts.append('0') else: exec('tempOcts.append(' + 'packet[3].extcap_b' + str(extCapBit) + ')') if "x" in tempOcts[extCapBit % 8]: tempOcts[extCapBit % 8] = int( tempOcts[extCapBit % 8][2:]) if ((extCapBit + 1) % 8 == 0) and extCapBit > 0: byteString = "" for item in range(0, 8): byteString = byteString + str( tempOcts[item]) tempOcts.clear() extCapField.append( str(int( (byteString[4:8])[::-1], 2)) + str(int( (byteString[:4])[::-1], 2))) except: pass print("Reading packet number: {}".format( packet.number)) """------------------------------------------------------------------------------------""" self.appendToDict( inputMAC=str(packet.wlan.ta), inputSSID=ssid, inputOUI=oui, inputHTCap=htCap, extCap=extCapField, timeStamp=packet.sniff_time, signalStrenght=packet.wlan_radio.signal_dbm) else: nossid = True except: pass return self.presentUniqueDevices()
class MACFingerPrinter: """ This program creates a python Dictionary with Randomized MAC-addresses as keys and Fingerprints as items. This is used to count mobile devices more accurately. """ def __init__(self): """ ----------------------Initiates the Dictionary------------------------------------ """ with open( "/home/andreas/Documents/Programming/Python/MACFingerPrinter/MACFingerprinter/assets/OUIs.json" ) as JSON_DATA: self.OUIs = json.load(JSON_DATA) self.MAC_Fingerprints = {} self.LocalBitSetSigns = ['2', '3', '6', '7', 'a', 'b', 'e', 'f'] self.UniqueDevices = [] self.PacketComparator = PacketComparator() self.timeAnalyser = TimeAnalyser2() def appendToDict(self, inputMAC, inputSSID, inputOUI, inputHTCap, extCap, timeStamp, signalStrenght): """ Adds the MAC and SSID to the dictionary if the MAC is new Adds SSID to corresponding MAC if the SSID has not been read to that MAC earlier :param inputMAC: MAC address read from probe request :param inputSSID: SSID read from probe request """ if ((str(inputMAC))[1] in self.LocalBitSetSigns): if inputMAC in self.MAC_Fingerprints.keys( ) and inputSSID not in self.MAC_Fingerprints[ inputMAC].getSSIDArray(): newFingerprint = self.MAC_Fingerprints[inputMAC] newFingerprint.addSSID(inputSSID, timeStamp) newFingerprint.addSignalStrengh(signalStrenght) self.MAC_Fingerprints[inputMAC] = newFingerprint else: fingerPrint = FingerPrint(SSID=inputSSID, OUI=inputOUI, timeStamp=timeStamp, extCap=extCap, htCap=inputHTCap) fingerPrint.addSignalStrengh(signalStrenght) self.MAC_Fingerprints[inputMAC] = fingerPrint else: if inputMAC not in self.MAC_Fingerprints.keys(): newFingerprint = FingerPrint(SSID=inputSSID, MAC=1, OUI=inputOUI, timeStamp=timeStamp, extCap=extCap, htCap=inputHTCap) newFingerprint.addSignalStrengh(signalStrenght) self.MAC_Fingerprints[inputMAC] = newFingerprint else: fingerPrint = self.MAC_Fingerprints[inputMAC] fingerPrint.addSSID(inputSSID) fingerPrint.addSignalStrengh(signalStrenght) self.MAC_Fingerprints[inputMAC] = fingerPrint self.MAC_Fingerprints[inputMAC].hashFingerPrint() #&& wlan_radio.signal_dbm > -90 def readMACAddresses(self, mode, selectedFile=None, consoleAddress=None, runningApplication=None): Probe_Request_Type = 4 self.runningApplication = runningApplication if (mode.lower() == "file"): try: self.source = selectedFile self.packets = pyshark.FileCapture( input_file=self.source, display_filter='wlan.fc.type_subtype eq 4') except: print("Could not find packet file!") elif (mode.lower() == "live"): try: self.source = "wlan0mon" self.packets = Capture( display_filter="wlan.fc.type_subtype eq 4") self.packets.load_packets(timeout=20, packet_count=10) except Exception as e: print( "Failed to run Live Capture, error message : {}".format(e)) """ Reads probe requests packets and extracts valuable parts """ for packet in self.packets: if "wlan_mgt" in packet: if int(packet.wlan_mgt.fc_type_subtype) == Probe_Request_Type: nossid = False if not str(packet.wlan_mgt.tag )[:34] == "Tag: SSID parameter set: Broadcast": ssid = packet.wlan_mgt.ssid oui = packet.wlan_mgt.tag_oui #self.appendToDict(packet.wlan.ta, ssid,oui, packet.sniff_time) else: nossid = True else: nossid = False try: if not str(packet[3].tag )[:34] == "Tag: SSID parameter set: Broadcast": ssid = packet[3].ssid try: oui = hex(int(packet[3].tag_oui)) oui = ("0" * (8 - len(oui)) + oui[(8 - len(oui)):]).upper() except: oui = 000000 try: htCap = packet[3].ht_capabilities except: htCap = 0 """-------------------------Extraction of Extended Capabilities------------------------""" extCapField = [] tempOcts = [] for extCapBit in range(0, 64): try: if (extCapBit == 41): """This is done since bit 41-43 are merged together as one variable within Wireshark/Pyshark""" threeBits = packet[ 3].extcap_serv_int_granularity for bit in range(0, 3): exec( 'tempOcts.append(threeBits & 0x0' + str(2 ^ bit) + ')') extCapBit = 43 elif (extCapBit == 60): """This is done since Wireshark 2.6.6 has a bug where the Protected QLoad report (bit 60) is read as bit 61""" tempOcts.append('0') else: exec('tempOcts.append(' + 'packet[3].extcap_b' + str(extCapBit) + ')') if "x" in tempOcts[extCapBit % 8]: tempOcts[extCapBit % 8] = int( tempOcts[extCapBit % 8][2:]) if ((extCapBit + 1) % 8 == 0) and extCapBit > 0: byteString = "" for item in range(0, 8): byteString = byteString + str( tempOcts[item]) tempOcts.clear() extCapField.append( str(int( (byteString[4:8])[::-1], 2)) + str(int( (byteString[:4])[::-1], 2))) except: pass print("Reading packet number: {}".format( packet.number)) """------------------------------------------------------------------------------------""" self.appendToDict( inputMAC=str(packet.wlan.ta), inputSSID=ssid, inputOUI=oui, inputHTCap=htCap, extCap=extCapField, timeStamp=packet.sniff_time, signalStrenght=packet.wlan_radio.signal_dbm) else: nossid = True except: pass return self.presentUniqueDevices() def processFingerprints(self): starttime = datetime.datetime.now() devices_not_to_be_time_analysed = [] readItems = [] for dictItem in self.MAC_Fingerprints.items(): ssidArray = dictItem[1].getSSIDArray() if (ssidArray[0] != "SSID: " or (not dictItem[1].isLocalMAC()) ): #or dictItem[1].getMaxSignalStrenght()>84 : devices_not_to_be_time_analysed.append(dictItem[0]) if (not (dictItem[1].getHash() in readItems)) and ( dictItem[0] in devices_not_to_be_time_analysed ): #and dictItem[1].getMaxSignalStrenght()<84: readItems.append(dictItem[1].getHash()) self.UniqueDevices.append(dictItem) timeAnalyseAmount = self.timeAnalyser.processData( self.packets, devices_not_to_be_time_analysed) for packetX in self.UniqueDevices: matches = [] print("Processing packet nr: {} of {}".format( self.UniqueDevices.index(packetX) + 1, len(self.UniqueDevices))) for packetY in self.UniqueDevices: if packetX[1].isLocalMAC() and packetY[1].isLocalMAC(): if (packetX[0] != packetY[0]): similarity = self.PacketComparator.comparePackets( packetX[1], packetY[1]) print("Similarity of packets {} and {} is : {}".format( packetX[0], packetY[0], similarity)) if (0.8 < similarity < 1): matches.append(packetY) for match in matches: packetX[1].mergeFingerPrints(match[1]) self.UniqueDevices.remove(match) print("Length of UniqueDevices: {}".format( len(self.UniqueDevices))) print("Processing time: {} ".format(datetime.datetime.now() - starttime)) return len(self.UniqueDevices) + timeAnalyseAmount def presentUniqueDevices(self): """ Presents Amount of read devices and the different MAC Addresses with Fingerprints. """ deviceAmount = self.processFingerprints() resultString = [] print("Amount of devices discovered: {}".format(deviceAmount)) for item in self.UniqueDevices: currentDevice = "" if item[1].getOUI() in self.OUIs.keys(): currentDevice = ( "MAC-Address:{} --- Fingerprint:{} --- \nOUI: {} --- First Timestamp: {} --- Last Modified Timestamp: {}--- \nMax Signal Strenght: -{}dBm --- Hash: {}" .format(item[0], item[1].getSSIDArray(), self.OUIs[item[1].getOUI()], item[1].getTimeStamp()[0], item[1].getTimeStamp()[1], item[1].getMaxSignalStrenght(), item[1].getHash())) else: currentDevice = ( "MAC-Address:{} --- Fingerprint:{} --- OUI: {} --- First Timestamp: {} --- Last Modified Timestamp: {} --- Hash: {}" .format(item[0], item[1].getSSIDArray(), item[1].getOUI(), item[1].getTimeStamp()[0], item[1].getTimeStamp()[1], item[1].getHash())) #print(currentDevice) resultString.append(currentDevice) print("RETURNING") return [deviceAmount, resultString]
def test_capture_gets_decoding_parameters(): c = Capture(decode_as={'tcp.port==8888': 'http'}) params = c.get_parameters() decode_index = params.index('-d') assert params[decode_index + 1] == 'tcp.port==8888,http'
def test_capture_gets_override_perfs(): c = Capture(override_prefs={'esp.enable_null_encryption_decode_heuristic': 'TRUE'}) params = c.get_parameters() override_index = params.index('-o') override_actual_value = params[override_index +1] assert override_actual_value == 'esp.enable_null_encryption_decode_heuristic:TRUE'