[FL-3284] Fix reading Mifare Classic cards with unusual access conditions and fix emulation of unknown keys (#2620)
* I was outplayed by the C programming language * Fix emulating empty keys as 0s * Add exceptions for Detect Reader * Sync api_symbols.csv for F18 * Outplayed by the C language [X2] Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									2312fe5bfc
								
							
						
					
					
						commit
						4900e8b7a2
					
				| @ -1,5 +1,5 @@ | ||||
| entry,status,name,type,params | ||||
| Version,+,30.0,, | ||||
| Version,+,30.1,, | ||||
| Header,+,applications/services/bt/bt_service/bt.h,, | ||||
| Header,+,applications/services/cli/cli.h,, | ||||
| Header,+,applications/services/cli/cli_vcp.h,, | ||||
|  | ||||
| 
 | 
| @ -1,5 +1,5 @@ | ||||
| entry,status,name,type,params | ||||
| Version,+,30.0,, | ||||
| Version,+,30.1,, | ||||
| Header,+,applications/services/bt/bt_service/bt.h,, | ||||
| Header,+,applications/services/cli/cli.h,, | ||||
| Header,+,applications/services/cli/cli_vcp.h,, | ||||
| @ -1957,7 +1957,7 @@ Function,-,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict* | ||||
| Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" | ||||
| Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*" | ||||
| Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict* | ||||
| Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*" | ||||
| Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*, _Bool" | ||||
| Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t" | ||||
| Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" | ||||
| Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t | ||||
|  | ||||
| 
 | 
| @ -917,7 +917,8 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | ||||
|                     if(mf_classic_authenticate_skip_activate( | ||||
|                            &tx_rx, block_num, key, MfClassicKeyA, !deactivated, cuid)) { | ||||
|                         mf_classic_set_key_found(data, i, MfClassicKeyA, key); | ||||
|                         FURI_LOG_D(TAG, "Key A found"); | ||||
|                         FURI_LOG_D( | ||||
|                             TAG, "Key A found: %04lx%08lx", (uint32_t)(key >> 32), (uint32_t)key); | ||||
|                         nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); | ||||
| 
 | ||||
|                         uint64_t found_key; | ||||
| @ -939,8 +940,14 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | ||||
|                     deactivated = true; | ||||
|                 } else { | ||||
|                     // If the key A is marked as found and matches the searching key, invalidate it
 | ||||
|                     uint8_t found_key[6]; | ||||
|                     memcpy(found_key, data->block[i].value, 6); | ||||
| 
 | ||||
|                     uint8_t current_key[6]; | ||||
|                     memcpy(current_key, &key, 6); | ||||
| 
 | ||||
|                     if(mf_classic_is_key_found(data, i, MfClassicKeyA) && | ||||
|                        data->block[i].value[0] == key) { | ||||
|                        memcmp(found_key, current_key, 6) == 0) { | ||||
|                         mf_classic_set_key_not_found(data, i, MfClassicKeyA); | ||||
|                         is_key_a_found = false; | ||||
|                         FURI_LOG_D(TAG, "Key %dA not found in attack", i); | ||||
| @ -950,7 +957,8 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | ||||
|                     is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); | ||||
|                     if(mf_classic_authenticate_skip_activate( | ||||
|                            &tx_rx, block_num, key, MfClassicKeyB, !deactivated, cuid)) { | ||||
|                         FURI_LOG_D(TAG, "Key B found"); | ||||
|                         FURI_LOG_D( | ||||
|                             TAG, "Key B found: %04lx%08lx", (uint32_t)(key >> 32), (uint32_t)key); | ||||
|                         mf_classic_set_key_found(data, i, MfClassicKeyB, key); | ||||
|                         nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); | ||||
|                         nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); | ||||
| @ -958,8 +966,14 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { | ||||
|                     deactivated = true; | ||||
|                 } else { | ||||
|                     // If the key B is marked as found and matches the searching key, invalidate it
 | ||||
|                     uint8_t found_key[6]; | ||||
|                     memcpy(found_key, data->block[i].value + 10, 6); | ||||
| 
 | ||||
|                     uint8_t current_key[6]; | ||||
|                     memcpy(current_key, &key, 6); | ||||
| 
 | ||||
|                     if(mf_classic_is_key_found(data, i, MfClassicKeyB) && | ||||
|                        data->block[i].value[10] == key) { | ||||
|                        memcmp(found_key, current_key, 6) == 0) { | ||||
|                         mf_classic_set_key_not_found(data, i, MfClassicKeyB); | ||||
|                         is_key_b_found = false; | ||||
|                         FURI_LOG_D(TAG, "Key %dB not found in attack", i); | ||||
| @ -1004,7 +1018,7 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { | ||||
|     furi_hal_nfc_listen_start(nfc_data); | ||||
|     while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { //-V1044
 | ||||
|         if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { | ||||
|             mf_classic_emulator(&emulator, &tx_rx); | ||||
|             mf_classic_emulator(&emulator, &tx_rx, false); | ||||
|         } | ||||
|     } | ||||
|     if(emulator.data_changed) { | ||||
| @ -1291,7 +1305,7 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { | ||||
|             NfcProtocol protocol = | ||||
|                 reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8); | ||||
|             if(protocol == NfcDeviceProtocolMifareClassic) { | ||||
|                 mf_classic_emulator(&emulator, &tx_rx); | ||||
|                 mf_classic_emulator(&emulator, &tx_rx, true); | ||||
|             } | ||||
|         } else { | ||||
|             reader_no_data_received_cnt++; | ||||
|  | ||||
| @ -845,7 +845,10 @@ uint8_t mf_classic_update_card(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data | ||||
|     return sectors_read; | ||||
| } | ||||
| 
 | ||||
| bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_rx) { | ||||
| bool mf_classic_emulator( | ||||
|     MfClassicEmulator* emulator, | ||||
|     FuriHalNfcTxRxContext* tx_rx, | ||||
|     bool is_reader_analyzer) { | ||||
|     furi_assert(emulator); | ||||
|     furi_assert(tx_rx); | ||||
|     bool command_processed = false; | ||||
| @ -892,11 +895,27 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ | ||||
|             MfClassicSectorTrailer* sector_trailer = | ||||
|                 (MfClassicSectorTrailer*)emulator->data.block[sector_trailer_block].value; | ||||
|             if(cmd == MF_CLASSIC_AUTH_KEY_A_CMD) { | ||||
|                 if(mf_classic_is_key_found( | ||||
|                        &emulator->data, mf_classic_get_sector_by_block(block), MfClassicKeyA) || | ||||
|                    is_reader_analyzer) { | ||||
|                     key = nfc_util_bytes2num(sector_trailer->key_a, 6); | ||||
|                     access_key = MfClassicKeyA; | ||||
|                 } else { | ||||
|                     FURI_LOG_D(TAG, "Key not known"); | ||||
|                     command_processed = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } else { | ||||
|                 if(mf_classic_is_key_found( | ||||
|                        &emulator->data, mf_classic_get_sector_by_block(block), MfClassicKeyB) || | ||||
|                    is_reader_analyzer) { | ||||
|                     key = nfc_util_bytes2num(sector_trailer->key_b, 6); | ||||
|                     access_key = MfClassicKeyB; | ||||
|                 } else { | ||||
|                     FURI_LOG_D(TAG, "Key not known"); | ||||
|                     command_processed = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             uint32_t nonce = prng_successor(DWT->CYCCNT, 32) ^ 0xAA; | ||||
|  | ||||
| @ -199,7 +199,10 @@ uint8_t mf_classic_read_card( | ||||
| 
 | ||||
| uint8_t mf_classic_update_card(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data); | ||||
| 
 | ||||
| bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_rx); | ||||
| bool mf_classic_emulator( | ||||
|     MfClassicEmulator* emulator, | ||||
|     FuriHalNfcTxRxContext* tx_rx, | ||||
|     bool is_reader_analyzer); | ||||
| 
 | ||||
| void mf_classic_halt(FuriHalNfcTxRxContext* tx_rx, Crypto1* crypto); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Astra
						Astra