nfc: make dict attack more interactive (#1462)
* nfc: deduplify dict attack worker code * nfc: make dict attack more interactive Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									284c56718b
								
							
						
					
					
						commit
						3ee93e1a82
					
				| @ -1,5 +1,7 @@ | |||||||
| #include "../nfc_i.h" | #include "../nfc_i.h" | ||||||
| 
 | 
 | ||||||
|  | #define TAG "NfcMfClassicDictAttack" | ||||||
|  | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     DictAttackStateIdle, |     DictAttackStateIdle, | ||||||
|     DictAttackStateUserDictInProgress, |     DictAttackStateUserDictInProgress, | ||||||
| @ -32,7 +34,9 @@ static void nfc_scene_mf_classic_dict_attack_update_view(Nfc* nfc) { | |||||||
| 
 | 
 | ||||||
| static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackState state) { | static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackState state) { | ||||||
|     MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; |     MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; | ||||||
|  |     NfcMfClassicDictAttackData* dict_attack_data = &nfc->dev->dev_data.mf_classic_dict_attack_data; | ||||||
|     NfcWorkerState worker_state = NfcWorkerStateReady; |     NfcWorkerState worker_state = NfcWorkerStateReady; | ||||||
|  |     MfClassicDict* dict = NULL; | ||||||
| 
 | 
 | ||||||
|     // Identify scene state
 |     // Identify scene state
 | ||||||
|     if(state == DictAttackStateIdle) { |     if(state == DictAttackStateIdle) { | ||||||
| @ -47,16 +51,36 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt | |||||||
| 
 | 
 | ||||||
|     // Setup view
 |     // Setup view
 | ||||||
|     if(state == DictAttackStateUserDictInProgress) { |     if(state == DictAttackStateUserDictInProgress) { | ||||||
|         worker_state = NfcWorkerStateMfClassicUserDictAttack; |         worker_state = NfcWorkerStateMfClassicDictAttack; | ||||||
|         dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict."); |         dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict."); | ||||||
|     } else if(state == DictAttackStateFlipperDictInProgress) { |         dict = mf_classic_dict_alloc(MfClassicDictTypeUser); | ||||||
|         worker_state = NfcWorkerStateMfClassicFlipperDictAttack; | 
 | ||||||
|         dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict."); |         // If failed to load user dictionary - try flipper dictionary
 | ||||||
|  |         if(!dict) { | ||||||
|  |             FURI_LOG_E(TAG, "User dictionary not found"); | ||||||
|  |             state = DictAttackStateFlipperDictInProgress; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |     if(state == DictAttackStateFlipperDictInProgress) { | ||||||
|  |         worker_state = NfcWorkerStateMfClassicDictAttack; | ||||||
|  |         dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict."); | ||||||
|  |         dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper); | ||||||
|  |         if(!dict) { | ||||||
|  |             FURI_LOG_E(TAG, "Flipper dictionary not found"); | ||||||
|  |             // Pass through to let worker handle the failure
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     // Free previous dictionary
 | ||||||
|  |     if(dict_attack_data->dict) { | ||||||
|  |         mf_classic_dict_free(dict_attack_data->dict); | ||||||
|  |     } | ||||||
|  |     dict_attack_data->dict = dict; | ||||||
|     scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfClassicDictAttack, state); |     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_callback(nfc->dict_attack, nfc_dict_attack_dict_attack_result_callback, nfc); | ||||||
|     dict_attack_set_current_sector(nfc->dict_attack, 0); |     dict_attack_set_current_sector(nfc->dict_attack, 0); | ||||||
|     dict_attack_set_card_detected(nfc->dict_attack, data->type); |     dict_attack_set_card_detected(nfc->dict_attack, data->type); | ||||||
|  |     dict_attack_set_total_dict_keys( | ||||||
|  |         nfc->dict_attack, dict ? mf_classic_dict_get_total_keys(dict) : 0); | ||||||
|     nfc_scene_mf_classic_dict_attack_update_view(nfc); |     nfc_scene_mf_classic_dict_attack_update_view(nfc); | ||||||
|     nfc_worker_start( |     nfc_worker_start( | ||||||
|         nfc->worker, worker_state, &nfc->dev->dev_data, nfc_dict_attack_worker_callback, nfc); |         nfc->worker, worker_state, &nfc->dev->dev_data, nfc_dict_attack_worker_callback, nfc); | ||||||
| @ -112,6 +136,10 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent | |||||||
|             nfc_scene_mf_classic_dict_attack_update_view(nfc); |             nfc_scene_mf_classic_dict_attack_update_view(nfc); | ||||||
|             dict_attack_inc_current_sector(nfc->dict_attack); |             dict_attack_inc_current_sector(nfc->dict_attack); | ||||||
|             consumed = true; |             consumed = true; | ||||||
|  |         } else if(event.event == NfcWorkerEventNewDictKeyBatch) { | ||||||
|  |             nfc_scene_mf_classic_dict_attack_update_view(nfc); | ||||||
|  |             dict_attack_inc_current_dict_key(nfc->dict_attack, NFC_DICT_KEY_BATCH_SIZE); | ||||||
|  |             consumed = true; | ||||||
|         } else if(event.event == NfcCustomEventDictAttackSkip) { |         } else if(event.event == NfcCustomEventDictAttackSkip) { | ||||||
|             if(state == DictAttackStateUserDictInProgress) { |             if(state == DictAttackStateUserDictInProgress) { | ||||||
|                 nfc_worker_stop(nfc->worker); |                 nfc_worker_stop(nfc->worker); | ||||||
| @ -130,8 +158,13 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent | |||||||
| 
 | 
 | ||||||
| void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { | void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { | ||||||
|     Nfc* nfc = context; |     Nfc* nfc = context; | ||||||
|  |     NfcMfClassicDictAttackData* dict_attack_data = &nfc->dev->dev_data.mf_classic_dict_attack_data; | ||||||
|     // Stop worker
 |     // Stop worker
 | ||||||
|     nfc_worker_stop(nfc->worker); |     nfc_worker_stop(nfc->worker); | ||||||
|  |     if(dict_attack_data->dict) { | ||||||
|  |         mf_classic_dict_free(dict_attack_data->dict); | ||||||
|  |         dict_attack_data->dict = NULL; | ||||||
|  |     } | ||||||
|     dict_attack_reset(nfc->dict_attack); |     dict_attack_reset(nfc->dict_attack); | ||||||
|     nfc_blink_stop(nfc); |     nfc_blink_stop(nfc); | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,6 +23,8 @@ typedef struct { | |||||||
|     uint8_t sector_current; |     uint8_t sector_current; | ||||||
|     uint8_t keys_total; |     uint8_t keys_total; | ||||||
|     uint8_t keys_found; |     uint8_t keys_found; | ||||||
|  |     uint16_t dict_keys_total; | ||||||
|  |     uint16_t dict_keys_current; | ||||||
| } DictAttackViewModel; | } DictAttackViewModel; | ||||||
| 
 | 
 | ||||||
| static void dict_attack_draw_callback(Canvas* canvas, void* model) { | static void dict_attack_draw_callback(Canvas* canvas, void* model) { | ||||||
| @ -38,8 +40,15 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { | |||||||
|         canvas_set_font(canvas, FontPrimary); |         canvas_set_font(canvas, FontPrimary); | ||||||
|         canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, string_get_cstr(m->header)); |         canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, string_get_cstr(m->header)); | ||||||
|         canvas_set_font(canvas, FontSecondary); |         canvas_set_font(canvas, FontSecondary); | ||||||
|         float progress = |         float dict_progress = m->dict_keys_total == 0 ? | ||||||
|             m->sectors_total == 0 ? 0 : (float)(m->sector_current) / (float)(m->sectors_total); |                                   0 : | ||||||
|  |                                   (float)(m->dict_keys_current) / (float)(m->dict_keys_total); | ||||||
|  |         float progress = m->sectors_total == 0 ? 0 : | ||||||
|  |                                                  ((float)(m->sector_current) + dict_progress) / | ||||||
|  |                                                      (float)(m->sectors_total); | ||||||
|  |         if(progress > 1.0) { | ||||||
|  |             progress = 1.0; | ||||||
|  |         } | ||||||
|         elements_progress_bar(canvas, 5, 15, 120, progress); |         elements_progress_bar(canvas, 5, 15, 120, progress); | ||||||
|         canvas_set_font(canvas, FontSecondary); |         canvas_set_font(canvas, FontSecondary); | ||||||
|         snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); |         snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); | ||||||
| @ -100,6 +109,8 @@ void dict_attack_reset(DictAttack* dict_attack) { | |||||||
|             model->sector_current = 0; |             model->sector_current = 0; | ||||||
|             model->keys_total = 0; |             model->keys_total = 0; | ||||||
|             model->keys_found = 0; |             model->keys_found = 0; | ||||||
|  |             model->dict_keys_total = 0; | ||||||
|  |             model->dict_keys_current = 0; | ||||||
|             string_reset(model->header); |             string_reset(model->header); | ||||||
|             return false; |             return false; | ||||||
|         }); |         }); | ||||||
| @ -171,6 +182,7 @@ void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) { | |||||||
|     with_view_model( |     with_view_model( | ||||||
|         dict_attack->view, (DictAttackViewModel * model) { |         dict_attack->view, (DictAttackViewModel * model) { | ||||||
|             model->sector_current = curr_sec; |             model->sector_current = curr_sec; | ||||||
|  |             model->dict_keys_current = 0; | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
| @ -181,6 +193,7 @@ void dict_attack_inc_current_sector(DictAttack* dict_attack) { | |||||||
|         dict_attack->view, (DictAttackViewModel * model) { |         dict_attack->view, (DictAttackViewModel * model) { | ||||||
|             if(model->sector_current < model->sectors_total) { |             if(model->sector_current < model->sectors_total) { | ||||||
|                 model->sector_current++; |                 model->sector_current++; | ||||||
|  |                 model->dict_keys_current = 0; | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| @ -196,3 +209,23 @@ void dict_attack_inc_keys_found(DictAttack* dict_attack) { | |||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total) { | ||||||
|  |     furi_assert(dict_attack); | ||||||
|  |     with_view_model( | ||||||
|  |         dict_attack->view, (DictAttackViewModel * model) { | ||||||
|  |             model->dict_keys_total = dict_keys_total; | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried) { | ||||||
|  |     furi_assert(dict_attack); | ||||||
|  |     with_view_model( | ||||||
|  |         dict_attack->view, (DictAttackViewModel * model) { | ||||||
|  |             if(model->dict_keys_current + keys_tried < model->dict_keys_total) { | ||||||
|  |                 model->dict_keys_current += keys_tried; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | |||||||
| @ -34,3 +34,7 @@ void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec); | |||||||
| void dict_attack_inc_current_sector(DictAttack* dict_attack); | void dict_attack_inc_current_sector(DictAttack* dict_attack); | ||||||
| 
 | 
 | ||||||
| void dict_attack_inc_keys_found(DictAttack* dict_attack); | 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); | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| #include <dialogs/dialogs.h> | #include <dialogs/dialogs.h> | ||||||
| 
 | 
 | ||||||
| #include <furi_hal_nfc.h> | #include <furi_hal_nfc.h> | ||||||
|  | #include <lib/nfc/helpers/mf_classic_dict.h> | ||||||
| #include <lib/nfc/protocols/emv.h> | #include <lib/nfc/protocols/emv.h> | ||||||
| #include <lib/nfc/protocols/mifare_ultralight.h> | #include <lib/nfc/protocols/mifare_ultralight.h> | ||||||
| #include <lib/nfc/protocols/mifare_classic.h> | #include <lib/nfc/protocols/mifare_classic.h> | ||||||
| @ -13,6 +14,7 @@ | |||||||
| 
 | 
 | ||||||
| #define NFC_DEV_NAME_MAX_LEN 22 | #define NFC_DEV_NAME_MAX_LEN 22 | ||||||
| #define NFC_READER_DATA_MAX_SIZE 64 | #define NFC_READER_DATA_MAX_SIZE 64 | ||||||
|  | #define NFC_DICT_KEY_BATCH_SIZE 50 | ||||||
| 
 | 
 | ||||||
| #define NFC_APP_FOLDER ANY_PATH("nfc") | #define NFC_APP_FOLDER ANY_PATH("nfc") | ||||||
| #define NFC_APP_EXTENSION ".nfc" | #define NFC_APP_EXTENSION ".nfc" | ||||||
| @ -41,10 +43,17 @@ typedef struct { | |||||||
|     uint16_t size; |     uint16_t size; | ||||||
| } NfcReaderRequestData; | } NfcReaderRequestData; | ||||||
| 
 | 
 | ||||||
|  | typedef struct { | ||||||
|  |     MfClassicDict* dict; | ||||||
|  | } NfcMfClassicDictAttackData; | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     FuriHalNfcDevData nfc_data; |     FuriHalNfcDevData nfc_data; | ||||||
|     NfcProtocol protocol; |     NfcProtocol protocol; | ||||||
|     NfcReaderRequestData reader_data; |     union { | ||||||
|  |         NfcReaderRequestData reader_data; | ||||||
|  |         NfcMfClassicDictAttackData mf_classic_dict_attack_data; | ||||||
|  |     }; | ||||||
|     union { |     union { | ||||||
|         EmvData emv_data; |         EmvData emv_data; | ||||||
|         MfUltralightData mf_ul_data; |         MfUltralightData mf_ul_data; | ||||||
|  | |||||||
| @ -101,10 +101,8 @@ int32_t nfc_worker_task(void* context) { | |||||||
|         nfc_worker_emulate_mf_ultralight(nfc_worker); |         nfc_worker_emulate_mf_ultralight(nfc_worker); | ||||||
|     } else if(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { |     } else if(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { | ||||||
|         nfc_worker_emulate_mf_classic(nfc_worker); |         nfc_worker_emulate_mf_classic(nfc_worker); | ||||||
|     } else if(nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) { |     } else if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) { | ||||||
|         nfc_worker_mf_classic_dict_attack(nfc_worker, MfClassicDictTypeUser); |         nfc_worker_mf_classic_dict_attack(nfc_worker); | ||||||
|     } else if(nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack) { |  | ||||||
|         nfc_worker_mf_classic_dict_attack(nfc_worker, MfClassicDictTypeFlipper); |  | ||||||
|     } |     } | ||||||
|     furi_hal_nfc_sleep(); |     furi_hal_nfc_sleep(); | ||||||
|     nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); |     nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); | ||||||
| @ -397,11 +395,13 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType type) { | void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | ||||||
|     furi_assert(nfc_worker); |     furi_assert(nfc_worker); | ||||||
|     furi_assert(nfc_worker->callback); |     furi_assert(nfc_worker->callback); | ||||||
| 
 | 
 | ||||||
|     MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; |     MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; | ||||||
|  |     NfcMfClassicDictAttackData* dict_attack_data = | ||||||
|  |         &nfc_worker->dev_data->mf_classic_dict_attack_data; | ||||||
|     uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); |     uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); | ||||||
|     uint64_t key = 0; |     uint64_t key = 0; | ||||||
|     FuriHalNfcTxRxContext tx_rx = {}; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
| @ -409,15 +409,17 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType | |||||||
|     bool card_removed_notified = false; |     bool card_removed_notified = false; | ||||||
| 
 | 
 | ||||||
|     // Load dictionary
 |     // Load dictionary
 | ||||||
|     MfClassicDict* dict = mf_classic_dict_alloc(type); |     MfClassicDict* dict = dict_attack_data->dict; | ||||||
|     if(!dict) { |     if(!dict) { | ||||||
|         FURI_LOG_E(TAG, "Dictionary not found"); |         FURI_LOG_E(TAG, "Dictionary not found"); | ||||||
|         nfc_worker->callback(NfcWorkerEventNoDictFound, nfc_worker->context); |         nfc_worker->callback(NfcWorkerEventNoDictFound, nfc_worker->context); | ||||||
|         mf_classic_dict_free(dict); |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     FURI_LOG_D(TAG, "Start Dictionary attack"); |     FURI_LOG_D( | ||||||
|  |         TAG, | ||||||
|  |         "Start Dictionary attack, Key Count %d", | ||||||
|  |         mf_classic_dict_get_total_keys(dict)); | ||||||
|     for(size_t i = 0; i < total_sectors; i++) { |     for(size_t i = 0; i < total_sectors; i++) { | ||||||
|         FURI_LOG_I(TAG, "Sector %d", i); |         FURI_LOG_I(TAG, "Sector %d", i); | ||||||
|         nfc_worker->callback(NfcWorkerEventNewSector, nfc_worker->context); |         nfc_worker->callback(NfcWorkerEventNewSector, nfc_worker->context); | ||||||
| @ -425,7 +427,11 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType | |||||||
|         if(mf_classic_is_sector_read(data, i)) continue; |         if(mf_classic_is_sector_read(data, i)) continue; | ||||||
|         bool is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA); |         bool is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA); | ||||||
|         bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); |         bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); | ||||||
|  |         uint16_t key_index = 0; | ||||||
|         while(mf_classic_dict_get_next_key(dict, &key)) { |         while(mf_classic_dict_get_next_key(dict, &key)) { | ||||||
|  |             if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) { | ||||||
|  |                 nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context); | ||||||
|  |             } | ||||||
|             furi_hal_nfc_sleep(); |             furi_hal_nfc_sleep(); | ||||||
|             if(furi_hal_nfc_activate_nfca(200, NULL)) { |             if(furi_hal_nfc_activate_nfca(200, NULL)) { | ||||||
|                 furi_hal_nfc_sleep(); |                 furi_hal_nfc_sleep(); | ||||||
| @ -456,8 +462,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if(is_key_a_found && is_key_b_found) break; |                 if(is_key_a_found && is_key_b_found) break; | ||||||
|                 if(!((nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) || |                 if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) | ||||||
|                      (nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack))) |  | ||||||
|                     break; |                     break; | ||||||
|             } else { |             } else { | ||||||
|                 if(!card_removed_notified) { |                 if(!card_removed_notified) { | ||||||
| @ -465,20 +470,16 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType | |||||||
|                     card_removed_notified = true; |                     card_removed_notified = true; | ||||||
|                     card_found_notified = false; |                     card_found_notified = false; | ||||||
|                 } |                 } | ||||||
|                 if(!((nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) || |                 if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) | ||||||
|                      (nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack))) |  | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if(!((nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) || |         if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) | ||||||
|              (nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack))) |  | ||||||
|             break; |             break; | ||||||
|         mf_classic_read_sector(&tx_rx, data, i); |         mf_classic_read_sector(&tx_rx, data, i); | ||||||
|         mf_classic_dict_rewind(dict); |         mf_classic_dict_rewind(dict); | ||||||
|     } |     } | ||||||
|     mf_classic_dict_free(dict); |     if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) { | ||||||
|     if((nfc_worker->state == NfcWorkerStateMfClassicUserDictAttack) || |  | ||||||
|        (nfc_worker->state == NfcWorkerStateMfClassicFlipperDictAttack)) { |  | ||||||
|         nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); |         nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); | ||||||
|     } else { |     } else { | ||||||
|         nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context); |         nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context); | ||||||
|  | |||||||
| @ -14,8 +14,7 @@ typedef enum { | |||||||
|     NfcWorkerStateUidEmulate, |     NfcWorkerStateUidEmulate, | ||||||
|     NfcWorkerStateMfUltralightEmulate, |     NfcWorkerStateMfUltralightEmulate, | ||||||
|     NfcWorkerStateMfClassicEmulate, |     NfcWorkerStateMfClassicEmulate, | ||||||
|     NfcWorkerStateMfClassicUserDictAttack, |     NfcWorkerStateMfClassicDictAttack, | ||||||
|     NfcWorkerStateMfClassicFlipperDictAttack, |  | ||||||
|     // Debug
 |     // Debug
 | ||||||
|     NfcWorkerStateEmulateApdu, |     NfcWorkerStateEmulateApdu, | ||||||
|     NfcWorkerStateField, |     NfcWorkerStateField, | ||||||
| @ -49,6 +48,7 @@ typedef enum { | |||||||
|     // Mifare Classic events
 |     // Mifare Classic events
 | ||||||
|     NfcWorkerEventNoDictFound, |     NfcWorkerEventNoDictFound, | ||||||
|     NfcWorkerEventNewSector, |     NfcWorkerEventNewSector, | ||||||
|  |     NfcWorkerEventNewDictKeyBatch, | ||||||
|     NfcWorkerEventFoundKeyA, |     NfcWorkerEventFoundKeyA, | ||||||
|     NfcWorkerEventFoundKeyB, |     NfcWorkerEventFoundKeyB, | ||||||
| } NfcWorkerEvent; | } NfcWorkerEvent; | ||||||
|  | |||||||
| @ -13,7 +13,6 @@ | |||||||
| #include <lib/nfc/protocols/mifare_desfire.h> | #include <lib/nfc/protocols/mifare_desfire.h> | ||||||
| #include <lib/nfc/protocols/nfca.h> | #include <lib/nfc/protocols/nfca.h> | ||||||
| 
 | 
 | ||||||
| #include "helpers/mf_classic_dict.h" |  | ||||||
| #include "helpers/nfc_debug_pcap.h" | #include "helpers/nfc_debug_pcap.h" | ||||||
| 
 | 
 | ||||||
| struct NfcWorker { | struct NfcWorker { | ||||||
| @ -43,6 +42,6 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker); | |||||||
| 
 | 
 | ||||||
| void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker); | void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker); | ||||||
| 
 | 
 | ||||||
| void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker, MfClassicDictType type); | void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker); | ||||||
| 
 | 
 | ||||||
| void nfc_worker_emulate_apdu(NfcWorker* nfc_worker); | void nfc_worker_emulate_apdu(NfcWorker* nfc_worker); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Fedor Indutny
						Fedor Indutny