From aa572f1dce72044571e27ff8ab03da4df36d2204 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Thu, 20 Jun 2024 18:48:50 -0700 Subject: [PATCH] Add elite keygen attack to UI --- scenes/picopass_scene_config.h | 1 + scenes/picopass_scene_elite_keygen_attack.c | 145 ++++++++++++++++++++ scenes/picopass_scene_start.c | 12 ++ 3 files changed, 158 insertions(+) create mode 100644 scenes/picopass_scene_elite_keygen_attack.c diff --git a/scenes/picopass_scene_config.h b/scenes/picopass_scene_config.h index 6a529d8aa37..d8a54a74281 100644 --- a/scenes/picopass_scene_config.h +++ b/scenes/picopass_scene_config.h @@ -23,3 +23,4 @@ ADD_SCENE(picopass, nr_mac_saved, NrMacSaved) ADD_SCENE(picopass, more_info, MoreInfo) ADD_SCENE(picopass, formats, Formats) ADD_SCENE(picopass, acknowledgements, Acknowledgements) +ADD_SCENE(picopass, elite_keygen_attack, EliteKeygenAttack) diff --git a/scenes/picopass_scene_elite_keygen_attack.c b/scenes/picopass_scene_elite_keygen_attack.c new file mode 100644 index 00000000000..fd5e5f6ea72 --- /dev/null +++ b/scenes/picopass_scene_elite_keygen_attack.c @@ -0,0 +1,145 @@ +#include "../picopass_i.h" +#include +#include "../picopass_elite_keygen.h" + +#define PICOPASS_SCENE_DICT_ATTACK_KEYS_BATCH_UPDATE (10) +#define PICOPASS_SCENE_ELITE_KEYGEN_ATTACK_LIMIT (2000) + +NfcCommand picopass_elite_keygen_attack_worker_callback(PicopassPollerEvent event, void* context) { + furi_assert(context); + NfcCommand command = NfcCommandContinue; + + Picopass* picopass = context; + + if(event.type == PicopassPollerEventTypeRequestMode) { + event.data->req_mode.mode = PicopassPollerModeRead; + } else if(event.type == PicopassPollerEventTypeRequestKey) { + uint8_t key[PICOPASS_KEY_LEN] = {}; + bool is_key_provided = false; + if(picopass->dict_attack_ctx.current_key < PICOPASS_SCENE_ELITE_KEYGEN_ATTACK_LIMIT) { + picopass_elite_nextKey(key); + is_key_provided = true; + } + + memcpy(event.data->req_key.key, key, PICOPASS_KEY_LEN); + event.data->req_key.is_elite_key = true; + event.data->req_key.is_key_provided = is_key_provided; + if(is_key_provided) { + picopass->dict_attack_ctx.current_key++; + if(picopass->dict_attack_ctx.current_key % + PICOPASS_SCENE_DICT_ATTACK_KEYS_BATCH_UPDATE == + 0) { + view_dispatcher_send_custom_event( + picopass->view_dispatcher, PicopassCustomEventDictAttackUpdateView); + } + } + } else if( + event.type == PicopassPollerEventTypeSuccess || + event.type == PicopassPollerEventTypeFail || + event.type == PicopassPollerEventTypeAuthFail) { + const PicopassDeviceData* data = picopass_poller_get_data(picopass->poller); + memcpy(&picopass->dev->dev_data, data, sizeof(PicopassDeviceData)); + view_dispatcher_send_custom_event( + picopass->view_dispatcher, PicopassCustomEventPollerSuccess); + } else if(event.type == PicopassPollerEventTypeCardLost) { + picopass->dict_attack_ctx.card_detected = false; + view_dispatcher_send_custom_event( + picopass->view_dispatcher, PicopassCustomEventDictAttackUpdateView); + } else if(event.type == PicopassPollerEventTypeCardDetected) { + picopass->dict_attack_ctx.card_detected = true; + view_dispatcher_send_custom_event( + picopass->view_dispatcher, PicopassCustomEventDictAttackUpdateView); + } + + return command; +} + +static void picopass_scene_elite_keygen_attack_update_view(Picopass* instance) { + if(instance->dict_attack_ctx.card_detected) { + dict_attack_set_card_detected(instance->dict_attack); + dict_attack_set_header(instance->dict_attack, instance->dict_attack_ctx.name); + dict_attack_set_total_dict_keys( + instance->dict_attack, PICOPASS_SCENE_ELITE_KEYGEN_ATTACK_LIMIT); + dict_attack_set_current_dict_key( + instance->dict_attack, instance->dict_attack_ctx.current_key); + } else { + dict_attack_set_card_removed(instance->dict_attack); + } +} + +static void picopass_scene_elite_keygen_attack_callback(void* context) { + Picopass* instance = context; + + view_dispatcher_send_custom_event( + instance->view_dispatcher, PicopassCustomEventDictAttackSkip); +} + +void picopass_scene_elite_keygen_attack_on_enter(void* context) { + Picopass* picopass = context; + dolphin_deed(DolphinDeedNfcRead); + + // Setup dict attack context + uint32_t state = PicopassSceneEliteKeygenAttack; + + picopass->dict = keys_dict_alloc( + PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME, KeysDictModeOpenExisting, PICOPASS_KEY_LEN); + + dict_attack_reset(picopass->dict_attack); + picopass->dict_attack_ctx.card_detected = false; + picopass->dict_attack_ctx.total_keys = PICOPASS_SCENE_ELITE_KEYGEN_ATTACK_LIMIT; + picopass->dict_attack_ctx.current_key = 0; + picopass->dict_attack_ctx.name = "Elite Keygen Attack"; + scene_manager_set_scene_state(picopass->scene_manager, PicopassSceneEliteKeygenAttack, state); + + // Setup view + picopass_scene_elite_keygen_attack_update_view(picopass); + dict_attack_set_callback( + picopass->dict_attack, picopass_scene_elite_keygen_attack_callback, picopass); + + // Start worker + picopass->poller = picopass_poller_alloc(picopass->nfc); + picopass_poller_start( + picopass->poller, picopass_elite_keygen_attack_worker_callback, picopass); + + view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewDictAttack); + picopass_blink_start(picopass); +} + +bool picopass_scene_elite_keygen_attack_on_event(void* context, SceneManagerEvent event) { + Picopass* picopass = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == PicopassCustomEventPollerSuccess) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess); + consumed = true; + } else if(event.event == PicopassCustomEventDictAttackUpdateView) { + picopass_scene_elite_keygen_attack_update_view(picopass); + consumed = true; + } else if(event.event == PicopassCustomEventDictAttackSkip) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess); + consumed = true; + } + } + return consumed; +} + +void picopass_scene_elite_keygen_attack_on_exit(void* context) { + Picopass* picopass = context; + + if(picopass->dict) { + keys_dict_free(picopass->dict); + picopass->dict = NULL; + } + picopass->dict_attack_ctx.current_key = 0; + picopass->dict_attack_ctx.total_keys = 0; + picopass_elite_reset(); + + picopass_poller_stop(picopass->poller); + picopass_poller_free(picopass->poller); + + // Clear view + popup_reset(picopass->popup); + + picopass_blink_stop(picopass); +} diff --git a/scenes/picopass_scene_start.c b/scenes/picopass_scene_start.c index 3fed865f2c3..316576bed50 100644 --- a/scenes/picopass_scene_start.c +++ b/scenes/picopass_scene_start.c @@ -4,6 +4,7 @@ enum SubmenuIndex { SubmenuIndexSaved, SubmenuIndexLoclass, SubmenuIndexAcknowledgements, + SubmenuIndexKeygenAttack, }; void picopass_scene_start_submenu_callback(void* context, uint32_t index) { @@ -26,6 +27,12 @@ void picopass_scene_start_on_enter(void* context) { SubmenuIndexAcknowledgements, picopass_scene_start_submenu_callback, picopass); + submenu_add_item( + submenu, + "Elite Keygen Attack", + SubmenuIndexKeygenAttack, + picopass_scene_start_submenu_callback, + picopass); submenu_set_selected_item( submenu, scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneStart)); @@ -60,6 +67,11 @@ bool picopass_scene_start_on_event(void* context, SceneManagerEvent event) { picopass->scene_manager, PicopassSceneStart, PicopassSceneAcknowledgements); scene_manager_next_scene(picopass->scene_manager, PicopassSceneAcknowledgements); consumed = true; + } else if(event.event == SubmenuIndexKeygenAttack) { + scene_manager_set_scene_state( + picopass->scene_manager, PicopassSceneStart, SubmenuIndexKeygenAttack); + scene_manager_next_scene(picopass->scene_manager, PicopassSceneEliteKeygenAttack); + consumed = true; } }