diff --git a/data/web/index.html b/data/web/index.html index b587b2d..f47f79d 100644 --- a/data/web/index.html +++ b/data/web/index.html @@ -279,6 +279,8 @@ + +
@@ -386,6 +388,9 @@
+ + + @@ -447,6 +452,7 @@ const attackSelector = document.getElementById('attack-selector'); const startAttackBtn = document.getElementById('start-attack-btn'); const stopAttackBtn = document.getElementById('stop-attack-btn'); + const autostartAttack = document.getElementById('autostart-attack'); const sendMessageBtn = document.getElementById('send-message-btn'); const applyConfigBtn = document.getElementById('apply-config-btn'); const saveWifiBtn = document.getElementById('save-wifi-btn'); @@ -492,6 +498,7 @@ case 'status_update': const attackName = data.current_attack || 'none'; statusValue.textContent = data.current_attack || 'Idle'; + autostartAttack.checked = data.autostart_attack || false; if (attackSelector.value !== attackName) { attackSelector.value = attackName; attackSelector.dispatchEvent(new Event('change')); @@ -618,6 +625,7 @@ command.params.interval = parseInt(document.getElementById('attack-interval').value, 10); command.params.mqtt = document.getElementById('attack-mqtt').checked ? 1 : 0; + command.params.autostart = document.getElementById('autostart-attack').checked ? 1 : 0; if (attack === 'node_flood') { command.params.min_lat = parseFloat(document.getElementById('flood-min-lat').value); diff --git a/main/main.cpp b/main/main.cpp index 5b631a2..f4d4bef 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -43,7 +43,7 @@ LoraConfig lora_config = { }; // default LoRa configuration for EU LONGFAST 433 uint8_t default_chanhash = 8; MtCompact mtCompact; - +void load_attack(); void initialize_mdns(void) { esp_err_t err = mdns_init(); if (err) { @@ -185,7 +185,7 @@ void app_main(void) { MtCompactHelpers::GeneratePrivateKey(*mtCompact.getMyNodeInfo()); uint32_t timer = 0; // 0.1 second timer // tmAttack.setAttackType(AttackType::DDOS); - + load_attack(); while (1) { timer++; tmAttack.loop(); @@ -205,6 +205,38 @@ uint32_t getNodeIdFromCh(const char* source_id) { return srcnode; } +void save_attack_stopped() { + nvs_handle_t handle; + esp_err_t err = nvs_open("attack_cfg", NVS_READWRITE, &handle); + if (err != ESP_OK) return; + nvs_set_str(handle, "attack_type", ""); + nvs_commit(handle); + nvs_close(handle); +} + +void save_attack(const char* attack_type, JSON_Object* params) { + ESP_LOGI("WEB", "Saving attack configuration: %s", attack_type); + bool autostart = json_object_get_number(params, "autostart") == 1; + nvs_handle_t handle; + esp_err_t err = nvs_open("attack_cfg", NVS_READWRITE, &handle); + if (err != ESP_OK) return; + nvs_set_str(handle, "attack_type", autostart ? attack_type : ""); + JSON_Value* params_value = json_object_get_wrapping_value(params); + size_t required_size = json_serialization_size(params_value); + if (required_size > 0) { + uint8_t buffer[1024]; + if (required_size <= sizeof(buffer)) { + json_serialize_to_buffer(params_value, (char*)buffer, sizeof(buffer)); + + nvs_set_blob(handle, "params", buffer, required_size); + } else { + ESP_LOGW("WEB", "JSON parameters too large to save"); + } + } + nvs_commit(handle); + nvs_close(handle); +} + void handle_start_attack(const char* attack_type, JSON_Object* params) { ESP_LOGI("WEB", "Handling 'start_attack': %s", attack_type); uint32_t ai = 10; @@ -222,6 +254,8 @@ void handle_start_attack(const char* attack_type, JSON_Object* params) { mtCompact.setPrimaryChanByHash(chanhash); ESP_LOGI("WEB", "Attack channel set to hash %d", chanhash); + + save_attack(attack_type, params); } if (strcmp(attack_type, "pos_poison") == 0 && params != NULL) { double min_lat = json_object_get_number(params, "min_lat"); @@ -300,6 +334,34 @@ void handle_start_attack(const char* attack_type, JSON_Object* params) { } } +void load_attack() { + nvs_handle_t handle; + esp_err_t err = nvs_open("attack_cfg", NVS_READONLY, &handle); + if (err != ESP_OK) return; + char tmpstr[64] = {0}; + size_t tmpstrlen = sizeof(tmpstr); + err = nvs_get_str(handle, "attack_type", tmpstr, &tmpstrlen); + if (err != ESP_OK || tmpstrlen <= 2) { + nvs_close(handle); + return; + } + uint8_t blob[1024] = {0}; + size_t blob_size = sizeof(blob); + err = nvs_get_blob(handle, "params", blob, &blob_size); + if (err != ESP_OK || blob_size == 0) { + nvs_close(handle); + return; + } + JSON_Value* root_value = json_parse_string((const char*)blob); + if (root_value == NULL) { + nvs_close(handle); + return; + } + handle_start_attack(tmpstr, json_value_get_object(root_value)); + json_value_free(root_value); + nvs_close(handle); +} + void handle_set_config(JSON_Object* params) { ESP_LOGI("WEB", "Handling 'set_config'"); double frequency = json_object_get_number(params, "frequency"); @@ -329,6 +391,7 @@ void handle_stop_attack() { tmAttack.setAttackType(AttackType::NONE); ESP_LOGI("WEB", "Handling 'stop_attack'"); std::string wsmsg = "{\"type\":\"status_update\"}"; + save_attack_stopped(); ws_sendall((uint8_t*)wsmsg.c_str(), wsmsg.length(), true); } diff --git a/sdkconfig.defaults b/sdkconfig.defaults index f5d79eb..468adda 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -8,3 +8,9 @@ CONFIG_HTTPD_MAX_URI_LEN=1024 CONFIG_HTTPD_WS_SUPPORT=y CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 CONFIG_LWIP_MAX_SOCKETS=15 +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp_large.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y \ No newline at end of file