diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_config.h b/applications/plugins/subbrute/scenes/subbrute_scene_config.h index 40806279f..3541df9ac 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_config.h +++ b/applications/plugins/subbrute/scenes/subbrute_scene_config.h @@ -1,4 +1,5 @@ ADD_SCENE(subbrute, load_file, LoadFile) +ADD_SCENE(subbrute, load_select, LoadSelect) ADD_SCENE(subbrute, run_attack, RunAttack) ADD_SCENE(subbrute, save_name, SaveName) ADD_SCENE(subbrute, save_success, SaveSuccess) diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c index f9bad3cea..6557b4ba1 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_load_file.c @@ -48,7 +48,7 @@ void subbrute_scene_load_file_on_enter(void* context) { } if(load_result == SubBruteFileResultOk) { - scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadSelect); } else { FURI_LOG_E(TAG, "Returned error: %d", load_result); diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c b/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c new file mode 100644 index 000000000..e3774e407 --- /dev/null +++ b/applications/plugins/subbrute/scenes/subbrute_scene_load_select.c @@ -0,0 +1,61 @@ +#include "../subbrute_i.h" +#include "../subbrute_custom_event.h" +#include "../views/subbrute_main_view.h" + +#define TAG "SubBruteSceneStart" + +void subbrute_scene_load_select_callback(SubBruteCustomEvent event, void* context) { + furi_assert(context); + + SubBruteState* instance = (SubBruteState*)context; +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "subbrute_scene_load_select_callback"); +#endif + view_dispatcher_send_custom_event(instance->view_dispatcher, event); +} + +void subbrute_scene_load_select_on_enter(void* context) { + furi_assert(context); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "subbrute_scene_load_select_on_enter"); +#endif + SubBruteState* instance = (SubBruteState*)context; + SubBruteMainView* view = instance->view_main; + + instance->current_view = SubBruteViewMain; + subbrute_main_view_set_callback(view, subbrute_scene_load_select_callback, instance); + subbrute_main_view_set_index(view, 7, true, instance->device->file_key); + + view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); +} + +void subbrute_scene_load_select_on_exit(void* context) { + UNUSED(context); +#ifdef FURI_DEBUG + FURI_LOG_I(TAG, "subbrute_scene_load_select_on_exit"); +#endif +} + +bool subbrute_scene_load_select_on_event(void* context, SceneManagerEvent event) { + SubBruteState* instance = (SubBruteState*)context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubBruteCustomEventTypeIndexSelected) { + instance->device->load_index = subbrute_main_view_get_index(instance->view_main); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "load_index: %d", instance->device->load_index); +#endif + scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + if(!scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, SubBruteSceneStart)) { + scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart); + } + consumed = true; + } + + return consumed; +} \ No newline at end of file diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c index eb00265b4..fe3a5d8b4 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_start.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -24,7 +24,7 @@ void subbrute_scene_start_on_enter(void* context) { instance->current_view = SubBruteViewMain; subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance); - subbrute_main_view_set_index(view, instance->device->attack); + subbrute_main_view_set_index(view, instance->device->attack, false, NULL); view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view); } @@ -55,7 +55,7 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile); consumed = true; } - } else if (event.type == SceneManagerEventTypeBack) { + } else if(event.type == SceneManagerEventTypeBack) { //exit app scene_manager_stop(instance->scene_manager); view_dispatcher_stop(instance->view_dispatcher); diff --git a/applications/plugins/subbrute/subbrute_custom_event.h b/applications/plugins/subbrute/subbrute_custom_event.h index c3b04ebdf..5ddab7fa1 100644 --- a/applications/plugins/subbrute/subbrute_custom_event.h +++ b/applications/plugins/subbrute/subbrute_custom_event.h @@ -8,7 +8,7 @@ typedef enum { SubBruteCustomEventTypeReserved = 100, SubBruteCustomEventTypeBackPressed, - SubBruteCustomEventTypeTextEditResult, + SubBruteCustomEventTypeIndexSelected, SubBruteCustomEventTypeTransmitStarted, SubBruteCustomEventTypeTransmitFinished, SubBruteCustomEventTypeTransmitNotStarted, diff --git a/applications/plugins/subbrute/subbrute_device.c b/applications/plugins/subbrute/subbrute_device.c index 8c02beb62..02913d577 100644 --- a/applications/plugins/subbrute/subbrute_device.c +++ b/applications/plugins/subbrute/subbrute_device.c @@ -207,7 +207,7 @@ bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t ste char subbrute_payload_byte[4]; string_set_str(candidate, instance->file_key); snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step); - string_replace_at(candidate, step, 3, subbrute_payload_byte); + string_replace_at(candidate, instance->load_index * 3, 3, subbrute_payload_byte); //snprintf(step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]); } else { //snprintf(step_payload, sizeof(step_payload), "%16X", step); @@ -512,6 +512,9 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p break; } else { instance->bit = temp_data32; +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Bit: %d", instance->bit); +#endif } // Key @@ -522,6 +525,9 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, string_t file_p } else { snprintf( instance->file_key, sizeof(instance->file_key), "%s", string_get_cstr(temp_str)); +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "Key: %s", instance->file_key); +#endif } // TE @@ -579,6 +585,7 @@ void subbrute_device_attack_set_default_values( #endif instance->attack = default_attack; instance->key_index = 0x00; + instance->load_index = 0x00; memset(instance->file_template, 0, sizeof(instance->file_template)); memset(instance->current_key, 0, sizeof(instance->current_key)); memset(instance->text_store, 0, sizeof(instance->text_store)); diff --git a/applications/plugins/subbrute/subbrute_device.h b/applications/plugins/subbrute/subbrute_device.h index f0d3d8a57..625c53d2a 100644 --- a/applications/plugins/subbrute/subbrute_device.h +++ b/applications/plugins/subbrute/subbrute_device.h @@ -8,7 +8,7 @@ #include #include -#define SUBBRUTE_TEXT_STORE_SIZE 128 +#define SUBBRUTE_TEXT_STORE_SIZE 256 #define SUBBRUTE_MAX_LEN_NAME 64 #define SUBBRUTE_PATH EXT_PATH("subghz") @@ -60,6 +60,8 @@ typedef struct { // Current step uint64_t key_index; string_t load_path; + // Index of group to bruteforce in loaded file + uint8_t load_index; SubGhzReceiver* receiver; SubGhzProtocolDecoderBase* decoder_result; @@ -82,7 +84,7 @@ typedef struct { char current_key[SUBBRUTE_PAYLOAD_SIZE]; uint32_t te; - char file_key[SUBBRUTE_PAYLOAD_SIZE]; + char file_key[SUBBRUTE_MAX_LEN_NAME]; char text_store[SUBBRUTE_PAYLOAD_SIZE]; } SubBruteDevice; diff --git a/applications/plugins/subbrute/views/subbrute_main_view.c b/applications/plugins/subbrute/views/subbrute_main_view.c index 67342cc9c..5275a9774 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.c +++ b/applications/plugins/subbrute/views/subbrute_main_view.c @@ -18,6 +18,8 @@ struct SubBruteMainView { typedef struct { uint8_t index; uint8_t window_position; + bool is_select_byte; + const char* key_field; } SubBruteMainViewModel; void subbrute_main_view_set_callback( @@ -31,6 +33,51 @@ void subbrute_main_view_set_callback( instance->context = context; } +void center_displayed_key(string_t result, const char* key_cstr, uint8_t index) { + uint8_t str_index = (index * 3); + + char display_menu[] = { + 'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'}; + + if(key_cstr != NULL) { + if(index > 1) { + display_menu[0] = key_cstr[str_index - 6]; + display_menu[1] = key_cstr[str_index - 5]; + } else { + display_menu[0] = ' '; + display_menu[1] = ' '; + } + + if(index > 0) { + display_menu[3] = key_cstr[str_index - 3]; + display_menu[4] = key_cstr[str_index - 2]; + } else { + display_menu[3] = ' '; + display_menu[4] = ' '; + } + + display_menu[7] = key_cstr[str_index]; + display_menu[8] = key_cstr[str_index + 1]; + + if((str_index + 4) <= (uint8_t)strlen(key_cstr)) { + display_menu[11] = key_cstr[str_index + 3]; + display_menu[12] = key_cstr[str_index + 4]; + } else { + display_menu[11] = ' '; + display_menu[12] = ' '; + } + + if((str_index + 8) <= (uint8_t)strlen(key_cstr)) { + display_menu[14] = key_cstr[str_index + 6]; + display_menu[15] = key_cstr[str_index + 7]; + } else { + display_menu[14] = ' '; + display_menu[15] = ' '; + } + } + string_init_set_str(result, display_menu); +} + void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { SubBruteMainViewModel* m = model; @@ -41,49 +88,72 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) { canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Sub-GHz Bruteforcer"); canvas_invert_color(canvas); - // Menu - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - uint8_t items_on_screen = 3; - const uint8_t item_height = 16; + if(m->is_select_byte) { +#ifdef FURI_DEBUG + FURI_LOG_D(TAG, "key_field: %s", m->key_field); +#endif + char msg_index[18]; + snprintf(msg_index, sizeof(msg_index), "Field index : %d", m->index); + canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index); + + string_t menu_items; + string_init(menu_items); + + center_displayed_key(menu_items, m->key_field, m->index); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, 64, 40, AlignCenter, AlignTop, string_get_cstr(menu_items)); + + elements_button_center(canvas, "Select"); + elements_button_left(canvas, "<"); + elements_button_right(canvas, ">"); + + string_reset(menu_items); + } else { + // Menu + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + uint8_t items_on_screen = 3; + const uint8_t item_height = 16; #ifdef FURI_DEBUG - FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index); + FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index); #endif - for(uint8_t position = 0; position < SubBruteAttackTotalCount; ++position) { - uint8_t item_position = position - model->window_position; + for(uint8_t position = 0; position < SubBruteAttackTotalCount; ++position) { + uint8_t item_position = position - model->window_position; - if(item_position < items_on_screen) { - const char* str = subbrute_get_menu_name(position); - if(m->index == position) { - canvas_draw_str_aligned( - canvas, - 64, - 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, - AlignCenter, - AlignCenter, - str); - elements_frame( - canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 125, 15); - } else { - canvas_draw_str_aligned( - canvas, - 64, - 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, - AlignCenter, - AlignCenter, - str); + if(item_position < items_on_screen) { + const char* str = subbrute_get_menu_name(position); + if(m->index == position) { + canvas_draw_str_aligned( + canvas, + 64, + 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, + AlignCenter, + AlignCenter, + str); + elements_frame( + canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 125, 15); + } else { + canvas_draw_str_aligned( + canvas, + 64, + 9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, + AlignCenter, + AlignCenter, + str); + } } } - } - elements_scrollbar_pos( - canvas, - canvas_width(canvas), - STATUS_BAR_Y_SHIFT + 2, - canvas_height(canvas) - STATUS_BAR_Y_SHIFT, - m->index, - SubBruteAttackTotalCount); + elements_scrollbar_pos( + canvas, + canvas_width(canvas), + STATUS_BAR_Y_SHIFT + 2, + canvas_height(canvas) - STATUS_BAR_Y_SHIFT, + m->index, + SubBruteAttackTotalCount); + } } bool subbrute_main_view_input(InputEvent* event, void* context) { @@ -101,66 +171,107 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { const uint8_t min_value = 0; const uint8_t correct_total = SubBruteAttackTotalCount - 1; uint8_t index = 0; - - bool consumed = false; - if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { - with_view_model( - instance->view, (SubBruteMainViewModel * model) { - bool ret = false; - uint8_t items_on_screen = 3; - if(event->key == InputKeyUp) { - if(model->index == min_value) { - model->index = correct_total; - } else { - model->index = CLAMP(model->index - 1, correct_total, min_value); - } - ret = true; - consumed = true; - } else if(event->key == InputKeyDown) { - if(model->index == correct_total) { - model->index = min_value; - } else { - model->index = CLAMP(model->index + 1, correct_total, min_value); - } - ret = true; - consumed = true; - } - if(ret) { - model->window_position = model->index; - if(model->window_position > 0) { - model->window_position -= 1; - } - - if(SubBruteAttackTotalCount <= items_on_screen) { - model->window_position = 0; - } else { - if(model->window_position >= - (SubBruteAttackTotalCount - items_on_screen)) { - model->window_position = (SubBruteAttackTotalCount - items_on_screen); - } - } - } - index = model->index; - return ret; - }); - } - -#ifdef FURI_DEBUG + bool is_select_byte = false; with_view_model( instance->view, (SubBruteMainViewModel * model) { - index = model->index; + is_select_byte = model->is_select_byte; return false; }); - FURI_LOG_I(TAG, "Index: %d", index); + + bool consumed = false; + if(!is_select_byte) { + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + bool ret = false; + uint8_t items_on_screen = 3; + if(event->key == InputKeyUp) { + if(model->index == min_value) { + model->index = correct_total; + } else { + model->index = CLAMP(model->index - 1, correct_total, min_value); + } + ret = true; + consumed = true; + } else if(event->key == InputKeyDown) { + if(model->index == correct_total) { + model->index = min_value; + } else { + model->index = CLAMP(model->index + 1, correct_total, min_value); + } + ret = true; + consumed = true; + } + if(ret) { + model->window_position = model->index; + if(model->window_position > 0) { + model->window_position -= 1; + } + + if(SubBruteAttackTotalCount <= items_on_screen) { + model->window_position = 0; + } else { + if(model->window_position >= + (SubBruteAttackTotalCount - items_on_screen)) { + model->window_position = + (SubBruteAttackTotalCount - items_on_screen); + } + } + } + index = model->index; + return ret; + }); + } + +#ifdef FURI_DEBUG + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + index = model->index; + return false; + }); + FURI_LOG_I(TAG, "Index: %d", index); #endif - if(event->key == InputKeyOk && event->type == InputTypeShort) { - if(index == SubBruteAttackLoadFile) { - instance->callback(SubBruteCustomEventTypeLoadFile, instance->context); - } else { - instance->callback(SubBruteCustomEventTypeMenuSelected, instance->context); + if(event->key == InputKeyOk && event->type == InputTypeShort) { + if(index == SubBruteAttackLoadFile) { + instance->callback(SubBruteCustomEventTypeLoadFile, instance->context); + } else { + instance->callback(SubBruteCustomEventTypeMenuSelected, instance->context); + } + consumed = true; + } + } else { + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + if(event->key == InputKeyLeft) { + if(model->index > 0) { + model->index--; + } + } else if(event->key == InputKeyRight) { + if(model->index < 7) { + model->index++; + } + } + + index = model->index; + return true; + }); + } + +#ifdef FURI_DEBUG + with_view_model( + instance->view, (SubBruteMainViewModel * model) { + index = model->index; + return false; + }); + FURI_LOG_I(TAG, "Index: %d", index); +#endif + + if(event->key == InputKeyOk && event->type == InputTypeShort) { + instance->callback(SubBruteCustomEventTypeIndexSelected, instance->context); + consumed = true; } - consumed = true; } return consumed; @@ -196,6 +307,8 @@ SubBruteMainView* subbrute_main_view_alloc() { instance->view, (SubBruteMainViewModel * model) { model->index = 0; model->window_position = 0; + model->key_field = NULL; + model->is_select_byte = false; return true; }); @@ -214,7 +327,11 @@ View* subbrute_main_view_get_view(SubBruteMainView* instance) { return instance->view; } -void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { +void subbrute_main_view_set_index( + SubBruteMainView* instance, + uint8_t idx, + bool is_select_byte, + const char* key_field) { furi_assert(instance); furi_assert(idx < SubBruteAttackTotalCount); #ifdef FURI_DEBUG @@ -222,23 +339,26 @@ void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx) { #endif with_view_model( instance->view, (SubBruteMainViewModel * model) { + model->is_select_byte = is_select_byte; + model->key_field = key_field; model->index = idx; model->window_position = idx; - uint8_t items_on_screen = 3; + if(!is_select_byte) { + uint8_t items_on_screen = 3; - if(model->window_position > 0) { - model->window_position -= 1; - } + if(model->window_position > 0) { + model->window_position -= 1; + } - if(SubBruteAttackTotalCount <= items_on_screen) { - model->window_position = 0; - } else { - if(model->window_position >= (SubBruteAttackTotalCount - items_on_screen)) { - model->window_position = (SubBruteAttackTotalCount - items_on_screen); + if(SubBruteAttackTotalCount <= items_on_screen) { + model->window_position = 0; + } else { + if(model->window_position >= (SubBruteAttackTotalCount - items_on_screen)) { + model->window_position = (SubBruteAttackTotalCount - items_on_screen); + } } } - return true; }); } diff --git a/applications/plugins/subbrute/views/subbrute_main_view.h b/applications/plugins/subbrute/views/subbrute_main_view.h index bb0e30b00..55a8bf0c3 100644 --- a/applications/plugins/subbrute/views/subbrute_main_view.h +++ b/applications/plugins/subbrute/views/subbrute_main_view.h @@ -19,7 +19,11 @@ SubBruteMainView* subbrute_main_view_alloc(); void subbrute_main_view_free(SubBruteMainView* instance); View* subbrute_main_view_get_view(SubBruteMainView* instance); -void subbrute_main_view_set_index(SubBruteMainView* instance, uint8_t idx); +void subbrute_main_view_set_index( + SubBruteMainView* instance, + uint8_t idx, + bool is_select_byte, + const char* key_field); uint8_t subbrute_main_view_get_index(SubBruteMainView* instance); void subbrute_attack_view_enter(void* context);