diff --git a/applications/flipfrid/README.md b/applications/flipfrid/README.md deleted file mode 100644 index d5f79bf5d..000000000 --- a/applications/flipfrid/README.md +++ /dev/null @@ -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/) \ No newline at end of file diff --git a/applications/flipfrid/application.fam b/applications/flipfrid/application.fam index 0eee3cc1b..59e4196f8 100644 --- a/applications/flipfrid/application.fam +++ b/applications/flipfrid/application.fam @@ -1,6 +1,6 @@ App( appid="flipfrid", - name="RFID Fuzzer", + name="Rfid Fuzzer", apptype=FlipperAppType.PLUGIN, entry_point="flipfrid_start", cdefines=["APP_FLIP_FRID"], diff --git a/applications/flipfrid/flipfrid.c b/applications/flipfrid/flipfrid.c index cc8898dff..7889f33c8 100644 --- a/applications/flipfrid/flipfrid.c +++ b/applications/flipfrid/flipfrid.c @@ -1,125 +1,34 @@ -#include -#include -#include -#include - -#include -#include "raw_em4100.h" -#include - #include "flipfrid.h" -#define NUMBER_OF_ATTACKS 3 -#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; +#include "scene/flipfrid_scene_entrypoint.h" +#include "scene/flipfrid_scene_load_file.h" +#include "scene/flipfrid_scene_select_field.h" +#include "scene/flipfrid_scene_run_attack.h" 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) { 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 >"); + // Draw correct Canvas + switch(flipfrid_state->current_scene) { + case NoneScene: + case SceneEntryPoint: + flipfrid_scene_entrypoint_on_draw(canvas, flipfrid_state); break; - case BruteForceCustomerId: - strcpy(badge_type, "< BF Customer ID >"); + case SceneSelectFile: + flipfrid_scene_load_file_on_draw(canvas, flipfrid_state); break; - case BadCrc: - strcpy(badge_type, "< Bad CRC "); + case SceneSelectField: + flipfrid_scene_select_field_on_draw(canvas, flipfrid_state); break; - default: + case SceneAttack: + flipfrid_scene_run_attack_on_draw(canvas, flipfrid_state); 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); } @@ -133,173 +42,177 @@ void flipfrid_input_callback(InputEvent* input_event, FuriMessageQueue* event_qu 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); } +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 int32_t flipfrid_start(void* p) { UNUSED(p); - // Input + FURI_LOG_I(TAG, "Initializing input"); 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; // Mutex + FURI_LOG_I(TAG, "Initializing flipfrid mutex"); 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); free(flipfrid_state); } // Configure view port + FURI_LOG_I(TAG, "Initializing viewport"); 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 + FURI_LOG_I(TAG, "Initializing 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 + furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); // 10 times per second // Register view port in GUI + FURI_LOG_I(TAG, "Initializing 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) { + while(flipfrid_state->is_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; - 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; - case InputKeyLeft: - // Previous badge type - 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; - 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_blue); - } - break; - case InputKeyBack: - notification_message(flipfrid_state->notify, &sequence_blink_stop); - flipfrid_state->emitting = false; - running = false; - break; - } + //Handle event key + switch(flipfrid_state->current_scene) { + case NoneScene: + case SceneEntryPoint: + flipfrid_scene_entrypoint_on_event(event, flipfrid_state); + break; + case SceneSelectFile: + flipfrid_scene_load_file_on_event(event, flipfrid_state); + break; + case SceneSelectField: + flipfrid_scene_select_field_on_event(event, flipfrid_state); + break; + case SceneAttack: + flipfrid_scene_run_attack_on_event(event, flipfrid_state); + 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; - } - } + //Handle event tick + if(flipfrid_state->current_scene != flipfrid_state->previous_scene) { + // Trigger Exit Scene + switch(flipfrid_state->previous_scene) { + case SceneEntryPoint: + flipfrid_scene_entrypoint_on_exit(flipfrid_state); + break; + case SceneSelectFile: + flipfrid_scene_load_file_on_exit(flipfrid_state); + break; + case SceneSelectField: + flipfrid_scene_select_field_on_exit(flipfrid_state); + break; + case SceneAttack: + flipfrid_scene_run_attack_on_exit(flipfrid_state); + break; + case NoneScene: + break; } - if(counter > TIME_BETWEEN_CARDS) { - counter = 0; - } else { - counter++; + + // Trigger Entry Scene + switch(flipfrid_state->current_scene) { + case NoneScene: + case SceneEntryPoint: + flipfrid_scene_entrypoint_on_enter(flipfrid_state); + break; + 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; } + flipfrid_state->previous_scene = flipfrid_state->current_scene; + } + + // Trigger Tick Scene + switch(flipfrid_state->current_scene) { + case NoneScene: + case SceneEntryPoint: + flipfrid_scene_entrypoint_on_tick(flipfrid_state); + 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; } view_port_update(view_port); } @@ -307,17 +220,15 @@ int32_t flipfrid_start(void* p) { } // 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); + + FURI_LOG_I(TAG, "Cleaning up"); gui_remove_view_port(gui, view_port); view_port_free(view_port); furi_message_queue_free(event_queue); furi_record_close(RECORD_GUI); + flipfrid_free(flipfrid_state); + return 0; } \ No newline at end of file diff --git a/applications/flipfrid/flipfrid.h b/applications/flipfrid/flipfrid.h index 1b2369a4c..e1c49e716 100644 --- a/applications/flipfrid/flipfrid.h +++ b/applications/flipfrid/flipfrid.h @@ -1,7 +1,67 @@ #pragma once #include +#include +#include +#include +#include +#include "m-string.h" +#include #include #include -#include "raw_em4100.h" +#include +#include -int32_t flipfrid_start(void* p); \ No newline at end of file +#include +#include + +#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; \ No newline at end of file diff --git a/applications/flipfrid/raw_em4100.c b/applications/flipfrid/raw_em4100.c deleted file mode 100644 index 4cc477ee7..000000000 --- a/applications/flipfrid/raw_em4100.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "raw_em4100.h" -#include - -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, -}; \ No newline at end of file diff --git a/applications/flipfrid/raw_em4100.h b/applications/flipfrid/raw_em4100.h deleted file mode 100644 index faa2ccd9e..000000000 --- a/applications/flipfrid/raw_em4100.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include - - -enum FlipFridProtocol { - CLEAN, - BAD_CRC, -}; - -extern const ProtocolBase protocol_raw_em4100; -extern const ProtocolBase protocol_raw_wrong_crc_em4100; \ No newline at end of file diff --git a/applications/flipfrid/scene/flipfrid_scene_entrypoint.c b/applications/flipfrid/scene/flipfrid_scene_entrypoint.c new file mode 100644 index 000000000..42bccb8f7 --- /dev/null +++ b/applications/flipfrid/scene/flipfrid_scene_entrypoint.c @@ -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])); + } +} \ No newline at end of file diff --git a/applications/flipfrid/scene/flipfrid_scene_entrypoint.h b/applications/flipfrid/scene/flipfrid_scene_entrypoint.h new file mode 100644 index 000000000..29ca5bdfa --- /dev/null +++ b/applications/flipfrid/scene/flipfrid_scene_entrypoint.h @@ -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); \ No newline at end of file diff --git a/applications/flipfrid/scene/flipfrid_scene_load_file.c b/applications/flipfrid/scene/flipfrid_scene_load_file.c new file mode 100644 index 000000000..157b8e807 --- /dev/null +++ b/applications/flipfrid/scene/flipfrid_scene_load_file.c @@ -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; +} \ No newline at end of file diff --git a/applications/flipfrid/scene/flipfrid_scene_load_file.h b/applications/flipfrid/scene/flipfrid_scene_load_file.h new file mode 100644 index 000000000..ca82daab4 --- /dev/null +++ b/applications/flipfrid/scene/flipfrid_scene_load_file.h @@ -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); \ No newline at end of file diff --git a/applications/flipfrid/scene/flipfrid_scene_run_attack.c b/applications/flipfrid/scene/flipfrid_scene_run_attack.c new file mode 100644 index 000000000..8681e0bcf --- /dev/null +++ b/applications/flipfrid/scene/flipfrid_scene_run_attack.c @@ -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); +} diff --git a/applications/flipfrid/scene/flipfrid_scene_run_attack.h b/applications/flipfrid/scene/flipfrid_scene_run_attack.h new file mode 100644 index 000000000..ae56d35e7 --- /dev/null +++ b/applications/flipfrid/scene/flipfrid_scene_run_attack.h @@ -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); diff --git a/applications/flipfrid/scene/flipfrid_scene_select_field.c b/applications/flipfrid/scene/flipfrid_scene_select_field.c new file mode 100644 index 000000000..307188029 --- /dev/null +++ b/applications/flipfrid/scene/flipfrid_scene_select_field.c @@ -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)); +} diff --git a/applications/flipfrid/scene/flipfrid_scene_select_field.h b/applications/flipfrid/scene/flipfrid_scene_select_field.h new file mode 100644 index 000000000..5533e321c --- /dev/null +++ b/applications/flipfrid/scene/flipfrid_scene_select_field.h @@ -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); \ No newline at end of file