mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
Misc bugfixes
This commit is contained in:
@@ -711,6 +711,22 @@ NfcCommand mf_classic_poller_handler_key_reuse_start(MfClassicPoller* instance)
|
|||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NfcCommand mf_classic_poller_handler_key_reuse_start_no_offset(MfClassicPoller* instance) {
|
||||||
|
NfcCommand command = NfcCommandContinue;
|
||||||
|
MfClassicPollerDictAttackContext* dict_attack_ctx = &instance->mode_ctx.dict_attack_ctx;
|
||||||
|
|
||||||
|
instance->mfc_event.type = MfClassicPollerEventTypeKeyAttackStart;
|
||||||
|
instance->mfc_event_data.key_attack_data.current_sector = dict_attack_ctx->reuse_key_sector;
|
||||||
|
command = instance->callback(instance->general_event, instance->context);
|
||||||
|
if(dict_attack_ctx->current_key_type == MfClassicKeyTypeA) {
|
||||||
|
instance->state = MfClassicPollerStateKeyReuseAuthKeyA;
|
||||||
|
} else {
|
||||||
|
instance->state = MfClassicPollerStateKeyReuseAuthKeyB;
|
||||||
|
}
|
||||||
|
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
NfcCommand mf_classic_poller_handler_key_reuse_auth_key_a(MfClassicPoller* instance) {
|
NfcCommand mf_classic_poller_handler_key_reuse_auth_key_a(MfClassicPoller* instance) {
|
||||||
NfcCommand command = NfcCommandContinue;
|
NfcCommand command = NfcCommandContinue;
|
||||||
MfClassicPollerDictAttackContext* dict_attack_ctx = &instance->mode_ctx.dict_attack_ctx;
|
MfClassicPollerDictAttackContext* dict_attack_ctx = &instance->mode_ctx.dict_attack_ctx;
|
||||||
@@ -1324,11 +1340,12 @@ static MfClassicKey* search_dicts_for_nonce_key(
|
|||||||
for(int i = 0; i < 2; i++) {
|
for(int i = 0; i < 2; i++) {
|
||||||
keys_dict_rewind(dicts[i]);
|
keys_dict_rewind(dicts[i]);
|
||||||
while(keys_dict_get_next_key(dicts[i], stack_key.data, sizeof(MfClassicKey))) {
|
while(keys_dict_get_next_key(dicts[i], stack_key.data, sizeof(MfClassicKey))) {
|
||||||
if(is_resumed && !(found_resume_point) &&
|
if(is_resumed && !found_resume_point) {
|
||||||
memcmp(dict_attack_ctx->current_key.data, stack_key.data, sizeof(MfClassicKey)) ==
|
found_resume_point =
|
||||||
0) {
|
(memcmp(
|
||||||
found_resume_point = true;
|
dict_attack_ctx->current_key.data,
|
||||||
} else {
|
stack_key.data,
|
||||||
|
sizeof(MfClassicKey)) == 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bool full_match = true;
|
bool full_match = true;
|
||||||
@@ -1458,6 +1475,7 @@ NfcCommand mf_classic_poller_handler_nested_dict_attack(MfClassicPoller* instanc
|
|||||||
bit_lib_bytes_to_num_be(key_candidate->data, sizeof(MfClassicKey)));
|
bit_lib_bytes_to_num_be(key_candidate->data, sizeof(MfClassicKey)));
|
||||||
dict_attack_ctx->current_key = *key_candidate;
|
dict_attack_ctx->current_key = *key_candidate;
|
||||||
dict_attack_ctx->reuse_key_sector = (target_block / 4);
|
dict_attack_ctx->reuse_key_sector = (target_block / 4);
|
||||||
|
dict_attack_ctx->current_key_type = target_key_type;
|
||||||
free(key_candidate);
|
free(key_candidate);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -1570,8 +1588,15 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
if(dict_attack_ctx->nested_phase == MfClassicNestedPhaseNone) {
|
if(dict_attack_ctx->nested_phase == MfClassicNestedPhaseNone) {
|
||||||
dict_attack_ctx->auth_passed = true;
|
dict_attack_ctx->auth_passed = true;
|
||||||
dict_attack_ctx->nested_known_key = dict_attack_ctx->current_key;
|
dict_attack_ctx->nested_known_key = dict_attack_ctx->current_key;
|
||||||
dict_attack_ctx->nested_known_key_type = dict_attack_ctx->current_key_type;
|
for(uint8_t sector = 0; sector < instance->sectors_total; sector++) {
|
||||||
dict_attack_ctx->nested_known_key_sector = dict_attack_ctx->reuse_key_sector;
|
for(uint8_t key_type = 0; key_type < 2; key_type++) {
|
||||||
|
if(mf_classic_is_key_found(instance->data, sector, key_type)) {
|
||||||
|
dict_attack_ctx->nested_known_key_sector = sector;
|
||||||
|
dict_attack_ctx->nested_known_key_type = key_type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
dict_attack_ctx->nested_phase = MfClassicNestedPhaseAnalyzePRNG;
|
dict_attack_ctx->nested_phase = MfClassicNestedPhaseAnalyzePRNG;
|
||||||
}
|
}
|
||||||
bool initial_dict_attack_iter = false;
|
bool initial_dict_attack_iter = false;
|
||||||
@@ -1634,18 +1659,28 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
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));
|
||||||
if(initial_dict_attack_iter) {
|
if(initial_dict_attack_iter) {
|
||||||
uint8_t nested_target_key_offset =
|
// Initialize dictionaries
|
||||||
(dict_attack_ctx->current_key_type == MfClassicKeyTypeA) ? 0 : 1;
|
// Note: System dict should always exist
|
||||||
dict_attack_ctx->nested_target_key =
|
bool system_dict_exists = keys_dict_check_presence(MF_CLASSIC_NESTED_SYSTEM_DICT_PATH);
|
||||||
(is_weak) ?
|
bool user_dict_exists = keys_dict_check_presence(MF_CLASSIC_NESTED_USER_DICT_PATH);
|
||||||
((dict_attack_ctx->current_sector * 2) + nested_target_key_offset) :
|
if(system_dict_exists) {
|
||||||
((dict_attack_ctx->current_sector * 16) + (nested_target_key_offset * 8));
|
dict_attack_ctx->mf_classic_system_dict = keys_dict_alloc(
|
||||||
|
MF_CLASSIC_NESTED_SYSTEM_DICT_PATH,
|
||||||
|
KeysDictModeOpenExisting,
|
||||||
|
sizeof(MfClassicKey));
|
||||||
|
}
|
||||||
|
if(user_dict_exists) {
|
||||||
|
dict_attack_ctx->mf_classic_user_dict = keys_dict_alloc(
|
||||||
|
MF_CLASSIC_NESTED_USER_DICT_PATH,
|
||||||
|
KeysDictModeOpenExisting,
|
||||||
|
sizeof(MfClassicKey));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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 reuse
|
||||||
dict_attack_ctx->nested_phase = MfClassicNestedPhaseDictAttackResume;
|
dict_attack_ctx->nested_phase = MfClassicNestedPhaseDictAttackResume;
|
||||||
dict_attack_ctx->auth_passed = false;
|
dict_attack_ctx->auth_passed = false;
|
||||||
instance->state = MfClassicPollerStateKeyReuseStart;
|
instance->state = MfClassicPollerStateKeyReuseStartNoOffset;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
if(!(dict_attack_ctx->auth_passed)) {
|
if(!(dict_attack_ctx->auth_passed)) {
|
||||||
@@ -1684,8 +1719,7 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
uint8_t target_sector = (is_weak) ? (dict_attack_ctx->nested_target_key / 2) :
|
uint8_t target_sector = (is_weak) ? (dict_attack_ctx->nested_target_key / 2) :
|
||||||
(dict_attack_ctx->nested_target_key / 16);
|
(dict_attack_ctx->nested_target_key / 16);
|
||||||
if(mf_classic_is_key_found(instance->data, target_sector, target_key_type)) {
|
if(mf_classic_is_key_found(instance->data, target_sector, target_key_type)) {
|
||||||
dict_attack_ctx->nested_target_key++;
|
// Continue to next key
|
||||||
dict_attack_ctx->attempt_count = 0;
|
|
||||||
instance->state = MfClassicPollerStateNestedController;
|
instance->state = MfClassicPollerStateNestedController;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
@@ -1696,23 +1730,6 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
dict_attack_ctx->nested_target_key++;
|
dict_attack_ctx->nested_target_key++;
|
||||||
dict_attack_ctx->attempt_count = 0;
|
dict_attack_ctx->attempt_count = 0;
|
||||||
}
|
}
|
||||||
if(dict_attack_ctx->nested_target_key == 0) {
|
|
||||||
// Note: System dict should always exist
|
|
||||||
bool system_dict_exists = keys_dict_check_presence(MF_CLASSIC_NESTED_SYSTEM_DICT_PATH);
|
|
||||||
bool user_dict_exists = keys_dict_check_presence(MF_CLASSIC_NESTED_USER_DICT_PATH);
|
|
||||||
if(system_dict_exists) {
|
|
||||||
dict_attack_ctx->mf_classic_system_dict = keys_dict_alloc(
|
|
||||||
MF_CLASSIC_NESTED_SYSTEM_DICT_PATH,
|
|
||||||
KeysDictModeOpenExisting,
|
|
||||||
sizeof(MfClassicKey));
|
|
||||||
}
|
|
||||||
if(user_dict_exists) {
|
|
||||||
dict_attack_ctx->mf_classic_user_dict = keys_dict_alloc(
|
|
||||||
MF_CLASSIC_NESTED_USER_DICT_PATH,
|
|
||||||
KeysDictModeOpenExisting,
|
|
||||||
sizeof(MfClassicKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
instance->state = MfClassicPollerStateNestedDictAttack;
|
instance->state = MfClassicPollerStateNestedDictAttack;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
@@ -1807,6 +1824,8 @@ static const MfClassicPollerReadHandler
|
|||||||
[MfClassicPollerStateAuthKeyB] = mf_classic_poller_handler_auth_b,
|
[MfClassicPollerStateAuthKeyB] = mf_classic_poller_handler_auth_b,
|
||||||
[MfClassicPollerStateReadSector] = mf_classic_poller_handler_read_sector,
|
[MfClassicPollerStateReadSector] = mf_classic_poller_handler_read_sector,
|
||||||
[MfClassicPollerStateKeyReuseStart] = mf_classic_poller_handler_key_reuse_start,
|
[MfClassicPollerStateKeyReuseStart] = mf_classic_poller_handler_key_reuse_start,
|
||||||
|
[MfClassicPollerStateKeyReuseStartNoOffset] =
|
||||||
|
mf_classic_poller_handler_key_reuse_start_no_offset,
|
||||||
[MfClassicPollerStateKeyReuseAuthKeyA] = mf_classic_poller_handler_key_reuse_auth_key_a,
|
[MfClassicPollerStateKeyReuseAuthKeyA] = mf_classic_poller_handler_key_reuse_auth_key_a,
|
||||||
[MfClassicPollerStateKeyReuseAuthKeyB] = mf_classic_poller_handler_key_reuse_auth_key_b,
|
[MfClassicPollerStateKeyReuseAuthKeyB] = mf_classic_poller_handler_key_reuse_auth_key_b,
|
||||||
[MfClassicPollerStateKeyReuseReadSector] = mf_classic_poller_handler_key_reuse_read_sector,
|
[MfClassicPollerStateKeyReuseReadSector] = mf_classic_poller_handler_key_reuse_read_sector,
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ typedef enum {
|
|||||||
MfClassicPollerStateAuthKeyA,
|
MfClassicPollerStateAuthKeyA,
|
||||||
MfClassicPollerStateAuthKeyB,
|
MfClassicPollerStateAuthKeyB,
|
||||||
MfClassicPollerStateKeyReuseStart,
|
MfClassicPollerStateKeyReuseStart,
|
||||||
|
MfClassicPollerStateKeyReuseStartNoOffset,
|
||||||
MfClassicPollerStateKeyReuseAuthKeyA,
|
MfClassicPollerStateKeyReuseAuthKeyA,
|
||||||
MfClassicPollerStateKeyReuseAuthKeyB,
|
MfClassicPollerStateKeyReuseAuthKeyB,
|
||||||
MfClassicPollerStateKeyReuseReadSector,
|
MfClassicPollerStateKeyReuseReadSector,
|
||||||
|
|||||||
Reference in New Issue
Block a user