class TestAirodumpAp(unittest.TestCase): def setUp(self): self.ap = AirodumpAp() def test_initLoad(self): data = [ [1,'2012-05-10 11:53:54','2012-05-10 11:53:54',4,5,6,7,8,9,10,11,12,13,14,15], [2,'2012-05-10 11:53:54','2012-05-10 11:53:54',4,5,6,7,8,9,10,11,12,13,14,150] ] ap = AirodumpAp(data) self.assertTrue(len(ap) == 2) record = ap[0] self.assertTrue(record[0] == 1) self.assertTrue(record[14] == 15) record = ap[1] self.assertTrue(record[0] == 2) self.assertTrue(record[14] == 150) def test_set_get(self): self.ap.add([1,'2012-05-10 11:53:54','2012-05-10 11:53:54',4,5,6,7,8,9,10,11,12,13,14,15]) self.assertTrue(len(self.ap) == 1) record = self.ap[0] self.assertTrue(record[0] == 1) self.assertTrue(record[14] == 15) def test_print(self): self.ap.add([1,'2012-05-10 11:53:54','2012-05-10 11:53:54',4,5,6,7,8,9,10,11,12,13,14,15]) str(self.ap)
def getBestAssociatedStation(in_data, in_by='iv'): best_aps = getAssociatedStations(in_data) if len(best_aps) == 0: return [] # Find the best candidate. iv_index = AirodumpAp.index(in_by) s = sorted(best_aps, key=lambda ap: ap['AP'][iv_index]) return s[len(s)-1]
def loadCsv(in_csv_path): in_ap = False # "True" if we are in the AP's section. in_station = False # "True" if we are in the STATION's section. # Loads the input CSV file. fd = open(in_csv_path, "r") lines = fd.readlines() fd.close() # Prepare regexps. rap = re.compile('^BSSID,') rstation = re.compile('^Station MAC,') rblanck = re.compile('^\s*$') result = {'AP' : AirodumpAp(), 'STATION': AirodumpStation()} for line in lines: # Skip empty lines. if re.match(rblanck, line) != None: continue; # Detect AP header. if re.match(rap, line) != None: if in_ap: raise RuntimeError('The CSV file generated by "airodump-ng" is corrupted : duplicated "AP header" (BSSID...)! - (%s)' % line.rstrip()) if in_station: raise RuntimeError('The CSV file generated by "airodump-ng" is corrupted : "STATION header" (Station MAC...) should not appear before "AP header" (BSSID...)! - (%s)' % line.rstrip()) in_ap = True continue # Detect STATION header. if re.match(rstation, line) != None: if in_station: raise RuntimeError('The CSV file generated by "airodump-ng" is corrupted : duplicated "STATION header" (Stattion MAC...)! - (%s)' % line.rstrip()) if not in_ap: raise RuntimeError('The CSV file generated by "airodump-ng" is corrupted : "STATION header" (Stattion MAC...) should appear after "AP header" (BSSID...)! - (%s)' % line.rstrip()) in_station = True in_ap = False continue values = line.rstrip().split(',') # This is a list of values for APs. if in_ap: result['AP'].add(values) continue # This is a list of values for STATIONs. if in_station: result['STATION'].add(values) continue # This is an unexpected line. raise RuntimeError('The CSV file generated by "airodump-ng" is corrupted : unexpected line (%s)' % line.rstrip()) return result
class TestAirodumpAp(unittest.TestCase): def setUp(self): self.ap = AirodumpAp() def test_initLoad(self): data = [[ 1, '2012-05-10 11:53:54', '2012-05-10 11:53:54', 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], [ 2, '2012-05-10 11:53:54', '2012-05-10 11:53:54', 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 150 ]] ap = AirodumpAp(data) self.assertTrue(len(ap) == 2) record = ap[0] self.assertTrue(record[0] == 1) self.assertTrue(record[14] == 15) record = ap[1] self.assertTrue(record[0] == 2) self.assertTrue(record[14] == 150) def test_set_get(self): self.ap.add([ 1, '2012-05-10 11:53:54', '2012-05-10 11:53:54', 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]) self.assertTrue(len(self.ap) == 1) record = self.ap[0] self.assertTrue(record[0] == 1) self.assertTrue(record[14] == 15) def test_print(self): self.ap.add([ 1, '2012-05-10 11:53:54', '2012-05-10 11:53:54', 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]) str(self.ap)
def getBestStation(in_data, in_sort_by='power'): aps = in_data['AP'] power_index = AirodumpAp.index(in_sort_by) essid_index = AirodumpAp.index('essid') best = 0 best_power = abs(int(aps[0][power_index])) essid = None for i in range(len(aps)): ap = aps[i] if isinstance(ap[essid_index], int): essid = '' else: essid = ap[essid_index] # print("essid = %s" % essid) if 0 == len(essid) : continue power = abs(int(ap[power_index])) if power > best_power: best = i best_power = power ap = aps[best] if isinstance(ap[essid_index], int): essid = '' else: essid = ap[essid_index] print("=====> %s" % essid) if 0 == len(essid) : return None return ap
def test_initLoad(self): data = [[ 1, '2012-05-10 11:53:54', '2012-05-10 11:53:54', 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], [ 2, '2012-05-10 11:53:54', '2012-05-10 11:53:54', 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 150 ]] ap = AirodumpAp(data) self.assertTrue(len(ap) == 2) record = ap[0] self.assertTrue(record[0] == 1) self.assertTrue(record[14] == 15) record = ap[1] self.assertTrue(record[0] == 2) self.assertTrue(record[14] == 150)
def getAssociatedStations(in_data, in_sort_by='iv'): aps = in_data['AP'] stations = in_data['STATION'] iv_index = AirodumpAp.index(in_sort_by) # Find all stations associated with an AP. # One station <=> one CSV record. sql = {'bssid':'^[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}$', 'probed essids':'^[a-zA-Z0-9_\.\-]+$'} associated = stations.select(sql, Csv.MATCH) # Find data for all associated APs. # One AP <=> one CSV record. best_aps = [] for station in associated: bssid = AirodumpStation.get(station, 'bssid') aps_records = aps.select({'bssid':bssid}, Csv.EQUALITY) if len(aps_records) == 0: continue # Note: We should always have len(aps_records) == 1. # Sorting is not necessary! # s = sorted(aps_records, key=lambda ap: ap[iv_index]) # best_aps.append(s[len(s)-1]) best_aps.append({'AP':aps_records[0], 'STATION':station}) return best_aps
def setUp(self): self.ap = AirodumpAp()