| 1841 | } |
| 1842 | |
| 1843 | bool HIDDuckyService::executeDuckyScript(NimBLEAddress target) { |
| 1844 | AutoCleanup cleanup([]() { BLEStateManager::deinitBLE(true); }); |
| 1845 | |
| 1846 | if (!duckyEngine.isLoaded()) return false; |
| 1847 | |
| 1848 | String connectionMethod = ""; |
| 1849 | NimBLEClient *pClient = attemptConnectionWithStrategies(target, connectionMethod); |
| 1850 | if (!pClient) { |
| 1851 | showAttackResult(false, "Failed to connect"); |
| 1852 | return false; |
| 1853 | } |
| 1854 | |
| 1855 | BLEStateManager::registerClient(pClient); |
| 1856 | showAttackProgress("Connected! Finding HID service...", TFT_GREEN); |
| 1857 | |
| 1858 | NimBLERemoteService *pHIDService = pClient->getService(NimBLEUUID((uint16_t)0x1812)); |
| 1859 | if (!pHIDService) { |
| 1860 | showAttackResult(false, "No HID service found"); |
| 1861 | pClient->disconnect(); |
| 1862 | BLEStateManager::unregisterClient(pClient); |
| 1863 | NimBLEDevice::deleteClient(pClient); |
| 1864 | return false; |
| 1865 | } |
| 1866 | |
| 1867 | NimBLERemoteCharacteristic *pReportChar = nullptr; |
| 1868 | const std::vector<NimBLERemoteCharacteristic *> &chars = pHIDService->getCharacteristics(true); |
| 1869 | for (auto &ch : chars) { |
| 1870 | std::string uuidStr = ch->getUUID().toString(); |
| 1871 | if ((uuidStr.find("2a4d") != std::string::npos || uuidStr.find("2a22") != std::string::npos || |
| 1872 | uuidStr.find("2a32") != std::string::npos) && |
| 1873 | ch->canWrite()) { |
| 1874 | pReportChar = ch; |
| 1875 | break; |
| 1876 | } |
| 1877 | } |
| 1878 | |
| 1879 | if (!pReportChar) { |
| 1880 | showAttackResult(false, "No writable HID characteristic"); |
| 1881 | pClient->disconnect(); |
| 1882 | BLEStateManager::unregisterClient(pClient); |
| 1883 | NimBLEDevice::deleteClient(pClient); |
| 1884 | return false; |
| 1885 | } |
| 1886 | |
| 1887 | showAttackProgress("Executing Ducky Script...", TFT_BLUE); |
| 1888 | std::vector<DuckyCommand> commands = duckyEngine.getCommands(); |
| 1889 | bool success = true; |
| 1890 | int currentDelay = defaultDelay; |
| 1891 | |
| 1892 | for (size_t i = 0; i < commands.size(); i++) { |
| 1893 | DuckyCommand cmd = commands[i]; |
| 1894 | if (i % 5 == 0) |
| 1895 | showAttackProgress( |
| 1896 | String("Executing command " + String(i + 1) + "/" + String(commands.size())).c_str(), TFT_BLUE |
| 1897 | ); |
| 1898 | |
| 1899 | if (cmd.command == "DELAY") delay(cmd.delay_ms); |
| 1900 | else if (cmd.command == "DEFAULT_DELAY") currentDelay = cmd.delay_ms; |
nothing calls this directly
no test coverage detected