From 2044cb51277886024794f2b63336ace5a9ed32b8 Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Thu, 1 Jun 2023 03:34:45 +0100 Subject: [PATCH] Add mifare fuzzer --- .../external/mifare_fuzzer/application.fam | 15 + .../images/mifare_fuzzer_10px.png | Bin 0 -> 139 bytes .../external/mifare_fuzzer/mifare_fuzzer.c | 157 +++++++++ .../external/mifare_fuzzer/mifare_fuzzer.h | 3 + .../mifare_fuzzer_custom_events.h | 14 + .../external/mifare_fuzzer/mifare_fuzzer_i.h | 76 +++++ .../mifare_fuzzer/mifare_fuzzer_worker.c | 88 +++++ .../mifare_fuzzer/mifare_fuzzer_worker.h | 31 ++ .../scenes/mifare_fuzzer_scene.c | 30 ++ .../scenes/mifare_fuzzer_scene.h | 29 ++ .../scenes/mifare_fuzzer_scene_attack.c | 143 +++++++++ .../scenes/mifare_fuzzer_scene_config.h | 3 + .../scenes/mifare_fuzzer_scene_emulator.c | 242 ++++++++++++++ .../scenes/mifare_fuzzer_scene_start.c | 124 ++++++++ .../views/mifare_fuzzer_emulator.c | 301 ++++++++++++++++++ .../views/mifare_fuzzer_emulator.h | 70 ++++ 16 files changed, 1326 insertions(+) create mode 100644 applications/external/mifare_fuzzer/application.fam create mode 100644 applications/external/mifare_fuzzer/images/mifare_fuzzer_10px.png create mode 100644 applications/external/mifare_fuzzer/mifare_fuzzer.c create mode 100644 applications/external/mifare_fuzzer/mifare_fuzzer.h create mode 100644 applications/external/mifare_fuzzer/mifare_fuzzer_custom_events.h create mode 100644 applications/external/mifare_fuzzer/mifare_fuzzer_i.h create mode 100644 applications/external/mifare_fuzzer/mifare_fuzzer_worker.c create mode 100644 applications/external/mifare_fuzzer/mifare_fuzzer_worker.h create mode 100644 applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.c create mode 100644 applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.h create mode 100644 applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c create mode 100644 applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_config.h create mode 100644 applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c create mode 100644 applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_start.c create mode 100644 applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.c create mode 100644 applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.h diff --git a/applications/external/mifare_fuzzer/application.fam b/applications/external/mifare_fuzzer/application.fam new file mode 100644 index 000000000..13e1a72c9 --- /dev/null +++ b/applications/external/mifare_fuzzer/application.fam @@ -0,0 +1,15 @@ +App( + appid="mifare_fuzzer", + name="Mifare Fuzzer", + apptype=FlipperAppType.EXTERNAL, + entry_point="mifare_fuzzer_app", + requires=[ + "storage", + "gui", + ], + stack_size=4 * 1024, + order=30, + fap_icon="images/mifare_fuzzer_10px.png", + fap_category="NFC", + fap_icon_assets="images", +) diff --git a/applications/external/mifare_fuzzer/images/mifare_fuzzer_10px.png b/applications/external/mifare_fuzzer/images/mifare_fuzzer_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..6987cbf95f8832f702d774103d44fc447bd9737b GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V6Od#Ih$G!y`3kF| kNd=F2-v2mJvpscene_manager, event); +} + +/// @brief mifare_fuzzer_back_event_callback() +/// @param context +/// @return +static bool mifare_fuzzer_back_event_callback(void* context) { + furi_assert(context); + MifareFuzzerApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +/// @brief mifare_fuzzer_tick_event_callback() +/// @param context +static void mifare_fuzzer_tick_event_callback(void* context) { + furi_assert(context); + MifareFuzzerApp* app = context; + scene_manager_handle_tick_event(app->scene_manager); +} + +/// @brief mifare_fuzzer_alloc() +/// @return +MifareFuzzerApp* mifare_fuzzer_alloc() { + MifareFuzzerApp* app = malloc(sizeof(MifareFuzzerApp)); + + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&mifare_fuzzer_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, mifare_fuzzer_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, mifare_fuzzer_back_event_callback); + + // 1000 ticks are about 1 sec + view_dispatcher_set_tick_event_callback( + app->view_dispatcher, mifare_fuzzer_tick_event_callback, MIFARE_FUZZER_TICK_PERIOD); + + // Open GUI record + app->gui = furi_record_open(RECORD_GUI); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // view: select card type + app->submenu_card = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, MifareFuzzerViewSelectCard, submenu_get_view(app->submenu_card)); + + // view: select attack type + app->submenu_attack = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, MifareFuzzerViewSelectAttack, submenu_get_view(app->submenu_attack)); + + // view: emulator + app->emulator_view = mifare_fuzzer_emulator_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + MifareFuzzerViewEmulator, + mifare_fuzzer_emulator_get_view(app->emulator_view)); + + // worker + app->worker = mifare_fuzzer_worker_alloc(); + + // storage + app->storage = furi_record_open(RECORD_STORAGE); + if(!storage_simply_mkdir(app->storage, MIFARE_FUZZER_APP_FOLDER)) { + FURI_LOG_E(TAG, "Could not create folder: %s", MIFARE_FUZZER_APP_FOLDER); + } + + // dialog + app->dialogs = furi_record_open(RECORD_DIALOGS); + + // furi strings + app->uid_str = furi_string_alloc(); + app->file_path = furi_string_alloc(); + app->app_folder = furi_string_alloc_set(MIFARE_FUZZER_APP_FOLDER); + + return app; +} + +/// @brief mifare_fuzzer_free() +/// @param app +void mifare_fuzzer_free(MifareFuzzerApp* app) { + furi_assert(app); + + // Views + //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: Views"); + view_dispatcher_remove_view(app->view_dispatcher, MifareFuzzerViewSelectCard); + view_dispatcher_remove_view(app->view_dispatcher, MifareFuzzerViewSelectAttack); + + // Submenus + //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: Submenus"); + submenu_free(app->submenu_card); + submenu_free(app->submenu_attack); + + // View Dispatcher + //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: View Dispatcher"); + view_dispatcher_free(app->view_dispatcher); + + // Scene Manager + //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: Scene Manager"); + scene_manager_free(app->scene_manager); + + // GUI + //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: GUI"); + furi_record_close(RECORD_GUI); + app->gui = NULL; + + // Worker + //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: Worker"); + mifare_fuzzer_worker_free(app->worker); + + // storage + furi_record_close(RECORD_STORAGE); + app->storage = NULL; + + // dialog + furi_record_close(RECORD_DIALOGS); + app->dialogs = NULL; + + // furi strings + furi_string_free(app->uid_str); + furi_string_free(app->file_path); + furi_string_free(app->app_folder); + + // App + //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: App"); + free(app); +} + +/// @brief mifare_fuzzer_app (ENTRYPOINT) +/// @param p +/// @return +int32_t mifare_fuzzer_app(void* p) { + UNUSED(p); + //FURI_LOG_D(TAG, "mifare_fuzzer_app()"); + + MifareFuzzerApp* app = mifare_fuzzer_alloc(); + // init some defaults + scene_manager_set_scene_state(app->scene_manager, MifareFuzzerSceneStart, 0); + scene_manager_set_scene_state(app->scene_manager, MifareFuzzerSceneAttack, 0); + // open scene + scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneStart); + view_dispatcher_run(app->view_dispatcher); + // free + mifare_fuzzer_free(app); + + return 0; +} diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer.h b/applications/external/mifare_fuzzer/mifare_fuzzer.h new file mode 100644 index 000000000..42e123e5f --- /dev/null +++ b/applications/external/mifare_fuzzer/mifare_fuzzer.h @@ -0,0 +1,3 @@ +#pragma once + +typedef struct MifareFuzzerApp MifareFuzzerApp; diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_custom_events.h b/applications/external/mifare_fuzzer/mifare_fuzzer_custom_events.h new file mode 100644 index 000000000..fc3fc28df --- /dev/null +++ b/applications/external/mifare_fuzzer/mifare_fuzzer_custom_events.h @@ -0,0 +1,14 @@ +#pragma once + +typedef enum MifareFuzzerEvent { + MifareFuzzerEventClassic1k = 1, + MifareFuzzerEventClassic4k, + MifareFuzzerEventUltralight, + MifareFuzzerEventTestValueAttack, + MifareFuzzerEventRandomValuesAttack, + MifareFuzzerEventLoadUIDsFromFileAttack, + MifareFuzzerEventStartAttack, + MifareFuzzerEventStopAttack, + MifareFuzzerEventIncrementTicks, + MifareFuzzerEventDecrementTicks, +} MifareFuzzerEvent; diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_i.h b/applications/external/mifare_fuzzer/mifare_fuzzer_i.h new file mode 100644 index 000000000..ea58fa267 --- /dev/null +++ b/applications/external/mifare_fuzzer/mifare_fuzzer_i.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +//#include +//#include +#include + +#include "mifare_fuzzer.h" + +#include "scenes/mifare_fuzzer_scene.h" +#include "views/mifare_fuzzer_emulator.h" + +#include "mifare_fuzzer_worker.h" + +#define TAG "MifareFuzzerApp" + +#define MIFARE_FUZZER_APP_FOLDER EXT_PATH("mifare_fuzzer") +#define MIFARE_FUZZER_FILE_EXT ".txt" + +#define MIFARE_FUZZER_TICK_PERIOD 200 +#define MIFARE_FUZZER_DEFAULT_TICKS_BETWEEN_CARDS 10 +#define MIFARE_FUZZER_MIN_TICKS_BETWEEN_CARDS 5 +#define MIFARE_FUZZER_MAX_TICKS_BETWEEN_CARDS 50 + +typedef enum MifareFuzzerSceneState { + MifareFuzzerSceneStateClassic1k, + MifareFuzzerSceneStateClassic4k, + MifareFuzzerSceneStateUltralight, +} MifareFuzzerSceneState; + +typedef enum { + MifareFuzzerViewSelectCard, + MifareFuzzerViewSelectAttack, + MifareFuzzerViewEmulator, +} MifareFuzzerView; + +struct MifareFuzzerApp { + Gui* gui; + + ViewDispatcher* view_dispatcher; + + SceneManager* scene_manager; + + DialogsApp* dialogs; + + Storage* storage; + + // Common Views + Submenu* submenu_card; + Submenu* submenu_attack; + + MifareFuzzerEmulator* emulator_view; + + MifareFuzzerWorker* worker; + + MifareCard card; + MifareFuzzerAttack attack; + FuriHalNfcDevData nfc_dev_data; + FuriString* app_folder; + FuriString* file_path; + FuriString* uid_str; + Stream* uids_stream; +}; diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c b/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c new file mode 100644 index 000000000..cc2ba138f --- /dev/null +++ b/applications/external/mifare_fuzzer/mifare_fuzzer_worker.c @@ -0,0 +1,88 @@ + +#include "mifare_fuzzer_worker.h" + +/// @brief mifare_fuzzer_worker_alloc() +/// @return +MifareFuzzerWorker* mifare_fuzzer_worker_alloc() { + MifareFuzzerWorker* mifare_fuzzer_worker = malloc(sizeof(MifareFuzzerWorker)); + // Worker thread attributes + mifare_fuzzer_worker->thread = furi_thread_alloc_ex( + "MifareFuzzerWorker", 8192, mifare_fuzzer_worker_task, mifare_fuzzer_worker); + mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop; + return mifare_fuzzer_worker; +} + +/// @brief mifare_fuzzer_worker_free() +/// @param mifare_fuzzer_worker +void mifare_fuzzer_worker_free(MifareFuzzerWorker* mifare_fuzzer_worker) { + furi_assert(mifare_fuzzer_worker); + furi_thread_free(mifare_fuzzer_worker->thread); + free(mifare_fuzzer_worker); +} + +/// @brief mifare_fuzzer_worker_stop() +/// @param mifare_fuzzer_worker +void mifare_fuzzer_worker_stop(MifareFuzzerWorker* mifare_fuzzer_worker) { + furi_assert(mifare_fuzzer_worker); + if(mifare_fuzzer_worker->state != MifareFuzzerWorkerStateStop) { + mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop; + furi_thread_join(mifare_fuzzer_worker->thread); + } +} + +/// @brief mifare_fuzzer_worker_start() +/// @param mifare_fuzzer_worker +void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker) { + furi_assert(mifare_fuzzer_worker); + mifare_fuzzer_worker->state = MifareFuzzerWorkerStateEmulate; + furi_thread_start(mifare_fuzzer_worker->thread); +} + +/// @brief mifare_fuzzer_worker_task() +/// @param context +/// @return +int32_t mifare_fuzzer_worker_task(void* context) { + MifareFuzzerWorker* mifare_fuzzer_worker = context; + + if(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) { + FuriHalNfcDevData params = mifare_fuzzer_worker->nfc_dev_data; + + furi_hal_nfc_exit_sleep(); + while(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) { + furi_hal_nfc_listen( + params.uid, params.uid_len, params.a_data.atqa, params.a_data.sak, false, 500); + furi_delay_ms(50); + } + furi_hal_nfc_sleep(); + } + + mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop; + + return 0; +} + +/// @brief mifare_fuzzer_worker_is_emulating() +/// @param mifare_fuzzer_worker +/// @return +bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker) { + if(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) { + return true; + } + return false; +} + +/// @brief mifare_fuzzer_worker_set_nfc_dev_data() +/// @param mifare_fuzzer_worker +/// @param nfc_dev_data +void mifare_fuzzer_worker_set_nfc_dev_data( + MifareFuzzerWorker* mifare_fuzzer_worker, + FuriHalNfcDevData nfc_dev_data) { + mifare_fuzzer_worker->nfc_dev_data = nfc_dev_data; +} + +/// @brief mifare_fuzzer_worker_get_nfc_dev_data() +/// @param mifare_fuzzer_worker +/// @return +FuriHalNfcDevData mifare_fuzzer_worker_get_nfc_dev_data(MifareFuzzerWorker* mifare_fuzzer_worker) { + return mifare_fuzzer_worker->nfc_dev_data; +} diff --git a/applications/external/mifare_fuzzer/mifare_fuzzer_worker.h b/applications/external/mifare_fuzzer/mifare_fuzzer_worker.h new file mode 100644 index 000000000..6829f4e9e --- /dev/null +++ b/applications/external/mifare_fuzzer/mifare_fuzzer_worker.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include + +typedef enum MifareFuzzerWorkerState { + MifareFuzzerWorkerStateEmulate, + MifareFuzzerWorkerStateStop, +} MifareFuzzerWorkerState; + +#define UID_LEN 7 +#define ATQA_LEN 2 + +typedef struct MifareFuzzerWorker { + FuriThread* thread; + MifareFuzzerWorkerState state; + FuriHalNfcDevData nfc_dev_data; +} MifareFuzzerWorker; + +// worker +MifareFuzzerWorker* mifare_fuzzer_worker_alloc(); +void mifare_fuzzer_worker_free(MifareFuzzerWorker* mifare_fuzzer_worker); +void mifare_fuzzer_worker_stop(MifareFuzzerWorker* mifare_fuzzer_worker); +void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker); +// task +int32_t mifare_fuzzer_worker_task(void* context); +// +bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker); +void mifare_fuzzer_worker_set_nfc_dev_data( + MifareFuzzerWorker* mifare_fuzzer_worker, + FuriHalNfcDevData nfc_dev_data); +FuriHalNfcDevData mifare_fuzzer_worker_get_nfc_dev_data(MifareFuzzerWorker* mifare_fuzzer_worker); diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.c new file mode 100644 index 000000000..1ee693eae --- /dev/null +++ b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.c @@ -0,0 +1,30 @@ +#include "mifare_fuzzer_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const mifare_fuzzer_on_enter_handlers[])(void*) = { +#include "mifare_fuzzer_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const mifare_fuzzer_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "mifare_fuzzer_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const mifare_fuzzer_on_exit_handlers[])(void* context) = { +#include "mifare_fuzzer_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers mifare_fuzzer_scene_handlers = { + .on_enter_handlers = mifare_fuzzer_on_enter_handlers, + .on_event_handlers = mifare_fuzzer_on_event_handlers, + .on_exit_handlers = mifare_fuzzer_on_exit_handlers, + .scene_num = MifareFuzzerSceneNum, +}; diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.h b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.h new file mode 100644 index 000000000..e3e4cde18 --- /dev/null +++ b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) MifareFuzzerScene##id, +typedef enum { +#include "mifare_fuzzer_scene_config.h" + MifareFuzzerSceneNum, +} MifareFuzzerScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers mifare_fuzzer_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "mifare_fuzzer_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "mifare_fuzzer_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "mifare_fuzzer_scene_config.h" +#undef ADD_SCENE diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c new file mode 100644 index 000000000..af5be18ad --- /dev/null +++ b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c @@ -0,0 +1,143 @@ +#include "../mifare_fuzzer_i.h" +#include "../mifare_fuzzer_custom_events.h" + +enum SubmenuIndex { + SubmenuIndexTestValue, + SubmenuIndexRandomValuesAttack, + SubmenuIndexLoadUIDsFromFile, +}; + +/// @brief mifare_fuzzer_scene_attack_submenu_callback() +/// @param context +/// @param index +void mifare_fuzzer_scene_attack_submenu_callback(void* context, uint32_t index) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_submenu_callback() :: index = %ld", index); + MifareFuzzerApp* app = context; + uint8_t custom_event = 255; + switch(index) { + case SubmenuIndexTestValue: + custom_event = MifareFuzzerEventTestValueAttack; + break; + case SubmenuIndexRandomValuesAttack: + custom_event = MifareFuzzerEventRandomValuesAttack; + break; + case SubmenuIndexLoadUIDsFromFile: + custom_event = MifareFuzzerEventLoadUIDsFromFileAttack; + break; + default: + return; + } + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_submenu_callback() :: custom_event = %d", custom_event); + view_dispatcher_send_custom_event(app->view_dispatcher, custom_event); +} + +/// @brief mifare_fuzzer_scene_attack_on_enter() +/// @param context +void mifare_fuzzer_scene_attack_on_enter(void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_enter()"); + MifareFuzzerApp* app = context; + + Submenu* submenu_attack = app->submenu_attack; + submenu_set_header(submenu_attack, "Mifare Fuzzer (attack)"); + submenu_add_item( + submenu_attack, + "Test Values", + SubmenuIndexTestValue, + mifare_fuzzer_scene_attack_submenu_callback, + app); + submenu_add_item( + submenu_attack, + "Random Values", + SubmenuIndexRandomValuesAttack, + mifare_fuzzer_scene_attack_submenu_callback, + app); + submenu_add_item( + submenu_attack, + "Load UIDs from file", + SubmenuIndexLoadUIDsFromFile, + mifare_fuzzer_scene_attack_submenu_callback, + app); + + // set selected menu + submenu_set_selected_item( + submenu_attack, + scene_manager_get_scene_state(app->scene_manager, MifareFuzzerSceneAttack)); + + view_dispatcher_switch_to_view(app->view_dispatcher, MifareFuzzerViewSelectAttack); +} + +/// @brief mifare_fuzzer_scene_attack_on_event() +/// @param context +/// @param event +/// @return +bool mifare_fuzzer_scene_attack_on_event(void* context, SceneManagerEvent event) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_event()"); + MifareFuzzerApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_event() :: event.event = %ld", event.event); + if(event.event == MifareFuzzerEventTestValueAttack) { + // save selected item + scene_manager_set_scene_state( + app->scene_manager, MifareFuzzerSceneAttack, SubmenuIndexTestValue); + // set emulator attack + app->attack = MifareFuzzerAttackTestValues; + mifare_fuzzer_emulator_set_attack(app->emulator_view, app->attack); + // open next scene + scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneEmulator); + consumed = true; + } else if(event.event == MifareFuzzerEventRandomValuesAttack) { + // save selected item + scene_manager_set_scene_state( + app->scene_manager, MifareFuzzerSceneAttack, SubmenuIndexRandomValuesAttack); + // set emulator attack + app->attack = MifareFuzzerAttackRandomValues; + mifare_fuzzer_emulator_set_attack(app->emulator_view, app->attack); + // open next scene + scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneEmulator); + consumed = true; + } else if(event.event == MifareFuzzerEventLoadUIDsFromFileAttack) { + // save selected item + scene_manager_set_scene_state( + app->scene_manager, MifareFuzzerSceneAttack, SubmenuIndexLoadUIDsFromFile); + // set emulator attack + app->attack = MifareFuzzerAttackLoadUidsFromFile; + mifare_fuzzer_emulator_set_attack(app->emulator_view, app->attack); + // open dialog file + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, MIFARE_FUZZER_FILE_EXT, NULL); + browser_options.hide_ext = false; + bool res = dialog_file_browser_show( + app->dialogs, app->file_path, app->app_folder, &browser_options); + if(res) { + app->uids_stream = buffered_file_stream_alloc(app->storage); + res = buffered_file_stream_open( + app->uids_stream, + furi_string_get_cstr(app->file_path), + FSAM_READ, + FSOM_OPEN_EXISTING); + if(res) { + // open next scene + scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneEmulator); + } else { + buffered_file_stream_close(app->uids_stream); + } + } + consumed = true; + } + } else if(event.type == SceneManagerEventTypeTick) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_event() :: SceneManagerEventTypeTick"); + //consumed = true; + } + + return consumed; +} + +/// @brief mifare_fuzzer_scene_attack_on_exit() +/// @param context +void mifare_fuzzer_scene_attack_on_exit(void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_attack_on_exit()"); + MifareFuzzerApp* app = context; + submenu_reset(app->submenu_attack); +} diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_config.h b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_config.h new file mode 100644 index 000000000..e93fc26e7 --- /dev/null +++ b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_config.h @@ -0,0 +1,3 @@ +ADD_SCENE(mifare_fuzzer, start, Start) +ADD_SCENE(mifare_fuzzer, attack, Attack) +ADD_SCENE(mifare_fuzzer, emulator, Emulator) \ No newline at end of file diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c new file mode 100644 index 000000000..4e4be5dfd --- /dev/null +++ b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c @@ -0,0 +1,242 @@ +#include "../mifare_fuzzer_i.h" + +uint8_t tick_counter = 0; +uint8_t attack_step = 0; + +uint8_t id_uid_test[9][7] = { + {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}, + {0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28}, + {0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}, + {0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a}, + {0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b}, + {0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c}, + {0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d}, + {0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e}, + {0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f}, +}; + +/// @brief mifare_fuzzer_scene_emulator_callback() +/// @param event +/// @param context +static void mifare_fuzzer_scene_emulator_callback(MifareFuzzerEvent event, void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_callback()"); + furi_assert(context); + MifareFuzzerApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +/// @brief mifare_fuzzer_scene_emulator_on_enter() +/// @param context +void mifare_fuzzer_scene_emulator_on_enter(void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_enter()"); + MifareFuzzerApp* app = context; + MifareFuzzerEmulator* emulator = app->emulator_view; + + // init callback + mifare_fuzzer_emulator_set_callback(emulator, mifare_fuzzer_scene_emulator_callback, app); + // init ticks + tick_counter = 0; + mifare_fuzzer_emulator_set_tick_num(app->emulator_view, tick_counter); + emulator->ticks_between_cards = MIFARE_FUZZER_DEFAULT_TICKS_BETWEEN_CARDS; + mifare_fuzzer_emulator_set_ticks_between_cards( + app->emulator_view, emulator->ticks_between_cards); + // init default card data + FuriHalNfcDevData nfc_dev_data; + nfc_dev_data.a_data.atqa[0] = 0x00; + nfc_dev_data.a_data.atqa[1] = 0x00; + nfc_dev_data.a_data.sak = 0x00; + if(app->card == MifareCardUltralight) { + nfc_dev_data.uid_len = 0x07; + } else { + nfc_dev_data.uid_len = 0x04; + } + for(uint32_t i = 0; i < nfc_dev_data.uid_len; i++) { + nfc_dev_data.uid[i] = 0x00; + } + mifare_fuzzer_emulator_set_nfc_dev_data(app->emulator_view, nfc_dev_data); + // init other vars + attack_step = 0; + + // switch to view + view_dispatcher_switch_to_view(app->view_dispatcher, MifareFuzzerViewEmulator); +} + +/// @brief mifare_fuzzer_scene_emulator_on_event() +/// @param context +/// @param event +/// @return +bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent event) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event()"); + FuriHalNfcDevData nfc_dev_data; + + MifareFuzzerApp* app = context; + MifareFuzzerEmulator* emulator = app->emulator_view; + + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == MifareFuzzerEventStartAttack) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event() :: MifareFuzzerEventStartAttack"); + + // Stop worker + mifare_fuzzer_worker_stop(app->worker); + + // Set card type + // TODO: Move somewhere else, I do not like this to be there + if(app->card == MifareCardClassic1k) { + nfc_dev_data.a_data.atqa[0] = 0x04; + nfc_dev_data.a_data.atqa[1] = 0x00; + nfc_dev_data.a_data.sak = 0x08; + nfc_dev_data.uid_len = 0x04; + } else if(app->card == MifareCardClassic4k) { + nfc_dev_data.a_data.atqa[0] = 0x02; + nfc_dev_data.a_data.atqa[1] = 0x00; + nfc_dev_data.a_data.sak = 0x18; + nfc_dev_data.uid_len = 0x04; + } else if(app->card == MifareCardUltralight) { + nfc_dev_data.a_data.atqa[0] = 0x44; + nfc_dev_data.a_data.atqa[1] = 0x00; + nfc_dev_data.a_data.sak = 0x00; + nfc_dev_data.uid_len = 0x07; + } + + // Set UIDs + if(app->attack == MifareFuzzerAttackTestValues) { + // Load test UIDs + for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) { + nfc_dev_data.uid[i] = id_uid_test[attack_step][i]; + } + // Next UIDs on next loop + if(attack_step >= 8) { + attack_step = 0; + } else { + attack_step++; + } + } else if(app->attack == MifareFuzzerAttackRandomValues) { + if(app->card == MifareCardUltralight) { + // First byte of a 7 byte UID is the manufacturer-code + // https://github.com/Proxmark/proxmark3/blob/master/client/taginfo.c + // https://stackoverflow.com/questions/37837730/mifare-cards-distinguish-between-4-byte-and-7-byte-uids + // https://stackoverflow.com/questions/31233652/how-to-detect-manufacturer-from-nfc-tag-using-android + + // TODO: Manufacture-code must be selectable from a list + // use a fixed manufacture-code for now: 0x04 = NXP Semiconductors Germany + nfc_dev_data.uid[0] = 0x04; + for(uint8_t i = 1; i < nfc_dev_data.uid_len; i++) { + nfc_dev_data.uid[i] = (furi_hal_random_get() & 0xFF); + } + } else { + for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) { + nfc_dev_data.uid[i] = (furi_hal_random_get() & 0xFF); + } + } + } else if(app->attack == MifareFuzzerAttackLoadUidsFromFile) { + //bool end_of_list = false; + // read stream + while(true) { + furi_string_reset(app->uid_str); + if(!stream_read_line(app->uids_stream, app->uid_str)) { + // restart from beginning on empty line + stream_rewind(app->uids_stream); + continue; + //end_of_list = true; + } + // Skip comments + if(furi_string_get_char(app->uid_str, 0) == '#') continue; + // Skip lines with invalid length + if((furi_string_size(app->uid_str) != 9) && + (furi_string_size(app->uid_str) != 15)) + continue; + break; + } + + // TODO: stop on end of list? + //if(end_of_list) break; + + // parse string to UID + // TODO: a better validation on input? + for(uint8_t i = 0; i < nfc_dev_data.uid_len; i++) { + if(i <= ((furi_string_size(app->uid_str) - 1) / 2)) { + char temp_str[3]; + temp_str[0] = furi_string_get_cstr(app->uid_str)[i * 2]; + temp_str[1] = furi_string_get_cstr(app->uid_str)[i * 2 + 1]; + temp_str[2] = '\0'; + nfc_dev_data.uid[i] = (uint8_t)strtol(temp_str, NULL, 16); + } else { + nfc_dev_data.uid[i] = 0x00; + } + } + } + + mifare_fuzzer_worker_set_nfc_dev_data(app->worker, nfc_dev_data); + mifare_fuzzer_emulator_set_nfc_dev_data(app->emulator_view, nfc_dev_data); + + // Reset tick_counter + tick_counter = 0; + mifare_fuzzer_emulator_set_tick_num(app->emulator_view, tick_counter); + + // Start worker + mifare_fuzzer_worker_start(app->worker); + + } else if(event.event == MifareFuzzerEventStopAttack) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event() :: MifareFuzzerEventStopAttack"); + // Stop worker + mifare_fuzzer_worker_stop(app->worker); + } else if(event.event == MifareFuzzerEventIncrementTicks) { + if(!emulator->is_attacking) { + if(emulator->ticks_between_cards < MIFARE_FUZZER_MAX_TICKS_BETWEEN_CARDS) { + emulator->ticks_between_cards++; + mifare_fuzzer_emulator_set_ticks_between_cards( + app->emulator_view, emulator->ticks_between_cards); + }; + }; + } else if(event.event == MifareFuzzerEventDecrementTicks) { + if(!emulator->is_attacking) { + if(emulator->ticks_between_cards > MIFARE_FUZZER_MIN_TICKS_BETWEEN_CARDS) { + emulator->ticks_between_cards--; + mifare_fuzzer_emulator_set_ticks_between_cards( + app->emulator_view, emulator->ticks_between_cards); + }; + }; + } + consumed = true; + } else if(event.type == SceneManagerEventTypeTick) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event() :: SceneManagerEventTypeTick"); + + // Used to check tick length (not perfect but enough) + //FuriHalRtcDateTime curr_dt; + //furi_hal_rtc_get_datetime(&curr_dt); + //FURI_LOG_D(TAG, "Time is: %.2d:%.2d:%.2d", curr_dt.hour, curr_dt.minute, curr_dt.second); + + // If emulator is attacking + if(emulator->is_attacking) { + // increment tick_counter + tick_counter++; + mifare_fuzzer_emulator_set_tick_num(app->emulator_view, tick_counter); + //FURI_LOG_D(TAG, "tick_counter is: %.2d", tick_counter); + if(tick_counter >= emulator->ticks_between_cards) { + // Queue event for changing UID + view_dispatcher_send_custom_event( + app->view_dispatcher, MifareFuzzerEventStartAttack); + } + } + + consumed = true; + } + + return consumed; +} + +/// @brief mifare_fuzzer_scene_emulator_on_exit() +/// @param context +void mifare_fuzzer_scene_emulator_on_exit(void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_exit()"); + MifareFuzzerApp* app = context; + mifare_fuzzer_worker_stop(app->worker); + + if(app->attack == MifareFuzzerAttackLoadUidsFromFile) { + furi_string_reset(app->uid_str); + stream_rewind(app->uids_stream); + buffered_file_stream_close(app->uids_stream); + } +} diff --git a/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_start.c b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_start.c new file mode 100644 index 000000000..443f117f4 --- /dev/null +++ b/applications/external/mifare_fuzzer/scenes/mifare_fuzzer_scene_start.c @@ -0,0 +1,124 @@ +#include "../mifare_fuzzer_i.h" +#include "../mifare_fuzzer_custom_events.h" + +enum SubmenuIndex { + SubmenuIndexClassic1k, + SubmenuIndexClassic4k, + SubmenuIndexUltralight, +}; + +/// @brief mifare_fuzzer_scene_start_submenu_callback() +/// @param context +/// @param index +void mifare_fuzzer_scene_start_submenu_callback(void* context, uint32_t index) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_submenu_callback() :: index = %ld", index); + MifareFuzzerApp* app = context; + uint8_t custom_event = 255; + switch(index) { + case SubmenuIndexClassic1k: + custom_event = MifareFuzzerEventClassic1k; + break; + case SubmenuIndexClassic4k: + custom_event = MifareFuzzerEventClassic4k; + break; + case SubmenuIndexUltralight: + custom_event = MifareFuzzerEventUltralight; + break; + default: + return; + } + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_submenu_callback() :: custom_event = %d", custom_event); + view_dispatcher_send_custom_event(app->view_dispatcher, custom_event); +} + +/// @brief mifare_fuzzer_scene_start_on_enter() +/// @param context +void mifare_fuzzer_scene_start_on_enter(void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_enter()"); + MifareFuzzerApp* app = context; + + Submenu* submenu_card = app->submenu_card; + submenu_set_header(submenu_card, "Mifare Fuzzer (card)"); + submenu_add_item( + submenu_card, + "Classic 1k", + SubmenuIndexClassic1k, + mifare_fuzzer_scene_start_submenu_callback, + app); + submenu_add_item( + submenu_card, + "Classic 4k", + SubmenuIndexClassic4k, + mifare_fuzzer_scene_start_submenu_callback, + app); + submenu_add_item( + submenu_card, + "Ultralight", + SubmenuIndexUltralight, + mifare_fuzzer_scene_start_submenu_callback, + app); + + // set selected menu + submenu_set_selected_item( + submenu_card, scene_manager_get_scene_state(app->scene_manager, MifareFuzzerSceneStart)); + + view_dispatcher_switch_to_view(app->view_dispatcher, MifareFuzzerViewSelectCard); +} + +/// @brief mifare_fuzzer_scene_start_on_event() +/// @param context +/// @param event +/// @return +bool mifare_fuzzer_scene_start_on_event(void* context, SceneManagerEvent event) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_event()"); + MifareFuzzerApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_event() :: event.event = %ld", event.event); + if(event.event == MifareFuzzerEventClassic1k) { + // save selected item + scene_manager_set_scene_state( + app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexClassic1k); + // set emulator card + app->card = MifareCardClassic1k; + mifare_fuzzer_emulator_set_card(app->emulator_view, app->card); + // open next scene + scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack); + consumed = true; + } else if(event.event == MifareFuzzerEventClassic4k) { + // save selected item + scene_manager_set_scene_state( + app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexClassic4k); + // set emulator card + app->card = MifareCardClassic4k; + mifare_fuzzer_emulator_set_card(app->emulator_view, app->card); + // open next scene + scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack); + consumed = true; + } else if(event.event == MifareFuzzerEventUltralight) { + // save selected item + scene_manager_set_scene_state( + app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexUltralight); + // set emulator card + app->card = MifareCardUltralight; + mifare_fuzzer_emulator_set_card(app->emulator_view, app->card); + // open next scene + scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeTick) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_event() :: SceneManagerEventTypeTick"); + //consumed = true; + } + + return consumed; +} + +/// @brief mifare_fuzzer_scene_start_on_exit() +/// @param context +void mifare_fuzzer_scene_start_on_exit(void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_exit()"); + MifareFuzzerApp* app = context; + submenu_reset(app->submenu_card); +} diff --git a/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.c b/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.c new file mode 100644 index 000000000..d4925e02b --- /dev/null +++ b/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.c @@ -0,0 +1,301 @@ +#include "mifare_fuzzer_emulator.h" + +#define TAG "MifareFuzzerApp_emulator_view" + +// Screen is 128 × 64 pixels + +/// @brief mifare_fuzzer_emulator_set_callback +/// @param mifare_fuzzer_emulator +/// @param callback +/// @param context +void mifare_fuzzer_emulator_set_callback( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + MifareFuzzerEmulatorCallback callback, + void* context) { + furi_assert(mifare_fuzzer_emulator); + furi_assert(callback); + + mifare_fuzzer_emulator->callback = callback; + mifare_fuzzer_emulator->context = context; +} + +/// @brief mifare_fuzzer_emulator_draw_callback +/// @param canvas +/// @param _model +static void mifare_fuzzer_emulator_draw_callback(Canvas* canvas, void* _model) { + MifareFuzzerEmulatorModel* model = _model; + FuriString* furi_string = furi_string_alloc(); + + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + + // Primary font + canvas_set_font(canvas, FontPrimary); + // Title + canvas_draw_str(canvas, 4, 11, model->title); + + // Emulated UID + uint8_t cpos; + char uid[25]; + char uid_char[3]; + cpos = 0; + for(uint8_t i = 0; i < model->nfc_dev_data.uid_len; i++) { + if(i > 0) { + uid[cpos] = ':'; + cpos++; + } + snprintf(uid_char, sizeof(uid_char), "%02X", model->nfc_dev_data.uid[i]); + uid[cpos] = uid_char[0]; + cpos++; + uid[cpos] = uid_char[1]; + cpos++; + } + uid[cpos] = 0x00; + canvas_draw_str_aligned(canvas, 128 / 2, 43, AlignCenter, AlignCenter, uid); + + // Secondary font + canvas_set_font(canvas, FontSecondary); + // Card + canvas_draw_str(canvas, 4, 22, "c:"); + canvas_draw_str(canvas, 15, 22, model->mifare_card_dsc); + // Timing + furi_string_printf(furi_string, "%d", model->ticks_between_cards); + canvas_draw_str(canvas, 90, 22, "t:"); + canvas_draw_str(canvas, 100, 22, furi_string_get_cstr(furi_string)); + // Attack + canvas_draw_str(canvas, 4, 33, "a:"); + canvas_draw_str(canvas, 15, 33, model->attack_dsc); + + if(!model->is_attacking) { + elements_button_left(canvas, "t-1"); + elements_button_center(canvas, "Start"); + elements_button_right(canvas, "t+1"); + } else { + canvas_draw_line(canvas, 1, 49, (128 * model->tick_num / model->ticks_between_cards), 49); + elements_button_center(canvas, "Stop"); + } + + // Free temp string + furi_string_free(furi_string); +} + +/// @brief mifare_fuzzer_emulator_input_callback +/// @param event +/// @param context +/// @return +static bool mifare_fuzzer_emulator_input_callback(InputEvent* event, void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_emulator_input_callback()"); + furi_assert(context); + MifareFuzzerEmulator* mifare_fuzzer_emulator = context; + bool consumed = false; + + if(event->type == InputTypeShort) { + if(event->key == InputKeyRight) { + if(!mifare_fuzzer_emulator->is_attacking) { + mifare_fuzzer_emulator->callback( + MifareFuzzerEventIncrementTicks, mifare_fuzzer_emulator->context); + }; + consumed = true; + } else if(event->key == InputKeyLeft) { + if(!mifare_fuzzer_emulator->is_attacking) { + mifare_fuzzer_emulator->callback( + MifareFuzzerEventDecrementTicks, mifare_fuzzer_emulator->context); + }; + consumed = true; + } else if(event->key == InputKeyUp) { + consumed = true; + } else if(event->key == InputKeyDown) { + consumed = true; + } else if(event->key == InputKeyOk) { + // Toggle attack + if(mifare_fuzzer_emulator->is_attacking) { + mifare_fuzzer_emulator->is_attacking = false; + mifare_fuzzer_emulator->callback( + MifareFuzzerEventStopAttack, mifare_fuzzer_emulator->context); + } else { + mifare_fuzzer_emulator->is_attacking = true; + mifare_fuzzer_emulator->callback( + MifareFuzzerEventStartAttack, mifare_fuzzer_emulator->context); + } + + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel * model, + { model->is_attacking = mifare_fuzzer_emulator->is_attacking; }, + true); + + consumed = true; + } + } + + return consumed; +} + +/// @brief mifare_fuzzer_emulator_enter_callback +/// @param context +static void mifare_fuzzer_emulator_enter_callback(void* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_emulator_enter_callback()"); + furi_assert(context); + MifareFuzzerEmulator* mifare_fuzzer_emulator = context; + + //UNUSED(mifare_fuzzer_emulator); + mifare_fuzzer_emulator->is_attacking = false; + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel * model, + { model->is_attacking = false; }, + true); +} + +/// @brief mifare_fuzzer_emulator_alloc +/// @return +MifareFuzzerEmulator* mifare_fuzzer_emulator_alloc() { + MifareFuzzerEmulator* mifare_fuzzer_emulator = malloc(sizeof(MifareFuzzerEmulator)); + mifare_fuzzer_emulator->view = view_alloc(); + view_set_context(mifare_fuzzer_emulator->view, mifare_fuzzer_emulator); + view_allocate_model( + mifare_fuzzer_emulator->view, ViewModelTypeLocking, sizeof(MifareFuzzerEmulatorModel)); + view_set_draw_callback(mifare_fuzzer_emulator->view, mifare_fuzzer_emulator_draw_callback); + view_set_input_callback(mifare_fuzzer_emulator->view, mifare_fuzzer_emulator_input_callback); + view_set_enter_callback(mifare_fuzzer_emulator->view, mifare_fuzzer_emulator_enter_callback); + + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel * model, + { model->title = "Mifare Fuzzer (emulator)"; }, + true); + + return mifare_fuzzer_emulator; +} + +/// @brief mifare_fuzzer_emulator_free +/// @param context +void mifare_fuzzer_emulator_free(MifareFuzzerEmulator* context) { + //FURI_LOG_D(TAG, "mifare_fuzzer_emulator_free()"); + furi_assert(context); + MifareFuzzerEmulator* mifare_fuzzer_emulator = context; + /* + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel* model, + { + UNUSED(model); + }, + true + ); + */ + + view_free(mifare_fuzzer_emulator->view); + free(mifare_fuzzer_emulator); +} + +/// @brief mifare_fuzzer_emulator_get_view +/// @param mifare_fuzzer_emulator +/// @return +View* mifare_fuzzer_emulator_get_view(MifareFuzzerEmulator* mifare_fuzzer_emulator) { + furi_assert(mifare_fuzzer_emulator); + return mifare_fuzzer_emulator->view; +} + +/// @brief Set card type +/// @param mifare_fuzzer_emulator +/// @param mifare_card +void mifare_fuzzer_emulator_set_card( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + MifareCard mifare_card) { + furi_assert(mifare_fuzzer_emulator); + furi_assert(mifare_card); + + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel * model, + { + model->mifare_card = mifare_card; + switch(mifare_card) { + case MifareCardClassic1k: + model->mifare_card_dsc = "Classic 1k"; + break; + case MifareCardClassic4k: + model->mifare_card_dsc = "Classic 4k"; + break; + case MifareCardUltralight: + model->mifare_card_dsc = "Ultralight"; + break; + } + }, + true); +} + +/// @brief Set attack type +/// @param mifare_fuzzer_emulator +/// @param mifare_attack +void mifare_fuzzer_emulator_set_attack( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + MifareFuzzerAttack mifare_attack) { + furi_assert(mifare_fuzzer_emulator); + furi_assert(mifare_attack); + + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel * model, + { + model->attack = mifare_attack; + switch(mifare_attack) { + case MifareFuzzerAttackTestValues: + model->attack_dsc = "Test values"; + break; + case MifareFuzzerAttackRandomValues: + model->attack_dsc = "Random values"; + break; + case MifareFuzzerAttackLoadUidsFromFile: + model->attack_dsc = "Load Uids From File"; + break; + } + }, + true); +} + +/// @brief mifare_fuzzer_emulator_set_nfc_dev_data +/// @param mifare_fuzzer_emulator +/// @param nfc_dev_data +void mifare_fuzzer_emulator_set_nfc_dev_data( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + FuriHalNfcDevData nfc_dev_data) { + furi_assert(mifare_fuzzer_emulator); + + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel * model, + { model->nfc_dev_data = nfc_dev_data; }, + true); +} + +/// @brief mifare_fuzzer_emulator_set_ticks_between_cards +/// @param mifare_fuzzer_emulator +/// @param ticks +void mifare_fuzzer_emulator_set_ticks_between_cards( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + uint8_t ticks) { + furi_assert(mifare_fuzzer_emulator); + + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel * model, + { model->ticks_between_cards = ticks; }, + true); +} + +/// @brief mifare_fuzzer_emulator_set_tick_num +/// @param mifare_fuzzer_emulator +/// @param tick_num +void mifare_fuzzer_emulator_set_tick_num( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + uint8_t tick_num) { + furi_assert(mifare_fuzzer_emulator); + + with_view_model( + mifare_fuzzer_emulator->view, + MifareFuzzerEmulatorModel * model, + { model->tick_num = tick_num; }, + true); +} diff --git a/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.h b/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.h new file mode 100644 index 000000000..30e56f4dd --- /dev/null +++ b/applications/external/mifare_fuzzer/views/mifare_fuzzer_emulator.h @@ -0,0 +1,70 @@ +#pragma once +#include "../mifare_fuzzer_custom_events.h" +#include +#include +#include +#include + +typedef void (*MifareFuzzerEmulatorCallback)(MifareFuzzerEvent event, void* context); + +typedef enum MifareCard { + MifareCardClassic1k = 1, + MifareCardClassic4k, + MifareCardUltralight, +} MifareCard; + +typedef enum MifareFuzzerAttack { + MifareFuzzerAttackTestValues = 1, + MifareFuzzerAttackRandomValues, + MifareFuzzerAttackLoadUidsFromFile, +} MifareFuzzerAttack; + +typedef struct MifareFuzzerEmulator { + View* view; + MifareFuzzerEmulatorCallback callback; + void* context; + bool is_attacking; + uint8_t ticks_between_cards; +} MifareFuzzerEmulator; + +typedef struct MifareFuzzerEmulatorModel { + const char* title; + MifareCard mifare_card; + const char* mifare_card_dsc; + MifareFuzzerAttack attack; + const char* attack_dsc; + FuriHalNfcDevData nfc_dev_data; + bool is_attacking; + uint8_t tick_num; + uint8_t ticks_between_cards; +} MifareFuzzerEmulatorModel; + +MifareFuzzerEmulator* mifare_fuzzer_emulator_alloc(); + +void mifare_fuzzer_emulator_free(MifareFuzzerEmulator* context); + +View* mifare_fuzzer_emulator_get_view(MifareFuzzerEmulator* context); + +void mifare_fuzzer_emulator_set_card( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + MifareCard mifare_card); +void mifare_fuzzer_emulator_set_attack( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + MifareFuzzerAttack mifare_attack); + +void mifare_fuzzer_emulator_set_callback( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + MifareFuzzerEmulatorCallback callback, + void* context); + +void mifare_fuzzer_emulator_set_nfc_dev_data( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + FuriHalNfcDevData nfc_dev_data); + +void mifare_fuzzer_emulator_set_ticks_between_cards( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + uint8_t ticks); + +void mifare_fuzzer_emulator_set_tick_num( + MifareFuzzerEmulator* mifare_fuzzer_emulator, + uint8_t tick_num);