[FL-2803] Mifare Classic read improvements Part 1 (#1822)
* Reuse found keys when reading a card * Fix keys not being read if no newline at the end of the file * Actually read all keys from the dictionary * Support for furi_string * Check only for re-used key after the current sector * Declare the key attack function as static * nfc: change logs, check worker state Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									5de2c32c81
								
							
						
					
					
						commit
						6dde5586af
					
				| @ -69,9 +69,18 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) { | |||||||
|         FuriString* next_line; |         FuriString* next_line; | ||||||
|         next_line = furi_string_alloc(); |         next_line = furi_string_alloc(); | ||||||
|         while(true) { |         while(true) { | ||||||
|             if(!stream_read_line(dict->stream, next_line)) break; |             if(!stream_read_line(dict->stream, next_line)) { | ||||||
|  |                 FURI_LOG_T(TAG, "No keys left in dict"); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             furi_string_trim(next_line); | ||||||
|  |             FURI_LOG_T( | ||||||
|  |                 TAG, | ||||||
|  |                 "Read line: %s, len: %d", | ||||||
|  |                 furi_string_get_cstr(next_line), | ||||||
|  |                 furi_string_size(next_line)); | ||||||
|             if(furi_string_get_char(next_line, 0) == '#') continue; |             if(furi_string_get_char(next_line, 0) == '#') continue; | ||||||
|             if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; |             if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN - 1) continue; | ||||||
|             dict->total_keys++; |             dict->total_keys++; | ||||||
|         } |         } | ||||||
|         furi_string_free(next_line); |         furi_string_free(next_line); | ||||||
|  | |||||||
| @ -453,6 +453,54 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void nfc_worker_mf_classic_key_attack( | ||||||
|  |     NfcWorker* nfc_worker, | ||||||
|  |     uint64_t key, | ||||||
|  |     FuriHalNfcTxRxContext* tx_rx, | ||||||
|  |     uint16_t start_sector) { | ||||||
|  |     furi_assert(nfc_worker); | ||||||
|  | 
 | ||||||
|  |     MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; | ||||||
|  |     uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); | ||||||
|  | 
 | ||||||
|  |     furi_assert(start_sector < total_sectors); | ||||||
|  | 
 | ||||||
|  |     // Check every sector's A and B keys with the given key
 | ||||||
|  |     for(size_t i = start_sector; i < total_sectors; i++) { | ||||||
|  |         uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i); | ||||||
|  |         if(mf_classic_is_sector_read(data, i)) continue; | ||||||
|  |         if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) { | ||||||
|  |             FURI_LOG_D( | ||||||
|  |                 TAG, | ||||||
|  |                 "Trying A key for sector %d, key: %04lx%08lx", | ||||||
|  |                 i, | ||||||
|  |                 (uint32_t)(key >> 32), | ||||||
|  |                 (uint32_t)key); | ||||||
|  |             if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyA)) { | ||||||
|  |                 mf_classic_set_key_found(data, i, MfClassicKeyA, key); | ||||||
|  |                 FURI_LOG_D(TAG, "Key found"); | ||||||
|  |                 nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) { | ||||||
|  |             FURI_LOG_D( | ||||||
|  |                 TAG, | ||||||
|  |                 "Trying B key for sector %d, key: %04lx%08lx", | ||||||
|  |                 i, | ||||||
|  |                 (uint32_t)(key >> 32), | ||||||
|  |                 (uint32_t)key); | ||||||
|  |             if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyB)) { | ||||||
|  |                 mf_classic_set_key_found(data, i, MfClassicKeyB, key); | ||||||
|  |                 FURI_LOG_D(TAG, "Key found"); | ||||||
|  |                 nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(mf_classic_is_sector_read(data, i)) continue; | ||||||
|  |         mf_classic_read_sector(tx_rx, data, i); | ||||||
|  |         if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | 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); | ||||||
| @ -484,6 +532,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | |||||||
|         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; |         uint16_t key_index = 0; | ||||||
|         while(mf_classic_dict_get_next_key(dict, &key)) { |         while(mf_classic_dict_get_next_key(dict, &key)) { | ||||||
|  |             FURI_LOG_T(TAG, "Key %d", key_index); | ||||||
|             if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) { |             if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) { | ||||||
|                 nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context); |                 nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context); | ||||||
|             } |             } | ||||||
| @ -505,15 +554,19 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | |||||||
|                     is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA); |                     is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA); | ||||||
|                     if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyA)) { |                     if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyA)) { | ||||||
|                         mf_classic_set_key_found(data, i, MfClassicKeyA, key); |                         mf_classic_set_key_found(data, i, MfClassicKeyA, key); | ||||||
|  |                         FURI_LOG_D(TAG, "Key found"); | ||||||
|                         nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); |                         nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); | ||||||
|  |                         nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); | ||||||
|                     } |                     } | ||||||
|                     furi_hal_nfc_sleep(); |                     furi_hal_nfc_sleep(); | ||||||
|                 } |                 } | ||||||
|                 if(!is_key_b_found) { |                 if(!is_key_b_found) { | ||||||
|                     is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); |                     is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); | ||||||
|                     if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyB)) { |                     if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyB)) { | ||||||
|  |                         FURI_LOG_D(TAG, "Key found"); | ||||||
|                         mf_classic_set_key_found(data, i, MfClassicKeyB, key); |                         mf_classic_set_key_found(data, i, MfClassicKeyB, key); | ||||||
|                         nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); |                         nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); | ||||||
|  |                         nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if(is_key_a_found && is_key_b_found) break; |                 if(is_key_a_found && is_key_b_found) break; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Astra
						Astra