MFC Improvements Part 2/2

OFW PR 1868 by Astrrra
This commit is contained in:
MX 2022-10-12 05:29:42 +03:00
parent 80735d4f51
commit 6b5631e5b0
No known key found for this signature in database
GPG key ID: 6C4C311DFD4B4AB5
3 changed files with 74 additions and 28 deletions

View file

@ -480,6 +480,9 @@ static void nfc_worker_mf_classic_key_attack(
uint16_t start_sector) {
furi_assert(nfc_worker);
bool card_found_notified = true;
bool card_removed_notified = false;
MfClassicData* data = &nfc_worker->dev_data->mf_classic_data;
uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type);
@ -487,36 +490,52 @@ static void nfc_worker_mf_classic_key_attack(
// 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);
furi_hal_nfc_sleep();
if(furi_hal_nfc_activate_nfca(200, NULL)) {
furi_hal_nfc_sleep();
if(!card_found_notified) {
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
card_found_notified = true;
card_removed_notified = false;
}
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);
} else {
if(!card_removed_notified) {
nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
card_removed_notified = true;
card_found_notified = false;
}
}
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;
}
}
@ -530,6 +549,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
&nfc_worker->dev_data->mf_classic_dict_attack_data;
uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type);
uint64_t key = 0;
uint64_t prev_key = 0;
FuriHalNfcTxRxContext tx_rx = {};
bool card_found_notified = true;
bool card_removed_notified = false;
@ -542,6 +562,18 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
return;
}
// Clear found keys if the key cache is incorrect (key set as found but sector not read)
for(uint16_t sector = 0; sector < total_sectors; sector++) {
if(mf_classic_is_key_found(data, sector, MfClassicKeyA) &&
!mf_classic_is_sector_read(data, sector)) {
mf_classic_set_key_not_found(data, sector, MfClassicKeyA);
}
if(mf_classic_is_key_found(data, sector, MfClassicKeyB) &&
!mf_classic_is_sector_read(data, sector)) {
mf_classic_set_key_not_found(data, sector, MfClassicKeyB);
}
}
FURI_LOG_D(
TAG, "Start Dictionary attack, Key Count %ld", mf_classic_dict_get_total_keys(dict));
for(size_t i = 0; i < total_sectors; i++) {
@ -564,6 +596,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
card_found_notified = true;
card_removed_notified = false;
nfc_worker_mf_classic_key_attack(nfc_worker, prev_key, &tx_rx, i);
}
FURI_LOG_D(
TAG,
@ -600,6 +633,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
}
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
}
memcpy(&prev_key, &key, sizeof(key));
}
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
mf_classic_read_sector(&tx_rx, data, i);

View file

@ -155,6 +155,16 @@ void mf_classic_set_key_found(
}
}
void mf_classic_set_key_not_found(MfClassicData* data, uint8_t sector_num, MfClassicKey key_type) {
furi_assert(data);
if(key_type == MfClassicKeyA) {
FURI_BIT_CLEAR(data->key_a_mask, sector_num);
} else if(key_type == MfClassicKeyB) {
FURI_BIT_CLEAR(data->key_b_mask, sector_num);
}
}
bool mf_classic_is_sector_read(MfClassicData* data, uint8_t sector_num) {
furi_assert(data);

View file

@ -98,6 +98,8 @@ void mf_classic_set_key_found(
MfClassicKey key_type,
uint64_t key);
void mf_classic_set_key_not_found(MfClassicData* data, uint8_t sector_num, MfClassicKey key_type);
bool mf_classic_is_block_read(MfClassicData* data, uint8_t block_num);
void mf_classic_set_block_read(MfClassicData* data, uint8_t block_num, MfClassicBlock* block_data);