Skip to content

Commit fb02471

Browse files
committed
Add card emulation logic
1 parent 54f8154 commit fb02471

11 files changed

+183
-62
lines changed

apps_source_code/mifare_fuzzer/application.fam

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ App(
44
apptype=FlipperAppType.EXTERNAL,
55
entry_point="mifare_fuzzer_app",
66
requires=[
7+
"nfc",
78
"storage",
89
"gui",
910
],

apps_source_code/mifare_fuzzer/mifare_fuzzer.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ MifareFuzzerApp* mifare_fuzzer_alloc() {
8080

8181
// furi strings
8282
app->uid_str = furi_string_alloc();
83-
app->file_path = furi_string_alloc();
83+
app->uid_file_path = furi_string_alloc();
84+
app->card_file_path = furi_string_alloc();
8485
app->app_folder = furi_string_alloc_set(MIFARE_FUZZER_APP_FOLDER);
8586

8687
return app;
@@ -129,8 +130,11 @@ void mifare_fuzzer_free(MifareFuzzerApp* app) {
129130

130131
// furi strings
131132
furi_string_free(app->uid_str);
132-
furi_string_free(app->file_path);
133+
furi_string_free(app->uid_file_path);
133134
furi_string_free(app->app_folder);
135+
if(app->card_file_path != NULL) {
136+
furi_string_free(app->card_file_path);
137+
}
134138

135139
// App
136140
//FURI_LOG_D(TAG, "mifare_fuzzer_free() :: App");

apps_source_code/mifare_fuzzer/mifare_fuzzer_custom_events.h

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ typedef enum MifareFuzzerEvent {
44
MifareFuzzerEventClassic1k = 1,
55
MifareFuzzerEventClassic4k,
66
MifareFuzzerEventUltralight,
7+
MifareFuzzerEventFile,
78
MifareFuzzerEventTestValueAttack,
89
MifareFuzzerEventRandomValuesAttack,
910
MifareFuzzerEventLoadUIDsFromFileAttack,

apps_source_code/mifare_fuzzer/mifare_fuzzer_i.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
#include <furi.h>
44
#include <furi_hal.h>
55

6+
#include <lib/nfc/nfc_device.h>
7+
#include <lib/nfc/protocols/nfc_protocol.h>
8+
#include "lib/nfc/protocols/mf_classic/mf_classic.h"
9+
610
#include <gui/gui.h>
711
#include <gui/view_dispatcher.h>
812
#include <gui/scene_manager.h>
@@ -28,7 +32,8 @@
2832
#define TAG "MifareFuzzerApp"
2933

3034
#define MIFARE_FUZZER_APP_FOLDER EXT_PATH("mifare_fuzzer")
31-
#define MIFARE_FUZZER_FILE_EXT ".txt"
35+
#define MIFARE_FUZZER_UID_FILE_EXT ".txt"
36+
#define MIFARE_FUZZER_CARD_FILE_EXT ".nfc"
3237

3338
#define MIFARE_FUZZER_TICK_PERIOD 200
3439
#define MIFARE_FUZZER_DEFAULT_TICKS_BETWEEN_CARDS 10
@@ -69,7 +74,8 @@ struct MifareFuzzerApp {
6974
MifareCard card;
7075
MifareFuzzerAttack attack;
7176
FuriString* app_folder;
72-
FuriString* file_path;
77+
FuriString* card_file_path;
78+
FuriString* uid_file_path;
7379
FuriString* uid_str;
7480
Stream* uids_stream;
7581
};

apps_source_code/mifare_fuzzer/mifare_fuzzer_worker.c

+42-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "mifare_fuzzer_worker.h"
2+
#include "mifare_fuzzer_i.h"
23

34
/// @brief mifare_fuzzer_worker_alloc()
45
/// @return
@@ -50,23 +51,31 @@ void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker) {
5051
/// @return
5152
int32_t mifare_fuzzer_worker_task(void* context) {
5253
MifareFuzzerWorker* mifare_fuzzer_worker = context;
54+
FURI_LOG_D(TAG, "mifare_fuzzer_worker_task()");
5355

5456
if(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) {
55-
const Iso14443_3aData* data =
56-
nfc_device_get_data(mifare_fuzzer_worker->nfc_device, NfcProtocolIso14443_3a);
57-
58-
mifare_fuzzer_worker->nfc_listener =
59-
nfc_listener_alloc(mifare_fuzzer_worker->nfc, NfcProtocolIso14443_3a, data);
57+
NfcDevice* device = mifare_fuzzer_worker->nfc_device;
58+
NfcProtocol protocol = nfc_device_get_protocol(device);
59+
60+
FURI_LOG_D(
61+
TAG,
62+
"mifare_fuzzer_worker_task() :: Allocating and starting with %s",
63+
nfc_device_get_protocol_name(protocol));
64+
mifare_fuzzer_worker->nfc_listener = nfc_listener_alloc(
65+
mifare_fuzzer_worker->nfc, protocol, nfc_device_get_data(device, protocol));
6066
nfc_listener_start(mifare_fuzzer_worker->nfc_listener, NULL, NULL);
6167

68+
FURI_LOG_D(TAG, "mifare_fuzzer_worker_task() :: Emulating...");
6269
while(mifare_fuzzer_worker->state == MifareFuzzerWorkerStateEmulate) {
6370
furi_delay_ms(50);
6471
}
6572

73+
FURI_LOG_D(TAG, "mifare_fuzzer_worker_task() :: Stopping NFC Listener");
6674
nfc_listener_stop(mifare_fuzzer_worker->nfc_listener);
6775
nfc_listener_free(mifare_fuzzer_worker->nfc_listener);
6876
}
6977

78+
FURI_LOG_D(TAG, "mifare_fuzzer_worker_task() :: Stopping");
7079
mifare_fuzzer_worker->state = MifareFuzzerWorkerStateStop;
7180

7281
return 0;
@@ -82,6 +91,26 @@ bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker)
8291
return false;
8392
}
8493

94+
/// @brief mifare_fuzzer_worker_set_nfc_device()
95+
/// @param mifare_fuzzer_worker
96+
/// @param nfc_device
97+
void mifare_fuzzer_worker_set_nfc_device(
98+
MifareFuzzerWorker* mifare_fuzzer_worker,
99+
NfcDevice* nfc_device) {
100+
FURI_LOG_D(
101+
TAG,
102+
"mifare_fuzzer_worker_set_nfc_device() :: Protocol: %s",
103+
nfc_device_get_protocol_name(nfc_device_get_protocol(nfc_device)));
104+
mifare_fuzzer_worker->nfc_device = nfc_device;
105+
}
106+
107+
/// @brief mifare_fuzzer_worker_get_nfc_device()
108+
/// @param mifare_fuzzer_worker
109+
/// @return
110+
NfcDevice* mifare_fuzzer_worker_get_nfc_device(MifareFuzzerWorker* mifare_fuzzer_worker) {
111+
return mifare_fuzzer_worker->nfc_device;
112+
}
113+
85114
/// @brief mifare_fuzzer_worker_set_nfc_data()
86115
/// @param mifare_fuzzer_worker
87116
/// @param nfc_data
@@ -94,9 +123,15 @@ void mifare_fuzzer_worker_set_nfc_data(
94123
memcpy(nfc_14a_data->atqa, nfc_data.atqa, ATQA_LEN);
95124
nfc_14a_data->sak = nfc_data.sak;
96125

126+
FURI_LOG_D(
127+
TAG,
128+
"mifare_fuzzer_worker_set_nfc_data() :: Clearing nfc_device and setting Iso14443_3aData");
97129
nfc_device_clear(mifare_fuzzer_worker->nfc_device);
98130
nfc_device_set_data(mifare_fuzzer_worker->nfc_device, NfcProtocolIso14443_3a, nfc_14a_data);
99-
131+
FURI_LOG_D(
132+
TAG,
133+
"mifare_fuzzer_worker_set_nfc_data() :: Protocol: %s",
134+
nfc_device_get_protocol_name(nfc_device_get_protocol(mifare_fuzzer_worker->nfc_device)));
100135
iso14443_3a_free(nfc_14a_data);
101136
}
102137

@@ -105,4 +140,4 @@ void mifare_fuzzer_worker_set_nfc_data(
105140
/// @return
106141
Iso14443_3aData mifare_fuzzer_worker_get_nfc_data(MifareFuzzerWorker* mifare_fuzzer_worker) {
107142
return mifare_fuzzer_worker->nfc_data;
108-
}
143+
}

apps_source_code/mifare_fuzzer/mifare_fuzzer_worker.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <nfc/nfc_device.h>
66
#include <nfc/nfc_listener.h>
77
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
8+
#include <nfc/protocols/iso14443_3a/iso14443_3a_listener.h>
89

910
typedef enum MifareFuzzerWorkerState {
1011
MifareFuzzerWorkerStateEmulate,
@@ -17,9 +18,9 @@ typedef enum MifareFuzzerWorkerState {
1718
typedef struct MifareFuzzerWorker {
1819
FuriThread* thread;
1920
MifareFuzzerWorkerState state;
20-
Iso14443_3aData nfc_data;
2121
NfcListener* nfc_listener;
2222
NfcDevice* nfc_device;
23+
Iso14443_3aData nfc_data;
2324
Nfc* nfc;
2425
} MifareFuzzerWorker;
2526

@@ -32,7 +33,13 @@ void mifare_fuzzer_worker_start(MifareFuzzerWorker* mifare_fuzzer_worker);
3233
int32_t mifare_fuzzer_worker_task(void* context);
3334
//
3435
bool mifare_fuzzer_worker_is_emulating(MifareFuzzerWorker* mifare_fuzzer_worker);
36+
37+
void mifare_fuzzer_worker_set_nfc_device(
38+
MifareFuzzerWorker* mifare_fuzzer_worker,
39+
NfcDevice* nfc_device);
40+
NfcDevice* mifare_fuzzer_worker_get_nfc_device(MifareFuzzerWorker* mifare_fuzzer_worker);
41+
3542
void mifare_fuzzer_worker_set_nfc_data(
3643
MifareFuzzerWorker* mifare_fuzzer_worker,
3744
Iso14443_3aData nfc_data);
38-
Iso14443_3aData mifare_fuzzer_worker_get_nfc_data(MifareFuzzerWorker* mifare_fuzzer_worker);
45+
Iso14443_3aData mifare_fuzzer_worker_get_nfc_data(MifareFuzzerWorker* mifare_fuzzer_worker);

apps_source_code/mifare_fuzzer/scenes/mifare_fuzzer_scene_attack.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,16 @@ bool mifare_fuzzer_scene_attack_on_event(void* context, SceneManagerEvent event)
106106
mifare_fuzzer_emulator_set_attack(app->emulator_view, app->attack);
107107
// open dialog file
108108
DialogsFileBrowserOptions browser_options;
109-
dialog_file_browser_set_basic_options(&browser_options, MIFARE_FUZZER_FILE_EXT, NULL);
109+
dialog_file_browser_set_basic_options(
110+
&browser_options, MIFARE_FUZZER_UID_FILE_EXT, NULL);
110111
browser_options.hide_ext = false;
111112
bool res = dialog_file_browser_show(
112-
app->dialogs, app->file_path, app->app_folder, &browser_options);
113+
app->dialogs, app->uid_file_path, app->app_folder, &browser_options);
113114
if(res) {
114115
app->uids_stream = buffered_file_stream_alloc(app->storage);
115116
res = buffered_file_stream_open(
116117
app->uids_stream,
117-
furi_string_get_cstr(app->file_path),
118+
furi_string_get_cstr(app->uid_file_path),
118119
FSAM_READ,
119120
FSOM_OPEN_EXISTING);
120121
if(res) {

apps_source_code/mifare_fuzzer/scenes/mifare_fuzzer_scene_emulator.c

+52-29
Original file line numberDiff line numberDiff line change
@@ -69,44 +69,64 @@ void mifare_fuzzer_scene_emulator_on_enter(void* context) {
6969
/// @return
7070
bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent event) {
7171
//FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event()");
72-
Iso14443_3aData nfc_data;
73-
7472
MifareFuzzerApp* app = context;
7573
MifareFuzzerEmulator* emulator = app->emulator_view;
76-
7774
bool consumed = false;
7875

7976
if(event.type == SceneManagerEventTypeCustom) {
8077
if(event.event == MifareFuzzerEventStartAttack) {
81-
//FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event() :: MifareFuzzerEventStartAttack");
78+
NfcDevice* nfc_device = NULL;
79+
const MfClassicData* mf_classic_data = NULL;
80+
if(app->card_file_path) {
81+
nfc_device = app->worker->nfc_device;
82+
const char* path = furi_string_get_cstr(app->card_file_path);
83+
if(nfc_device_load(nfc_device, path)) {
84+
mf_classic_data = nfc_device_get_data(nfc_device, NfcProtocolMfClassic);
85+
if(mf_classic_data->type == MfClassicType1k) {
86+
app->card = MifareCardClassic1k;
87+
} else if(mf_classic_data->type == MfClassicType4k) {
88+
app->card = MifareCardClassic4k;
89+
} else if(nfc_device_get_protocol(nfc_device) == NfcProtocolMfUltralight) {
90+
app->card = MifareCardUltralight;
91+
}
92+
mifare_fuzzer_emulator_set_card(emulator, app->card, app->card_file_path);
93+
}
94+
}
95+
96+
Iso14443_3aData* nfc_data;
97+
if(mf_classic_data) {
98+
nfc_data = mf_classic_data->iso14443_3a_data;
99+
} else {
100+
nfc_data = iso14443_3a_alloc();
101+
}
82102

83103
// Stop worker
84104
mifare_fuzzer_worker_stop(app->worker);
85105

86106
// Set card type
87107
// TODO: Move somewhere else, I do not like this to be there
88108
if(app->card == MifareCardClassic1k) {
89-
nfc_data.atqa[0] = 0x04;
90-
nfc_data.atqa[1] = 0x00;
91-
nfc_data.sak = 0x08;
92-
nfc_data.uid_len = 0x04;
109+
nfc_data->atqa[0] = 0x04;
110+
nfc_data->atqa[1] = 0x00;
111+
nfc_data->sak = 0x08;
112+
nfc_data->uid_len = 0x04;
93113
} else if(app->card == MifareCardClassic4k) {
94-
nfc_data.atqa[0] = 0x02;
95-
nfc_data.atqa[1] = 0x00;
96-
nfc_data.sak = 0x18;
97-
nfc_data.uid_len = 0x04;
114+
nfc_data->atqa[0] = 0x02;
115+
nfc_data->atqa[1] = 0x00;
116+
nfc_data->sak = 0x18;
117+
nfc_data->uid_len = 0x04;
98118
} else if(app->card == MifareCardUltralight) {
99-
nfc_data.atqa[0] = 0x44;
100-
nfc_data.atqa[1] = 0x00;
101-
nfc_data.sak = 0x00;
102-
nfc_data.uid_len = 0x07;
119+
nfc_data->atqa[0] = 0x44;
120+
nfc_data->atqa[1] = 0x00;
121+
nfc_data->sak = 0x00;
122+
nfc_data->uid_len = 0x07;
103123
}
104124

105125
// Set UIDs
106126
if(app->attack == MifareFuzzerAttackTestValues) {
107127
// Load test UIDs
108-
for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
109-
nfc_data.uid[i] = id_uid_test[attack_step][i];
128+
for(uint8_t i = 0; i < nfc_data->uid_len; i++) {
129+
nfc_data->uid[i] = id_uid_test[attack_step][i];
110130
}
111131
// Next UIDs on next loop
112132
if(attack_step >= 8) {
@@ -123,13 +143,13 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
123143

124144
// TODO: Manufacture-code must be selectable from a list
125145
// use a fixed manufacture-code for now: 0x04 = NXP Semiconductors Germany
126-
nfc_data.uid[0] = 0x04;
127-
for(uint8_t i = 1; i < nfc_data.uid_len; i++) {
128-
nfc_data.uid[i] = (furi_hal_random_get() & 0xFF);
146+
nfc_data->uid[0] = 0x04;
147+
for(uint8_t i = 1; i < nfc_data->uid_len; i++) {
148+
nfc_data->uid[i] = (furi_hal_random_get() & 0xFF);
129149
}
130150
} else {
131-
for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
132-
nfc_data.uid[i] = (furi_hal_random_get() & 0xFF);
151+
for(uint8_t i = 0; i < nfc_data->uid_len; i++) {
152+
nfc_data->uid[i] = (furi_hal_random_get() & 0xFF);
133153
}
134154
}
135155
} else if(app->attack == MifareFuzzerAttackLoadUidsFromFile) {
@@ -157,29 +177,32 @@ bool mifare_fuzzer_scene_emulator_on_event(void* context, SceneManagerEvent even
157177

158178
// parse string to UID
159179
// TODO: a better validation on input?
160-
for(uint8_t i = 0; i < nfc_data.uid_len; i++) {
180+
for(uint8_t i = 0; i < nfc_data->uid_len; i++) {
161181
if(i <= ((furi_string_size(app->uid_str) - 1) / 2)) {
162182
char temp_str[3];
163183
temp_str[0] = furi_string_get_cstr(app->uid_str)[i * 2];
164184
temp_str[1] = furi_string_get_cstr(app->uid_str)[i * 2 + 1];
165185
temp_str[2] = '\0';
166-
nfc_data.uid[i] = (uint8_t)strtol(temp_str, NULL, 16);
186+
nfc_data->uid[i] = (uint8_t)strtol(temp_str, NULL, 16);
167187
} else {
168-
nfc_data.uid[i] = 0x00;
188+
nfc_data->uid[i] = 0x00;
169189
}
170190
}
171191
}
172192

173-
mifare_fuzzer_worker_set_nfc_data(app->worker, nfc_data);
174-
mifare_fuzzer_emulator_set_nfc_data(app->emulator_view, nfc_data);
193+
mifare_fuzzer_emulator_set_nfc_data(app->emulator_view, *nfc_data);
194+
if(nfc_device_parsed) {
195+
mifare_fuzzer_worker_set_nfc_device(app->worker, nfc_device);
196+
} else {
197+
mifare_fuzzer_worker_set_nfc_data(app->worker, *nfc_data);
198+
}
175199

176200
// Reset tick_counter
177201
tick_counter = 0;
178202
mifare_fuzzer_emulator_set_tick_num(app->emulator_view, tick_counter);
179203

180204
// Start worker
181205
mifare_fuzzer_worker_start(app->worker);
182-
183206
} else if(event.event == MifareFuzzerEventStopAttack) {
184207
//FURI_LOG_D(TAG, "mifare_fuzzer_scene_emulator_on_event() :: MifareFuzzerEventStopAttack");
185208
// Stop worker

0 commit comments

Comments
 (0)