Compare commits

..

19 Commits

Author SHA1 Message Date
Just Call Me Koko
10f90d93d8 Merge pull request #715 from justcallmekoko/develop
Fix missing JSON for Load APs
2025-04-16 11:18:59 -04:00
Just Call Me Koko
51588497aa Fix missing JSON for Load APs 2025-04-16 11:08:25 -04:00
Just Call Me Koko
4a0a3f5182 Merge pull request #714 from justcallmekoko/develop
Add more stats to raw capture
2025-04-16 10:35:56 -04:00
Just Call Me Koko
8b84f4c19a Add more stats to raw capture 2025-04-16 10:23:11 -04:00
Just Call Me Koko
74baf42dca Merge pull request #713 from justcallmekoko/develop
Add WPS and Manufacturer check for AP scan
2025-04-15 21:12:09 -04:00
Just Call Me Koko
983887191c Add WPS and Manufacturer check for AP scan 2025-04-15 20:40:43 -04:00
Just Call Me Koko
046b396612 Merge pull request #711 from justcallmekoko/develop
Add security check to AP scanning
2025-04-15 14:50:30 -04:00
Just Call Me Koko
86bec1e91a Add security check to AP scanning 2025-04-15 14:24:19 -04:00
Just Call Me Koko
ae51c321ff Merge pull request #710 from justcallmekoko/develop
Fix packet count for non-display models
2025-04-15 11:56:21 -04:00
Just Call Me Koko
f3d9fbc2f8 Fix packet count not displaying for no screen models 2025-04-15 11:38:36 -04:00
Just Call Me Koko
1767f76362 Merge pull request #702 from justcallmekoko/develop
Adjust conditions for MAC set errors
2025-04-10 11:40:56 -04:00
Just Call Me Koko
908aae7965 Adjust conditions for MAC set errors 2025-04-10 11:35:58 -04:00
Just Call Me Koko
4127e4d3d0 Merge pull request #700 from justcallmekoko/develop
Make select -s all actually select all stations
2025-04-09 12:57:59 -04:00
Just Call Me Koko
cc4a069af3 Make select -s all actually select all 2025-04-09 12:52:10 -04:00
Just Call Me Koko
dae7e19abe Merge pull request #699 from justcallmekoko/develop
Fix evil portal AP name character limit
2025-04-09 12:48:05 -04:00
Just Call Me Koko
2a8006a59d Fix evil portal AP name character limit 2025-04-09 12:28:26 -04:00
Just Call Me Koko
f0d1c048f5 Merge pull request #691 from justcallmekoko/develop
Fix PSRAM crash issue with dual esp32 devices
2025-04-06 14:00:29 -04:00
Just Call Me Koko
94a7c6c587 Increment version number to v1.4.1 2025-04-06 13:52:52 -04:00
Just Call Me Koko
0a395944c6 Fix psram crash issue on dual ESP32 devices 2025-04-06 13:52:24 -04:00
6 changed files with 511 additions and 138 deletions

View File

