diff --git a/esp8266_deauther/APScan.cpp b/esp8266_deauther/APScan.cpp index ec959ed..aa17b5c 100644 --- a/esp8266_deauther/APScan.cpp +++ b/esp8266_deauther/APScan.cpp @@ -60,7 +60,13 @@ String APScan::getEncryption(int code){ break; } } - +bool APScan::setAsyncIndex() { + asyncIndex = results-1; + if(asyncIndex > maxResults) { + asyncIndex = maxResults-1; + } + return true; +} String APScan::getAPName(int num){ return names[num]; } String APScan::getAPEncryption(int num){ return encryption[num]; } String APScan::getAPVendor(int num){ return vendors[num]; } @@ -78,7 +84,21 @@ int APScan::getFirstTarget(){ } return -1; } - +String APScan::getResult(int i){ + String json = "{ \"aps\":[ "; + json += "{"; + json += "\"id\": "+(String)i+","; + json += "\"channel\": "+(String)getAPChannel(i)+","; + json += "\"mac\": \""+getAPMac(i)+"\","; + json += "\"ssid\": \""+getAPName(i)+"\","; + json += "\"rssi\": "+(String)getAPRSSI(i)+","; + json += "\"encryption\": \""+getAPEncryption(i)+"\","; + json += "\"vendor\": \""+getAPVendor(i)+"\","; + json += "\"selected\": "+getAPSelected(i); + json += "}"; + json += "] }"; + return json; +} String APScan::getResults(){ if(debug) Serial.print("getting AP scan result JSON "); String json = "{ \"aps\":[ "; @@ -101,6 +121,14 @@ String APScan::getResults(){ return json; } +void APScan::select(int num){ + if(selected != num) selected = num; + else selected = -1; +} + + + + void APScan::select(int num){ if(debug) Serial.println("seect "+(String)num+" - "+!selected[num]); if(selected[num]){ @@ -110,10 +138,8 @@ void APScan::select(int num){ selected[num] = true; selectedSum++; } -} - bool APScan::isSelected(int num){ return selected[num]; } - + \ No newline at end of file diff --git a/esp8266_deauther/APScan.h b/esp8266_deauther/APScan.h index eafa49b..f902e3e 100644 --- a/esp8266_deauther/APScan.h +++ b/esp8266_deauther/APScan.h @@ -15,9 +15,11 @@ class APScan{ APScan(); bool start(); + String getResult(int i); String getResults(); - void select(int num); - + int getResultByAPName(String apName); + int select(int num); + bool setAsyncIndex(); String getAPName(int num); String getAPEncryption(int num); String getAPVendor(int num); @@ -32,6 +34,7 @@ class APScan{ int results = 0; int selectedSum; MacList aps; + int asyncIndex = -1; private: int channels[maxResults]; int rssi[maxResults]; @@ -44,4 +47,4 @@ class APScan{ bool selected[maxResults]; }; -#endif +#endif diff --git a/esp8266_deauther/ClientScan.cpp b/esp8266_deauther/ClientScan.cpp index 7caffbb..f51c1b7 100644 --- a/esp8266_deauther/ClientScan.cpp +++ b/esp8266_deauther/ClientScan.cpp @@ -136,5 +136,6 @@ String ClientScan::getResults(){ } void ClientScan::select(int num){ + lastSelected = num; selected[num] = !selected[num]; -} +} diff --git a/esp8266_deauther/ClientScan.h b/esp8266_deauther/ClientScan.h index be55964..78c01c0 100644 --- a/esp8266_deauther/ClientScan.h +++ b/esp8266_deauther/ClientScan.h @@ -31,6 +31,7 @@ class ClientScan{ String getResults(); void select(int num); + int lastSelected; String getClientName(int num); int getClientPackets(int num); @@ -62,4 +63,4 @@ class ClientScan{ int curChannel = 0; }; -#endif +#endif diff --git a/esp8266_deauther/MacList.h b/esp8266_deauther/MacList.h index e15a8a1..a4f0018 100644 --- a/esp8266_deauther/MacList.h +++ b/esp8266_deauther/MacList.h @@ -25,4 +25,4 @@ class MacList void addPacket(Mac adr); }; -#endif +#endif diff --git a/esp8266_deauther/SerialServer.h b/esp8266_deauther/SerialServer.h new file mode 100644 index 0000000..f688043 --- /dev/null +++ b/esp8266_deauther/SerialServer.h @@ -0,0 +1,187 @@ + +#include "data.h" +#include "NameList.h" +#include "APScan.h" +#include "ClientScan.h" +#include "Attack.h" + +// MOTD +#define helpMessageSize 17 +String helpMessages[helpMessageSize] = { + "Command List:", + " apjson [ap id] Print Scan Result for AP xx [sendAPResult(xx)]", + " apscan Start AP Scan [startAPScan]", + " aplist Prints AP Scan List", + " clear NameList clear", + " apget [ap mac/name] Search, Select and Print AP mac or name [getResultByAPName(blah)]", + " apselect [ap id] Select AP [selectAP(xx)]", + " cscan Start Client Scan [startClientScan]", + " cjson Get Client Scan Results [sendClientResults]", + " cselect [client id] Select Client [selectClient(xx)]", + " cset [name] BookMark Client setClientName(clientSelected, xx)", + " attackinfo Show Last Attack Info sendAttackInfo", + " attack [attack num] Start Attack [startAttack(xx)]", + " 0 = deauth_selected", + " 1 = deauth broadcast", + " 2 = beacon", + " 3 = random beacon" +}; +unsigned int helpMessagesPos = 0; + +String incomingSerialData = ""; +bool incomingSerialDataReady = false; + +void SerialPrintJSON(String msg) { + Serial.println("{\"message\":[\""+msg+"\"]}"); +} + +void handleSerialClient() { + + // serial command received! + String msg = incomingSerialData; + String msgNumStr; + int msgNum; + + msg.trim(); + + if(msg=="*") { + SerialPrintJSON( helpMessages[helpMessagesPos] ); + helpMessagesPos++; + if( helpMessagesPos < helpMessageSize ) { + // continue with async printing + return; + } + helpMessagesPos = 0; + + } else if(msg=="cscan") { // startClientScan + if(apScan.selected > -1 && !clientScan.sniffing) { + SerialPrintJSON("CLIENT SCAN START"); + clientScan.start(10); + attack.stop(0); + } else { + SerialPrintJSON("CLIENT SCAN SKIPPED"); + } + + } else if(msg=="apscan") { // startAPScan + + if(apScan.start()) { + attack.stopAll(); + apScan.setAsyncIndex(); + incomingSerialData = "aplist"; + return; + } + + } else if(msg=="aplist") { // + if(apScan.results==0) { + incomingSerialData = "apscan"; + return; + } + + if(apScan.asyncIndex>=0) { + Serial.println(apScan.getResult(apScan.asyncIndex)); + apScan.asyncIndex--; + + if(apScan.asyncIndex<0) { + // scan done, reset async index + apScan.setAsyncIndex(); + + } else { + // continue with async printing + return; + } + } else { + // list done, reset async index + apScan.setAsyncIndex(); + } + + } else if(msg=="cjson") { // sendClientResults + Serial.println(clientScan.getResults()); + + } else if(msg=="attackinfo") { // sendAttackInfo + Serial.println( attack.getResults() ); + + } else if(msg.startsWith("cselect ")) { // selectClient(x) + msgNumStr = msg.substring(8); + msgNum = msgNumStr.toInt(); + if(msgNum>-1) { + SerialPrintJSON("SELECTED Client #" + msgNumStr); + clientScan.select(msgNum); + attack.stop(0); + } else { + SerialPrintJSON("INVALID Client #" + msgNumStr); + } + Serial.println( clientScan.getResults() ); + + } else if(msg.startsWith("apjson ")) { // sendAPResults(xx) + msgNumStr = msg.substring(7); + msgNum = msgNumStr.toInt(); + if(msgNum>-1) { + Serial.println( apScan.getResult(msgNum) ); + } else { + SerialPrintJSON("ERROR INVALID AP "); + } + + } else if(msg=="reset") { + ESP.reset(); + + } else if(msg=="clear") { + nameList.clear(); + + } else if(msg.startsWith("apget ")) { // getResultByAPName('blah') + msgNumStr = msg.substring(6); + if(msgNumStr!="") { + int apNum = apScan.getResultByAPName(msgNumStr); + if(apNum>-1) { + Serial.println(apScan.getResult(apNum)); + } else { + SerialPrintJSON("ERROR,AP Not Found:" + msgNumStr); + } + } else { + SerialPrintJSON("ERROR INVALID AP "); + } + + } else if(msg.startsWith("apselect ")) { // selectAP(x) + msgNumStr = msg.substring(9); + msgNum = msgNumStr.toInt(); + if(msgNum>-1) { + if(apScan.select(msgNum)>-1) { + SerialPrintJSON("SELECTED AP #" + String(msgNum) + "/" + msgNumStr); + } else { + SerialPrintJSON("UNSELECTED AP #" + String(msgNum) + "/" + msgNumStr); + } + attack.stopAll(); + } else { + SerialPrintJSON("ERROR INVALID AP "); + } + + } else if(msg.startsWith("cset ")) { // setClientName(x) + msgNumStr = msg.substring(5); + //msgNum = msgNumStr.toInt(); + if(msgNumStr!="") { + SerialPrintJSON("Adding " + msgNumStr + " to namelist"); + nameList.add(clientScan.getClientMac(clientScan.lastSelected), msgNumStr); + } else { + SerialPrintJSON("ERROR INVALID Client"); + } + + } else if(msg.startsWith("attack ")) { // attack(x) + msgNumStr = msg.substring(7); + msgNum = msgNumStr.toInt(); + if(msgNum>-1) { + if(apScan.selected > -1 || msgNum == 3){ + attack.start(msgNum); + SerialPrintJSON("ATTACK Client #" + msgNumStr); + } else { + SerialPrintJSON("ERROR no AP selected"); + } + } else { + SerialPrintJSON("ERROR INVALID Client"); + } + + } + + incomingSerialData = ""; + incomingSerialDataReady = false; + + +} diff --git a/esp8266_deauther/esp8266_deauther.ino b/esp8266_deauther/esp8266_deauther.ino index 24f7c6b..7f0d96a 100644 --- a/esp8266_deauther/esp8266_deauther.ino +++ b/esp8266_deauther/esp8266_deauther.ino @@ -18,6 +18,8 @@ const static char *ssid = "pwned"; const static char *password = "deauther"; //must have at least 8 characters const bool debug = false; +#define WIFI_UI_ON false + ESP8266WebServer server(80); /* @@ -32,6 +34,8 @@ APScan apScan; ClientScan clientScan; Attack attack; +#include "SerialServer.h" + void sniffer(uint8_t *buf, uint16_t len){ clientScan.packetSniffer(buf,len); } @@ -43,10 +47,12 @@ void startWifi(){ WiFi.softAP(ssid, password); //for an open network without a password change to: WiFi.softAP(ssid); String _ssid = (String)ssid; String _password = (String)password; + #if WIFI_UI_ON==true Serial.println("SSID: "+_ssid); Serial.println("Password: "+_password); if(_password.length()<8) Serial.println("WARNING: password must have at least 8 characters!"); if(_ssid.length()<1 || _ssid.length()>32) Serial.println("WARNING: SSID length must be between 1 and 32 characters!"); + #endif } @@ -166,4 +172,95 @@ void startAttack(){ server.send ( 200, "text/json", "true"); }else server.send ( 200, "text/json", "false"); } -} +} + + + +void setup(){ + + Serial.begin(115200); + delay(2000); + + nameList.begin(); + //nameList.clear(); + nameList.load(); + + Serial.println(""); + Serial.println("starting..."); + + startWifi(); + attack.generate(-1); + + #if WIFI_UI_ON==true + /* ========== Web Server ========== */ + /* HTML sites */ + server.onNotFound(load404); + + server.on("/", loadIndex); + server.on("/index.html", loadIndex); + server.on("/clients.html", loadClients); + server.on("/attack.html", loadAttack); + server.on("/functions.js", loadFunctionsJS); + + /* header links */ + server.on ("/style.css", loadStyle); + + /* JSON */ + server.on("/APScanResults.json", sendAPResults); + server.on("/APScan.json", startAPScan); + server.on("/APSelect.json", selectAP); + server.on("/ClientScan.json", startClientScan); + server.on("/ClientScanResults.json", sendClientResults); + server.on("/clientSelect.json", selectClient); + server.on("/setName.json", setClientName); + server.on("/attackInfo.json", sendAttackInfo); + server.on("/attackStart.json", startAttack); + + server.begin(); + #else + // send MOTD + incomingSerialData = "*"; + incomingSerialDataReady = true; + #endif +} + +void loop(){ + #if WIFI_UI_ON!=true + bool show_hidden = false; + byte inByte = 0; + byte outByte = 0; + #endif + + if(clientScan.sniffing){ + if(clientScan.stop()){ + #if WIFI_UI_ON!=true + SerialPrintJSON( "CLIENT SCAN DONE" ); + Serial.println( clientScan.getResults() ); + #endif + startWifi(); + } + } else{ + #if WIFI_UI_ON==true + server.handleClient(); + #else + if(incomingSerialDataReady) { + handleSerialClient(); + } + #endif + attack.run(); + } + + #if WIFI_UI_ON!=true + if(Serial.available()){ + // Read Arduino IDE Serial Monitor inputs (if available) and capture orders + outByte = Serial.read(); + if(outByte==13) { + incomingSerialDataReady = true; + } else { + incomingSerialData = incomingSerialData + (char)outByte; + } + } + #endif + +} +