Merge branch 'mpu' into dev

This commit is contained in:
MX 2022-09-11 03:44:11 +03:00
commit 9dc337a02c
No known key found for this signature in database
GPG key ID: 6C4C311DFD4B4AB5
23 changed files with 410 additions and 137 deletions

View file

@ -5,6 +5,6 @@ App(
entry_point="arkanoid_game_app",
cdefines=["APP_ARKANOID_GAME"],
requires=["gui"],
stack_size=4 * 1024,
stack_size=1 * 1024,
order=30,
)

View file

@ -6,5 +6,5 @@ App(
cdefines=["APP_FLIP_FRID"],
requires=["gui"],
stack_size=1 * 1024,
order=13,
order=15,
)

View file

@ -9,7 +9,6 @@
#include <furi_hal_interrupt.h>
#include <furi_hal_resources.h>
#include <nrf24.h>
#include <toolbox/stream/file_stream.h>
#include "mousejacker_ducky.h"
#define TAG "mousejacker"
@ -31,14 +30,8 @@ typedef struct {
InputEvent input;
} PluginEvent;
typedef struct {
int x;
int y;
bool ducky_err;
bool addr_err;
} PluginState;
uint8_t addrs_count = 0;
uint8_t addr_idx = 0;
uint8_t loaded_addrs[MAX_ADDRS][6]; // first byte is rate, the rest are the address
char target_fmt_text[] = "Target addr: %s";
@ -54,7 +47,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_frame(canvas, 0, 0, 128, 64);
canvas_set_font(canvas, FontSecondary);
if(!plugin_state->addr_err && !plugin_state->ducky_err) {
if(!plugin_state->addr_err && !plugin_state->ducky_err && !plugin_state->is_thread_running) {
snprintf(target_text, sizeof(target_text), target_fmt_text, target_address_str);
canvas_draw_str_aligned(canvas, 7, 10, AlignLeft, AlignBottom, target_text);
canvas_draw_str_aligned(canvas, 22, 20, AlignLeft, AlignBottom, "<- select address ->");
@ -70,9 +63,17 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas, 7, 40, AlignLeft, AlignBottom, "Run (NRF24: Sniff) app first!");
} else if(plugin_state->ducky_err) {
canvas_draw_str_aligned(
canvas, 10, 10, AlignLeft, AlignBottom, "Error: No mousejacker folder");
canvas_draw_str_aligned(canvas, 10, 20, AlignLeft, AlignBottom, "or duckyscript file");
canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, "loading error");
canvas, 3, 10, AlignLeft, AlignBottom, "Error: No mousejacker folder");
canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "or duckyscript file");
canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "loading error");
} else if(plugin_state->is_thread_running) {
canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Running duckyscript");
canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "press back");
canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "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");
canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "to exit");
}
release_mutex((ValueMutex*)ctx, plugin_state);
@ -86,8 +87,7 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu
}
static void mousejacker_state_init(PluginState* const plugin_state) {
plugin_state->x = 50;
plugin_state->y = 30;
plugin_state->is_thread_running = false;
}
static void hexlify(uint8_t* in, uint8_t size, char* out) {
@ -108,7 +108,7 @@ static bool open_ducky_script(Stream* stream) {
furi_record_close("dialogs");
if(ret) {
if(!file_stream_open(stream, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
FURI_LOG_I(TAG, "Cannot open file \"%s\"", (path));
FURI_LOG_D(TAG, "Cannot open file \"%s\"", (path));
} else {
result = true;
}
@ -129,7 +129,7 @@ static bool open_addrs_file(Stream* stream) {
furi_record_close("dialogs");
if(ret) {
if(!file_stream_open(stream, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
FURI_LOG_I(TAG, "Cannot open file \"%s\"", (path));
FURI_LOG_D(TAG, "Cannot open file \"%s\"", (path));
} else {
result = true;
}
@ -138,29 +138,34 @@ static bool open_addrs_file(Stream* stream) {
return result;
}
static bool
process_ducky_file(Stream* file_stream, uint8_t* addr, uint8_t addr_size, uint8_t rate) {
static bool process_ducky_file(
Stream* file_stream,
uint8_t* addr,
uint8_t addr_size,
uint8_t rate,
PluginState* plugin_state) {
size_t file_size = 0;
size_t bytes_read = 0;
uint8_t* file_buf;
bool loaded = false;
FURI_LOG_I(TAG, "opening ducky script");
FURI_LOG_D(TAG, "opening ducky script");
if(open_ducky_script(file_stream)) {
file_size = stream_size(file_stream);
if(file_size == (size_t)0) {
FURI_LOG_I(TAG, "load failed. file_size: %d", file_size);
FURI_LOG_D(TAG, "load failed. file_size: %d", file_size);
return loaded;
}
file_buf = malloc(file_size);
memset(file_buf, 0, file_size);
bytes_read = stream_read(file_stream, file_buf, file_size);
if(bytes_read == file_size) {
FURI_LOG_I(TAG, "executing ducky script");
mj_process_ducky_script(nrf24_HANDLE, addr, addr_size, rate, (char*)file_buf);
FURI_LOG_I(TAG, "finished execution");
FURI_LOG_D(TAG, "executing ducky script");
mj_process_ducky_script(
nrf24_HANDLE, addr, addr_size, rate, (char*)file_buf, plugin_state);
FURI_LOG_D(TAG, "finished execution");
loaded = true;
} else {
FURI_LOG_I(TAG, "load failed. file size: %d", file_size);
FURI_LOG_D(TAG, "load failed. file size: %d", file_size);
}
free(file_buf);
}
@ -179,19 +184,19 @@ static bool load_addrs_file(Stream* file_stream) {
uint32_t i_addr_lo = 0;
uint32_t i_addr_hi = 0;
bool loaded = false;
FURI_LOG_I(TAG, "opening addrs file");
FURI_LOG_D(TAG, "opening addrs file");
addrs_count = 0;
if(open_addrs_file(file_stream)) {
file_size = stream_size(file_stream);
if(file_size == (size_t)0) {
FURI_LOG_I(TAG, "load failed. file_size: %d", file_size);
FURI_LOG_D(TAG, "load failed. file_size: %d", file_size);
return loaded;
}
file_buf = malloc(file_size);
memset(file_buf, 0, file_size);
bytes_read = stream_read(file_stream, file_buf, file_size);
if(bytes_read == file_size) {
FURI_LOG_I(TAG, "loading addrs file");
FURI_LOG_D(TAG, "loading addrs file");
char* line = strtok((char*)file_buf, "\n");
while(line != NULL) {
@ -211,17 +216,54 @@ static bool load_addrs_file(Stream* file_stream) {
loaded = true;
}
} else {
FURI_LOG_I(TAG, "load failed. file size: %d", file_size);
FURI_LOG_D(TAG, "load failed. file size: %d", file_size);
}
free(file_buf);
}
return loaded;
}
// entrypoint for worker
static int32_t mj_worker_thread(void* ctx) {
PluginState* plugin_state = ctx;
bool ducky_ok = false;
if(!plugin_state->addr_err) {
plugin_state->is_thread_running = true;
plugin_state->file_stream = file_stream_alloc(plugin_state->storage);
nrf24_find_channel(
nrf24_HANDLE,
loaded_addrs[addr_idx] + 1,
loaded_addrs[addr_idx] + 1,
5,
loaded_addrs[addr_idx][0],
2,
LOGITECH_MAX_CHANNEL,
true);
ducky_ok = process_ducky_file(
plugin_state->file_stream,
loaded_addrs[addr_idx] + 1,
5,
loaded_addrs[addr_idx][0],
plugin_state);
if(!ducky_ok) {
plugin_state->ducky_err = true;
} else {
plugin_state->ducky_err = false;
}
stream_free(plugin_state->file_stream);
}
plugin_state->is_thread_running = false;
return 0;
}
void start_mjthread(PluginState* plugin_state) {
if(!plugin_state->is_thread_running) {
furi_thread_start(plugin_state->mjthread);
}
}
int32_t mousejacker_app(void* p) {
UNUSED(p);
uint8_t addr_idx = 0;
bool ducky_ok = false;
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
PluginState* plugin_state = malloc(sizeof(PluginState));
@ -243,19 +285,25 @@ int32_t mousejacker_app(void* p) {
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
Storage* storage = furi_record_open(RECORD_STORAGE);
storage_common_mkdir(storage, MOUSEJACKER_APP_PATH_FOLDER);
Stream* file_stream = file_stream_alloc(storage);
plugin_state->storage = furi_record_open(RECORD_STORAGE);
storage_common_mkdir(plugin_state->storage, MOUSEJACKER_APP_PATH_FOLDER);
plugin_state->file_stream = file_stream_alloc(plugin_state->storage);
plugin_state->mjthread = furi_thread_alloc();
furi_thread_set_name(plugin_state->mjthread, "MJ Worker");
furi_thread_set_stack_size(plugin_state->mjthread, 2048);
furi_thread_set_context(plugin_state->mjthread, plugin_state);
furi_thread_set_callback(plugin_state->mjthread, mj_worker_thread);
// spawn load file dialog to choose sniffed addresses file
if(load_addrs_file(file_stream)) {
if(load_addrs_file(plugin_state->file_stream)) {
addr_idx = 0;
hexlify(&loaded_addrs[addr_idx][1], 5, target_address_str);
plugin_state->addr_err = false;
} else {
plugin_state->addr_err = true;
}
stream_free(file_stream);
stream_free(plugin_state->file_stream);
nrf24_init();
PluginEvent event;
@ -288,44 +336,31 @@ int32_t mousejacker_app(void* p) {
break;
case InputKeyOk:
if(!plugin_state->addr_err) {
file_stream = file_stream_alloc(storage);
nrf24_find_channel(
nrf24_HANDLE,
loaded_addrs[addr_idx] + 1,
loaded_addrs[addr_idx] + 1,
5,
loaded_addrs[addr_idx][0],
2,
LOGITECH_MAX_CHANNEL,
true);
ducky_ok = process_ducky_file(
file_stream,
loaded_addrs[addr_idx] + 1,
5,
loaded_addrs[addr_idx][0]);
if(!ducky_ok) {
plugin_state->ducky_err = true;
} else {
plugin_state->ducky_err = false;
if(!plugin_state->is_thread_running) {
start_mjthread(plugin_state);
view_port_update(view_port);
}
stream_free(file_stream);
}
break;
case InputKeyBack:
plugin_state->close_thread_please = true;
if(plugin_state->is_thread_running && plugin_state->mjthread) {
furi_thread_join(
plugin_state->mjthread); // wait until thread is finished
}
plugin_state->close_thread_please = false;
processing = false;
break;
}
}
}
} else {
FURI_LOG_D("mousejacker", "furi_message_queue: event timeout");
// event timeout
}
view_port_update(view_port);
release_mutex(&state_mutex, plugin_state);
}
furi_thread_free(plugin_state->mjthread);
furi_hal_spi_release(nrf24_HANDLE);
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
@ -333,6 +368,7 @@ int32_t mousejacker_app(void* p) {
furi_record_close(RECORD_STORAGE);
view_port_free(view_port);
furi_message_queue_free(event_queue);
free(plugin_state);
return 0;
}

View file

@ -87,7 +87,7 @@ static uint32_t mj_ducky_get_command_len(const char* line) {
}
static bool mj_get_ducky_key(char* key, size_t keylen, MJDuckyKey* dk) {
//FURI_LOG_I(TAG, "looking up key %s with length %d", key, keylen);
//FURI_LOG_D(TAG, "looking up key %s with length %d", key, keylen);
for(uint i = 0; i < sizeof(mj_ducky_keys) / sizeof(MJDuckyKey); i++) {
if(!strncmp(mj_ducky_keys[i].name, key, keylen)) {
memcpy(dk, &mj_ducky_keys[i], sizeof(MJDuckyKey));
@ -113,10 +113,16 @@ static void inject_packet(
uint8_t addr_size,
uint8_t rate,
uint8_t* payload,
size_t payload_size) {
size_t payload_size,
PluginState* plugin_state) {
uint8_t rt_count = 0;
while(1) {
if(nrf24_txpacket(handle, payload, payload_size, true)) break;
if(!plugin_state->is_thread_running || plugin_state->close_thread_please) {
return;
}
if(nrf24_txpacket(handle, payload, payload_size, true)) {
break;
}
rt_count++;
// retransmit threshold exceeded, scan for new channel
@ -129,8 +135,10 @@ static void inject_packet(
rate,
LOGITECH_MIN_CHANNEL,
LOGITECH_MAX_CHANNEL,
true) > LOGITECH_MAX_CHANNEL)
true) > LOGITECH_MAX_CHANNEL) {
return; // fail
}
//FURI_LOG_D("mj", "find channel passed, %d", tessst);
rt_count = 0;
}
@ -150,7 +158,8 @@ static void send_hid_packet(
uint8_t addr_size,
uint8_t rate,
uint8_t mod,
uint8_t hid) {
uint8_t hid,
PluginState* plugin_state) {
uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0};
build_hid_packet(0, 0, hid_payload);
if(hid == prev_hid)
@ -160,11 +169,13 @@ static void send_hid_packet(
addr_size,
rate,
hid_payload,
LOGITECH_HID_TEMPLATE_SIZE); // empty hid packet
LOGITECH_HID_TEMPLATE_SIZE,
plugin_state); // empty hid packet
prev_hid = hid;
build_hid_packet(mod, hid, hid_payload);
inject_packet(handle, addr, addr_size, rate, hid_payload, LOGITECH_HID_TEMPLATE_SIZE);
inject_packet(
handle, addr, addr_size, rate, hid_payload, LOGITECH_HID_TEMPLATE_SIZE, plugin_state);
furi_delay_ms(12);
}
@ -175,11 +186,15 @@ static bool mj_process_ducky_line(
uint8_t addr_size,
uint8_t rate,
char* line,
char* prev_line) {
char* prev_line,
PluginState* plugin_state) {
MJDuckyKey dk;
uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0};
char* line_tmp = line;
uint32_t line_len = strlen(line);
if(!plugin_state->is_thread_running || plugin_state->close_thread_please) {
return true;
}
for(uint32_t i = 0; i < line_len; i++) {
if((line_tmp[i] != ' ') && (line_tmp[i] != '\t') && (line_tmp[i] != '\n')) {
line_tmp = &line_tmp[i];
@ -188,7 +203,7 @@ static bool mj_process_ducky_line(
if(i == line_len - 1) return true; // Skip empty lines
}
FURI_LOG_I(TAG, "line: %s", line_tmp);
FURI_LOG_D(TAG, "line: %s", line_tmp);
// General commands
if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) {
@ -208,10 +223,20 @@ static bool mj_process_ducky_line(
addr_size,
rate,
hid_payload,
LOGITECH_HID_TEMPLATE_SIZE); // empty hid packet
LOGITECH_HID_TEMPLATE_SIZE,
plugin_state); // empty hid packet
for(uint32_t i = 0; i < delay_count; i++) {
if(!plugin_state->is_thread_running || plugin_state->close_thread_please) {
return true;
}
inject_packet(
handle, addr, addr_size, rate, LOGITECH_KEEPALIVE, LOGITECH_KEEPALIVE_SIZE);
handle,
addr,
addr_size,
rate,
LOGITECH_KEEPALIVE,
LOGITECH_KEEPALIVE_SIZE,
plugin_state);
furi_delay_ms(10);
}
return true;
@ -223,7 +248,7 @@ static bool mj_process_ducky_line(
for(size_t i = 0; i < strlen(line_tmp); i++) {
if(!mj_get_ducky_key(&line_tmp[i], 1, &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
}
return true;
@ -236,15 +261,15 @@ static bool mj_process_ducky_line(
repeat_cnt = atoi(line_tmp);
if(repeat_cnt < 2) return false;
FURI_LOG_I(TAG, "repeating %s %d times", prev_line, repeat_cnt);
FURI_LOG_D(TAG, "repeating %s %d times", prev_line, repeat_cnt);
for(uint32_t i = 0; i < repeat_cnt; i++)
mj_process_ducky_line(handle, addr, addr_size, rate, prev_line, NULL);
mj_process_ducky_line(handle, addr, addr_size, rate, prev_line, NULL, plugin_state);
return true;
} else if(strncmp(line_tmp, "ALT", strlen("ALT")) == 0) {
line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 4, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 4, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "GUI", strlen("GUI")) == 0 ||
@ -252,72 +277,72 @@ static bool mj_process_ducky_line(
strncmp(line_tmp, "COMMAND", strlen("COMMAND")) == 0) {
line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 8, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 8, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "CTRL-ALT", strlen("CTRL-ALT")) == 0 ||
strncmp(line_tmp, "CONTROL-ALT", strlen("CONTROL-ALT")) == 0) {
line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 4 | 1, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 4 | 1, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "CTRL-SHIFT", strlen("CTRL-SHIFT")) == 0 ||
strncmp(line_tmp, "CONTROL-SHIFT", strlen("CONTROL-SHIFT")) == 0) {
line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 4 | 2, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 4 | 2, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "CTRL", strlen("CTRL")) == 0 ||
strncmp(line_tmp, "CONTROL", strlen("CONTROL")) == 0) {
line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 1, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 1, dk.hid, plugin_state);
return true;
} else if(strncmp(line_tmp, "SHIFT", strlen("SHIFT")) == 0) {
line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 2, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod | 2, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "ESC", strlen("ESC")) == 0 ||
strncmp(line_tmp, "APP", strlen("APP")) == 0 ||
strncmp(line_tmp, "ESCAPE", strlen("ESCAPE")) == 0) {
if(!mj_get_ducky_key("ESCAPE", 6, &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
return true;
} else if(strncmp(line_tmp, "ENTER", strlen("ENTER")) == 0) {
if(!mj_get_ducky_key("ENTER", 5, &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "UP", strlen("UP")) == 0 ||
strncmp(line_tmp, "UPARROW", strlen("UPARROW")) == 0) {
if(!mj_get_ducky_key("UP", 2, &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "DOWN", strlen("DOWN")) == 0 ||
strncmp(line_tmp, "DOWNARROW", strlen("DOWNARROW")) == 0) {
if(!mj_get_ducky_key("DOWN", 4, &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "LEFT", strlen("LEFT")) == 0 ||
strncmp(line_tmp, "LEFTARROW", strlen("LEFTARROW")) == 0) {
if(!mj_get_ducky_key("LEFT", 4, &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
return true;
} else if(
strncmp(line_tmp, "RIGHT", strlen("RIGHT")) == 0 ||
strncmp(line_tmp, "RIGHTARROW", strlen("RIGHTARROW")) == 0) {
if(!mj_get_ducky_key("RIGHT", 5, &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
return true;
} else if(strncmp(line_tmp, "SPACE", strlen("SPACE")) == 0) {
if(!mj_get_ducky_key("SPACE", 5, &dk)) return false;
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid);
send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
return true;
}
@ -329,17 +354,19 @@ void mj_process_ducky_script(
uint8_t* addr,
uint8_t addr_size,
uint8_t rate,
char* script) {
char* script,
PluginState* plugin_state) {
uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0};
char* prev_line = NULL;
inject_packet(handle, addr, addr_size, rate, LOGITECH_HELLO, LOGITECH_HELLO_SIZE);
inject_packet(
handle, addr, addr_size, rate, LOGITECH_HELLO, LOGITECH_HELLO_SIZE, plugin_state);
char* line = strtok(script, "\n");
while(line != NULL) {
if(strcmp(&line[strlen(line) - 1], "\r") == 0) line[strlen(line) - 1] = (char)0;
if(!mj_process_ducky_line(handle, addr, addr_size, rate, line, prev_line))
FURI_LOG_I(TAG, "unable to process ducky script line: %s", line);
if(!mj_process_ducky_line(handle, addr, addr_size, rate, line, prev_line, plugin_state))
FURI_LOG_D(TAG, "unable to process ducky script line: %s", line);
prev_line = line;
line = strtok(NULL, "\n");
@ -351,5 +378,6 @@ void mj_process_ducky_script(
addr_size,
rate,
hid_payload,
LOGITECH_HID_TEMPLATE_SIZE); // empty hid packet at end
LOGITECH_HID_TEMPLATE_SIZE,
plugin_state); // empty hid packet at end
}

View file

@ -8,6 +8,7 @@
#include <nrf24.h>
#include <furi.h>
#include <furi_hal.h>
#include <toolbox/stream/file_stream.h>
#ifdef __cplusplus
extern "C" {
@ -19,12 +20,23 @@ typedef struct {
uint8_t mod;
} MJDuckyKey;
typedef struct {
bool ducky_err;
bool addr_err;
bool is_thread_running;
bool close_thread_please;
Storage* storage;
FuriThread* mjthread;
Stream* file_stream;
} PluginState;
void mj_process_ducky_script(
FuriHalSpiBusHandle* handle,
uint8_t* addr,
uint8_t addr_size,
uint8_t rate,
char* script);
char* script,
PluginState* plugin_state);
#ifdef __cplusplus
}

View file

@ -1,6 +1,6 @@
App(
appid="sub_playlist",
name=".sub Playlist",
name="Sub-GHz Playlist",
apptype=FlipperAppType.PLUGIN,
entry_point="playlist_app",
cdefines=["APP_PLAYLIST"],

View file

@ -310,6 +310,9 @@ static int32_t playlist_worker_thread(void* ctx) {
++worker->meta->current_playlist_repetition;
// send playlist
worker->meta->current_count = 0;
if(worker->ctl_request_exit) {
break;
}
FURI_LOG_D(
TAG,
@ -464,7 +467,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
canvas_draw_str_aligned(canvas, 1, 19, AlignLeft, AlignTop, string_get_cstr(temp_str));
if(app->meta->playlist_repetitions <= 0) {
string_printf(temp_str, "Repeat: yes", app->meta->playlist_repetitions);
string_printf(temp_str, "Repeat: inf", app->meta->playlist_repetitions);
} else if(app->meta->playlist_repetitions == 1) {
string_printf(temp_str, "Repeat: no", app->meta->playlist_repetitions);
} else {

View file

@ -15,6 +15,7 @@ int playlist_count_playlist_items(Storage* storage, const char* file_path) {
++count;
}
flipper_format_file_close(format);
flipper_format_free(format);
string_clear(data);
return count;
}

View file

@ -6,6 +6,6 @@ App(
cdefines=["APP_SPECTRUM_ANALYZER"],
requires=["gui"],
icon="A_SpectrumAnalyzer_14",
stack_size=4 * 1024,
stack_size=2 * 1024,
order=12,
)

View file

@ -1,6 +1,6 @@
App(
appid="subbrute",
name="SubGHz Bruteforcer",
name="Sub-GHz Bruteforcer",
apptype=FlipperAppType.PLUGIN,
entry_point="subbrute_start",
cdefines=["APP_SUB_BRUTE"],

View file

@ -162,7 +162,7 @@ void subbrute_scene_entrypoint_on_draw(Canvas* canvas, SubBruteState* context) {
// Title
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignTop, "SubGHz Fuzzer");
canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignTop, "Sub-GHz Bruteforcer");
if(context->menu_index > SubBruteAttackLoadFile) {
canvas_set_font(canvas, FontSecondary);

View file

@ -134,6 +134,7 @@ bool subbrute_load(SubBruteState* context, const char* file_path) {
string_clear(temp_str);
flipper_format_file_close(fff_data_file);
flipper_format_free(fff_data_file);
furi_record_close(RECORD_STORAGE);
if(result) {
FURI_LOG_I(TAG, "Loaded successfully");
string_reset(context->notification_msg);
@ -197,6 +198,9 @@ bool subbrute_load_protocol_from_file(SubBruteState* context) {
string_t file_path;
string_init(file_path);
string_set_str(file_path, SUBGHZ_APP_PATH_FOLDER);
context->environment = subghz_environment_alloc();
context->receiver = subghz_receiver_alloc_init(context->environment);
subghz_receiver_set_filter(context->receiver, SubGhzProtocolFlag_Decodable);
// Input events and views are managed by file_select
bool res = dialog_file_browser_show(
@ -206,6 +210,9 @@ bool subbrute_load_protocol_from_file(SubBruteState* context) {
res = subbrute_load(context, string_get_cstr(file_path));
}
subghz_environment_free(context->environment);
subghz_receiver_free(context->receiver);
string_clear(file_path);
return res;

View file

@ -2,7 +2,7 @@
#include <lib/subghz/transmitter.h>
#include <gui/elements.h>
uint64_t subbrute_counter = 0;
//uint64_t subbrute_counter = 0;
uint64_t max_value;
bool locked = false;
bool toSave = false;
@ -63,8 +63,8 @@ void prepare_emit(SubBruteState* context) {
void clear_emit(SubBruteState* context) {
UNUSED(context);
furi_hal_subghz_stop_async_tx();
furi_hal_subghz_idle();
//furi_hal_subghz_stop_async_tx();
//furi_hal_subghz_idle();
furi_hal_subghz_sleep();
}
/*
@ -172,8 +172,6 @@ void subbrute_send_packet_parsed(SubBruteState* context) {
stream_clean(context->stream);
stream_write_string(context->stream, context->flipper_format_string);
subbrute_emit(context);
}
void subbrute_send_packet(SubBruteState* context) {
@ -181,6 +179,7 @@ void subbrute_send_packet(SubBruteState* context) {
// subbrute_send_raw_packet(context);
//} else {
subbrute_send_packet_parsed(context);
subbrute_emit(context);
//}
string_clear(context->flipper_format_string);
}
@ -189,6 +188,9 @@ void subbrute_scene_run_attack_on_exit(SubBruteState* context) {
if(!toSave) {
clear_emit(context);
furi_thread_free(context->bruthread);
flipper_format_free(context->flipper_format);
subghz_receiver_free(context->receiver);
subghz_environment_free(context->environment);
}
}
@ -201,8 +203,8 @@ void subbrute_scene_run_attack_on_tick(SubBruteState* context) {
subbrute_send_packet(context);
if(context->payload == max_value) {
context->payload = 0x00;
subbrute_counter = 0;
//context->payload = 0x00;
//subbrute_counter = 0;
context->is_attacking = false;
notification_message(context->notify, &sequence_blink_stop);
notification_message(context->notify, &sequence_single_vibro);
@ -219,7 +221,7 @@ void subbrute_scene_run_attack_on_tick(SubBruteState* context) {
}
void subbrute_run_timer(SubBruteState* context) {
while(true) {
if(context->close_thread_please) {
if(!context->is_attacking) {
context->is_thread_running = false;
break;
}
@ -260,6 +262,8 @@ void subbrute_scene_run_attack_on_enter(SubBruteState* context) {
context->flipper_format = flipper_format_string_alloc();
context->stream = flipper_format_get_raw_stream(context->flipper_format);
context->environment = subghz_environment_alloc();
context->receiver = subghz_receiver_alloc_init(context->environment);
subghz_receiver_set_filter(context->receiver, SubGhzProtocolFlag_Decodable);
prepare_emit(context);
context->bruthread = furi_thread_alloc();
@ -280,6 +284,8 @@ void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* cont
break;
case InputKeyUp:
if(!context->is_attacking) {
subbrute_send_packet_parsed(context);
string_clear(context->flipper_format_string);
toSave = true;
context->current_scene = SceneSaveName;
}
@ -289,6 +295,10 @@ void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* cont
context->payload--;
subbrute_send_packet(context);
notification_message(context->notify, &sequence_blink_blue_10);
} else if(!context->is_attacking && context->payload == 0x00) {
context->payload = max_value;
subbrute_send_packet(context);
notification_message(context->notify, &sequence_blink_blue_10);
}
break;
case InputKeyRight:
@ -296,35 +306,43 @@ void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* cont
context->payload++;
subbrute_send_packet(context);
notification_message(context->notify, &sequence_blink_blue_10);
} else if(!context->is_attacking && context->payload == max_value) {
context->payload = 0x00;
subbrute_send_packet(context);
notification_message(context->notify, &sequence_blink_blue_10);
}
break;
case InputKeyOk:
if(!context->is_attacking) {
if(context->payload == max_value) {
context->payload = 0x00;
//subbrute_counter = 0;
}
context->is_attacking = true;
start_bruthread(context);
notification_message(context->notify, &sequence_blink_start_blue);
} else {
context->is_attacking = false;
context->close_thread_please = true;
//context->close_thread_please = true;
if(context->is_thread_running && context->bruthread) {
furi_thread_join(context->bruthread); // wait until thread is finished
}
context->close_thread_please = false;
//context->close_thread_please = false;
notification_message(context->notify, &sequence_blink_stop);
notification_message(context->notify, &sequence_single_vibro);
}
break;
case InputKeyBack:
locked = false;
context->close_thread_please = true;
//context->close_thread_please = true;
context->is_attacking = false;
if(context->is_thread_running && context->bruthread) {
furi_thread_join(context->bruthread); // wait until thread is finished
}
context->close_thread_please = false;
//context->close_thread_please = false;
string_reset(context->notification_msg);
context->payload = 0x00;
subbrute_counter = 0;
//subbrute_counter = 0;
notification_message(context->notify, &sequence_blink_stop);
if(context->attack == SubBruteAttackLoadFile) {
context->current_scene = SceneSelectField;

View file

@ -75,10 +75,8 @@ SubBruteState* subbrute_alloc() {
subbrute->preset_def = malloc(sizeof(SubGhzPresetDefinition));
subbrute->flipper_format = flipper_format_string_alloc();
subbrute->environment = subghz_environment_alloc();
subbrute->receiver = subghz_receiver_alloc_init(subbrute->environment);
subghz_receiver_set_filter(subbrute->receiver, SubGhzProtocolFlag_Decodable);
//subbrute->flipper_format = flipper_format_string_alloc();
//subbrute->environment = subghz_environment_alloc();
return subbrute;
}
@ -103,9 +101,9 @@ void subbrute_free(SubBruteState* subbrute) {
string_clear(subbrute->candidate);
string_clear(subbrute->flipper_format_string);
flipper_format_free(subbrute->flipper_format);
subghz_environment_free(subbrute->environment);
subghz_receiver_free(subbrute->receiver);
//flipper_format_free(subbrute->flipper_format);
//subghz_environment_free(subbrute->environment);
//subghz_receiver_free(subbrute->receiver);
free(subbrute->preset_def);

View file

@ -98,7 +98,7 @@ FIRMWARE_APPS = {
# Svc
"basic_services",
# Apps
#"basic_apps",
"basic_apps",
"updater_app",
"storage_move_to_sd",
"archive",
@ -109,7 +109,7 @@ FIRMWARE_APPS = {
# Plugins
#"basic_plugins",
# Debug
"debug_apps",
#"debug_apps",
],
}

View file

@ -32,7 +32,7 @@ extern uint32_t SystemCoreClock;
#define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 0
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configENABLE_BACKWARD_COMPATIBILITY 0
@ -145,3 +145,7 @@ standard names. */
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION \
1 /* required only for Keil but does not hurt otherwise */
#define traceTASK_SWITCHED_IN() \
extern void furi_hal_mpu_set_stack_protection(uint32_t* stack); \
furi_hal_mpu_set_stack_protection((uint32_t*)pxCurrentTCB->pxStack)

View file

@ -1,5 +1,6 @@
#include <furi_hal.h>
#include <furi_hal_memory.h>
#include <furi_hal_mpu.h>
#include <stm32wbxx_ll_cortex.h>
@ -36,6 +37,7 @@ void furi_hal_deinit_early() {
}
void furi_hal_init() {
furi_hal_mpu_init();
furi_hal_clock_init();
furi_hal_console_init();
furi_hal_rtc_init();
@ -82,17 +84,6 @@ void furi_hal_init() {
// FatFS driver initialization
MX_FATFS_Init();
FURI_LOG_I(TAG, "FATFS OK");
// Partial null pointer dereference protection
LL_MPU_Disable();
LL_MPU_ConfigRegion(
LL_MPU_REGION_NUMBER0,
0x00,
0x0,
LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | LL_MPU_ACCESS_BUFFERABLE |
LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_SHAREABLE | LL_MPU_TEX_LEVEL1 |
LL_MPU_INSTRUCTION_ACCESS_ENABLE);
LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT);
}
void furi_hal_switch(void* address) {

View file

@ -6,6 +6,7 @@
#include <stm32wbxx.h>
#include <stm32wbxx_ll_tim.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_cortex.h>
#define TAG "FuriHalInterrupt"
@ -95,6 +96,10 @@ void furi_hal_interrupt_init() {
LL_SYSCFG_DisableIT_FPU_IDC();
LL_SYSCFG_DisableIT_FPU_IXC();
LL_HANDLER_EnableFault(LL_HANDLER_FAULT_USG);
LL_HANDLER_EnableFault(LL_HANDLER_FAULT_BUS);
LL_HANDLER_EnableFault(LL_HANDLER_FAULT_MEM);
FURI_LOG_I(TAG, "Init OK");
}
@ -241,6 +246,20 @@ void HardFault_Handler() {
}
void MemManage_Handler() {
if(FURI_BIT(SCB->CFSR, SCB_CFSR_MMARVALID_Pos)) {
uint32_t memfault_address = SCB->MMFAR;
if(memfault_address < (1024 * 1024)) {
// from 0x00 to 1MB, see FuriHalMpuRegionNULL
furi_crash("NULL pointer dereference");
} else {
// write or read of MPU region 1 (FuriHalMpuRegionStack)
furi_crash("MPU fault, possibly stack overflow");
}
} else if(FURI_BIT(SCB->CFSR, SCB_CFSR_MSTKERR_Pos)) {
// push to stack on MPU region 1 (FuriHalMpuRegionStack)
furi_crash("MemManage fault, possibly stack overflow");
}
furi_crash("MemManage");
}

View file

@ -0,0 +1,66 @@
#include <furi_hal_mpu.h>
#include <stm32wbxx_ll_cortex.h>
#define FURI_HAL_MPU_ATTRIBUTES \
(LL_MPU_ACCESS_BUFFERABLE | LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_SHAREABLE | \
LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_ENABLE)
#define FURI_HAL_MPU_STACK_PROTECT_REGION FuriHalMPURegionSize32B
void furi_hal_mpu_init() {
furi_hal_mpu_enable();
// NULL pointer dereference protection
furi_hal_mpu_protect_no_access(FuriHalMpuRegionNULL, 0x00, FuriHalMPURegionSize1MB);
}
void furi_hal_mpu_enable() {
LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT);
}
void furi_hal_mpu_disable() {
LL_MPU_Disable();
}
void furi_hal_mpu_protect_no_access(
FuriHalMpuRegion region,
uint32_t address,
FuriHalMPURegionSize size) {
uint32_t size_ll = size;
size_ll = size_ll << MPU_RASR_SIZE_Pos;
furi_hal_mpu_disable();
LL_MPU_ConfigRegion(
region, 0x00, address, FURI_HAL_MPU_ATTRIBUTES | LL_MPU_REGION_NO_ACCESS | size_ll);
furi_hal_mpu_enable();
}
void furi_hal_mpu_protect_read_only(
FuriHalMpuRegion region,
uint32_t address,
FuriHalMPURegionSize size) {
uint32_t size_ll = size;
size_ll = size_ll << MPU_RASR_SIZE_Pos;
furi_hal_mpu_disable();
LL_MPU_ConfigRegion(
region, 0x00, address, FURI_HAL_MPU_ATTRIBUTES | LL_MPU_REGION_PRIV_RO_URO | size_ll);
furi_hal_mpu_enable();
}
void furi_hal_mpu_protect_disable(FuriHalMpuRegion region) {
furi_hal_mpu_disable();
LL_MPU_DisableRegion(region);
furi_hal_mpu_enable();
}
void furi_hal_mpu_set_stack_protection(uint32_t* stack) {
// Protection area address must be aligned to region size
uint32_t stack_ptr = (uint32_t)stack;
uint32_t mask = ((1 << (FURI_HAL_MPU_STACK_PROTECT_REGION + 2)) - 1);
stack_ptr &= ~mask;
if(stack_ptr < (uint32_t)stack) stack_ptr += (mask + 1);
furi_hal_mpu_protect_read_only(
FuriHalMpuRegionStack, stack_ptr, FURI_HAL_MPU_STACK_PROTECT_REGION);
}

View file

@ -0,0 +1,86 @@
/**
* @file furi_hal_light.h
* Light control HAL API
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
FuriHalMpuRegionNULL = 0x00, // region 0 used to protect null pointer dereference
FuriHalMpuRegionStack = 0x01, // region 1 used to protect stack
FuriHalMpuRegion2 = 0x02,
FuriHalMpuRegion3 = 0x03,
FuriHalMpuRegion4 = 0x04,
FuriHalMpuRegion5 = 0x05,
FuriHalMpuRegion6 = 0x06,
FuriHalMpuRegion7 = 0x07,
} FuriHalMpuRegion;
typedef enum {
FuriHalMPURegionSize32B = 0x04U,
FuriHalMPURegionSize64B = 0x05U,
FuriHalMPURegionSize128B = 0x06U,
FuriHalMPURegionSize256B = 0x07U,
FuriHalMPURegionSize512B = 0x08U,
FuriHalMPURegionSize1KB = 0x09U,
FuriHalMPURegionSize2KB = 0x0AU,
FuriHalMPURegionSize4KB = 0x0BU,
FuriHalMPURegionSize8KB = 0x0CU,
FuriHalMPURegionSize16KB = 0x0DU,
FuriHalMPURegionSize32KB = 0x0EU,
FuriHalMPURegionSize64KB = 0x0FU,
FuriHalMPURegionSize128KB = 0x10U,
FuriHalMPURegionSize256KB = 0x11U,
FuriHalMPURegionSize512KB = 0x12U,
FuriHalMPURegionSize1MB = 0x13U,
FuriHalMPURegionSize2MB = 0x14U,
FuriHalMPURegionSize4MB = 0x15U,
FuriHalMPURegionSize8MB = 0x16U,
FuriHalMPURegionSize16MB = 0x17U,
FuriHalMPURegionSize32MB = 0x18U,
FuriHalMPURegionSize64MB = 0x19U,
FuriHalMPURegionSize128MB = 0x1AU,
FuriHalMPURegionSize256MB = 0x1BU,
FuriHalMPURegionSize512MB = 0x1CU,
FuriHalMPURegionSize1GB = 0x1DU,
FuriHalMPURegionSize2GB = 0x1EU,
FuriHalMPURegionSize4GB = 0x1FU,
} FuriHalMPURegionSize;
/**
* @brief Initialize memory protection unit
*/
void furi_hal_mpu_init();
/**
* @brief Enable memory protection unit
*/
void furi_hal_mpu_enable();
/**
* @brief Disable memory protection unit
*/
void furi_hal_mpu_disable();
void furi_hal_mpu_protect_no_access(
FuriHalMpuRegion region,
uint32_t address,
FuriHalMPURegionSize size);
void furi_hal_mpu_protect_read_only(
FuriHalMpuRegion region,
uint32_t address,
FuriHalMPURegionSize size);
void furi_hal_mpu_protect_disable(FuriHalMpuRegion region);
#ifdef __cplusplus
}
#endif

View file

@ -37,10 +37,8 @@ void* calloc(size_t count, size_t size) {
}
char* strdup(const char* s) {
const char* s_null = s;
if(s_null == NULL) {
return NULL;
}
// arg s marked as non-null, so we need hack to check for NULL
furi_check(((uint32_t)s << 2) != 0);
size_t siz = strlen(s) + 1;
char* y = pvPortMalloc(siz);

View file

@ -504,7 +504,7 @@ uint8_t nrf24_find_channel(
}
if(autoinit) {
FURI_LOG_I("nrf24", "initializing radio for channel %d", ch);
FURI_LOG_D("nrf24", "initializing radio for channel %d", ch);
nrf24_configure(handle, rate, srcmac, dstmac, maclen, ch, false, false);
return ch;
}

View file

@ -140,6 +140,9 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc
uint64_t man = 0;
uint64_t code_found_reverse;
int res = 0;
if(instance->manufacture_name == 0x0) {
instance->manufacture_name = "";
}
if(strcmp(instance->manufacture_name, "Unknown") == 0) {
code_found_reverse = subghz_protocol_blocks_reverse_key(
@ -559,6 +562,9 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
uint32_t decrypt = 0;
uint64_t man;
int res = 0;
if(mfname == 0x0) {
mfname = "";
}
if(strcmp(mfname, "") == 0) {
for