wifi_marauder_scene_console_output.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include "../wifi_marauder_app_i.h"
  2. char* _wifi_marauder_get_prefix_from_cmd(const char* command) {
  3. int end = strcspn(command, " ");
  4. char* prefix = (char*)malloc(sizeof(char) * (end + 1));
  5. strncpy(prefix, command, end);
  6. prefix[end] = '\0';
  7. return prefix;
  8. }
  9. bool _wifi_marauder_is_saving_enabled(WifiMarauderApp* app) {
  10. // If it is a script that contains a sniff function
  11. if(app->script != NULL) {
  12. if(app->script->save_pcap == WifiMarauderScriptBooleanFalse) {
  13. return false;
  14. }
  15. if(app->script->save_pcap == WifiMarauderScriptBooleanUndefined) {
  16. if(!app->ok_to_save_pcaps) {
  17. return false;
  18. }
  19. }
  20. return wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffRaw) ||
  21. wifi_marauder_script_has_stage(
  22. app->script, WifiMarauderScriptStageTypeSniffBeacon) ||
  23. wifi_marauder_script_has_stage(
  24. app->script, WifiMarauderScriptStageTypeSniffDeauth) ||
  25. wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffEsp) ||
  26. wifi_marauder_script_has_stage(
  27. app->script, WifiMarauderScriptStageTypeSniffPmkid) ||
  28. wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffPwn);
  29. }
  30. if(!app->ok_to_save_pcaps) {
  31. return false;
  32. }
  33. // If it is a sniff/wardrive/btwardrive/evilportal function
  34. return app->is_command && app->selected_tx_string &&
  35. (strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0 ||
  36. strncmp("wardrive", app->selected_tx_string, strlen("wardrive")) == 0 ||
  37. strncmp("btwardrive", app->selected_tx_string, strlen("btwardrive")) == 0 ||
  38. strncmp("evilportal", app->selected_tx_string, strlen("evilportal")) == 0);
  39. }
  40. void wifi_marauder_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
  41. furi_assert(context);
  42. WifiMarauderApp* app = context;
  43. if(app->is_writing_log) {
  44. app->has_saved_logs_this_session = true;
  45. storage_file_write(app->log_file, buf, len);
  46. }
  47. // If text box store gets too big, then truncate it
  48. app->text_box_store_strlen += len;
  49. if(app->text_box_store_strlen >= WIFI_MARAUDER_TEXT_BOX_STORE_SIZE - 1) {
  50. furi_string_right(app->text_box_store, app->text_box_store_strlen / 2);
  51. app->text_box_store_strlen = furi_string_size(app->text_box_store) + len;
  52. }
  53. // Null-terminate buf and append to text box store
  54. buf[len] = '\0';
  55. furi_string_cat_printf(app->text_box_store, "%s", buf);
  56. view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshConsoleOutput);
  57. }
  58. void wifi_marauder_console_output_handle_rx_packets_cb(uint8_t* buf, size_t len, void* context) {
  59. furi_assert(context);
  60. WifiMarauderApp* app = context;
  61. if(app->is_writing_pcap) {
  62. storage_file_write(app->capture_file, buf, len);
  63. }
  64. }
  65. void wifi_marauder_scene_console_output_on_enter(void* context) {
  66. WifiMarauderApp* app = context;
  67. // Reset text box and set font
  68. TextBox* text_box = app->text_box;
  69. text_box_reset(text_box);
  70. text_box_set_font(text_box, TextBoxFontText);
  71. // Set focus on start or end
  72. if(app->focus_console_start) {
  73. text_box_set_focus(text_box, TextBoxFocusStart);
  74. } else {
  75. text_box_set_focus(text_box, TextBoxFocusEnd);
  76. }
  77. // Set command-related messages
  78. if(app->is_command) {
  79. furi_string_reset(app->text_box_store);
  80. app->text_box_store_strlen = 0;
  81. // Help message
  82. if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
  83. const char* help_msg = "Marauder companion " WIFI_MARAUDER_APP_VERSION "\n";
  84. furi_string_cat_str(app->text_box_store, help_msg);
  85. app->text_box_store_strlen += strlen(help_msg);
  86. }
  87. // Stopscan message
  88. if(app->show_stopscan_tip) {
  89. const char* help_msg = "Press BACK to send stopscan\n";
  90. furi_string_cat_str(app->text_box_store, help_msg);
  91. app->text_box_store_strlen += strlen(help_msg);
  92. }
  93. }
  94. // Set starting text
  95. text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
  96. // Set scene state and switch view
  97. scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneConsoleOutput, 0);
  98. view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput);
  99. // Register callbacks to receive data
  100. wifi_marauder_uart_set_handle_rx_data_cb(
  101. app->uart,
  102. wifi_marauder_console_output_handle_rx_data_cb); // setup callback for general log rx thread
  103. wifi_marauder_uart_set_handle_rx_pcap_cb(
  104. app->uart,
  105. wifi_marauder_console_output_handle_rx_packets_cb); // setup callback for packets rx thread
  106. // Get ready to send command
  107. if((app->is_command && app->selected_tx_string) || app->script) {
  108. char* prefix_buf = NULL;
  109. if(strlen(app->selected_tx_string) > 0) {
  110. prefix_buf = _wifi_marauder_get_prefix_from_cmd(app->selected_tx_string);
  111. }
  112. const char* prefix = prefix_buf ? prefix_buf : // Function name
  113. app->script->name; // Script name
  114. // Create files *before* sending command
  115. // (it takes time to iterate through the directory)
  116. if(app->ok_to_save_logs) {
  117. char* resolved_path = sequential_file_resolve_path(app->storage, MARAUDER_APP_FOLDER_LOGS, prefix, "log");
  118. if(resolved_path != NULL) {
  119. strcpy(app->log_file_path, resolved_path);
  120. free(resolved_path);
  121. if(storage_file_open(app->log_file, app->log_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
  122. app->is_writing_log = true;
  123. } else {
  124. dialog_message_show_storage_error(app->dialogs, "Cannot open log file");
  125. }
  126. } else {
  127. dialog_message_show_storage_error(app->dialogs, "Cannot resolve log path");
  128. }
  129. }
  130. // If it is a sniff/wardrive/btwardrive/evilportal function or script, open the capture file for recording
  131. if(_wifi_marauder_is_saving_enabled(app)) {
  132. const char* folder = NULL;
  133. const char* extension = NULL;
  134. if(app->script || // Scripts only support sniff functions, but selected_tx_string is empty
  135. strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0) {
  136. folder = MARAUDER_APP_FOLDER_PCAPS;
  137. extension = "pcap";
  138. } else {
  139. folder = MARAUDER_APP_FOLDER_DUMPS;
  140. extension = "txt";
  141. }
  142. if(sequential_file_open(app->storage, app->capture_file, folder, prefix, extension)) {
  143. app->is_writing_pcap = true;
  144. } else {
  145. dialog_message_show_storage_error(app->dialogs, "Cannot open capture file");
  146. }
  147. }
  148. bool send_html = false;
  149. uint8_t* the_html = NULL;
  150. size_t html_size = 0;
  151. if(app->selected_tx_string && strncmp(
  152. "evilportal -c sethtmlstr",
  153. app->selected_tx_string,
  154. strlen("evilportal -c sethtmlstr")) == 0) {
  155. send_html = wifi_marauder_ep_read_html_file(app, &the_html, &html_size);
  156. }
  157. // Send command with newline '\n'
  158. if(app->selected_tx_string) {
  159. if(app->script == NULL) {
  160. wifi_marauder_uart_tx(
  161. app->uart,
  162. (uint8_t*)(app->selected_tx_string),
  163. strlen(app->selected_tx_string));
  164. if(app->is_writing_pcap) {
  165. wifi_marauder_uart_tx(
  166. app->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n"));
  167. } else {
  168. wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1);
  169. }
  170. }
  171. if(send_html && the_html) {
  172. wifi_marauder_uart_tx(app->uart, the_html, html_size);
  173. wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1);
  174. free(the_html);
  175. send_html = false;
  176. }
  177. }
  178. // Run the script if the file with the script has been opened
  179. if(app->script != NULL) {
  180. app->script_worker = wifi_marauder_script_worker_alloc(app->uart);
  181. wifi_marauder_script_worker_start(app->script_worker, app->script);
  182. }
  183. if(prefix_buf) {
  184. free(prefix_buf);
  185. }
  186. }
  187. }
  188. bool wifi_marauder_scene_console_output_on_event(void* context, SceneManagerEvent event) {
  189. WifiMarauderApp* app = context;
  190. bool consumed = false;
  191. if(event.type == SceneManagerEventTypeCustom) {
  192. text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
  193. consumed = true;
  194. } else if(event.type == SceneManagerEventTypeTick) {
  195. consumed = true;
  196. }
  197. return consumed;
  198. }
  199. void wifi_marauder_scene_console_output_on_exit(void* context) {
  200. WifiMarauderApp* app = context;
  201. // Automatically stop the scan when exiting view
  202. if(app->is_command) {
  203. wifi_marauder_uart_tx(app->uart, (uint8_t*)("stopscan\n"), strlen("stopscan\n"));
  204. furi_delay_ms(50);
  205. }
  206. // Unregister rx callback
  207. wifi_marauder_uart_set_handle_rx_data_cb(app->uart, NULL);
  208. wifi_marauder_uart_set_handle_rx_pcap_cb(app->uart, NULL);
  209. if(app->script_worker) {
  210. wifi_marauder_script_worker_free(app->script_worker);
  211. app->script_worker = NULL;
  212. }
  213. app->is_writing_pcap = false;
  214. if(app->capture_file && storage_file_is_open(app->capture_file)) {
  215. storage_file_close(app->capture_file);
  216. }
  217. app->is_writing_log = false;
  218. if(app->log_file && storage_file_is_open(app->log_file)) {
  219. storage_file_close(app->log_file);
  220. }
  221. }