├── .github ├── FUNDING.yml └── workflows │ └── build.yml ├── LICENSE ├── ReadMe.md ├── application.fam ├── assets ├── DolphinCommon_56x48.png ├── KeyBackspaceSelected_16x9.png ├── KeyBackspace_16x9.png ├── KeyKeyboardSelected_10x11.png ├── KeyKeyboard_10x11.png ├── KeySaveSelected_24x11.png ├── KeySave_24x11.png ├── Text_10x10.png └── WarningDolphin_45x42.png ├── docs ├── README.md └── changelog.md ├── file ├── sequential_file.c └── sequential_file.h ├── scenes ├── wifi_marauder_scene.c ├── wifi_marauder_scene.h ├── wifi_marauder_scene_config.h ├── wifi_marauder_scene_console_output.c ├── wifi_marauder_scene_log_viewer.c ├── wifi_marauder_scene_script_confirm_delete.c ├── wifi_marauder_scene_script_edit.c ├── wifi_marauder_scene_script_edit_list.c ├── wifi_marauder_scene_script_options.c ├── wifi_marauder_scene_script_select.c ├── wifi_marauder_scene_script_settings.c ├── wifi_marauder_scene_script_stage_add.c ├── wifi_marauder_scene_script_stage_edit.c ├── wifi_marauder_scene_settings_init.c ├── wifi_marauder_scene_sniffpmkid_options.c ├── wifi_marauder_scene_start.c ├── wifi_marauder_scene_text_input.c └── wifi_marauder_scene_user_input.c ├── screenshots ├── marauder-save-pcaps.png ├── marauder-script-demo.png └── marauder-topmenu.png ├── script ├── cJSON.c ├── cJSON.h ├── menu │ ├── wifi_marauder_script_stage_menu.c │ ├── wifi_marauder_script_stage_menu.h │ ├── wifi_marauder_script_stage_menu_beaconap.c │ ├── wifi_marauder_script_stage_menu_beaconlist.c │ ├── wifi_marauder_script_stage_menu_config.h │ ├── wifi_marauder_script_stage_menu_deauth.c │ ├── wifi_marauder_script_stage_menu_delay.c │ ├── wifi_marauder_script_stage_menu_exec.c │ ├── wifi_marauder_script_stage_menu_probe.c │ ├── wifi_marauder_script_stage_menu_scan.c │ ├── wifi_marauder_script_stage_menu_select.c │ ├── wifi_marauder_script_stage_menu_sniffbeacon.c │ ├── wifi_marauder_script_stage_menu_sniffdeauth.c │ ├── wifi_marauder_script_stage_menu_sniffesp.c │ ├── wifi_marauder_script_stage_menu_sniffpmkid.c │ ├── wifi_marauder_script_stage_menu_sniffpwn.c │ └── wifi_marauder_script_stage_menu_sniffraw.c ├── wifi_marauder_script.c ├── wifi_marauder_script.h ├── wifi_marauder_script_executor.c ├── wifi_marauder_script_executor.h ├── wifi_marauder_script_worker.c └── wifi_marauder_script_worker.h ├── wifi_10px.png ├── wifi_marauder_app.c ├── wifi_marauder_app.h ├── wifi_marauder_app_i.h ├── wifi_marauder_custom_event.h ├── wifi_marauder_ep.c ├── wifi_marauder_ep.h ├── wifi_marauder_text_input.c ├── wifi_marauder_text_input.h ├── wifi_marauder_uart.c ├── wifi_marauder_uart.h ├── wifi_marauder_validators.c └── wifi_marauder_validators.h /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: cococode 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "FAP Build" 2 | on: 3 | push: 4 | branches: 5 | - feature_wifi_marauder_app 6 | pull_request: 7 | schedule: 8 | # do a build every day 9 | - cron: "1 1 * * *" 10 | jobs: 11 | ufbt-build-action: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | include: 16 | - name: dev channel 17 | sdk-channel: dev 18 | - name: release channel 19 | sdk-channel: release 20 | - name: Unleashed dev 21 | sdk-index-url: https://up.unleashedflip.com/directory.json 22 | sdk-channel: dev 23 | - name: Unleashed release 24 | sdk-index-url: https://up.unleashedflip.com/directory.json 25 | sdk-channel: release 26 | name: 'ufbt: Build for ${{ matrix.name }}' 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v3 30 | with: 31 | submodules: recursive 32 | - name: Build with ufbt 33 | uses: flipperdevices/flipperzero-ufbt-action@v0.1.2 34 | id: build-app 35 | with: 36 | sdk-channel: ${{ matrix.sdk-channel }} 37 | sdk-index-url: ${{ matrix.sdk-index-url }} 38 | - name: Upload app artifacts 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: ${{ github.event.repository.name }}-${{ steps.build-app.outputs.suffix }} 42 | path: ${{ steps.build-app.outputs.fap-artifacts }} 43 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | [![FAP Build](https://github.com/0xchocolate/flipperzero-wifi-marauder/actions/workflows/build.yml/badge.svg)](https://github.com/0xchocolate/flipperzero-wifi-marauder/actions/workflows/build.yml) 2 | 3 | # WiFi Marauder companion app for Flipper Zero 4 | 5 | Requires a connected dev board running Marauder FW. [See install instructions from UberGuidoZ here.](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard#marauder-install-information) 6 | 7 | 8 | 9 | ## Get the app 10 | 1. Make sure you're logged in with a github account (otherwise the downloads in step 2 won't work) 11 | 2. Navigate to the [FAP Build](https://github.com/0xchocolate/flipperzero-wifi-marauder/actions/workflows/build.yml) 12 | GitHub action workflow, and select the most recent run, scroll down to artifacts. 13 | 3. The FAP is built for the `dev` and `release` channels of both official and unleashed 14 | firmware. Download the artifact corresponding to your firmware version. 15 | 4. (Optional step to avoid confusion) Go to "Apps/GPIO" on the Flipper SD Card, delete any existing Marauder app, on some firmwares there will be a `ESP32CAM_Marauder.fap` or similar. 16 | 5. Extract `esp32_wifi_marauder.fap` from the ZIP file downloaded in step 3 to your Flipper Zero SD card, preferably under Apps/GPIO along with the rest of the GPIO apps. (If you're using qFlipper to transfer files you need to extract the content of the ZIP file to your computer before you drag it to qFlipper, as qFlipper does not support direct dragging from a ZIP file (at least on Windows)). 17 | 18 | From a local clone of this repo, you can also build the app yourself using ufbt. 19 | 20 | ### FYI - the ESP flasher is now its own app: https://github.com/0xchocolate/flipperzero-esp-flasher 21 | 22 | 23 | ## Support 24 | 25 | For app feedback, bugs, and feature requests, please [create an issue here](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion/issues). 26 | 27 | You can find me (0xchocolate) on discord as @cococode. 28 | 29 | If you'd like to donate to the app development effort: 30 | 31 | [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/O4O1R7X6K) 32 | 33 | **ETH**: `0xf32A1F0CD6122C97d8953183E53cB889cc087C9b` 34 | **BTC**: `bc1qtw7s25cwdkuaups22yna8sttfxn0usm2f35wc3` 35 | 36 | Find more info about Marauder and support its developer (justcallmekoko aka WillStunForFood) here: https://github.com/justcallmekoko/ESP32Marauder 37 | 38 | If you found the app preinstalled in a firmware release, consider supporting the maintainers! 39 | -------------------------------------------------------------------------------- /application.fam: -------------------------------------------------------------------------------- 1 | App( 2 | appid="esp32_wifi_marauder", 3 | name="[ESP32] WiFi Marauder", 4 | fap_version=(7, 2), 5 | apptype=FlipperAppType.EXTERNAL, 6 | entry_point="wifi_marauder_app", 7 | requires=["gui"], 8 | stack_size=4 * 1024, 9 | order=90, 10 | fap_icon="wifi_10px.png", 11 | fap_category="GPIO", 12 | fap_icon_assets="assets", 13 | ) 14 | -------------------------------------------------------------------------------- /assets/DolphinCommon_56x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/DolphinCommon_56x48.png -------------------------------------------------------------------------------- /assets/KeyBackspaceSelected_16x9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/KeyBackspaceSelected_16x9.png -------------------------------------------------------------------------------- /assets/KeyBackspace_16x9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/KeyBackspace_16x9.png -------------------------------------------------------------------------------- /assets/KeyKeyboardSelected_10x11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/KeyKeyboardSelected_10x11.png -------------------------------------------------------------------------------- /assets/KeyKeyboard_10x11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/KeyKeyboard_10x11.png -------------------------------------------------------------------------------- /assets/KeySaveSelected_24x11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/KeySaveSelected_24x11.png -------------------------------------------------------------------------------- /assets/KeySave_24x11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/KeySave_24x11.png -------------------------------------------------------------------------------- /assets/Text_10x10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/Text_10x10.png -------------------------------------------------------------------------------- /assets/WarningDolphin_45x42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/assets/WarningDolphin_45x42.png -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ## WiFi Marauder companion app for Flipper Zero 2 | 3 | Requires a connected dev board running Marauder FW. See install instructions from UberGuidoZ here: https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard#marauder-install-information 4 | 5 | ## Support 6 | 7 | For app feedback, bugs, and feature requests, please create an issue here: https://github.com/0xchocolate/flipperzero-wifi-marauder/issues 8 | 9 | You can find me (0xchocolate) on discord as @cococode. 10 | -------------------------------------------------------------------------------- /docs/changelog.md: -------------------------------------------------------------------------------- 1 | ## v0.7.2 2 | 3 | Thanks to @justcallmekoko for adding app support for the new features in Marauder firmware v1.1.0! See the additions and grab the firmware for your wifi board here: https://github.com/justcallmekoko/ESP32Marauder/releases/tag/v1.1.0 4 | 5 | <3 @0xchocolate (cococode) 6 | 7 | 8 | ## v0.7.1 9 | 10 | Bug fixes and improvements! 11 | 12 | - Back to working on latest official firmware ( @GeorgeBotsev ) 13 | - Now the Evil Portal and wardrive dumps will be saved to a new directory apps_data/marauder/dumps, and the "-serial" argument for all commands will respect your "save pcaps" app setting ( @Willy-JL ) 14 | - You'll also notice an apps_data/marauder/html directory, to support migrating from the standalone Evil Portal ( @RogueMaster ) 15 | - Fixes an issue with loading scripts due to upstream toolchain changes ( @Willy-JL , @vollukas ) 16 | 17 | As always, make sure you're running the latest version of Marauder FW on your wifi board: https://github.com/justcallmekoko/ESP32Marauder/releases/latest 18 | 19 | <3 @0xchocolate (cococode) 20 | 21 | 22 | ## v0.7.0 23 | 24 | Unified serial update! No more complicated wiring of 2x UART connections - all your boards are supported now, with PCAPs and text both going over just ONE, SINGLE serial channel! Thanks to @Willy-JL for adding this amazing feature and fixing up the app for the new APIs. 25 | 26 | Requires Marauder **FW v0.13.7** (or newer) flashed to your wifi board: https://github.com/justcallmekoko/ESP32Marauder/releases/latest 27 | 28 | <3 @0xchocolate (cococode) 29 | 30 | 31 | ## v0.6.6 32 | 33 | Bug fixes and new BLE spam commands! Thanks to @justcallmekoko for adding the new commands! I also fixed the script user input bug where it would hang after selecting "save". 34 | 35 | The BLE spam command format has changed and requires at least **FW v0.13.6**. Make sure you flash the latest release of Marauder FW to your wifi board: https://github.com/justcallmekoko/ESP32Marauder/releases/latest 36 | 37 | Note: if you're flashing directly from your flipper using the [ESP Flasher app](https://github.com/0xchocolate/flipperzero-esp-flasher), grab the bin that corresponds to your hardware and only reflash the Firmware partition. (If you have dual boot set up, then choose the slot where you want to install it. Otherwise, reflash FirmwareA only.) 38 | 39 | By the way, want to support app development by buying me a coffee? You finally have that option! https://ko-fi.com/cococode 40 | 41 | <3 @0xchocolate (cococode) 42 | 43 | 44 | ## v0.6.5 45 | 46 | New option to load Evil Portal HTML files from the flipper sd card! 47 | 48 | 49 | ## v0.6.4 50 | 51 | swiftpair spam and ESP32 sd card commands: sethtml, ls. Requires a board with BT and sd card support. Thanks to @justcallmekoko for adding the new commands! 52 | 53 | 54 | ## v0.6.3 55 | 56 | BT wardriving and Sour Apple! Requires a board with BT support. Thanks to @justcallmekoko for adding the new commands! 57 | 58 | 59 | ## v0.6.2 60 | 61 | Happy wardriving! Thanks to @justcallmekoko for adding the gps and wardrive commands! 62 | 63 | Instructions to install a GPS module: https://github.com/justcallmekoko/ESP32Marauder/wiki/gps-modification 64 | 65 | 66 | ## v0.6.1 67 | 68 | Thanks to @superhedge22 for adding a channel hop option to the sniffpmkid script stage! 69 | 70 | 71 | ## v0.6.0 72 | 73 | Evil Portal and LED control! Thanks @justcallmekoko for adding the commands! See Evil Portal workflow here: https://github.com/justcallmekoko/ESP32Marauder/wiki/evil-portal-workflow 74 | 75 | This version also removes the in-app ESP flasher, but don't worry! It's grown up into its own app, where development will continue separately: https://github.com/0xchocolate/flipperzero-esp-flasher 76 | 77 | 78 | ## v0.4.0 79 | 80 | Added Signal Monitor (thanks @justcallmekoko!) to support new sigmon command in Marauder v0.10.5: https://github.com/justcallmekoko/ESP32Marauder/releases 81 | 82 | Added keyboard and +5V support from unleashed (thanks @xMasterX!) 83 | -------------------------------------------------------------------------------- /file/sequential_file.c: -------------------------------------------------------------------------------- 1 | #include "sequential_file.h" 2 | 3 | char* sequential_file_resolve_path( 4 | Storage* storage, 5 | const char* dir, 6 | const char* prefix, 7 | const char* extension) { 8 | if(storage == NULL || dir == NULL || prefix == NULL || extension == NULL) { 9 | return NULL; 10 | } 11 | 12 | char file_path[256]; 13 | int file_index = 0; 14 | 15 | do { 16 | if(snprintf( 17 | file_path, sizeof(file_path), "%s/%s_%d.%s", dir, prefix, file_index, extension) < 18 | 0) { 19 | return NULL; 20 | } 21 | file_index++; 22 | } while(storage_file_exists(storage, file_path)); 23 | 24 | return strdup(file_path); 25 | } 26 | 27 | bool sequential_file_open( 28 | Storage* storage, 29 | File* file, 30 | const char* dir, 31 | const char* prefix, 32 | const char* extension) { 33 | if(storage == NULL || file == NULL || dir == NULL || prefix == NULL || extension == NULL) { 34 | return false; 35 | } 36 | 37 | char* file_path = sequential_file_resolve_path(storage, dir, prefix, extension); 38 | if(file_path == NULL) { 39 | return false; 40 | } 41 | 42 | bool success = storage_file_open(file, file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS); 43 | free(file_path); 44 | 45 | return success; 46 | } -------------------------------------------------------------------------------- /file/sequential_file.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | char* sequential_file_resolve_path( 6 | Storage* storage, 7 | const char* dir, 8 | const char* prefix, 9 | const char* extension); 10 | bool sequential_file_open( 11 | Storage* storage, 12 | File* file, 13 | const char* dir, 14 | const char* prefix, 15 | const char* extension); -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene.c: -------------------------------------------------------------------------------- 1 | #include "wifi_marauder_scene.h" 2 | 3 | // Generate scene on_enter handlers array 4 | #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, 5 | void (*const wifi_marauder_scene_on_enter_handlers[])(void*) = { 6 | #include "wifi_marauder_scene_config.h" 7 | }; 8 | #undef ADD_SCENE 9 | 10 | // Generate scene on_event handlers array 11 | #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, 12 | bool (*const wifi_marauder_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { 13 | #include "wifi_marauder_scene_config.h" 14 | }; 15 | #undef ADD_SCENE 16 | 17 | // Generate scene on_exit handlers array 18 | #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, 19 | void (*const wifi_marauder_scene_on_exit_handlers[])(void* context) = { 20 | #include "wifi_marauder_scene_config.h" 21 | }; 22 | #undef ADD_SCENE 23 | 24 | // Initialize scene handlers configuration structure 25 | const SceneManagerHandlers wifi_marauder_scene_handlers = { 26 | .on_enter_handlers = wifi_marauder_scene_on_enter_handlers, 27 | .on_event_handlers = wifi_marauder_scene_on_event_handlers, 28 | .on_exit_handlers = wifi_marauder_scene_on_exit_handlers, 29 | .scene_num = WifiMarauderSceneNum, 30 | }; 31 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Generate scene id and total number 6 | #define ADD_SCENE(prefix, name, id) WifiMarauderScene##id, 7 | typedef enum { 8 | #include "wifi_marauder_scene_config.h" 9 | WifiMarauderSceneNum, 10 | } WifiMarauderScene; 11 | #undef ADD_SCENE 12 | 13 | extern const SceneManagerHandlers wifi_marauder_scene_handlers; 14 | 15 | // Generate scene on_enter handlers declaration 16 | #define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); 17 | #include "wifi_marauder_scene_config.h" 18 | #undef ADD_SCENE 19 | 20 | // Generate scene on_event handlers declaration 21 | #define ADD_SCENE(prefix, name, id) \ 22 | bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); 23 | #include "wifi_marauder_scene_config.h" 24 | #undef ADD_SCENE 25 | 26 | // Generate scene on_exit handlers declaration 27 | #define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); 28 | #include "wifi_marauder_scene_config.h" 29 | #undef ADD_SCENE 30 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_config.h: -------------------------------------------------------------------------------- 1 | ADD_SCENE(wifi_marauder, start, Start) 2 | ADD_SCENE(wifi_marauder, console_output, ConsoleOutput) 3 | ADD_SCENE(wifi_marauder, text_input, TextInput) 4 | ADD_SCENE(wifi_marauder, settings_init, SettingsInit) 5 | ADD_SCENE(wifi_marauder, log_viewer, LogViewer) 6 | ADD_SCENE(wifi_marauder, user_input, UserInput) 7 | ADD_SCENE(wifi_marauder, script_select, ScriptSelect) 8 | ADD_SCENE(wifi_marauder, script_options, ScriptOptions) 9 | ADD_SCENE(wifi_marauder, script_edit, ScriptEdit) 10 | ADD_SCENE(wifi_marauder, script_settings, ScriptSettings) 11 | ADD_SCENE(wifi_marauder, script_confirm_delete, ScriptConfirmDelete) 12 | ADD_SCENE(wifi_marauder, script_stage_edit, ScriptStageEdit) 13 | ADD_SCENE(wifi_marauder, script_stage_add, ScriptStageAdd) 14 | ADD_SCENE(wifi_marauder, script_stage_edit_list, ScriptStageEditList) 15 | ADD_SCENE(wifi_marauder, sniffpmkid_options, SniffPmkidOptions) 16 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_console_output.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | char* _wifi_marauder_get_prefix_from_cmd(const char* command) { 4 | int end = strcspn(command, " "); 5 | char* prefix = (char*)malloc(sizeof(char) * (end + 1)); 6 | strncpy(prefix, command, end); 7 | prefix[end] = '\0'; 8 | return prefix; 9 | } 10 | 11 | bool _wifi_marauder_is_saving_enabled(WifiMarauderApp* app) { 12 | // If it is a script that contains a sniff function 13 | if(app->script != NULL) { 14 | if(app->script->save_pcap == WifiMarauderScriptBooleanFalse) { 15 | return false; 16 | } 17 | if(app->script->save_pcap == WifiMarauderScriptBooleanUndefined) { 18 | if(!app->ok_to_save_pcaps) { 19 | return false; 20 | } 21 | } 22 | return wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffRaw) || 23 | wifi_marauder_script_has_stage( 24 | app->script, WifiMarauderScriptStageTypeSniffBeacon) || 25 | wifi_marauder_script_has_stage( 26 | app->script, WifiMarauderScriptStageTypeSniffDeauth) || 27 | wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffEsp) || 28 | wifi_marauder_script_has_stage( 29 | app->script, WifiMarauderScriptStageTypeSniffPmkid) || 30 | wifi_marauder_script_has_stage(app->script, WifiMarauderScriptStageTypeSniffPwn); 31 | } 32 | if(!app->ok_to_save_pcaps) { 33 | return false; 34 | } 35 | // If it is a sniff/wardrive/btwardrive/evilportal function 36 | return app->is_command && app->selected_tx_string && 37 | (strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0 || 38 | strncmp("wardrive", app->selected_tx_string, strlen("wardrive")) == 0 || 39 | strncmp("btwardrive", app->selected_tx_string, strlen("btwardrive")) == 0 || 40 | strncmp("evilportal", app->selected_tx_string, strlen("evilportal")) == 0); 41 | } 42 | 43 | void wifi_marauder_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) { 44 | furi_assert(context); 45 | WifiMarauderApp* app = context; 46 | 47 | if(app->is_writing_log) { 48 | app->has_saved_logs_this_session = true; 49 | storage_file_write(app->log_file, buf, len); 50 | } 51 | 52 | // If text box store gets too big, then truncate it 53 | app->text_box_store_strlen += len; 54 | if(app->text_box_store_strlen >= WIFI_MARAUDER_TEXT_BOX_STORE_SIZE - 1) { 55 | furi_string_right(app->text_box_store, app->text_box_store_strlen / 2); 56 | app->text_box_store_strlen = furi_string_size(app->text_box_store) + len; 57 | } 58 | 59 | // Null-terminate buf and append to text box store 60 | buf[len] = '\0'; 61 | furi_string_cat_printf(app->text_box_store, "%s", buf); 62 | view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshConsoleOutput); 63 | } 64 | 65 | void wifi_marauder_console_output_handle_rx_packets_cb(uint8_t* buf, size_t len, void* context) { 66 | furi_assert(context); 67 | WifiMarauderApp* app = context; 68 | 69 | if(app->is_writing_pcap) { 70 | storage_file_write(app->capture_file, buf, len); 71 | } 72 | } 73 | 74 | void wifi_marauder_scene_console_output_on_enter(void* context) { 75 | WifiMarauderApp* app = context; 76 | 77 | // Reset text box and set font 78 | TextBox* text_box = app->text_box; 79 | text_box_reset(text_box); 80 | text_box_set_font(text_box, TextBoxFontText); 81 | 82 | // Set focus on start or end 83 | if(app->focus_console_start) { 84 | text_box_set_focus(text_box, TextBoxFocusStart); 85 | } else { 86 | text_box_set_focus(text_box, TextBoxFocusEnd); 87 | } 88 | 89 | // Set command-related messages 90 | if(app->is_command) { 91 | furi_string_reset(app->text_box_store); 92 | app->text_box_store_strlen = 0; 93 | // Help message 94 | if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) { 95 | const char* help_msg = "Marauder companion " WIFI_MARAUDER_APP_VERSION "\n"; 96 | furi_string_cat_str(app->text_box_store, help_msg); 97 | app->text_box_store_strlen += strlen(help_msg); 98 | } 99 | // Stopscan message 100 | if(app->show_stopscan_tip) { 101 | const char* help_msg = "Press BACK to send stopscan\n"; 102 | furi_string_cat_str(app->text_box_store, help_msg); 103 | app->text_box_store_strlen += strlen(help_msg); 104 | } 105 | } 106 | 107 | // Set starting text 108 | text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); 109 | 110 | // Set scene state and switch view 111 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneConsoleOutput, 0); 112 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput); 113 | 114 | // Register callbacks to receive data 115 | wifi_marauder_uart_set_handle_rx_data_cb( 116 | app->uart, 117 | wifi_marauder_console_output_handle_rx_data_cb); // setup callback for general log rx thread 118 | wifi_marauder_uart_set_handle_rx_pcap_cb( 119 | app->uart, 120 | wifi_marauder_console_output_handle_rx_packets_cb); // setup callback for packets rx thread 121 | 122 | // Get ready to send command 123 | if((app->is_command && app->selected_tx_string) || app->script) { 124 | char* prefix_buf = NULL; 125 | if(strlen(app->selected_tx_string) > 0) { 126 | prefix_buf = _wifi_marauder_get_prefix_from_cmd(app->selected_tx_string); 127 | } 128 | const char* prefix = prefix_buf ? prefix_buf : // Function name 129 | app->script->name; // Script name 130 | 131 | // Create files *before* sending command 132 | // (it takes time to iterate through the directory) 133 | if(app->ok_to_save_logs) { 134 | char* resolved_path = sequential_file_resolve_path( 135 | app->storage, MARAUDER_APP_FOLDER_LOGS, prefix, "log"); 136 | if(resolved_path != NULL) { 137 | strcpy(app->log_file_path, resolved_path); 138 | free(resolved_path); 139 | if(storage_file_open( 140 | app->log_file, app->log_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { 141 | app->is_writing_log = true; 142 | } else { 143 | dialog_message_show_storage_error(app->dialogs, "Cannot open log file"); 144 | } 145 | } else { 146 | dialog_message_show_storage_error(app->dialogs, "Cannot resolve log path"); 147 | } 148 | } 149 | 150 | // If it is a sniff/wardrive/btwardrive/evilportal function or script, open the capture file for recording 151 | if(_wifi_marauder_is_saving_enabled(app)) { 152 | const char* folder = NULL; 153 | const char* extension = NULL; 154 | if(app->script || // Scripts only support sniff functions, but selected_tx_string is empty 155 | strncmp("sniff", app->selected_tx_string, strlen("sniff")) == 0) { 156 | folder = MARAUDER_APP_FOLDER_PCAPS; 157 | extension = "pcap"; 158 | } else { 159 | folder = MARAUDER_APP_FOLDER_DUMPS; 160 | extension = "txt"; 161 | } 162 | if(sequential_file_open(app->storage, app->capture_file, folder, prefix, extension)) { 163 | app->is_writing_pcap = true; 164 | } else { 165 | dialog_message_show_storage_error(app->dialogs, "Cannot open capture file"); 166 | } 167 | } 168 | 169 | bool send_html = false; 170 | uint8_t* the_html = NULL; 171 | size_t html_size = 0; 172 | if(app->selected_tx_string && strncmp( 173 | "evilportal -c sethtmlstr", 174 | app->selected_tx_string, 175 | strlen("evilportal -c sethtmlstr")) == 0) { 176 | send_html = wifi_marauder_ep_read_html_file(app, &the_html, &html_size); 177 | } 178 | 179 | // Send command with newline '\n' 180 | if(app->selected_tx_string) { 181 | if(app->script == NULL) { 182 | wifi_marauder_uart_tx( 183 | app->uart, 184 | (uint8_t*)(app->selected_tx_string), 185 | strlen(app->selected_tx_string)); 186 | if(app->is_writing_pcap) { 187 | wifi_marauder_uart_tx( 188 | app->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n")); 189 | } else { 190 | wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1); 191 | } 192 | } 193 | if(send_html && the_html) { 194 | wifi_marauder_uart_tx(app->uart, the_html, html_size); 195 | wifi_marauder_uart_tx(app->uart, (uint8_t*)("\n"), 1); 196 | free(the_html); 197 | send_html = false; 198 | } 199 | } 200 | 201 | // Run the script if the file with the script has been opened 202 | if(app->script != NULL) { 203 | app->script_worker = wifi_marauder_script_worker_alloc(app->uart); 204 | wifi_marauder_script_worker_start(app->script_worker, app->script); 205 | } 206 | 207 | if(prefix_buf) { 208 | free(prefix_buf); 209 | } 210 | } 211 | } 212 | 213 | bool wifi_marauder_scene_console_output_on_event(void* context, SceneManagerEvent event) { 214 | WifiMarauderApp* app = context; 215 | 216 | bool consumed = false; 217 | 218 | if(event.type == SceneManagerEventTypeCustom) { 219 | text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); 220 | consumed = true; 221 | } else if(event.type == SceneManagerEventTypeTick) { 222 | consumed = true; 223 | } 224 | 225 | return consumed; 226 | } 227 | 228 | void wifi_marauder_scene_console_output_on_exit(void* context) { 229 | WifiMarauderApp* app = context; 230 | 231 | // Automatically stop the scan when exiting view 232 | if(app->is_command) { 233 | wifi_marauder_uart_tx(app->uart, (uint8_t*)("stopscan\n"), strlen("stopscan\n")); 234 | furi_delay_ms(50); 235 | } 236 | 237 | // Unregister rx callback 238 | wifi_marauder_uart_set_handle_rx_data_cb(app->uart, NULL); 239 | wifi_marauder_uart_set_handle_rx_pcap_cb(app->uart, NULL); 240 | 241 | if(app->script_worker) { 242 | wifi_marauder_script_worker_free(app->script_worker); 243 | app->script_worker = NULL; 244 | } 245 | 246 | app->is_writing_pcap = false; 247 | if(app->capture_file && storage_file_is_open(app->capture_file)) { 248 | storage_file_close(app->capture_file); 249 | } 250 | 251 | app->is_writing_log = false; 252 | if(app->log_file && storage_file_is_open(app->log_file)) { 253 | storage_file_close(app->log_file); 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_log_viewer.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_scene_log_viewer_widget_callback( 4 | GuiButtonType result, 5 | InputType type, 6 | void* context) { 7 | WifiMarauderApp* app = context; 8 | if(type == InputTypeShort) { 9 | view_dispatcher_send_custom_event(app->view_dispatcher, result); 10 | } 11 | } 12 | 13 | static void _read_log_page_into_text_store(WifiMarauderApp* app) { 14 | char temp[64 + 1]; 15 | storage_file_seek( 16 | app->log_file, WIFI_MARAUDER_TEXT_BOX_STORE_SIZE * (app->open_log_file_page - 1), true); 17 | furi_string_reset(app->text_box_store); 18 | for(uint16_t i = 0; i < (WIFI_MARAUDER_TEXT_BOX_STORE_SIZE / (sizeof(temp) - 1)); i++) { 19 | uint16_t num_bytes = storage_file_read(app->log_file, temp, sizeof(temp) - 1); 20 | if(num_bytes == 0) { 21 | break; 22 | } 23 | temp[num_bytes] = '\0'; 24 | furi_string_cat_str(app->text_box_store, temp); 25 | } 26 | } 27 | 28 | void wifi_marauder_scene_log_viewer_setup_widget(WifiMarauderApp* app, bool called_from_browse) { 29 | Widget* widget = app->widget; 30 | bool is_open = storage_file_is_open(app->log_file); 31 | bool should_open_log = (app->has_saved_logs_this_session || called_from_browse); 32 | if(is_open) { 33 | _read_log_page_into_text_store(app); 34 | } else if( 35 | should_open_log && 36 | storage_file_open(app->log_file, app->log_file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { 37 | uint64_t filesize = storage_file_size(app->log_file); 38 | app->open_log_file_num_pages = filesize / WIFI_MARAUDER_TEXT_BOX_STORE_SIZE; 39 | int extra_page = (filesize % WIFI_MARAUDER_TEXT_BOX_STORE_SIZE != 0) ? 1 : 0; 40 | app->open_log_file_num_pages = (filesize / WIFI_MARAUDER_TEXT_BOX_STORE_SIZE) + extra_page; 41 | app->open_log_file_page = 1; 42 | _read_log_page_into_text_store(app); 43 | } else { 44 | app->open_log_file_page = 0; 45 | app->open_log_file_num_pages = 0; 46 | } 47 | 48 | widget_reset(widget); 49 | 50 | if(furi_string_empty(app->text_box_store)) { 51 | char help_msg[256]; 52 | snprintf( 53 | help_msg, 54 | sizeof(help_msg), 55 | "The log is empty! :(\nTry sending a command?\n\nSaving pcaps to flipper sdcard: %s\nSaving logs to flipper sdcard: %s", 56 | app->ok_to_save_pcaps ? "ON" : "OFF", 57 | app->ok_to_save_logs ? "ON" : "OFF"); 58 | furi_string_set_str(app->text_box_store, help_msg); 59 | } 60 | 61 | widget_add_text_scroll_element( 62 | widget, 0, 0, 128, 53, furi_string_get_cstr(app->text_box_store)); 63 | 64 | if(1 < app->open_log_file_page && app->open_log_file_page < app->open_log_file_num_pages) { 65 | // hide "Browse" text for middle pages 66 | widget_add_button_element( 67 | widget, GuiButtonTypeCenter, "", wifi_marauder_scene_log_viewer_widget_callback, app); 68 | } else { 69 | // only show "Browse" text on first and last page 70 | widget_add_button_element( 71 | widget, 72 | GuiButtonTypeCenter, 73 | "Browse", 74 | wifi_marauder_scene_log_viewer_widget_callback, 75 | app); 76 | } 77 | 78 | char pagecounter[100]; 79 | snprintf( 80 | pagecounter, 81 | sizeof(pagecounter), 82 | "%d/%d", 83 | app->open_log_file_page, 84 | app->open_log_file_num_pages); 85 | if(app->open_log_file_page > 1) { 86 | if(app->open_log_file_page == app->open_log_file_num_pages) { 87 | // only show left side page-count on last page 88 | widget_add_button_element( 89 | widget, 90 | GuiButtonTypeLeft, 91 | pagecounter, 92 | wifi_marauder_scene_log_viewer_widget_callback, 93 | app); 94 | } else { 95 | widget_add_button_element( 96 | widget, GuiButtonTypeLeft, "", wifi_marauder_scene_log_viewer_widget_callback, app); 97 | } 98 | } 99 | if(app->open_log_file_page < app->open_log_file_num_pages) { 100 | widget_add_button_element( 101 | widget, 102 | GuiButtonTypeRight, 103 | pagecounter, 104 | wifi_marauder_scene_log_viewer_widget_callback, 105 | app); 106 | } 107 | } 108 | 109 | void wifi_marauder_scene_log_viewer_on_enter(void* context) { 110 | WifiMarauderApp* app = context; 111 | 112 | app->open_log_file_page = 0; 113 | app->open_log_file_num_pages = 0; 114 | bool saved_logs_exist = false; 115 | if(!app->has_saved_logs_this_session && furi_string_empty(app->text_box_store)) { 116 | // no commands sent yet this session, find last saved log 117 | if(storage_dir_open(app->log_file, MARAUDER_APP_FOLDER_LOGS)) { 118 | char name[70]; 119 | char lastname[70]; 120 | while(storage_dir_read(app->log_file, NULL, name, sizeof(name))) { 121 | // keep reading directory until last file is reached 122 | strlcpy(lastname, name, sizeof(lastname)); 123 | saved_logs_exist = true; 124 | } 125 | if(saved_logs_exist) { 126 | snprintf( 127 | app->log_file_path, 128 | sizeof(app->log_file_path), 129 | "%s/%s", 130 | MARAUDER_APP_FOLDER_LOGS, 131 | lastname); 132 | } 133 | } 134 | storage_dir_close(app->log_file); 135 | } 136 | 137 | wifi_marauder_scene_log_viewer_setup_widget(app, saved_logs_exist); 138 | 139 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget); 140 | } 141 | 142 | bool wifi_marauder_scene_log_viewer_on_event(void* context, SceneManagerEvent event) { 143 | WifiMarauderApp* app = context; 144 | bool consumed = false; 145 | 146 | if(event.type == SceneManagerEventTypeCustom) { 147 | if(event.event == GuiButtonTypeCenter) { 148 | // Browse 149 | FuriString* predefined_filepath = furi_string_alloc_set_str(MARAUDER_APP_FOLDER_LOGS); 150 | FuriString* selected_filepath = furi_string_alloc(); 151 | DialogsFileBrowserOptions browser_options; 152 | dialog_file_browser_set_basic_options(&browser_options, ".log", &I_Text_10x10); 153 | if(dialog_file_browser_show( 154 | app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { 155 | strncpy( 156 | app->log_file_path, 157 | furi_string_get_cstr(selected_filepath), 158 | sizeof(app->log_file_path)); 159 | if(storage_file_is_open(app->log_file)) { 160 | storage_file_close(app->log_file); 161 | } 162 | wifi_marauder_scene_log_viewer_setup_widget(app, true); 163 | } 164 | furi_string_free(selected_filepath); 165 | furi_string_free(predefined_filepath); 166 | consumed = true; 167 | } else if(event.event == GuiButtonTypeRight) { 168 | // Advance page 169 | ++app->open_log_file_page; 170 | wifi_marauder_scene_log_viewer_setup_widget(app, false); 171 | } else if(event.event == GuiButtonTypeLeft) { 172 | // Previous page 173 | --app->open_log_file_page; 174 | wifi_marauder_scene_log_viewer_setup_widget(app, false); 175 | } 176 | } 177 | 178 | return consumed; 179 | } 180 | 181 | void wifi_marauder_scene_log_viewer_on_exit(void* context) { 182 | WifiMarauderApp* app = context; 183 | widget_reset(app->widget); 184 | if(storage_file_is_open(app->log_file)) { 185 | storage_file_close(app->log_file); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_script_confirm_delete.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_scene_script_confirm_delete_widget_callback( 4 | GuiButtonType result, 5 | InputType type, 6 | void* context) { 7 | WifiMarauderApp* app = context; 8 | if(type == InputTypeShort) { 9 | view_dispatcher_send_custom_event(app->view_dispatcher, result); 10 | } 11 | } 12 | 13 | void wifi_marauder_scene_script_confirm_delete_on_enter(void* context) { 14 | WifiMarauderApp* app = context; 15 | 16 | widget_add_button_element( 17 | app->widget, 18 | GuiButtonTypeLeft, 19 | "No", 20 | wifi_marauder_scene_script_confirm_delete_widget_callback, 21 | app); 22 | widget_add_button_element( 23 | app->widget, 24 | GuiButtonTypeRight, 25 | "Yes", 26 | wifi_marauder_scene_script_confirm_delete_widget_callback, 27 | app); 28 | 29 | widget_add_string_element( 30 | app->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Are you sure?"); 31 | widget_add_text_box_element( 32 | app->widget, 33 | 0, 34 | 12, 35 | 128, 36 | 38, 37 | AlignCenter, 38 | AlignCenter, 39 | "The script will be\npermanently deleted", 40 | false); 41 | 42 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget); 43 | } 44 | 45 | bool wifi_marauder_scene_script_confirm_delete_on_event(void* context, SceneManagerEvent event) { 46 | WifiMarauderApp* app = context; 47 | bool consumed = false; 48 | 49 | if(event.type == SceneManagerEventTypeCustom) { 50 | // get which button press: "Yes" or "No" 51 | if(event.event == GuiButtonTypeRight) { 52 | // Yes 53 | if(app->script != NULL) { 54 | char script_path[256]; 55 | snprintf( 56 | script_path, 57 | sizeof(script_path), 58 | "%s/%s.json", 59 | MARAUDER_APP_FOLDER_SCRIPTS, 60 | app->script->name); 61 | storage_simply_remove(app->storage, script_path); 62 | wifi_marauder_script_free(app->script); 63 | app->script = NULL; 64 | 65 | DialogMessage* message = dialog_message_alloc(); 66 | dialog_message_set_text(message, "Deleted!", 88, 32, AlignCenter, AlignCenter); 67 | dialog_message_set_icon(message, &I_DolphinCommon_56x48, 5, 6); 68 | dialog_message_set_buttons(message, NULL, "Ok", NULL); 69 | dialog_message_show(app->dialogs, message); 70 | dialog_message_free(message); 71 | } 72 | } 73 | scene_manager_previous_scene(app->scene_manager); 74 | consumed = true; 75 | } 76 | 77 | return consumed; 78 | } 79 | 80 | void wifi_marauder_scene_script_confirm_delete_on_exit(void* context) { 81 | WifiMarauderApp* app = context; 82 | widget_reset(app->widget); 83 | } 84 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_script_edit.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | static void wifi_marauder_scene_script_edit_callback(void* context, uint32_t index) { 4 | WifiMarauderApp* app = context; 5 | WifiMarauderScriptStage* current_stage = app->script->first_stage; 6 | uint32_t stage_index = 0; 7 | 8 | while(current_stage != NULL && stage_index < index) { 9 | current_stage = current_stage->next_stage; 10 | stage_index++; 11 | } 12 | app->script_edit_selected_stage = current_stage; 13 | 14 | if(app->script_edit_selected_stage != NULL) { 15 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit, index); 16 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptStageEdit); 17 | } 18 | } 19 | 20 | static void wifi_marauder_scene_script_edit_add_callback(void* context, uint32_t index) { 21 | WifiMarauderApp* app = context; 22 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit, index); 23 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptStageAdd); 24 | } 25 | 26 | void wifi_marauder_scene_script_edit_on_enter(void* context) { 27 | WifiMarauderApp* app = context; 28 | Submenu* submenu = app->submenu; 29 | WifiMarauderScript* script = app->script; 30 | submenu_set_header(submenu, script->name); 31 | 32 | WifiMarauderScriptStage* current_stage = script->first_stage; 33 | int stage_index = 0; 34 | while(current_stage != NULL) { 35 | switch(current_stage->type) { 36 | case WifiMarauderScriptStageTypeScan: 37 | submenu_add_item( 38 | submenu, "Scan", stage_index, wifi_marauder_scene_script_edit_callback, app); 39 | break; 40 | case WifiMarauderScriptStageTypeSelect: 41 | submenu_add_item( 42 | submenu, "Select", stage_index, wifi_marauder_scene_script_edit_callback, app); 43 | break; 44 | case WifiMarauderScriptStageTypeDeauth: 45 | submenu_add_item( 46 | submenu, "Deauth", stage_index, wifi_marauder_scene_script_edit_callback, app); 47 | break; 48 | case WifiMarauderScriptStageTypeProbe: 49 | submenu_add_item( 50 | submenu, "Probe", stage_index, wifi_marauder_scene_script_edit_callback, app); 51 | break; 52 | case WifiMarauderScriptStageTypeSniffRaw: 53 | submenu_add_item( 54 | submenu, "Sniff raw", stage_index, wifi_marauder_scene_script_edit_callback, app); 55 | break; 56 | case WifiMarauderScriptStageTypeSniffBeacon: 57 | submenu_add_item( 58 | submenu, 59 | "Sniff beacon", 60 | stage_index, 61 | wifi_marauder_scene_script_edit_callback, 62 | app); 63 | break; 64 | case WifiMarauderScriptStageTypeSniffDeauth: 65 | submenu_add_item( 66 | submenu, 67 | "Sniff deauth", 68 | stage_index, 69 | wifi_marauder_scene_script_edit_callback, 70 | app); 71 | break; 72 | case WifiMarauderScriptStageTypeSniffEsp: 73 | submenu_add_item( 74 | submenu, "Sniff esp", stage_index, wifi_marauder_scene_script_edit_callback, app); 75 | break; 76 | case WifiMarauderScriptStageTypeSniffPmkid: 77 | submenu_add_item( 78 | submenu, "Sniff PMKID", stage_index, wifi_marauder_scene_script_edit_callback, app); 79 | break; 80 | case WifiMarauderScriptStageTypeSniffPwn: 81 | submenu_add_item( 82 | submenu, "Sniff pwn", stage_index, wifi_marauder_scene_script_edit_callback, app); 83 | break; 84 | case WifiMarauderScriptStageTypeBeaconList: 85 | submenu_add_item( 86 | submenu, "Beacon list", stage_index, wifi_marauder_scene_script_edit_callback, app); 87 | break; 88 | case WifiMarauderScriptStageTypeBeaconAp: 89 | submenu_add_item( 90 | submenu, "Beacon AP", stage_index, wifi_marauder_scene_script_edit_callback, app); 91 | break; 92 | case WifiMarauderScriptStageTypeExec: 93 | submenu_add_item( 94 | submenu, 95 | "Custom command", 96 | stage_index, 97 | wifi_marauder_scene_script_edit_callback, 98 | app); 99 | break; 100 | case WifiMarauderScriptStageTypeDelay: 101 | submenu_add_item( 102 | submenu, "Delay", stage_index, wifi_marauder_scene_script_edit_callback, app); 103 | break; 104 | } 105 | current_stage = current_stage->next_stage; 106 | stage_index++; 107 | } 108 | 109 | submenu_add_item( 110 | submenu, "[+] ADD STAGE", stage_index++, wifi_marauder_scene_script_edit_add_callback, app); 111 | submenu_set_selected_item( 112 | submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit)); 113 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); 114 | } 115 | 116 | bool wifi_marauder_scene_script_edit_on_event(void* context, SceneManagerEvent event) { 117 | UNUSED(context); 118 | UNUSED(event); 119 | return false; 120 | } 121 | 122 | void wifi_marauder_scene_script_edit_on_exit(void* context) { 123 | WifiMarauderApp* app = context; 124 | submenu_reset(app->submenu); 125 | } 126 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_script_edit_list.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | static void 4 | wifi_marauder_scene_script_stage_edit_list_add_callback(void* context, uint32_t index) { 5 | WifiMarauderApp* app = context; 6 | 7 | // Creates new item 8 | WifiMarauderScriptStageListItem* new_item = 9 | (WifiMarauderScriptStageListItem*)malloc(sizeof(WifiMarauderScriptStageListItem)); 10 | new_item->value = malloc(64); 11 | new_item->next_item = NULL; 12 | 13 | if(app->script_stage_edit_first_item == NULL) { 14 | app->script_stage_edit_first_item = new_item; 15 | } else { 16 | WifiMarauderScriptStageListItem* last_item = app->script_stage_edit_first_item; 17 | while(last_item->next_item != NULL) { 18 | last_item = last_item->next_item; 19 | } 20 | last_item->next_item = new_item; 21 | } 22 | 23 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEditList, index); 24 | app->user_input_type = WifiMarauderUserInputTypeString; 25 | app->user_input_string_reference = &new_item->value; 26 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); 27 | } 28 | 29 | static void wifi_marauder_scene_script_stage_edit_list_deallocate_items(WifiMarauderApp* app) { 30 | WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; 31 | while(current_item != NULL) { 32 | WifiMarauderScriptStageListItem* next_item = current_item->next_item; 33 | free(current_item->value); 34 | free(current_item); 35 | current_item = next_item; 36 | } 37 | app->script_stage_edit_first_item = NULL; 38 | } 39 | 40 | static void wifi_marauder_scene_script_stage_edit_list_save_strings(WifiMarauderApp* app) { 41 | WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; 42 | int array_size = 0; 43 | 44 | // Calculates the required array size 45 | while(current_item != NULL) { 46 | array_size++; 47 | current_item = current_item->next_item; 48 | } 49 | 50 | // Reallocate the array of strings if necessary 51 | if(*app->script_stage_edit_string_count_reference < array_size) { 52 | *app->script_stage_edit_strings_reference = 53 | realloc(*app->script_stage_edit_strings_reference, array_size * sizeof(char*)); 54 | } 55 | 56 | // Fills the array of strings 57 | current_item = app->script_stage_edit_first_item; 58 | int i = 0; 59 | while(current_item != NULL) { 60 | char* current_str = malloc(strlen(current_item->value) + 1); 61 | strncpy(current_str, current_item->value, strlen(current_item->value) + 1); 62 | (*app->script_stage_edit_strings_reference)[i] = current_str; 63 | current_item = current_item->next_item; 64 | i++; 65 | } 66 | 67 | *app->script_stage_edit_string_count_reference = array_size; 68 | } 69 | 70 | static void wifi_marauder_scene_script_stage_edit_list_save_numbers(WifiMarauderApp* app) { 71 | WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; 72 | int array_size = 0; 73 | 74 | // Calculates the required array size 75 | while(current_item != NULL) { 76 | array_size++; 77 | current_item = current_item->next_item; 78 | } 79 | 80 | // Reallocate the array of integers if necessary 81 | if(*app->script_stage_edit_number_count_reference < array_size) { 82 | *app->script_stage_edit_numbers_reference = 83 | realloc(*app->script_stage_edit_numbers_reference, array_size * sizeof(int)); 84 | } 85 | 86 | // Fills the array of integers 87 | current_item = app->script_stage_edit_first_item; 88 | int i = 0; 89 | while(current_item != NULL) { 90 | (*app->script_stage_edit_numbers_reference)[i] = atoi(current_item->value); 91 | current_item = current_item->next_item; 92 | i++; 93 | } 94 | 95 | *app->script_stage_edit_number_count_reference = array_size; 96 | } 97 | 98 | static void 99 | wifi_marauder_scene_script_stage_edit_list_save_callback(void* context, uint32_t index) { 100 | UNUSED(index); 101 | WifiMarauderApp* app = context; 102 | 103 | if(app->script_stage_edit_strings_reference != NULL && 104 | app->script_stage_edit_string_count_reference != NULL) { 105 | wifi_marauder_scene_script_stage_edit_list_save_strings(app); 106 | } 107 | 108 | if(app->script_stage_edit_numbers_reference != NULL && 109 | app->script_stage_edit_number_count_reference != NULL) { 110 | wifi_marauder_scene_script_stage_edit_list_save_numbers(app); 111 | } 112 | 113 | wifi_marauder_scene_script_stage_edit_list_deallocate_items(app); 114 | scene_manager_previous_scene(app->scene_manager); 115 | } 116 | 117 | static void 118 | wifi_marauder_scene_script_stage_edit_list_clear_callback(void* context, uint32_t index) { 119 | UNUSED(index); 120 | WifiMarauderApp* app = context; 121 | 122 | wifi_marauder_scene_script_stage_edit_list_deallocate_items(app); 123 | 124 | submenu_reset(app->submenu); 125 | submenu_add_item( 126 | app->submenu, 127 | "[+] ADD ITEM", 128 | 99, 129 | wifi_marauder_scene_script_stage_edit_list_add_callback, 130 | app); 131 | submenu_add_item( 132 | app->submenu, 133 | "[*] SAVE ITEMS", 134 | 99, 135 | wifi_marauder_scene_script_stage_edit_list_save_callback, 136 | app); 137 | submenu_add_item( 138 | app->submenu, 139 | "[-] CLEAR LIST", 140 | 99, 141 | wifi_marauder_scene_script_stage_edit_list_clear_callback, 142 | app); 143 | } 144 | 145 | void wifi_marauder_scene_script_stage_edit_list_on_enter(void* context) { 146 | WifiMarauderApp* app = context; 147 | int item_index = 0; 148 | WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; 149 | 150 | while(current_item != NULL) { 151 | submenu_add_item(app->submenu, current_item->value, item_index++, NULL, app); 152 | current_item = current_item->next_item; 153 | } 154 | submenu_add_item( 155 | app->submenu, 156 | "[+] ADD ITEM", 157 | 99, 158 | wifi_marauder_scene_script_stage_edit_list_add_callback, 159 | app); 160 | submenu_add_item( 161 | app->submenu, 162 | "[*] SAVE ITEMS", 163 | 99, 164 | wifi_marauder_scene_script_stage_edit_list_save_callback, 165 | app); 166 | submenu_add_item( 167 | app->submenu, 168 | "[-] CLEAR LIST", 169 | 99, 170 | wifi_marauder_scene_script_stage_edit_list_clear_callback, 171 | app); 172 | 173 | submenu_set_selected_item( 174 | app->submenu, 175 | scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEditList)); 176 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); 177 | } 178 | 179 | bool wifi_marauder_scene_script_stage_edit_list_on_event(void* context, SceneManagerEvent event) { 180 | UNUSED(context); 181 | UNUSED(event); 182 | return false; 183 | } 184 | 185 | void wifi_marauder_scene_script_stage_edit_list_on_exit(void* context) { 186 | WifiMarauderApp* app = context; 187 | submenu_reset(app->submenu); 188 | } 189 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_script_options.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | enum SubmenuIndex { 4 | SubmenuIndexRun, 5 | SubmenuIndexSettings, 6 | SubmenuIndexEditStages, 7 | SubmenuIndexSave, 8 | SubmenuIndexDelete 9 | }; 10 | 11 | void wifi_marauder_scene_script_options_save_script(WifiMarauderApp* app) { 12 | char script_path[256]; 13 | snprintf( 14 | script_path, 15 | sizeof(script_path), 16 | "%s/%s.json", 17 | MARAUDER_APP_FOLDER_SCRIPTS, 18 | app->script->name); 19 | wifi_marauder_script_save_json(app->storage, script_path, app->script); 20 | 21 | DialogMessage* message = dialog_message_alloc(); 22 | dialog_message_set_text(message, "Saved!", 88, 32, AlignCenter, AlignCenter); 23 | dialog_message_set_icon(message, &I_DolphinCommon_56x48, 5, 6); 24 | dialog_message_set_buttons(message, NULL, "Ok", NULL); 25 | dialog_message_show(app->dialogs, message); 26 | dialog_message_free(message); 27 | } 28 | 29 | static void wifi_marauder_scene_script_options_callback(void* context, uint32_t index) { 30 | WifiMarauderApp* app = context; 31 | 32 | switch(index) { 33 | case SubmenuIndexRun: 34 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions, index); 35 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); 36 | break; 37 | case SubmenuIndexSettings: 38 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions, index); 39 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptSettings); 40 | break; 41 | case SubmenuIndexEditStages: 42 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions, index); 43 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptEdit); 44 | break; 45 | case SubmenuIndexSave: 46 | wifi_marauder_scene_script_options_save_script(app); 47 | break; 48 | case SubmenuIndexDelete: 49 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions, index); 50 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptConfirmDelete); 51 | break; 52 | } 53 | } 54 | 55 | void wifi_marauder_scene_script_options_on_enter(void* context) { 56 | WifiMarauderApp* app = context; 57 | 58 | // If returning after confirming script deletion 59 | if(app->script == NULL) { 60 | scene_manager_previous_scene(app->scene_manager); 61 | return; 62 | } 63 | 64 | Submenu* submenu = app->submenu; 65 | 66 | submenu_set_header(submenu, app->script->name); 67 | submenu_add_item( 68 | submenu, "[>] RUN", SubmenuIndexRun, wifi_marauder_scene_script_options_callback, app); 69 | submenu_add_item( 70 | submenu, 71 | "[S] SETTINGS", 72 | SubmenuIndexSettings, 73 | wifi_marauder_scene_script_options_callback, 74 | app); 75 | submenu_add_item( 76 | submenu, 77 | "[+] EDIT STAGES", 78 | SubmenuIndexEditStages, 79 | wifi_marauder_scene_script_options_callback, 80 | app); 81 | submenu_add_item( 82 | submenu, "[*] SAVE", SubmenuIndexSave, wifi_marauder_scene_script_options_callback, app); 83 | submenu_add_item( 84 | submenu, 85 | "[X] DELETE", 86 | SubmenuIndexDelete, 87 | wifi_marauder_scene_script_options_callback, 88 | app); 89 | 90 | submenu_set_selected_item( 91 | submenu, 92 | scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptOptions)); 93 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); 94 | } 95 | 96 | bool wifi_marauder_scene_script_options_on_event(void* context, SceneManagerEvent event) { 97 | WifiMarauderApp* app = context; 98 | bool consumed = false; 99 | 100 | if(event.type == SceneManagerEventTypeBack) { 101 | wifi_marauder_script_free(app->script); 102 | app->script = NULL; 103 | } 104 | 105 | return consumed; 106 | } 107 | 108 | void wifi_marauder_scene_script_options_on_exit(void* context) { 109 | WifiMarauderApp* app = context; 110 | submenu_reset(app->submenu); 111 | } 112 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_script_select.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | static void wifi_marauder_scene_script_select_callback(void* context, uint32_t index) { 4 | WifiMarauderApp* app = context; 5 | 6 | char script_path[256]; 7 | snprintf( 8 | script_path, 9 | sizeof(script_path), 10 | "%s/%s.json", 11 | MARAUDER_APP_FOLDER_SCRIPTS, 12 | furi_string_get_cstr(app->script_list[index])); 13 | 14 | app->script = wifi_marauder_script_parse_json(app->storage, script_path); 15 | if(app->script) { 16 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptSelect, index); 17 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptOptions); 18 | } 19 | } 20 | 21 | static void wifi_marauder_scene_script_select_add_callback(void* context, uint32_t index) { 22 | WifiMarauderApp* app = context; 23 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptSelect, index); 24 | 25 | app->user_input_type = WifiMarauderUserInputTypeFileName; 26 | app->user_input_file_dir = strdup(MARAUDER_APP_FOLDER_SCRIPTS); 27 | app->user_input_file_extension = strdup("json"); 28 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); 29 | } 30 | 31 | void wifi_marauder_scene_script_select_on_enter(void* context) { 32 | WifiMarauderApp* app = context; 33 | Submenu* submenu = app->submenu; 34 | 35 | File* dir_scripts = storage_file_alloc(app->storage); 36 | if(storage_dir_open(dir_scripts, MARAUDER_APP_FOLDER_SCRIPTS)) { 37 | FileInfo file_info; 38 | char file_path[255]; 39 | app->script_list_count = 0; 40 | // Goes through the files in the folder counting the ones that end with the json extension 41 | while(storage_dir_read(dir_scripts, &file_info, file_path, 255)) { 42 | app->script_list_count++; 43 | } 44 | if(app->script_list_count > 0) { 45 | submenu_set_header(submenu, "Select a script:"); 46 | app->script_list = malloc(app->script_list_count * sizeof(FuriString*)); 47 | storage_dir_close(dir_scripts); 48 | storage_dir_open(dir_scripts, MARAUDER_APP_FOLDER_SCRIPTS); 49 | // Read the files again from the beginning, adding the scripts in the list 50 | int script_index = 0; 51 | while(storage_dir_read(dir_scripts, &file_info, file_path, 255)) { 52 | app->script_list[script_index] = furi_string_alloc(); 53 | path_extract_filename_no_ext(file_path, app->script_list[script_index]); 54 | submenu_add_item( 55 | submenu, 56 | furi_string_get_cstr(app->script_list[script_index]), 57 | script_index, 58 | wifi_marauder_scene_script_select_callback, 59 | app); 60 | script_index++; 61 | } 62 | } else { 63 | submenu_set_header(submenu, "No script found"); 64 | } 65 | submenu_add_item( 66 | submenu, "[+] ADD SCRIPT", 99, wifi_marauder_scene_script_select_add_callback, app); 67 | storage_dir_close(dir_scripts); 68 | } 69 | storage_file_free(dir_scripts); 70 | 71 | submenu_set_selected_item( 72 | submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptSelect)); 73 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); 74 | } 75 | 76 | bool wifi_marauder_scene_script_select_on_event(void* context, SceneManagerEvent event) { 77 | UNUSED(context); 78 | UNUSED(event); 79 | return false; 80 | } 81 | 82 | void wifi_marauder_scene_script_select_on_exit(void* context) { 83 | WifiMarauderApp* app = context; 84 | submenu_reset(app->submenu); 85 | 86 | for(int i = 0; i < app->script_list_count; i++) { 87 | furi_string_free(app->script_list[i]); 88 | } 89 | free(app->script_list); 90 | } 91 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_script_settings.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | enum ScriptSettingsOption { 4 | ScriptSettingsOptionRepeat, 5 | ScriptSettingsOptionSavePcap, 6 | ScriptSettingsOptionEnableLed 7 | }; 8 | 9 | const char* option_values[3] = {"No", "Yes", "Default"}; 10 | 11 | static void wifi_marauder_scene_script_settings_enter_callback(void* context, uint32_t index) { 12 | WifiMarauderApp* app = context; 13 | // Accept script repeat value 14 | if(index == ScriptSettingsOptionRepeat) { 15 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptSettings, index); 16 | app->user_input_type = WifiMarauderUserInputTypeNumber; 17 | app->user_input_number_reference = &app->script->repeat; 18 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); 19 | } 20 | } 21 | 22 | static void wifi_marauder_scene_script_settings_change_callback(VariableItem* item) { 23 | WifiMarauderApp* app = variable_item_get_context(item); 24 | 25 | uint8_t current_option = variable_item_list_get_selected_item_index(app->var_item_list); 26 | uint8_t option_value_index = variable_item_get_current_value_index(item); 27 | 28 | switch(current_option) { 29 | case ScriptSettingsOptionSavePcap: 30 | variable_item_set_current_value_text(item, option_values[option_value_index]); 31 | app->script->save_pcap = option_value_index; 32 | break; 33 | case ScriptSettingsOptionEnableLed: 34 | variable_item_set_current_value_text(item, option_values[option_value_index]); 35 | app->script->enable_led = option_value_index; 36 | break; 37 | } 38 | } 39 | 40 | void wifi_marauder_scene_script_settings_on_enter(void* context) { 41 | WifiMarauderApp* app = context; 42 | VariableItemList* var_item_list = app->var_item_list; 43 | variable_item_list_set_enter_callback( 44 | app->var_item_list, wifi_marauder_scene_script_settings_enter_callback, app); 45 | 46 | // Script repeat option 47 | VariableItem* repeat_item = variable_item_list_add(app->var_item_list, "Repeat", 1, NULL, app); 48 | char repeat_str[32]; 49 | snprintf(repeat_str, sizeof(repeat_str), "%d", app->script->repeat); 50 | variable_item_set_current_value_text(repeat_item, repeat_str); 51 | 52 | // Save PCAP option 53 | VariableItem* save_pcap_item = variable_item_list_add( 54 | app->var_item_list, 55 | "Save PCAP", 56 | 3, 57 | wifi_marauder_scene_script_settings_change_callback, 58 | app); 59 | variable_item_set_current_value_index(save_pcap_item, app->script->save_pcap); 60 | variable_item_set_current_value_text(save_pcap_item, option_values[app->script->save_pcap]); 61 | 62 | // Enable board LED option 63 | VariableItem* enable_led_item = variable_item_list_add( 64 | app->var_item_list, 65 | "Enable LED", 66 | 3, 67 | wifi_marauder_scene_script_settings_change_callback, 68 | app); 69 | variable_item_set_current_value_index(enable_led_item, app->script->enable_led); 70 | variable_item_set_current_value_text(enable_led_item, option_values[app->script->enable_led]); 71 | 72 | variable_item_list_set_selected_item( 73 | var_item_list, 74 | scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptSettings)); 75 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); 76 | } 77 | 78 | bool wifi_marauder_scene_script_settings_on_event(void* context, SceneManagerEvent event) { 79 | UNUSED(context); 80 | UNUSED(event); 81 | return false; 82 | } 83 | 84 | void wifi_marauder_scene_script_settings_on_exit(void* context) { 85 | WifiMarauderApp* app = context; 86 | variable_item_list_reset(app->var_item_list); 87 | } 88 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_script_stage_add.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | // Scan 4 | static void wifi_marauder_scene_script_stage_add_scan_callback(void* context, uint32_t index) { 5 | UNUSED(index); 6 | WifiMarauderApp* app = context; 7 | 8 | WifiMarauderScriptStageScan* stage = 9 | (WifiMarauderScriptStageScan*)malloc(sizeof(WifiMarauderScriptStageScan)); 10 | stage->type = WifiMarauderScriptScanTypeAp; 11 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SCAN; 12 | 13 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeScan, stage); 14 | scene_manager_previous_scene(app->scene_manager); 15 | } 16 | 17 | // Select 18 | static void wifi_marauder_scene_script_stage_add_select_callback(void* context, uint32_t index) { 19 | UNUSED(index); 20 | WifiMarauderApp* app = context; 21 | 22 | WifiMarauderScriptStageSelect* stage = 23 | (WifiMarauderScriptStageSelect*)malloc(sizeof(WifiMarauderScriptStageSelect)); 24 | stage->type = WifiMarauderScriptSelectTypeAp; 25 | stage->filter = strdup("all"); 26 | 27 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSelect, stage); 28 | scene_manager_previous_scene(app->scene_manager); 29 | } 30 | 31 | // Deauth 32 | static void wifi_marauder_scene_script_stage_add_deauth_callback(void* context, uint32_t index) { 33 | UNUSED(index); 34 | WifiMarauderApp* app = context; 35 | 36 | WifiMarauderScriptStageDeauth* stage = 37 | (WifiMarauderScriptStageDeauth*)malloc(sizeof(WifiMarauderScriptStageDeauth)); 38 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_DEAUTH; 39 | 40 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeDeauth, stage); 41 | scene_manager_previous_scene(app->scene_manager); 42 | } 43 | 44 | // Probe 45 | static void wifi_marauder_scene_script_stage_add_probe_callback(void* context, uint32_t index) { 46 | UNUSED(index); 47 | WifiMarauderApp* app = context; 48 | 49 | WifiMarauderScriptStageProbe* stage = 50 | (WifiMarauderScriptStageProbe*)malloc(sizeof(WifiMarauderScriptStageProbe)); 51 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_PROBE; 52 | 53 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeProbe, stage); 54 | scene_manager_previous_scene(app->scene_manager); 55 | } 56 | 57 | // Sniff RAW 58 | static void wifi_marauder_scene_script_stage_add_sniffraw_callback(void* context, uint32_t index) { 59 | UNUSED(index); 60 | WifiMarauderApp* app = context; 61 | 62 | WifiMarauderScriptStageSniffRaw* stage = 63 | (WifiMarauderScriptStageSniffRaw*)malloc(sizeof(WifiMarauderScriptStageSniffRaw)); 64 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; 65 | 66 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffRaw, stage); 67 | scene_manager_previous_scene(app->scene_manager); 68 | } 69 | 70 | // Sniff Beacon 71 | static void 72 | wifi_marauder_scene_script_stage_add_sniffbeacon_callback(void* context, uint32_t index) { 73 | UNUSED(index); 74 | WifiMarauderApp* app = context; 75 | 76 | WifiMarauderScriptStageSniffBeacon* stage = 77 | (WifiMarauderScriptStageSniffBeacon*)malloc(sizeof(WifiMarauderScriptStageSniffBeacon)); 78 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; 79 | 80 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffBeacon, stage); 81 | scene_manager_previous_scene(app->scene_manager); 82 | } 83 | 84 | // Sniff Deauth 85 | static void 86 | wifi_marauder_scene_script_stage_add_sniffdeauth_callback(void* context, uint32_t index) { 87 | UNUSED(index); 88 | WifiMarauderApp* app = context; 89 | 90 | WifiMarauderScriptStageSniffDeauth* stage = 91 | (WifiMarauderScriptStageSniffDeauth*)malloc(sizeof(WifiMarauderScriptStageSniffDeauth)); 92 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; 93 | 94 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffDeauth, stage); 95 | scene_manager_previous_scene(app->scene_manager); 96 | } 97 | 98 | // Sniff Esp 99 | static void wifi_marauder_scene_script_stage_add_sniffesp_callback(void* context, uint32_t index) { 100 | UNUSED(index); 101 | WifiMarauderApp* app = context; 102 | 103 | WifiMarauderScriptStageSniffEsp* stage = 104 | (WifiMarauderScriptStageSniffEsp*)malloc(sizeof(WifiMarauderScriptStageSniffEsp)); 105 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; 106 | 107 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffEsp, stage); 108 | scene_manager_previous_scene(app->scene_manager); 109 | } 110 | 111 | // Sniff PMKID 112 | static void 113 | wifi_marauder_scene_script_stage_add_sniffpmkid_callback(void* context, uint32_t index) { 114 | UNUSED(index); 115 | WifiMarauderApp* app = context; 116 | 117 | WifiMarauderScriptStageSniffPmkid* stage = 118 | (WifiMarauderScriptStageSniffPmkid*)malloc(sizeof(WifiMarauderScriptStageSniffPmkid)); 119 | stage->channel = 0; 120 | stage->force_deauth = WifiMarauderScriptBooleanTrue; 121 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; 122 | 123 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffPmkid, stage); 124 | scene_manager_previous_scene(app->scene_manager); 125 | } 126 | 127 | // Sniff Pwn 128 | static void wifi_marauder_scene_script_stage_add_sniffpwn_callback(void* context, uint32_t index) { 129 | UNUSED(index); 130 | WifiMarauderApp* app = context; 131 | 132 | WifiMarauderScriptStageSniffPwn* stage = 133 | (WifiMarauderScriptStageSniffPwn*)malloc(sizeof(WifiMarauderScriptStageSniffPwn)); 134 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF; 135 | 136 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeSniffPwn, stage); 137 | scene_manager_previous_scene(app->scene_manager); 138 | } 139 | 140 | // Beacon list 141 | static void 142 | wifi_marauder_scene_script_stage_add_beaconlist_callback(void* context, uint32_t index) { 143 | UNUSED(index); 144 | WifiMarauderApp* app = context; 145 | 146 | WifiMarauderScriptStageBeaconList* stage = 147 | (WifiMarauderScriptStageBeaconList*)malloc(sizeof(WifiMarauderScriptStageBeaconList)); 148 | stage->ssids = NULL; 149 | stage->ssid_count = 0; 150 | stage->random_ssids = 0; 151 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_BEACON; 152 | 153 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeBeaconList, stage); 154 | scene_manager_previous_scene(app->scene_manager); 155 | } 156 | 157 | // Beacon AP 158 | static void wifi_marauder_scene_script_stage_add_beaconap_callback(void* context, uint32_t index) { 159 | UNUSED(index); 160 | WifiMarauderApp* app = context; 161 | 162 | WifiMarauderScriptStageBeaconAp* stage = 163 | (WifiMarauderScriptStageBeaconAp*)malloc(sizeof(WifiMarauderScriptStageBeaconAp)); 164 | stage->timeout = WIFI_MARAUDER_DEFAULT_TIMEOUT_BEACON; 165 | 166 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeBeaconAp, stage); 167 | scene_manager_previous_scene(app->scene_manager); 168 | } 169 | 170 | // Exec 171 | static void wifi_marauder_scene_script_stage_add_exec_callback(void* context, uint32_t index) { 172 | UNUSED(index); 173 | WifiMarauderApp* app = context; 174 | 175 | WifiMarauderScriptStageExec* stage = 176 | (WifiMarauderScriptStageExec*)malloc(sizeof(WifiMarauderScriptStageExec)); 177 | stage->command = NULL; 178 | 179 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeExec, stage); 180 | scene_manager_previous_scene(app->scene_manager); 181 | } 182 | 183 | // Delay 184 | static void wifi_marauder_scene_script_stage_add_delay_callback(void* context, uint32_t index) { 185 | UNUSED(index); 186 | WifiMarauderApp* app = context; 187 | 188 | WifiMarauderScriptStageDelay* stage = 189 | (WifiMarauderScriptStageDelay*)malloc(sizeof(WifiMarauderScriptStageDelay)); 190 | stage->timeout = 0; 191 | 192 | wifi_marauder_script_add_stage(app->script, WifiMarauderScriptStageTypeDelay, stage); 193 | scene_manager_previous_scene(app->scene_manager); 194 | } 195 | 196 | void wifi_marauder_scene_script_stage_add_on_enter(void* context) { 197 | WifiMarauderApp* app = context; 198 | Submenu* submenu = app->submenu; 199 | submenu_set_header(submenu, "Add stage"); 200 | 201 | int menu_index = 0; 202 | submenu_add_item( 203 | submenu, "[+] Scan", menu_index++, wifi_marauder_scene_script_stage_add_scan_callback, app); 204 | submenu_add_item( 205 | submenu, 206 | "[+] Select", 207 | menu_index++, 208 | wifi_marauder_scene_script_stage_add_select_callback, 209 | app); 210 | submenu_add_item( 211 | submenu, 212 | "[+] Deauth", 213 | menu_index++, 214 | wifi_marauder_scene_script_stage_add_deauth_callback, 215 | app); 216 | submenu_add_item( 217 | submenu, 218 | "[+] Probe", 219 | menu_index++, 220 | wifi_marauder_scene_script_stage_add_probe_callback, 221 | app); 222 | submenu_add_item( 223 | submenu, 224 | "[+] Sniff RAW", 225 | menu_index++, 226 | wifi_marauder_scene_script_stage_add_sniffraw_callback, 227 | app); 228 | submenu_add_item( 229 | submenu, 230 | "[+] Sniff Beacon", 231 | menu_index++, 232 | wifi_marauder_scene_script_stage_add_sniffbeacon_callback, 233 | app); 234 | submenu_add_item( 235 | submenu, 236 | "[+] Sniff Deauth", 237 | menu_index++, 238 | wifi_marauder_scene_script_stage_add_sniffdeauth_callback, 239 | app); 240 | submenu_add_item( 241 | submenu, 242 | "[+] Sniff Esp", 243 | menu_index++, 244 | wifi_marauder_scene_script_stage_add_sniffesp_callback, 245 | app); 246 | submenu_add_item( 247 | submenu, 248 | "[+] Sniff PMKID", 249 | menu_index++, 250 | wifi_marauder_scene_script_stage_add_sniffpmkid_callback, 251 | app); 252 | submenu_add_item( 253 | submenu, 254 | "[+] Sniff Pwnagotchi", 255 | menu_index++, 256 | wifi_marauder_scene_script_stage_add_sniffpwn_callback, 257 | app); 258 | submenu_add_item( 259 | submenu, 260 | "[+] Beacon List", 261 | menu_index++, 262 | wifi_marauder_scene_script_stage_add_beaconlist_callback, 263 | app); 264 | submenu_add_item( 265 | submenu, 266 | "[+] Beacon AP", 267 | menu_index++, 268 | wifi_marauder_scene_script_stage_add_beaconap_callback, 269 | app); 270 | submenu_add_item( 271 | submenu, 272 | "[+] Custom command", 273 | menu_index++, 274 | wifi_marauder_scene_script_stage_add_exec_callback, 275 | app); 276 | submenu_add_item( 277 | submenu, 278 | "[+] Delay", 279 | menu_index++, 280 | wifi_marauder_scene_script_stage_add_delay_callback, 281 | app); 282 | 283 | submenu_set_selected_item( 284 | submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit)); 285 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); 286 | } 287 | 288 | bool wifi_marauder_scene_script_stage_add_on_event(void* context, SceneManagerEvent event) { 289 | UNUSED(context); 290 | UNUSED(event); 291 | return false; 292 | } 293 | 294 | void wifi_marauder_scene_script_stage_add_on_exit(void* context) { 295 | WifiMarauderApp* app = context; 296 | submenu_reset(app->submenu); 297 | } 298 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_script_stage_edit.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_scene_script_stage_edit_create_list_strings( 4 | WifiMarauderApp* app, 5 | char** strings, 6 | int string_count) { 7 | // Deallocates the existing list 8 | WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; 9 | while(current_item != NULL) { 10 | WifiMarauderScriptStageListItem* next_item = current_item->next_item; 11 | free(current_item->value); 12 | free(current_item); 13 | current_item = next_item; 14 | } 15 | 16 | // Create a new list with numbers 17 | WifiMarauderScriptStageListItem* first_item = NULL; 18 | WifiMarauderScriptStageListItem* previous_item = NULL; 19 | for(int i = 0; i < string_count; i++) { 20 | WifiMarauderScriptStageListItem* item = malloc(sizeof(WifiMarauderScriptStageListItem)); 21 | item->value = strdup(strings[i]); 22 | item->next_item = NULL; 23 | 24 | if(previous_item == NULL) { 25 | first_item = item; 26 | } else { 27 | previous_item->next_item = item; 28 | } 29 | previous_item = item; 30 | } 31 | 32 | app->script_stage_edit_first_item = first_item; 33 | } 34 | 35 | void wifi_marauder_scene_script_stage_edit_create_list_numbers( 36 | WifiMarauderApp* app, 37 | int* numbers, 38 | int number_count) { 39 | // Deallocates the existing list 40 | WifiMarauderScriptStageListItem* current_item = app->script_stage_edit_first_item; 41 | while(current_item != NULL) { 42 | WifiMarauderScriptStageListItem* next_item = current_item->next_item; 43 | free(current_item->value); 44 | free(current_item); 45 | current_item = next_item; 46 | } 47 | 48 | // Create a new list with numbers 49 | WifiMarauderScriptStageListItem* first_item = NULL; 50 | WifiMarauderScriptStageListItem* previous_item = NULL; 51 | for(int i = 0; i < number_count; i++) { 52 | char number_str[32]; 53 | snprintf(number_str, sizeof(number_str), "%d", numbers[i]); 54 | 55 | WifiMarauderScriptStageListItem* item = malloc(sizeof(WifiMarauderScriptStageListItem)); 56 | item->value = strdup(number_str); 57 | item->next_item = NULL; 58 | 59 | if(previous_item == NULL) { 60 | first_item = item; 61 | } else { 62 | previous_item->next_item = item; 63 | } 64 | previous_item = item; 65 | } 66 | 67 | app->script_stage_edit_first_item = first_item; 68 | } 69 | 70 | static void 71 | wifi_marauder_scene_script_stage_edit_list_enter_callback(void* context, uint32_t index) { 72 | WifiMarauderApp* app = context; 73 | const WifiMarauderScriptMenuItem* menu_item = &app->script_stage_menu->items[index]; 74 | 75 | // Fixed delete item 76 | if(index == app->script_stage_menu->num_items) { 77 | uint32_t deleted_stage_index = 78 | scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptEdit); 79 | if(deleted_stage_index > 0) { 80 | scene_manager_set_scene_state( 81 | app->scene_manager, WifiMarauderSceneScriptEdit, deleted_stage_index - 1); 82 | } 83 | WifiMarauderScriptStage* previous_stage = NULL; 84 | WifiMarauderScriptStage* current_stage = app->script->first_stage; 85 | uint32_t current_stage_index = 0; 86 | 87 | while(current_stage != NULL && current_stage_index < deleted_stage_index) { 88 | previous_stage = current_stage; 89 | current_stage = current_stage->next_stage; 90 | current_stage_index++; 91 | } 92 | 93 | // Delete the stage 94 | if(current_stage != NULL) { 95 | if(previous_stage != NULL) { 96 | if(current_stage->next_stage != NULL) { 97 | previous_stage->next_stage = current_stage->next_stage; 98 | } else { 99 | previous_stage->next_stage = NULL; 100 | app->script->last_stage = previous_stage; 101 | } 102 | } else { 103 | if(current_stage->next_stage != NULL) { 104 | app->script->first_stage = current_stage->next_stage; 105 | } else { 106 | app->script->first_stage = NULL; 107 | app->script->last_stage = NULL; 108 | } 109 | } 110 | } 111 | app->script_edit_selected_stage = NULL; 112 | 113 | scene_manager_previous_scene(app->scene_manager); 114 | return; 115 | } 116 | 117 | if(menu_item->select_callback == NULL) { 118 | return; 119 | } 120 | if(menu_item->type == WifiMarauderScriptMenuItemTypeNumber) { 121 | // Accepts user number input, assigning the value to the reference passed as a parameter 122 | menu_item->select_callback(app); 123 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit, index); 124 | app->user_input_type = WifiMarauderUserInputTypeNumber; 125 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); 126 | } else if(menu_item->type == WifiMarauderScriptMenuItemTypeString) { 127 | // Accepts user string input, assigning the value to the reference passed as a parameter 128 | menu_item->select_callback(app); 129 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit, index); 130 | app->user_input_type = WifiMarauderUserInputTypeString; 131 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneUserInput); 132 | } else if(menu_item->type == WifiMarauderScriptMenuItemTypeListString) { 133 | // Accepts the strings that compose the list 134 | menu_item->select_callback(app); 135 | wifi_marauder_scene_script_stage_edit_create_list_strings( 136 | app, 137 | *app->script_stage_edit_strings_reference, 138 | *app->script_stage_edit_string_count_reference); 139 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit, index); 140 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptStageEditList); 141 | } else if(menu_item->type == WifiMarauderScriptMenuItemTypeListNumber) { 142 | // Accepts the numbers that compose the list 143 | menu_item->select_callback(app); 144 | wifi_marauder_scene_script_stage_edit_create_list_numbers( 145 | app, 146 | *app->script_stage_edit_numbers_reference, 147 | *app->script_stage_edit_number_count_reference); 148 | scene_manager_set_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit, index); 149 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptStageEditList); 150 | } 151 | } 152 | 153 | void wifi_marauder_scene_script_stage_edit_on_enter(void* context) { 154 | WifiMarauderApp* app = context; 155 | VariableItemList* var_item_list = app->var_item_list; 156 | 157 | variable_item_list_set_enter_callback( 158 | app->var_item_list, wifi_marauder_scene_script_stage_edit_list_enter_callback, app); 159 | app->script_stage_menu = 160 | wifi_marauder_script_stage_menu_create(app->script_edit_selected_stage->type); 161 | 162 | if(app->script_stage_menu->items != NULL) { 163 | for(uint32_t i = 0; i < app->script_stage_menu->num_items; i++) { 164 | WifiMarauderScriptMenuItem* stage_item = &app->script_stage_menu->items[i]; 165 | 166 | // Changes the list item to handle it in callbacks 167 | VariableItem* list_item = variable_item_list_add( 168 | app->var_item_list, 169 | stage_item->name, 170 | stage_item->num_options, 171 | stage_item->change_callback, 172 | app); 173 | 174 | variable_item_list_set_selected_item(app->var_item_list, i); 175 | if(stage_item->setup_callback != NULL) { 176 | stage_item->setup_callback(list_item); 177 | } 178 | if(stage_item->change_callback != NULL) { 179 | stage_item->change_callback(list_item); 180 | } 181 | } 182 | } 183 | 184 | variable_item_list_add(app->var_item_list, "[-] DELETE STAGE", 0, NULL, app); 185 | 186 | variable_item_list_set_selected_item( 187 | var_item_list, 188 | scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneScriptStageEdit)); 189 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); 190 | } 191 | 192 | bool wifi_marauder_scene_script_stage_edit_on_event(void* context, SceneManagerEvent event) { 193 | UNUSED(context); 194 | UNUSED(event); 195 | return false; 196 | } 197 | 198 | void wifi_marauder_scene_script_stage_edit_on_exit(void* context) { 199 | WifiMarauderApp* app = context; 200 | wifi_marauder_script_stage_menu_free(app->script_stage_menu); 201 | app->script_stage_menu = NULL; 202 | variable_item_list_reset(app->var_item_list); 203 | } 204 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_settings_init.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | const char* Y = "Y"; 4 | const char* N = "N"; 5 | 6 | #define PROMPT_PCAPS 0 7 | #define PROMPT_LOGS 1 8 | 9 | void wifi_marauder_scene_settings_init_widget_callback( 10 | GuiButtonType result, 11 | InputType type, 12 | void* context) { 13 | WifiMarauderApp* app = context; 14 | if(type == InputTypeShort) { 15 | view_dispatcher_send_custom_event(app->view_dispatcher, result); 16 | } 17 | } 18 | 19 | void wifi_marauder_scene_settings_init_setup_widget(WifiMarauderApp* app) { 20 | Widget* widget = app->widget; 21 | 22 | widget_reset(widget); 23 | 24 | widget_add_button_element( 25 | widget, GuiButtonTypeLeft, "No", wifi_marauder_scene_settings_init_widget_callback, app); 26 | widget_add_button_element( 27 | widget, GuiButtonTypeRight, "Yes", wifi_marauder_scene_settings_init_widget_callback, app); 28 | 29 | if(app->which_prompt == PROMPT_PCAPS) { 30 | widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Save pcaps?"); 31 | widget_add_text_scroll_element( 32 | widget, 33 | 0, 34 | 12, 35 | 128, 36 | 38, 37 | "With compatible marauder\nfirmware, you can choose to\nsave captures (pcaps) to the\nflipper sd card here:\n" MARAUDER_APP_FOLDER_USER_PCAPS 38 | "\n\nYou can change this setting in the app at any time. Would\nyou like to enable this feature now?"); 39 | } else { 40 | widget_add_string_element(widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Save logs?"); 41 | widget_add_text_scroll_element( 42 | widget, 43 | 0, 44 | 12, 45 | 128, 46 | 38, 47 | "This app supports saving text\nlogs of console output to the\nflipper sd card here:\n" MARAUDER_APP_FOLDER_USER_LOGS 48 | "\n\nYou can change this setting in the app at any time. Would\nyou like to enable this feature now?"); 49 | } 50 | } 51 | 52 | void wifi_marauder_scene_settings_init_on_enter(void* context) { 53 | WifiMarauderApp* app = context; 54 | 55 | app->which_prompt = PROMPT_PCAPS; 56 | wifi_marauder_scene_settings_init_setup_widget(app); 57 | 58 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewWidget); 59 | } 60 | 61 | bool wifi_marauder_scene_settings_init_on_event(void* context, SceneManagerEvent event) { 62 | WifiMarauderApp* app = context; 63 | bool consumed = false; 64 | 65 | if(event.type == SceneManagerEventTypeCustom) { 66 | // get which button press: "Yes" or "No" 67 | if(event.event == GuiButtonTypeRight) { 68 | // Yes 69 | if(app->which_prompt == PROMPT_PCAPS) { 70 | app->ok_to_save_pcaps = true; 71 | } else { 72 | app->ok_to_save_logs = true; 73 | } 74 | } else if(event.event == GuiButtonTypeLeft) { 75 | // No 76 | if(app->which_prompt == PROMPT_PCAPS) { 77 | app->ok_to_save_pcaps = false; 78 | } else { 79 | app->ok_to_save_logs = false; 80 | } 81 | } 82 | 83 | // save setting to file, load next widget or scene 84 | if(app->which_prompt == PROMPT_PCAPS) { 85 | if(storage_file_open( 86 | app->save_pcap_setting_file, 87 | SAVE_PCAP_SETTING_FILEPATH, 88 | FSAM_WRITE, 89 | FSOM_CREATE_ALWAYS)) { 90 | const char* ok = app->ok_to_save_pcaps ? Y : N; 91 | storage_file_write(app->save_pcap_setting_file, ok, sizeof(ok)); 92 | } else { 93 | dialog_message_show_storage_error(app->dialogs, "Cannot save settings"); 94 | } 95 | storage_file_close(app->save_pcap_setting_file); 96 | // same scene, different-looking widget 97 | app->which_prompt = PROMPT_LOGS; 98 | wifi_marauder_scene_settings_init_setup_widget(app); 99 | } else { 100 | if(storage_file_open( 101 | app->save_logs_setting_file, 102 | SAVE_LOGS_SETTING_FILEPATH, 103 | FSAM_WRITE, 104 | FSOM_CREATE_ALWAYS)) { 105 | const char* ok = app->ok_to_save_logs ? Y : N; 106 | storage_file_write(app->save_logs_setting_file, ok, sizeof(ok)); 107 | } else { 108 | dialog_message_show_storage_error(app->dialogs, "Cannot save settings"); 109 | } 110 | storage_file_close(app->save_logs_setting_file); 111 | // go back to start scene (main menu) 112 | app->need_to_prompt_settings_init = false; 113 | scene_manager_previous_scene(app->scene_manager); 114 | } 115 | consumed = true; 116 | } 117 | 118 | return consumed; 119 | } 120 | 121 | void wifi_marauder_scene_settings_init_on_exit(void* context) { 122 | WifiMarauderApp* app = context; 123 | widget_reset(app->widget); 124 | if(storage_file_is_open(app->save_pcap_setting_file)) { 125 | storage_file_close(app->save_pcap_setting_file); 126 | } 127 | if(storage_file_is_open(app->save_logs_setting_file)) { 128 | storage_file_close(app->save_logs_setting_file); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_sniffpmkid_options.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | enum SubmenuIndex { 4 | SubmenuIndexPassive, 5 | SubmenuIndexActive, 6 | SubmenuIndexTargetedPassive, 7 | SubmenuIndexTargetedActive, 8 | SubmenuIndexChannelPassive, 9 | SubmenuIndexChannelActive, 10 | }; 11 | 12 | static void wifi_marauder_scene_sniffpmkid_options_callback(void* context, uint32_t index) { 13 | WifiMarauderApp* app = context; 14 | 15 | app->is_custom_tx_string = false; // this will be set if needed by text input 16 | switch(index) { 17 | case SubmenuIndexPassive: 18 | app->selected_tx_string = "sniffpmkid"; 19 | scene_manager_set_scene_state( 20 | app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); 21 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); 22 | break; 23 | case SubmenuIndexActive: 24 | app->selected_tx_string = "sniffpmkid -d"; 25 | scene_manager_set_scene_state( 26 | app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); 27 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); 28 | break; 29 | case SubmenuIndexTargetedPassive: 30 | app->selected_tx_string = "sniffpmkid -l"; 31 | scene_manager_set_scene_state( 32 | app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); 33 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); 34 | break; 35 | case SubmenuIndexTargetedActive: 36 | app->selected_tx_string = "sniffpmkid -d -l"; 37 | scene_manager_set_scene_state( 38 | app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); 39 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); 40 | break; 41 | case SubmenuIndexChannelPassive: 42 | app->selected_tx_string = "sniffpmkid -c"; 43 | scene_manager_set_scene_state( 44 | app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); 45 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput); 46 | break; 47 | case SubmenuIndexChannelActive: 48 | app->selected_tx_string = "sniffpmkid -d -c"; 49 | scene_manager_set_scene_state( 50 | app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index); 51 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput); 52 | break; 53 | } 54 | } 55 | 56 | void wifi_marauder_scene_sniffpmkid_options_on_enter(void* context) { 57 | WifiMarauderApp* app = context; 58 | 59 | Submenu* submenu = app->submenu; 60 | 61 | submenu_set_header(submenu, "Sniff PMKID"); 62 | submenu_add_item( 63 | submenu, 64 | "Passive", 65 | SubmenuIndexPassive, 66 | wifi_marauder_scene_sniffpmkid_options_callback, 67 | app); 68 | submenu_add_item( 69 | submenu, 70 | "Active (Force Deauth)", 71 | SubmenuIndexActive, 72 | wifi_marauder_scene_sniffpmkid_options_callback, 73 | app); 74 | submenu_add_item( 75 | submenu, 76 | "Targeted Passive (List)", 77 | SubmenuIndexTargetedPassive, 78 | wifi_marauder_scene_sniffpmkid_options_callback, 79 | app); 80 | submenu_add_item( 81 | submenu, 82 | "Targeted Active (List)", 83 | SubmenuIndexTargetedActive, 84 | wifi_marauder_scene_sniffpmkid_options_callback, 85 | app); 86 | submenu_add_item( 87 | submenu, 88 | "On Channel # - Passive", 89 | SubmenuIndexChannelPassive, 90 | wifi_marauder_scene_sniffpmkid_options_callback, 91 | app); 92 | submenu_add_item( 93 | submenu, 94 | "On Channel # - Active", 95 | SubmenuIndexChannelActive, 96 | wifi_marauder_scene_sniffpmkid_options_callback, 97 | app); 98 | 99 | submenu_set_selected_item( 100 | submenu, 101 | scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneSniffPmkidOptions)); 102 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); 103 | } 104 | 105 | bool wifi_marauder_scene_sniffpmkid_options_on_event(void* context, SceneManagerEvent event) { 106 | //WifiMarauderApp* app = context; 107 | UNUSED(context); 108 | UNUSED(event); 109 | bool consumed = false; 110 | 111 | return consumed; 112 | } 113 | 114 | void wifi_marauder_scene_sniffpmkid_options_on_exit(void* context) { 115 | WifiMarauderApp* app = context; 116 | submenu_reset(app->submenu); 117 | } 118 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_start.c: -------------------------------------------------------------------------------- 1 | //** Includes sniffbt and sniffskim for compatible ESP32-WROOM hardware. 2 | //wifi_marauder_app_i.h also changed **// 3 | #include "../wifi_marauder_app_i.h" 4 | 5 | // For each command, define whether additional arguments are needed 6 | // (enabling text input to fill them out), and whether the console 7 | // text box should focus at the start of the output or the end 8 | typedef enum { NO_ARGS = 0, INPUT_ARGS, TOGGLE_ARGS } InputArgs; 9 | 10 | typedef enum { FOCUS_CONSOLE_END = 0, FOCUS_CONSOLE_START, FOCUS_CONSOLE_TOGGLE } FocusConsole; 11 | 12 | #define SHOW_STOPSCAN_TIP (true) 13 | #define NO_TIP (false) 14 | 15 | #define MAX_OPTIONS (13) 16 | typedef struct { 17 | const char* item_string; 18 | const char* options_menu[MAX_OPTIONS]; 19 | int num_options_menu; 20 | const char* actual_commands[MAX_OPTIONS]; 21 | InputArgs needs_keyboard; 22 | FocusConsole focus_console; 23 | bool show_stopscan_tip; 24 | } WifiMarauderItem; 25 | 26 | // NUM_MENU_ITEMS defined in wifi_marauder_app_i.h - if you add an entry here, increment it! 27 | const WifiMarauderItem items[NUM_MENU_ITEMS] = { 28 | {"View Log from", {"start", "end"}, 2, {"", ""}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP}, 29 | {"Scan", 30 | {"all", "ap", "station"}, 31 | 3, 32 | {"scanall", "scanap", "scansta"}, 33 | NO_ARGS, 34 | FOCUS_CONSOLE_END, 35 | SHOW_STOPSCAN_TIP}, 36 | {"SSID", 37 | {"add rand", "add name", "remove"}, 38 | 3, 39 | {"ssid -a -g", "ssid -a -n", "ssid -r"}, 40 | INPUT_ARGS, 41 | FOCUS_CONSOLE_START, 42 | NO_TIP}, 43 | {"List", 44 | {"ap", "ssid", "station", "airtag"}, 45 | 4, 46 | {"list -a", "list -s", "list -c", "list -t"}, 47 | NO_ARGS, 48 | FOCUS_CONSOLE_START, 49 | NO_TIP}, 50 | {"AP Info", 51 | {""}, 52 | 1, 53 | {"info -a"}, 54 | INPUT_ARGS, 55 | FOCUS_CONSOLE_END, 56 | NO_TIP}, 57 | {"Select", 58 | {"ap", "ssid", "station"}, 59 | 3, 60 | {"select -a", "select -s", "select -c"}, 61 | INPUT_ARGS, 62 | FOCUS_CONSOLE_END, 63 | NO_TIP}, 64 | {"Clear List", 65 | {"ap", "ssid", "station"}, 66 | 3, 67 | {"clearlist -a", "clearlist -s", "clearlist -c"}, 68 | NO_ARGS, 69 | FOCUS_CONSOLE_END, 70 | NO_TIP}, 71 | {"Attack", 72 | {"deauth", 73 | "probe", 74 | "rickroll", 75 | "sour apple", 76 | "swiftpair spam", 77 | "samsung spam", 78 | "google spam", 79 | "flipper spam", 80 | "bt spam all"}, 81 | 9, 82 | {"attack -t deauth", 83 | "attack -t probe", 84 | "attack -t rickroll", 85 | "blespam -t apple", 86 | "blespam -t windows", 87 | "blespam -t samsung", 88 | "blespam -t google", 89 | "blespam -t flipper", 90 | "blespam -t all"}, 91 | NO_ARGS, 92 | FOCUS_CONSOLE_END, 93 | SHOW_STOPSCAN_TIP}, 94 | {"Spoof Airtag", 95 | {""}, 96 | 1, 97 | {"spoofat -t"}, 98 | INPUT_ARGS, 99 | FOCUS_CONSOLE_END, 100 | NO_TIP}, 101 | {"Wardrive", 102 | {"ap", "station", "bt", "bt cont"}, 103 | 4, 104 | {"wardrive", "wardrive -s", "btwardrive", "btwardrive -c"}, 105 | NO_ARGS, 106 | FOCUS_CONSOLE_END, 107 | SHOW_STOPSCAN_TIP}, 108 | {"Evil Portal", 109 | {"start", "set html"}, 110 | 2, 111 | {"evilportal -c start", "evilportal -c sethtml"}, 112 | TOGGLE_ARGS, 113 | FOCUS_CONSOLE_END, 114 | SHOW_STOPSCAN_TIP}, 115 | {"Load Evil Portal HTML file", 116 | {""}, 117 | 1, 118 | {"evilportal -c sethtmlstr"}, 119 | NO_ARGS, 120 | FOCUS_CONSOLE_END, 121 | NO_TIP}, 122 | {"Targeted Deauth", 123 | {"station", "manual"}, 124 | 2, 125 | {"attack -t deauth -c", "attack -t deauth -s"}, 126 | TOGGLE_ARGS, 127 | FOCUS_CONSOLE_END, 128 | SHOW_STOPSCAN_TIP}, 129 | {"Beacon Spam", 130 | {"ap list", "ssid list", "random"}, 131 | 3, 132 | {"attack -t beacon -a", "attack -t beacon -l", "attack -t beacon -r"}, 133 | NO_ARGS, 134 | FOCUS_CONSOLE_END, 135 | SHOW_STOPSCAN_TIP}, 136 | {"Sniff", 137 | {"beacon", "deauth", "pmkid", "probe", "pwn", "raw", "bt", "skim", "airtag", "flipper", "packetcount", "pineapple", "multissid"}, 138 | 13, 139 | {"sniffbeacon", 140 | "sniffdeauth", 141 | "sniffpmkid", 142 | "sniffprobe", 143 | "sniffpwn", 144 | "sniffraw", 145 | "sniffbt", 146 | "sniffskim", 147 | "sniffbt -t airtag", 148 | "sniffbt -t flipper", 149 | "packetcount", 150 | "sniffpinescan", 151 | "sniffmultissid"}, 152 | NO_ARGS, 153 | FOCUS_CONSOLE_END, 154 | SHOW_STOPSCAN_TIP}, 155 | {"Signal Monitor", {""}, 1, {"sigmon"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, 156 | {"Channel", 157 | {"get", "set"}, 158 | 2, 159 | {"channel", "channel -s"}, 160 | TOGGLE_ARGS, 161 | FOCUS_CONSOLE_END, 162 | NO_TIP}, 163 | {"LED", {"hex", "pattern"}, 2, {"led -s", "led -p"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, 164 | {"GPS Data", 165 | {"stream", "fix", "sats", "lat", "lon", "alt", "date"}, 166 | 7, 167 | {"gpsdata", 168 | "gps -g fix", 169 | "gps -g sat", 170 | "gps -g lat", 171 | "gps -g lon", 172 | "gps -g alt", 173 | "gps -g date"}, 174 | NO_ARGS, 175 | FOCUS_CONSOLE_END, 176 | NO_TIP}, 177 | {"Settings", 178 | {"display", "restore", "ForcePMKID", "ForceProbe", "SavePCAP", "EnableLED", "other"}, 179 | 7, 180 | {"settings", 181 | "settings -r", 182 | "settings -s ForcePMKID enable", 183 | "settings -s ForceProbe enable", 184 | "settings -s SavePCAP enable", 185 | "settings -s EnableLED enable", 186 | "settings -s"}, 187 | TOGGLE_ARGS, 188 | FOCUS_CONSOLE_START, 189 | NO_TIP}, 190 | {"List SD", {""}, 1, {"ls /"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, 191 | {"Update", {"sd"}, 1, {"update -s"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, 192 | {"Reboot", {""}, 1, {"reboot"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, 193 | {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, 194 | {"Info", {""}, 1, {"info"}, NO_ARGS, FOCUS_CONSOLE_START, NO_TIP}, 195 | {"Scripts", {""}, 1, {""}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, 196 | {"Save to flipper sdcard", // keep as last entry or change logic in callback below 197 | {""}, 198 | 1, 199 | {""}, 200 | NO_ARGS, 201 | FOCUS_CONSOLE_START, 202 | NO_TIP}, 203 | }; 204 | 205 | static void wifi_marauder_scene_start_var_list_enter_callback(void* context, uint32_t index) { 206 | furi_assert(context); 207 | WifiMarauderApp* app = context; 208 | 209 | furi_assert(index < NUM_MENU_ITEMS); 210 | const WifiMarauderItem* item = &items[index]; 211 | 212 | const int selected_option_index = app->selected_option_index[index]; 213 | furi_assert(selected_option_index < item->num_options_menu); 214 | app->selected_tx_string = item->actual_commands[selected_option_index]; 215 | app->is_command = (1 <= index); 216 | app->is_custom_tx_string = false; 217 | app->selected_menu_index = index; 218 | app->focus_console_start = (item->focus_console == FOCUS_CONSOLE_TOGGLE) ? 219 | (selected_option_index == 0) : 220 | item->focus_console; 221 | app->show_stopscan_tip = item->show_stopscan_tip; 222 | 223 | if(!app->is_command && selected_option_index == 0) { 224 | // View Log from start 225 | view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartLogViewer); 226 | return; 227 | } 228 | 229 | if(app->selected_tx_string && 230 | strncmp("sniffpmkid", app->selected_tx_string, strlen("sniffpmkid")) == 0) { 231 | // sniffpmkid submenu 232 | view_dispatcher_send_custom_event( 233 | app->view_dispatcher, WifiMarauderEventStartSniffPmkidOptions); 234 | return; 235 | } 236 | 237 | // Select automation script 238 | if(index == NUM_MENU_ITEMS - 2) { 239 | view_dispatcher_send_custom_event( 240 | app->view_dispatcher, WifiMarauderEventStartScriptSelect); 241 | return; 242 | } 243 | 244 | if(index == NUM_MENU_ITEMS - 1) { 245 | // "Save to flipper sdcard" special case - start SettingsInit widget 246 | view_dispatcher_send_custom_event( 247 | app->view_dispatcher, WifiMarauderEventStartSettingsInit); 248 | return; 249 | } 250 | 251 | bool needs_keyboard = (item->needs_keyboard == TOGGLE_ARGS) ? (selected_option_index != 0) : 252 | item->needs_keyboard; 253 | if(needs_keyboard) { 254 | view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartKeyboard); 255 | } else { 256 | view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole); 257 | } 258 | } 259 | 260 | static void wifi_marauder_scene_start_var_list_change_callback(VariableItem* item) { 261 | furi_assert(item); 262 | 263 | WifiMarauderApp* app = variable_item_get_context(item); 264 | furi_assert(app); 265 | 266 | const WifiMarauderItem* menu_item = &items[app->selected_menu_index]; 267 | uint8_t item_index = variable_item_get_current_value_index(item); 268 | furi_assert(item_index < menu_item->num_options_menu); 269 | variable_item_set_current_value_text(item, menu_item->options_menu[item_index]); 270 | app->selected_option_index[app->selected_menu_index] = item_index; 271 | } 272 | 273 | void wifi_marauder_scene_start_on_enter(void* context) { 274 | WifiMarauderApp* app = context; 275 | VariableItemList* var_item_list = app->var_item_list; 276 | 277 | variable_item_list_set_enter_callback( 278 | var_item_list, wifi_marauder_scene_start_var_list_enter_callback, app); 279 | 280 | VariableItem* item; 281 | for(int i = 0; i < NUM_MENU_ITEMS; ++i) { 282 | item = variable_item_list_add( 283 | var_item_list, 284 | items[i].item_string, 285 | items[i].num_options_menu, 286 | wifi_marauder_scene_start_var_list_change_callback, 287 | app); 288 | variable_item_set_current_value_index(item, app->selected_option_index[i]); 289 | variable_item_set_current_value_text( 290 | item, items[i].options_menu[app->selected_option_index[i]]); 291 | } 292 | 293 | variable_item_list_set_selected_item( 294 | var_item_list, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneStart)); 295 | 296 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); 297 | 298 | // Wait, if the user hasn't initialized sdcard settings, let's prompt them once (then come back here) 299 | if(app->need_to_prompt_settings_init) { 300 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSettingsInit); 301 | } 302 | } 303 | 304 | bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event) { 305 | UNUSED(context); 306 | WifiMarauderApp* app = context; 307 | bool consumed = false; 308 | 309 | if(event.type == SceneManagerEventTypeCustom) { 310 | if(event.event == WifiMarauderEventStartKeyboard) { 311 | scene_manager_set_scene_state( 312 | app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); 313 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput); 314 | } else if(event.event == WifiMarauderEventStartConsole) { 315 | scene_manager_set_scene_state( 316 | app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); 317 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); 318 | } else if(event.event == WifiMarauderEventStartSettingsInit) { 319 | scene_manager_set_scene_state( 320 | app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); 321 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSettingsInit); 322 | } else if(event.event == WifiMarauderEventStartLogViewer) { 323 | scene_manager_set_scene_state( 324 | app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); 325 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneLogViewer); 326 | } else if(event.event == WifiMarauderEventStartScriptSelect) { 327 | scene_manager_set_scene_state( 328 | app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); 329 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptSelect); 330 | } else if(event.event == WifiMarauderEventStartSniffPmkidOptions) { 331 | scene_manager_set_scene_state( 332 | app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index); 333 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSniffPmkidOptions); 334 | } 335 | consumed = true; 336 | } else if(event.type == SceneManagerEventTypeTick) { 337 | app->selected_menu_index = variable_item_list_get_selected_item_index(app->var_item_list); 338 | consumed = true; 339 | } else if(event.type == SceneManagerEventTypeBack) { 340 | scene_manager_stop(app->scene_manager); 341 | view_dispatcher_stop(app->view_dispatcher); 342 | consumed = true; 343 | } 344 | 345 | return consumed; 346 | } 347 | 348 | void wifi_marauder_scene_start_on_exit(void* context) { 349 | WifiMarauderApp* app = context; 350 | variable_item_list_reset(app->var_item_list); 351 | } 352 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_text_input.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_scene_text_input_callback(void* context) { 4 | WifiMarauderApp* app = context; 5 | 6 | switch(app->special_case_input_step) { 7 | case 0: // most commands 8 | view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole); 9 | break; 10 | case 1: // special case for deauth: save source MAC 11 | view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventSaveSourceMac); 12 | break; 13 | case 2: // special case for deauth: save destination MAC 14 | view_dispatcher_send_custom_event( 15 | app->view_dispatcher, WifiMarauderEventSaveDestinationMac); 16 | break; 17 | default: 18 | break; 19 | } 20 | } 21 | 22 | void wifi_marauder_scene_text_input_on_enter(void* context) { 23 | WifiMarauderApp* app = context; 24 | 25 | if(0 == 26 | strncmp("attack -t deauth -s", app->selected_tx_string, strlen("attack -t deauth -s"))) { 27 | // Special case for manual deauth input 28 | app->special_case_input_step = 1; 29 | bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); 30 | } else if(false == app->is_custom_tx_string) { 31 | // Most commands 32 | app->special_case_input_step = 0; 33 | 34 | // Fill text input with selected string so that user can add to it 35 | size_t length = strlen(app->selected_tx_string); 36 | furi_assert(length < WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); 37 | bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); 38 | strncpy(app->text_input_store, app->selected_tx_string, length); 39 | 40 | // Add space - because flipper keyboard currently doesn't have a space 41 | app->text_input_store[length] = ' '; 42 | app->text_input_store[length + 1] = '\0'; 43 | app->is_custom_tx_string = true; 44 | } 45 | 46 | // Setup view 47 | WIFI_TextInput* text_input = app->text_input; 48 | // Add help message to header 49 | if(app->special_case_input_step == 1) { 50 | wifi_text_input_set_header_text(text_input, "Enter source MAC"); 51 | } else if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) { 52 | wifi_text_input_set_header_text(text_input, "Enter # SSIDs to generate"); 53 | } else if(0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) { 54 | wifi_text_input_set_header_text(text_input, "Enter SSID name to add"); 55 | } else if(0 == strncmp("ssid -r", app->selected_tx_string, strlen("ssid -r"))) { 56 | wifi_text_input_set_header_text(text_input, "Remove target from SSID list"); 57 | } else if(0 == strncmp("select -a", app->selected_tx_string, strlen("select -a"))) { 58 | wifi_text_input_set_header_text(text_input, "Add target from AP list"); 59 | } else if(0 == strncmp("select -s", app->selected_tx_string, strlen("select -s"))) { 60 | wifi_text_input_set_header_text(text_input, "Add target from SSID list"); 61 | } else { 62 | wifi_text_input_set_header_text(text_input, "Add command arguments"); 63 | } 64 | wifi_text_input_set_result_callback( 65 | text_input, 66 | wifi_marauder_scene_text_input_callback, 67 | app, 68 | app->text_input_store, 69 | WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE, 70 | false); 71 | 72 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewTextInput); 73 | } 74 | 75 | bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent event) { 76 | WifiMarauderApp* app = context; 77 | bool consumed = false; 78 | 79 | if(event.type == SceneManagerEventTypeCustom) { 80 | if(event.event == WifiMarauderEventStartConsole) { 81 | // Point to custom string to send 82 | app->selected_tx_string = app->text_input_store; 83 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); 84 | consumed = true; 85 | } else if(event.event == WifiMarauderEventSaveSourceMac) { 86 | if(12 != strlen(app->text_input_store)) { 87 | wifi_text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); 88 | } else { 89 | snprintf( 90 | app->special_case_input_src_addr, 91 | sizeof(app->special_case_input_src_addr), 92 | "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", 93 | app->text_input_store[0], 94 | app->text_input_store[1], 95 | app->text_input_store[2], 96 | app->text_input_store[3], 97 | app->text_input_store[4], 98 | app->text_input_store[5], 99 | app->text_input_store[6], 100 | app->text_input_store[7], 101 | app->text_input_store[8], 102 | app->text_input_store[9], 103 | app->text_input_store[10], 104 | app->text_input_store[11]); 105 | 106 | // Advance scene to input destination MAC, clear text input 107 | app->special_case_input_step = 2; 108 | bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); 109 | wifi_text_input_set_header_text(app->text_input, "Enter destination MAC"); 110 | } 111 | consumed = true; 112 | } else if(event.event == WifiMarauderEventSaveDestinationMac) { 113 | if(12 != strlen(app->text_input_store)) { 114 | wifi_text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); 115 | } else { 116 | snprintf( 117 | app->special_case_input_dst_addr, 118 | sizeof(app->special_case_input_dst_addr), 119 | "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", 120 | app->text_input_store[0], 121 | app->text_input_store[1], 122 | app->text_input_store[2], 123 | app->text_input_store[3], 124 | app->text_input_store[4], 125 | app->text_input_store[5], 126 | app->text_input_store[6], 127 | app->text_input_store[7], 128 | app->text_input_store[8], 129 | app->text_input_store[9], 130 | app->text_input_store[10], 131 | app->text_input_store[11]); 132 | 133 | // Construct command with source and destination MACs 134 | snprintf( 135 | app->text_input_store, 136 | WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE, 137 | "attack -t deauth -s %18s -d %18s", 138 | app->special_case_input_src_addr, 139 | app->special_case_input_dst_addr); 140 | app->selected_tx_string = app->text_input_store; 141 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); 142 | } 143 | consumed = true; 144 | } 145 | } 146 | 147 | return consumed; 148 | } 149 | 150 | void wifi_marauder_scene_text_input_on_exit(void* context) { 151 | WifiMarauderApp* app = context; 152 | 153 | wifi_text_input_reset(app->text_input); 154 | } 155 | -------------------------------------------------------------------------------- /scenes/wifi_marauder_scene_user_input.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | 3 | bool wifi_marauder_scene_user_input_validator_number_callback( 4 | const char* text, 5 | FuriString* error, 6 | void* context) { 7 | UNUSED(context); 8 | for(int i = 0; text[i] != '\0'; i++) { 9 | if(text[i] < '0' || text[i] > '9') { 10 | furi_string_printf(error, "This is not\na valid\nnumber!"); 11 | return false; 12 | } 13 | } 14 | return true; 15 | } 16 | 17 | bool wifi_marauder_scene_user_input_validator_file_callback( 18 | const char* text, 19 | FuriString* error, 20 | void* context) { 21 | UNUSED(context); 22 | if(strlen(text) == 0) { 23 | furi_string_printf(error, "File name\ncannot be\nblank!"); 24 | return false; 25 | } 26 | return true; 27 | } 28 | 29 | void wifi_marauder_scene_user_input_ok_callback(void* context) { 30 | WifiMarauderApp* app = context; 31 | 32 | File* file = NULL; 33 | char* file_path = NULL; 34 | 35 | switch(app->user_input_type) { 36 | // Writes the string value of the reference 37 | case WifiMarauderUserInputTypeString: 38 | if(app->user_input_string_reference != NULL) { 39 | strncpy( 40 | *app->user_input_string_reference, 41 | app->text_input_store, 42 | strlen(app->text_input_store) + 1); 43 | app->user_input_string_reference = NULL; 44 | } 45 | break; 46 | // Writes the numerical value of the reference 47 | case WifiMarauderUserInputTypeNumber: 48 | if(app->user_input_number_reference != NULL) { 49 | *app->user_input_number_reference = atoi(app->text_input_store); 50 | app->user_input_number_reference = NULL; 51 | } 52 | break; 53 | // Creates a file with the name entered by the user, if it does not exist 54 | case WifiMarauderUserInputTypeFileName: 55 | file = storage_file_alloc(app->storage); 56 | // Use application directory if not specified 57 | if(app->user_input_file_dir == NULL) { 58 | app->user_input_file_dir = strdup(MARAUDER_APP_FOLDER); 59 | } 60 | if(app->user_input_file_extension != NULL) { 61 | size_t file_path_len = strlen(app->user_input_file_dir) + 62 | strlen(app->text_input_store) + 63 | strlen(app->user_input_file_extension) + 3; 64 | file_path = (char*)malloc(file_path_len); 65 | snprintf( 66 | file_path, 67 | file_path_len, 68 | "%s/%s.%s", 69 | app->user_input_file_dir, 70 | app->text_input_store, 71 | app->user_input_file_extension); 72 | } else { 73 | size_t file_path_len = 74 | strlen(app->user_input_file_dir) + strlen(app->text_input_store) + 2; 75 | file_path = (char*)malloc(file_path_len); 76 | snprintf( 77 | file_path, file_path_len, "%s/%s", app->user_input_file_dir, app->text_input_store); 78 | } 79 | if(storage_file_open(file, file_path, FSAM_WRITE, FSOM_CREATE_NEW)) { 80 | storage_file_close(file); 81 | } 82 | // Free memory 83 | free(app->user_input_file_dir); 84 | app->user_input_file_dir = NULL; 85 | free(app->user_input_file_extension); 86 | app->user_input_file_extension = NULL; 87 | free(file_path); 88 | storage_file_free(file); 89 | break; 90 | default: 91 | break; 92 | } 93 | 94 | view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventPrevScene); 95 | } 96 | 97 | void wifi_marauder_scene_user_input_on_enter(void* context) { 98 | WifiMarauderApp* app = context; 99 | 100 | switch(app->user_input_type) { 101 | // Loads the string value of the reference 102 | case WifiMarauderUserInputTypeString: 103 | wifi_text_input_set_header_text(app->text_input, "Enter value:"); 104 | wifi_text_input_set_validator(app->text_input, NULL, app); 105 | if(app->user_input_string_reference != NULL) { 106 | strncpy( 107 | app->text_input_store, 108 | *app->user_input_string_reference, 109 | strlen(*app->user_input_string_reference) + 1); 110 | } 111 | break; 112 | // Loads the numerical value of the reference 113 | case WifiMarauderUserInputTypeNumber: 114 | wifi_text_input_set_header_text(app->text_input, "Enter a valid number:"); 115 | wifi_text_input_set_validator( 116 | app->text_input, wifi_marauder_scene_user_input_validator_number_callback, app); 117 | if(app->user_input_number_reference != NULL) { 118 | char number_str[32]; 119 | snprintf(number_str, sizeof(number_str), "%d", *app->user_input_number_reference); 120 | strncpy(app->text_input_store, number_str, strlen(number_str) + 1); 121 | } 122 | break; 123 | // File name 124 | case WifiMarauderUserInputTypeFileName: 125 | wifi_text_input_set_header_text(app->text_input, "Enter file name:"); 126 | wifi_text_input_set_validator( 127 | app->text_input, wifi_marauder_scene_user_input_validator_file_callback, app); 128 | break; 129 | default: 130 | scene_manager_previous_scene(app->scene_manager); 131 | return; 132 | } 133 | 134 | wifi_text_input_set_result_callback( 135 | app->text_input, 136 | wifi_marauder_scene_user_input_ok_callback, 137 | app, 138 | app->text_input_store, 139 | WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE, 140 | false); 141 | 142 | view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewTextInput); 143 | } 144 | 145 | bool wifi_marauder_scene_user_input_on_event(void* context, SceneManagerEvent event) { 146 | WifiMarauderApp* app = context; 147 | 148 | bool consumed = false; 149 | 150 | if(event.type == SceneManagerEventTypeCustom) { 151 | if(event.event == WifiMarauderEventPrevScene) { 152 | scene_manager_previous_scene(app->scene_manager); 153 | consumed = true; 154 | } 155 | } 156 | 157 | return consumed; 158 | } 159 | 160 | void wifi_marauder_scene_user_input_on_exit(void* context) { 161 | WifiMarauderApp* app = context; 162 | memset(app->text_input_store, 0, sizeof(app->text_input_store)); 163 | wifi_text_input_reset(app->text_input); 164 | } 165 | -------------------------------------------------------------------------------- /screenshots/marauder-save-pcaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/screenshots/marauder-save-pcaps.png -------------------------------------------------------------------------------- /screenshots/marauder-script-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/screenshots/marauder-script-demo.png -------------------------------------------------------------------------------- /screenshots/marauder-topmenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/screenshots/marauder-topmenu.png -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu.c: -------------------------------------------------------------------------------- 1 | #include "wifi_marauder_script_stage_menu.h" 2 | 3 | WifiMarauderScriptStageMenu* 4 | wifi_marauder_script_stage_menu_create(WifiMarauderScriptStageType stage_type) { 5 | WifiMarauderScriptStageMenu* script_stage_menu = malloc(sizeof(WifiMarauderScriptStageMenu)); 6 | 7 | switch(stage_type) { 8 | #define ADD_STAGE(name, id) \ 9 | case WifiMarauderScriptStageType##id: \ 10 | wifi_marauder_script_stage_menu_##name##_load(script_stage_menu); \ 11 | break; 12 | 13 | #include "wifi_marauder_script_stage_menu_config.h" 14 | #undef ADD_STAGE 15 | } 16 | return script_stage_menu; 17 | } 18 | 19 | void wifi_marauder_script_stage_menu_free(WifiMarauderScriptStageMenu* stage_menu) { 20 | if(stage_menu == NULL) { 21 | return; 22 | } 23 | for(uint32_t i = 0; i < stage_menu->num_items; i++) { 24 | WifiMarauderScriptMenuItem* item = &(stage_menu->items[i]); 25 | for(int j = 0; j < item->num_options; j++) { 26 | free(item->options[j]); 27 | } 28 | free(item->name); 29 | } 30 | free(stage_menu->items); 31 | free(stage_menu); 32 | } 33 | -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../wifi_marauder_script.h" 5 | 6 | #define ITEM_EDIT_MAX_OPTIONS (12) 7 | 8 | typedef void (*VariableItemSetupCallback)(VariableItem* item); 9 | typedef void (*VariableItemSelectCallback)(void* context); 10 | 11 | typedef enum WifiMarauderScriptMenuItemType { 12 | WifiMarauderScriptMenuItemTypeString, 13 | WifiMarauderScriptMenuItemTypeNumber, 14 | WifiMarauderScriptMenuItemTypeOptionsString, 15 | WifiMarauderScriptMenuItemTypeOptionsNumber, 16 | WifiMarauderScriptMenuItemTypeListString, 17 | WifiMarauderScriptMenuItemTypeListNumber 18 | } WifiMarauderScriptMenuItemType; 19 | 20 | typedef struct WifiMarauderScriptMenuItem { 21 | char* name; 22 | WifiMarauderScriptMenuItemType type; 23 | int num_options; 24 | char* options[ITEM_EDIT_MAX_OPTIONS]; 25 | VariableItemSetupCallback setup_callback; 26 | VariableItemChangeCallback change_callback; 27 | VariableItemSelectCallback select_callback; 28 | } WifiMarauderScriptMenuItem; 29 | 30 | typedef struct WifiMarauderScriptStageMenu { 31 | WifiMarauderScriptMenuItem* items; 32 | uint32_t num_items; 33 | } WifiMarauderScriptStageMenu; 34 | 35 | #define ADD_STAGE(name, id) \ 36 | void wifi_marauder_script_stage_menu_##name##_load(WifiMarauderScriptStageMenu*); 37 | #include "wifi_marauder_script_stage_menu_config.h" 38 | #undef ADD_STAGE 39 | 40 | WifiMarauderScriptStageMenu* 41 | wifi_marauder_script_stage_menu_create(WifiMarauderScriptStageType stage_type); 42 | void wifi_marauder_script_stage_menu_free(WifiMarauderScriptStageMenu* list); 43 | -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_beaconap.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_beaconap_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageBeaconAp* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_beaconap_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageBeaconAp* stage_beaconap = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_beaconap->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_beaconap_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = "Timeout", 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_beaconap_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_beaconap_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_beaconlist.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_beaconlist_stage_ssids_select_callback(void* context) { 4 | WifiMarauderApp* app = context; 5 | WifiMarauderScriptStageBeaconList* stage_beaconlist = app->script_edit_selected_stage->stage; 6 | app->script_stage_edit_strings_reference = &stage_beaconlist->ssids; 7 | app->script_stage_edit_string_count_reference = &stage_beaconlist->ssid_count; 8 | } 9 | 10 | void wifi_marauder_beaconlist_stage_random_ssids_setup_callback(VariableItem* item) { 11 | WifiMarauderApp* app = variable_item_get_context(item); 12 | WifiMarauderScriptStageBeaconList* stage = app->script_edit_selected_stage->stage; 13 | char random_ssids_str[32]; 14 | snprintf(random_ssids_str, sizeof(random_ssids_str), "%d", stage->random_ssids); 15 | variable_item_set_current_value_text(item, random_ssids_str); 16 | } 17 | 18 | void wifi_marauder_beaconlist_stage_random_ssids_select_callback(void* context) { 19 | WifiMarauderApp* app = context; 20 | WifiMarauderScriptStageBeaconList* stage_beaconlist = app->script_edit_selected_stage->stage; 21 | app->user_input_number_reference = &stage_beaconlist->random_ssids; 22 | } 23 | 24 | void wifi_marauder_beaconlist_stage_timeout_setup_callback(VariableItem* item) { 25 | WifiMarauderApp* app = variable_item_get_context(item); 26 | WifiMarauderScriptStageBeaconList* stage = app->script_edit_selected_stage->stage; 27 | char timeout_str[32]; 28 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 29 | variable_item_set_current_value_text(item, timeout_str); 30 | } 31 | 32 | void wifi_marauder_beaconlist_stage_timeout_select_callback(void* context) { 33 | WifiMarauderApp* app = context; 34 | WifiMarauderScriptStageBeaconList* stage_beaconlist = app->script_edit_selected_stage->stage; 35 | app->user_input_number_reference = &stage_beaconlist->timeout; 36 | } 37 | 38 | void wifi_marauder_script_stage_menu_beaconlist_load(WifiMarauderScriptStageMenu* stage_menu) { 39 | stage_menu->num_items = 3; 40 | stage_menu->items = malloc(3 * sizeof(WifiMarauderScriptMenuItem)); 41 | 42 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 43 | .name = strdup("SSIDs"), 44 | .type = WifiMarauderScriptMenuItemTypeListString, 45 | .num_options = 1, 46 | .select_callback = wifi_marauder_beaconlist_stage_ssids_select_callback}; 47 | stage_menu->items[1] = (WifiMarauderScriptMenuItem){ 48 | .name = strdup("Generate random"), 49 | .type = WifiMarauderScriptMenuItemTypeNumber, 50 | .num_options = 1, 51 | .setup_callback = wifi_marauder_beaconlist_stage_random_ssids_setup_callback, 52 | .select_callback = wifi_marauder_beaconlist_stage_random_ssids_select_callback}; 53 | stage_menu->items[2] = (WifiMarauderScriptMenuItem){ 54 | .name = strdup("Timeout"), 55 | .type = WifiMarauderScriptMenuItemTypeNumber, 56 | .num_options = 1, 57 | .setup_callback = wifi_marauder_beaconlist_stage_timeout_setup_callback, 58 | .select_callback = wifi_marauder_beaconlist_stage_timeout_select_callback}; 59 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_config.h: -------------------------------------------------------------------------------- 1 | ADD_STAGE(scan, Scan) 2 | ADD_STAGE(select, Select) 3 | ADD_STAGE(deauth, Deauth) 4 | ADD_STAGE(probe, Probe) 5 | ADD_STAGE(sniffraw, SniffRaw) 6 | ADD_STAGE(sniffbeacon, SniffBeacon) 7 | ADD_STAGE(sniffdeauth, SniffDeauth) 8 | ADD_STAGE(sniffesp, SniffEsp) 9 | ADD_STAGE(sniffpmkid, SniffPmkid) 10 | ADD_STAGE(sniffpwn, SniffPwn) 11 | ADD_STAGE(beaconlist, BeaconList) 12 | ADD_STAGE(beaconap, BeaconAp) 13 | ADD_STAGE(exec, Exec) 14 | ADD_STAGE(delay, Delay) -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_deauth.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_deauth_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageDeauth* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_deauth_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageDeauth* stage_deauth = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_deauth->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_deauth_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = strdup("Timeout"), 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_deauth_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_deauth_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_delay.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_delay_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageDelay* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_delay_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageDelay* stage_delay = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_delay->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_delay_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = strdup("Timeout"), 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_delay_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_delay_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_exec.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_exec_stage_filter_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageExec* stage = app->script_edit_selected_stage->stage; 6 | if(stage->command != NULL) { 7 | variable_item_set_current_value_text(item, stage->command); 8 | } 9 | } 10 | 11 | void wifi_marauder_exec_stage_filter_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageExec* stage_select = app->script_edit_selected_stage->stage; 14 | if(stage_select->command == NULL) { 15 | stage_select->command = malloc(128); 16 | } 17 | app->user_input_string_reference = &stage_select->command; 18 | } 19 | 20 | void wifi_marauder_script_stage_menu_exec_load(WifiMarauderScriptStageMenu* stage_menu) { 21 | stage_menu->num_items = 1; 22 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 23 | 24 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 25 | .name = strdup("Command"), 26 | .type = WifiMarauderScriptMenuItemTypeString, 27 | .num_options = 1, 28 | .setup_callback = wifi_marauder_exec_stage_filter_setup_callback, 29 | .select_callback = wifi_marauder_exec_stage_filter_select_callback}; 30 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_probe.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_probe_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageProbe* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_probe_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageProbe* stage_probe = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_probe->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_probe_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = strdup("Timeout"), 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_probe_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_probe_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_scan.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_scan_stage_type_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; 6 | variable_item_set_current_value_index(item, stage->type); 7 | } 8 | 9 | void wifi_marauder_scan_stage_type_change_callback(VariableItem* item) { 10 | WifiMarauderApp* app = variable_item_get_context(item); 11 | 12 | // Get menu item 13 | uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); 14 | const WifiMarauderScriptMenuItem* menu_item = 15 | &app->script_stage_menu->items[current_stage_index]; 16 | 17 | // Defines the text of the selected option 18 | uint8_t option_index = variable_item_get_current_value_index(item); 19 | variable_item_set_current_value_text(item, menu_item->options[option_index]); 20 | 21 | // Updates the attribute value of the current stage 22 | WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; 23 | stage->type = option_index; 24 | } 25 | 26 | void wifi_marauder_scan_stage_channel_setup_callback(VariableItem* item) { 27 | WifiMarauderApp* app = variable_item_get_context(item); 28 | WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; 29 | if(stage->channel >= 0 && stage->channel < 12) { 30 | variable_item_set_current_value_index(item, stage->channel); 31 | } else { 32 | variable_item_set_current_value_index(item, 0); 33 | } 34 | } 35 | 36 | void wifi_marauder_scan_stage_channel_change_callback(VariableItem* item) { 37 | WifiMarauderApp* app = variable_item_get_context(item); 38 | 39 | // Get menu item 40 | uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); 41 | const WifiMarauderScriptMenuItem* menu_item = 42 | &app->script_stage_menu->items[current_stage_index]; 43 | 44 | // Defines the text of the selected option 45 | uint8_t option_index = variable_item_get_current_value_index(item); 46 | variable_item_set_current_value_text(item, menu_item->options[option_index]); 47 | 48 | // Updates the attribute value of the current stage 49 | WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; 50 | stage->channel = option_index; 51 | } 52 | 53 | void wifi_marauder_scan_stage_timeout_setup_callback(VariableItem* item) { 54 | WifiMarauderApp* app = variable_item_get_context(item); 55 | WifiMarauderScriptStageScan* stage = app->script_edit_selected_stage->stage; 56 | char timeout_str[32]; 57 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 58 | variable_item_set_current_value_text(item, timeout_str); 59 | } 60 | 61 | void wifi_marauder_scan_stage_timeout_select_callback(void* context) { 62 | WifiMarauderApp* app = context; 63 | WifiMarauderScriptStageScan* stage_scan = app->script_edit_selected_stage->stage; 64 | app->user_input_number_reference = &stage_scan->timeout; 65 | } 66 | 67 | void wifi_marauder_script_stage_menu_scan_load(WifiMarauderScriptStageMenu* stage_menu) { 68 | stage_menu->num_items = 3; 69 | stage_menu->items = malloc(3 * sizeof(WifiMarauderScriptMenuItem)); 70 | 71 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 72 | .name = strdup("Type"), 73 | .type = WifiMarauderScriptMenuItemTypeOptionsString, 74 | .num_options = 2, 75 | .options = {"ap", "station"}, 76 | .setup_callback = wifi_marauder_scan_stage_type_setup_callback, 77 | .change_callback = wifi_marauder_scan_stage_type_change_callback, 78 | }; 79 | stage_menu->items[1] = (WifiMarauderScriptMenuItem){ 80 | .name = strdup("Channel"), 81 | .type = WifiMarauderScriptMenuItemTypeOptionsNumber, 82 | .num_options = 12, 83 | .options = {"none", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}, 84 | .setup_callback = wifi_marauder_scan_stage_channel_setup_callback, 85 | .change_callback = wifi_marauder_scan_stage_channel_change_callback, 86 | }; 87 | stage_menu->items[2] = (WifiMarauderScriptMenuItem){ 88 | .name = strdup("Timeout"), 89 | .type = WifiMarauderScriptMenuItemTypeNumber, 90 | .num_options = 1, 91 | .setup_callback = wifi_marauder_scan_stage_timeout_setup_callback, 92 | .select_callback = wifi_marauder_scan_stage_timeout_select_callback}; 93 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_select.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_select_stage_type_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageSelect* stage = app->script_edit_selected_stage->stage; 6 | variable_item_set_current_value_index(item, stage->type); 7 | } 8 | 9 | void wifi_marauder_select_stage_type_change_callback(VariableItem* item) { 10 | WifiMarauderApp* app = variable_item_get_context(item); 11 | 12 | // Get menu item 13 | uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); 14 | const WifiMarauderScriptMenuItem* menu_item = 15 | &app->script_stage_menu->items[current_stage_index]; 16 | 17 | // Defines the text of the selected option 18 | uint8_t option_index = variable_item_get_current_value_index(item); 19 | variable_item_set_current_value_text(item, menu_item->options[option_index]); 20 | 21 | // Updates the attribute value of the current stage 22 | WifiMarauderScriptStageSelect* stage = app->script_edit_selected_stage->stage; 23 | stage->type = option_index; 24 | } 25 | 26 | void wifi_marauder_select_stage_filter_setup_callback(VariableItem* item) { 27 | WifiMarauderApp* app = variable_item_get_context(item); 28 | WifiMarauderScriptStageSelect* stage = app->script_edit_selected_stage->stage; 29 | 30 | if(stage->filter != NULL) { 31 | variable_item_set_current_value_index(item, 0); 32 | variable_item_set_current_value_text(item, stage->filter); 33 | } else { 34 | variable_item_set_current_value_index(item, 1); 35 | } 36 | } 37 | 38 | void wifi_marauder_select_stage_filter_change_callback(VariableItem* item) { 39 | WifiMarauderApp* app = variable_item_get_context(item); 40 | WifiMarauderScriptStageSelect* stage = app->script_edit_selected_stage->stage; 41 | 42 | // Clears the filter if you change the option. Flipper input box does not accept blank text 43 | if(variable_item_get_current_value_index(item) == 1) { 44 | stage->filter = NULL; 45 | variable_item_set_current_value_index(item, 0); 46 | variable_item_set_values_count(item, 1); 47 | } 48 | 49 | if(stage->filter != NULL) { 50 | variable_item_set_current_value_text(item, stage->filter); 51 | } else { 52 | variable_item_set_current_value_text(item, ""); 53 | } 54 | } 55 | 56 | void wifi_marauder_select_stage_filter_select_callback(void* context) { 57 | WifiMarauderApp* app = context; 58 | WifiMarauderScriptStageSelect* stage_select = app->script_edit_selected_stage->stage; 59 | if(stage_select->filter == NULL) { 60 | stage_select->filter = malloc(128); 61 | } 62 | app->user_input_string_reference = &stage_select->filter; 63 | } 64 | 65 | void wifi_marauder_select_stage_indexes_select_callback(void* context) { 66 | WifiMarauderApp* app = context; 67 | WifiMarauderScriptStageSelect* stage_select = app->script_edit_selected_stage->stage; 68 | app->script_stage_edit_numbers_reference = &stage_select->indexes; 69 | app->script_stage_edit_number_count_reference = &stage_select->index_count; 70 | } 71 | 72 | void wifi_marauder_script_stage_menu_select_load(WifiMarauderScriptStageMenu* stage_menu) { 73 | stage_menu->num_items = 3; 74 | stage_menu->items = malloc(3 * sizeof(WifiMarauderScriptMenuItem)); 75 | 76 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 77 | .name = strdup("Type"), 78 | .type = WifiMarauderScriptMenuItemTypeOptionsString, 79 | .num_options = 2, 80 | .options = {"ap", "station"}, 81 | .setup_callback = wifi_marauder_select_stage_type_setup_callback, 82 | .change_callback = wifi_marauder_select_stage_type_change_callback}; 83 | stage_menu->items[1] = (WifiMarauderScriptMenuItem){ 84 | .name = strdup("Filter"), 85 | .type = WifiMarauderScriptMenuItemTypeString, 86 | .num_options = 2, 87 | .setup_callback = wifi_marauder_select_stage_filter_setup_callback, 88 | .change_callback = wifi_marauder_select_stage_filter_change_callback, 89 | .select_callback = wifi_marauder_select_stage_filter_select_callback}; 90 | stage_menu->items[2] = (WifiMarauderScriptMenuItem){ 91 | .name = strdup("Indexes"), 92 | .type = WifiMarauderScriptMenuItemTypeListNumber, 93 | .num_options = 1, 94 | .select_callback = wifi_marauder_select_stage_indexes_select_callback}; 95 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_sniffbeacon.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_sniffbeacon_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageSniffBeacon* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_sniffbeacon_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageSniffBeacon* stage_sniffbeacon = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_sniffbeacon->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_sniffbeacon_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = strdup("Timeout"), 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_sniffbeacon_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_sniffbeacon_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_sniffdeauth.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_sniffdeauth_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageSniffDeauth* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_sniffdeauth_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageSniffDeauth* stage_sniffdeauth = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_sniffdeauth->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_sniffdeauth_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = strdup("Timeout"), 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_sniffdeauth_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_sniffdeauth_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_sniffesp.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_sniffesp_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageSniffEsp* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_sniffesp_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageSniffEsp* stage_sniffesp = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_sniffesp->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_sniffesp_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = strdup("Timeout"), 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_sniffesp_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_sniffesp_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_sniffpmkid.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | static void wifi_marauder_sniffpmkid_stage_hop_channels_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; 6 | variable_item_set_current_value_index(item, stage->hop_channels); 7 | } 8 | 9 | static void wifi_marauder_sniffpmkid_stage_hop_channels_change_callback(VariableItem* item) { 10 | WifiMarauderApp* app = variable_item_get_context(item); 11 | 12 | uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); 13 | const WifiMarauderScriptMenuItem* menu_item = 14 | &app->script_stage_menu->items[current_stage_index]; 15 | 16 | uint8_t option_index = variable_item_get_current_value_index(item); 17 | variable_item_set_current_value_text(item, menu_item->options[option_index]); 18 | 19 | WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; 20 | stage->hop_channels = option_index; 21 | } 22 | 23 | static void wifi_marauder_sniffpmkid_stage_force_deauth_setup_callback(VariableItem* item) { 24 | WifiMarauderApp* app = variable_item_get_context(item); 25 | WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; 26 | variable_item_set_current_value_index(item, stage->force_deauth); 27 | } 28 | 29 | static void wifi_marauder_sniffpmkid_stage_force_deauth_change_callback(VariableItem* item) { 30 | WifiMarauderApp* app = variable_item_get_context(item); 31 | 32 | // Get menu item 33 | uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); 34 | const WifiMarauderScriptMenuItem* menu_item = 35 | &app->script_stage_menu->items[current_stage_index]; 36 | 37 | // Defines the text of the selected option 38 | uint8_t option_index = variable_item_get_current_value_index(item); 39 | variable_item_set_current_value_text(item, menu_item->options[option_index]); 40 | 41 | // Updates the attribute value of the current stage 42 | WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; 43 | stage->force_deauth = option_index; 44 | } 45 | 46 | static void wifi_marauder_sniffpmkid_stage_channel_setup_callback(VariableItem* item) { 47 | WifiMarauderApp* app = variable_item_get_context(item); 48 | WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; 49 | if(stage->channel >= 0 && stage->channel < 12) { 50 | variable_item_set_current_value_index(item, stage->channel); 51 | } else { 52 | variable_item_set_current_value_index(item, 0); 53 | } 54 | } 55 | 56 | static void wifi_marauder_sniffpmkid_stage_channel_change_callback(VariableItem* item) { 57 | WifiMarauderApp* app = variable_item_get_context(item); 58 | 59 | // Get menu item 60 | uint8_t current_stage_index = variable_item_list_get_selected_item_index(app->var_item_list); 61 | const WifiMarauderScriptMenuItem* menu_item = 62 | &app->script_stage_menu->items[current_stage_index]; 63 | 64 | // Defines the text of the selected option 65 | uint8_t option_index = variable_item_get_current_value_index(item); 66 | variable_item_set_current_value_text(item, menu_item->options[option_index]); 67 | 68 | // Updates the attribute value of the current stage 69 | WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; 70 | stage->channel = option_index; 71 | } 72 | 73 | static void wifi_marauder_sniffpmkid_stage_timeout_setup_callback(VariableItem* item) { 74 | WifiMarauderApp* app = variable_item_get_context(item); 75 | WifiMarauderScriptStageSniffPmkid* stage = app->script_edit_selected_stage->stage; 76 | char timeout_str[32]; 77 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 78 | variable_item_set_current_value_text(item, timeout_str); 79 | } 80 | 81 | static void wifi_marauder_sniffpmkid_stage_timeout_select_callback(void* context) { 82 | WifiMarauderApp* app = context; 83 | WifiMarauderScriptStageSniffPmkid* stage_sniffpmkid = app->script_edit_selected_stage->stage; 84 | app->user_input_number_reference = &stage_sniffpmkid->timeout; 85 | } 86 | 87 | void wifi_marauder_script_stage_menu_sniffpmkid_load(WifiMarauderScriptStageMenu* stage_menu) { 88 | stage_menu->num_items = 4; 89 | stage_menu->items = malloc(4 * sizeof(WifiMarauderScriptMenuItem)); 90 | 91 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 92 | .name = strdup("Force deauth"), 93 | .type = WifiMarauderScriptMenuItemTypeOptionsString, 94 | .num_options = 2, 95 | .options = {"no", "yes"}, 96 | .setup_callback = wifi_marauder_sniffpmkid_stage_force_deauth_setup_callback, 97 | .change_callback = wifi_marauder_sniffpmkid_stage_force_deauth_change_callback}; 98 | stage_menu->items[1] = (WifiMarauderScriptMenuItem){ 99 | .name = strdup("Channel"), 100 | .type = WifiMarauderScriptMenuItemTypeOptionsNumber, 101 | .num_options = 12, 102 | .options = {"none", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}, 103 | .setup_callback = wifi_marauder_sniffpmkid_stage_channel_setup_callback, 104 | .change_callback = wifi_marauder_sniffpmkid_stage_channel_change_callback}; 105 | stage_menu->items[2] = (WifiMarauderScriptMenuItem){ 106 | .name = strdup("Timeout"), 107 | .type = WifiMarauderScriptMenuItemTypeNumber, 108 | .num_options = 1, 109 | .setup_callback = wifi_marauder_sniffpmkid_stage_timeout_setup_callback, 110 | .select_callback = wifi_marauder_sniffpmkid_stage_timeout_select_callback}; 111 | stage_menu->items[3] = (WifiMarauderScriptMenuItem){ 112 | .name = strdup("Hop Channels"), 113 | .type = WifiMarauderScriptMenuItemTypeOptionsString, 114 | .num_options = 2, 115 | .options = {"no", "yes"}, 116 | .setup_callback = wifi_marauder_sniffpmkid_stage_hop_channels_setup_callback, 117 | .change_callback = wifi_marauder_sniffpmkid_stage_hop_channels_change_callback}; 118 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_sniffpwn.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_sniffpwn_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageSniffPwn* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_sniffpwn_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageSniffPwn* stage_sniffpwn = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_sniffpwn->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_sniffpwn_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = strdup("Timeout"), 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_sniffpwn_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_sniffpwn_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/menu/wifi_marauder_script_stage_menu_sniffraw.c: -------------------------------------------------------------------------------- 1 | #include "../../wifi_marauder_app_i.h" 2 | 3 | void wifi_marauder_sniffraw_stage_timeout_setup_callback(VariableItem* item) { 4 | WifiMarauderApp* app = variable_item_get_context(item); 5 | WifiMarauderScriptStageSniffRaw* stage = app->script_edit_selected_stage->stage; 6 | char timeout_str[32]; 7 | snprintf(timeout_str, sizeof(timeout_str), "%d", stage->timeout); 8 | variable_item_set_current_value_text(item, timeout_str); 9 | } 10 | 11 | void wifi_marauder_sniffraw_stage_timeout_select_callback(void* context) { 12 | WifiMarauderApp* app = context; 13 | WifiMarauderScriptStageSniffRaw* stage_sniffraw = app->script_edit_selected_stage->stage; 14 | app->user_input_number_reference = &stage_sniffraw->timeout; 15 | } 16 | 17 | void wifi_marauder_script_stage_menu_sniffraw_load(WifiMarauderScriptStageMenu* stage_menu) { 18 | stage_menu->num_items = 1; 19 | stage_menu->items = malloc(1 * sizeof(WifiMarauderScriptMenuItem)); 20 | 21 | stage_menu->items[0] = (WifiMarauderScriptMenuItem){ 22 | .name = strdup("Timeout"), 23 | .type = WifiMarauderScriptMenuItemTypeNumber, 24 | .num_options = 1, 25 | .setup_callback = wifi_marauder_sniffraw_stage_timeout_setup_callback, 26 | .select_callback = wifi_marauder_sniffraw_stage_timeout_select_callback}; 27 | } -------------------------------------------------------------------------------- /script/wifi_marauder_script.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ---------------------------------------------------------------------------------------------------- 3 | * STEPS TO ADD A NEW STAGE: 4 | * 5 | * wifi_marauder_script.h 6 | * - Complement WifiMarauderScriptStageType enum with new stage 7 | * - Create struct WifiMarauderScriptStage???? for the new stage 8 | * 9 | * wifi_marauder_script.c 10 | * - Change _wifi_marauder_script_load_stages() to load new stage 11 | * - Change wifi_marauder_script_save_json() to support the new stage 12 | * - Add case to free memory in wifi_marauder_script_free() 13 | * 14 | * wifi_marauder_script_executor.c 15 | * - Create function "void _wifi_marauder_script_execute_????(WifiMarauderScriptStage????* stage)" 16 | * - Add case in wifi_marauder_script_execute_stage() 17 | * 18 | * wifi_marauder_scene_script_edit.c 19 | * - Add case in wifi_marauder_scene_script_edit_on_enter() 20 | * 21 | * wifi_marauder_scene_script_stage_add.c 22 | * - Create stage creation function and add in wifi_marauder_scene_script_stage_add_on_enter() 23 | * 24 | * wifi_marauder_script_stage_menu_config.h 25 | * - Add the new stage and implement its functions in a new file 26 | * 27 | * ---------------------------------------------------------------------------------------------------- 28 | * SCRIPT SYNTAX (In order of execution): 29 | * { 30 | * "meta": { 31 | * "description": "My script", 32 | * "repeat": times the script will repeat (default 1), 33 | * "enableLed": true (default) | false, 34 | * "savePcap": true (default) | false 35 | * }, 36 | * "stages": { 37 | * "scan": { 38 | * "type": "ap" | "station", 39 | * "timeout": seconds, 40 | * "channel": 1-11 41 | * }, 42 | * "select": { 43 | * "type": "ap" | "station" | "ssid", 44 | * "filter": "all" | "contains -f '{SSID fragment}' or equals '{SSID}' or ...", 45 | * "indexes": [0, 1, 2, 3...], 46 | * }, 47 | * "deauth": { 48 | * "timeout": seconds 49 | * }, 50 | * "probe": { 51 | * "timeout": seconds 52 | * }, 53 | * "sniffRaw": { 54 | * "timeout": seconds 55 | * }, 56 | * "sniffBeacon": { 57 | * "timeout": seconds 58 | * }, 59 | * "sniffDeauth": { 60 | * "timeout": seconds 61 | * }, 62 | * "sniffEsp": { 63 | * "timeout": seconds 64 | * }, 65 | * "sniffPmkid": { 66 | * "forceDeauth": true (default) | false, 67 | * "channel": 1-11, 68 | * "timeout": seconds 69 | * }, 70 | * "sniffPwn": { 71 | * "timeout": seconds 72 | * }, 73 | * "beaconList": { 74 | * "ssids": [ 75 | * "SSID 1", 76 | * "SSID 2", 77 | * "SSID 3" 78 | * ], 79 | * "generate": number of random SSIDs that will be generated, 80 | * "timeout": seconds 81 | * } 82 | * "beaconAp": { 83 | * "timeout": seconds 84 | * } 85 | * "exec": { 86 | * "command": Command (eg: "clearlist -a") 87 | * } 88 | * "delay": { 89 | * "timeout": seconds 90 | * } 91 | * } 92 | * } 93 | * 94 | * Note: It is possible to inform "stages" as an array, allowing ordering and repetition of stages of the same type: 95 | * "stages": [ 96 | * { 97 | * "beaconList": { "ssids": ["SSID 1", "SSID 2"] } 98 | * }, 99 | * { 100 | * "beaconList": { "generate": 4 } 101 | * }, 102 | * ] 103 | * ---------------------------------------------------------------------------------------------------- 104 | */ 105 | 106 | #pragma once 107 | 108 | #include 109 | #include "cJSON.h" 110 | 111 | #define WIFI_MARAUDER_DEFAULT_TIMEOUT_SCAN 15 112 | #define WIFI_MARAUDER_DEFAULT_TIMEOUT_DEAUTH 30 113 | #define WIFI_MARAUDER_DEFAULT_TIMEOUT_PROBE 60 114 | #define WIFI_MARAUDER_DEFAULT_TIMEOUT_SNIFF 60 115 | #define WIFI_MARAUDER_DEFAULT_TIMEOUT_BEACON 60 116 | 117 | typedef enum { 118 | WifiMarauderScriptBooleanFalse = 0, 119 | WifiMarauderScriptBooleanTrue = 1, 120 | WifiMarauderScriptBooleanUndefined = 2 121 | } WifiMarauderScriptBoolean; 122 | 123 | typedef enum { 124 | WifiMarauderScriptStageTypeScan, 125 | WifiMarauderScriptStageTypeSelect, 126 | WifiMarauderScriptStageTypeDeauth, 127 | WifiMarauderScriptStageTypeProbe, 128 | WifiMarauderScriptStageTypeSniffRaw, 129 | WifiMarauderScriptStageTypeSniffBeacon, 130 | WifiMarauderScriptStageTypeSniffDeauth, 131 | WifiMarauderScriptStageTypeSniffEsp, 132 | WifiMarauderScriptStageTypeSniffPmkid, 133 | WifiMarauderScriptStageTypeSniffPwn, 134 | WifiMarauderScriptStageTypeBeaconList, 135 | WifiMarauderScriptStageTypeBeaconAp, 136 | WifiMarauderScriptStageTypeExec, 137 | WifiMarauderScriptStageTypeDelay, 138 | } WifiMarauderScriptStageType; 139 | 140 | typedef enum { 141 | WifiMarauderScriptScanTypeAp = 0, 142 | WifiMarauderScriptScanTypeStation = 1 143 | } WifiMarauderScriptScanType; 144 | 145 | typedef enum { 146 | WifiMarauderScriptSelectTypeAp, 147 | WifiMarauderScriptSelectTypeStation, 148 | WifiMarauderScriptSelectTypeSsid 149 | } WifiMarauderScriptSelectType; 150 | 151 | // Stages 152 | typedef struct WifiMarauderScriptStage { 153 | WifiMarauderScriptStageType type; 154 | void* stage; 155 | struct WifiMarauderScriptStage* next_stage; 156 | } WifiMarauderScriptStage; 157 | 158 | typedef struct WifiMarauderScriptStageScan { 159 | WifiMarauderScriptScanType type; 160 | int channel; 161 | int timeout; 162 | } WifiMarauderScriptStageScan; 163 | 164 | typedef struct WifiMarauderScriptStageSelect { 165 | WifiMarauderScriptSelectType type; 166 | char* filter; 167 | int* indexes; 168 | int index_count; 169 | // TODO: Implement a feature to not select the same items in the next iteration of the script 170 | bool allow_repeat; 171 | } WifiMarauderScriptStageSelect; 172 | 173 | typedef struct WifiMarauderScriptStageDeauth { 174 | int timeout; 175 | } WifiMarauderScriptStageDeauth; 176 | 177 | typedef struct WifiMarauderScriptStageProbe { 178 | int timeout; 179 | } WifiMarauderScriptStageProbe; 180 | 181 | typedef struct WifiMarauderScriptStageSniffRaw { 182 | int timeout; 183 | } WifiMarauderScriptStageSniffRaw; 184 | 185 | typedef struct WifiMarauderScriptStageSniffBeacon { 186 | int timeout; 187 | } WifiMarauderScriptStageSniffBeacon; 188 | 189 | typedef struct WifiMarauderScriptStageSniffDeauth { 190 | int timeout; 191 | } WifiMarauderScriptStageSniffDeauth; 192 | 193 | typedef struct WifiMarauderScriptStageSniffEsp { 194 | int timeout; 195 | } WifiMarauderScriptStageSniffEsp; 196 | 197 | typedef struct WifiMarauderScriptStageSniffPmkid { 198 | bool force_deauth; 199 | bool hop_channels; 200 | int channel; 201 | int timeout; 202 | } WifiMarauderScriptStageSniffPmkid; 203 | 204 | typedef struct WifiMarauderScriptStageSniffPwn { 205 | int timeout; 206 | } WifiMarauderScriptStageSniffPwn; 207 | 208 | typedef struct WifiMarauderScriptStageBeaconList { 209 | char** ssids; 210 | int ssid_count; 211 | int random_ssids; 212 | int timeout; 213 | } WifiMarauderScriptStageBeaconList; 214 | 215 | typedef struct WifiMarauderScriptStageBeaconAp { 216 | int timeout; 217 | } WifiMarauderScriptStageBeaconAp; 218 | 219 | typedef struct WifiMarauderScriptStageExec { 220 | char* command; 221 | } WifiMarauderScriptStageExec; 222 | 223 | typedef struct WifiMarauderScriptStageDelay { 224 | int timeout; 225 | } WifiMarauderScriptStageDelay; 226 | 227 | // Script 228 | typedef struct WifiMarauderScript { 229 | char* name; 230 | char* description; 231 | WifiMarauderScriptStage* first_stage; 232 | WifiMarauderScriptStage* last_stage; 233 | WifiMarauderScriptBoolean enable_led; 234 | WifiMarauderScriptBoolean save_pcap; 235 | int repeat; 236 | } WifiMarauderScript; 237 | 238 | typedef struct WifiMarauderScriptStageListItem { 239 | char* value; 240 | struct WifiMarauderScriptStageListItem* next_item; 241 | } WifiMarauderScriptStageListItem; 242 | 243 | WifiMarauderScript* wifi_marauder_script_alloc(); 244 | WifiMarauderScript* wifi_marauder_script_create(const char* script_name); 245 | WifiMarauderScript* wifi_marauder_script_parse_raw(const char* script_raw); 246 | WifiMarauderScript* wifi_marauder_script_parse_json(Storage* storage, const char* file_path); 247 | void wifi_marauder_script_save_json( 248 | Storage* storage, 249 | const char* file_path, 250 | WifiMarauderScript* script); 251 | void wifi_marauder_script_add_stage( 252 | WifiMarauderScript* script, 253 | WifiMarauderScriptStageType stage_type, 254 | void* stage_data); 255 | bool wifi_marauder_script_has_stage( 256 | WifiMarauderScript* script, 257 | WifiMarauderScriptStageType stage_type); 258 | void wifi_marauder_script_free(WifiMarauderScript* script); 259 | -------------------------------------------------------------------------------- /script/wifi_marauder_script_executor.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | #include "wifi_marauder_script_executor.h" 3 | 4 | void _wifi_marauder_script_delay(WifiMarauderScriptWorker* worker, uint32_t delay_secs) { 5 | for(uint32_t i = 0; i < delay_secs && worker->is_running; i++) furi_delay_ms(1000); 6 | } 7 | 8 | void _send_stop(WifiMarauderScriptWorker* worker) { 9 | const char stop_command[] = "stopscan\n"; 10 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(stop_command), strlen(stop_command)); 11 | } 12 | 13 | void _send_line_break(WifiMarauderScriptWorker* worker) { 14 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1); 15 | } 16 | 17 | void _send_channel_select(WifiMarauderScriptWorker* worker, int channel) { 18 | char command[30]; 19 | _send_line_break(worker); 20 | snprintf(command, sizeof(command), "channel -s %d\n", channel); 21 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command)); 22 | } 23 | 24 | void _wifi_marauder_script_execute_scan( 25 | WifiMarauderScriptStageScan* stage, 26 | WifiMarauderScriptWorker* worker) { 27 | char command[15]; 28 | // Set channel 29 | if(stage->channel > 0) { 30 | _send_channel_select(worker, stage->channel); 31 | } 32 | // Start scan 33 | if(stage->type == WifiMarauderScriptScanTypeAp) { 34 | snprintf(command, sizeof(command), "scanap\n"); 35 | } else { 36 | snprintf(command, sizeof(command), "scansta\n"); 37 | } 38 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command)); 39 | _wifi_marauder_script_delay(worker, stage->timeout); 40 | _send_stop(worker); 41 | } 42 | 43 | void _wifi_marauder_script_execute_select( 44 | WifiMarauderScriptStageSelect* stage, 45 | WifiMarauderScriptWorker* worker) { 46 | const char* select_type = NULL; 47 | switch(stage->type) { 48 | case WifiMarauderScriptSelectTypeAp: 49 | select_type = "-a"; 50 | break; 51 | case WifiMarauderScriptSelectTypeStation: 52 | select_type = "-c"; 53 | break; 54 | case WifiMarauderScriptSelectTypeSsid: 55 | select_type = "-s"; 56 | break; 57 | default: 58 | return; // invalid stage 59 | } 60 | 61 | char command[256]; 62 | size_t command_length = 0; 63 | 64 | if(stage->indexes != NULL && stage->index_count > 0) { 65 | command_length = snprintf(command, sizeof(command), "select %s ", select_type); 66 | 67 | for(int i = 0; i < stage->index_count; i++) { 68 | int index = stage->indexes[i]; 69 | command_length += snprintf( 70 | command + command_length, sizeof(command) - command_length, "%d, ", index); 71 | } 72 | 73 | // Remove the trailing comma and space 74 | command_length -= 2; 75 | command[command_length] = '\n'; 76 | command_length++; 77 | } else if(stage->filter == NULL || strcmp(stage->filter, "all") == 0) { 78 | command_length = snprintf(command, sizeof(command), "select %s all\n", select_type); 79 | } else { 80 | command_length = snprintf( 81 | command, sizeof(command), "select %s -f \"%s\"\n", select_type, stage->filter); 82 | } 83 | 84 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, command_length); 85 | } 86 | 87 | void _wifi_marauder_script_execute_deauth( 88 | WifiMarauderScriptStageDeauth* stage, 89 | WifiMarauderScriptWorker* worker) { 90 | const char attack_command[] = "attack -t deauth\n"; 91 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command)); 92 | _wifi_marauder_script_delay(worker, stage->timeout); 93 | _send_stop(worker); 94 | } 95 | 96 | void _wifi_marauder_script_execute_probe( 97 | WifiMarauderScriptStageProbe* stage, 98 | WifiMarauderScriptWorker* worker) { 99 | const char attack_command[] = "attack -t probe\n"; 100 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command)); 101 | _wifi_marauder_script_delay(worker, stage->timeout); 102 | _send_stop(worker); 103 | } 104 | 105 | void _wifi_marauder_script_execute_sniff_raw( 106 | WifiMarauderScriptStageSniffRaw* stage, 107 | WifiMarauderScriptWorker* worker) { 108 | const char sniff_command[] = "sniffraw"; 109 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); 110 | if(((WifiMarauderScript*)worker->context)->save_pcap != WifiMarauderScriptBooleanFalse) { 111 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n")); 112 | } else { 113 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1); 114 | } 115 | _wifi_marauder_script_delay(worker, stage->timeout); 116 | _send_stop(worker); 117 | } 118 | 119 | void _wifi_marauder_script_execute_sniff_beacon( 120 | WifiMarauderScriptStageSniffBeacon* stage, 121 | WifiMarauderScriptWorker* worker) { 122 | const char sniff_command[] = "sniffbeacon"; 123 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); 124 | if(((WifiMarauderScript*)worker->context)->save_pcap != WifiMarauderScriptBooleanFalse) { 125 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n")); 126 | } else { 127 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1); 128 | } 129 | _wifi_marauder_script_delay(worker, stage->timeout); 130 | _send_stop(worker); 131 | } 132 | 133 | void _wifi_marauder_script_execute_sniff_deauth( 134 | WifiMarauderScriptStageSniffDeauth* stage, 135 | WifiMarauderScriptWorker* worker) { 136 | const char sniff_command[] = "sniffdeauth"; 137 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); 138 | if(((WifiMarauderScript*)worker->context)->save_pcap != WifiMarauderScriptBooleanFalse) { 139 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n")); 140 | } else { 141 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1); 142 | } 143 | _wifi_marauder_script_delay(worker, stage->timeout); 144 | _send_stop(worker); 145 | } 146 | 147 | void _wifi_marauder_script_execute_sniff_esp( 148 | WifiMarauderScriptStageSniffEsp* stage, 149 | WifiMarauderScriptWorker* worker) { 150 | const char sniff_command[] = "sniffesp"; 151 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); 152 | if(((WifiMarauderScript*)worker->context)->save_pcap != WifiMarauderScriptBooleanFalse) { 153 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n")); 154 | } else { 155 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1); 156 | } 157 | _wifi_marauder_script_delay(worker, stage->timeout); 158 | _send_stop(worker); 159 | } 160 | 161 | void _wifi_marauder_script_execute_sniff_pmkid( 162 | WifiMarauderScriptStageSniffPmkid* stage, 163 | WifiMarauderScriptWorker* worker) { 164 | // If channel hopping is enabled, loop through channels 1-11 165 | if(stage->hop_channels) { 166 | for(int i = 1; i <= 11; i++) { 167 | char attack_command[50] = "sniffpmkid"; 168 | int len = strlen(attack_command); 169 | 170 | len += snprintf(attack_command + len, sizeof(attack_command) - len, " -c %d", i); 171 | if(stage->force_deauth) { 172 | len += snprintf(attack_command + len, sizeof(attack_command) - len, " -d"); 173 | } 174 | 175 | if(((WifiMarauderScript*)worker->context)->save_pcap != 176 | WifiMarauderScriptBooleanFalse) { 177 | len += snprintf(attack_command + len, sizeof(attack_command) - len, " -serial\n"); 178 | } else { 179 | len += snprintf(attack_command + len, sizeof(attack_command) - len, "\n"); 180 | } 181 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)attack_command, len); 182 | _wifi_marauder_script_delay(worker, stage->timeout); 183 | _send_stop(worker); 184 | } 185 | } else { 186 | char attack_command[50] = "sniffpmkid"; 187 | int len = strlen(attack_command); 188 | 189 | if(stage->channel > 0) { 190 | len += snprintf( 191 | attack_command + len, sizeof(attack_command) - len, " -c %d", stage->channel); 192 | } 193 | 194 | if(stage->force_deauth) { 195 | len += snprintf(attack_command + len, sizeof(attack_command) - len, " -d"); 196 | } 197 | if(((WifiMarauderScript*)worker->context)->save_pcap != WifiMarauderScriptBooleanFalse) { 198 | len += snprintf(attack_command + len, sizeof(attack_command) - len, " -serial\n"); 199 | } else { 200 | len += snprintf(attack_command + len, sizeof(attack_command) - len, "\n"); 201 | } 202 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)attack_command, len); 203 | _wifi_marauder_script_delay(worker, stage->timeout); 204 | _send_stop(worker); 205 | } 206 | } 207 | 208 | void _wifi_marauder_script_execute_sniff_pwn( 209 | WifiMarauderScriptStageSniffPwn* stage, 210 | WifiMarauderScriptWorker* worker) { 211 | const char sniff_command[] = "sniffpwn"; 212 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)sniff_command, strlen(sniff_command)); 213 | if(((WifiMarauderScript*)worker->context)->save_pcap != WifiMarauderScriptBooleanFalse) { 214 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(" -serial\n"), strlen(" -serial\n")); 215 | } else { 216 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)("\n"), 1); 217 | } 218 | _wifi_marauder_script_delay(worker, stage->timeout); 219 | _send_stop(worker); 220 | } 221 | 222 | void _wifi_marauder_script_execute_beacon_list( 223 | WifiMarauderScriptStageBeaconList* stage, 224 | WifiMarauderScriptWorker* worker) { 225 | const char clearlist_command[] = "clearlist -s\n"; 226 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(clearlist_command), strlen(clearlist_command)); 227 | 228 | char command[100]; 229 | char* ssid; 230 | 231 | for(int i = 0; i < stage->ssid_count; i++) { 232 | ssid = stage->ssids[i]; 233 | snprintf(command, sizeof(command), "ssid -a -n \"%s\"", ssid); 234 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(command), strlen(command)); 235 | _send_line_break(worker); 236 | } 237 | if(stage->random_ssids > 0) { 238 | char add_random_command[50]; 239 | snprintf( 240 | add_random_command, 241 | sizeof(add_random_command), 242 | "ssid -a -r -g %d\n", 243 | stage->random_ssids); 244 | wifi_marauder_uart_tx( 245 | worker->uart, (uint8_t*)add_random_command, strlen(add_random_command)); 246 | } 247 | const char attack_command[] = "attack -t beacon -l\n"; 248 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)(attack_command), strlen(attack_command)); 249 | _wifi_marauder_script_delay(worker, stage->timeout); 250 | _send_stop(worker); 251 | } 252 | 253 | void _wifi_marauder_script_execute_beacon_ap( 254 | WifiMarauderScriptStageBeaconAp* stage, 255 | WifiMarauderScriptWorker* worker) { 256 | const char command[] = "attack -t beacon -a\n"; 257 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command)); 258 | _wifi_marauder_script_delay(worker, stage->timeout); 259 | _send_stop(worker); 260 | } 261 | 262 | void _wifi_marauder_script_execute_exec( 263 | WifiMarauderScriptStageExec* stage, 264 | WifiMarauderScriptWorker* worker) { 265 | if(stage->command != NULL) { 266 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)stage->command, strlen(stage->command)); 267 | _send_line_break(worker); 268 | } 269 | } 270 | 271 | void _wifi_marauder_script_execute_delay( 272 | WifiMarauderScriptStageDelay* stage, 273 | WifiMarauderScriptWorker* worker) { 274 | _wifi_marauder_script_delay(worker, stage->timeout); 275 | } 276 | 277 | void wifi_marauder_script_execute_start(void* context) { 278 | furi_assert(context); 279 | WifiMarauderScriptWorker* worker = context; 280 | WifiMarauderScript* script = worker->script; 281 | char command[100]; 282 | 283 | // Enables or disables the LED according to script settings 284 | if(script->enable_led != WifiMarauderScriptBooleanUndefined) { 285 | snprintf( 286 | command, 287 | sizeof(command), 288 | "settings -s EnableLED %s", 289 | script->enable_led ? "enable" : "disable"); 290 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command)); 291 | _send_line_break(worker); 292 | } 293 | 294 | // Enables or disables PCAP saving according to script settings 295 | if(script->save_pcap != WifiMarauderScriptBooleanUndefined) { 296 | snprintf( 297 | command, 298 | sizeof(command), 299 | "settings -s SavePCAP %s", 300 | script->save_pcap ? "enable" : "disable"); 301 | wifi_marauder_uart_tx(worker->uart, (uint8_t*)command, strlen(command)); 302 | _send_line_break(worker); 303 | } 304 | } 305 | 306 | void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* context) { 307 | furi_assert(context); 308 | WifiMarauderScriptWorker* worker = context; 309 | void* stage_data = stage->stage; 310 | 311 | switch(stage->type) { 312 | case WifiMarauderScriptStageTypeScan: 313 | _wifi_marauder_script_execute_scan((WifiMarauderScriptStageScan*)stage_data, worker); 314 | break; 315 | case WifiMarauderScriptStageTypeSelect: 316 | _wifi_marauder_script_execute_select((WifiMarauderScriptStageSelect*)stage_data, worker); 317 | break; 318 | case WifiMarauderScriptStageTypeDeauth: 319 | _wifi_marauder_script_execute_deauth((WifiMarauderScriptStageDeauth*)stage_data, worker); 320 | break; 321 | case WifiMarauderScriptStageTypeProbe: 322 | _wifi_marauder_script_execute_probe((WifiMarauderScriptStageProbe*)stage_data, worker); 323 | break; 324 | case WifiMarauderScriptStageTypeSniffRaw: 325 | _wifi_marauder_script_execute_sniff_raw( 326 | (WifiMarauderScriptStageSniffRaw*)stage_data, worker); 327 | break; 328 | case WifiMarauderScriptStageTypeSniffBeacon: 329 | _wifi_marauder_script_execute_sniff_beacon( 330 | (WifiMarauderScriptStageSniffBeacon*)stage_data, worker); 331 | break; 332 | case WifiMarauderScriptStageTypeSniffDeauth: 333 | _wifi_marauder_script_execute_sniff_deauth( 334 | (WifiMarauderScriptStageSniffDeauth*)stage_data, worker); 335 | break; 336 | case WifiMarauderScriptStageTypeSniffEsp: 337 | _wifi_marauder_script_execute_sniff_esp( 338 | (WifiMarauderScriptStageSniffEsp*)stage_data, worker); 339 | break; 340 | case WifiMarauderScriptStageTypeSniffPmkid: 341 | _wifi_marauder_script_execute_sniff_pmkid( 342 | (WifiMarauderScriptStageSniffPmkid*)stage_data, worker); 343 | break; 344 | case WifiMarauderScriptStageTypeSniffPwn: 345 | _wifi_marauder_script_execute_sniff_pwn( 346 | (WifiMarauderScriptStageSniffPwn*)stage_data, worker); 347 | break; 348 | case WifiMarauderScriptStageTypeBeaconList: 349 | _wifi_marauder_script_execute_beacon_list( 350 | (WifiMarauderScriptStageBeaconList*)stage_data, worker); 351 | break; 352 | case WifiMarauderScriptStageTypeBeaconAp: 353 | _wifi_marauder_script_execute_beacon_ap( 354 | (WifiMarauderScriptStageBeaconAp*)stage_data, worker); 355 | break; 356 | case WifiMarauderScriptStageTypeExec: 357 | _wifi_marauder_script_execute_exec((WifiMarauderScriptStageExec*)stage_data, worker); 358 | break; 359 | case WifiMarauderScriptStageTypeDelay: 360 | _wifi_marauder_script_execute_delay((WifiMarauderScriptStageDelay*)stage_data, worker); 361 | break; 362 | } 363 | } -------------------------------------------------------------------------------- /script/wifi_marauder_script_executor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "wifi_marauder_script.h" 4 | 5 | void wifi_marauder_script_execute_start(void* context); 6 | void wifi_marauder_script_execute_stage(WifiMarauderScriptStage* stage, void* context); 7 | -------------------------------------------------------------------------------- /script/wifi_marauder_script_worker.c: -------------------------------------------------------------------------------- 1 | #include "../wifi_marauder_app_i.h" 2 | #include "wifi_marauder_script_worker.h" 3 | 4 | WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc(WifiMarauderUart* uart) { 5 | WifiMarauderScriptWorker* worker = malloc(sizeof(WifiMarauderScriptWorker)); 6 | if(worker == NULL) { 7 | return NULL; 8 | } 9 | worker->callback_start = NULL; 10 | worker->callback_stage = NULL; 11 | worker->worker_thread = NULL; 12 | worker->uart = uart; 13 | worker->is_running = false; 14 | return worker; 15 | } 16 | 17 | int32_t _wifi_marauder_script_worker_task(void* worker) { 18 | WifiMarauderScriptWorker* script_worker = worker; 19 | WifiMarauderScript* script = script_worker->script; 20 | if(script == NULL) { 21 | return WifiMarauderScriptWorkerStatusInvalidScript; 22 | } 23 | 24 | // Setup 25 | script_worker->callback_start(script_worker->context); 26 | if(!script_worker->is_running) { 27 | return WifiMarauderScriptWorkerStatusForceExit; 28 | } 29 | 30 | // Stages 31 | for(int i = 0; i < script->repeat; i++) { 32 | WifiMarauderScriptStage* current_stage = script->first_stage; 33 | while(current_stage != NULL && script_worker->is_running) { 34 | script_worker->callback_stage(current_stage, script_worker->context); 35 | current_stage = current_stage->next_stage; 36 | } 37 | if(!script_worker->is_running) { 38 | return WifiMarauderScriptWorkerStatusForceExit; 39 | } 40 | } 41 | 42 | script_worker->is_running = false; 43 | 44 | return WifiMarauderScriptWorkerStatusSuccess; 45 | } 46 | 47 | bool wifi_marauder_script_worker_start( 48 | WifiMarauderScriptWorker* instance, 49 | WifiMarauderScript* script) { 50 | if(!instance || !script) { 51 | return false; 52 | } 53 | instance->callback_start = wifi_marauder_script_execute_start; 54 | instance->callback_stage = wifi_marauder_script_execute_stage; 55 | instance->script = script; 56 | instance->context = instance; 57 | instance->is_running = true; 58 | instance->worker_thread = furi_thread_alloc_ex( 59 | "WifiMarauderScriptWorker", 1024, _wifi_marauder_script_worker_task, instance); 60 | if(!instance->worker_thread) { 61 | return false; 62 | } 63 | furi_thread_start(instance->worker_thread); 64 | return true; 65 | } 66 | 67 | void wifi_marauder_script_worker_free(WifiMarauderScriptWorker* worker) { 68 | if(worker != NULL) { 69 | if(worker->worker_thread != NULL) { 70 | worker->is_running = false; 71 | furi_thread_join(worker->worker_thread); 72 | furi_thread_free(worker->worker_thread); 73 | } 74 | free(worker); 75 | } 76 | } -------------------------------------------------------------------------------- /script/wifi_marauder_script_worker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "wifi_marauder_script.h" 4 | 5 | typedef enum { 6 | WifiMarauderScriptWorkerStatusSuccess = 0, 7 | WifiMarauderScriptWorkerStatusInvalidScript = 1, 8 | WifiMarauderScriptWorkerStatusForceExit = 2 9 | } WifiMarauderScriptWorkerStatus; 10 | 11 | typedef struct WifiMarauderScriptWorker { 12 | WifiMarauderScript* script; 13 | FuriThread* worker_thread; 14 | WifiMarauderUart* uart; 15 | void (*callback_start)(void*); 16 | void (*callback_stage)(WifiMarauderScriptStage*, void*); 17 | void* context; 18 | bool is_running; 19 | } WifiMarauderScriptWorker; 20 | 21 | /** 22 | * @brief Allocates a new instance of WifiMarauderScriptWorker. 23 | * 24 | * @return A pointer to the allocated instance or NULL if allocation fails. 25 | */ 26 | WifiMarauderScriptWorker* wifi_marauder_script_worker_alloc(); 27 | 28 | /** 29 | * @brief Starts the execution of the worker and sets the callback function to be called after each stage is executed. 30 | * 31 | * @param instance A pointer to the instance of WifiMarauderScriptWorker to start. 32 | * @param script Script to be executed 33 | * @return True if the worker was successfully started, false otherwise. 34 | */ 35 | bool wifi_marauder_script_worker_start( 36 | WifiMarauderScriptWorker* instance, 37 | WifiMarauderScript* script); 38 | 39 | /** 40 | * @brief Frees the memory used by the instance of WifiMarauderScriptWorker. 41 | * 42 | * @param script A pointer to the instance of WifiMarauderScriptWorker to free. 43 | */ 44 | void wifi_marauder_script_worker_free(WifiMarauderScriptWorker* script); 45 | -------------------------------------------------------------------------------- /wifi_10px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justcallmekoko/flipperzero-wifi-marauder/316258b8c708c1f2a67a2c087aa6d16348ed76f5/wifi_10px.png -------------------------------------------------------------------------------- /wifi_marauder_app.c: -------------------------------------------------------------------------------- 1 | #include "wifi_marauder_app_i.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | static bool wifi_marauder_app_custom_event_callback(void* context, uint32_t event) { 8 | furi_assert(context); 9 | WifiMarauderApp* app = context; 10 | return scene_manager_handle_custom_event(app->scene_manager, event); 11 | } 12 | 13 | static bool wifi_marauder_app_back_event_callback(void* context) { 14 | furi_assert(context); 15 | WifiMarauderApp* app = context; 16 | return scene_manager_handle_back_event(app->scene_manager); 17 | } 18 | 19 | static void wifi_marauder_app_tick_event_callback(void* context) { 20 | furi_assert(context); 21 | WifiMarauderApp* app = context; 22 | scene_manager_handle_tick_event(app->scene_manager); 23 | } 24 | 25 | WifiMarauderApp* wifi_marauder_app_alloc() { 26 | WifiMarauderApp* app = malloc(sizeof(WifiMarauderApp)); 27 | 28 | app->gui = furi_record_open(RECORD_GUI); 29 | app->dialogs = furi_record_open(RECORD_DIALOGS); 30 | app->storage = furi_record_open(RECORD_STORAGE); 31 | app->capture_file = storage_file_alloc(app->storage); 32 | app->log_file = storage_file_alloc(app->storage); 33 | app->save_pcap_setting_file = storage_file_alloc(app->storage); 34 | app->save_logs_setting_file = storage_file_alloc(app->storage); 35 | 36 | app->view_dispatcher = view_dispatcher_alloc(); 37 | app->scene_manager = scene_manager_alloc(&wifi_marauder_scene_handlers, app); 38 | view_dispatcher_enable_queue(app->view_dispatcher); 39 | view_dispatcher_set_event_callback_context(app->view_dispatcher, app); 40 | 41 | view_dispatcher_set_custom_event_callback( 42 | app->view_dispatcher, wifi_marauder_app_custom_event_callback); 43 | view_dispatcher_set_navigation_event_callback( 44 | app->view_dispatcher, wifi_marauder_app_back_event_callback); 45 | view_dispatcher_set_tick_event_callback( 46 | app->view_dispatcher, wifi_marauder_app_tick_event_callback, 100); 47 | 48 | view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); 49 | 50 | app->var_item_list = variable_item_list_alloc(); 51 | view_dispatcher_add_view( 52 | app->view_dispatcher, 53 | WifiMarauderAppViewVarItemList, 54 | variable_item_list_get_view(app->var_item_list)); 55 | 56 | for(int i = 0; i < NUM_MENU_ITEMS; ++i) { 57 | app->selected_option_index[i] = 0; 58 | } 59 | 60 | app->special_case_input_step = 0; 61 | 62 | app->text_box = text_box_alloc(); 63 | view_dispatcher_add_view( 64 | app->view_dispatcher, WifiMarauderAppViewConsoleOutput, text_box_get_view(app->text_box)); 65 | app->text_box_store = furi_string_alloc(); 66 | furi_string_reserve(app->text_box_store, WIFI_MARAUDER_TEXT_BOX_STORE_SIZE); 67 | 68 | app->text_input = wifi_text_input_alloc(); 69 | view_dispatcher_add_view( 70 | app->view_dispatcher, 71 | WifiMarauderAppViewTextInput, 72 | wifi_text_input_get_view(app->text_input)); 73 | 74 | app->widget = widget_alloc(); 75 | view_dispatcher_add_view( 76 | app->view_dispatcher, WifiMarauderAppViewWidget, widget_get_view(app->widget)); 77 | 78 | app->has_saved_logs_this_session = false; 79 | 80 | // if user hasn't confirmed whether to save pcaps and logs to sdcard, then prompt when scene starts 81 | app->need_to_prompt_settings_init = 82 | (!storage_file_exists(app->storage, SAVE_PCAP_SETTING_FILEPATH) || 83 | !storage_file_exists(app->storage, SAVE_LOGS_SETTING_FILEPATH)); 84 | 85 | // Submenu 86 | app->submenu = submenu_alloc(); 87 | view_dispatcher_add_view( 88 | app->view_dispatcher, WifiMarauderAppViewSubmenu, submenu_get_view(app->submenu)); 89 | 90 | scene_manager_next_scene(app->scene_manager, WifiMarauderSceneStart); 91 | 92 | return app; 93 | } 94 | 95 | void wifi_marauder_make_app_folder(WifiMarauderApp* app) { 96 | furi_assert(app); 97 | 98 | if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER)) { 99 | dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder"); 100 | } 101 | 102 | if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_PCAPS)) { 103 | dialog_message_show_storage_error(app->dialogs, "Cannot create\npcaps folder"); 104 | } 105 | 106 | if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_DUMPS)) { 107 | dialog_message_show_storage_error(app->dialogs, "Cannot create\ndumps folder"); 108 | } 109 | 110 | if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_LOGS)) { 111 | dialog_message_show_storage_error(app->dialogs, "Cannot create\nlogs folder"); 112 | } 113 | 114 | if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_SCRIPTS)) { 115 | dialog_message_show_storage_error(app->dialogs, "Cannot create\nscripts folder"); 116 | } 117 | 118 | if(!storage_simply_mkdir(app->storage, MARAUDER_APP_FOLDER_HTML)) { 119 | dialog_message_show_storage_error(app->dialogs, "Cannot create\nhtml folder"); 120 | } 121 | } 122 | 123 | void wifi_marauder_load_settings(WifiMarauderApp* app) { 124 | if(storage_file_open( 125 | app->save_pcap_setting_file, 126 | SAVE_PCAP_SETTING_FILEPATH, 127 | FSAM_READ, 128 | FSOM_OPEN_EXISTING)) { 129 | char ok[1]; 130 | storage_file_read(app->save_pcap_setting_file, ok, sizeof(ok)); 131 | app->ok_to_save_pcaps = ok[0] == 'Y'; 132 | } 133 | storage_file_close(app->save_pcap_setting_file); 134 | 135 | if(storage_file_open( 136 | app->save_logs_setting_file, 137 | SAVE_LOGS_SETTING_FILEPATH, 138 | FSAM_READ, 139 | FSOM_OPEN_EXISTING)) { 140 | char ok[1]; 141 | storage_file_read(app->save_logs_setting_file, ok, sizeof(ok)); 142 | app->ok_to_save_logs = ok[0] == 'Y'; 143 | } 144 | storage_file_close(app->save_logs_setting_file); 145 | } 146 | 147 | void wifi_marauder_app_free(WifiMarauderApp* app) { 148 | furi_assert(app); 149 | 150 | // Views 151 | view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewVarItemList); 152 | view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewConsoleOutput); 153 | view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewTextInput); 154 | view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewWidget); 155 | view_dispatcher_remove_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); 156 | 157 | widget_free(app->widget); 158 | text_box_free(app->text_box); 159 | furi_string_free(app->text_box_store); 160 | wifi_text_input_free(app->text_input); 161 | submenu_free(app->submenu); 162 | variable_item_list_free(app->var_item_list); 163 | storage_file_free(app->capture_file); 164 | storage_file_free(app->log_file); 165 | storage_file_free(app->save_pcap_setting_file); 166 | storage_file_free(app->save_logs_setting_file); 167 | 168 | // View dispatcher 169 | view_dispatcher_free(app->view_dispatcher); 170 | scene_manager_free(app->scene_manager); 171 | 172 | wifi_marauder_uart_free(app->uart); 173 | 174 | // Close records 175 | furi_record_close(RECORD_GUI); 176 | furi_record_close(RECORD_STORAGE); 177 | furi_record_close(RECORD_DIALOGS); 178 | 179 | free(app); 180 | } 181 | 182 | int32_t wifi_marauder_app(void* p) { 183 | UNUSED(p); 184 | // Disable expansion protocol to avoid interference with UART Handle 185 | Expansion* expansion = furi_record_open(RECORD_EXPANSION); 186 | expansion_disable(expansion); 187 | 188 | uint8_t attempts = 0; 189 | bool otg_was_enabled = furi_hal_power_is_otg_enabled(); 190 | while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { 191 | furi_hal_power_enable_otg(); 192 | furi_delay_ms(10); 193 | } 194 | furi_delay_ms(200); 195 | 196 | WifiMarauderApp* wifi_marauder_app = wifi_marauder_app_alloc(); 197 | 198 | wifi_marauder_make_app_folder(wifi_marauder_app); 199 | wifi_marauder_load_settings(wifi_marauder_app); 200 | 201 | wifi_marauder_app->uart = wifi_marauder_usart_init(wifi_marauder_app); 202 | 203 | view_dispatcher_run(wifi_marauder_app->view_dispatcher); 204 | 205 | wifi_marauder_app_free(wifi_marauder_app); 206 | 207 | if(furi_hal_power_is_otg_enabled() && !otg_was_enabled) { 208 | furi_hal_power_disable_otg(); 209 | } 210 | 211 | // Return previous state of expansion 212 | expansion_enable(expansion); 213 | furi_record_close(RECORD_EXPANSION); 214 | 215 | return 0; 216 | } 217 | -------------------------------------------------------------------------------- /wifi_marauder_app.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #define WIFI_MARAUDER_APP_VERSION "v0.7.2" 8 | 9 | typedef struct WifiMarauderApp WifiMarauderApp; 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /wifi_marauder_app_i.h: -------------------------------------------------------------------------------- 1 | //** Includes sniffbt and sniffskim for compatible ESP32-WROOM hardware. 2 | // wifi_marauder_scene_start.c also changed **// 3 | #pragma once 4 | 5 | #include "wifi_marauder_app.h" 6 | #include "scenes/wifi_marauder_scene.h" 7 | #include "wifi_marauder_custom_event.h" 8 | #include "wifi_marauder_uart.h" 9 | #include "wifi_marauder_ep.h" 10 | #include "file/sequential_file.h" 11 | #include "script/wifi_marauder_script.h" 12 | #include "script/wifi_marauder_script_worker.h" 13 | #include "script/wifi_marauder_script_executor.h" 14 | #include "script/menu/wifi_marauder_script_stage_menu.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "wifi_marauder_text_input.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define NUM_MENU_ITEMS (27) 31 | 32 | #define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) 33 | #define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512) 34 | 35 | #define MARAUDER_APP_FOLDER_USER "apps_data/marauder" 36 | #define MARAUDER_APP_FOLDER EXT_PATH(MARAUDER_APP_FOLDER_USER) 37 | #define MARAUDER_APP_FOLDER_HTML MARAUDER_APP_FOLDER "/html" 38 | #define MARAUDER_APP_FOLDER_PCAPS MARAUDER_APP_FOLDER "/pcaps" 39 | #define MARAUDER_APP_FOLDER_DUMPS MARAUDER_APP_FOLDER "/dumps" 40 | #define MARAUDER_APP_FOLDER_LOGS MARAUDER_APP_FOLDER "/logs" 41 | #define MARAUDER_APP_FOLDER_USER_PCAPS MARAUDER_APP_FOLDER_USER "/pcaps" 42 | #define MARAUDER_APP_FOLDER_USER_LOGS MARAUDER_APP_FOLDER_USER "/logs" 43 | #define MARAUDER_APP_FOLDER_SCRIPTS MARAUDER_APP_FOLDER "/scripts" 44 | #define MARAUDER_APP_SCRIPT_PATH(file_name) MARAUDER_APP_FOLDER_SCRIPTS "/" file_name ".json" 45 | #define SAVE_PCAP_SETTING_FILEPATH MARAUDER_APP_FOLDER "/save_pcaps_here.setting" 46 | #define SAVE_LOGS_SETTING_FILEPATH MARAUDER_APP_FOLDER "/save_logs_here.setting" 47 | 48 | typedef enum WifiMarauderUserInputType { 49 | WifiMarauderUserInputTypeString, 50 | WifiMarauderUserInputTypeNumber, 51 | WifiMarauderUserInputTypeFileName 52 | } WifiMarauderUserInputType; 53 | 54 | struct WifiMarauderApp { 55 | Gui* gui; 56 | ViewDispatcher* view_dispatcher; 57 | SceneManager* scene_manager; 58 | 59 | char text_input_store[WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE + 1]; 60 | FuriString* text_box_store; 61 | size_t text_box_store_strlen; 62 | TextBox* text_box; 63 | WIFI_TextInput* text_input; 64 | Storage* storage; 65 | File* capture_file; 66 | File* log_file; 67 | char log_file_path[100]; 68 | File* save_pcap_setting_file; 69 | File* save_logs_setting_file; 70 | bool need_to_prompt_settings_init; 71 | int which_prompt; 72 | bool ok_to_save_pcaps; 73 | bool ok_to_save_logs; 74 | bool has_saved_logs_this_session; 75 | DialogsApp* dialogs; 76 | 77 | VariableItemList* var_item_list; 78 | Widget* widget; 79 | Submenu* submenu; 80 | int open_log_file_page; 81 | int open_log_file_num_pages; 82 | 83 | WifiMarauderUart* uart; 84 | int selected_menu_index; 85 | int selected_option_index[NUM_MENU_ITEMS]; 86 | const char* selected_tx_string; 87 | bool is_command; 88 | bool is_custom_tx_string; 89 | bool focus_console_start; 90 | bool show_stopscan_tip; 91 | bool is_writing_pcap; 92 | bool is_writing_log; 93 | 94 | // User input 95 | WifiMarauderUserInputType user_input_type; 96 | char** user_input_string_reference; 97 | int* user_input_number_reference; 98 | char* user_input_file_dir; 99 | char* user_input_file_extension; 100 | 101 | // Automation script 102 | WifiMarauderScript* script; 103 | WifiMarauderScriptWorker* script_worker; 104 | FuriString** script_list; 105 | int script_list_count; 106 | WifiMarauderScriptStage* script_edit_selected_stage; 107 | WifiMarauderScriptStageMenu* script_stage_menu; 108 | WifiMarauderScriptStageListItem* script_stage_edit_first_item; 109 | char*** script_stage_edit_strings_reference; 110 | int* script_stage_edit_string_count_reference; 111 | int** script_stage_edit_numbers_reference; 112 | int* script_stage_edit_number_count_reference; 113 | 114 | // For input source and destination MAC in targeted deauth attack 115 | int special_case_input_step; 116 | char special_case_input_src_addr[20]; 117 | char special_case_input_dst_addr[20]; 118 | }; 119 | 120 | // Supported commands: 121 | // https://github.com/justcallmekoko/ESP32Marauder/wiki/cli 122 | // Scan 123 | // -> If list is empty, then start a new scanap. (Tap any button to stop.) 124 | // -> If there's a list, provide option to rescan and dump list of targets to select. 125 | // -> Press BACK to go back to top-level. 126 | // Attack 127 | // -> Beacon 128 | // -> Deauth 129 | // -> Probe 130 | // -> Rickroll 131 | // Sniff 132 | // -> Beacon 133 | // -> Deauth 134 | // -> ESP 135 | // -> PMKID 136 | // -> Pwnagotchi 137 | // Channel 138 | // Update 139 | // Reboot 140 | 141 | typedef enum { 142 | WifiMarauderAppViewVarItemList, 143 | WifiMarauderAppViewConsoleOutput, 144 | WifiMarauderAppViewTextInput, 145 | WifiMarauderAppViewWidget, 146 | WifiMarauderAppViewSubmenu, 147 | } WifiMarauderAppView; 148 | -------------------------------------------------------------------------------- /wifi_marauder_custom_event.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef enum { 4 | WifiMarauderEventRefreshConsoleOutput = 0, 5 | WifiMarauderEventStartConsole, 6 | WifiMarauderEventStartKeyboard, 7 | WifiMarauderEventSaveSourceMac, 8 | WifiMarauderEventSaveDestinationMac, 9 | WifiMarauderEventStartSettingsInit, 10 | WifiMarauderEventStartLogViewer, 11 | WifiMarauderEventStartScriptSelect, 12 | WifiMarauderEventStartSniffPmkidOptions, 13 | WifiMarauderEventPrevScene 14 | } WifiMarauderCustomEvent; 15 | -------------------------------------------------------------------------------- /wifi_marauder_ep.c: -------------------------------------------------------------------------------- 1 | #include "wifi_marauder_ep.h" 2 | 3 | // returns success (if true, then caller needs to free(the_html)) 4 | bool wifi_marauder_ep_read_html_file(WifiMarauderApp* app, uint8_t** the_html, size_t* html_size) { 5 | // browse for files 6 | FuriString* predefined_filepath = furi_string_alloc_set_str(MARAUDER_APP_FOLDER_HTML); 7 | FuriString* selected_filepath = furi_string_alloc(); 8 | DialogsFileBrowserOptions browser_options; 9 | dialog_file_browser_set_basic_options(&browser_options, ".html", &I_Text_10x10); 10 | if(!dialog_file_browser_show( 11 | app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { 12 | return false; 13 | } 14 | 15 | File* index_html = storage_file_alloc(app->storage); 16 | if(!storage_file_open( 17 | index_html, furi_string_get_cstr(selected_filepath), FSAM_READ, FSOM_OPEN_EXISTING)) { 18 | dialog_message_show_storage_error(app->dialogs, "Cannot open file"); 19 | return false; 20 | } 21 | 22 | uint64_t size = storage_file_size(index_html); 23 | 24 | *the_html = malloc(size); // to be freed by caller 25 | uint8_t* buf_ptr = *the_html; 26 | size_t read = 0; 27 | while(read < size) { 28 | size_t to_read = size - read; 29 | if(to_read > UINT16_MAX) to_read = UINT16_MAX; 30 | uint16_t now_read = storage_file_read(index_html, buf_ptr, (uint16_t)to_read); 31 | read += now_read; 32 | buf_ptr += now_read; 33 | } 34 | 35 | *html_size = read; 36 | 37 | storage_file_close(index_html); 38 | storage_file_free(index_html); 39 | 40 | furi_string_free(selected_filepath); 41 | furi_string_free(predefined_filepath); 42 | 43 | return true; 44 | } -------------------------------------------------------------------------------- /wifi_marauder_ep.h: -------------------------------------------------------------------------------- 1 | // evil portal helper 2 | #pragma once 3 | 4 | #include "wifi_marauder_app_i.h" 5 | 6 | bool wifi_marauder_ep_read_html_file(WifiMarauderApp* app, uint8_t** the_html, size_t* html_size); -------------------------------------------------------------------------------- /wifi_marauder_text_input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "wifi_marauder_validators.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** Text input anonymous structure */ 11 | typedef struct WIFI_TextInput WIFI_TextInput; 12 | typedef void (*WIFI_TextInputCallback)(void* context); 13 | typedef bool (*WIFI_TextInputValidatorCallback)(const char* text, FuriString* error, void* context); 14 | 15 | /** Allocate and initialize text input 16 | * 17 | * This text input is used to enter string 18 | * 19 | * @return WIFI_TextInput instance 20 | */ 21 | WIFI_TextInput* wifi_text_input_alloc(); 22 | 23 | /** Deinitialize and free text input 24 | * 25 | * @param text_input WIFI_TextInput instance 26 | */ 27 | void wifi_text_input_free(WIFI_TextInput* text_input); 28 | 29 | /** Clean text input view Note: this function does not free memory 30 | * 31 | * @param text_input Text input instance 32 | */ 33 | void wifi_text_input_reset(WIFI_TextInput* text_input); 34 | 35 | /** Get text input view 36 | * 37 | * @param text_input WIFI_TextInput instance 38 | * 39 | * @return View instance that can be used for embedding 40 | */ 41 | View* wifi_text_input_get_view(WIFI_TextInput* text_input); 42 | 43 | /** Set text input result callback 44 | * 45 | * @param text_input WIFI_TextInput instance 46 | * @param callback callback fn 47 | * @param callback_context callback context 48 | * @param text_buffer pointer to YOUR text buffer, that we going 49 | * to modify 50 | * @param text_buffer_size YOUR text buffer size in bytes. Max string 51 | * length will be text_buffer_size-1. 52 | * @param clear_default_text clear text from text_buffer on first OK 53 | * event 54 | */ 55 | void wifi_text_input_set_result_callback( 56 | WIFI_TextInput* text_input, 57 | WIFI_TextInputCallback callback, 58 | void* callback_context, 59 | char* text_buffer, 60 | size_t text_buffer_size, 61 | bool clear_default_text); 62 | 63 | void wifi_text_input_set_validator( 64 | WIFI_TextInput* text_input, 65 | WIFI_TextInputValidatorCallback callback, 66 | void* callback_context); 67 | 68 | void wifi_text_input_set_minimum_length(WIFI_TextInput* text_input, size_t minimum_length); 69 | 70 | WIFI_TextInputValidatorCallback wifi_text_input_get_validator_callback(WIFI_TextInput* text_input); 71 | 72 | void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* text_input); 73 | 74 | /** Set text input header text 75 | * 76 | * @param text_input WIFI_TextInput instance 77 | * @param text text to be shown 78 | */ 79 | void wifi_text_input_set_header_text(WIFI_TextInput* text_input, const char* text); 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif -------------------------------------------------------------------------------- /wifi_marauder_uart.c: -------------------------------------------------------------------------------- 1 | #include "wifi_marauder_app_i.h" 2 | #include "wifi_marauder_uart.h" 3 | 4 | #define UART_CH (FuriHalSerialIdUsart) 5 | #define BAUDRATE (115200) 6 | 7 | struct WifiMarauderUart { 8 | WifiMarauderApp* app; 9 | FuriThread* rx_thread; 10 | FuriStreamBuffer* rx_stream; 11 | FuriStreamBuffer* pcap_stream; 12 | FuriHalSerialHandle* serial_handle; 13 | bool pcap; 14 | uint8_t mark_test_buf[11]; 15 | uint8_t mark_test_idx; 16 | uint8_t rx_buf[RX_BUF_SIZE + 1]; 17 | void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context); 18 | void (*handle_rx_pcap_cb)(uint8_t* buf, size_t len, void* context); 19 | }; 20 | 21 | typedef enum { 22 | WorkerEvtStop = (1 << 0), 23 | WorkerEvtRxDone = (1 << 1), 24 | WorkerEvtPcapDone = (1 << 2), 25 | } WorkerEvtFlags; 26 | 27 | void wifi_marauder_uart_set_handle_rx_data_cb( 28 | WifiMarauderUart* uart, 29 | void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)) { 30 | furi_assert(uart); 31 | uart->handle_rx_data_cb = handle_rx_data_cb; 32 | } 33 | 34 | void wifi_marauder_uart_set_handle_rx_pcap_cb( 35 | WifiMarauderUart* uart, 36 | void (*handle_rx_pcap_cb)(uint8_t* buf, size_t len, void* context)) { 37 | furi_assert(uart); 38 | uart->handle_rx_pcap_cb = handle_rx_pcap_cb; 39 | } 40 | 41 | #define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone | WorkerEvtPcapDone) 42 | 43 | void wifi_marauder_uart_on_irq_cb( 44 | FuriHalSerialHandle* handle, 45 | FuriHalSerialRxEvent event, 46 | void* context) { 47 | WifiMarauderUart* uart = (WifiMarauderUart*)context; 48 | 49 | if(event == FuriHalSerialRxEventData) { 50 | uint8_t data = furi_hal_serial_async_rx(handle); 51 | const char* mark_begin = "[BUF/BEGIN]"; 52 | const char* mark_close = "[BUF/CLOSE]"; 53 | if(uart->mark_test_idx != 0) { 54 | // We are trying to match a marker 55 | if(data == mark_begin[uart->mark_test_idx] || 56 | data == mark_close[uart->mark_test_idx]) { 57 | // Received char matches next char in a marker, append to test buffer 58 | uart->mark_test_buf[uart->mark_test_idx++] = data; 59 | if(uart->mark_test_idx == sizeof(uart->mark_test_buf)) { 60 | // Test buffer reached max length, parse what marker this is and discard buffer 61 | if(!memcmp( 62 | uart->mark_test_buf, (void*)mark_begin, sizeof(uart->mark_test_buf))) { 63 | uart->pcap = true; 64 | } else if(!memcmp( 65 | uart->mark_test_buf, 66 | (void*)mark_close, 67 | sizeof(uart->mark_test_buf))) { 68 | uart->pcap = false; 69 | } 70 | uart->mark_test_idx = 0; 71 | } 72 | // Don't pass to stream 73 | return; 74 | } else { 75 | // Received char doesn't match any expected next char, send current test buffer 76 | if(uart->pcap) { 77 | furi_stream_buffer_send( 78 | uart->pcap_stream, uart->mark_test_buf, uart->mark_test_idx, 0); 79 | furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtPcapDone); 80 | } else { 81 | furi_stream_buffer_send( 82 | uart->rx_stream, uart->mark_test_buf, uart->mark_test_idx, 0); 83 | furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); 84 | } 85 | // Reset test buffer and try parsing this char from scratch 86 | uart->mark_test_idx = 0; 87 | } 88 | } 89 | // If we reach here the buffer is empty 90 | if(data == mark_begin[0]) { 91 | // Received marker start, append to test buffer 92 | uart->mark_test_buf[uart->mark_test_idx++] = data; 93 | } else { 94 | // Not a marker start and we aren't matching a marker, this is just data 95 | if(uart->pcap) { 96 | furi_stream_buffer_send(uart->pcap_stream, &data, 1, 0); 97 | furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtPcapDone); 98 | } else { 99 | furi_stream_buffer_send(uart->rx_stream, &data, 1, 0); 100 | furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtRxDone); 101 | } 102 | } 103 | } 104 | } 105 | 106 | static int32_t uart_worker(void* context) { 107 | WifiMarauderUart* uart = (void*)context; 108 | 109 | while(1) { 110 | uint32_t events = 111 | furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever); 112 | furi_check((events & FuriFlagError) == 0); 113 | if(events & WorkerEvtStop) break; 114 | if(events & WorkerEvtRxDone) { 115 | size_t len = furi_stream_buffer_receive(uart->rx_stream, uart->rx_buf, RX_BUF_SIZE, 0); 116 | if(len > 0) { 117 | if(uart->handle_rx_data_cb) uart->handle_rx_data_cb(uart->rx_buf, len, uart->app); 118 | } 119 | } 120 | if(events & WorkerEvtPcapDone) { 121 | size_t len = 122 | furi_stream_buffer_receive(uart->pcap_stream, uart->rx_buf, RX_BUF_SIZE, 0); 123 | if(len > 0) { 124 | if(uart->handle_rx_pcap_cb) uart->handle_rx_pcap_cb(uart->rx_buf, len, uart->app); 125 | } 126 | } 127 | } 128 | 129 | furi_stream_buffer_free(uart->rx_stream); 130 | furi_stream_buffer_free(uart->pcap_stream); 131 | 132 | return 0; 133 | } 134 | 135 | void wifi_marauder_uart_tx(WifiMarauderUart* uart, uint8_t* data, size_t len) { 136 | furi_hal_serial_tx(uart->serial_handle, data, len); 137 | } 138 | 139 | WifiMarauderUart* wifi_marauder_uart_init( 140 | WifiMarauderApp* app, 141 | FuriHalSerialId channel, 142 | const char* thread_name) { 143 | WifiMarauderUart* uart = malloc(sizeof(WifiMarauderUart)); 144 | 145 | uart->app = app; 146 | uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); 147 | uart->pcap_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); 148 | uart->rx_thread = furi_thread_alloc(); 149 | furi_thread_set_name(uart->rx_thread, thread_name); 150 | furi_thread_set_stack_size(uart->rx_thread, 1024); 151 | furi_thread_set_context(uart->rx_thread, uart); 152 | furi_thread_set_callback(uart->rx_thread, uart_worker); 153 | furi_thread_start(uart->rx_thread); 154 | uart->serial_handle = furi_hal_serial_control_acquire(channel); 155 | furi_check(uart->serial_handle); 156 | furi_hal_serial_init(uart->serial_handle, BAUDRATE); 157 | furi_hal_serial_async_rx_start(uart->serial_handle, wifi_marauder_uart_on_irq_cb, uart, false); 158 | 159 | return uart; 160 | } 161 | 162 | WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app) { 163 | return wifi_marauder_uart_init(app, UART_CH, "WifiMarauderUartRxThread"); 164 | } 165 | 166 | void wifi_marauder_uart_free(WifiMarauderUart* uart) { 167 | furi_assert(uart); 168 | 169 | furi_thread_flags_set(furi_thread_get_id(uart->rx_thread), WorkerEvtStop); 170 | furi_thread_join(uart->rx_thread); 171 | furi_thread_free(uart->rx_thread); 172 | 173 | furi_hal_serial_deinit(uart->serial_handle); 174 | furi_hal_serial_control_release(uart->serial_handle); 175 | 176 | free(uart); 177 | } 178 | -------------------------------------------------------------------------------- /wifi_marauder_uart.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "furi_hal.h" 4 | 5 | #define RX_BUF_SIZE (2048) 6 | 7 | typedef struct WifiMarauderUart WifiMarauderUart; 8 | 9 | void wifi_marauder_uart_set_handle_rx_data_cb( 10 | WifiMarauderUart* uart, 11 | void (*handle_rx_data_cb)(uint8_t* buf, size_t len, void* context)); 12 | void wifi_marauder_uart_set_handle_rx_pcap_cb( 13 | WifiMarauderUart* uart, 14 | void (*handle_rx_pcap_cb)(uint8_t* buf, size_t len, void* context)); 15 | void wifi_marauder_uart_tx(WifiMarauderUart* uart, uint8_t* data, size_t len); 16 | WifiMarauderUart* wifi_marauder_usart_init(WifiMarauderApp* app); 17 | void wifi_marauder_uart_free(WifiMarauderUart* uart); 18 | -------------------------------------------------------------------------------- /wifi_marauder_validators.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "wifi_marauder_validators.h" 3 | #include 4 | 5 | struct ValidatorIsFile { 6 | char* app_path_folder; 7 | const char* app_extension; 8 | char* current_name; 9 | }; 10 | 11 | bool validator_is_file_callback(const char* text, FuriString* error, void* context) { 12 | furi_assert(context); 13 | ValidatorIsFile* instance = context; 14 | 15 | if(instance->current_name != NULL) { 16 | if(strcmp(instance->current_name, text) == 0) { 17 | return true; 18 | } 19 | } 20 | 21 | bool ret = true; 22 | FuriString* path = furi_string_alloc_printf( 23 | "%s/%s%s", instance->app_path_folder, text, instance->app_extension); 24 | Storage* storage = furi_record_open(RECORD_STORAGE); 25 | if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) { 26 | ret = false; 27 | furi_string_printf(error, "This name\nexists!\nChoose\nanother one."); 28 | } else { 29 | ret = true; 30 | } 31 | furi_string_free(path); 32 | furi_record_close(RECORD_STORAGE); 33 | 34 | return ret; 35 | } 36 | 37 | ValidatorIsFile* validator_is_file_alloc_init( 38 | const char* app_path_folder, 39 | const char* app_extension, 40 | const char* current_name) { 41 | ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile)); 42 | 43 | instance->app_path_folder = strdup(app_path_folder); 44 | instance->app_extension = app_extension; 45 | if(current_name != NULL) { 46 | instance->current_name = strdup(current_name); 47 | } 48 | 49 | return instance; 50 | } 51 | 52 | void validator_is_file_free(ValidatorIsFile* instance) { 53 | furi_assert(instance); 54 | free(instance->app_path_folder); 55 | free(instance->current_name); 56 | free(instance); 57 | } 58 | -------------------------------------------------------------------------------- /wifi_marauder_validators.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | typedef struct ValidatorIsFile ValidatorIsFile; 9 | 10 | ValidatorIsFile* validator_is_file_alloc_init( 11 | const char* app_path_folder, 12 | const char* app_extension, 13 | const char* current_name); 14 | 15 | void validator_is_file_free(ValidatorIsFile* instance); 16 | 17 | bool validator_is_file_callback(const char* text, FuriString* error, void* context); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | --------------------------------------------------------------------------------