@@ -1345,26 +1345,43 @@ void CommandLine::runCommand(String input) {
// Get list of indices
LinkedList<String> ss_index = this->parseCommand(cmd_args.get(ss_sw + 1), ",");
// Mark APs as selected
for (int i = 0; i < ss_index.size(); i++) {
int index = ss_index.get(i).toInt();
if (!this->inRange(ssids->size(), index)) {
Serial.println("Index not in range: " + (String)index);
continue;
// Select ALL SSIDs
if (cmd_args.get(ss_sw + 1) == "all") {
for (int i = 0; i < ssids->size(); i++) {
if (ssids->get(i).selected) {
ssid new_ssid = ssids->get(i);
new_ssid.selected = false;
ssids->set(i, new_ssid);
count_unselected += 1;
}
else {
ssid new_ssid = ssids->get(i);
new_ssid.selected = true;
ssids->set(i, new_ssid);
count_selected += 1;
}
}
if (ssids->get(index).selected) {
// Unselect "selected" ap
ssid new_ssid = ssids->get(index);
new_ssid.selected = false;
ssids->set(index, new_ssid);
count_unselected += 1;
}
else {
// Select "unselected" ap
ssid new_ssid = ssids->get(index);
new_ssid.selected = true;
ssids->set(index, new_ssid);
count_selected += 1;
}
else {
// Mark SSIDs as selected
for (int i = 0; i < ss_index.size(); i++) {
int index = ss_index.get(i).toInt();
if (!this->inRange(ssids->size(), index)) {
Serial.println("Index not in range: " + (String)index);
continue;
}
if (ssids->get(index).selected) {
ssid new_ssid = ssids->get(index);
new_ssid.selected = false;
ssids->set(index, new_ssid);
count_unselected += 1;
}
else {
ssid new_ssid = ssids->get(index);
new_ssid.selected = true;
ssids->set(index, new_ssid);
count_selected += 1;
}
}
}
this->showCounts(count_selected, count_unselected);

View File

@@ -33,7 +33,7 @@ extern Buffer buffer_obj;
#define RESET_CMD "reset"
#define START_CMD "start"
#define ACK_CMD "ack"
#define MAX_AP_NAME_SIZE 30
#define MAX_AP_NAME_SIZE 32
#define WIFI_SCAN_EVIL_PORTAL 30
char apName[MAX_AP_NAME_SIZE] = "PORTAL";
@@ -55,6 +55,9 @@ struct AccessPoint {
int8_t rssi;
LinkedList<uint16_t>* stations;
uint16_t packets;
uint8_t sec;
bool wps;
String man;
};
class CaptiveRequestHandler : public AsyncWebHandler {

View File

@@ -1025,6 +1025,13 @@ void WiFiScan::StopScan(uint8_t scan_mode)
this->analyzer_name_update = true;
this->mgmt_frames = 0;
this->data_frames = 0;
this->beacon_frames = 0;
this->req_frames = 0;
this->resp_frames = 0;
this->deauth_frames = 0;
this->eapol_frames = 0;
this->min_rssi = 0;
this->max_rssi = -128;
#endif
}
@@ -1368,7 +1375,6 @@ void WiFiScan::RunLoadAPList() {
display_obj.tft.setCursor(0, 100);
display_obj.tft.setTextSize(1);
display_obj.tft.setTextColor(TFT_CYAN);
display_obj.tft.println("Could not open /APs_0.log");
#endif
return;
@@ -1386,7 +1392,6 @@ void WiFiScan::RunLoadAPList() {
display_obj.tft.setCursor(0, 100);
display_obj.tft.setTextSize(1);
display_obj.tft.setTextColor(TFT_CYAN);
display_obj.tft.println("Could not deserialize JSON");
display_obj.tft.println(error.c_str());
#endif
@@ -1396,25 +1401,36 @@ void WiFiScan::RunLoadAPList() {
JsonArray array = doc.as<JsonArray>();
for (JsonObject obj : array) {
AccessPoint ap;
ap.essid = obj["essid"].as<String>();
ap.channel = obj["channel"];
ap.essid = obj.containsKey("essid") ? obj["essid"].as<String>() : "";
ap.channel = obj.containsKey("channel") ? obj["channel"].as<uint8_t>() : 1;
ap.selected = false;
parseBSSID(obj["bssid"], ap.bssid);
if (obj.containsKey("bssid")) {
parseBSSID(obj["bssid"], ap.bssid);
} else {
memset(ap.bssid, 0, 6); // Zero BSSID if missing
}
ap.stations = new LinkedList<uint16_t>();
ap.rssi = obj.containsKey("rssi") ? obj["rssi"].as<int>() : -127;
ap.packets = obj.containsKey("packet") ? obj["packet"].as<uint32_t>() : 0;
ap.sec = obj.containsKey("sec") ? obj["sec"].as<uint8_t>() : 0;
ap.wps = obj.containsKey("wps") ? obj["wps"].as<bool>() : false;
ap.man = obj.containsKey("man") ? obj["man"].as<String>() : "Unknown";
access_points->add(ap);
Serial.println("Got: " + ap.essid);
}
file.close();
//doc.clear();
#ifdef HAS_SCREEN
display_obj.tft.setTextWrap(false);
display_obj.tft.setFreeFont(NULL);
display_obj.tft.setCursor(0, 100);
display_obj.tft.setTextSize(1);
display_obj.tft.setTextColor(TFT_CYAN);
display_obj.tft.print("Loaded APs: ");
display_obj.tft.println((String)access_points->size());
#endif
@@ -1444,6 +1460,11 @@ void WiFiScan::RunSaveAPList(bool save_as) {
ap.bssid[0], ap.bssid[1], ap.bssid[2],
ap.bssid[3], ap.bssid[4], ap.bssid[5]);
jsonAp["bssid"] = bssidStr;
jsonAp["rssi"] = ap.rssi;
jsonAp["packets"] = ap.packets;
jsonAp["sec"] = ap.sec;
jsonAp["wps"] = ap.wps;
jsonAp["man"] = ap.man;
}
String jsonString;
@@ -1624,7 +1645,6 @@ void WiFiScan::RunAPScan(uint8_t scan_mode, uint16_t color)
delete access_points;
access_points = new LinkedList<AccessPoint>();
//esp_wifi_init(&cfg);
esp_wifi_init(&cfg2);
esp_wifi_set_storage(WIFI_STORAGE_RAM);
esp_wifi_set_mode(WIFI_MODE_NULL);
@@ -1632,10 +1652,7 @@ void WiFiScan::RunAPScan(uint8_t scan_mode, uint16_t color)
this->setMac();
esp_wifi_set_promiscuous(true);
esp_wifi_set_promiscuous_filter(&filt);
//if (scan_mode == WIFI_SCAN_TARGET_AP_FULL)
esp_wifi_set_promiscuous_rx_cb(&apSnifferCallbackFull);
//else
// esp_wifi_set_promiscuous_rx_cb(&apSnifferCallback);
esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE);
this->wifi_initialized = true;
initTime = millis();
@@ -1714,13 +1731,23 @@ void WiFiScan::RunClearSSIDs() {
}
void WiFiScan::setMac() {
wifi_mode_t currentWiFiMode;
esp_wifi_get_mode(&currentWiFiMode);
esp_err_t result;
result = esp_wifi_set_mac(WIFI_IF_AP, this->ap_mac);
if (result != ESP_OK) Serial.printf("Failed to set AP MAC: %s | 0x%X\n", macToString(this->ap_mac), result);
else Serial.println("Successfully set AP MAC: " + macToString(this->ap_mac));
if ((result != ESP_OK) &&
((currentWiFiMode == WIFI_MODE_AP) || (currentWiFiMode == WIFI_MODE_APSTA) || (currentWiFiMode == WIFI_MODE_NULL)))
Serial.printf("Failed to set AP MAC: %s | 0x%X\n", macToString(this->ap_mac), result);
else if ((currentWiFiMode == WIFI_MODE_AP) || (currentWiFiMode == WIFI_MODE_APSTA) || (currentWiFiMode == WIFI_MODE_NULL))
Serial.println("Successfully set AP MAC: " + macToString(this->ap_mac));
// Do the station
result = esp_wifi_set_mac(WIFI_IF_STA, this->sta_mac);
if (result != ESP_OK) Serial.printf("Failed to set STA MAC: %s | 0x%X\n", macToString(this->sta_mac), result);
else Serial.println("Successfully set STA MAC: " + macToString(this->sta_mac));
if ((result != ESP_OK) &&
((currentWiFiMode == WIFI_MODE_STA) || (currentWiFiMode == WIFI_MODE_APSTA)))
Serial.printf("Failed to set STA MAC: %s | 0x%X\n", macToString(this->sta_mac), result);
else if ((currentWiFiMode == WIFI_MODE_STA) || (currentWiFiMode == WIFI_MODE_APSTA))
Serial.println("Successfully set STA MAC: " + macToString(this->sta_mac));
}
void WiFiScan::RunSetMac(uint8_t * mac, bool ap) {
@@ -2014,6 +2041,31 @@ void WiFiScan::RunAPInfo(uint16_t index, bool do_display) {
Serial.println(" RSSI: " + (String)access_points->get(index).rssi);
Serial.println(" Frames: " + (String)access_points->get(index).packets);
Serial.println("Stations: " + (String)access_points->get(index).stations->size());
Serial.println(" Brand: " + (String)access_points->get(index).man);
uint8_t sec = access_points->get(index).sec;
bool wps = access_points->get(index).wps;
Serial.print("Security: ");
switch (sec) {
case WIFI_SECURITY_OPEN: Serial.println("Open"); break;
case WIFI_SECURITY_WEP: Serial.println("WEP"); break;
case WIFI_SECURITY_WPA: Serial.println("WPA"); break;
case WIFI_SECURITY_WPA2: Serial.println("WPA2"); break;
case WIFI_SECURITY_WPA3: Serial.println("WPA3"); break;
case WIFI_SECURITY_WPA_WPA2_MIXED: Serial.println("WPA/WPA2 Mixed"); break;
case WIFI_SECURITY_WPA2_ENTERPRISE: Serial.println("WPA2 Enterprise"); break;
case WIFI_SECURITY_WPA3_ENTERPRISE: Serial.println("WPA3 Enterprise"); break;
case WIFI_SECURITY_WAPI: Serial.println("WAPI"); break;
default: Serial.println("Unknown"); break;
}
Serial.print(" WPS: ");
switch (wps) {
case true: Serial.println("true"); break;
case false: Serial.println("false"); break;
default: Serial.println("false"); break;
}
#ifdef HAS_SCREEN
if (do_display) {
@@ -2023,6 +2075,28 @@ void WiFiScan::RunAPInfo(uint16_t index, bool do_display) {
display_obj.tft.println(" RSSI: " + (String)access_points->get(index).rssi);
display_obj.tft.println(" Frames: " + (String)access_points->get(index).packets);
display_obj.tft.println("Stations: " + (String)access_points->get(index).stations->size());
display_obj.tft.println(" Brand: " + (String)access_points->get(index).man);
display_obj.tft.print("Security: ");
switch (sec) {
case WIFI_SECURITY_OPEN: display_obj.tft.println("Open"); break;
case WIFI_SECURITY_WEP: display_obj.tft.println("WEP"); break;
case WIFI_SECURITY_WPA: display_obj.tft.println("WPA"); break;
case WIFI_SECURITY_WPA2: display_obj.tft.println("WPA2"); break;
case WIFI_SECURITY_WPA3: display_obj.tft.println("WPA3"); break;
case WIFI_SECURITY_WPA_WPA2_MIXED: display_obj.tft.println("WPA/WPA2 Mixed"); break;
case WIFI_SECURITY_WPA2_ENTERPRISE: display_obj.tft.println("WPA2 Enterprise"); break;
case WIFI_SECURITY_WPA3_ENTERPRISE: display_obj.tft.println("WPA3 Enterprise"); break;
case WIFI_SECURITY_WAPI: display_obj.tft.println("WAPI"); break;
default: display_obj.tft.println("Unknown"); break;
}
display_obj.tft.print(" WPS: ");
switch (wps) {
case true: display_obj.tft.println("true"); break;
case false: display_obj.tft.println("false"); break;
default: display_obj.tft.println("false"); break;
}
}
#endif
@@ -3261,6 +3335,68 @@ void WiFiScan::pwnSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
}
}
int WiFiScan::checkMatchAP(char addr[]) {
for (int i = 0; i < access_points->size(); i++) {
bool mac_match = true;
for (int x = 0; x < 6; x++) {
if ((uint8_t)strtol(&addr[x * 3], NULL, 16) != access_points->get(i).bssid[x]) {
mac_match = false;
break;
}
}
if (mac_match) {
AccessPoint ap = access_points->get(i);
ap.packets += 1;
access_points->set(i, ap);
return i;
}
}
return -1;
}
String WiFiScan::extractManufacturer(const uint8_t* payload) {
const int fixedHeaderSize = 36; // 802.11 mgmt header (24) + fixed fields (12)
int pos = fixedHeaderSize;
while (pos < 512) { // safety bounds
uint8_t tagNumber = payload[pos];
uint8_t tagLength = payload[pos + 1];
// Check for vendor-specific IE (Tag number 221)
if (tagNumber == 0xdd && tagLength >= 4) {
const uint8_t* oui = &payload[pos + 2];
// Check if OUI is 00:50:F2 (Microsoft WPS)
if (oui[0] == 0x00 && oui[1] == 0x50 && oui[2] == 0xF2) {
int wpsPos = pos + 6; // Skip: tag + len + OUI (2 + 1 + 3)
int end = pos + 2 + tagLength;
// Iterate through WPS sub-TLVs
while (wpsPos + 4 <= end) {
uint16_t type = (payload[wpsPos] << 8) | payload[wpsPos + 1];
uint16_t len = (payload[wpsPos + 2] << 8) | payload[wpsPos + 3];
if (type == 0x1021) { // Manufacturer
char buffer[65]; // reasonable max
int copyLen = len > 64 ? 64 : len;
memcpy(buffer, &payload[wpsPos + 4], copyLen);
buffer[copyLen] = '\0';
return String(buffer);
}
wpsPos += 4 + len;
}
}
}
pos += 2 + tagLength;
}
return String(""); // not found
}
void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type) {
extern WiFiScan wifi_scan_obj;
wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf;
@@ -3277,47 +3413,64 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type
if (type == WIFI_PKT_MGMT)
{
len -= 4;
int fctl = ntohs(frameControl->fctl);
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload;
const WifiMgmtHdr *hdr = &ipkt->hdr;
//int fctl = ntohs(frameControl->fctl);
//const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload;
//const WifiMgmtHdr *hdr = &ipkt->hdr;
// If we dont the buffer size is not 0, don't write or else we get CORRUPT_HEAP
#ifdef HAS_SCREEN
int buf = display_obj.display_buffer->size();
#else
int buf = 0;
#endif
int buf = 0;
bool wps = wifi_scan_obj.beaconHasWPS(snifferPacket->payload, len);
// We got a probe resp. Check for WPS configs
if (snifferPacket->payload[0] == 0x50) {
String man = wifi_scan_obj.extractManufacturer(snifferPacket->payload);
if (wps) {
char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->payload, 10);
int index = wifi_scan_obj.checkMatchAP(addr);
if ((index > 0) && (!access_points->get(index).wps)) {
AccessPoint new_ap = access_points->get(index);
new_ap.wps = true;
new_ap.man = man;
access_points->set(index, new_ap);
Serial.println((String)access_points->get(index).essid + ": RXd WPS Configs");
#ifdef HAS_SCREEN
display_string = RED_KEY;
display_string.concat((String)access_points->get(index).essid + ": RXd WPS Configs");
int temp_len = display_string.length();
for (int i = 0; i < 50 - temp_len; i++)
display_string.concat(" ");
display_obj.display_buffer->add(display_string);
#endif
}
}
}
// We got an AP. Check if in list and add if not
if ((snifferPacket->payload[0] == 0x80) && (buf == 0))
{
// Get security info
uint8_t security_type = wifi_scan_obj.getSecurityType(snifferPacket->payload, len);
#ifdef HAS_SCREEN
display_string = GREEN_KEY;
if (!wps)
display_string = GREEN_KEY;
else
display_string = RED_KEY;
#endif
char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->payload, 10);
bool in_list = false;
bool mac_match = true;
int in_list = wifi_scan_obj.checkMatchAP(addr);
for (int i = 0; i < access_points->size(); i++) {
mac_match = true;
for (int x = 0; x < 6; x++) {
if (snifferPacket->payload[x + 10] != access_points->get(i).bssid[x]) {
mac_match = false;
break;
}
}
if (mac_match) {
in_list = true;
AccessPoint ap = access_points->get(i);
ap.packets = ap.packets + 1;
access_points->set(i, ap);
break;
}
}
if (!in_list) {
if (in_list < 0) {
Serial.print("RSSI: ");
Serial.print(snifferPacket->rx_ctrl.rssi);
@@ -3373,19 +3526,6 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type
Serial.print(essid + " ");
}
//LinkedList<char> beacon = new LinkedList<char>();
/*AccessPoint ap = {essid,
snifferPacket->rx_ctrl.channel,
{snifferPacket->payload[10],
snifferPacket->payload[11],
snifferPacket->payload[12],
snifferPacket->payload[13],
snifferPacket->payload[14],
snifferPacket->payload[15]},
false,
NULL};*/
if (wifi_scan_obj.checkMem()) {
AccessPoint ap;
@@ -3422,6 +3562,14 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type
ap.rssi = snifferPacket->rx_ctrl.rssi;
ap.sec = security_type;
ap.wps = wps;
ap.packets = 0;
ap.man = "";
access_points->add(ap);
Serial.print(access_points->size());
@@ -3438,6 +3586,8 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type
}
}
}
// We got a client possibly. Check for AP association
if ((snifferPacket->payload[0] != 0x80) && (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA)) {
#ifdef HAS_SCREEN
display_string = CYAN_KEY;
@@ -3584,6 +3734,129 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type
}
}
bool WiFiScan::beaconHasWPS(const uint8_t* payload, int len) {
int i = 36; // skip radiotap + fixed 802.11 header
while (i < len - 2) {
uint8_t tagNumber = payload[i];
uint8_t tagLength = payload[i + 1];
if (i + 2 + tagLength > len) break; // prevent overflow
const uint8_t* tagData = &payload[i + 2];
// Look for Tag Number 0xDD (Vendor Specific)
if (tagNumber == 0xDD && tagLength >= 6) {
// Check for WPS OUI: 00:50:F2 and WPS type: 0x04
if (tagData[0] == 0x00 && tagData[1] == 0x50 && tagData[2] == 0xF2 && tagData[3] == 0x04) {
// Parse the WPS IE data starting after the OUI and type
int wpsLen = tagLength - 4;
const uint8_t* wpsData = &tagData[4];
int j = 0;
while (j + 4 <= wpsLen) {
uint16_t attrType = (wpsData[j] << 8) | wpsData[j + 1];
uint16_t attrLen = (wpsData[j + 2] << 8) | wpsData[j + 3];
if (j + 4 + attrLen > wpsLen) break; // prevent overflow
if (attrType == 0x1008 && attrLen == 2) { // Config Methods attribute
uint16_t configMethods = (wpsData[j + 4] << 8) | wpsData[j + 5];
// Check for any vulnerable method
if (configMethods & (WPS_CONFIG_LABEL |
WPS_CONFIG_DISPLAY |
WPS_CONFIG_KEYPAD |
WPS_CONFIG_VIRT_DISPLAY |
WPS_CONFIG_PHY_DISPLAY |
WPS_CONFIG_PUSH_BUTTON |
WPS_CONFIG_VIRT_PUSH_BUTTON |
WPS_CONFIG_PHY_PUSH_BUTTON)) {
return true;
}
}
j += 4 + attrLen;
}
}
}
i += 2 + tagLength;
}
return false;
}
uint8_t WiFiScan::getSecurityType(const uint8_t* beacon, uint16_t len) {
const uint8_t* frame = beacon;
const uint8_t* ies = beacon + 36; // Start of tagged parameters
uint16_t ies_len = len - 36;
bool hasRSN = false;
bool hasWPA = false;
bool hasWEP = false;
bool isEnterprise = false;
bool isWPA3 = false;
bool isWAPI = false;
uint16_t i = 0;
while (i + 2 <= ies_len) {
uint8_t tag_id = ies[i];
uint8_t tag_len = ies[i + 1];
if (i + 2 + tag_len > ies_len) break;
const uint8_t* tag_data = ies + i + 2;
// Check for RSN (WPA2)
if (tag_id == 48) {
hasRSN = true;
// WPA2-Enterprise usually uses 802.1X AKM (type 1)
if (tag_len >= 20 && tag_data[14] == 0x01 && tag_data[15] == 0x00 && tag_data[16] == 0x00 && tag_data[17] == 0x0f && tag_data[18] == 0xac) {
isEnterprise = true;
}
// WPA3 typically uses SAE (type 8)
if (tag_len >= 20 && tag_data[14] == 0x01 && tag_data[15] == 0x00 && tag_data[16] == 0x00 && tag_data[17] == 0x0f && tag_data[18] == 0xac && tag_data[19] == 0x08) {
isWPA3 = true;
}
}
// Check for WPA (in vendor specific tag)
else if (tag_id == 221 && tag_len >= 8 &&
tag_data[0] == 0x00 && tag_data[1] == 0x50 && tag_data[2] == 0xF2 && tag_data[3] == 0x01) {
hasWPA = true;
// WPA-Enterprise (AKM 1)
if (tag_len >= 20 && tag_data[14] == 0x01 && tag_data[15] == 0x00 && tag_data[16] == 0x00 && tag_data[17] == 0x50 && tag_data[18] == 0xf2) {
isEnterprise = true;
}
}
// Check for WAPI (Chinese standard)
else if (tag_id == 221 && tag_len >= 4 &&
tag_data[0] == 0x00 && tag_data[1] == 0x14 && tag_data[2] == 0x72 && tag_data[3] == 0x01) {
isWAPI = true;
}
i += 2 + tag_len;
}
// Decision tree
if (isWAPI) return WIFI_SECURITY_WAPI;
if (hasRSN && isWPA3) return WIFI_SECURITY_WPA3;
if (hasRSN && isEnterprise) return WIFI_SECURITY_WPA2_ENTERPRISE;
if (hasRSN && hasWPA) return WIFI_SECURITY_WPA_WPA2_MIXED;
if (hasRSN) return WIFI_SECURITY_WPA2;
if (hasWPA) return isEnterprise ? WIFI_SECURITY_WPA2_ENTERPRISE : WIFI_SECURITY_WPA;
// WEP is identified via capability flags
uint16_t capab_info = ((uint16_t)frame[34] << 8) | frame[35];
if (capab_info & 0x0010) return WIFI_SECURITY_WEP;
return WIFI_SECURITY_OPEN;
}
void WiFiScan::apSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
{
extern WiFiScan wifi_scan_obj;
@@ -3672,6 +3945,11 @@ void WiFiScan::apSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
essid = bssid;
Serial.print(essid + " ");
}
// Get security info
uint8_t security_type = wifi_scan_obj.getSecurityType(snifferPacket->payload, snifferPacket->rx_ctrl.sig_len);
bool wps = wifi_scan_obj.beaconHasWPS(snifferPacket->payload, snifferPacket->rx_ctrl.sig_len);
AccessPoint ap = {essid,
snifferPacket->rx_ctrl.channel,
@@ -3685,7 +3963,9 @@ void WiFiScan::apSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
NULL,
snifferPacket->rx_ctrl.rssi,
new LinkedList<uint16_t>(),
0};
0,
security_type,
wps};
access_points->add(ap);
@@ -4189,6 +4469,25 @@ void WiFiScan::rawSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload;
const WifiMgmtHdr *hdr = &ipkt->hdr;
wifi_scan_obj.mgmt_frames++;
// Do our counts
if (snifferPacket->payload[0] == 0x40) // Probe request
wifi_scan_obj.req_frames++;
else if (snifferPacket->payload[0] == 0x50) // Probe response
wifi_scan_obj.resp_frames++;
else if (snifferPacket->payload[0] == 0x80) // Beacon
wifi_scan_obj.beacon_frames++;
else if (snifferPacket->payload[0] == 0xC0) // Deauth
wifi_scan_obj.deauth_frames++;
else if (((snifferPacket->payload[30] == 0x88 && snifferPacket->payload[31] == 0x8e) || ( snifferPacket->payload[32] == 0x88 && snifferPacket->payload[33] == 0x8e))) // eapol
wifi_scan_obj.eapol_frames++;
// Get min/max rssi
if (snifferPacket->rx_ctrl.rssi < wifi_scan_obj.min_rssi)
wifi_scan_obj.min_rssi = snifferPacket->rx_ctrl.rssi;
if (snifferPacket->rx_ctrl.rssi > wifi_scan_obj.max_rssi)
wifi_scan_obj.max_rssi = snifferPacket->rx_ctrl.rssi;
}
else {
wifi_scan_obj.data_frames++;
@@ -5799,19 +6098,32 @@ void WiFiScan::renderRawStats() {
display_obj.tft.println("Stats\n");
display_obj.tft.println("Mgmt: " + (String)this->mgmt_frames);
display_obj.tft.println("Data: " + (String)this->data_frames);
display_obj.tft.println("Chan: " + (String)this->set_channel);
display_obj.tft.println(" Mgmt: " + (String)this->mgmt_frames);
display_obj.tft.println(" Data: " + (String)this->data_frames);
display_obj.tft.println(" Channel: " + (String)this->set_channel);
display_obj.tft.println(" Beacon: " + (String)this->beacon_frames);
display_obj.tft.println("Probe Req: " + (String)this->req_frames);
display_obj.tft.println("Probe Res: " + (String)this->resp_frames);
display_obj.tft.println(" Deauth: " + (String)this->deauth_frames);
display_obj.tft.println(" EAPOL: " + (String)this->eapol_frames);
display_obj.tft.println(" RSSI: " + (String)this->min_rssi + " - " + (String)this->max_rssi);
Serial.println("Mgmt: " + (String)this->mgmt_frames);
Serial.println("Data: " + (String)this->data_frames);
Serial.println("Chan: " + (String)this->set_channel);
#endif
Serial.println(" Mgmt: " + (String)this->mgmt_frames);
Serial.println(" Data: " + (String)this->data_frames);
Serial.println(" Channel: " + (String)this->set_channel);
Serial.println(" Beacon: " + (String)this->beacon_frames);
Serial.println("Probe Req: " + (String)this->req_frames);
Serial.println("Probe Res: " + (String)this->resp_frames);
Serial.println(" Deauth: " + (String)this->deauth_frames);
Serial.println(" EAPOL: " + (String)this->eapol_frames);
Serial.println(" RSSI: " + (String)this->min_rssi + " - " + (String)this->max_rssi);
}
void WiFiScan::renderPacketRate() {
uint8_t line_count = 0;
#ifdef HAS_SCREEN
uint8_t line_count = 0;
display_obj.tft.fillRect(0,
(STATUS_BAR_WIDTH * 2) + 1 + EXT_BUTTON_WIDTH,
TFT_WIDTH,
@@ -5820,62 +6132,65 @@ void WiFiScan::renderPacketRate() {
display_obj.tft.setCursor(0, (STATUS_BAR_WIDTH * 2) + CHAR_WIDTH + EXT_BUTTON_WIDTH);
display_obj.tft.setTextSize(1);
display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
for (int i = 0; i < access_points->size(); i++) {
if (access_points->get(i).selected) {
display_obj.tft.println(access_points->get(i).essid + ": " + (String)access_points->get(i).packets);
Serial.println(access_points->get(i).essid + ": " + (String)access_points->get(i).packets);
}
}
for (int i = 0; i < stations->size(); i++) {
if (stations->get(i).selected) {
display_obj.tft.println(macToString(stations->get(i).mac) + ": " + (String)stations->get(i).packets);
Serial.println(macToString(stations->get(i).mac) + ": " + (String)stations->get(i).packets);
}
}
#endif
for (int i = 0; i < access_points->size(); i++) {
if (access_points->get(i).selected) {
#ifdef HAS_SCREEN
display_obj.tft.println(access_points->get(i).essid + ": " + (String)access_points->get(i).packets);
#endif
Serial.println(access_points->get(i).essid + ": " + (String)access_points->get(i).packets);
}
}
for (int i = 0; i < stations->size(); i++) {
if (stations->get(i).selected) {
#ifdef HAS_SCREEN
display_obj.tft.println(macToString(stations->get(i).mac) + ": " + (String)stations->get(i).packets);
#endif
Serial.println(macToString(stations->get(i).mac) + ": " + (String)stations->get(i).packets);
}
}
}
void WiFiScan::packetRateLoop(uint32_t tick) {
#ifdef HAS_SCREEN
if (tick - this->initTime >= BANNER_TIME * 10) {
this->initTime = millis();
if (this->currentScanMode == WIFI_SCAN_PACKET_RATE)
this->renderPacketRate();
else if (this->currentScanMode == WIFI_SCAN_RAW_CAPTURE)
this->renderRawStats();
if (tick - this->initTime >= BANNER_TIME * 10) {
this->initTime = millis();
if (this->currentScanMode == WIFI_SCAN_PACKET_RATE)
this->renderPacketRate();
else if (this->currentScanMode == WIFI_SCAN_RAW_CAPTURE)
this->renderRawStats();
}
#ifdef HAS_ILI9341
int8_t b = this->checkAnalyzerButtons(millis());
if (b == 6) {
this->StartScan(WIFI_SCAN_OFF);
this->orient_display = true;
return;
}
#ifdef HAS_ILI9341
int8_t b = this->checkAnalyzerButtons(millis());
if (b == 6) {
this->StartScan(WIFI_SCAN_OFF);
this->orient_display = true;
else if (b == 4) {
if (set_channel > 1) {
set_channel--;
display_obj.tftDrawChannelScaleButtons(set_channel, false);
display_obj.tftDrawExitScaleButtons(false);
changeChannel();
return;
}
else if (b == 4) {
if (set_channel > 1) {
set_channel--;
display_obj.tftDrawChannelScaleButtons(set_channel, false);
display_obj.tftDrawExitScaleButtons(false);
changeChannel();
return;
}
}
}
// Channel + button pressed
else if (b == 5) {
if (set_channel < MAX_CHANNEL) {
set_channel++;
display_obj.tftDrawChannelScaleButtons(set_channel, false);
display_obj.tftDrawExitScaleButtons(false);
changeChannel();
return;
}
// Channel + button pressed
else if (b == 5) {
if (set_channel < MAX_CHANNEL) {
set_channel++;
display_obj.tftDrawChannelScaleButtons(set_channel, false);
display_obj.tftDrawExitScaleButtons(false);
changeChannel();
return;
}
#endif
}
#endif
}

View File

@@ -109,6 +109,31 @@
#define MAX_CHANNEL 14
#define WIFI_SECURITY_OPEN 0
#define WIFI_SECURITY_WEP 1
#define WIFI_SECURITY_WPA 2
#define WIFI_SECURITY_WPA2 3
#define WIFI_SECURITY_WPA3 4
#define WIFI_SECURITY_WPA_WPA2_MIXED 5
#define WIFI_SECURITY_WPA2_ENTERPRISE 6
#define WIFI_SECURITY_WPA3_ENTERPRISE 7
#define WIFI_SECURITY_WAPI 8
#define WIFI_SECURITY_UNKNOWN 255
#define WPS_CONFIG_USBA 0x0001
#define WPS_CONFIG_ETHERNET 0x0002
#define WPS_CONFIG_LABEL 0x0004
#define WPS_CONFIG_DISPLAY 0x0008
#define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
#define WPS_CONFIG_INT_NFC_TOKEN 0x0020
#define WPS_CONFIG_NFC_INTERFACE 0x0040
#define WPS_CONFIG_PUSH_BUTTON 0x0080
#define WPS_CONFIG_KEYPAD 0x0100
#define WPS_CONFIG_VIRT_PUSH_BUTTON 0x1000
#define WPS_CONFIG_PHY_PUSH_BUTTON 0x2000
#define WPS_CONFIG_VIRT_DISPLAY 0x4000
#define WPS_CONFIG_PHY_DISPLAY 0x8000
extern EvilPortal evil_portal_obj;
#ifdef HAS_SCREEN
@@ -314,6 +339,10 @@ class WiFiScan
NimBLEAdvertisementData GetUniversalAdvertisementData(EBLEPayloadType type);
#endif
String extractManufacturer(const uint8_t* payload);
int checkMatchAP(char addr[]);
bool beaconHasWPS(const uint8_t* payload, int len);
uint8_t getSecurityType(const uint8_t* beacon, uint16_t len);
void addAnalyzerValue(int16_t value, int rssi_avg, int16_t target_array[], int array_size);
bool seen_mac(unsigned char* mac);
bool mac_cmp(struct mac_addr addr1, struct mac_addr addr2);
@@ -380,6 +409,13 @@ class WiFiScan
// Stuff for RAW stats
uint32_t mgmt_frames = 0;
uint32_t data_frames = 0;
uint32_t beacon_frames = 0;
uint32_t req_frames = 0;
uint32_t resp_frames = 0;
uint32_t deauth_frames = 0;
uint32_t eapol_frames = 0;
int8_t min_rssi = 0;
int8_t max_rssi = -128;
String analyzer_name_string = "";

View File

@@ -7,7 +7,7 @@
#define POLISH_POTATO
//// BOARD TARGETS
//#define MARAUDER_M5STICKC
//#define MARAUDER_M5STICKC
//#define MARAUDER_M5STICKCP2
//#define MARAUDER_MINI
//#define MARAUDER_V4
@@ -23,7 +23,7 @@
//#define MARAUDER_REV_FEATHER
//// END BOARD TARGETS
#define MARAUDER_VERSION "v1.4.0"
#define MARAUDER_VERSION "v1.4.3"
#define GRAPH_REFRESH 100
@@ -1145,6 +1145,8 @@
//// SCREEN STUFF
#ifndef HAS_SCREEN
#define BANNER_TIME GRAPH_REFRESH
#define TFT_WHITE 0
#define TFT_CYAN 0
#define TFT_BLUE 0

View File

@@ -150,7 +150,7 @@ void backlightOff() {
void setup()
{
//esp_spiram_init();
esp_spiram_init();
#ifdef defined(MARAUDER_M5STICKC) && !defined(MARAUDER_M5STICKCP2)
axp192_obj.begin();