From 0a32cd252820d6a32ff7ffebb45bf918e507150a Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Thu, 27 Apr 2023 00:27:57 +0300 Subject: [PATCH 1/5] I was outplayed by the C programming language --- lib/nfc/nfc_worker.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 28a1f6827977..5a0145bf4ac6 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -661,7 +661,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; @@ -683,8 +684,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) { + found_key == current_key) { 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); @@ -694,7 +701,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); @@ -702,8 +710,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) { + found_key == current_key) { 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); From 102dd690b7ec6b679bfd56d75bfe682af6c81e00 Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Thu, 27 Apr 2023 00:28:21 +0300 Subject: [PATCH 2/5] Fix emulating empty keys as 0s --- lib/nfc/protocols/mifare_classic.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index d2d7467dce09..204e3a5ebeb1 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -892,11 +892,25 @@ 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) { - key = nfc_util_bytes2num(sector_trailer->key_a, 6); - access_key = MfClassicKeyA; + if(mf_classic_is_key_found( + &emulator->data, mf_classic_get_sector_by_block(block), MfClassicKeyA)) { + 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 { - key = nfc_util_bytes2num(sector_trailer->key_b, 6); - access_key = MfClassicKeyB; + if(mf_classic_is_key_found( + &emulator->data, mf_classic_get_sector_by_block(block), MfClassicKeyB)) { + 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; From 4934e9f882b492246a97384d48b478761a4b60a1 Mon Sep 17 00:00:00 2001 From: Astra Date: Wed, 7 Jun 2023 15:07:14 +0300 Subject: [PATCH 3/5] Add exceptions for Detect Reader --- firmware/targets/f7/api_symbols.csv | 4 ++-- lib/nfc/nfc_worker.c | 4 ++-- lib/nfc/protocols/mifare_classic.c | 11 ++++++++--- lib/nfc/protocols/mifare_classic.h | 5 ++++- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index d0c6b36ad54c..117504bc3ce1 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,23.0,, +Version,+,23.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1923,7 +1923,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 diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 5a0145bf4ac6..29d582327d0f 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -762,7 +762,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) { @@ -1049,7 +1049,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++; diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index 204e3a5ebeb1..ebe49a4a0e04 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -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; @@ -893,7 +896,8 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ (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)) { + &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 { @@ -903,7 +907,8 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ } } else { if(mf_classic_is_key_found( - &emulator->data, mf_classic_get_sector_by_block(block), MfClassicKeyB)) { + &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 { diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index c03350f2e938..b3e3cbdf80df 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -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); From 85d59f14c34edf970a5902925c5a907151c8b005 Mon Sep 17 00:00:00 2001 From: Astra Date: Wed, 7 Jun 2023 15:10:28 +0300 Subject: [PATCH 4/5] Sync api_symbols.csv for F18 --- firmware/targets/f18/api_symbols.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index f551a09c159d..5f2593179695 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,29.0,, +Version,+,29.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, From 0ff9ea0a461b4b10142ae543bf78794039051679 Mon Sep 17 00:00:00 2001 From: Astra Date: Thu, 8 Jun 2023 14:31:41 +0300 Subject: [PATCH 5/5] Outplayed by the C language [X2] --- lib/nfc/nfc_worker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 93bf05ced6b2..11be7c5fa05a 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -704,7 +704,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { memcpy(current_key, &key, 6); if(mf_classic_is_key_found(data, i, MfClassicKeyA) && - found_key == current_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); @@ -730,7 +730,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { memcpy(current_key, &key, 6); if(mf_classic_is_key_found(data, i, MfClassicKeyB) && - found_key == current_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);