diff --git a/applications/external/wifi_marauder_companion/application.fam b/applications/external/wifi_marauder_companion/application.fam index d8bfc58a6..66255706a 100644 --- a/applications/external/wifi_marauder_companion/application.fam +++ b/applications/external/wifi_marauder_companion/application.fam @@ -4,7 +4,7 @@ App( apptype=FlipperAppType.EXTERNAL, entry_point="wifi_marauder_app", requires=["gui"], - stack_size=1 * 1024, + stack_size=4 * 1024, order=90, fap_icon="wifi_10px.png", fap_category="GPIO", diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_config.h b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_config.h index 75e95c9bc..715897d17 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_config.h +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_config.h @@ -1,3 +1,5 @@ ADD_SCENE(wifi_marauder, start, Start) ADD_SCENE(wifi_marauder, console_output, ConsoleOutput) ADD_SCENE(wifi_marauder, text_input, TextInput) +ADD_SCENE(wifi_marauder, settings_init, SettingsInit) +ADD_SCENE(wifi_marauder, log_viewer, LogViewer) diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c index 77beb733c..0729500eb 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c @@ -4,6 +4,11 @@ void wifi_marauder_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, vo furi_assert(context); WifiMarauderApp* app = context; + if(app->is_writing_log) { + app->has_saved_logs_this_session = true; + storage_file_write(app->log_file, buf, len); + } + // If text box store gets too big, then truncate it app->text_box_store_strlen += len; if(app->text_box_store_strlen >= WIFI_MARAUDER_TEXT_BOX_STORE_SIZE - 1) { @@ -21,15 +26,7 @@ void wifi_marauder_console_output_handle_rx_packets_cb(uint8_t* buf, size_t len, furi_assert(context); WifiMarauderApp* app = context; - // If it is a sniff function, open the pcap file for recording - if(strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0 && !app->is_writing) { - app->is_writing = true; - if(!app->capture_file || !storage_file_is_open(app->capture_file)) { - wifi_marauder_create_pcap_file(app); - } - } - - if(app->is_writing) { + if(app->is_writing_pcap) { storage_file_write(app->capture_file, buf, len); } } @@ -49,8 +46,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { furi_string_reset(app->text_box_store); app->text_box_store_strlen = 0; if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) { - const char* help_msg = "Marauder companion " WIFI_MARAUDER_APP_VERSION - "\nby @0xchocolate\nmodified by @tcpassos\n"; + const char* help_msg = "Marauder companion " WIFI_MARAUDER_APP_VERSION "\n"; furi_string_cat_str(app->text_box_store, help_msg); app->text_box_store_strlen += strlen(help_msg); } @@ -62,7 +58,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { } } - // Set starting text - for "View Log", this will just be what was already in the text box store + // Set starting text - for "View Log from end", this will just be what was already in the text box store text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneConsoleOutput, 0); @@ -76,8 +72,23 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { app->lp_uart, wifi_marauder_console_output_handle_rx_packets_cb); // setup callback for packets rx thread - // Send command with newline '\n' + // Get ready to send command if(app->is_command && app->selected_tx_string) { + // Create files *before* sending command + // (it takes time to iterate through the directory) + if(app->ok_to_save_logs) { + app->is_writing_log = true; + wifi_marauder_create_log_file(app); + } + + // If it is a sniff function, open the pcap file for recording + if(app->ok_to_save_pcaps && + strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0) { + app->is_writing_pcap = true; + wifi_marauder_create_pcap_file(app); + } + + // Send command with newline '\n' wifi_marauder_uart_tx( (uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string)); wifi_marauder_uart_tx((uint8_t*)("\n"), 1); @@ -111,8 +122,13 @@ void wifi_marauder_scene_console_output_on_exit(void* context) { wifi_marauder_uart_tx((uint8_t*)("stopscan\n"), strlen("stopscan\n")); } - app->is_writing = false; + app->is_writing_pcap = false; if(app->capture_file && storage_file_is_open(app->capture_file)) { storage_file_close(app->capture_file); } + + app->is_writing_log = false; + if(app->log_file && storage_file_is_open(app->log_file)) { + storage_file_close(app->log_file); + } } diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_log_viewer.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_log_viewer.c new file mode 100644 index 000000000..f4e84ccc8 --- /dev/null +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_log_viewer.c @@ -0,0 +1,185 @@ +#include "../wifi_marauder_app_i.h" + +void wifi_marauder_scene_log_viewer_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + WifiMarauderApp* app = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(app->view_dispatcher, result); + } +} + +static void _read_log_page_into_text_store(WifiMarauderApp* app) { + char temp[64 + 1]; + storage_file_seek( + app->log_file, WIFI_MARAUDER_TEXT_BOX_STORE_SIZE * (app->open_log_file_page - 1), true); + furi_string_reset(app->text_box_store); + for(uint16_t i = 0; i < (WIFI_MARAUDER_TEXT_BOX_STORE_SIZE / (sizeof(temp) - 1)); i++) { + uint16_t num_bytes = storage_file_read(app->log_file, temp, sizeof(temp) - 1); + if(num_bytes == 0) { + break; + } + temp[num_bytes] = '\0'; + furi_string_cat_str(app->text_box_store, temp); + } +} + +void wifi_marauder_scene_log_viewer_setup_widget(WifiMarauderApp* app, bool called_from_browse) { + Widget* widget = app->widget; + bool is_open = storage_file_is_open(app->log_file); + bool should_open_log = (app->has_saved_logs_this_session || called_from_browse); + if(is_open) { + _read_log_page_into_text_store(app); + } else if( + should_open_log && + storage_file_open(app->log_file, app->log_file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { + uint64_t filesize = storage_file_size(app->log_file); + app->open_log_file_num_pages = filesize / WIFI_MARAUDER_TEXT_BOX_STORE_SIZE; + int extra_page = (filesize % WIFI_MARAUDER_TEXT_BOX_STORE_SIZE != 0) ? 1 : 0; + app->open_log_file_num_pages = (filesize / WIFI_MARAUDER_TEXT_BOX_STORE_SIZE) + extra_page; + app->open_log_file_page = 1; + _read_log_page_into_text_store(app); + } else { + app->open_log_file_page = 0; + app->open_log_file_num_pages = 0; + } + + widget_reset(widget); + + if(furi_string_empty(app->text_box_store)) { + char help_msg[256]; + snprintf( + help_msg, + sizeof(help_msg), + "The log is empty! :(\nTry sending a command?\n\nSaving pcaps to flipper sdcard: %s\nSaving logs to flipper sdcard: %s", + app->ok_to_save_pcaps ? "ON" : "OFF", + app->ok_to_save_logs ? "ON" : "OFF"); + furi_string_set_str(app->text_box_store, help_msg); + } + + widget_add_text_scroll_element( + widget, 0, 0, 128, 53, furi_string_get_cstr(app->text_box_store)); + + if(1 < app->open_log_file_page && app->open_log_file_page < app->open_log_file_num_pages) { + // hide "Browse" text for middle pages + widget_add_button_element( + widget, GuiButtonTypeCenter, "", wifi_marauder_scene_log_viewer_widget_callback, app); + } else { + // only show "Browse" text on first and last page + widget_add_button_element( + widget, + GuiButtonTypeCenter, + "Browse", + wifi_marauder_scene_log_viewer_widget_callback, + app); + } + + char pagecounter[100]; + snprintf( + pagecounter, + sizeof(pagecounter), + "%d/%d", + app->open_log_file_page, + app->open_log_file_num_pages); + if(app->open_log_file_page > 1) { + if(app->open_log_file_page == app->open_log_file_num_pages) { + // only show left side page-count on last page + widget_add_button_element( + widget, + GuiButtonTypeLeft, + pagecounter, + wifi_marauder_scene_log_viewer_widget_callback, + app); + } else { + widget_add_button_element( + widget, GuiButtonTypeLeft, "", wifi_marauder_scene_log_viewer_widget_callback, app); + } + } + if(app->open_log_file_page < app->open_log_file_num_pages) { + widget_add_button_element( + widget, + GuiButtonTypeRight, + pagecounter, + wifi_marauder_scene_log_viewer_widget_callback, + app); + } +} + +void wifi_marauder_scene_log_viewer_on_enter(void* context) { + WifiMarauderApp* app = context; + + app->open_log_file_page = 0; + app->open_log_file_num_pages = 0; + bool saved_logs_exist = false; + if(!app->has_saved_logs_this_session && furi_string_empty(app->text_box_store)) { + // no commands sent yet this session, find last saved log + if(storage_dir_open(app->log_file, MARAUDER_APP_FOLDER_LOGS)) { + char name[70]; + char lastname[70]; + while(storage_dir_read(app->log_file, NULL, name, sizeof(name))) { + // keep reading directory until last file is reached + strlcpy(lastname, name, sizeof(lastname)); + saved_logs_exist = true; + } + if(saved_logs_exist) { + snprintf( + app->log_file_path, + sizeof(app->log_file_path), + "%s/%s", + MARAUDER_APP_FOLDER_LOGS, + lastname); + } + } + storage_dir_close(app->log_file); + } + + wifi_marauder_scene_log_viewer_setup_widget(app, saved_logs_exist); + + view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget); +} + +bool wifi_marauder_scene_log_viewer_on_event(void* context, SceneManagerEvent event) { + WifiMarauderApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeCenter) { + // Browse + FuriString* predefined_filepath = furi_string_alloc_set_str(MARAUDER_APP_FOLDER_LOGS); + FuriString* selected_filepath = furi_string_alloc(); + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, NULL)) { + strncpy( + app->log_file_path, + furi_string_get_cstr(selected_filepath), + sizeof(app->log_file_path)); + if(storage_file_is_open(app->log_file)) { + storage_file_close(app->log_file); + } + wifi_marauder_scene_log_viewer_setup_widget(app, true); + } + furi_string_free(selected_filepath); + furi_string_free(predefined_filepath); + consumed = true; + } else if(event.event == GuiButtonTypeRight) { + // Advance page + ++app->open_log_file_page; + wifi_marauder_scene_log_viewer_setup_widget(app, false); + } else if(event.event == GuiButtonTypeLeft) { + // Previous page + --app->open_log_file_page; + wifi_marauder_scene_log_viewer_setup_widget(app, false); + } + } + + return consumed; +} + +void wifi_marauder_scene_log_viewer_on_exit(void* context) { + WifiMarauderApp* app = context; + widget_reset(app->widget); + if(storage_file_is_open(app->log_file)) { + storage_file_close(app->log_file); + } +} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_settings_init.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_settings_init.c new file mode 100644 index 000000000..04d099d12 --- /dev/null +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_settings_init.c @@ -0,0 +1,130 @@ +#include "../wifi_marauder_app_i.h" + +const char* Y = "Y"; +const char* N = "N"; + +#define PROMPT_PCAPS 0 +#define PROMPT_LOGS 1 + +void wifi_marauder_scene_settings_init_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + WifiMarauderApp* app = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(app->view_dispatcher, result); + } +} + +void wifi_marauder_scene_settings_init_setup_widget(WifiMarauderApp* app) { + Widget* widget = app->widget; + + widget_reset(widget); + + widget_add_button_element( + widget, GuiButtonTypeLeft, "No", wifi_marauder_scene_settings_init_widget_callback, app); + widget_add_button_element( + widget, GuiButtonTypeRight, "Yes", wifi_marauder_scene_settings_init_widget_callback, app); + + if(app->which_prompt == PROMPT_PCAPS) { + widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Save pcaps?"); + widget_add_text_scroll_element( + widget, + 0, + 12, + 128, + 38, + "With compatible marauder\nfirmware, you can choose to\nsave captures (pcaps) to the\nflipper sd card here:\n" MARAUDER_APP_FOLDER_USER_PCAPS + "\n\nYou can change this setting in the app at any time. Would\nyou like to enable this feature now?"); + } else { + widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Save logs?"); + widget_add_text_scroll_element( + widget, + 0, + 12, + 128, + 38, + "This app supports saving text\nlogs of console output to the\nflipper sd card here:\n" MARAUDER_APP_FOLDER_USER_LOGS + "\n\nYou can change this setting in the app at any time. Would\nyou like to enable this feature now?"); + } +} + +void wifi_marauder_scene_settings_init_on_enter(void* context) { + WifiMarauderApp* app = context; + + app->which_prompt = PROMPT_PCAPS; + wifi_marauder_scene_settings_init_setup_widget(app); + + view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget); +} + +bool wifi_marauder_scene_settings_init_on_event(void* context, SceneManagerEvent event) { + WifiMarauderApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + // get which button press: "Yes" or "No" + if(event.event == GuiButtonTypeRight) { + // Yes + if(app->which_prompt == PROMPT_PCAPS) { + app->ok_to_save_pcaps = true; + } else { + app->ok_to_save_logs = true; + } + } else if(event.event == GuiButtonTypeLeft) { + // No + if(app->which_prompt == PROMPT_PCAPS) { + app->ok_to_save_pcaps = false; + } else { + app->ok_to_save_logs = false; + } + } + + // save setting to file, load next widget or scene + if(app->which_prompt == PROMPT_PCAPS) { + if(storage_file_open( + app->save_pcap_setting_file, + SAVE_PCAP_SETTING_FILEPATH, + FSAM_WRITE, + FSOM_CREATE_ALWAYS)) { + const char* ok = app->ok_to_save_pcaps ? Y : N; + storage_file_write(app->save_pcap_setting_file, ok, sizeof(ok)); + } else { + dialog_message_show_storage_error(app->dialogs, "Cannot save settings"); + } + storage_file_close(app->save_pcap_setting_file); + // same scene, different-looking widget + app->which_prompt = PROMPT_LOGS; + wifi_marauder_scene_settings_init_setup_widget(app); + } else { + if(storage_file_open( + app->save_logs_setting_file, + SAVE_LOGS_SETTING_FILEPATH, + FSAM_WRITE, + FSOM_CREATE_ALWAYS)) { + const char* ok = app->ok_to_save_logs ? Y : N; + storage_file_write(app->save_logs_setting_file, ok, sizeof(ok)); + } else { + dialog_message_show_storage_error(app->dialogs, "Cannot save settings"); + } + storage_file_close(app->save_logs_setting_file); + // go back to start scene (main menu) + app->need_to_prompt_settings_init = false; + scene_manager_previous_scene(app->scene_manager); + } + consumed = true; + } + + return consumed; +} + +void wifi_marauder_scene_settings_init_on_exit(void* context) { + WifiMarauderApp* app = context; + widget_reset(app->widget); + if(storage_file_is_open(app->save_pcap_setting_file)) { + storage_file_close(app->save_pcap_setting_file); + } + if(storage_file_is_open(app->save_logs_setting_file)) { + storage_file_close(app->save_logs_setting_file); + } +} diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index df759bd15..2b2ee3a8a 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -127,6 +127,13 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { {"Update", {"ota", "sd"}, 2, {"update -w", "update -s"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, {"Reboot", {""}, 1, {"reboot"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, + {"Save to flipper sdcard", // keep as last entry or change logic in callback below + {""}, + 1, + {""}, + NO_ARGS, + FOCUS_CONSOLE_START, + NO_TIP}, }; static void wifi_marauder_scene_start_var_list_enter_callback(void* context, uint32_t index) { @@ -136,6 +143,13 @@ static void wifi_marauder_scene_start_var_list_enter_callback(void* context, uin furi_assert(index < NUM_MENU_ITEMS); const WifiMarauderItem* item = &items[index]; + if(index == NUM_MENU_ITEMS - 1) { + // "Save to flipper sdcard" special case - start SettingsInit widget + view_dispatcher_send_custom_event( + app->view_dispatcher, WifiMarauderEventStartSettingsInit); + return; + } + const int selected_option_index = app->selected_option_index[index]; furi_assert(selected_option_index < item->num_options_menu); app->selected_tx_string = item->actual_commands[selected_option_index]; @@ -147,6 +161,12 @@ static void wifi_marauder_scene_start_var_list_enter_callback(void* context, uin item->focus_console; app->show_stopscan_tip = item->show_stopscan_tip; + if(!app->is_command && selected_option_index == 0) { + // View Log from start + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartLogViewer); + return; + } + bool needs_keyboard = (item->needs_keyboard == TOGGLE_ARGS) ? (selected_option_index != 0) : item->needs_keyboard; if(needs_keyboard) { @@ -193,6 +213,11 @@ void wifi_marauder_scene_start_on_enter(void* context) { var_item_list, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneStart)); view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); + + // Wait, if the user hasn't initialized sdcard settings, let's prompt them once (then come back here) + if(app->need_to_prompt_settings_init) { + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSettingsInit); + } } bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event) { @@ -204,16 +229,28 @@ bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event) if(event.event == WifiMarauderEventStartKeyboard) { scene_manager_set_scene_state( app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewTextInput); + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput); } else if(event.event == WifiMarauderEventStartConsole) { scene_manager_set_scene_state( app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); - scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput); + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); + } else if(event.event == WifiMarauderEventStartSettingsInit) { + scene_manager_set_scene_state( + app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSettingsInit); + } else if(event.event == WifiMarauderEventStartLogViewer) { + scene_manager_set_scene_state( + app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneLogViewer); } consumed = true; } else if(event.type == SceneManagerEventTypeTick) { app->selected_menu_index = variable_item_list_get_selected_item_index(app->var_item_list); consumed = true; + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_stop(app->scene_manager); + view_dispatcher_stop(app->view_dispatcher); + consumed = true; } return consumed; diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c index ac8b15a2d..b721e868d 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c @@ -80,7 +80,7 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev if(event.event == WifiMarauderEventStartConsole) { // Point to custom string to send app->selected_tx_string = app->text_input_store; - scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput); + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); consumed = true; } else if(event.event == WifiMarauderEventSaveSourceMac) { if(12 != strlen(app->text_input_store)) { @@ -138,7 +138,7 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev app->special_case_input_src_addr, app->special_case_input_dst_addr); app->selected_tx_string = app->text_input_store; - scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput); + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); } consumed = true; } diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.c b/applications/external/wifi_marauder_companion/wifi_marauder_app.c index 7563d927a..a5521d49a 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.c +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.c @@ -28,6 +28,9 @@ WifiMarauderApp* wifi_marauder_app_alloc() { app->dialogs = furi_record_open(RECORD_DIALOGS); app->storage = furi_record_open(RECORD_STORAGE); app->capture_file = storage_file_alloc(app->storage); + app->log_file = storage_file_alloc(app->storage); + app->save_pcap_setting_file = storage_file_alloc(app->storage); + app->save_logs_setting_file = storage_file_alloc(app->storage); app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&wifi_marauder_scene_handlers, app); @@ -65,6 +68,17 @@ WifiMarauderApp* wifi_marauder_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, WifiMarauderAppViewTextInput, text_input_get_view(app->text_input)); + app->widget = widget_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, WifiMarauderAppViewWidget, widget_get_view(app->widget)); + + app->has_saved_logs_this_session = false; + + // if user hasn't confirmed whether to save pcaps and logs to sdcard, then prompt when scene starts + app->need_to_prompt_settings_init = + (!storage_file_exists(app->storage, SAVE_PCAP_SETTING_FILEPATH) || + !storage_file_exists(app->storage, SAVE_LOGS_SETTING_FILEPATH)); + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneStart); return app; @@ -76,6 +90,38 @@ void wifi_marauder_make_app_folder(WifiMarauderApp* app) { if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER)) { dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder"); } + + if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_PCAPS)) { + dialog_message_show_storage_error(app->dialogs, "Cannot create\npcaps folder"); + } + + if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_LOGS)) { + dialog_message_show_storage_error(app->dialogs, "Cannot create\npcaps folder"); + } +} + +void wifi_marauder_load_settings(WifiMarauderApp* app) { + if(storage_file_open( + app->save_pcap_setting_file, + SAVE_PCAP_SETTING_FILEPATH, + FSAM_READ, + FSOM_OPEN_EXISTING)) { + char ok[1]; + storage_file_read(app->save_pcap_setting_file, ok, sizeof(ok)); + app->ok_to_save_pcaps = ok[0] == 'Y'; + } + storage_file_close(app->save_pcap_setting_file); + + if(storage_file_open( + app->save_logs_setting_file, + SAVE_LOGS_SETTING_FILEPATH, + FSAM_READ, + FSOM_OPEN_EXISTING)) { + char ok[1]; + storage_file_read(app->save_logs_setting_file, ok, sizeof(ok)); + app->ok_to_save_logs = ok[0] == 'Y'; + } + storage_file_close(app->save_logs_setting_file); } void wifi_marauder_app_free(WifiMarauderApp* app) { @@ -85,10 +131,15 @@ void wifi_marauder_app_free(WifiMarauderApp* app) { view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput); view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewTextInput); + view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewWidget); + widget_free(app->widget); text_box_free(app->text_box); furi_string_free(app->text_box_store); text_input_free(app->text_input); storage_file_free(app->capture_file); + storage_file_free(app->log_file); + storage_file_free(app->save_pcap_setting_file); + storage_file_free(app->save_logs_setting_file); // View dispatcher view_dispatcher_free(app->view_dispatcher); @@ -118,6 +169,7 @@ int32_t wifi_marauder_app(void* p) { WifiMarauderApp* wifi_marauder_app = wifi_marauder_app_alloc(); wifi_marauder_make_app_folder(wifi_marauder_app); + wifi_marauder_load_settings(wifi_marauder_app); wifi_marauder_app->uart = wifi_marauder_usart_init(wifi_marauder_app); wifi_marauder_app->lp_uart = wifi_marauder_lp_uart_init(wifi_marauder_app); diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.h b/applications/external/wifi_marauder_companion/wifi_marauder_app.h index 92dd1dbd9..89a06f904 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.h @@ -4,7 +4,7 @@ extern "C" { #endif -#define WIFI_MARAUDER_APP_VERSION "v0.3.1" +#define WIFI_MARAUDER_APP_VERSION "v0.3.3" typedef struct WifiMarauderApp WifiMarauderApp; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h index 1165c6d9d..39b48fae3 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h @@ -14,16 +14,24 @@ #include #include #include +#include #include #include -#define NUM_MENU_ITEMS (16) +#define NUM_MENU_ITEMS (17) #define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) #define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512) -#define MARAUDER_APP_FOLDER EXT_PATH("apps_data/marauder") +#define MARAUDER_APP_FOLDER_USER "apps_data/marauder" +#define MARAUDER_APP_FOLDER EXT_PATH(MARAUDER_APP_FOLDER_USER) +#define MARAUDER_APP_FOLDER_PCAPS MARAUDER_APP_FOLDER "/pcaps" +#define MARAUDER_APP_FOLDER_LOGS MARAUDER_APP_FOLDER "/logs" +#define MARAUDER_APP_FOLDER_USER_PCAPS MARAUDER_APP_FOLDER_USER "/pcaps" +#define MARAUDER_APP_FOLDER_USER_LOGS MARAUDER_APP_FOLDER_USER "/logs" +#define SAVE_PCAP_SETTING_FILEPATH MARAUDER_APP_FOLDER "/save_pcaps_here.setting" +#define SAVE_LOGS_SETTING_FILEPATH MARAUDER_APP_FOLDER "/save_logs_here.setting" struct WifiMarauderApp { Gui* gui; @@ -37,9 +45,21 @@ struct WifiMarauderApp { TextInput* text_input; Storage* storage; File* capture_file; + File* log_file; + char log_file_path[100]; + File* save_pcap_setting_file; + File* save_logs_setting_file; + bool need_to_prompt_settings_init; + int which_prompt; + bool ok_to_save_pcaps; + bool ok_to_save_logs; + bool has_saved_logs_this_session; DialogsApp* dialogs; VariableItemList* var_item_list; + Widget* widget; + int open_log_file_page; + int open_log_file_num_pages; WifiMarauderUart* uart; WifiMarauderUart* lp_uart; @@ -50,7 +70,8 @@ struct WifiMarauderApp { bool is_custom_tx_string; bool focus_console_start; bool show_stopscan_tip; - bool is_writing; + bool is_writing_pcap; + bool is_writing_log; // For input source and destination MAC in targeted deauth attack int special_case_input_step; @@ -83,4 +104,5 @@ typedef enum { WifiMarauderAppViewVarItemList, WifiMarauderAppViewConsoleOutput, WifiMarauderAppViewTextInput, + WifiMarauderAppViewWidget, } WifiMarauderAppView; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h b/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h index 990b457f5..79f96b107 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h @@ -5,5 +5,7 @@ typedef enum { WifiMarauderEventStartConsole, WifiMarauderEventStartKeyboard, WifiMarauderEventSaveSourceMac, - WifiMarauderEventSaveDestinationMac + WifiMarauderEventSaveDestinationMac, + WifiMarauderEventStartSettingsInit, + WifiMarauderEventStartLogViewer } WifiMarauderCustomEvent; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_pcap.c b/applications/external/wifi_marauder_companion/wifi_marauder_pcap.c index fc5f39022..73e3d98ea 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_pcap.c +++ b/applications/external/wifi_marauder_companion/wifi_marauder_pcap.c @@ -1,7 +1,7 @@ #include "wifi_marauder_app_i.h" #include "wifi_marauder_pcap.h" -void wifi_marauder_get_prefix_from_cmd(char* dest, const char* command) { +void wifi_marauder_get_prefix_from_sniff_cmd(char* dest, const char* command) { int start, end, delta; start = strlen("sniff"); end = strcspn(command, " "); @@ -10,10 +10,17 @@ void wifi_marauder_get_prefix_from_cmd(char* dest, const char* command) { dest[delta] = '\0'; } +void wifi_marauder_get_prefix_from_cmd(char* dest, const char* command) { + int end; + end = strcspn(command, " "); + strncpy(dest, command, end); + dest[end] = '\0'; +} + void wifi_marauder_create_pcap_file(WifiMarauderApp* app) { char prefix[10]; char capture_file_path[100]; - wifi_marauder_get_prefix_from_cmd(prefix, app->selected_tx_string); + wifi_marauder_get_prefix_from_sniff_cmd(prefix, app->selected_tx_string); int i = 0; do { @@ -21,7 +28,7 @@ void wifi_marauder_create_pcap_file(WifiMarauderApp* app) { capture_file_path, sizeof(capture_file_path), "%s/%s_%d.pcap", - MARAUDER_APP_FOLDER, + MARAUDER_APP_FOLDER_PCAPS, prefix, i); i++; @@ -30,4 +37,28 @@ void wifi_marauder_create_pcap_file(WifiMarauderApp* app) { if(!storage_file_open(app->capture_file, capture_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { dialog_message_show_storage_error(app->dialogs, "Cannot open pcap file"); } +} + +void wifi_marauder_create_log_file(WifiMarauderApp* app) { + char prefix[10]; + char log_file_path[100]; + wifi_marauder_get_prefix_from_cmd(prefix, app->selected_tx_string); + + int i = 0; + do { + snprintf( + log_file_path, + sizeof(log_file_path), + "%s/%s_%d.log", + MARAUDER_APP_FOLDER_LOGS, + prefix, + i); + i++; + } while(storage_file_exists(app->storage, log_file_path)); + + if(!storage_file_open(app->log_file, log_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); + } else { + strcpy(app->log_file_path, log_file_path); + } } \ No newline at end of file diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_pcap.h b/applications/external/wifi_marauder_companion/wifi_marauder_pcap.h index 29f8fcf8a..94f6282f3 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_pcap.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_pcap.h @@ -8,4 +8,13 @@ * * @param app Application context */ -void wifi_marauder_create_pcap_file(WifiMarauderApp* app); \ No newline at end of file +void wifi_marauder_create_pcap_file(WifiMarauderApp* app); + +/** + * Creates a log file to store text from console output. + * The file name will have a prefix according to the command being performed by the application (Eg: scanap_0.log) + * + * @param app Application context + */ +// same as wifi_marauder_create_pcap_file, but for log files (to save console text output) +void wifi_marauder_create_log_file(WifiMarauderApp* app); diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_uart.h b/applications/external/wifi_marauder_companion/wifi_marauder_uart.h index 4835d52ce..e352cfec5 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_uart.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_uart.h @@ -2,7 +2,7 @@ #include "furi_hal.h" -#define RX_BUF_SIZE (320) +#define RX_BUF_SIZE (2048) typedef struct WifiMarauderUart WifiMarauderUart;