[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) {
|
||||
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) ||
|
||||
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 {
|
||||
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) ||
|
||||
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