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:
AloneLiberty 2023-03-07 21:33:59 +03:00 committed by GitHub
parent 9819306731
commit eb5dae1cda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 6 deletions

View File

@ -11,6 +11,10 @@ void nfc_magic_scene_file_select_on_enter(void* context) {
// Process file_select return // Process file_select return
nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic); 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_file_select(nfc_magic->nfc_dev)) {
if(nfc_magic_scene_file_select_is_file_suitable(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); scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm);

View File

@ -1892,7 +1892,7 @@ Function,+,menu_free,void,Menu*
Function,+,menu_get_view,View*,Menu* Function,+,menu_get_view,View*,Menu*
Function,+,menu_reset,void,Menu* Function,+,menu_reset,void,Menu*
Function,+,menu_set_selected_item,void,"Menu*, uint32_t" 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_init_context,void,"MfClassicAuthContext*, uint8_t"
Function,-,mf_classic_auth_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_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" Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey"

1 entry status name type params
1892 Function + menu_get_view View* Menu*
1893 Function + menu_reset void Menu*
1894 Function + menu_set_selected_item void Menu*, uint32_t
1895 Function - mf_classic_auth_attempt _Bool FuriHalNfcTxRxContext*, MfClassicAuthContext*, uint64_t FuriHalNfcTxRxContext*, Crypto1*, MfClassicAuthContext*, uint64_t
1896 Function - mf_classic_auth_init_context void MfClassicAuthContext*, uint8_t
1897 Function - mf_classic_auth_write_block _Bool FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t
1898 Function - mf_classic_authenticate _Bool FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey

View File

@ -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( static void nfc_worker_mf_classic_key_attack(
NfcWorker* nfc_worker, NfcWorker* nfc_worker,
uint64_t key, uint64_t key,
@ -614,6 +640,16 @@ static void nfc_worker_mf_classic_key_attack(
mf_classic_set_key_found(data, i, MfClassicKeyA, key); mf_classic_set_key_found(data, i, MfClassicKeyA, key);
FURI_LOG_D(TAG, "Key found"); FURI_LOG_D(TAG, "Key found");
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); 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)) { 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); mf_classic_set_key_found(data, i, MfClassicKeyA, key);
FURI_LOG_D(TAG, "Key found"); FURI_LOG_D(TAG, "Key found");
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); 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); nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1);
} }
furi_hal_nfc_sleep(); furi_hal_nfc_sleep();

View File

@ -541,6 +541,7 @@ bool mf_classic_authenticate_skip_activate(
bool mf_classic_auth_attempt( bool mf_classic_auth_attempt(
FuriHalNfcTxRxContext* tx_rx, FuriHalNfcTxRxContext* tx_rx,
Crypto1* crypto,
MfClassicAuthContext* auth_ctx, MfClassicAuthContext* auth_ctx,
uint64_t key) { uint64_t key) {
furi_assert(tx_rx); furi_assert(tx_rx);
@ -549,15 +550,14 @@ bool mf_classic_auth_attempt(
bool need_halt = (auth_ctx->key_a == MF_CLASSIC_NO_KEY) && bool need_halt = (auth_ctx->key_a == MF_CLASSIC_NO_KEY) &&
(auth_ctx->key_b == MF_CLASSIC_NO_KEY); (auth_ctx->key_b == MF_CLASSIC_NO_KEY);
Crypto1 crypto;
if(auth_ctx->key_a == MF_CLASSIC_NO_KEY) { if(auth_ctx->key_a == MF_CLASSIC_NO_KEY) {
// Try AUTH with key A // Try AUTH with key A
if(mf_classic_auth( if(mf_classic_auth(
tx_rx, 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, key,
MfClassicKeyA, MfClassicKeyA,
&crypto, crypto,
false, false,
0)) { 0)) {
auth_ctx->key_a = key; auth_ctx->key_a = key;
@ -573,10 +573,10 @@ bool mf_classic_auth_attempt(
// Try AUTH with key B // Try AUTH with key B
if(mf_classic_auth( if(mf_classic_auth(
tx_rx, 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, key,
MfClassicKeyB, MfClassicKeyB,
&crypto, crypto,
false, false,
0)) { 0)) {
auth_ctx->key_b = key; auth_ctx->key_b = key;
@ -671,6 +671,9 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u
do { do {
if(blocks_read == total_blocks) break; if(blocks_read == total_blocks) break;
if(!key_b_found) 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"); FURI_LOG_D(TAG, "Try to read blocks with key B");
key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->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; if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break;

View File

@ -174,6 +174,7 @@ bool mf_classic_authenticate_skip_activate(
bool mf_classic_auth_attempt( bool mf_classic_auth_attempt(
FuriHalNfcTxRxContext* tx_rx, FuriHalNfcTxRxContext* tx_rx,
Crypto1* crypto,
MfClassicAuthContext* auth_ctx, MfClassicAuthContext* auth_ctx,
uint64_t key); uint64_t key);