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