Vladimir Kondenko 2 лет назад
Родитель
Сommit
fb02471461

+ 1 - 0
apps_source_code/mifare_fuzzer/application.fam

@@ -4,6 +4,7 @@ App(
     apptype=FlipperAppType.EXTERNAL,
     entry_point="mifare_fuzzer_app",
     requires=[
+        "nfc",
         "storage",
         "gui",
     ],

+ 6 - 2
apps_source_code/mifare_fuzzer/mifare_fuzzer.c

@@ -80,7 +80,8 @@ MifareFuzzerApp* mifare_fuzzer_alloc() {
 
     // furi strings
     app->uid_str = furi_string_alloc();
-    app->file_path = furi_string_alloc();
+    app->uid_file_path = furi_string_alloc();
+    app->card_file_path = furi_string_alloc();
     app->app_folder = furi_string_alloc_set(MIFARE_FUZZER_APP_FOLDER);
 
     return app;
@@ -129,8 +130,11 @@ void mifare_fuzzer_free(MifareFuzzerApp* app) {
 
     // furi strings
     furi_string_free(app->uid_str);
-    furi_string_free(app->file_path);
+    furi_string_free(app->uid_file_path);
     furi_string_free(app->app_folder);
+    if(app->card_file_path != NULL) {
+        furi_string_free(app->card_file_path);
+    }
 
     // App
     //FURI_LOG_D(TAG, "mifare_fuzzer_free() :: App");

+ 1 - 0
apps_source_code/mifare_fuzzer/mifare_fuzzer_custom_events.h

@@ -4,6 +4,7 @@ typedef enum MifareFuzzerEvent {
     MifareFuzzerEventClassic1k = 1,
     MifareFuzzerEventClassic4k,
     MifareFuzzerEventUltralight,
+    MifareFuzzerEventFile,
     MifareFuzzerEventTestValueAttack,
     MifareFuzzerEventRandomValuesAttack,
     MifareFuzzerEventLoadUIDsFromFileAttack,

+ 8 - 2
apps_source_code/mifare_fuzzer/mifare_fuzzer_i.h

@@ -3,6 +3,10 @@
 #include <furi.h>
 #include <furi_hal.h>
 
+#include <lib/nfc/nfc_device.h>
+#include <lib/nfc/protocols/nfc_protocol.h>
+#include "lib/nfc/protocols/mf_classic/mf_classic.h"
+
 #include <gui/gui.h>
 #include <gui/view_dispatcher.h>
 #include <gui/scene_manager.h>
@@ -28,7 +32,8 @@
 #define TAG "MifareFuzzerApp"
 
 #define MIFARE_FUZZER_APP_FOLDER EXT_PATH("mifare_fuzzer")
-#define MIFARE_FUZZER_FILE_EXT ".txt"
+#define MIFARE_FUZZER_UID_FILE_EXT ".txt"
+#define MIFARE_FUZZER_CARD_FILE_EXT ".nfc"
 
 #define MIFARE_FUZZER_TICK_PERIOD 200
 #define MIFARE_FUZZER_DEFAULT_TICKS_BETWEEN_CARDS 10
@@ -69,7 +74,8 @@ struct MifareFuzzerApp {
     MifareCard card;
     MifareFuzzerAttack attack;
     FuriString* app_folder;
-    FuriString* file_path;
+    FuriString* card_file_path;
+    FuriString* uid_file_path;
     FuriString* uid_str;
     Stream* uids_stream;
 };

+ 42 - 7
apps_source_code/mifare_fuzzer/mifare_fuzzer_worker.c

@@ -1,4 +1,5 @@
 #include "mifare_fuzzer_worker.h"
+#include "mifare_fuzzer_i.h"
 
 /// @brief mifare_fuzzer_worker_alloc()
 /// @return
@@ -50,23 +51,31 @@ void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker) {
 /// @return
 int32_t mifare_fuzzer_worker_task(void* context) {
     MifareFuzzerWorker* mifare_fuzzer_worker = context;
+    FURI_LOG_D(TAG, "mifare_fuzzer_worker_task()");
 
     if(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) {
-        const Iso14443_3aData* data =
-            nfc_device_get_data(mifare_fuzzer_worker->nfc_device, NfcProtocolIso14443_3a);
-
-        mifare_fuzzer_worker->nfc_listener =
-            nfc_listener_alloc(mifare_fuzzer_worker->nfc, NfcProtocolIso14443_3a, data);
+        NfcDevice* device = mifare_fuzzer_worker->nfc_device;
+        NfcProtocol protocol = nfc_device_get_protocol(device);
+
+        FURI_LOG_D(
+            TAG,
+            "mifare_fuzzer_worker_task() :: Allocating and starting with %s",
+            nfc_device_get_protocol_name(protocol));
+        mifare_fuzzer_worker->nfc_listener = nfc_listener_alloc(
+            mifare_fuzzer_worker->nfc, protocol, nfc_device_get_data(device, protocol));
         nfc_listener_start(mifare_fuzzer_worker->nfc_listener, NULL, NULL);
 
+        FURI_LOG_D(TAG, "mifare_fuzzer_worker_task() :: Emulating...");
         while(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) {
             furi_delay_ms(50);
         }
 
+        FURI_LOG_D(TAG, "mifare_fuzzer_worker_task() :: Stopping NFC Listener");
         nfc_listener_stop(mifare_fuzzer_worker->nfc_listener);
         nfc_listener_free(mifare_fuzzer_worker->nfc_listener);
     }
 
+    FURI_LOG_D(TAG, "mifare_fuzzer_worker_task() :: Stopping");
     mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop;
 
     return 0;
@@ -82,6 +91,26 @@ bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker)
     return false;
 }
 
+/// @brief mifare_fuzzer_worker_set_nfc_device()
+/// @param mifare_fuzzer_worker
+/// @param nfc_device
+void mifare_fuzzer_worker_set_nfc_device(
+    MifareFuzzerWorker* mifare_fuzzer_worker,
+    NfcDevice* nfc_device) {
+    FURI_LOG_D(
+        TAG,
+        "mifare_fuzzer_worker_set_nfc_device() :: Protocol: %s",
+        nfc_device_get_protocol_name(nfc_device_get_protocol(nfc_device)));
+    mifare_fuzzer_worker->nfc_device = nfc_device;
+}
+
+/// @brief mifare_fuzzer_worker_get_nfc_device()
+/// @param mifare_fuzzer_worker
+/// @return
+NfcDevice* mifare_fuzzer_worker_get_nfc_device(MifareFuzzerWorker* mifare_fuzzer_worker) {
+    return mifare_fuzzer_worker->nfc_device;
+}
+
 /// @brief mifare_fuzzer_worker_set_nfc_data()
 /// @param mifare_fuzzer_worker
 /// @param nfc_data
@@ -94,9 +123,15 @@ void mifare_fuzzer_worker_set_nfc_data(
     memcpy(nfc_14a_data->atqa, nfc_data.atqa, ATQA_LEN);
     nfc_14a_data->sak = nfc_data.sak;
 
+    FURI_LOG_D(
+        TAG,
+        "mifare_fuzzer_worker_set_nfc_data() :: Clearing nfc_device and setting Iso14443_3aData");
     nfc_device_clear(mifare_fuzzer_worker->nfc_device);
     nfc_device_set_data(mifare_fuzzer_worker->nfc_device, NfcProtocolIso14443_3a, nfc_14a_data);
-
+    FURI_LOG_D(
+        TAG,
+        "mifare_fuzzer_worker_set_nfc_data() :: Protocol: %s",
+        nfc_device_get_protocol_name(nfc_device_get_protocol(mifare_fuzzer_worker->nfc_device)));
     iso14443_3a_free(nfc_14a_data);
 }
 
@@ -105,4 +140,4 @@ void mifare_fuzzer_worker_set_nfc_data(
 /// @return
 Iso14443_3aData mifare_fuzzer_worker_get_nfc_data(MifareFuzzerWorker* mifare_fuzzer_worker) {
     return mifare_fuzzer_worker->nfc_data;
-}
+}

+ 9 - 2
apps_source_code/mifare_fuzzer/mifare_fuzzer_worker.h

@@ -5,6 +5,7 @@
 #include <nfc/nfc_device.h>
 #include <nfc/nfc_listener.h>
 #include <nfc/protocols/iso14443_3a/iso14443_3a.h>
+#include <nfc/protocols/iso14443_3a/iso14443_3a_listener.h>
 
 typedef enum MifareFuzzerWorkerState {
     MifareFuzzerWorkerStateEmulate,
@@ -17,9 +18,9 @@ typedef enum MifareFuzzerWorkerState {
 typedef struct MifareFuzzerWorker {
     FuriThread* thread;
     MifareFuzzerWorkerState state;
-    Iso14443_3aData nfc_data;
     NfcListener* nfc_listener;
     NfcDevice* nfc_device;
+    Iso14443_3aData nfc_data;
     Nfc* nfc;
 } MifareFuzzerWorker;
 
@@ -32,7 +33,13 @@ void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker);
 int32_t mifare_fuzzer_worker_task(void* context);
 //
 bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker);
+
+void mifare_fuzzer_worker_set_nfc_device(
+    MifareFuzzerWorker* mifare_fuzzer_worker,
+    NfcDevice* nfc_device);
+NfcDevice* mifare_fuzzer_worker_get_nfc_device(MifareFuzzerWorker* mifare_fuzzer_worker);
+
 void mifare_fuzzer_worker_set_nfc_data(
     MifareFuzzerWorker* mifare_fuzzer_worker,
     Iso14443_3aData nfc_data);
-Iso14443_3aData mifare_fuzzer_worker_get_nfc_data(MifareFuzzerWorker* mifare_fuzzer_worker);
+Iso14443_3aData mifare_fuzzer_worker_get_nfc_data(MifareFuzzerWorker* mifare_fuzzer_worker);

+ 4 - 3
apps_source_code/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c

@@ -106,15 +106,16 @@ bool mifare_fuzzer_scene_attack_on_event(void* context, SceneManagerEvent event)
             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);
+            dialog_file_browser_set_basic_options(
+                &browser_options, MIFARE_FUZZER_UID_FILE_EXT, NULL);
             browser_options.hide_ext = false;
             bool res = dialog_file_browser_show(
-                app->dialogs, app->file_path, app->app_folder, &browser_options);
+                app->dialogs, app->uid_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),
+                    furi_string_get_cstr(app->uid_file_path),
                     FSAM_READ,
                     FSOM_OPEN_EXISTING);
                 if(res) {

+ 52 - 29
apps_source_code/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c

@@ -69,16 +69,36 @@ void mifare_fuzzer_scene_emulator_on_enter(void* context) {
 /// @return
 bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent event) {
     //FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event()");
-    Iso14443_3aData nfc_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");
+            NfcDevice* nfc_device = NULL;
+            const MfClassicData* mf_classic_data = NULL;
+            if(app->card_file_path) {
+                nfc_device = app->worker->nfc_device;
+                const char* path = furi_string_get_cstr(app->card_file_path);
+                if(nfc_device_load(nfc_device, path)) {
+                    mf_classic_data = nfc_device_get_data(nfc_device, NfcProtocolMfClassic);
+                    if(mf_classic_data->type == MfClassicType1k) {
+                        app->card = MifareCardClassic1k;
+                    } else if(mf_classic_data->type == MfClassicType4k) {
+                        app->card = MifareCardClassic4k;
+                    } else if(nfc_device_get_protocol(nfc_device) == NfcProtocolMfUltralight) {
+                        app->card = MifareCardUltralight;
+                    }
+                    mifare_fuzzer_emulator_set_card(emulator, app->card, app->card_file_path);
+                }
+            }
+
+            Iso14443_3aData* nfc_data;
+            if(mf_classic_data) {
+                nfc_data = mf_classic_data->iso14443_3a_data;
+            } else {
+                nfc_data = iso14443_3a_alloc();
+            }
 
             // Stop worker
             mifare_fuzzer_worker_stop(app->worker);
@@ -86,27 +106,27 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
             // Set card type
             // TODO: Move somewhere else, I do not like this to be there
             if(app->card == MifareCardClassic1k) {
-                nfc_data.atqa[0] = 0x04;
-                nfc_data.atqa[1] = 0x00;
-                nfc_data.sak = 0x08;
-                nfc_data.uid_len = 0x04;
+                nfc_data->atqa[0] = 0x04;
+                nfc_data->atqa[1] = 0x00;
+                nfc_data->sak = 0x08;
+                nfc_data->uid_len = 0x04;
             } else if(app->card == MifareCardClassic4k) {
-                nfc_data.atqa[0] = 0x02;
-                nfc_data.atqa[1] = 0x00;
-                nfc_data.sak = 0x18;
-                nfc_data.uid_len = 0x04;
+                nfc_data->atqa[0] = 0x02;
+                nfc_data->atqa[1] = 0x00;
+                nfc_data->sak = 0x18;
+                nfc_data->uid_len = 0x04;
             } else if(app->card == MifareCardUltralight) {
-                nfc_data.atqa[0] = 0x44;
-                nfc_data.atqa[1] = 0x00;
-                nfc_data.sak = 0x00;
-                nfc_data.uid_len = 0x07;
+                nfc_data->atqa[0] = 0x44;
+                nfc_data->atqa[1] = 0x00;
+                nfc_data->sak = 0x00;
+                nfc_data->uid_len = 0x07;
             }
 
             // Set UIDs
             if(app->attack == MifareFuzzerAttackTestValues) {
                 // Load test UIDs
-                for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
-                    nfc_data.uid[i] = id_uid_test[attack_step][i];
+                for(uint8_t i = 0; i < nfc_data->uid_len; i++) {
+                    nfc_data->uid[i] = id_uid_test[attack_step][i];
                 }
                 // Next UIDs on next loop
                 if(attack_step >= 8) {
@@ -123,13 +143,13 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
 
                     // TODO: Manufacture-code must be selectable from a list
                     // use a fixed manufacture-code for now: 0x04 = NXP Semiconductors Germany
-                    nfc_data.uid[0] = 0x04;
-                    for(uint8_t i = 1; i < nfc_data.uid_len; i++) {
-                        nfc_data.uid[i] = (furi_hal_random_get() & 0xFF);
+                    nfc_data->uid[0] = 0x04;
+                    for(uint8_t i = 1; i < nfc_data->uid_len; i++) {
+                        nfc_data->uid[i] = (furi_hal_random_get() & 0xFF);
                     }
                 } else {
-                    for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
-                        nfc_data.uid[i] = (furi_hal_random_get() & 0xFF);
+                    for(uint8_t i = 0; i < nfc_data->uid_len; i++) {
+                        nfc_data->uid[i] = (furi_hal_random_get() & 0xFF);
                     }
                 }
             } else if(app->attack == MifareFuzzerAttackLoadUidsFromFile) {
@@ -157,21 +177,25 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
 
                 // parse string to UID
                 // TODO: a better validation on input?
-                for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
+                for(uint8_t i = 0; i < nfc_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_data.uid[i] = (uint8_t)strtol(temp_str, NULL, 16);
+                        nfc_data->uid[i] = (uint8_t)strtol(temp_str, NULL, 16);
                     } else {
-                        nfc_data.uid[i] = 0x00;
+                        nfc_data->uid[i] = 0x00;
                     }
                 }
             }
 
-            mifare_fuzzer_worker_set_nfc_data(app->worker, nfc_data);
-            mifare_fuzzer_emulator_set_nfc_data(app->emulator_view, nfc_data);
+            mifare_fuzzer_emulator_set_nfc_data(app->emulator_view, *nfc_data);
+            if(nfc_device_parsed) {
+                mifare_fuzzer_worker_set_nfc_device(app->worker, nfc_device);
+            } else {
+                mifare_fuzzer_worker_set_nfc_data(app->worker, *nfc_data);
+            }
 
             // Reset tick_counter
             tick_counter = 0;
@@ -179,7 +203,6 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
 
             // 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

+ 36 - 3
apps_source_code/mifare_fuzzer/scenes/mifare_fuzzer_scene_start.c

@@ -5,6 +5,7 @@ enum SubmenuIndex {
     SubmenuIndexClassic1k,
     SubmenuIndexClassic4k,
     SubmenuIndexUltralight,
+    SubmenuIndexFile,
 };
 
 /// @brief mifare_fuzzer_scene_start_submenu_callback()
@@ -24,6 +25,9 @@ void mifare_fuzzer_scene_start_submenu_callback(void* context, uint32_t index) {
     case SubmenuIndexUltralight:
         custom_event = MifareFuzzerEventUltralight;
         break;
+    case SubmenuIndexFile:
+        custom_event = MifareFuzzerEventFile;
+        break;
     default:
         return;
     }
@@ -57,6 +61,12 @@ void mifare_fuzzer_scene_start_on_enter(void* context) {
         SubmenuIndexUltralight,
         mifare_fuzzer_scene_start_submenu_callback,
         app);
+    submenu_add_item(
+        submenu_card,
+        "From file",
+        SubmenuIndexFile,
+        mifare_fuzzer_scene_start_submenu_callback,
+        app);
 
     // set selected menu
     submenu_set_selected_item(
@@ -69,6 +79,9 @@ void mifare_fuzzer_scene_start_on_enter(void* context) {
 /// @param context
 /// @param event
 /// @return
+/// @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;
@@ -76,13 +89,14 @@ bool mifare_fuzzer_scene_start_on_event(void* context, SceneManagerEvent event)
 
     if(event.type == SceneManagerEventTypeCustom) {
         //FURI_LOG_D(TAG, "mifare_fuzzer_scene_start_on_event() :: event.event = %ld", event.event);
+        app->card_file_path = NULL;
         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);
+            mifare_fuzzer_emulator_set_card(app->emulator_view, app->card, NULL);
             // open next scene
             scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack);
             consumed = true;
@@ -92,7 +106,7 @@ bool mifare_fuzzer_scene_start_on_event(void* context, SceneManagerEvent event)
                 app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexClassic4k);
             // set emulator card
             app->card = MifareCardClassic4k;
-            mifare_fuzzer_emulator_set_card(app->emulator_view, app->card);
+            mifare_fuzzer_emulator_set_card(app->emulator_view, app->card, NULL);
             // open next scene
             scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack);
             consumed = true;
@@ -102,10 +116,29 @@ bool mifare_fuzzer_scene_start_on_event(void* context, SceneManagerEvent event)
                 app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexUltralight);
             // set emulator card
             app->card = MifareCardUltralight;
