mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-01 10:04:03 +03:00
commit
f99c1a8c0a
@ -1,4 +0,0 @@
|
|||||||
# FlipFrid
|
|
||||||
|
|
||||||
A simple implementation of ZigFrid on Flipper zero (+bonus)
|
|
||||||
(https://z4ziggy.wordpress.com/2017/07/21/zigfrid-a-passive-rfid-fuzzer/)
|
|
@ -1,6 +1,6 @@
|
|||||||
App(
|
App(
|
||||||
appid="flipfrid",
|
appid="flipfrid",
|
||||||
name="RFID Fuzzer",
|
name="Rfid Fuzzer",
|
||||||
apptype=FlipperAppType.PLUGIN,
|
apptype=FlipperAppType.PLUGIN,
|
||||||
entry_point="flipfrid_start",
|
entry_point="flipfrid_start",
|
||||||
cdefines=["APP_FLIP_FRID"],
|
cdefines=["APP_FLIP_FRID"],
|
||||||
|
@ -1,125 +1,34 @@
|
|||||||
#include <furi.h>
|
|
||||||
#include <gui/gui.h>
|
|
||||||
#include <input/input.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <lib/lfrfid/lfrfid_worker.h>
|
|
||||||
#include "raw_em4100.h"
|
|
||||||
#include <lfrfid/protocols/lfrfid_protocols.h>
|
|
||||||
|
|
||||||
#include "flipfrid.h"
|
#include "flipfrid.h"
|
||||||
|
|
||||||
#define NUMBER_OF_ATTACKS 3
|
#include "scene/flipfrid_scene_entrypoint.h"
|
||||||
#define TIME_BETWEEN_CARDS \
|
#include "scene/flipfrid_scene_load_file.h"
|
||||||
5 // Emulate 2 cards per second : (5 * (configTICK_RATE_HZ_RAW/10)) == (5*(1000/10)) == (5*100) == (500)ms
|
#include "scene/flipfrid_scene_select_field.h"
|
||||||
#define TAG "FLIPFRID"
|
#include "scene/flipfrid_scene_run_attack.h"
|
||||||
|
|
||||||
uint8_t id_list[16][5] = {
|
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
|
||||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
|
||||||
{0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
|
|
||||||
{0x22, 0x22, 0x22, 0x22, 0x22}, // Only 22
|
|
||||||
{0x33, 0x33, 0x33, 0x33, 0x33}, // Only 33
|
|
||||||
{0x44, 0x44, 0x44, 0x44, 0x44}, // Only 44
|
|
||||||
{0x55, 0x55, 0x55, 0x55, 0x55}, // Only 55
|
|
||||||
{0x66, 0x66, 0x66, 0x66, 0x66}, // Only 66
|
|
||||||
{0x77, 0x77, 0x77, 0x77, 0x77}, // Only 77
|
|
||||||
{0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
|
|
||||||
{0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
|
|
||||||
{0x12, 0x34, 0x56, 0x78, 0x9A}, // Incremental UID
|
|
||||||
{0x04, 0xd0, 0x9b, 0x0d, 0x6a}, // From arha
|
|
||||||
{0x34, 0x00, 0x29, 0x3d, 0x9e}, // From arha
|
|
||||||
{0x04, 0xdf, 0x00, 0x00, 0x01}, // From arha
|
|
||||||
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
DefaultKeys,
|
|
||||||
BruteForceCustomerId,
|
|
||||||
BadCrc,
|
|
||||||
} AttackType;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
EventTypeTick,
|
|
||||||
EventTypeKey,
|
|
||||||
} EventType;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
EventType evt_type;
|
|
||||||
InputKey key;
|
|
||||||
InputType input_type;
|
|
||||||
} FlipFridEvent;
|
|
||||||
|
|
||||||
// STRUCTS
|
|
||||||
typedef struct {
|
|
||||||
bool emitting;
|
|
||||||
AttackType current_attack_type;
|
|
||||||
uint8_t* current_uid;
|
|
||||||
uint8_t meta_data;
|
|
||||||
NotificationApp* notify;
|
|
||||||
} FlipFridState;
|
|
||||||
|
|
||||||
static void flipfrid_draw_callback(Canvas* const canvas, void* ctx) {
|
static void flipfrid_draw_callback(Canvas* const canvas, void* ctx) {
|
||||||
const FlipFridState* flipfrid_state = (FlipFridState*)acquire_mutex((ValueMutex*)ctx, 100);
|
FlipFridState* flipfrid_state = (FlipFridState*)acquire_mutex((ValueMutex*)ctx, 100);
|
||||||
|
|
||||||
if(flipfrid_state == NULL) {
|
if(flipfrid_state == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas_clear(canvas);
|
// Draw correct Canvas
|
||||||
canvas_set_color(canvas, ColorBlack);
|
switch(flipfrid_state->current_scene) {
|
||||||
|
case NoneScene:
|
||||||
// Frame
|
case SceneEntryPoint:
|
||||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
flipfrid_scene_entrypoint_on_draw(canvas, flipfrid_state);
|
||||||
|
|
||||||
// Title
|
|
||||||
canvas_set_font(canvas, FontPrimary);
|
|
||||||
canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignTop, "Flip/Frid");
|
|
||||||
|
|
||||||
// Badge Type
|
|
||||||
char uid[16];
|
|
||||||
char badge_type[21];
|
|
||||||
switch(flipfrid_state->current_attack_type) {
|
|
||||||
case DefaultKeys:
|
|
||||||
strcpy(badge_type, " Default Values >");
|
|
||||||
break;
|
break;
|
||||||
case BruteForceCustomerId:
|
case SceneSelectFile:
|
||||||
strcpy(badge_type, "< BF Customer ID >");
|
flipfrid_scene_load_file_on_draw(canvas, flipfrid_state);
|
||||||
break;
|
break;
|
||||||
case BadCrc:
|
case SceneSelectField:
|
||||||
strcpy(badge_type, "< Bad CRC ");
|
flipfrid_scene_select_field_on_draw(canvas, flipfrid_state);
|
||||||
break;
|
break;
|
||||||
default:
|
case SceneAttack:
|
||||||
|
flipfrid_scene_run_attack_on_draw(canvas, flipfrid_state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flipfrid_state->current_attack_type == BruteForceCustomerId) {
|
|
||||||
snprintf(uid, sizeof(uid), " ID : %2X ", flipfrid_state->current_uid[0]);
|
|
||||||
} else if(flipfrid_state->current_attack_type == BadCrc) {
|
|
||||||
snprintf(uid, sizeof(uid), "Sending packets");
|
|
||||||
} else {
|
|
||||||
snprintf(
|
|
||||||
uid,
|
|
||||||
sizeof(uid),
|
|
||||||
"%2X:%2X:%2X:%2X:%2X",
|
|
||||||
flipfrid_state->current_uid[0],
|
|
||||||
flipfrid_state->current_uid[1],
|
|
||||||
flipfrid_state->current_uid[2],
|
|
||||||
flipfrid_state->current_uid[3],
|
|
||||||
flipfrid_state->current_uid[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Badge infos
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
|
||||||
canvas_draw_str_aligned(canvas, 64, 28, AlignCenter, AlignCenter, badge_type);
|
|
||||||
|
|
||||||
if(flipfrid_state->emitting) {
|
|
||||||
canvas_draw_str_aligned(canvas, 64, 42, AlignCenter, AlignCenter, uid);
|
|
||||||
} else {
|
|
||||||
canvas_draw_str_aligned(
|
|
||||||
canvas, 64, 42, AlignCenter, AlignCenter, "Press OK to start/stop");
|
|
||||||
}
|
|
||||||
|
|
||||||
release_mutex((ValueMutex*)ctx, flipfrid_state);
|
release_mutex((ValueMutex*)ctx, flipfrid_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,173 +42,177 @@ void flipfrid_input_callback(InputEvent* input_event, FuriMessageQueue* event_qu
|
|||||||
|
|
||||||
static void flipfrid_timer_callback(FuriMessageQueue* event_queue) {
|
static void flipfrid_timer_callback(FuriMessageQueue* event_queue) {
|
||||||
furi_assert(event_queue);
|
furi_assert(event_queue);
|
||||||
|
|
||||||
FlipFridEvent event = {
|
FlipFridEvent event = {
|
||||||
.evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease};
|
.evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease};
|
||||||
furi_message_queue_put(event_queue, &event, 25);
|
furi_message_queue_put(event_queue, &event, 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlipFridState* flipfrid_alloc() {
|
||||||
|
FlipFridState* flipfrid = malloc(sizeof(FlipFridState));
|
||||||
|
string_init(flipfrid->file_path);
|
||||||
|
string_init(flipfrid->file_path_tmp);
|
||||||
|
string_init(flipfrid->notification_msg);
|
||||||
|
string_init(flipfrid->attack_name);
|
||||||
|
|
||||||
|
flipfrid->previous_scene = NoneScene;
|
||||||
|
flipfrid->current_scene = SceneEntryPoint;
|
||||||
|
flipfrid->is_running = true;
|
||||||
|
flipfrid->is_attacking = false;
|
||||||
|
flipfrid->key_index = 0;
|
||||||
|
flipfrid->menu_index = 0;
|
||||||
|
|
||||||
|
flipfrid->attack = FlipFridAttackDefaultValues;
|
||||||
|
flipfrid->notify = furi_record_open(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
|
flipfrid->data[0] = 0x00;
|
||||||
|
flipfrid->data[1] = 0x00;
|
||||||
|
flipfrid->data[2] = 0x00;
|
||||||
|
flipfrid->data[3] = 0x00;
|
||||||
|
flipfrid->data[4] = 0x00;
|
||||||
|
|
||||||
|
flipfrid->payload[0] = 0x00;
|
||||||
|
flipfrid->payload[1] = 0x00;
|
||||||
|
flipfrid->payload[2] = 0x00;
|
||||||
|
flipfrid->payload[3] = 0x00;
|
||||||
|
flipfrid->payload[4] = 0x00;
|
||||||
|
|
||||||
|
//Dialog
|
||||||
|
flipfrid->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||||
|
|
||||||
|
return flipfrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_free(FlipFridState* flipfrid) {
|
||||||
|
//Dialog
|
||||||
|
furi_record_close(RECORD_DIALOGS);
|
||||||
|
notification_message(flipfrid->notify, &sequence_blink_stop);
|
||||||
|
|
||||||
|
// Path strings
|
||||||
|
string_clear(flipfrid->file_path);
|
||||||
|
string_clear(flipfrid->file_path_tmp);
|
||||||
|
string_clear(flipfrid->notification_msg);
|
||||||
|
string_clear(flipfrid->attack_name);
|
||||||
|
|
||||||
|
free(flipfrid->data);
|
||||||
|
free(flipfrid->payload);
|
||||||
|
|
||||||
|
// The rest
|
||||||
|
free(flipfrid);
|
||||||
|
}
|
||||||
|
|
||||||
// ENTRYPOINT
|
// ENTRYPOINT
|
||||||
int32_t flipfrid_start(void* p) {
|
int32_t flipfrid_start(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
|
FURI_LOG_I(TAG, "Initializing input");
|
||||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(FlipFridEvent));
|
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(FlipFridEvent));
|
||||||
FlipFridState* flipfrid_state = (FlipFridState*)malloc(sizeof(FlipFridState));
|
FlipFridState* flipfrid_state = flipfrid_alloc();
|
||||||
ValueMutex flipfrid_state_mutex;
|
ValueMutex flipfrid_state_mutex;
|
||||||
|
|
||||||
// Mutex
|
// Mutex
|
||||||
|
FURI_LOG_I(TAG, "Initializing flipfrid mutex");
|
||||||
if(!init_mutex(&flipfrid_state_mutex, flipfrid_state, sizeof(FlipFridState))) {
|
if(!init_mutex(&flipfrid_state_mutex, flipfrid_state, sizeof(FlipFridState))) {
|
||||||
|
FURI_LOG_E(TAG, "cannot create mutex\r\n");
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
free(flipfrid_state);
|
free(flipfrid_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure view port
|
// Configure view port
|
||||||
|
FURI_LOG_I(TAG, "Initializing viewport");
|
||||||
ViewPort* view_port = view_port_alloc();
|
ViewPort* view_port = view_port_alloc();
|
||||||
view_port_draw_callback_set(view_port, flipfrid_draw_callback, &flipfrid_state_mutex);
|
view_port_draw_callback_set(view_port, flipfrid_draw_callback, &flipfrid_state_mutex);
|
||||||
view_port_input_callback_set(view_port, flipfrid_input_callback, event_queue);
|
view_port_input_callback_set(view_port, flipfrid_input_callback, event_queue);
|
||||||
|
|
||||||
// Configure timer
|
// Configure timer
|
||||||
|
FURI_LOG_I(TAG, "Initializing timer");
|
||||||
FuriTimer* timer =
|
FuriTimer* timer =
|
||||||
furi_timer_alloc(flipfrid_timer_callback, FuriTimerTypePeriodic, event_queue);
|
furi_timer_alloc(flipfrid_timer_callback, FuriTimerTypePeriodic, event_queue);
|
||||||
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); // configTICK_RATE_HZ_RAW 1000
|
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); // 10 times per second
|
||||||
|
|
||||||
// Register view port in GUI
|
// Register view port in GUI
|
||||||
|
FURI_LOG_I(TAG, "Initializing gui");
|
||||||
Gui* gui = (Gui*)furi_record_open(RECORD_GUI);
|
Gui* gui = (Gui*)furi_record_open(RECORD_GUI);
|
||||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
// Init values
|
// Init values
|
||||||
FlipFridEvent event;
|
FlipFridEvent event;
|
||||||
flipfrid_state->emitting = false;
|
while(flipfrid_state->is_running) {
|
||||||
flipfrid_state->current_uid = id_list[0];
|
|
||||||
flipfrid_state->current_attack_type = DefaultKeys;
|
|
||||||
flipfrid_state->meta_data = 0;
|
|
||||||
flipfrid_state->notify = furi_record_open(RECORD_NOTIFICATION);
|
|
||||||
|
|
||||||
// RFID Configuration
|
|
||||||
size_t data_size = 5; // Default EM4100 data size is 5 (1 customer id + 4 uid)
|
|
||||||
LFRFIDWorker* worker;
|
|
||||||
const ProtocolBase* lfrfid_protocol[] = {&protocol_raw_em4100, &protocol_raw_wrong_crc_em4100};
|
|
||||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocol, 2);
|
|
||||||
worker = lfrfid_worker_alloc(dict);
|
|
||||||
uint8_t selectedProtocol = CLEAN;
|
|
||||||
|
|
||||||
// Application state
|
|
||||||
int menu_selected_item_index = 0; // Menu current item index
|
|
||||||
uint8_t counter = 0; // Used to count the step and wqaiting time between each test
|
|
||||||
uint8_t attack_state = 0; // Used to store the current attack state
|
|
||||||
uint8_t candidate[5]; // uid candidate
|
|
||||||
bool running = true; // Used to stop the application
|
|
||||||
|
|
||||||
// Main loop
|
|
||||||
while(running) {
|
|
||||||
// Get next event
|
// Get next event
|
||||||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25);
|
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25);
|
||||||
if(event_status == FuriStatusOk) {
|
if(event_status == FuriStatusOk) {
|
||||||
if(event.evt_type == EventTypeKey) {
|
if(event.evt_type == EventTypeKey) {
|
||||||
if(event.input_type == InputTypeShort) {
|
//Handle event key
|
||||||
counter = 0;
|
switch(flipfrid_state->current_scene) {
|
||||||
switch(event.key) {
|
case NoneScene:
|
||||||
case InputKeyUp:
|
case SceneEntryPoint:
|
||||||
case InputKeyDown:
|
flipfrid_scene_entrypoint_on_event(event, flipfrid_state);
|
||||||
// OSEF
|
|
||||||
break;
|
break;
|
||||||
case InputKeyRight:
|
case SceneSelectFile:
|
||||||
// Next badge type
|
flipfrid_scene_load_file_on_event(event, flipfrid_state);
|
||||||
flipfrid_state->emitting = false;
|
|
||||||
attack_state = 0;
|
|
||||||
notification_message(flipfrid_state->notify, &sequence_blink_stop);
|
|
||||||
if(menu_selected_item_index < (NUMBER_OF_ATTACKS - 1)) {
|
|
||||||
menu_selected_item_index++;
|
|
||||||
flipfrid_state->current_attack_type =
|
|
||||||
(AttackType)menu_selected_item_index;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case InputKeyLeft:
|
case SceneSelectField:
|
||||||
// Previous badge type
|
flipfrid_scene_select_field_on_event(event, flipfrid_state);
|
||||||
flipfrid_state->emitting = false;
|
|
||||||
attack_state = 0;
|
|
||||||
notification_message(flipfrid_state->notify, &sequence_blink_stop);
|
|
||||||
if(menu_selected_item_index > 0) {
|
|
||||||
menu_selected_item_index--;
|
|
||||||
flipfrid_state->current_attack_type =
|
|
||||||
(AttackType)menu_selected_item_index;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case InputKeyOk:
|
case SceneAttack:
|
||||||
if(flipfrid_state->emitting) {
|
flipfrid_scene_run_attack_on_event(event, flipfrid_state);
|
||||||
flipfrid_state->emitting = false;
|
|
||||||
attack_state = 0;
|
|
||||||
// TODO FIX BLINK
|
|
||||||
notification_message(flipfrid_state->notify, &sequence_blink_stop);
|
|
||||||
} else {
|
|
||||||
flipfrid_state->emitting = true;
|
|
||||||
attack_state = 0;
|
|
||||||
// TODO FIX BLINK
|
|
||||||
notification_message(
|
|
||||||
flipfrid_state->notify, &sequence_blink_start_blue);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case InputKeyBack:
|
|
||||||
notification_message(flipfrid_state->notify, &sequence_blink_stop);
|
|
||||||
flipfrid_state->emitting = false;
|
|
||||||
running = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if(event.evt_type == EventTypeTick) {
|
} else if(event.evt_type == EventTypeTick) {
|
||||||
// Emulate card
|
//Handle event tick
|
||||||
if(flipfrid_state->emitting) {
|
if(flipfrid_state->current_scene != flipfrid_state->previous_scene) {
|
||||||
if(1 == counter) {
|
// Trigger Exit Scene
|
||||||
protocol_dict_set_data(
|
switch(flipfrid_state->previous_scene) {
|
||||||
dict, (LFRFIDProtocol)0, flipfrid_state->current_uid, data_size);
|
case SceneEntryPoint:
|
||||||
worker = lfrfid_worker_alloc(dict);
|
flipfrid_scene_entrypoint_on_exit(flipfrid_state);
|
||||||
lfrfid_worker_start_thread(worker);
|
break;
|
||||||
lfrfid_worker_emulate_start(worker, (LFRFIDProtocol)selectedProtocol);
|
case SceneSelectFile:
|
||||||
} else if(0 == counter) {
|
flipfrid_scene_load_file_on_exit(flipfrid_state);
|
||||||
lfrfid_worker_stop(worker);
|
break;
|
||||||
lfrfid_worker_stop_thread(worker);
|
case SceneSelectField:
|
||||||
// set next value
|
flipfrid_scene_select_field_on_exit(flipfrid_state);
|
||||||
switch(flipfrid_state->current_attack_type) {
|
break;
|
||||||
case DefaultKeys: {
|
case SceneAttack:
|
||||||
selectedProtocol = CLEAN;
|
flipfrid_scene_run_attack_on_exit(flipfrid_state);
|
||||||
data_size = 5;
|
break;
|
||||||
flipfrid_state->current_uid = id_list[attack_state];
|
case NoneScene:
|
||||||
attack_state = attack_state + 1;
|
|
||||||
if(attack_state >= sizeof(id_list) / sizeof(id_list[0])) {
|
|
||||||
attack_state = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BruteForceCustomerId: {
|
|
||||||
data_size = 5;
|
// Trigger Entry Scene
|
||||||
selectedProtocol = CLEAN;
|
switch(flipfrid_state->current_scene) {
|
||||||
candidate[0] = attack_state;
|
case NoneScene:
|
||||||
flipfrid_state->current_uid = candidate;
|
case SceneEntryPoint:
|
||||||
attack_state = attack_state + 1;
|
flipfrid_scene_entrypoint_on_enter(flipfrid_state);
|
||||||
if((attack_state + 1) == 256) {
|
break;
|
||||||
attack_state = 0;
|
case SceneSelectFile:
|
||||||
}
|
flipfrid_scene_load_file_on_enter(flipfrid_state);
|
||||||
|
break;
|
||||||
|
case SceneSelectField:
|
||||||
|
flipfrid_scene_select_field_on_enter(flipfrid_state);
|
||||||
|
break;
|
||||||
|
case SceneAttack:
|
||||||
|
flipfrid_scene_run_attack_on_enter(flipfrid_state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BadCrc: {
|
flipfrid_state->previous_scene = flipfrid_state->current_scene;
|
||||||
selectedProtocol = BAD_CRC;
|
}
|
||||||
data_size = 5;
|
|
||||||
candidate[0] = 0xFF;
|
// Trigger Tick Scene
|
||||||
candidate[1] = 0xDE;
|
switch(flipfrid_state->current_scene) {
|
||||||
candidate[2] = 0xAD;
|
case NoneScene:
|
||||||
candidate[3] = 0xBE;
|
case SceneEntryPoint:
|
||||||
candidate[4] = 0xEF;
|
flipfrid_scene_entrypoint_on_tick(flipfrid_state);
|
||||||
flipfrid_state->current_uid = candidate;
|
break;
|
||||||
|
case SceneSelectFile:
|
||||||
|
flipfrid_scene_load_file_on_tick(flipfrid_state);
|
||||||
|
break;
|
||||||
|
case SceneSelectField:
|
||||||
|
flipfrid_scene_select_field_on_tick(flipfrid_state);
|
||||||
|
break;
|
||||||
|
case SceneAttack:
|
||||||
|
flipfrid_scene_run_attack_on_tick(flipfrid_state);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(counter > TIME_BETWEEN_CARDS) {
|
|
||||||
counter = 0;
|
|
||||||
} else {
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
view_port_update(view_port);
|
view_port_update(view_port);
|
||||||
}
|
}
|
||||||
@ -307,17 +220,15 @@ int32_t flipfrid_start(void* p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
notification_message(flipfrid_state->notify, &sequence_blink_stop);
|
|
||||||
lfrfid_worker_stop(worker);
|
|
||||||
lfrfid_worker_stop_thread(worker);
|
|
||||||
lfrfid_worker_free(worker);
|
|
||||||
protocol_dict_free(dict);
|
|
||||||
furi_timer_stop(timer);
|
furi_timer_stop(timer);
|
||||||
furi_timer_free(timer);
|
furi_timer_free(timer);
|
||||||
free(flipfrid_state);
|
|
||||||
|
FURI_LOG_I(TAG, "Cleaning up");
|
||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
furi_record_close(RECORD_GUI);
|
furi_record_close(RECORD_GUI);
|
||||||
|
flipfrid_free(flipfrid_state);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -1,7 +1,67 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
#include <input/input.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/modules/submenu.h>
|
||||||
|
#include "m-string.h"
|
||||||
|
#include <dialogs/dialogs.h>
|
||||||
#include <notification/notification.h>
|
#include <notification/notification.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
#include "raw_em4100.h"
|
#include <toolbox/stream/stream.h>
|
||||||
|
#include <flipper_format/flipper_format_i.h>
|
||||||
|
|
||||||
int32_t flipfrid_start(void* p);
|
#include <lib/lfrfid/lfrfid_worker.h>
|
||||||
|
#include <lfrfid/protocols/lfrfid_protocols.h>
|
||||||
|
|
||||||
|
#define TAG "FlipFrid"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FlipFridAttackDefaultValues,
|
||||||
|
FlipFridAttackBfCustomerId,
|
||||||
|
FlipFridAttackLoadFile
|
||||||
|
} FlipFridAttacks;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NoneScene,
|
||||||
|
SceneEntryPoint,
|
||||||
|
SceneSelectFile,
|
||||||
|
SceneSelectField,
|
||||||
|
SceneAttack
|
||||||
|
} FlipFridScene;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EventTypeTick,
|
||||||
|
EventTypeKey,
|
||||||
|
} EventType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EventType evt_type;
|
||||||
|
InputKey key;
|
||||||
|
InputType input_type;
|
||||||
|
} FlipFridEvent;
|
||||||
|
|
||||||
|
// STRUCTS
|
||||||
|
typedef struct {
|
||||||
|
bool is_running;
|
||||||
|
bool is_attacking;
|
||||||
|
FlipFridScene current_scene;
|
||||||
|
FlipFridScene previous_scene;
|
||||||
|
NotificationApp* notify;
|
||||||
|
u_int8_t menu_index;
|
||||||
|
|
||||||
|
string_t data_str;
|
||||||
|
uint8_t data[5];
|
||||||
|
uint8_t payload[5];
|
||||||
|
uint8_t attack_step;
|
||||||
|
FlipFridAttacks attack;
|
||||||
|
string_t attack_name;
|
||||||
|
|
||||||
|
DialogsApp* dialogs;
|
||||||
|
string_t file_path;
|
||||||
|
string_t file_path_tmp;
|
||||||
|
string_t notification_msg;
|
||||||
|
uint8_t key_index;
|
||||||
|
LFRFIDWorker* worker;
|
||||||
|
ProtocolDict* dict;
|
||||||
|
} FlipFridState;
|
@ -1,106 +0,0 @@
|
|||||||
#include "raw_em4100.h"
|
|
||||||
#include <lib/lfrfid/protocols/protocol_em4100.c>
|
|
||||||
|
|
||||||
bool protocol_em4100_raw_encoder_start(ProtocolEM4100* proto) {
|
|
||||||
FURI_LOG_D("RAW_EM4100", "encoder_start : CLEAN");
|
|
||||||
// header
|
|
||||||
proto->encoded_data = 0b111111111;
|
|
||||||
|
|
||||||
// data
|
|
||||||
for(uint8_t i = 0; i < EM4100_DECODED_DATA_SIZE; i++) {
|
|
||||||
em4100_write_nibble(false, proto->data[i], &proto->encoded_data);
|
|
||||||
em4100_write_nibble(true, proto->data[i], &proto->encoded_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// column parity and stop bit
|
|
||||||
uint8_t parity_sum;
|
|
||||||
|
|
||||||
for(uint8_t c = 0; c < EM_COLUMN_COUNT; c++) {
|
|
||||||
parity_sum = 0;
|
|
||||||
for(uint8_t i = 1; i <= EM_ROW_COUNT; i++) {
|
|
||||||
uint8_t parity_bit = (proto->encoded_data >> (i * EM_BITS_PER_ROW_COUNT - 1)) & 1;
|
|
||||||
parity_sum += parity_bit;
|
|
||||||
}
|
|
||||||
proto->encoded_data = (proto->encoded_data << 1) | ((parity_sum % 2) & 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop bit
|
|
||||||
proto->encoded_data = (proto->encoded_data << 1) | 0;
|
|
||||||
|
|
||||||
proto->encoded_data_index = 0;
|
|
||||||
proto->encoded_polarity = true;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool protocol_em4100_wrong_crc_encoder_start(ProtocolEM4100* proto) {
|
|
||||||
FURI_LOG_D("RAW_EM4100", "encoder_start : WRONG CRC");
|
|
||||||
// header
|
|
||||||
proto->encoded_data = 0b111111111;
|
|
||||||
|
|
||||||
// data
|
|
||||||
for(uint8_t i = 0; i < EM4100_DECODED_DATA_SIZE; i++) {
|
|
||||||
em4100_write_nibble(false, proto->data[i], &proto->encoded_data);
|
|
||||||
em4100_write_nibble(true, proto->data[i], &proto->encoded_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(uint8_t c = 0; c < EM_COLUMN_COUNT; c++) {
|
|
||||||
proto->encoded_data = (proto->encoded_data << 1) | ((0 % 2) & 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop bit
|
|
||||||
proto->encoded_data = (proto->encoded_data << 1) | 1;
|
|
||||||
|
|
||||||
proto->encoded_data_index = 0;
|
|
||||||
proto->encoded_polarity = true;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ProtocolBase protocol_raw_em4100 = {
|
|
||||||
.name = "RawEM4100",
|
|
||||||
.manufacturer = "EM-Micro",
|
|
||||||
.data_size = EM4100_DECODED_DATA_SIZE,
|
|
||||||
.features = LFRFIDFeatureASK | LFRFIDFeaturePSK,
|
|
||||||
.validate_count = 3,
|
|
||||||
.alloc = (ProtocolAlloc)protocol_em4100_alloc,
|
|
||||||
.free = (ProtocolFree)protocol_em4100_free,
|
|
||||||
.get_data = (ProtocolGetData)protocol_em4100_get_data,
|
|
||||||
.decoder =
|
|
||||||
{
|
|
||||||
.start = (ProtocolDecoderStart)protocol_em4100_decoder_start,
|
|
||||||
.feed = (ProtocolDecoderFeed)protocol_em4100_decoder_feed,
|
|
||||||
},
|
|
||||||
.encoder =
|
|
||||||
{
|
|
||||||
.start = (ProtocolEncoderStart)protocol_em4100_raw_encoder_start,
|
|
||||||
.yield = (ProtocolEncoderYield)protocol_em4100_encoder_yield,
|
|
||||||
},
|
|
||||||
.render_data = (ProtocolRenderData)protocol_em4100_render_data,
|
|
||||||
.render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
|
|
||||||
.write_data = (ProtocolWriteData)protocol_em4100_write_data,
|
|
||||||
};
|
|
||||||
|
|
||||||
const ProtocolBase protocol_raw_wrong_crc_em4100 = {
|
|
||||||
.name = "RawEM4100",
|
|
||||||
.manufacturer = "EM-Micro",
|
|
||||||
.data_size = EM4100_DECODED_DATA_SIZE,
|
|
||||||
.features = LFRFIDFeatureASK | LFRFIDFeaturePSK,
|
|
||||||
.validate_count = 3,
|
|
||||||
.alloc = (ProtocolAlloc)protocol_em4100_alloc,
|
|
||||||
.free = (ProtocolFree)protocol_em4100_free,
|
|
||||||
.get_data = (ProtocolGetData)protocol_em4100_get_data,
|
|
||||||
.decoder =
|
|
||||||
{
|
|
||||||
.start = (ProtocolDecoderStart)protocol_em4100_decoder_start,
|
|
||||||
.feed = (ProtocolDecoderFeed)protocol_em4100_decoder_feed,
|
|
||||||
},
|
|
||||||
.encoder =
|
|
||||||
{
|
|
||||||
.start = (ProtocolEncoderStart)protocol_em4100_wrong_crc_encoder_start,
|
|
||||||
.yield = (ProtocolEncoderYield)protocol_em4100_encoder_yield,
|
|
||||||
},
|
|
||||||
.render_data = (ProtocolRenderData)protocol_em4100_render_data,
|
|
||||||
.render_brief_data = (ProtocolRenderData)protocol_em4100_render_data,
|
|
||||||
.write_data = (ProtocolWriteData)protocol_em4100_write_data,
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <toolbox/protocols/protocol.h>
|
|
||||||
|
|
||||||
|
|
||||||
enum FlipFridProtocol {
|
|
||||||
CLEAN,
|
|
||||||
BAD_CRC,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const ProtocolBase protocol_raw_em4100;
|
|
||||||
extern const ProtocolBase protocol_raw_wrong_crc_em4100;
|
|
97
applications/flipfrid/scene/flipfrid_scene_entrypoint.c
Normal file
97
applications/flipfrid/scene/flipfrid_scene_entrypoint.c
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include "flipfrid_scene_entrypoint.h"
|
||||||
|
|
||||||
|
string_t menu_items[4];
|
||||||
|
|
||||||
|
void flipfrid_scene_entrypoint_menu_callback(FlipFridState* context, uint32_t index) {
|
||||||
|
FURI_LOG_D(TAG, "MENU: %d", index);
|
||||||
|
switch(index) {
|
||||||
|
case FlipFridAttackDefaultValues:
|
||||||
|
context->attack = FlipFridAttackDefaultValues;
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
string_set_str(context->attack_name, "Default Values");
|
||||||
|
break;
|
||||||
|
case FlipFridAttackBfCustomerId:
|
||||||
|
context->attack = FlipFridAttackBfCustomerId;
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
string_set_str(context->attack_name, "Bad Customer ID");
|
||||||
|
break;
|
||||||
|
case FlipFridAttackLoadFile:
|
||||||
|
context->attack = FlipFridAttackLoadFile;
|
||||||
|
context->current_scene = SceneSelectFile;
|
||||||
|
string_set_str(context->attack_name, "Load File");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_entrypoint_on_enter(FlipFridState* context) {
|
||||||
|
context->menu_index = 0;
|
||||||
|
for (uint32_t i = 0; i < 3; i++) {
|
||||||
|
string_init(menu_items[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_set(menu_items[0], "Default Values");
|
||||||
|
string_set(menu_items[1], "BF Customer ID");
|
||||||
|
string_set(menu_items[2], "Load File");
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_entrypoint_on_exit(FlipFridState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
for (uint32_t i = 0; i < 3; i++) {
|
||||||
|
string_clear(menu_items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_entrypoint_on_tick(FlipFridState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
if(context->menu_index < FlipFridAttackLoadFile) {
|
||||||
|
context->menu_index++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyUp:
|
||||||
|
if(context->menu_index > FlipFridAttackDefaultValues) {
|
||||||
|
context->menu_index--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyLeft:
|
||||||
|
case InputKeyRight:
|
||||||
|
case InputKeyOk:
|
||||||
|
flipfrid_scene_entrypoint_menu_callback(context, context->menu_index);
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
context->is_running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||||
|
canvas_clear(canvas);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignTop, "RFID Fuzzer");
|
||||||
|
|
||||||
|
if(context->menu_index > FlipFridAttackDefaultValues) {
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, string_get_cstr(menu_items[context->menu_index - 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 36, AlignCenter, AlignTop, string_get_cstr(menu_items[context->menu_index]));
|
||||||
|
|
||||||
|
if(context->menu_index < FlipFridAttackLoadFile) {
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 48, AlignCenter, AlignTop, string_get_cstr(menu_items[context->menu_index + 1]));
|
||||||
|
}
|
||||||
|
}
|
8
applications/flipfrid/scene/flipfrid_scene_entrypoint.h
Normal file
8
applications/flipfrid/scene/flipfrid_scene_entrypoint.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../flipfrid.h"
|
||||||
|
|
||||||
|
void flipfrid_scene_entrypoint_on_enter(FlipFridState* context);
|
||||||
|
void flipfrid_scene_entrypoint_on_exit(FlipFridState* context);
|
||||||
|
void flipfrid_scene_entrypoint_on_tick(FlipFridState* context);
|
||||||
|
void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* context);
|
||||||
|
void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context);
|
143
applications/flipfrid/scene/flipfrid_scene_load_file.c
Normal file
143
applications/flipfrid/scene/flipfrid_scene_load_file.c
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#include "flipfrid_scene_load_file.h"
|
||||||
|
|
||||||
|
#define LFRFID_APP_EXTENSION ".rfid"
|
||||||
|
|
||||||
|
bool flipfrid_load(FlipFridState* context, const char* file_path) {
|
||||||
|
bool result = false;
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||||
|
string_t temp_str;
|
||||||
|
string_init(temp_str);
|
||||||
|
do {
|
||||||
|
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||||
|
FURI_LOG_E(TAG, "Error open file %s", file_path);
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Error open file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileType
|
||||||
|
if(!flipper_format_read_string(fff_data_file, "Filetype", temp_str)) {
|
||||||
|
FURI_LOG_E(TAG, "Missing or incorrect Filetype");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Missing or incorrect Filetypes");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "Filetype: %s", string_get_cstr(temp_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key type
|
||||||
|
if(!flipper_format_read_string(fff_data_file, "Key type", temp_str)) {
|
||||||
|
FURI_LOG_E(TAG, "Missing or incorrect Key type");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Missing or incorrect Key type");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "Key type: %s", string_get_cstr(temp_str));
|
||||||
|
if (strcmp(string_get_cstr(temp_str), "EM4100") != 0) {
|
||||||
|
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Unsupported Key type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data
|
||||||
|
if(!flipper_format_read_string(fff_data_file, "Data", context->data_str)) {
|
||||||
|
FURI_LOG_E(TAG, "Missing or incorrect Data");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Missing or incorrect Key");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "Key: %s", string_get_cstr(context->data_str));
|
||||||
|
|
||||||
|
// Check data size
|
||||||
|
if (string_size(context->data_str) != 14) {
|
||||||
|
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Incorrect Key length");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// String to uint8_t
|
||||||
|
for (uint8_t i = 0; i < 5; i++) {
|
||||||
|
char temp_str2[3];
|
||||||
|
temp_str2[0] = string_get_cstr(context->data_str)[i*3];
|
||||||
|
temp_str2[1] = string_get_cstr(context->data_str)[i*3+1];
|
||||||
|
temp_str2[2] = '\0';
|
||||||
|
context->data[i] = (uint8_t)strtol(temp_str2, NULL, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
} while(0);
|
||||||
|
string_clear(temp_str);
|
||||||
|
flipper_format_free(fff_data_file);
|
||||||
|
if(result) {
|
||||||
|
FURI_LOG_I(TAG, "Loaded successfully");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Source loaded.");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_load_file_on_enter(FlipFridState* context) {
|
||||||
|
if(flipfrid_load_protocol_from_file(context)) {
|
||||||
|
context->current_scene = SceneSelectField;
|
||||||
|
} else {
|
||||||
|
context->current_scene = SceneEntryPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_load_file_on_exit(FlipFridState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_load_file_on_tick(FlipFridState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_load_file_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
case InputKeyUp:
|
||||||
|
case InputKeyLeft:
|
||||||
|
case InputKeyRight:
|
||||||
|
case InputKeyOk:
|
||||||
|
case InputKeyBack:
|
||||||
|
context->current_scene = SceneEntryPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_load_file_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
UNUSED(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool flipfrid_load_protocol_from_file(FlipFridState* context) {
|
||||||
|
string_t file_path;
|
||||||
|
string_init(file_path);
|
||||||
|
|
||||||
|
// Input events and views are managed by file_select
|
||||||
|
bool res = dialog_file_browser_show(
|
||||||
|
context->dialogs,
|
||||||
|
context->file_path,
|
||||||
|
context->file_path,
|
||||||
|
LFRFID_APP_EXTENSION,
|
||||||
|
true,
|
||||||
|
&I_sub1_10px,
|
||||||
|
true);
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
res = flipfrid_load(context, string_get_cstr(context->file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
string_clear(file_path);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
9
applications/flipfrid/scene/flipfrid_scene_load_file.h
Normal file
9
applications/flipfrid/scene/flipfrid_scene_load_file.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../flipfrid.h"
|
||||||
|
|
||||||
|
void flipfrid_scene_load_file_on_enter(FlipFridState* context);
|
||||||
|
void flipfrid_scene_load_file_on_exit(FlipFridState* context);
|
||||||
|
void flipfrid_scene_load_file_on_tick(FlipFridState* context);
|
||||||
|
void flipfrid_scene_load_file_on_event(FlipFridEvent event, FlipFridState* context);
|
||||||
|
void flipfrid_scene_load_file_on_draw(Canvas* canvas, FlipFridState* context);
|
||||||
|
bool flipfrid_load_protocol_from_file(FlipFridState* context);
|
167
applications/flipfrid/scene/flipfrid_scene_run_attack.c
Normal file
167
applications/flipfrid/scene/flipfrid_scene_run_attack.c
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include "flipfrid_scene_run_attack.h"
|
||||||
|
|
||||||
|
uint8_t counter = 0;
|
||||||
|
#define TIME_BETWEEN_CARDS 5
|
||||||
|
uint8_t id_list[16][5] = {
|
||||||
|
{0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||||
|
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||||
|
{0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||||
|
{0x22, 0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||||
|
{0x33, 0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||||
|
{0x44, 0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||||
|
{0x55, 0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||||
|
{0x66, 0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||||
|
{0x77, 0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||||
|
{0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||||
|
{0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||||
|
{0x12, 0x34, 0x56, 0x78, 0x9A}, // Incremental UID
|
||||||
|
{0x04, 0xd0, 0x9b, 0x0d, 0x6a}, // From arha
|
||||||
|
{0x34, 0x00, 0x29, 0x3d, 0x9e}, // From arha
|
||||||
|
{0x04, 0xdf, 0x00, 0x00, 0x01}, // From arha
|
||||||
|
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||||
|
};
|
||||||
|
|
||||||
|
void flipfrid_scene_run_attack_on_enter(FlipFridState* context) {
|
||||||
|
context->attack_step = 0;
|
||||||
|
context->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||||
|
context->worker = lfrfid_worker_alloc(context->dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_run_attack_on_exit(FlipFridState* context) {
|
||||||
|
lfrfid_worker_stop(context->worker);
|
||||||
|
lfrfid_worker_stop_thread(context->worker);
|
||||||
|
lfrfid_worker_free(context->worker);
|
||||||
|
protocol_dict_free(context->dict);
|
||||||
|
notification_message(context->notify, &sequence_blink_stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||||
|
ProtocolId protocol;
|
||||||
|
protocol = protocol_dict_get_protocol_by_name(context->dict, "EM4100");
|
||||||
|
if(context->is_attacking) {
|
||||||
|
if(1 == counter) {
|
||||||
|
protocol_dict_set_data(context->dict, protocol, context->payload, 5);
|
||||||
|
context->worker = lfrfid_worker_alloc(context->dict);
|
||||||
|
lfrfid_worker_start_thread(context->worker);
|
||||||
|
lfrfid_worker_emulate_start(context->worker, protocol);
|
||||||
|
} else if(0 == counter) {
|
||||||
|
lfrfid_worker_stop(context->worker);
|
||||||
|
lfrfid_worker_stop_thread(context->worker);
|
||||||
|
switch(context->attack) {
|
||||||
|
case FlipFridAttackDefaultValues:
|
||||||
|
context->payload[0] = id_list[context->attack_step][0];
|
||||||
|
context->payload[1] = id_list[context->attack_step][1];
|
||||||
|
context->payload[2] = id_list[context->attack_step][2];
|
||||||
|
context->payload[3] = id_list[context->attack_step][3];
|
||||||
|
context->payload[4] = id_list[context->attack_step][4];
|
||||||
|
|
||||||
|
if(context->attack_step == 15) {
|
||||||
|
context->attack_step = 0;
|
||||||
|
} else {
|
||||||
|
context->attack_step++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FlipFridAttackBfCustomerId:
|
||||||
|
context->payload[0] = context->attack_step;
|
||||||
|
context->payload[1] = 0x00;
|
||||||
|
context->payload[2] = 0x00;
|
||||||
|
context->payload[3] = 0x00;
|
||||||
|
context->payload[4] = 0x00;
|
||||||
|
|
||||||
|
if(context->attack_step == 255) {
|
||||||
|
context->attack_step = 0;
|
||||||
|
} else {
|
||||||
|
context->attack_step++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FlipFridAttackLoadFile:
|
||||||
|
context->payload[0] = context->data[0];
|
||||||
|
context->payload[1] = context->data[1];
|
||||||
|
context->payload[2] = context->data[2];
|
||||||
|
context->payload[3] = context->data[3];
|
||||||
|
context->payload[4] = context->data[4];
|
||||||
|
|
||||||
|
context->payload[context->key_index] = context->attack_step;
|
||||||
|
|
||||||
|
if(context->attack_step == 255) {
|
||||||
|
context->attack_step = 0;
|
||||||
|
} else {
|
||||||
|
context->attack_step++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(counter > TIME_BETWEEN_CARDS) {
|
||||||
|
counter = 0;
|
||||||
|
} else {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
case InputKeyUp:
|
||||||
|
case InputKeyLeft:
|
||||||
|
case InputKeyRight:
|
||||||
|
case InputKeyOk:
|
||||||
|
counter = 0;
|
||||||
|
if(!context->is_attacking) {
|
||||||
|
notification_message(context->notify, &sequence_blink_start_blue);
|
||||||
|
context->is_attacking = true;
|
||||||
|
} else {
|
||||||
|
context->is_attacking = false;
|
||||||
|
notification_message(context->notify, &sequence_blink_stop);
|
||||||
|
notification_message(context->notify, &sequence_single_vibro);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
context->attack_step = 0;
|
||||||
|
context->is_attacking = false;
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
context->current_scene = SceneEntryPoint;
|
||||||
|
notification_message(context->notify, &sequence_blink_stop);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||||
|
canvas_clear(canvas);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
|
// Frame
|
||||||
|
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas, 64, 8, AlignCenter, AlignTop, string_get_cstr(context->attack_name));
|
||||||
|
|
||||||
|
char uid[16];
|
||||||
|
snprintf(
|
||||||
|
uid,
|
||||||
|
sizeof(uid),
|
||||||
|
"%2X:%2X:%2X:%2X:%2X",
|
||||||
|
context->payload[0],
|
||||||
|
context->payload[1],
|
||||||
|
context->payload[2],
|
||||||
|
context->payload[3],
|
||||||
|
context->payload[4]);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, uid);
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
char start_stop_msg[20];
|
||||||
|
if(context->is_attacking) {
|
||||||
|
snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to stop ");
|
||||||
|
} else {
|
||||||
|
snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to start ");
|
||||||
|
}
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignTop, start_stop_msg);
|
||||||
|
}
|
8
applications/flipfrid/scene/flipfrid_scene_run_attack.h
Normal file
8
applications/flipfrid/scene/flipfrid_scene_run_attack.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../flipfrid.h"
|
||||||
|
|
||||||
|
void flipfrid_scene_run_attack_on_enter(FlipFridState* context);
|
||||||
|
void flipfrid_scene_run_attack_on_exit(FlipFridState* context);
|
||||||
|
void flipfrid_scene_run_attack_on_tick(FlipFridState* context);
|
||||||
|
void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* context);
|
||||||
|
void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context);
|
120
applications/flipfrid/scene/flipfrid_scene_select_field.c
Normal file
120
applications/flipfrid/scene/flipfrid_scene_select_field.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include "flipfrid_scene_select_field.h"
|
||||||
|
|
||||||
|
void flipfrid_center_displayed_key(FlipFridState* context, uint8_t index) {
|
||||||
|
const char* key_cstr = string_get_cstr(context->data_str);
|
||||||
|
uint8_t str_index = (index * 3);
|
||||||
|
|
||||||
|
char display_menu[17] = {'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'};
|
||||||
|
|
||||||
|
if(index > 1) {
|
||||||
|
display_menu[0] = key_cstr[str_index - 6];
|
||||||
|
display_menu[1] = key_cstr[str_index - 5];
|
||||||
|
} else {
|
||||||
|
display_menu[0] = ' ';
|
||||||
|
display_menu[1] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index > 0) {
|
||||||
|
display_menu[3] = key_cstr[str_index - 3];
|
||||||
|
display_menu[4] = key_cstr[str_index - 2];
|
||||||
|
} else {
|
||||||
|
display_menu[3] = ' ';
|
||||||
|
display_menu[4] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
display_menu[7] = key_cstr[str_index];
|
||||||
|
display_menu[8] = key_cstr[str_index + 1];
|
||||||
|
|
||||||
|
if((str_index + 4) <= (uint8_t) strlen(key_cstr)) {
|
||||||
|
display_menu[11] = key_cstr[str_index + 3];
|
||||||
|
display_menu[12] = key_cstr[str_index + 4];
|
||||||
|
} else {
|
||||||
|
display_menu[11] = ' ';
|
||||||
|
display_menu[12] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if((str_index + 8) <= (uint8_t) strlen(key_cstr)) {
|
||||||
|
display_menu[14] = key_cstr[str_index + 6];
|
||||||
|
display_menu[15] = key_cstr[str_index + 7];
|
||||||
|
} else {
|
||||||
|
display_menu[14] = ' ';
|
||||||
|
display_menu[15] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, display_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_select_field_on_enter(FlipFridState* context) {
|
||||||
|
string_clear(context->notification_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_select_field_on_exit(FlipFridState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_select_field_on_tick(FlipFridState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
const char* key_cstr = string_get_cstr(context->data_str);
|
||||||
|
|
||||||
|
// don't look, it's ugly but I'm a python dev so...
|
||||||
|
uint8_t nb_bytes = 0;
|
||||||
|
for(uint8_t i = 0; i < strlen(key_cstr); i++) {
|
||||||
|
if(' ' == key_cstr[i]) {
|
||||||
|
nb_bytes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
case InputKeyUp:
|
||||||
|
break;
|
||||||
|
case InputKeyLeft:
|
||||||
|
if(context->key_index > 0) {
|
||||||
|
context->key_index = context->key_index - 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyRight:
|
||||||
|
if(context->key_index < nb_bytes) {
|
||||||
|
context->key_index = context->key_index + 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyOk:
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
context->current_scene = SceneSelectFile;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipfrid_scene_select_field_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||||
|
canvas_clear(canvas);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
|
// Frame
|
||||||
|
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Use < > to select byte.");
|
||||||
|
|
||||||
|
char msg_index[18];
|
||||||
|
snprintf(msg_index, sizeof(msg_index), "Field index : %d", context->key_index);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index);
|
||||||
|
|
||||||
|
flipfrid_center_displayed_key(context, context->key_index);
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas, 64, 40, AlignCenter, AlignTop, string_get_cstr(context->notification_msg));
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../flipfrid.h"
|
||||||
|
|
||||||
|
void flipfrid_scene_select_field_on_enter(FlipFridState* context);
|
||||||
|
void flipfrid_scene_select_field_on_exit(FlipFridState* context);
|
||||||
|
void flipfrid_scene_select_field_on_tick(FlipFridState* context);
|
||||||
|
void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* context);
|
||||||
|
void flipfrid_scene_select_field_on_draw(Canvas* canvas, FlipFridState* context);
|
||||||
|
void center_displayed_key(FlipFridState* context, uint8_t index);
|
Loading…
Reference in New Issue
Block a user