diff --git a/enrich.py b/enrich.py index 6c91342..ac07be9 100755 --- a/enrich.py +++ b/enrich.py @@ -299,6 +299,8 @@ def analyze_pcap(pcapng_path, start_ts, end_ts, ap_bssid, ap_channel): unlinked_devices = 0 ssid_clients = defaultdict(set) + ssid_hidden_status = {} + cisco_ssid_clients = defaultdict(list) ssid_signals = defaultdict(list) ssid_to_bssids = defaultdict(set) bssid_to_ssid = {} @@ -341,17 +343,34 @@ def analyze_pcap(pcapng_path, start_ts, end_ts, ap_bssid, ap_channel): continue ssid = None + hidden_ssid = False + for tag in tags: tag_number = tag.get('wlan.tag.number') - # SSID - if tag_number == '0' and 'wlan.ssid' in tag: + if tag_number == '0': + raw_ssid = tag.get('wlan.ssid', '') + if not raw_ssid: + hidden_ssid = True + ssid = '' + else: + try: + ssid_bytes = bytes.fromhex(raw_ssid.replace(':', '')) + ssid = ssid_bytes.decode('utf-8', errors='replace') + except Exception: + ssid = None + + if tag_number == '133': try: - raw_ssid = tag['wlan.ssid'] - ssid_bytes = bytes.fromhex(raw_ssid.replace(':', '')) - ssid = ssid_bytes.decode('utf-8', errors='replace') - except Exception as e: - ssid = None + num_clients = int(tag.get('wlan.cisco.ccx1.clients')) + if ssid: + cisco_ssid_clients[ssid].append(num_clients) + except (TypeError, ValueError): + pass + + if ssid: + ssid_hidden_status[ssid] = hidden_ssid + # Cisco Client Count if tag_number == '133': @@ -398,16 +417,18 @@ def analyze_pcap(pcapng_path, start_ts, end_ts, ap_bssid, ap_channel): signals = ssid_signals.get(ssid, []) ssid_summary.append({ 'SSID': ssid, + 'Hidden': ssid_hidden_status.get(ssid, False), 'BSSID_Count': len(bssids), 'Avg_Signal': mean(signals) if signals else 0, 'Max_Signal': max(signals) if signals else 0, 'Min_Signal': min(signals) if signals else 0, 'Clients_Seen': len(ssid_clients.get(ssid, [])), - 'CiscoAvgClients': round(mean(cisco_reported_clients), 2) if cisco_reported_clients else 0, - 'CiscoMaxClients': max(cisco_reported_clients) if cisco_reported_clients else 0 + 'CiscoAvgClients': round(mean(cisco_ssid_clients.get(ssid, [])), 2) if cisco_ssid_clients.get(ssid) else 0, + 'CiscoMaxClients': max(cisco_ssid_clients.get(ssid, [])) if cisco_ssid_clients.get(ssid) else 0 }) + finally: cap.close() @@ -488,7 +509,7 @@ def main(): ssid_outfile = args.output.replace('.csv+rf.csv', '-ssid-metrics.csv') with open(ssid_outfile, 'w', newline='', encoding='utf-8') as f: fieldnames = [ - 'SSID', 'BSSID_Count', 'Avg_Signal', 'Max_Signal', + 'SSID', 'Hidden', 'BSSID_Count', 'Avg_Signal', 'Max_Signal', 'Min_Signal', 'Clients_Seen', 'CiscoAvgClients', 'CiscoMaxClients' ] ssid_writer = csv.DictWriter(f, fieldnames=fieldnames) diff --git a/runtest.sh b/runtest.sh index a672666..2551e3d 100755 --- a/runtest.sh +++ b/runtest.sh @@ -151,6 +151,11 @@ if [ -f "$FAILURE_LOG" ]; then echo "[+] Attaching failure log: $FAILURE_LOG" fi +if [ -f "$SSID_METRICS_FILE" ]; then + ATTACHMENTS+=("$SSID_METRICS_FILE") + echo "[+] Attaching SSID metrics file: $SSID_METRICS_FILE" +fi + # Check if there's at least one file to send if [ ${#ATTACHMENTS[@]} -eq 0 ]; then echo "[!] No files to attach. Email not sent." diff --git a/settings.env.default b/settings.env.default index 1468218..b8aa68e 100644 --- a/settings.env.default +++ b/settings.env.default @@ -4,6 +4,7 @@ SCRIPT_DIRECTORY="${HOME}/wifi_test" KISMET_LOG_DIR="${HOME}/kismet_logs" TEST_FILE="${HOME}/${BOOT_ID}-speedtest.csv" ENRICHED_FILE="${TEST_FILE%}+rf.csv" +SSID_METRICS_FILE="${TEST_FILE%}-ssid-metrics.csv" NUM_TESTS=1 NUM_SAMPLES=5