#include "../nfc_i.h" typedef enum { DictAttackStateIdle, DictAttackStateUserDictInProgress, DictAttackStateFlipperDictInProgress, } DictAttackState; bool nfc_dict_attack_worker_callback(NfcWorkerEvent event, void* context) { furi_assert(context); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, event); return true; } void nfc_dict_attack_dict_attack_result_callback(void* context) { furi_assert(context); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventDictAttackSkip); } static void nfc_scene_mf_classic_dict_attack_update_view(Nfc* nfc) { MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; uint8_t sectors_read = 0; uint8_t keys_found = 0; // Calculate found keys and read sectors mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found); dict_attack_set_keys_found(nfc->dict_attack, keys_found); dict_attack_set_sector_read(nfc->dict_attack, sectors_read); } static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackState state) { MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; NfcWorkerState worker_state = NfcWorkerStateReady; // Identify scene state if(state == DictAttackStateIdle) { if(mf_classic_dict_check_presence(MfClassicDictTypeUser)) { state = DictAttackStateUserDictInProgress; } else { state = DictAttackStateFlipperDictInProgress; } } else if(state == DictAttackStateUserDictInProgress) { state = DictAttackStateFlipperDictInProgress; } // Setup view if(state == DictAttackStateUserDictInProgress) { worker_state = NfcWorkerStateMfClassicUserDictAttack; dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict."); } else if(state == DictAttackStateFlipperDictInProgress) { worker_state = NfcWorkerStateMfClassicFlipperDictAttack; dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict."); } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfClassicDictAttack, state); dict_attack_set_callback(nfc->dict_attack, nfc_dict_attack_dict_attack_result_callback, nfc); dict_attack_set_current_sector(nfc->dict_attack, 0); dict_attack_set_card_detected(nfc->dict_attack, data->type); nfc_scene_mf_classic_dict_attack_update_view(nfc); nfc_worker_start( nfc->worker, worker_state, &nfc->dev->dev_data, nfc_dict_attack_worker_callback, nfc); } void nfc_scene_mf_classic_dict_attack_on_enter(void* context) { Nfc* nfc = context; nfc_scene_mf_classic_dict_attack_prepare_view(nfc, DictAttackStateIdle); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDictAttack); nfc_blink_start(nfc); } bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; bool consumed = false; uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicDictAttack); if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcWorkerEventSuccess) { if(state == DictAttackStateUserDictInProgress) { nfc_worker_stop(nfc->worker); nfc_scene_mf_classic_dict_attack_prepare_view(nfc, state); consumed = true; } else { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess); consumed = true; } } else if(event.event == NfcWorkerEventAborted) { if(state == DictAttackStateUserDictInProgress) { nfc_scene_mf_classic_dict_attack_prepare_view(nfc, state); consumed = true; } else { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess); consumed = true; } } else if(event.event == NfcWorkerEventCardDetected) { dict_attack_set_card_detected(nfc->dict_attack, data->type); consumed = true; } else if(event.event == NfcWorkerEventNoCardDetected) { dict_attack_set_card_removed(nfc->dict_attack); consumed = true; } else if(event.event == NfcWorkerEventFoundKeyA) { dict_attack_inc_keys_found(nfc->dict_attack); consumed = true; } else if(event.event == NfcWorkerEventFoundKeyB) { dict_attack_inc_keys_found(nfc->dict_attack); consumed = true; } else if(event.event == NfcWorkerEventNewSector) { nfc_scene_mf_classic_dict_attack_update_view(nfc); dict_attack_inc_current_sector(nfc->dict_attack); consumed = true; } else if(event.event == NfcCustomEventDictAttackSkip) { if(state == DictAttackStateUserDictInProgress) { nfc_worker_stop(nfc->worker); consumed = true; } else if(state == DictAttackStateFlipperDictInProgress) { nfc_worker_stop(nfc->worker); consumed = true; } } } else if(event.type == SceneManagerEventTypeBack) { scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); consumed = true; } return consumed; } void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { Nfc* nfc = context; // Stop worker nfc_worker_stop(nfc->worker); dict_attack_reset(nfc->dict_attack); nfc_blink_stop(nfc); }