mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-25 01:38:11 -07:00
Add mifare fuzzer
This commit is contained in:
@@ -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",
|
||||
)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 139 B |
+157
@@ -0,0 +1,157 @@
|
||||
#include "mifare_fuzzer_i.h"
|
||||
|
||||
/// @brief mifare_fuzzer_custom_event_callback()
|
||||
/// @param context
|
||||
/// @param event
|
||||
/// @return
|
||||
static bool mifare_fuzzer_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
MifareFuzzerApp* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct MifareFuzzerApp MifareFuzzerApp;
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum MifareFuzzerEvent {
|
||||
MifareFuzzerEventClassic1k = 1,
|
||||
MifareFuzzerEventClassic4k,
|
||||
MifareFuzzerEventUltralight,
|
||||
MifareFuzzerEventTestValueAttack,
|
||||
MifareFuzzerEventRandomValuesAttack,
|
||||
MifareFuzzerEventLoadUIDsFromFileAttack,
|
||||
MifareFuzzerEventStartAttack,
|
||||
MifareFuzzerEventStopAttack,
|
||||
MifareFuzzerEventIncrementTicks,
|
||||
MifareFuzzerEventDecrementTicks,
|
||||
} MifareFuzzerEvent;
|
||||
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#include <input/input.h>
|
||||
|
||||
#include <toolbox/stream/stream.h>
|
||||
//#include <toolbox/stream/string_stream.h>
|
||||
//#include <toolbox/stream/file_stream.h>
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
|
||||
#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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
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);
|
||||
@@ -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,
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// 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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
ADD_SCENE(mifare_fuzzer, start, Start)
|
||||
ADD_SCENE(mifare_fuzzer, attack, Attack)
|
||||
ADD_SCENE(mifare_fuzzer, emulator, Emulator)
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
#include "../mifare_fuzzer_custom_events.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
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);
|
||||
Reference in New Issue
Block a user