mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 04:34:43 +04:00
Update found keys, second attempt
This commit is contained in:
@@ -729,9 +729,6 @@ NfcCommand mf_classic_poller_handler_key_reuse_auth_key_a(MfClassicPoller* insta
|
|||||||
instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeA, NULL);
|
instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeA, NULL);
|
||||||
if(error == MfClassicErrorNone) {
|
if(error == MfClassicErrorNone) {
|
||||||
FURI_LOG_I(TAG, "Key A found");
|
FURI_LOG_I(TAG, "Key A found");
|
||||||
if(dict_attack_ctx->nested_phase == MfClassicNestedPhaseDictAttackResume) {
|
|
||||||
dict_attack_ctx->reuse_success = true;
|
|
||||||
}
|
|
||||||
mf_classic_set_key_found(
|
mf_classic_set_key_found(
|
||||||
instance->data, dict_attack_ctx->reuse_key_sector, MfClassicKeyTypeA, key);
|
instance->data, dict_attack_ctx->reuse_key_sector, MfClassicKeyTypeA, key);
|
||||||
|
|
||||||
@@ -768,9 +765,6 @@ NfcCommand mf_classic_poller_handler_key_reuse_auth_key_b(MfClassicPoller* insta
|
|||||||
instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeB, NULL);
|
instance, block, &dict_attack_ctx->current_key, MfClassicKeyTypeB, NULL);
|
||||||
if(error == MfClassicErrorNone) {
|
if(error == MfClassicErrorNone) {
|
||||||
FURI_LOG_I(TAG, "Key B found");
|
FURI_LOG_I(TAG, "Key B found");
|
||||||
if(dict_attack_ctx->nested_phase == MfClassicNestedPhaseDictAttackResume) {
|
|
||||||
dict_attack_ctx->reuse_success = true;
|
|
||||||
}
|
|
||||||
mf_classic_set_key_found(
|
mf_classic_set_key_found(
|
||||||
instance->data, dict_attack_ctx->reuse_key_sector, MfClassicKeyTypeB, key);
|
instance->data, dict_attack_ctx->reuse_key_sector, MfClassicKeyTypeB, key);
|
||||||
|
|
||||||
@@ -1613,11 +1607,25 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
(instance->sectors_total * 2) :
|
(instance->sectors_total * 2) :
|
||||||
(instance->sectors_total * 16);
|
(instance->sectors_total * 16);
|
||||||
if(dict_attack_ctx->nested_phase == MfClassicNestedPhaseDictAttackResume) {
|
if(dict_attack_ctx->nested_phase == MfClassicNestedPhaseDictAttackResume) {
|
||||||
if(!(dict_attack_ctx->reuse_success)) {
|
bool is_weak = dict_attack_ctx->prng_type == MfClassicPrngTypeWeak;
|
||||||
|
MfClassicKeyType target_key_type =
|
||||||
|
(((is_weak) && ((dict_attack_ctx->nested_target_key % 2) == 0)) ||
|
||||||
|
((!is_weak) && ((dict_attack_ctx->nested_target_key % 16) < 8))) ?
|
||||||
|
MfClassicKeyTypeA :
|
||||||
|
MfClassicKeyTypeB;
|
||||||
|
uint8_t target_sector = (is_weak) ? (dict_attack_ctx->nested_target_key / 2) :
|
||||||
|
(dict_attack_ctx->nested_target_key / 16);
|
||||||
|
if(!(mf_classic_is_key_found(instance->data, target_sector, target_key_type))) {
|
||||||
instance->state = MfClassicPollerStateNestedDictAttack;
|
instance->state = MfClassicPollerStateNestedDictAttack;
|
||||||
return command;
|
return command;
|
||||||
|
} else {
|
||||||
|
dict_attack_ctx->auth_passed = true;
|
||||||
|
furi_assert(dict_attack_ctx->nested_nonce.nonces);
|
||||||
|
free(dict_attack_ctx->nested_nonce.nonces);
|
||||||
|
dict_attack_ctx->nested_nonce.nonces = NULL;
|
||||||
|
dict_attack_ctx->nested_nonce.count = 0;
|
||||||
|
dict_attack_ctx->nested_phase = MfClassicNestedPhaseDictAttack;
|
||||||
}
|
}
|
||||||
dict_attack_ctx->nested_phase = MfClassicNestedPhaseDictAttack;
|
|
||||||
}
|
}
|
||||||
if((dict_attack_ctx->nested_phase == MfClassicNestedPhaseDictAttack) &&
|
if((dict_attack_ctx->nested_phase == MfClassicNestedPhaseDictAttack) &&
|
||||||
(dict_attack_ctx->nested_target_key < dict_target_key_max)) {
|
(dict_attack_ctx->nested_target_key < dict_target_key_max)) {
|
||||||
@@ -1633,14 +1641,7 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
}
|
}
|
||||||
if(!(dict_attack_ctx->auth_passed)) {
|
if(!(dict_attack_ctx->auth_passed)) {
|
||||||
dict_attack_ctx->attempt_count++;
|
dict_attack_ctx->attempt_count++;
|
||||||
} else if(dict_attack_ctx->auth_passed || dict_attack_ctx->reuse_success) {
|
} else if(dict_attack_ctx->auth_passed) {
|
||||||
if(dict_attack_ctx->reuse_success) {
|
|
||||||
furi_assert(dict_attack_ctx->nested_nonce.nonces);
|
|
||||||
free(dict_attack_ctx->nested_nonce.nonces);
|
|
||||||
dict_attack_ctx->nested_nonce.nonces = NULL;
|
|
||||||
dict_attack_ctx->nested_nonce.count = 0;
|
|
||||||
dict_attack_ctx->reuse_success = false;
|
|
||||||
}
|
|
||||||
dict_attack_ctx->nested_target_key++;
|
dict_attack_ctx->nested_target_key++;
|
||||||
dict_attack_ctx->attempt_count = 0;
|
dict_attack_ctx->attempt_count = 0;
|
||||||
}
|
}
|
||||||
@@ -1654,8 +1655,7 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
}
|
}
|
||||||
dict_attack_ctx->nested_target_key = 0;
|
dict_attack_ctx->nested_target_key = 0;
|
||||||
if(mf_classic_is_card_read(instance->data)) {
|
if(mf_classic_is_card_read(instance->data)) {
|
||||||
// TODO: Ensure this works
|
// All keys have been collected
|
||||||
// All keys have been collected, skip to reading blocks
|
|
||||||
FURI_LOG_E(TAG, "All keys collected and sectors read");
|
FURI_LOG_E(TAG, "All keys collected and sectors read");
|
||||||
dict_attack_ctx->nested_phase = MfClassicNestedPhaseFinished;
|
dict_attack_ctx->nested_phase = MfClassicNestedPhaseFinished;
|
||||||
instance->state = MfClassicPollerStateSuccess;
|
instance->state = MfClassicPollerStateSuccess;
|
||||||
@@ -1665,19 +1665,21 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
instance->state = MfClassicPollerStateNestedController;
|
instance->state = MfClassicPollerStateNestedController;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
// Check if the nested target key is a known key
|
if(dict_attack_ctx->attempt_count == 0) {
|
||||||
MfClassicKeyType target_key_type =
|
// Check if the nested target key is a known key
|
||||||
(((is_weak) && ((dict_attack_ctx->nested_target_key % 2) == 0)) ||
|
MfClassicKeyType target_key_type =
|
||||||
((!is_weak) && ((dict_attack_ctx->nested_target_key % 16) < 8))) ?
|
(((is_weak) && ((dict_attack_ctx->nested_target_key % 2) == 0)) ||
|
||||||
MfClassicKeyTypeA :
|
((!is_weak) && ((dict_attack_ctx->nested_target_key % 16) < 8))) ?
|
||||||
MfClassicKeyTypeB;
|
MfClassicKeyTypeA :
|
||||||
uint8_t target_sector = (is_weak) ? (dict_attack_ctx->nested_target_key / 2) :
|
MfClassicKeyTypeB;
|
||||||
(dict_attack_ctx->nested_target_key / 16);
|
uint8_t target_sector = (is_weak) ? (dict_attack_ctx->nested_target_key / 2) :
|
||||||
if(mf_classic_is_key_found(instance->data, target_sector, target_key_type)) {
|
(dict_attack_ctx->nested_target_key / 16);
|
||||||
dict_attack_ctx->nested_target_key++;
|
if(mf_classic_is_key_found(instance->data, target_sector, target_key_type)) {
|
||||||
dict_attack_ctx->attempt_count = 0;
|
dict_attack_ctx->nested_target_key++;
|
||||||
instance->state = MfClassicPollerStateNestedController;
|
dict_attack_ctx->attempt_count = 0;
|
||||||
return command;
|
instance->state = MfClassicPollerStateNestedController;
|
||||||
|
return command;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(dict_attack_ctx->attempt_count >= 3) {
|
if(dict_attack_ctx->attempt_count >= 3) {
|
||||||
// Unpredictable, skip
|
// Unpredictable, skip
|
||||||
@@ -1757,8 +1759,8 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
instance->state = MfClassicPollerStateNestedCollectNtEnc;
|
instance->state = MfClassicPollerStateNestedCollectNtEnc;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
// TODO: If we've recovered all keys, read blocks and go to complete
|
dict_attack_ctx->nested_phase = MfClassicNestedPhaseFinished;
|
||||||
instance->state = MfClassicPollerStateKeyReuseStart;
|
instance->state = MfClassicPollerStateSuccess;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ typedef struct {
|
|||||||
MfClassicKey current_key;
|
MfClassicKey current_key;
|
||||||
MfClassicKeyType current_key_type;
|
MfClassicKeyType current_key_type;
|
||||||
bool auth_passed;
|
bool auth_passed;
|
||||||
bool reuse_success;
|
|
||||||
uint16_t current_block;
|
uint16_t current_block;
|
||||||
uint8_t reuse_key_sector;
|
uint8_t reuse_key_sector;
|
||||||
// Enhanced dictionary attack and nested nonce collection
|
// Enhanced dictionary attack and nested nonce collection
|
||||||
|
|||||||
Reference in New Issue
Block a user