NFC: Support reading Mifare Classic key B from sector trailer, reading sector with B key where A key can't read block, Nfc Magic app not using NFC folder by default (in file select) (#2437)
* NFC: Support reading Mifare Classic key B from sector trailer and reusing it for other sectors * NFC: Fix my pointer typo * NFC: Fix reading sector with B key where A key can't read block (fixes #2413) and fix Nfc Magic app not using NFC folder by default (in file select) * NFC: Fix strange bug Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									9819306731
								
							
						
					
					
						commit
						eb5dae1cda
					
				| @ -11,6 +11,10 @@ void nfc_magic_scene_file_select_on_enter(void* context) { | ||||
|     // Process file_select return
 | ||||
|     nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic); | ||||
| 
 | ||||
|     if(!furi_string_size(nfc_magic->nfc_dev->load_path)) { | ||||
|         furi_string_set_str(nfc_magic->nfc_dev->load_path, NFC_APP_FOLDER); | ||||
|     } | ||||
| 
 | ||||
|     if(nfc_file_select(nfc_magic->nfc_dev)) { | ||||
|         if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) { | ||||
|             scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); | ||||
|  | ||||
| @ -1892,7 +1892,7 @@ Function,+,menu_free,void,Menu* | ||||
| Function,+,menu_get_view,View*,Menu* | ||||
| Function,+,menu_reset,void,Menu* | ||||
| Function,+,menu_set_selected_item,void,"Menu*, uint32_t" | ||||
| Function,-,mf_classic_auth_attempt,_Bool,"FuriHalNfcTxRxContext*, MfClassicAuthContext*, uint64_t" | ||||
| Function,-,mf_classic_auth_attempt,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, MfClassicAuthContext*, uint64_t" | ||||
| Function,-,mf_classic_auth_init_context,void,"MfClassicAuthContext*, uint8_t" | ||||
| Function,-,mf_classic_auth_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t" | ||||
| Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey" | ||||
|  | ||||
| 
 | 
