wifi_marauder_scene_console_output.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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. strcpy(
  118. app->log_file_path,
  119. sequential_file_resolve_path(
  120. app->storage, MARAUDER_APP_FOLDER_LOGS, prefix, "log"));
  121. if(storage_file_open(
  122. app->log_file, app->log_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
  123. app->is_writing_log = true;
  124. } else {
  125. dialog_message_show_storage_error(app->dialogs, "Cannot open log file");
  126. }
  127. }
  128. // If it is a sniff/wardrive/btwardrive/evilportal function or script, open the capture file for recording
  129. if(_wifi_marauder_is_saving_enabled(app)) {
  130. const char* folder = NULL;
  131. const char* extension = NULL;
  132. if(app->script || // Scripts only support sniff functions, but selected_tx_string is empty
  133. strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0) {
  134. folder = MARAUDER_APP_FOLDER_PCAPS;
  135. extension = "pcap";
  136. } else {
  137. folder = MARAUDER_APP_FOLDER_DUMPS;
  138. extension = "txt";
  139. }
  140. if(sequential_file_open(app->storage, app->capture_file, folder, prefix, extension)) {
  141. app->is_writing_pcap = true;
  142. } else {
  143. dialog_message_show_storage_error(app->dialogs, "Cannot open capture file");
  144. }
  145. }
  146. bool send_html = false;
  147. uint8_t* the_html = NULL;
  148. size_t html_size = 0;
  149. if(app->selected_tx_string && strncmp(
  150. "evilportal -c sethtmlstr",
  151. app->selected_tx_string,
  152. strlen("evilportal -c sethtmlstr")) == 0) {
  153. send_html = wifi_marauder_ep_read_html_file(app, &the_html, &html_size);
  154. }
  155. // Send command with newline '\n'
  156. if(app->selected_tx_string) {
  157. if(app->script == NULL) {
  158. wifi_marauder_uart_tx(
  159. app->uart,
  160. (uint8_t*)(app->selected_tx_string),
  161. strlen(app->selected_tx_string));
  162. if(app->is_writing_pcap) {
  163. wifi_marauder_uart_tx(
  164. app->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n"));
  165. } else {
  166. wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1);
  167. }
  168. }
  169. if(send_html && the_html) {
  170. wifi_marauder_uart_tx(app->uart, the_html, html_size);
  171. wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1);
  172. free(the_html);
  173. send_html = false;
  174. }
  175. }
  176. // Run the script if the file with the script has been opened
  177. if(app->script != NULL) {
  178. app->script_worker = wifi_marauder_script_worker_alloc(app->uart);
  179. wifi_marauder_script_worker_start(app->script_worker, app->script);
  180. }
  181. if(prefix_buf) {
  182. free(prefix_buf);
  183. }
  184. }
  185. }
  186. bool wifi_marauder_scene_console_output_on_event(void* context, SceneManagerEvent event) {
  187. WifiMarauderApp* app = context;
  188. bool consumed = false;
  189. if(event.type == SceneManagerEventTypeCustom) {
  190. text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
  191. consumed = true;
  192. } else if(event.type == SceneManagerEventTypeTick) {
  193. consumed = true;
  194. }
  195. return consumed;
  196. }
  197. void wifi_marauder_scene_console_output_on_exit(void* context) {
  198. WifiMarauderApp* app = context;
  199. // Automatically stop the scan when exiting view
  200. if(app->is_command) {
  201. wifi_marauder_uart_tx(app->uart, (uint8_t*)("stopscan\n"), strlen("stopscan\n"));
  202. furi_delay_ms(50);
  203. }
  204. // Unregister rx callback
  205. wifi_marauder_uart_set_handle_rx_data_cb(app->uart, NULL);
  206. wifi_marauder_uart_set_handle_rx_pcap_cb(app->uart, NULL);
  207. if(app->script_worker) {
  208. wifi_marauder_script_worker_free(app->script_worker);
  209. app->script_worker = NULL;
  210. }
  211. app->is_writing_pcap = false;
  212. if(app->capture_file && storage_file_is_open(app->capture_file)) {
  213. storage_file_close(app->capture_file);
  214. }
  215. app->is_writing_log = false;
  216. if(app->log_file && storage_file_is_open(app->log_file)) {
  217. storage_file_close(app->log_file);
  218. }
  219. }