Added WiFi jammer

This commit is contained in:
W0rthlessS0ul
2025-06-16 19:01:49 +03:00
parent b5322d57d7
commit d4fa97039f
+191 -72
View File
@@ -20,13 +20,13 @@
#define TAG "jammer"
#define MARGIN_LEFT 5
#define MARGIN_TOP 5
#define MARGIN_BOT 5
#define MARGIN_LEFT 5
#define MARGIN_TOP 5
#define MARGIN_BOT 5
#define MARGIN_RIGHT 5
#define KEY_WIDTH 5
#define KEY_HEIGHT 10
#define KEY_PADDING 2
#define KEY_WIDTH 5
#define KEY_HEIGHT 10
#define KEY_PADDING 2
typedef struct {
FuriMutex* mutex;
@@ -34,7 +34,8 @@ typedef struct {
bool is_nrf24_connected;
bool close_thread_please;
bool select_file_on_next_render;
uint8_t jam_type; // 0:narrow, 1:wide, 2:all, 3:custom
uint8_t wifi_channel;
uint8_t jam_type; // 0:narrow, 1:wide, 2:all, 3:WiFi, 4:custom
FuriThread* jam_thread;
} PluginState;
@@ -50,51 +51,52 @@ typedef struct {
// various types of hopping I empirically found
uint8_t hopping_channels_2[128];
uint8_t hopping_channels_1[] = {32,34, 46,48, 50, 52, 0, 1, 2, 4, 6, 8, 22, 24, 26, 28, 30, 74, 76, 78, 80, 82, 84,86 };
uint8_t hopping_channels_1[] = {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, 8,
22, 24, 26, 28, 30, 74, 76, 78, 80, 82, 84, 86};
uint8_t hopping_channels_0[] = {2, 26, 80};
uint8_t hopping_channels_len[] = {3, 24, 42, 0};
uint8_t hopping_channels_3[] = {12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72};
uint8_t hopping_channels_len[] = {3, 24, 42, 12, 0};
int parse_custom_list(char *input, uint8_t **out_arr) {
int parse_custom_list(char* input, uint8_t** out_arr) {
// Make a copy of the input string, because strtok modifies it
char *temp = strdup(input);
if (!temp) {
char* temp = strdup(input);
if(!temp) {
*out_arr = NULL;
return 0;
}
// First pass: count how many integers we have (commas + 1)
int count = 0;
for (int i = 0; temp[i] != '\0'; i++) {
if (temp[i] == ',') {
for(int i = 0; temp[i] != '\0'; i++) {
if(temp[i] == ',') {
count++;
}
}
count++; // one more than number of commas
count++; // one more than number of commas
// Allocate the array
*out_arr = (uint8_t *)malloc(count * sizeof(uint8_t));
if (!(*out_arr)) {
*out_arr = (uint8_t*)malloc(count * sizeof(uint8_t));
if(!(*out_arr)) {
free(temp);
return 0; // allocation failed
}
// Second pass: tokenize and parse
int index = 0;
char *token = strtok(temp, ",");
while (token != NULL) {
(*out_arr)[index++] = (uint8_t) atoi(token);
char* token = strtok(temp, ",");
while(token != NULL) {
(*out_arr)[index++] = (uint8_t)atoi(token);
token = strtok(NULL, ",");
}
free(temp);
return count; // number of integers parsed
return count; // number of integers parsed
}
char *jam_types[] = {"narrow", "wide", "full", "custom"};
uint8_t *hopping_channels;
char* jam_types[] = {"narrow", "wide", "full", "WiFi", "custom"};
uint8_t* hopping_channels;
int hopping_channels_custom_len = 0;
uint8_t *hopping_channels_custom_arr = NULL;
uint8_t* hopping_channels_custom_arr = NULL;
static void render_callback(Canvas* const canvas, void* ctx) {
furi_assert(ctx);
@@ -107,27 +109,35 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas_set_font(canvas, FontSecondary);
char tmp[128];
snprintf(tmp, 128, "^ type:%s", jam_types[plugin_state->jam_type]);
if(plugin_state->jam_type == 3)
snprintf(
tmp,
128,
"^ type:%s > channel:%d",
jam_types[plugin_state->jam_type],
plugin_state->wifi_channel + 1);
else
snprintf(tmp, 128, "^ type:%s", jam_types[plugin_state->jam_type]);
canvas_draw_str_aligned(canvas, 10, 3, AlignLeft, AlignTop, tmp);
if(!plugin_state->is_thread_running && plugin_state->jam_type <= 3) {
if(!plugin_state->is_thread_running && plugin_state->jam_type <= 4) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 10, 20, AlignLeft, AlignBottom, "Press Ok button to start");
if (plugin_state->jam_type == 3) {
canvas_draw_str(canvas, 80, 30, "select file >");
canvas_draw_str_aligned(
canvas, 10, 20, AlignLeft, AlignBottom, "Press Ok button to start");
if(plugin_state->jam_type == 4) {
canvas_draw_str(canvas, 80, 30, "select file >");
}
if(!plugin_state->is_nrf24_connected) {
canvas_draw_str_aligned(
canvas, 10, 30, AlignLeft, AlignBottom, "Connect NRF24 to GPIO!");
}
} else if(plugin_state->is_thread_running && plugin_state->jam_type <= 3) {
} else if(plugin_state->is_thread_running && plugin_state->jam_type <= 4) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "Causing mayhem...");
canvas_draw_str_aligned(canvas, 3, 40, AlignLeft, AlignBottom, "Please wait!");
canvas_draw_str_aligned(
canvas, 3, 50, AlignLeft, AlignBottom, "Press back to exit.");
canvas_draw_str_aligned(canvas, 3, 50, AlignLeft, AlignBottom, "Press back to exit.");
} else {
canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Unknown Error");
canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "press back");
@@ -135,9 +145,9 @@ static void render_callback(Canvas* const canvas, void* ctx) {
}
uint8_t limit = hopping_channels_len[plugin_state->jam_type];
canvas_draw_frame(canvas, 0, 52, 128, 13);
if (limit > 0) {
if(limit > 0) {
for(int i = 0; i < limit; i++) {
canvas_draw_line(canvas, hopping_channels[i]+1, 53, hopping_channels[i]+1, 64);
canvas_draw_line(canvas, hopping_channels[i] + 1, 53, hopping_channels[i] + 1, 64);
}
}
//furi_mutex_release(plugin_state->mutex);
@@ -158,24 +168,71 @@ static void jammer_state_init(PluginState* const plugin_state) {
static int32_t mj_worker_thread(void* ctx) {
PluginState* plugin_state = ctx;
plugin_state->is_thread_running = true;
#define size 32
uint8_t tx[size + 1] = {0};
FURI_LOG_D(TAG, "Starting optimized carrier jamming");
if(plugin_state->jam_type == 3) {
char tmp[128];
nrf24_set_idle(nrf24_HANDLE);
uint8_t mac[] = {0xDE, 0xAD}; // DEAD BEEF FEED
uint8_t ping_packet[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE,
0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD,
0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF};
nrf24_configure(nrf24_HANDLE, 2, mac, mac, 2, 1, true, true);
uint8_t setup;
nrf24_read_reg(nrf24_HANDLE, REG_RF_SETUP, &setup, 1);
setup = (setup & 0xF8) | 7;
nrf24_write_reg(nrf24_HANDLE, REG_RF_SETUP, setup);
uint8_t conf;
nrf24_read_reg(nrf24_HANDLE, REG_CONFIG, &conf, 1);
snprintf(tmp, sizeof(tmp), "NRF24 SETUP REGISTER: %d", setup);
FURI_LOG_D(TAG, tmp);
snprintf(tmp, sizeof(tmp), "NRF24 CONFIG REGISTER: %d", conf);
FURI_LOG_D(TAG, tmp);
tx[0] = W_TX_PAYLOAD_NOACK;
memcpy(&tx[1], ping_packet, size);
#define nrf24_TIMEOUT 500
nrf24_spi_trx(nrf24_HANDLE, tx, 0, size + 1, nrf24_TIMEOUT);
nrf24_set_tx_mode(nrf24_HANDLE);
}
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
notification_message(notification, &sequence_blink_red_100);
nrf24_startConstCarrier(nrf24_HANDLE, 3, hopping_channels[0]);
if(plugin_state->jam_type != 3) nrf24_startConstCarrier(nrf24_HANDLE, 3, hopping_channels[0]);
uint8_t current_channel = 0;
uint8_t limit = hopping_channels_len[plugin_state->jam_type];
while(!plugin_state->close_thread_please) {
for(int ch = 0; ch < limit && !plugin_state->close_thread_please; ch++) {
current_channel = hopping_channels[ch];
nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, current_channel);
if(plugin_state->jam_type == 3) {
for(int wifi_ch = hopping_channels_3[plugin_state->wifi_channel];
wifi_ch < hopping_channels_3[plugin_state->wifi_channel + 6] &&
!plugin_state->close_thread_please;
wifi_ch++) {
nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, wifi_ch);
nrf24_spi_trx(nrf24_HANDLE, tx, 0, 3, nrf24_TIMEOUT);
}
} else
nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, current_channel);
}
}
nrf24_stopConstCarrier(nrf24_HANDLE);
if(plugin_state->jam_type != 3) nrf24_stopConstCarrier(nrf24_HANDLE);
furi_record_close(RECORD_NOTIFICATION);
plugin_state->is_thread_running = false;
return 0;
@@ -189,6 +246,7 @@ int32_t jammer_app(void* p) {
PluginState* plugin_state = malloc(sizeof(PluginState));
jammer_state_init(plugin_state);
plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
plugin_state->wifi_channel = 0;
if(!plugin_state->mutex) {
FURI_LOG_E("jammer", "cannot create mutex\r\n");
furi_message_queue_free(event_queue);
@@ -216,7 +274,8 @@ int32_t jammer_app(void* p) {
nrf24_init();
FURI_LOG_D(TAG, "nrf24 init done!");
PluginEvent event;
for(int i = 0; i < 128; i++) hopping_channels_2[i] = i*2;
for(int i = 0; i < 128; i++)
hopping_channels_2[i] = i * 2;
hopping_channels = hopping_channels_0;
plugin_state->is_nrf24_connected = true;
if(!nrf24_check_connected(nrf24_HANDLE)) {
@@ -225,7 +284,6 @@ int32_t jammer_app(void* p) {
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
if(event_status == FuriStatusOk) {
// press events
if(event.type == EventTypeKey) {
@@ -234,24 +292,60 @@ int32_t jammer_app(void* p) {
switch(event.input.key) {
case InputKeyUp:
if(!plugin_state -> is_thread_running) {
plugin_state->jam_type = (plugin_state->jam_type + 1) % 4;
if(!plugin_state->is_thread_running) {
plugin_state->jam_type = (plugin_state->jam_type + 1) % 5;
switch(plugin_state->jam_type) {
case 0: hopping_channels = hopping_channels_0; break;
case 1: hopping_channels = hopping_channels_1; break;
case 2: hopping_channels = hopping_channels_2; break;
case 3: hopping_channels = hopping_channels_custom_arr;
default: break;
case 0:
hopping_channels = hopping_channels_0;
break;
case 1:
hopping_channels = hopping_channels_1;
break;
case 2:
hopping_channels = hopping_channels_2;
break;
case 3:
hopping_channels = hopping_channels_3;
break;
case 4:
hopping_channels = hopping_channels_custom_arr;
default:
break;
}
view_port_update(view_port);
}
break;
case InputKeyDown:
if(!plugin_state->is_thread_running) {
plugin_state->jam_type =
(plugin_state->jam_type == 0) ? 4 : (plugin_state->jam_type - 1);
switch(plugin_state->jam_type) {
case 0:
hopping_channels = hopping_channels_0;
break;
case 1:
hopping_channels = hopping_channels_1;
break;
case 2:
hopping_channels = hopping_channels_2;
break;
case 3:
hopping_channels = hopping_channels_3;
break;
case 4:
hopping_channels = hopping_channels_custom_arr;
default:
break;
}
view_port_update(view_port);
}
break;
case InputKeyRight:
if(plugin_state->jam_type == 3) {
if(plugin_state->jam_type == 4 && !plugin_state->is_thread_running) {
DialogsApp* dialogs = furi_record_open("dialogs");
Storage* storage = furi_record_open(RECORD_STORAGE);
plugin_state->select_file_on_next_render = true;
@@ -261,15 +355,24 @@ int32_t jammer_app(void* p) {
path = furi_string_alloc();
furi_string_set(path, "/ext/");
DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(&browser_options, ".txt", &I_badusb_10px);
dialog_file_browser_set_basic_options(
&browser_options, ".txt", &I_badusb_10px);
browser_options.hide_ext = false;
browser_options.base_path = "/ext/";
furi_delay_ms(1000);
bool ret = dialog_file_browser_show(dialogs, path, path, &browser_options);
bool ret =
dialog_file_browser_show(dialogs, path, path, &browser_options);
furi_record_close("dialogs");
if(ret) {
if(!file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
FURI_LOG_D(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path));
if(!file_stream_open(
file_stream,
furi_string_get_cstr(path),
FSAM_READ,
FSOM_OPEN_EXISTING)) {
FURI_LOG_D(
TAG,
"Cannot open file \"%s\"",
furi_string_get_cstr(path));
} else {
size_t file_size = 0;
size_t bytes_read = 0;
@@ -281,11 +384,18 @@ int32_t jammer_app(void* p) {
bytes_read = stream_read(file_stream, file_buf, file_size);
if(bytes_read == file_size) {
FURI_LOG_I(TAG, "read file");
hopping_channels_custom_len = parse_custom_list((char *)file_buf, &hopping_channels_custom_arr);
hopping_channels_custom_len = parse_custom_list(
(char*)file_buf, &hopping_channels_custom_arr);
FURI_LOG_D(TAG, "Length: %d\n", hopping_channels_custom_len); // e.g. 6
for (int i = 0; i < hopping_channels_custom_len; i++) {
FURI_LOG_D(TAG, "%d ", hopping_channels_custom_arr[i]); // 1 2 3 4 1 2
FURI_LOG_D(
TAG,
"Length: %d\n",
hopping_channels_custom_len); // e.g. 6
for(int i = 0; i < hopping_channels_custom_len; i++) {
FURI_LOG_D(
TAG,
"%d ",
hopping_channels_custom_arr[i]); // 1 2 3 4 1 2
}
hopping_channels_len[3] = hopping_channels_custom_len;
hopping_channels = hopping_channels_custom_arr;
@@ -298,15 +408,25 @@ int32_t jammer_app(void* p) {
}
}
furi_string_free(path);
view_port_update(view_port);
} else if(plugin_state->jam_type == 3 && !plugin_state->is_thread_running) {
plugin_state->wifi_channel = (plugin_state->wifi_channel + 1) % 13;
view_port_update(view_port);
}
break;
case InputKeyLeft:
if(plugin_state->jam_type == 3 && !plugin_state->is_thread_running) {
plugin_state->wifi_channel = (plugin_state->wifi_channel == 0) ?
12 :
(plugin_state->wifi_channel - 1);
view_port_update(view_port);
}
break;
case InputKeyOk:
if(!plugin_state->is_thread_running) {
if(!nrf24_check_connected(nrf24_HANDLE)) {
if(!nrf24_check_connected(nrf24_HANDLE) ||
!plugin_state->is_nrf24_connected) {
plugin_state->is_nrf24_connected = false;
notification_message(notification, &sequence_error);
} else {
@@ -314,30 +434,29 @@ int32_t jammer_app(void* p) {
}
view_port_update(view_port);
}
break;
case InputKeyBack:
FURI_LOG_D(TAG, "terminating thread...");
if(!plugin_state->is_thread_running) processing = false;
plugin_state->close_thread_please = true;
if(plugin_state->is_thread_running && plugin_state->jam_thread) {
plugin_state->is_thread_running = false;
furi_thread_join(plugin_state->jam_thread); // wait until thread is finished
furi_thread_join(
plugin_state->jam_thread); // wait until thread is finished
view_port_update(view_port);
}
plugin_state->close_thread_please = false;
break;
default:
break;
}
//view_port_update(view_port);
//view_port_update(view_port);
}
}
}