[FL-3060] New MFC Bruteforce animation (#2190)
* Change the wording in the headers * Add support for text in the progress bar * New MFC key bruteforce screen * Typo fix * nfc: rename Flipper Dict to System Dict * elements: fix types * Display the correct key attack sector Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		| @@ -43,7 +43,7 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) { | ||||
|  | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == SubmenuIndexMfClassicKeys) { | ||||
|             if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) { | ||||
|             if(mf_classic_dict_check_presence(MfClassicDictTypeSystem)) { | ||||
|                 scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeys); | ||||
|             } else { | ||||
|                 scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); | ||||
|   | ||||
| @@ -53,10 +53,10 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt | ||||
|     // Setup view | ||||
|     if(state == DictAttackStateUserDictInProgress) { | ||||
|         worker_state = NfcWorkerStateMfClassicDictAttack; | ||||
|         dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict."); | ||||
|         dict_attack_set_header(nfc->dict_attack, "MF Classic User Dictionary"); | ||||
|         dict = mf_classic_dict_alloc(MfClassicDictTypeUser); | ||||
|  | ||||
|         // If failed to load user dictionary - try flipper dictionary | ||||
|         // If failed to load user dictionary - try the system dictionary | ||||
|         if(!dict) { | ||||
|             FURI_LOG_E(TAG, "User dictionary not found"); | ||||
|             state = DictAttackStateFlipperDictInProgress; | ||||
| @@ -64,11 +64,11 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt | ||||
|     } | ||||
|     if(state == DictAttackStateFlipperDictInProgress) { | ||||
|         worker_state = NfcWorkerStateMfClassicDictAttack; | ||||
|         dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict."); | ||||
|         dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper); | ||||
|         dict_attack_set_header(nfc->dict_attack, "MF Classic System Dictionary"); | ||||
|         dict = mf_classic_dict_alloc(MfClassicDictTypeSystem); | ||||
|         if(!dict) { | ||||
|             FURI_LOG_E(TAG, "Flipper dictionary not found"); | ||||
|             // Pass through to let worker handle the failure | ||||
|             // Pass through to let the worker handle the failure | ||||
|         } | ||||
|     } | ||||
|     // Free previous dictionary | ||||
| @@ -153,6 +153,15 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent | ||||
|                 nfc_worker_stop(nfc->worker); | ||||
|                 consumed = true; | ||||
|             } | ||||
|         } else if(event.event == NfcWorkerEventKeyAttackStart) { | ||||
|             dict_attack_set_key_attack( | ||||
|                 nfc->dict_attack, | ||||
|                 true, | ||||
|                 nfc->dev->dev_data.mf_classic_dict_attack_data.current_sector); | ||||
|         } else if(event.event == NfcWorkerEventKeyAttackStop) { | ||||
|             dict_attack_set_key_attack(nfc->dict_attack, false, 0); | ||||
|         } else if(event.event == NfcWorkerEventKeyAttackNextSector) { | ||||
|             dict_attack_inc_key_attack_current_sector(nfc->dict_attack); | ||||
|         } | ||||
|     } else if(event.type == SceneManagerEventTypeBack) { | ||||
|         scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); | ||||
|   | ||||
| @@ -12,7 +12,7 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { | ||||
|  | ||||
|     // Load flipper dict keys total | ||||
|     uint32_t flipper_dict_keys_total = 0; | ||||
|     MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper); | ||||
|     MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeSystem); | ||||
|     if(dict) { | ||||
|         flipper_dict_keys_total = mf_classic_dict_get_total_keys(dict); | ||||
|         mf_classic_dict_free(dict); | ||||
| @@ -26,11 +26,11 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { | ||||
|     } | ||||
|  | ||||
|     widget_add_string_element( | ||||
|         nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Mifare Classic Keys"); | ||||
|         nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MIFARE Classic Keys"); | ||||
|     char temp_str[32]; | ||||
|     snprintf(temp_str, sizeof(temp_str), "Flipper list: %lu", flipper_dict_keys_total); | ||||
|     snprintf(temp_str, sizeof(temp_str), "System dict: %lu", flipper_dict_keys_total); | ||||
|     widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str); | ||||
|     snprintf(temp_str, sizeof(temp_str), "User list: %lu", user_dict_keys_total); | ||||
|     snprintf(temp_str, sizeof(temp_str), "User dict: %lu", user_dict_keys_total); | ||||
|     widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); | ||||
|     widget_add_button_element( | ||||
|         nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); | ||||
|   | ||||
| @@ -91,7 +91,7 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { | ||||
|             DOLPHIN_DEED(DolphinDeedNfcReadSuccess); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcWorkerEventReadMfClassicDictAttackRequired) { | ||||
|             if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) { | ||||
|             if(mf_classic_dict_check_presence(MfClassicDictTypeSystem)) { | ||||
|                 scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicDictAttack); | ||||
|             } else { | ||||
|                 scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); | ||||
|   | ||||
| @@ -24,6 +24,8 @@ typedef struct { | ||||
|     uint8_t keys_found; | ||||
|     uint16_t dict_keys_total; | ||||
|     uint16_t dict_keys_current; | ||||
|     bool is_key_attack; | ||||
|     uint8_t key_attack_current_sector; | ||||
| } DictAttackViewModel; | ||||
|  | ||||
| static void dict_attack_draw_callback(Canvas* canvas, void* model) { | ||||
| @@ -36,10 +38,19 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { | ||||
|             canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); | ||||
|     } else if(m->state == DictAttackStateRead) { | ||||
|         char draw_str[32] = {}; | ||||
|         canvas_set_font(canvas, FontPrimary); | ||||
|         canvas_draw_str_aligned( | ||||
|             canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
|         canvas_draw_str_aligned( | ||||
|             canvas, 64, 0, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); | ||||
|         if(m->is_key_attack) { | ||||
|             snprintf( | ||||
|                 draw_str, | ||||
|                 sizeof(draw_str), | ||||
|                 "Reuse key check for sector: %d", | ||||
|                 m->key_attack_current_sector); | ||||
|         } else { | ||||
|             snprintf(draw_str, sizeof(draw_str), "Unlocking sector: %d", m->sector_current); | ||||
|         } | ||||
|         canvas_draw_str_aligned(canvas, 0, 10, AlignLeft, AlignTop, draw_str); | ||||
|         float dict_progress = m->dict_keys_total == 0 ? | ||||
|                                   0 : | ||||
|                                   (float)(m->dict_keys_current) / (float)(m->dict_keys_total); | ||||
| @@ -49,13 +60,14 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { | ||||
|         if(progress > 1.0) { | ||||
|             progress = 1.0; | ||||
|         } | ||||
|         elements_progress_bar(canvas, 5, 15, 120, progress); | ||||
|         snprintf(draw_str, sizeof(draw_str), "%d/%d", m->dict_keys_current, m->dict_keys_total); | ||||
|         elements_progress_bar_with_text(canvas, 0, 20, 128, dict_progress, draw_str); | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
|         snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); | ||||
|         canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); | ||||
|         canvas_draw_str_aligned(canvas, 0, 33, AlignLeft, AlignTop, draw_str); | ||||
|         snprintf( | ||||
|             draw_str, sizeof(draw_str), "Sectors Read: %d/%d", m->sectors_read, m->sectors_total); | ||||
|         canvas_draw_str_aligned(canvas, 1, 40, AlignLeft, AlignTop, draw_str); | ||||
|         canvas_draw_str_aligned(canvas, 0, 43, AlignLeft, AlignTop, draw_str); | ||||
|     } | ||||
|     elements_button_center(canvas, "Skip"); | ||||
| } | ||||
| @@ -113,6 +125,7 @@ void dict_attack_reset(DictAttack* dict_attack) { | ||||
|             model->keys_found = 0; | ||||
|             model->dict_keys_total = 0; | ||||
|             model->dict_keys_current = 0; | ||||
|             model->is_key_attack = false; | ||||
|             furi_string_reset(model->header); | ||||
|         }, | ||||
|         false); | ||||
| @@ -235,3 +248,28 @@ void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tri | ||||
|         }, | ||||
|         true); | ||||
| } | ||||
|  | ||||
| void dict_attack_set_key_attack(DictAttack* dict_attack, bool is_key_attack, uint8_t sector) { | ||||
|     furi_assert(dict_attack); | ||||
|     with_view_model( | ||||
|         dict_attack->view, | ||||
|         DictAttackViewModel * model, | ||||
|         { | ||||
|             model->is_key_attack = is_key_attack; | ||||
|             model->key_attack_current_sector = sector; | ||||
|         }, | ||||
|         true); | ||||
| } | ||||
|  | ||||
| void dict_attack_inc_key_attack_current_sector(DictAttack* dict_attack) { | ||||
|     furi_assert(dict_attack); | ||||
|     with_view_model( | ||||
|         dict_attack->view, | ||||
|         DictAttackViewModel * model, | ||||
|         { | ||||
|             if(model->key_attack_current_sector < model->sectors_total) { | ||||
|                 model->key_attack_current_sector++; | ||||
|             } | ||||
|         }, | ||||
|         true); | ||||
| } | ||||
|   | ||||
| @@ -38,3 +38,7 @@ void dict_attack_inc_keys_found(DictAttack* dict_attack); | ||||
| void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total); | ||||
|  | ||||
| void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried); | ||||
|  | ||||
| void dict_attack_set_key_attack(DictAttack* dict_attack, bool is_key_attack, uint8_t sector); | ||||
|  | ||||
| void dict_attack_inc_key_attack_current_sector(DictAttack* dict_attack); | ||||
		Reference in New Issue
	
	Block a user