mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-12 23:48:10 -07:00
Add flipfrid application
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* @G4N4P4T1 wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -0,0 +1,4 @@
|
||||
# FlipFrid
|
||||
|
||||
A simple implementation of ZigFrid on Flipper zero (+bonus)
|
||||
(https://z4ziggy.wordpress.com/2017/07/21/zigfrid-a-passive-rfid-fuzzer/)
|
||||
@@ -0,0 +1,11 @@
|
||||
App(
|
||||
appid="flipfrid",
|
||||
name="Rfid fuzzer",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="flipfrid_start",
|
||||
cdefines=["APP_FLIP_FRID"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
icon="A_125khz_14",
|
||||
order=185,
|
||||
)
|
||||
@@ -0,0 +1,317 @@
|
||||
#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"
|
||||
|
||||
#define NUMBER_OF_ATTACKS 4
|
||||
#define TIME_BETWEEN_CARDS \
|
||||
5 // Emulate 2 cards per second : (5 * (configTICK_RATE_HZ_RAW/10)) == (5*(1000/10)) == (5*100) == (500)ms
|
||||
#define TAG "FLIPFRID"
|
||||
|
||||
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) {
|
||||
const FlipFridState* flipfrid_state = (FlipFridState*)acquire_mutex((ValueMutex*)ctx, 100);
|
||||
|
||||
if(flipfrid_state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
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, "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;
|
||||
case BruteForceCustomerId:
|
||||
strcpy(badge_type, "< BF Customer ID >");
|
||||
break;
|
||||
case BadCrc:
|
||||
strcpy(badge_type, "< Bad CRC ");
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
}
|
||||
|
||||
void flipfrid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
|
||||
FlipFridEvent event = {
|
||||
.evt_type = EventTypeKey, .key = input_event->key, .input_type = input_event->type};
|
||||
furi_message_queue_put(event_queue, &event, 25);
|
||||
}
|
||||
|
||||
static void flipfrid_timer_callback(FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
|
||||
FlipFridEvent event = {
|
||||
.evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease};
|
||||
furi_message_queue_put(event_queue, &event, 25);
|
||||
}
|
||||
|
||||
// ENTRYPOINT
|
||||
int32_t flipfrid_start(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
// Input
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(FlipFridEvent));
|
||||
FlipFridState* flipfrid_state = (FlipFridState*)malloc(sizeof(FlipFridState));
|
||||
ValueMutex flipfrid_state_mutex;
|
||||
|
||||
// Mutex
|
||||
if(!init_mutex(&flipfrid_state_mutex, flipfrid_state, sizeof(FlipFridState))) {
|
||||
furi_message_queue_free(event_queue);
|
||||
free(flipfrid_state);
|
||||
}
|
||||
|
||||
// Configure view port
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
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);
|
||||
|
||||
// Configure timer
|
||||
FuriTimer* timer =
|
||||
furi_timer_alloc(flipfrid_timer_callback, FuriTimerTypePeriodic, event_queue);
|
||||
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); // configTICK_RATE_HZ_RAW 1000
|
||||
|
||||
// Register view port in GUI
|
||||
Gui* gui = (Gui*)furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
// Init values
|
||||
FlipFridEvent event;
|
||||
flipfrid_state->emitting = false;
|
||||
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
|
||||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25);
|
||||
if(event_status == FuriStatusOk) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
counter = 0;
|
||||
switch(event.key) {
|
||||
case InputKeyUp:
|
||||
case InputKeyDown:
|
||||
// OSEF
|
||||
break;
|
||||
case InputKeyRight:
|
||||
// Next badge type
|
||||
flipfrid_state->emitting = false;
|
||||
if(menu_selected_item_index < (NUMBER_OF_ATTACKS - 1)) {
|
||||
menu_selected_item_index++;
|
||||
flipfrid_state->current_attack_type =
|
||||
(AttackType)menu_selected_item_index;
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
// Previous badge type
|
||||
flipfrid_state->emitting = false;
|
||||
if(menu_selected_item_index > 0) {
|
||||
menu_selected_item_index--;
|
||||
flipfrid_state->current_attack_type =
|
||||
(AttackType)menu_selected_item_index;
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
if(flipfrid_state->emitting) {
|
||||
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_magenta);
|
||||
}
|
||||
break;
|
||||
case InputKeyBack:
|
||||
flipfrid_state->emitting = false;
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(event.evt_type == EventTypeTick) {
|
||||
// Emulate card
|
||||
if(flipfrid_state->emitting) {
|
||||
if(1 == counter) {
|
||||
protocol_dict_set_data(
|
||||
dict, (LFRFIDProtocol)0, flipfrid_state->current_uid, data_size);
|
||||
worker = lfrfid_worker_alloc(dict);
|
||||
lfrfid_worker_start_thread(worker);
|
||||
lfrfid_worker_emulate_start(worker, (LFRFIDProtocol)selectedProtocol);
|
||||
} else if(0 == counter) {
|
||||
lfrfid_worker_stop(worker);
|
||||
lfrfid_worker_stop_thread(worker);
|
||||
// set next value
|
||||
switch(flipfrid_state->current_attack_type) {
|
||||
case DefaultKeys: {
|
||||
selectedProtocol = CLEAN;
|
||||
data_size = 5;
|
||||
flipfrid_state->current_uid = id_list[attack_state];
|
||||
attack_state = attack_state + 1;
|
||||
if(attack_state >= sizeof(id_list) / sizeof(id_list[0])) {
|
||||
attack_state = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BruteForceCustomerId: {
|
||||
data_size = 5;
|
||||
selectedProtocol = CLEAN;
|
||||
candidate[0] = attack_state;
|
||||
flipfrid_state->current_uid = candidate;
|
||||
attack_state = attack_state + 1;
|
||||
if((attack_state + 1) == 256) {
|
||||
attack_state = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BadCrc: {
|
||||
selectedProtocol = BAD_CRC;
|
||||
data_size = 5;
|
||||
candidate[0] = 0xFF;
|
||||
candidate[1] = 0xDE;
|
||||
candidate[2] = 0xAD;
|
||||
candidate[3] = 0xBE;
|
||||
candidate[4] = 0xEF;
|
||||
flipfrid_state->current_uid = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(counter > TIME_BETWEEN_CARDS) {
|
||||
counter = 0;
|
||||
} else {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
view_port_update(view_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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_free(timer);
|
||||
free(flipfrid_state);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_record_close(RECORD_GUI);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include "raw_em4100.h"
|
||||
|
||||
int32_t flipfrid_start(void* p);
|
||||
@@ -0,0 +1,106 @@
|
||||
#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,
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
#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;
|
||||
@@ -36,6 +36,7 @@ App(
|
||||
provides=[
|
||||
"music_player",
|
||||
"bt_hid",
|
||||
"flipfrid",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user