Skip to content

Commit

Permalink
Add card emulation logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Kondenko committed Jan 8, 2024
1 parent 54f8154 commit fb02471
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 62 deletions.
1 change: 1 addition & 0 deletions apps_source_code/mifare_fuzzer/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ App(
apptype=FlipperAppType.EXTERNAL,
entry_point="mifare_fuzzer_app",
requires=[
"nfc",
"storage",
"gui",
],
Expand Down
8 changes: 6 additions & 2 deletions apps_source_code/mifare_fuzzer/mifare_fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ typedef enum MifareFuzzerEvent {
MifareFuzzerEventClassic1k = 1,
MifareFuzzerEventClassic4k,
MifareFuzzerEventUltralight,
MifareFuzzerEventFile,
MifareFuzzerEventTestValueAttack,
MifareFuzzerEventRandomValuesAttack,
MifareFuzzerEventLoadUIDsFromFileAttack,
Expand Down
10 changes: 8 additions & 2 deletions apps_source_code/mifare_fuzzer/mifare_fuzzer_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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
Expand Down Expand Up @@ -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;
};
49 changes: 42 additions & 7 deletions apps_source_code/mifare_fuzzer/mifare_fuzzer_worker.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "mifare_fuzzer_worker.h"
#include "mifare_fuzzer_i.h"

/// @brief mifare_fuzzer_worker_alloc()
/// @return
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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);
}

Expand All @@ -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;
}
}
11 changes: 9 additions & 2 deletions apps_source_code/mifare_fuzzer/mifare_fuzzer_worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;

Expand All @@ -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);
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,44 +69,64 @@ 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);

// 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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -157,29 +177,32 @@ 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;
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
Expand Down
Loading

0 comments on commit fb02471

Please sign in to comment.