| @ -569,6 +569,32 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool nfc_worker_mf_get_b_key_from_sector_trailer( | ||||
|     FuriHalNfcTxRxContext* tx_rx, | ||||
|     uint16_t sector, | ||||
|     uint64_t key, | ||||
|     uint64_t* found_key) { | ||||
|     // Some access conditions allow reading B key via A key
 | ||||
| 
 | ||||
|     uint8_t block = mf_classic_get_sector_trailer_block_num_by_sector(sector); | ||||
| 
 | ||||
|     Crypto1 crypto = {}; | ||||
|     MfClassicBlock block_tmp = {}; | ||||
|     MfClassicAuthContext auth_context = {.sector = sector, .key_a = MF_CLASSIC_NO_KEY, .key_b = 0}; | ||||
| 
 | ||||
|     furi_hal_nfc_sleep(); | ||||
| 
 | ||||
|     if(mf_classic_auth_attempt(tx_rx, &crypto, &auth_context, key)) { | ||||
|         if(mf_classic_read_block(tx_rx, &crypto, block, &block_tmp)) { | ||||
|             *found_key = nfc_util_bytes2num(&block_tmp.value[10], sizeof(uint8_t) * 6); | ||||
| 
 | ||||
|             return *found_key; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| static void nfc_worker_mf_classic_key_attack( | ||||
|     NfcWorker* nfc_worker, | ||||
|     uint64_t key, | ||||
| @ -614,6 +640,16 @@ static void nfc_worker_mf_classic_key_attack( | ||||
|                     mf_classic_set_key_found(data, i, MfClassicKeyA, key); | ||||
|                     FURI_LOG_D(TAG, "Key found"); | ||||
|                     nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); | ||||
| 
 | ||||
|                     uint64_t found_key; | ||||
|                     if(nfc_worker_mf_get_b_key_from_sector_trailer(tx_rx, i, key, &found_key)) { | ||||
|                         FURI_LOG_D(TAG, "Found B key via reading sector %d", i); | ||||
|                         mf_classic_set_key_found(data, i, MfClassicKeyB, found_key); | ||||
| 
 | ||||
|                         if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) { | ||||
|                             nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) { | ||||
| @ -705,6 +741,19 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | ||||
|                         mf_classic_set_key_found(data, i, MfClassicKeyA, key); | ||||
|                         FURI_LOG_D(TAG, "Key found"); | ||||
|                         nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); | ||||
| 
 | ||||
|                         uint64_t found_key; | ||||
|                         if(nfc_worker_mf_get_b_key_from_sector_trailer( | ||||
|                                &tx_rx, i, key, &found_key)) { | ||||
|                             FURI_LOG_D(TAG, "Found B key via reading sector %d", i); | ||||
|                             mf_classic_set_key_found(data, i, MfClassicKeyB, found_key); | ||||
| 
 | ||||
|                             if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) { | ||||
|                                 nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); | ||||
|                             } | ||||
| 
 | ||||
|                             nfc_worker_mf_classic_key_attack(nfc_worker, found_key, &tx_rx, i + 1); | ||||
|                         } | ||||
|                         nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); | ||||
|                     } | ||||
|                     furi_hal_nfc_sleep(); | ||||
|  | ||||
| @ -541,6 +541,7 @@ bool mf_classic_authenticate_skip_activate( | ||||
| 
 | ||||
| bool mf_classic_auth_attempt( | ||||
|     FuriHalNfcTxRxContext* tx_rx, | ||||
|     Crypto1* crypto, | ||||
|     MfClassicAuthContext* auth_ctx, | ||||
|     uint64_t key) { | ||||
|     furi_assert(tx_rx); | ||||
| @ -549,15 +550,14 @@ bool mf_classic_auth_attempt( | ||||
|     bool need_halt = (auth_ctx->key_a == MF_CLASSIC_NO_KEY) && | ||||
|                      (auth_ctx->key_b == MF_CLASSIC_NO_KEY); | ||||
| 
 | ||||
|     Crypto1 crypto; | ||||
|     if(auth_ctx->key_a == MF_CLASSIC_NO_KEY) { | ||||
|         // Try AUTH with key A
 | ||||
|         if(mf_classic_auth( | ||||
|                tx_rx, | ||||
|                mf_classic_get_first_block_num_of_sector(auth_ctx->sector), | ||||
|                mf_classic_get_sector_trailer_block_num_by_sector(auth_ctx->sector), | ||||
|                key, | ||||
|                MfClassicKeyA, | ||||
|                &crypto, | ||||
|                crypto, | ||||
|                false, | ||||
|                0)) { | ||||
|             auth_ctx->key_a = key; | ||||
| @ -573,10 +573,10 @@ bool mf_classic_auth_attempt( | ||||
|         // Try AUTH with key B
 | ||||
|         if(mf_classic_auth( | ||||
|                tx_rx, | ||||
|                mf_classic_get_first_block_num_of_sector(auth_ctx->sector), | ||||
|                mf_classic_get_sector_trailer_block_num_by_sector(auth_ctx->sector), | ||||
|                key, | ||||
|                MfClassicKeyB, | ||||
|                &crypto, | ||||
|                crypto, | ||||
|                false, | ||||
|                0)) { | ||||
|             auth_ctx->key_b = key; | ||||
| @ -671,6 +671,9 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u | ||||
|     do { | ||||
|         if(blocks_read == total_blocks) break; | ||||
|         if(!key_b_found) break; | ||||
|         if(key_a_found) { | ||||
|             furi_hal_nfc_sleep(); | ||||
|         } | ||||
|         FURI_LOG_D(TAG, "Try to read blocks with key B"); | ||||
|         key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b)); | ||||
|         if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break; | ||||
|  | ||||
| @ -174,6 +174,7 @@ bool mf_classic_authenticate_skip_activate( | ||||
| 
 | ||||
| bool mf_classic_auth_attempt( | ||||
|     FuriHalNfcTxRxContext* tx_rx, | ||||
|     Crypto1* crypto, | ||||
|     MfClassicAuthContext* auth_ctx, | ||||
|     uint64_t key); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 AloneLiberty
						AloneLiberty