|
@@ -453,6 +453,54 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void nfc_worker_mf_classic_key_attack(
|
|
|
|
|
+ NfcWorker* nfc_worker,
|
|
|
|
|
+ uint64_t key,
|
|
|
|
|
+ FuriHalNfcTxRxContext* tx_rx,
|
|
|
|
|
+ uint16_t start_sector) {
|
|
|
|
|
+ furi_assert(nfc_worker);
|
|
|
|
|
+
|
|
|
|
|
+ MfClassicData* data = &nfc_worker->dev_data->mf_classic_data;
|
|
|
|
|
+ uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type);
|
|
|
|
|
+
|
|
|
|
|
+ furi_assert(start_sector < total_sectors);
|
|
|
|
|
+
|
|
|
|
|
+ // 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);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
|
void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
|
|
furi_assert(nfc_worker);
|
|
furi_assert(nfc_worker);
|
|
|
furi_assert(nfc_worker->callback);
|
|
furi_assert(nfc_worker->callback);
|
|
@@ -484,6 +532,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
|
|
bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB);
|
|
bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB);
|
|
|
uint16_t key_index = 0;
|
|
uint16_t key_index = 0;
|
|
|
while(mf_classic_dict_get_next_key(dict, &key)) {
|
|
while(mf_classic_dict_get_next_key(dict, &key)) {
|
|
|
|
|
+ FURI_LOG_T(TAG, "Key %d", key_index);
|
|
|
if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) {
|
|
if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) {
|
|
|
nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context);
|
|
nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context);
|
|
|
}
|
|
}
|
|
@@ -505,15 +554,19 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
|
|
is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA);
|
|
is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA);
|
|
|
if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyA)) {
|
|
if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyA)) {
|
|
|
mf_classic_set_key_found(data, i, MfClassicKeyA, key);
|
|
mf_classic_set_key_found(data, i, MfClassicKeyA, key);
|
|
|
|
|
+ FURI_LOG_D(TAG, "Key found");
|
|
|
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
|
|
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
|
|
|
|
|
+ nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1);
|
|
|
}
|
|
}
|
|
|
furi_hal_nfc_sleep();
|
|
furi_hal_nfc_sleep();
|
|
|
}
|
|
}
|
|
|
if(!is_key_b_found) {
|
|
if(!is_key_b_found) {
|
|
|
is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB);
|
|
is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB);
|
|
|
if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyB)) {
|
|
if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyB)) {
|
|
|
|
|
+ FURI_LOG_D(TAG, "Key found");
|
|
|
mf_classic_set_key_found(data, i, MfClassicKeyB, key);
|
|
mf_classic_set_key_found(data, i, MfClassicKeyB, key);
|
|
|
nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
|
|
nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
|
|
|
|
|
+ nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if(is_key_a_found && is_key_b_found) break;
|
|
if(is_key_a_found && is_key_b_found) break;
|