diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp index 4ca9af9..8fc337d 100644 --- a/esp32_marauder/MenuFunctions.cpp +++ b/esp32_marauder/MenuFunctions.cpp @@ -339,6 +339,7 @@ void MenuFunctions::main(uint32_t currentTime) (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) || (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) || + (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) || (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) || (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) || (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) || @@ -407,6 +408,7 @@ void MenuFunctions::main(uint32_t currentTime) (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) || + (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) || (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) || (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) || @@ -3205,17 +3207,17 @@ void MenuFunctions::RunSetup() // Clear nodes and add back button wifiAPMenu.list->clear(); - this->addNodes(&wifiAPMenu, text09, TFT_LIGHTGREY, 0, [this]() { + this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() { this->changeMenu(wifiAPMenu.parentMenu, true); }); - // Add buttons for all airtags - // Find out how big our menu is going to be - int menu_limit; - if (airtags->size() <= BUTTON_ARRAY_LEN) - menu_limit = airtags->size(); - else - menu_limit = BUTTON_ARRAY_LEN; + /*this->addNodes(&wifiAPMenu, "Live", TFTMAGENTA, 0, [this]() { + display_obj.clearScreen(); + this->drawStatusBar(); + wifi_scan_obj.StartScan(BT_ATTACK_FINDMY_LIVE, TFT_RED); + });*/ + + int menu_limit = airtags->size(); // Create the menu nodes for all of the list items for (int i = 0; i < menu_limit; i++) { @@ -3224,6 +3226,7 @@ void MenuFunctions::RunSetup() this->addNodes(&wifiAPMenu, node_name.c_str(), node_color, BLUETOOTH, [this, i](){ AirTag new_at = airtags->get(i); new_at.selected = true; + new_at.connectable = true; airtags->set(i, new_at); diff --git a/esp32_marauder/WiFiScan.cpp b/esp32_marauder/WiFiScan.cpp index 42b8724..eb45b90 100644 --- a/esp32_marauder/WiFiScan.cpp +++ b/esp32_marauder/WiFiScan.cpp @@ -314,7 +314,60 @@ extern "C" { String display_string = ""; - if ((wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) || + if (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) { + if (connectionPending) { + wifi_scan_obj.bt_cb_busy = false; + return; + } + + #ifndef HAS_NIMBLE_2 + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + if (!payLoad) { + wifi_scan_obj.bt_cb_busy = false; + return; + } + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif + + bool match = false; + if (len >= 4) { + for (size_t i = 0; i <= len - 4; i++) { + if (payLoad[i] == 0x1E && payLoad[i+1] == 0xFF && payLoad[i+2] == 0x4C && payLoad[i+3] == 0x00) { + match = true; + break; + } + if (payLoad[i] == 0x4C && payLoad[i+1] == 0x00 && payLoad[i+2] == 0x12) { + match = true; + break; + } + } + } else { + wifi_scan_obj.bt_cb_busy = false; + return; + } + + bool is_fmna = false; + bool is_dult = false; + + if (advertisedDevice->isAdvertisingService(FMNA_SERVICE_UUID)) { + is_fmna = true; + } + else if (advertisedDevice->isAdvertisingService(DULT_SERVICE_UUID)) { + is_dult = true; + } + + if ((match) || (is_fmna) || (is_dult)) { + pendingAddress = advertisedDevice->getAddress(); + connectionPending = true; + wifi_scan_obj.bt_cb_busy = false; + return; + } + } + + else if ((wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) || (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON)) { //Serial.println("Getting payload length..."); //Serial.flush(); @@ -986,7 +1039,61 @@ extern "C" { String display_string = ""; - if ((wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) || + if (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) { + if (connectionPending) { + wifi_scan_obj.bt_cb_busy = false; + return; + } + + #ifndef HAS_NIMBLE_2 + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + if (!payLoad) { + wifi_scan_obj.bt_cb_busy = false; + return; + } + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif + + bool match = false; + if (len >= 4) { + for (size_t i = 0; i <= len - 4; i++) { + if (payLoad[i] == 0x1E && payLoad[i+1] == 0xFF && payLoad[i+2] == 0x4C && payLoad[i+3] == 0x00) { + match = true; + break; + } + if (payLoad[i] == 0x4C && payLoad[i+1] == 0x00 && payLoad[i+2] == 0x12) { + match = true; + break; + } + } + } else { + wifi_scan_obj.bt_cb_busy = false; + return; + } + + bool is_fmna = false; + bool is_dult = false; + + if (advertisedDevice->isAdvertisingService(FMNA_SERVICE_UUID)) { + is_fmna = true; + } + else if (advertisedDevice->isAdvertisingService(DULT_SERVICE_UUID)) { + is_dult = true; + } + + if ((match) || (is_fmna) || (is_dult)) { + pendingAddress = advertisedDevice->getAddress(); + Serial.println("Detected " + String(pendingAddress.toString().c_str())); + connectionPending = true; + wifi_scan_obj.bt_cb_busy = false; + return; + } + } + + else if ((wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) || (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON)) { #ifndef HAS_NIMBLE_2 uint8_t* payLoad = advertisedDevice->getPayload(); @@ -2261,6 +2368,11 @@ void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color) { RunBluetoothScan(scan_mode, color); #endif } + else if (scan_mode == BT_ATTACK_FINDMY_LIVE) { + #ifdef HAS_BT + this->RunFindMyLive(scan_mode, color); + #endif + } else if ((scan_mode == BT_ATTACK_SOUR_APPLE) || (scan_mode == BT_ATTACK_APPLE_JUICE)) { #ifdef HAS_BT @@ -2634,6 +2746,7 @@ void WiFiScan::StopScan(uint8_t scan_mode) { (currentScanMode == BT_SCAN_AIRTAG_MON) || (currentScanMode == BT_SCAN_FLIPPER) || (currentScanMode == BT_SCAN_FLOCK) || + (currentScanMode == BT_ATTACK_FINDMY_LIVE) || (currentScanMode == BT_ATTACK_SOUR_APPLE) || (currentScanMode == BT_ATTACK_APPLE_JUICE) || (currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) || @@ -4586,12 +4699,18 @@ int WiFiScan::connectAndProcessTracker(NimBLEAddress& address) { Serial.println(address.toString().c_str()); - nimbleClient->setConnectTimeout(5000); + nimbleClient->setConnectTimeout(15000); if (!nimbleClient->connect(address, true, false, true)) { Serial.printf("Connection failed; error=%d\n", nimbleClient->getLastError()); + + Serial.printf( + "connected=%d lastError=%d\n", + nimbleClient->isConnected(), + nimbleClient->getLastError() + ); - return -1; + //return -1; } bool hasAirTagService = false; @@ -4885,6 +5004,119 @@ bool WiFiScan::sendAirtagSoundCommand(NimBLEClient* currentClient) { return false; } +bool WiFiScan::backendFindMySound(NimBLEAddress& address, bool gui) { + bool send_success = false; + + int device_type = this->connectAndProcessTracker(address); + + if (device_type >= 0) { + Serial.println("Connected to " + String(address.toString().c_str())); + #ifdef HAS_SCREEN + if (gui) { + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + display_obj.tft.println("Connected"); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + #endif + + if (device_type == IS_AIRTAG) { + #ifdef HAS_SCREEN + if (gui) + display_obj.tft.println("Type: Airtag"); + #endif + send_success = this->sendAirtagSoundCommand(nimbleClient); + if (send_success) { + #ifdef HAS_SCREEN + if (gui) { + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + display_obj.tft.println("Command sent"); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + #endif + } else { + #ifdef HAS_SCREEN + if (gui) { + display_obj.tft.setTextColor(TFT_RED, TFT_BLACK); + display_obj.tft.println("Failed to send AT cmd"); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + #endif + } + } + else if (device_type == IS_FMNA) { + #ifdef HAS_SCREEN + if (gui) + display_obj.tft.println("Type: FMNA"); + #endif + send_success = this->sendFmnaSoundCommand(nimbleClient); + if (send_success) { + #ifdef HAS_SCREEN + if (gui) { + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + display_obj.tft.println("Command sent"); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + #endif + } else { + #ifdef HAS_SCREEN + if (gui) { + display_obj.tft.setTextColor(TFT_RED, TFT_BLACK); + display_obj.tft.println("Failed to send FMNA cmd"); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + #endif + } + } + else { + #ifdef HAS_SCREEN + if (gui) + display_obj.tft.println("Type: DULT"); + #endif + send_success = this->sendDultSoundCommand(nimbleClient); + if (send_success) { + #ifdef HAS_SCREEN + if (gui) { + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + display_obj.tft.println("Command sent"); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + #endif + } else { + #ifdef HAS_SCREEN + if (gui) { + display_obj.tft.setTextColor(TFT_RED, TFT_BLACK); + display_obj.tft.println("Failed to send DULT cmd"); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + #endif + } + } + } else { + #ifdef HAS_SCREEN + if (gui) { + display_obj.tft.setTextColor(TFT_RED, TFT_BLACK); + display_obj.tft.println("Failed to connect"); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + } + #endif + } + + if (nimbleClient != nullptr) { + if (nimbleClient->isConnected()) { + Serial.println("Disconnecting locally..."); + + nimbleClient->disconnect(); + } + + NimBLEDevice::deleteClient(nimbleClient); + nimbleClient = nullptr; + } + + NimBLEDevice::deinit(true); + + return send_success; +} + bool WiFiScan::executeFindMySound(bool gui) { bool send_success = false; bool selected = false; @@ -4910,121 +5142,59 @@ bool WiFiScan::executeFindMySound(bool gui) { selected = true; - uint8_t addr[6]; - - convertMacStringToUint8(airtag.mac, addr); - - int device_type = this->connectAndProcessTracker(airtag.device_address); - - if (device_type >= 0) { - Serial.println("Connected to " + airtag.mac); - #ifdef HAS_SCREEN - if (gui) { - display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); - display_obj.tft.println("Connected"); - display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - #endif - - if (device_type == IS_AIRTAG) { - #ifdef HAS_SCREEN - if (gui) - display_obj.tft.println("Type: Airtag"); - #endif - send_success = this->sendAirtagSoundCommand(nimbleClient); - if (send_success) { - #ifdef HAS_SCREEN - if (gui) { - display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); - display_obj.tft.println("Command sent"); - display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - #endif - } else { - #ifdef HAS_SCREEN - if (gui) { - display_obj.tft.setTextColor(TFT_RED, TFT_BLACK); - display_obj.tft.println("Failed to send"); - display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - #endif - } - } - else if (device_type == IS_FMNA) { - #ifdef HAS_SCREEN - if (gui) - display_obj.tft.println("Type: FMNA"); - #endif - send_success = this->sendFmnaSoundCommand(nimbleClient); - if (send_success) { - #ifdef HAS_SCREEN - if (gui) { - display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); - display_obj.tft.println("Command sent"); - display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - #endif - } else { - #ifdef HAS_SCREEN - if (gui) { - display_obj.tft.setTextColor(TFT_RED, TFT_BLACK); - display_obj.tft.println("Failed to send"); - display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - #endif - } - } - else { - #ifdef HAS_SCREEN - if (gui) - display_obj.tft.println("Type: DULT"); - #endif - send_success = this->sendDultSoundCommand(nimbleClient); - if (send_success) { - #ifdef HAS_SCREEN - if (gui) { - display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); - display_obj.tft.println("Command sent"); - display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - #endif - } else { - #ifdef HAS_SCREEN - if (gui) { - display_obj.tft.setTextColor(TFT_RED, TFT_BLACK); - display_obj.tft.println("Failed to send"); - display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - #endif - } - } - } else { - #ifdef HAS_SCREEN - if (gui) { - display_obj.tft.setTextColor(TFT_RED, TFT_BLACK); - display_obj.tft.println("Failed to connect"); - display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - } - #endif + if (!this->backendFindMySound(airtag.device_address, gui)) { + airtag.connectable = false; + airtags->set(i, airtag); } + + break; } } - if (nimbleClient != nullptr) { - if (nimbleClient->isConnected()) { - Serial.println("Disconnecting locally..."); - - nimbleClient->disconnect(); - } - - NimBLEDevice::deleteClient(nimbleClient); - nimbleClient = nullptr; - } - - NimBLEDevice::deinit(true); - return send_success; } + +void WiFiScan::executeFindMyLive(uint32_t current_time) { + if (connectionPending && !operationInProgress) { + this->shutdownBLE(); + operationInProgress = true; + connectionPending = false; + + NimBLEAddress address = pendingAddress; + + this->setLEDMode(MODE_ATTACK); + + this->backendFindMySound(address); + + operationInProgress = false; + + this->initializeFindMyScan(); + } + + if (!connectionPending && !operationInProgress && !this->ble_initialized) + this->initializeFindMyScan(); +} + +void WiFiScan::initializeFindMyScan() { + NimBLEDevice::init(""); + pBLEScan = NimBLEDevice::getScan(); + + #ifndef HAS_NIMBLE_2 + pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); + #else + pBLEScan->setScanCallbacks(new bluetoothScanAllCallback(), true); + #endif + + pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster + pBLEScan->setInterval(50); + pBLEScan->setWindow(30); // less or equal setInterval value + pBLEScan->setMaxResults(0); + pBLEScan->setDuplicateFilter(false); + pBLEScan->start(0, scanCompleteCB, false); + this->setLEDMode(MODE_SNIFF); + this->ble_initialized = true; + Serial.println("Initialized NimBLEDevice scan"); +} #endif void WiFiScan::executeBLESpam(EBLEPayloadType type) { @@ -6049,6 +6219,24 @@ void WiFiScan::RunProbeScan(uint8_t scan_mode, uint16_t color) { initTime = millis(); } +void WiFiScan::RunFindMyLive(uint8_t scan_mode, uint16_t color) { + #ifdef HAS_BT + #ifdef HAS_SCREEN + this->setupScanDisplayArea(TFT_BLACK, color); + #ifdef HAS_FULL_SCREEN + display_obj.tft.fillRect(0,16,TFT_WIDTH,16, color); + display_obj.tft.drawCentreString("Find My Live",TFT_WIDTH / 2,16,2); + #endif + #ifdef HAS_ILI9341 + display_obj.touchToExit(); + #endif + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + #endif + + this->setLEDMode(MODE_ATTACK); + #endif +} + void WiFiScan::RunSourApple(uint8_t scan_mode, uint16_t color) { #ifdef HAS_BT NimBLEDevice::init(""); @@ -11419,6 +11607,11 @@ void WiFiScan::main(uint32_t currentTime) } this->packetRateLoop(currentTime); } + else if (currentScanMode == BT_ATTACK_FINDMY_LIVE) { + #ifdef HAS_NIMBLE_2 + this->executeFindMyLive(currentTime); + #endif + } else if ((currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) || (currentScanMode == BT_ATTACK_SOUR_APPLE) || (currentScanMode == BT_ATTACK_APPLE_JUICE) || diff --git a/esp32_marauder/WiFiScan.h b/esp32_marauder/WiFiScan.h index 5b4fffe..fde38fa 100644 --- a/esp32_marauder/WiFiScan.h +++ b/esp32_marauder/WiFiScan.h @@ -165,6 +165,7 @@ #define WIFI_SCAN_DISPLAY_AP_INFO 83 #define BT_SCAN_FOX_HUNT 84 #define BT_FINDMY_SOUND 85 +#define BT_ATTACK_FINDMY_LIVE 86 #define WIFI_ATTACK_FUNNY_BEACON 99 @@ -300,6 +301,14 @@ static const uint8_t DULT_START_SOUND_COMMAND[] = { static const uint8_t DULT_STOP_SOUND_COMMAND[] = { 0x01, 0x03 }; + +static NimBLEAddress pendingAddress( + "00:00:00:00:00:00", + BLE_ADDR_PUBLIC +); + +bool connectionPending = false; +bool operationInProgress = false; #endif #pragma pack(push, 1) @@ -325,9 +334,10 @@ struct AirTag { bool selected; int8_t rssi; uint32_t last_seen; - bool is_airtag = false; - bool is_fmna = false; - bool is_dult = false; + bool is_airtag = false; + bool is_fmna = false; + bool is_dult = false; + bool connectable = true; #ifdef HAS_BT NimBLEAddress device_address; #endif @@ -668,11 +678,13 @@ class WiFiScan #ifdef HAS_NIMBLE_2 int connectAndProcessTracker(NimBLEAddress& address); + bool backendFindMySound(NimBLEAddress& address, bool gui = false); bool sendAirtagSoundCommand(NimBLEClient* currentClient); bool sendFmnaSoundCommand(NimBLEClient* currentClient); bool sendDultSoundCommand(NimBLEClient* currentClient); bool enableTrackerResponses(NimBLERemoteCharacteristic* characteristic); void createNimbleClient(); + void initializeFindMyScan(); #endif bool wigleUpload(String filePath); @@ -737,6 +749,7 @@ class WiFiScan void broadcastCustomBeacon(uint32_t current_time, ssid custom_ssid, bool for_camera = false); void broadcastCustomBeacon(uint32_t current_time, AccessPoint custom_ssid, int scan_mode); void broadcastSetSSID(uint32_t current_time, const char* ESSID, uint8_t chan = 0, bool legit = false); + void executeFindMyLive(uint32_t current_time); void RunAPScan(uint8_t scan_mode, uint16_t color); void RunGPSNmea(); void RunPwnScan(uint8_t scan_mode, uint16_t color); @@ -751,6 +764,7 @@ class WiFiScan void RunPacketMonitor(uint8_t scan_mode, uint16_t color); void RunBluetoothScan(uint8_t scan_mode, uint16_t color); void RunSourApple(uint8_t scan_mode, uint16_t color); + void RunFindMyLive(uint8_t scan_mode, uint16_t color); void RunSwiftpairSpam(uint8_t scan_mode, uint16_t color); void RunEvilPortal(uint8_t scan_mode, uint16_t color); void RunPingScan(uint8_t scan_mode, uint16_t color);