mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
Fix issue with resume logic
This commit is contained in:
@@ -45,6 +45,7 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) {
|
|||||||
furi_string_set(m->header, "PRNG Analysis");
|
furi_string_set(m->header, "PRNG Analysis");
|
||||||
break;
|
break;
|
||||||
case MfClassicNestedPhaseDictAttack:
|
case MfClassicNestedPhaseDictAttack:
|
||||||
|
case MfClassicNestedPhaseDictAttackVerify:
|
||||||
case MfClassicNestedPhaseDictAttackResume:
|
case MfClassicNestedPhaseDictAttackResume:
|
||||||
furi_string_set(m->header, "Nested Dictionary");
|
furi_string_set(m->header, "Nested Dictionary");
|
||||||
break;
|
break;
|
||||||
@@ -91,6 +92,7 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) {
|
|||||||
float dict_progress = 0;
|
float dict_progress = 0;
|
||||||
if(m->nested_phase == MfClassicNestedPhaseAnalyzePRNG ||
|
if(m->nested_phase == MfClassicNestedPhaseAnalyzePRNG ||
|
||||||
m->nested_phase == MfClassicNestedPhaseDictAttack ||
|
m->nested_phase == MfClassicNestedPhaseDictAttack ||
|
||||||
|
m->nested_phase == MfClassicNestedPhaseDictAttackVerify ||
|
||||||
m->nested_phase == MfClassicNestedPhaseDictAttackResume) {
|
m->nested_phase == MfClassicNestedPhaseDictAttackResume) {
|
||||||
// Phase: Nested dictionary attack
|
// Phase: Nested dictionary attack
|
||||||
uint8_t target_sector =
|
uint8_t target_sector =
|
||||||
|
|||||||
@@ -1881,9 +1881,10 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
uint16_t dict_target_key_max = (dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) ?
|
uint16_t dict_target_key_max = (dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) ?
|
||||||
(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 == MfClassicNestedPhaseDictAttackVerify) {
|
||||||
if(!(mf_classic_nested_is_target_key_found(instance, true)) &&
|
if(!(mf_classic_nested_is_target_key_found(instance, true)) &&
|
||||||
(dict_attack_ctx->nested_nonce.count > 0)) {
|
(dict_attack_ctx->nested_nonce.count > 0)) {
|
||||||
|
dict_attack_ctx->nested_phase = MfClassicNestedPhaseDictAttackResume;
|
||||||
instance->state = MfClassicPollerStateNestedDictAttack;
|
instance->state = MfClassicPollerStateNestedDictAttack;
|
||||||
return command;
|
return command;
|
||||||
} else {
|
} else {
|
||||||
@@ -1898,7 +1899,8 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
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_phase == MfClassicNestedPhaseDictAttackResume) &&
|
||||||
(dict_attack_ctx->nested_target_key < dict_target_key_max)) {
|
(dict_attack_ctx->nested_target_key < dict_target_key_max)) {
|
||||||
bool is_last_iter_for_hard_key =
|
bool is_last_iter_for_hard_key =
|
||||||
((!is_weak) && ((dict_attack_ctx->nested_target_key % 8) == 7));
|
((!is_weak) && ((dict_attack_ctx->nested_target_key % 8) == 7));
|
||||||
@@ -1922,11 +1924,14 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
NULL;
|
NULL;
|
||||||
}
|
}
|
||||||
if((is_weak || is_last_iter_for_hard_key) && dict_attack_ctx->nested_nonce.count > 0) {
|
if((is_weak || is_last_iter_for_hard_key) && dict_attack_ctx->nested_nonce.count > 0) {
|
||||||
// Key reuse
|
// Key verify and reuse
|
||||||
dict_attack_ctx->nested_phase = MfClassicNestedPhaseDictAttackResume;
|
dict_attack_ctx->nested_phase = MfClassicNestedPhaseDictAttackVerify;
|
||||||
dict_attack_ctx->auth_passed = false;
|
dict_attack_ctx->auth_passed = false;
|
||||||
instance->state = MfClassicPollerStateKeyReuseStartNoOffset;
|
instance->state = MfClassicPollerStateKeyReuseStartNoOffset;
|
||||||
return command;
|
return command;
|
||||||
|
} else if(dict_attack_ctx->nested_phase == MfClassicNestedPhaseDictAttackResume) {
|
||||||
|
dict_attack_ctx->nested_phase = MfClassicNestedPhaseDictAttack;
|
||||||
|
dict_attack_ctx->auth_passed = true;
|
||||||
}
|
}
|
||||||
if(!(dict_attack_ctx->auth_passed)) {
|
if(!(dict_attack_ctx->auth_passed)) {
|
||||||
dict_attack_ctx->attempt_count++;
|
dict_attack_ctx->attempt_count++;
|
||||||
|
|||||||
@@ -52,14 +52,15 @@ typedef enum {
|
|||||||
* @brief MfClassic poller nested attack phase.
|
* @brief MfClassic poller nested attack phase.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MfClassicNestedPhaseNone,
|
MfClassicNestedPhaseNone, /**< No nested attack has taken place yet. */
|
||||||
MfClassicNestedPhaseAnalyzePRNG,
|
MfClassicNestedPhaseAnalyzePRNG, /**< Analyze nonces produced by the PRNG to determine if they fit a weak PRNG */
|
||||||
MfClassicNestedPhaseDictAttack,
|
MfClassicNestedPhaseDictAttack, /**< Search keys which match the expected PRNG properties and parity for collected nonces */
|
||||||
MfClassicNestedPhaseDictAttackResume,
|
MfClassicNestedPhaseDictAttackVerify, /**< Verify candidate keys by authenticating to the sector with the key */
|
||||||
MfClassicNestedPhaseCalibrate,
|
MfClassicNestedPhaseDictAttackResume, /**< Resume nested dictionary attack from the last tested (invalid) key */
|
||||||
MfClassicNestedPhaseRecalibrate,
|
MfClassicNestedPhaseCalibrate, /**< Perform necessary calculations to recover the plaintext nonce during later collection phase (weak PRNG tags only) */
|
||||||
MfClassicNestedPhaseCollectNtEnc,
|
MfClassicNestedPhaseRecalibrate, /**< Collect the next plaintext static encrypted nonce for backdoor static encrypted nonce nested attack */
|
||||||
MfClassicNestedPhaseFinished,
|
MfClassicNestedPhaseCollectNtEnc, /**< Log nonces collected during nested authentication for key recovery */
|
||||||
|
MfClassicNestedPhaseFinished, /**< Nested attack has finished */
|
||||||
} MfClassicNestedPhase;
|
} MfClassicNestedPhase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user