wifi_marauder_scene_console_output.c 9.9 KB

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