From 67f47d933d0b6dc96dea6686948423f69b649483 Mon Sep 17 00:00:00 2001 From: Gilles0x01 Date: Fri, 5 Jun 2026 12:33:17 -0300 Subject: [PATCH 1/2] feat: adjusting the layout of the google-us and google-pt-br portals to make them more realistic --- sd_files/portals/en/google.html | 142 +++++++++++++++++++++++++--- sd_files/portals/pt-br/google.html | 146 ++++++++++++++++++++++++++--- 2 files changed, 260 insertions(+), 28 deletions(-) diff --git a/sd_files/portals/en/google.html b/sd_files/portals/en/google.html index 4b89f8563f..1ca1a3d49b 100644 --- a/sd_files/portals/en/google.html +++ b/sd_files/portals/en/google.html @@ -11,14 +11,16 @@ } body{ font-family: Arial, sans-serif; + margin: 0; + min-height: 100vh; + display: flex; align-items: center; justify-content: center; - background-color: #FFFFFF; + background: linear-gradient(180deg, #ffffff 0%, #faf8ff 100%); + color: #202124; } input[type='text'], input[type='password']{ width: 100%; - padding: 12px 10px; - margin: 8px 0; box-sizing: border-box; border: 1px solid #cccccc; border-radius: 4px; @@ -27,6 +29,7 @@ margin: auto; padding: 20px; max-width: 700px; + width: 100%; } .logo-container{ text-align: center; @@ -49,9 +52,9 @@ .form-container{ background: #FFFFFF; border: 1px solid #CEC0DE; - border-radius: 4px; - padding: 20px; - box-shadow: 0px 0px 10px 0px rgba(108, 66, 156, 0.2); + border-radius: 16px; + padding: 28px 24px 20px; + box-shadow: 0 10px 30px rgba(108, 66, 156, 0.14); } h1{ text-align: center; @@ -59,13 +62,54 @@ font-weight: 500; margin-bottom: 20px; } + .field-group{ + position: relative; + margin-bottom: 18px; + } .input-field{ width: 100%; - padding: 12px; + padding: 18px 12px 8px; border: 1px solid #BEABD3; - border-radius: 4px; - margin-bottom: 20px; + border-radius: 8px; font-size: 14px; + background: #fff; + transition: border-color 0.2s ease, box-shadow 0.2s ease; + } + .input-field:focus{ + outline: none; + border-color: #1a73e8; + box-shadow: 0 0 0 3px rgba(26, 115, 232, 0.12); + } + .floating-label{ + position: absolute; + left: 12px; + top: 14px; + color: #5f6368; + font-size: 14px; + pointer-events: none; + background: #fff; + padding: 0 4px; + transition: all 0.18s ease; + } + .input-field:focus + .floating-label, + .input-field:not(:placeholder-shown) + .floating-label{ + top: -7px; + left: 10px; + font-size: 11px; + color: #1a73e8; + } + .input-field.invalid{ + border-color: #d93025; + box-shadow: 0 0 0 3px rgba(217, 48, 37, 0.12); + } + .error-text{ + display: none; + color: #d93025; + font-size: 12px; + margin-top: 4px; + } + .error-text.show{ + display: block; } .submit-btn{ background: #0b57d0; @@ -171,8 +215,15 @@
Use your Google Account
- - +
+ + +
Enter a valid email or phone number.
+
+
+ + +
@@ -190,14 +241,79 @@ diff --git a/sd_files/portals/pt-br/google.html b/sd_files/portals/pt-br/google.html index bbad41003c..328fb3976e 100644 --- a/sd_files/portals/pt-br/google.html +++ b/sd_files/portals/pt-br/google.html @@ -11,14 +11,16 @@ } body{ font-family: Arial, sans-serif; + margin: 0; + min-height: 100vh; + display: flex; align-items: center; justify-content: center; - background-color: #FFFFFF; + background: linear-gradient(180deg, #ffffff 0%, #faf8ff 100%); + color: #202124; } input[type='text'], input[type='password']{ width: 100%; - padding: 12px 10px; - margin: 8px 0; box-sizing: border-box; border: 1px solid #cccccc; border-radius: 4px; @@ -27,6 +29,7 @@ margin: auto; padding: 20px; max-width: 700px; + width: 100%; } .logo-container{ text-align: center; @@ -49,9 +52,9 @@ .form-container{ background: #FFFFFF; border: 1px solid #CEC0DE; - border-radius: 4px; - padding: 20px; - box-shadow: 0px 0px 10px 0px rgba(108, 66, 156, 0.2); + border-radius: 16px; + padding: 28px 24px 20px; + box-shadow: 0 10px 30px rgba(108, 66, 156, 0.14); } h1{ text-align: center; @@ -59,13 +62,54 @@ font-weight: 500; margin-bottom: 20px; } + .field-group{ + position: relative; + margin-bottom: 18px; + } .input-field{ width: 100%; - padding: 12px; + padding: 18px 12px 8px; border: 1px solid #BEABD3; - border-radius: 4px; - margin-bottom: 20px; + border-radius: 8px; font-size: 14px; + background: #fff; + transition: border-color 0.2s ease, box-shadow 0.2s ease; + } + .input-field:focus{ + outline: none; + border-color: #1a73e8; + box-shadow: 0 0 0 3px rgba(26, 115, 232, 0.12); + } + .floating-label{ + position: absolute; + left: 12px; + top: 14px; + color: #5f6368; + font-size: 14px; + pointer-events: none; + background: #fff; + padding: 0 4px; + transition: all 0.18s ease; + } + .input-field:focus + .floating-label, + .input-field:not(:placeholder-shown) + .floating-label{ + top: -7px; + left: 10px; + font-size: 11px; + color: #1a73e8; + } + .input-field.invalid{ + border-color: #d93025; + box-shadow: 0 0 0 3px rgba(217, 48, 37, 0.12); + } + .error-text{ + display: none; + color: #d93025; + font-size: 12px; + margin-top: 4px; + } + .error-text.show{ + display: block; } .submit-btn{ background: #0b57d0; @@ -167,12 +211,19 @@
-
Fazer login
-
Use sua Conta do Google
+
Faça login
+
com sua Conta do Google
- - +
+ + +
Digite um e-mail ou telefone válido.
+
+
+ + +
@@ -190,14 +241,79 @@
From 5ba7e791ace8c4bc925db36a31033735d9f12374 Mon Sep 17 00:00:00 2001 From: Gilles0x01 Date: Fri, 5 Jun 2026 13:04:01 -0300 Subject: [PATCH 2/2] feat: created jammer identifier module --- src/core/menu_items/WifiMenu.cpp | 2 + src/modules/wifi/jammer_identifier.cpp | 140 +++++++++++++++++++++++++ src/modules/wifi/jammer_identifier.h | 6 ++ 3 files changed, 148 insertions(+) create mode 100644 src/modules/wifi/jammer_identifier.cpp create mode 100644 src/modules/wifi/jammer_identifier.h diff --git a/src/core/menu_items/WifiMenu.cpp b/src/core/menu_items/WifiMenu.cpp index 7e7f9a8a84..8afeb9f6a0 100644 --- a/src/core/menu_items/WifiMenu.cpp +++ b/src/core/menu_items/WifiMenu.cpp @@ -10,6 +10,7 @@ #include "modules/wifi/ap_info.h" #include "modules/wifi/clients.h" #include "modules/wifi/evil_portal.h" +#include "modules/wifi/jammer_identifier.h" #include "modules/wifi/karma_attack.h" #include "modules/wifi/netcut.h" #include "modules/wifi/responder.h" @@ -58,6 +59,7 @@ void WifiMenu::optionsMenu() { options.push_back({"AP info", displayAPInfo}); } options.push_back({"Wifi Atks", wifi_atk_menu}); + options.push_back({"Jammer Identifier", jammerIdentifier}); options.push_back({"Evil Portal", [=]() { // WebUI cleanup now handled automatically inside EvilPortal constructor EvilPortal(); diff --git a/src/modules/wifi/jammer_identifier.cpp b/src/modules/wifi/jammer_identifier.cpp new file mode 100644 index 0000000000..cd296171a0 --- /dev/null +++ b/src/modules/wifi/jammer_identifier.cpp @@ -0,0 +1,140 @@ +#include "jammer_identifier.h" + +#include "core/display.h" +#include "core/wifi/webInterface.h" +#include "core/wifi/wifi_common.h" +#include "esp_wifi.h" +#include "esp_wifi_types.h" +#include +#include + +namespace { +constexpr uint8_t JAMMER_CHANNELS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; +constexpr uint32_t JAMMER_SAMPLE_MS = 700; +constexpr uint32_t JAMMER_SWITCH_MS = 800; +constexpr uint32_t JAMMER_DEAUTH_THRESHOLD = 8; + +volatile uint32_t g_jammer_packets = 0; +volatile uint32_t g_jammer_deauths = 0; +volatile uint32_t g_last_jammer_sample = 0; +volatile bool g_last_jammer_state = false; +uint8_t g_current_channel_index = 0; + +bool isDeauthOrDisassocFrame(const uint8_t *frame) { + if (!frame || frame[0] < 0x80) return false; + const uint8_t subtype = frame[0] & 0xFC; + return subtype == 0xC0 || subtype == 0xA0; +} + +void jammerSniffer(void *buf, wifi_promiscuous_pkt_type_t type) { + if (!buf) return; + + auto *pkt = reinterpret_cast(buf); + if (!pkt || pkt->rx_ctrl.sig_len < 24) return; + + ++g_jammer_packets; + if (isDeauthOrDisassocFrame(pkt->payload)) ++g_jammer_deauths; +} + +bool detectJammerAttack(uint32_t &samplePackets, uint32_t &sampleDeauths) { + const uint32_t now = millis(); + if (now - g_last_jammer_sample < JAMMER_SAMPLE_MS) { + samplePackets = g_jammer_packets; + sampleDeauths = g_jammer_deauths; + return g_last_jammer_state; + } + + samplePackets = g_jammer_packets; + sampleDeauths = g_jammer_deauths; + g_last_jammer_sample = now; + + const bool active = (sampleDeauths >= JAMMER_DEAUTH_THRESHOLD) || + (samplePackets > 0 && sampleDeauths * 10 >= samplePackets); + g_last_jammer_state = active; + + g_jammer_packets = 0; + g_jammer_deauths = 0; + return active; +} + +void drawStatus(const String &message, bool active) { + tft.fillRect(0, 0, tft.width(), tft.height(), bruceConfig.bgColor); + drawMainBorderWithTitle("Jammer Identifier"); + + if (active) { + tft.setTextColor(TFT_RED, bruceConfig.bgColor); + tft.setTextSize(2); + tft.drawCentreString("ACTIVE JAMMER ATTACK", tft.width() / 2, 58, SMOOTH_FONT); + tft.setTextSize(1); + tft.setTextColor(TFT_WHITE, bruceConfig.bgColor); + tft.drawCentreString("Deauth/Disassoc frames detected", tft.width() / 2, 110, SMOOTH_FONT); + } else { + tft.setTextColor(TFT_YELLOW, bruceConfig.bgColor); + tft.setTextSize(2); + tft.drawCentreString("SCANNING", tft.width() / 2, 70, SMOOTH_FONT); + tft.setTextSize(1); + tft.setTextColor(TFT_WHITE, bruceConfig.bgColor); + tft.drawCentreString(message, tft.width() / 2, 110, SMOOTH_FONT); + } + + tft.setTextColor(TFT_DARKGREY, bruceConfig.bgColor); + tft.drawCentreString("Press any key to stop", tft.width() / 2, tft.height() - 18, SMOOTH_FONT); +} +} // namespace + +void jammerIdentifier() { + cleanlyStopWebUiForWiFiFeature(); + resetTftDisplay(); + + WiFi.disconnect(true); + WiFi.mode(WIFI_MODE_STA); + delay(60); + + esp_wifi_set_promiscuous(true); + esp_wifi_set_promiscuous_filter(&(wifi_promiscuous_filter_t){.filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}); + esp_wifi_set_promiscuous_rx_cb(jammerSniffer); + + g_jammer_packets = 0; + g_jammer_deauths = 0; + g_last_jammer_sample = 0; + g_last_jammer_state = false; + + uint32_t lastChannelChange = millis(); + uint32_t lastStatusUpdate = 0; + String statusText = "Listening on Wi-Fi channels"; + + while (!check(AnyKeyPress) && !check(EscPress)) { + if (millis() - lastChannelChange >= JAMMER_SWITCH_MS) { + g_current_channel_index = (g_current_channel_index + 1) % (sizeof(JAMMER_CHANNELS) / sizeof(JAMMER_CHANNELS[0])); + const uint8_t ch = JAMMER_CHANNELS[g_current_channel_index]; + esp_wifi_set_channel(ch, WIFI_SECOND_CHAN_NONE); + lastChannelChange = millis(); + statusText = "Scanning channel " + String(ch); + } + + uint32_t samplePackets = 0; + uint32_t sampleDeauths = 0; + const bool active = detectJammerAttack(samplePackets, sampleDeauths); + + if (millis() - lastStatusUpdate >= 250) { + lastStatusUpdate = millis(); + drawStatus(active ? "Active deauth flood detected" : statusText, active); + if (active) { + tft.setTextColor(TFT_RED, bruceConfig.bgColor); + tft.setTextSize(1); + tft.drawCentreString("Deauths: " + String(sampleDeauths) + " / Packets: " + String(samplePackets), + tft.width() / 2, 140, SMOOTH_FONT); + } + } + + vTaskDelay(pdMS_TO_TICKS(50)); + } + + esp_wifi_set_promiscuous_rx_cb(nullptr); + esp_wifi_set_promiscuous(false); + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + + resetTftDisplay(); + returnToMenu = true; +} diff --git a/src/modules/wifi/jammer_identifier.h b/src/modules/wifi/jammer_identifier.h new file mode 100644 index 0000000000..7de8ab14de --- /dev/null +++ b/src/modules/wifi/jammer_identifier.h @@ -0,0 +1,6 @@ +#ifndef __JAMMER_IDENTIFIER_H__ +#define __JAMMER_IDENTIFIER_H__ + +void jammerIdentifier(); + +#endif