-            mifare_fuzzer_emulator_set_card(app->emulator_view, app->card);
+            mifare_fuzzer_emulator_set_card(app->emulator_view, app->card, NULL);
             // open next scene
             scene_manager_next_scene(app->scene_manager, MifareFuzzerSceneAttack);
             consumed = true;
+        } else if(event.event == MifareFuzzerEventFile) {
+            // save selected item
+            scene_manager_set_scene_state(
+                app->scene_manager, MifareFuzzerSceneStart, SubmenuIndexFile);
+            // Don't set emulator card (yet), read file instead
+            DialogsFileBrowserOptions browser_options;
+            FuriString* initial_path = furi_string_alloc_set("/ext/nfc");
+            dialog_file_browser_set_basic_options(
+                &browser_options, MIFARE_FUZZER_CARD_FILE_EXT, NULL);
+            browser_options.hide_ext = false;
+            app->card_file_path = furi_string_alloc();
+            bool wasFileSelected = dialog_file_browser_show(
+                app->dialogs, app->card_file_path, initial_path, &browser_options);
+            furi_string_free(initial_path);
+            if(wasFileSelected) {
+                // 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");

+ 21 - 13
apps_source_code/mifare_fuzzer/views/mifare_fuzzer_emulator.c

@@ -60,8 +60,8 @@ static void mifare_fuzzer_emulator_draw_callback(Canvas* canvas, void* _model) {
     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));
+    canvas_draw_str(canvas, 100, 33, "t:");
+    canvas_draw_str(canvas, 110, 33, furi_string_get_cstr(furi_string));
     // Attack
     canvas_draw_str(canvas, 4, 33, "a:");
     canvas_draw_str(canvas, 15, 33, model->attack_dsc);
@@ -202,7 +202,8 @@ View* mifare_fuzzer_emulator_get_view(MifareFuzzerEmulator* mifare_fuzzer_emulat
 /// @param mifare_card
 void mifare_fuzzer_emulator_set_card(
     MifareFuzzerEmulator* mifare_fuzzer_emulator,
-    MifareCard mifare_card) {
+    MifareCard mifare_card,
+    FuriString* name) {
     furi_assert(mifare_fuzzer_emulator);
     furi_assert(mifare_card);
 
@@ -211,16 +212,23 @@ void mifare_fuzzer_emulator_set_card(
         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;
+            if(name == NULL) {
+                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;
+                }
+            } else {
+                FuriString* card_name = furi_string_alloc_set(name);
+                size_t filename_start = furi_string_search_rchar(card_name, '/') + 1;
+                furi_string_right(card_name, filename_start);
+                model->mifare_card_dsc = furi_string_get_cstr(card_name);
             }
         },
         true);

+ 3 - 1
apps_source_code/mifare_fuzzer/views/mifare_fuzzer_emulator.h

@@ -4,6 +4,7 @@
 #include <furi_hal.h>
 #include <gui/view.h>
 #include <gui/elements.h>
+#include <lib/nfc/nfc_device.h>
 
 #include "lib/nfc/protocols/iso14443_3a/iso14443_3a.h"
 
@@ -49,7 +50,8 @@ View* mifare_fuzzer_emulator_get_view(MifareFuzzerEmulator* context);
 
 void mifare_fuzzer_emulator_set_card(
     MifareFuzzerEmulator* mifare_fuzzer_emulator,
-    MifareCard mifare_card);
+    MifareCard mifare_card,
+    FuriString* name);
 void mifare_fuzzer_emulator_set_attack(
     MifareFuzzerEmulator* mifare_fuzzer_emulator,
     MifareFuzzerAttack mifare_attack);