mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-13 05:06:30 +04:00
Identified method to reduce candidate states
This commit is contained in:
@@ -838,37 +838,15 @@ NfcCommand mf_classic_poller_handler_key_reuse_read_sector(MfClassicPoller* inst
|
|||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nonce_distance(uint32_t* msb, uint32_t* lsb) {
|
bool validate_prng_nonce(uint32_t nonce) {
|
||||||
uint16_t x = 1, pos;
|
if(nonce == 0) return false;
|
||||||
uint8_t calc_ok = 0;
|
uint16_t x = nonce >> 16;
|
||||||
|
x = (x & 0xff) << 8 | x >> 8;
|
||||||
for(uint16_t i = 1; i; ++i) {
|
for(uint8_t i = 0; i < 16; i++) {
|
||||||
pos = (x & 0xff) << 8 | x >> 8;
|
|
||||||
|
|
||||||
if((pos == *msb) & !(calc_ok >> 0 & 0x01)) {
|
|
||||||
*msb = i;
|
|
||||||
calc_ok |= 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((pos == *lsb) & !(calc_ok >> 1 & 0x01)) {
|
|
||||||
*lsb = i;
|
|
||||||
calc_ok |= 0x02;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(calc_ok == 0x03) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
|
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
|
||||||
}
|
}
|
||||||
}
|
x = (x & 0xff) << 8 | x >> 8;
|
||||||
|
return x == (nonce & 0xFFFF);
|
||||||
// TODO: Faster? https://github.com/RfidResearchGroup/proxmark3/commit/bd3e8db852186d4ab9d5dda890d1cd52389b1254
|
|
||||||
bool validate_prng_nonce(uint32_t nonce) {
|
|
||||||
uint32_t msb = nonce >> 16;
|
|
||||||
uint32_t lsb = nonce & 0xffff;
|
|
||||||
nonce_distance(&msb, &lsb);
|
|
||||||
return ((65535 - msb + lsb) % 65535) == 16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return 1 if the nonce is invalid else return 0
|
// Return 1 if the nonce is invalid else return 0
|
||||||
@@ -883,9 +861,17 @@ uint8_t valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Helper function to add a nonce to the array
|
// Helper function to add a nonce to the array
|
||||||
static bool add_nested_nonce(MfClassicNestedNonceArray* array, uint32_t cuid, uint8_t key_idx, uint32_t nt, uint32_t nt_enc, uint8_t par, uint16_t dist) {
|
static bool add_nested_nonce(
|
||||||
MfClassicNestedNonce* new_nonces = realloc(array->nonces, (array->count + 1) * sizeof(MfClassicNestedNonce));
|
MfClassicNestedNonceArray* array,
|
||||||
if (new_nonces == NULL) return false;
|
uint32_t cuid,
|
||||||
|
uint8_t key_idx,
|
||||||
|
uint32_t nt,
|
||||||
|
uint32_t nt_enc,
|
||||||
|
uint8_t par,
|
||||||
|
uint16_t dist) {
|
||||||
|
MfClassicNestedNonce* new_nonces =
|
||||||
|
realloc(array->nonces, (array->count + 1) * sizeof(MfClassicNestedNonce));
|
||||||
|
if(new_nonces == NULL) return false;
|
||||||
|
|
||||||
array->nonces = new_nonces;
|
array->nonces = new_nonces;
|
||||||
array->nonces[array->count].cuid = cuid;
|
array->nonces[array->count].cuid = cuid;
|
||||||
@@ -905,11 +891,11 @@ NfcCommand mf_classic_poller_handler_nested_analyze_prng(MfClassicPoller* instan
|
|||||||
// Analyze PRNG by collecting nt
|
// Analyze PRNG by collecting nt
|
||||||
uint8_t nonce_limit = 10;
|
uint8_t nonce_limit = 10;
|
||||||
|
|
||||||
if (dict_attack_ctx->nt_count > 0) {
|
if(dict_attack_ctx->nt_count > 0) {
|
||||||
if(!validate_prng_nonce(dict_attack_ctx->nt_prev)) dict_attack_ctx->hard_nt_count++;
|
if(!validate_prng_nonce(dict_attack_ctx->nt_prev)) dict_attack_ctx->hard_nt_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dict_attack_ctx->nt_count <= nonce_limit) {
|
if(dict_attack_ctx->nt_count < nonce_limit) {
|
||||||
instance->state = MfClassicPollerStateNestedCollectNt;
|
instance->state = MfClassicPollerStateNestedCollectNt;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
@@ -933,6 +919,7 @@ NfcCommand mf_classic_poller_handler_nested_analyze_backdoor(MfClassicPoller* in
|
|||||||
MfClassicPollerDictAttackContext* dict_attack_ctx = &instance->mode_ctx.dict_attack_ctx;
|
MfClassicPollerDictAttackContext* dict_attack_ctx = &instance->mode_ctx.dict_attack_ctx;
|
||||||
// TODO: Check for Fudan backdoor
|
// TODO: Check for Fudan backdoor
|
||||||
dict_attack_ctx->backdoor = MfClassicBackdoorNone;
|
dict_attack_ctx->backdoor = MfClassicBackdoorNone;
|
||||||
|
instance->state = MfClassicPollerStateNestedController;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -962,11 +949,7 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt(MfClassicPoller* instance
|
|||||||
|
|
||||||
NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* instance) {
|
NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* instance) {
|
||||||
// TODO: Collect parity
|
// TODO: Collect parity
|
||||||
// TODO: FURI_CRITICAL_ENTER
|
// TODO: Use the mode (most frequently observed) value and parity to reliably get a single candidate state
|
||||||
// xTickCount
|
|
||||||
// Modify targets/f7/furi_hal/furi_hal_rtc.c to expose sub-second time (https://stackoverflow.com/questions/55534873/how-to-setup-the-stm32f4-real-time-clockrtc-to-get-valid-values-in-the-sub-sec)
|
|
||||||
// furi_hal_rtc_get_timestamp isn't precise enough
|
|
||||||
// TODO: Measure ticks with https://github.com/flipperdevices/flipperzero-firmware/blob/bec6bd381f222cf14658fd862a2c7f6e620bbf00/targets/f7/furi_hal/furi_hal_idle_timer.h#L51
|
|
||||||
/*
|
/*
|
||||||
uint32_t ncount = 0;
|
uint32_t ncount = 0;
|
||||||
uint32_t nttest = prng_successor(nt1, dmin - 1);
|
uint32_t nttest = prng_successor(nt1, dmin - 1);
|
||||||
@@ -986,14 +969,15 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* inst
|
|||||||
// TODO: Target sector, key A/B
|
// TODO: Target sector, key A/B
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (dict_attack_ctx->prng_type == MfClassicPrngTypeHard) {
|
if(dict_attack_ctx->prng_type == MfClassicPrngTypeHard) {
|
||||||
FURI_LOG_E(TAG, "Hard PRNG, skipping calibration");
|
FURI_LOG_E(TAG, "Hard PRNG, skipping calibration");
|
||||||
// TODO: Collect hardnested nonces (cuid, sec, par, nt_enc, A/B)
|
// TODO: Collect hardnested nonces (cuid, sec, par, nt_enc, A/B)
|
||||||
// https://github.com/AloneLiberty/FlipperNested/blob/eba6163d7ef22adef5f9fe4d77a78ccfcc27a952/lib/nested/nested.c#L564-L645
|
// https://github.com/AloneLiberty/FlipperNested/blob/eba6163d7ef22adef5f9fe4d77a78ccfcc27a952/lib/nested/nested.c#L564-L645
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t block = mf_classic_get_first_block_num_of_sector(dict_attack_ctx->reuse_key_sector);
|
uint8_t block =
|
||||||
|
mf_classic_get_first_block_num_of_sector(dict_attack_ctx->reuse_key_sector);
|
||||||
uint32_t cuid = iso14443_3a_get_cuid(instance->data->iso14443_3a_data);
|
uint32_t cuid = iso14443_3a_get_cuid(instance->data->iso14443_3a_data);
|
||||||
|
|
||||||
MfClassicAuthContext auth_ctx = {};
|
MfClassicAuthContext auth_ctx = {};
|
||||||
@@ -1005,7 +989,6 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* inst
|
|||||||
uint32_t nt_enc_prev = 0;
|
uint32_t nt_enc_prev = 0;
|
||||||
uint32_t same_nt_enc_cnt = 0;
|
uint32_t same_nt_enc_cnt = 0;
|
||||||
bool static_encrypted = false;
|
bool static_encrypted = false;
|
||||||
// Store last timestamp
|
|
||||||
|
|
||||||
// Step 1: Perform full authentication once
|
// Step 1: Perform full authentication once
|
||||||
error = mf_classic_poller_auth(
|
error = mf_classic_poller_auth(
|
||||||
@@ -1015,7 +998,7 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* inst
|
|||||||
dict_attack_ctx->current_key_type,
|
dict_attack_ctx->current_key_type,
|
||||||
&auth_ctx);
|
&auth_ctx);
|
||||||
|
|
||||||
if (error != MfClassicErrorNone) {
|
if(error != MfClassicErrorNone) {
|
||||||
FURI_LOG_E(TAG, "Failed to perform full authentication");
|
FURI_LOG_E(TAG, "Failed to perform full authentication");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1025,7 +1008,7 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* inst
|
|||||||
nt_prev = bit_lib_bytes_to_num_be(auth_ctx.nt.data, sizeof(MfClassicNt));
|
nt_prev = bit_lib_bytes_to_num_be(auth_ctx.nt.data, sizeof(MfClassicNt));
|
||||||
|
|
||||||
// Step 2: Perform nested authentication multiple times
|
// Step 2: Perform nested authentication multiple times
|
||||||
for (uint32_t round_no = 0; round_no < rounds; round_no++) {
|
for(uint32_t round_no = 0; round_no < rounds; round_no++) {
|
||||||
error = mf_classic_poller_auth_nested(
|
error = mf_classic_poller_auth_nested(
|
||||||
instance,
|
instance,
|
||||||
block,
|
block,
|
||||||
@@ -1033,15 +1016,15 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* inst
|
|||||||
dict_attack_ctx->current_key_type,
|
dict_attack_ctx->current_key_type,
|
||||||
&auth_ctx);
|
&auth_ctx);
|
||||||
|
|
||||||
if (error != MfClassicErrorNone) {
|
if(error != MfClassicErrorNone) {
|
||||||
FURI_LOG_E(TAG, "Failed to perform nested authentication %lu", round_no);
|
FURI_LOG_E(TAG, "Failed to perform nested authentication %lu", round_no);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t nt_enc = bit_lib_bytes_to_num_be(auth_ctx.nt.data, sizeof(MfClassicNt));
|
uint32_t nt_enc = bit_lib_bytes_to_num_be(auth_ctx.nt.data, sizeof(MfClassicNt));
|
||||||
if (nt_enc == nt_enc_prev) {
|
if(nt_enc == nt_enc_prev) {
|
||||||
same_nt_enc_cnt++;
|
same_nt_enc_cnt++;
|
||||||
if (same_nt_enc_cnt > 3) {
|
if(same_nt_enc_cnt > 3) {
|
||||||
static_encrypted = true;
|
static_encrypted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1052,15 +1035,22 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* inst
|
|||||||
nt_enc_arr[round_no] = nt_enc;
|
nt_enc_arr[round_no] = nt_enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (static_encrypted) {
|
if(static_encrypted) {
|
||||||
FURI_LOG_E(TAG, "Static encrypted nonce detected");
|
FURI_LOG_E(TAG, "Static encrypted nonce detected");
|
||||||
if (dict_attack_ctx->backdoor == MfClassicBackdoorFM11RF08S) {
|
if(dict_attack_ctx->backdoor == MfClassicBackdoorFM11RF08S) {
|
||||||
// TODO: Backdoor static nested attack
|
// TODO: Backdoor static nested attack
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// TODO: If not present, just log nonces with parity bits
|
// TODO: If not present, just log nonces with parity bits
|
||||||
bool success = add_nested_nonce(&result, cuid, dict_attack_ctx->reuse_key_sector, nt_prev, nt_enc_prev, 0, 65535);
|
bool success = add_nested_nonce(
|
||||||
if (!success) {
|
&result,
|
||||||
|
cuid,
|
||||||
|
dict_attack_ctx->reuse_key_sector,
|
||||||
|
nt_prev,
|
||||||
|
nt_enc_prev,
|
||||||
|
0,
|
||||||
|
UINT16_MAX);
|
||||||
|
if(!success) {
|
||||||
FURI_LOG_E(TAG, "Failed to add nested nonce to array. OOM?");
|
FURI_LOG_E(TAG, "Failed to add nested nonce to array. OOM?");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1069,32 +1059,44 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* inst
|
|||||||
|
|
||||||
// Find the distance between each nonce
|
// Find the distance between each nonce
|
||||||
// TODO: Distance calculation
|
// TODO: Distance calculation
|
||||||
|
// TODO: Avoid repeated calibration
|
||||||
|
FURI_LOG_E(TAG, "Calibrating distance between nonces");
|
||||||
|
// Checking for d_min == 0 is more of a workaround for not having a proper calibration process
|
||||||
|
if(dict_attack_ctx->d_min == 0) dict_attack_ctx->d_min = UINT16_MAX;
|
||||||
uint64_t known_key = bit_lib_bytes_to_num_be(dict_attack_ctx->current_key.data, 6);
|
uint64_t known_key = bit_lib_bytes_to_num_be(dict_attack_ctx->current_key.data, 6);
|
||||||
Crypto1 crypto;
|
Crypto1 crypto;
|
||||||
crypto1_init(&crypto, known_key);
|
crypto1_init(&crypto, known_key);
|
||||||
// Skip the first round (typically an outlier)
|
for(uint32_t rtr = 0; rtr < rounds; rtr++) {
|
||||||
for (uint32_t rtr = 1; rtr < rounds; rtr++) {
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i = 0; i < 65535; i++) {
|
for(int i = 0; i < 65535; i++) {
|
||||||
Crypto1 crypto_temp = {.odd = crypto.odd, .even = crypto.even};
|
Crypto1 crypto_temp = {.odd = crypto.odd, .even = crypto.even};
|
||||||
uint32_t nth_successor = prng_successor(nt_prev, i);
|
uint32_t nth_successor = prng_successor(nt_prev, i);
|
||||||
if ((nth_successor ^ crypto1_word(&crypto_temp, cuid ^ nth_successor, 0)) == nt_enc_arr[rtr]) {
|
if((nth_successor ^ crypto1_word(&crypto_temp, cuid ^ nth_successor, 0)) !=
|
||||||
|
nt_enc_arr[rtr]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(rtr > 0) {
|
||||||
FURI_LOG_E(TAG, "nt_enc (plain) %08lx", nth_successor);
|
FURI_LOG_E(TAG, "nt_enc (plain) %08lx", nth_successor);
|
||||||
FURI_LOG_E(TAG, "dist from nt prev: %i", i);
|
FURI_LOG_E(TAG, "dist from nt prev: %i", i);
|
||||||
if (i > dict_attack_ctx->d_max) {
|
if(i > dict_attack_ctx->d_max) {
|
||||||
dict_attack_ctx->d_max = i;
|
dict_attack_ctx->d_max = i;
|
||||||
}
|
}
|
||||||
if (i < dict_attack_ctx->d_min) {
|
if(i < dict_attack_ctx->d_min) {
|
||||||
dict_attack_ctx->d_min = i;
|
dict_attack_ctx->d_min = i;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
nt_prev = nth_successor;
|
nt_prev = nth_successor;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
if(!found) {
|
||||||
if (!found) {
|
|
||||||
FURI_LOG_E(TAG, "Failed to find distance for nt_enc %08lx", nt_enc_arr[rtr]);
|
FURI_LOG_E(TAG, "Failed to find distance for nt_enc %08lx", nt_enc_arr[rtr]);
|
||||||
FURI_LOG_E(TAG, "using key %06llx and uid %08lx, nt_prev is %08lx", known_key, cuid, nt_prev);
|
FURI_LOG_E(
|
||||||
|
TAG,
|
||||||
|
"using key %06llx and uid %08lx, nt_prev is %08lx",
|
||||||
|
known_key,
|
||||||
|
cuid,
|
||||||
|
nt_prev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool is_static = (dict_attack_ctx->d_min == dict_attack_ctx->d_max);
|
bool is_static = (dict_attack_ctx->d_min == dict_attack_ctx->d_max);
|
||||||
@@ -1107,6 +1109,7 @@ NfcCommand mf_classic_poller_handler_nested_collect_nt_enc(MfClassicPoller* inst
|
|||||||
is_static ? "true" : "false");
|
is_static ? "true" : "false");
|
||||||
|
|
||||||
//printf("ks: %08x\n", nth_successor ^ nt_enc);
|
//printf("ks: %08x\n", nth_successor ^ nt_enc);
|
||||||
|
//dict_attack_ctx->nested_target_key
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
instance->state = MfClassicPollerStateNestedController;
|
instance->state = MfClassicPollerStateNestedController;
|
||||||
@@ -1135,18 +1138,31 @@ NfcCommand mf_classic_poller_handler_nested_log(MfClassicPoller* instance) {
|
|||||||
FuriString* temp_str = furi_string_alloc();
|
FuriString* temp_str = furi_string_alloc();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) && (dict_attack_ctx->nested_nonce.count != 2)) {
|
if((dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) &&
|
||||||
FURI_LOG_E(TAG, "MfClassicPollerStateNestedLog expected 2 nonces, received %u", dict_attack_ctx->nested_nonce.count);
|
(dict_attack_ctx->nested_nonce.count != 2)) {
|
||||||
|
FURI_LOG_E(
|
||||||
|
TAG,
|
||||||
|
"MfClassicPollerStateNestedLog expected 2 nonces, received %u",
|
||||||
|
dict_attack_ctx->nested_nonce.count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!buffered_file_stream_open(stream, MF_CLASSIC_NESTED_LOGS_FILE_PATH, FSAM_WRITE, FSOM_OPEN_APPEND)) break;
|
if(!buffered_file_stream_open(
|
||||||
|
stream, MF_CLASSIC_NESTED_LOGS_FILE_PATH, FSAM_WRITE, FSOM_OPEN_APPEND))
|
||||||
|
break;
|
||||||
|
|
||||||
bool params_write_success = true;
|
bool params_write_success = true;
|
||||||
for(size_t i = 0; i < dict_attack_ctx->nested_nonce.count; i++) {
|
for(size_t i = 0; i < dict_attack_ctx->nested_nonce.count; i++) {
|
||||||
MfClassicNestedNonce* nonce = &dict_attack_ctx->nested_nonce.nonces[i];
|
MfClassicNestedNonce* nonce = &dict_attack_ctx->nested_nonce.nonces[i];
|
||||||
furi_string_printf(temp_str, "Sec %d key %c cuid %08lx", (nonce->key_idx / 2), (nonce->key_idx % 2 == 0) ? 'A' : 'B', nonce->cuid);
|
furi_string_printf(
|
||||||
for(uint8_t nt_idx = 0; nt_idx < ((dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) ? 2 : 1); nt_idx++) {
|
temp_str,
|
||||||
|
"Sec %d key %c cuid %08lx",
|
||||||
|
(nonce->key_idx / 2),
|
||||||
|
(nonce->key_idx % 2 == 0) ? 'A' : 'B',
|
||||||
|
nonce->cuid);
|
||||||
|
for(uint8_t nt_idx = 0;
|
||||||
|
nt_idx < ((dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) ? 2 : 1);
|
||||||
|
nt_idx++) {
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
" nt%u %08lx ks%u %08lx par%u ",
|
" nt%u %08lx ks%u %08lx par%u ",
|
||||||
@@ -1159,7 +1175,7 @@ NfcCommand mf_classic_poller_handler_nested_log(MfClassicPoller* instance) {
|
|||||||
furi_string_cat_printf(temp_str, "%u", (nonce->par >> (3 - pb)) & 1);
|
furi_string_cat_printf(temp_str, "%u", (nonce->par >> (3 - pb)) & 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) {
|
if(dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) {
|
||||||
furi_string_cat_printf(temp_str, " dist %u\n", nonce->dist);
|
furi_string_cat_printf(temp_str, " dist %u\n", nonce->dist);
|
||||||
} else {
|
} else {
|
||||||
furi_string_cat_printf(temp_str, "\n");
|
furi_string_cat_printf(temp_str, "\n");
|
||||||
@@ -1189,21 +1205,21 @@ NfcCommand mf_classic_poller_handler_nested_controller(MfClassicPoller* instance
|
|||||||
// Iterate through keys
|
// Iterate through keys
|
||||||
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;
|
||||||
if (dict_attack_ctx->nested_nonce.count > 0) {
|
if(dict_attack_ctx->nested_nonce.count > 0) {
|
||||||
if (dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) {
|
if(dict_attack_ctx->prng_type == MfClassicPrngTypeWeak) {
|
||||||
instance->state = MfClassicPollerStateNestedDictAttack;
|
instance->state = MfClassicPollerStateNestedDictAttack;
|
||||||
return command;
|
return command;
|
||||||
} else if (dict_attack_ctx->prng_type == MfClassicPrngTypeHard) {
|
} else if(dict_attack_ctx->prng_type == MfClassicPrngTypeHard) {
|
||||||
instance->state = MfClassicPollerStateNestedLog;
|
instance->state = MfClassicPollerStateNestedLog;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dict_attack_ctx->backdoor == MfClassicBackdoorUnknown) {
|
if(dict_attack_ctx->backdoor == MfClassicBackdoorUnknown) {
|
||||||
instance->state = MfClassicPollerStateNestedAnalyzeBackdoor;
|
instance->state = MfClassicPollerStateNestedAnalyzeBackdoor;
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
// Target all sectors, key A and B
|
// Target all sectors, key A and B
|
||||||
for (uint8_t key_idx = 0; key_idx <= (instance->sectors_total * 2); key_idx++) {
|
for(uint8_t key_idx = 0; key_idx <= (instance->sectors_total * 2); key_idx++) {
|
||||||
dict_attack_ctx->nested_target_key = key_idx;
|
dict_attack_ctx->nested_target_key = key_idx;
|
||||||
instance->state = MfClassicPollerStateNestedCollectNtEnc;
|
instance->state = MfClassicPollerStateNestedCollectNtEnc;
|
||||||
return command;
|
return command;
|
||||||
@@ -1253,15 +1269,12 @@ static const MfClassicPollerReadHandler
|
|||||||
[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,
|
||||||
[MfClassicPollerStateNestedAnalyzePRNG] = mf_classic_poller_handler_nested_analyze_prng,
|
[MfClassicPollerStateNestedAnalyzePRNG] = mf_classic_poller_handler_nested_analyze_prng,
|
||||||
[MfClassicPollerStateNestedAnalyzeBackdoor] = mf_classic_poller_handler_nested_analyze_backdoor,
|
[MfClassicPollerStateNestedAnalyzeBackdoor] =
|
||||||
[MfClassicPollerStateNestedCollectNt] =
|
mf_classic_poller_handler_nested_analyze_backdoor,
|
||||||
mf_classic_poller_handler_nested_collect_nt,
|
[MfClassicPollerStateNestedCollectNt] = mf_classic_poller_handler_nested_collect_nt,
|
||||||
[MfClassicPollerStateNestedController] =
|
[MfClassicPollerStateNestedController] = mf_classic_poller_handler_nested_controller,
|
||||||
mf_classic_poller_handler_nested_controller,
|
[MfClassicPollerStateNestedCollectNtEnc] = mf_classic_poller_handler_nested_collect_nt_enc,
|
||||||
[MfClassicPollerStateNestedCollectNtEnc] =
|
[MfClassicPollerStateNestedDictAttack] = mf_classic_poller_handler_nested_dict_attack,
|
||||||
mf_classic_poller_handler_nested_collect_nt_enc,
|
|
||||||
[MfClassicPollerStateNestedDictAttack] =
|
|
||||||
mf_classic_poller_handler_nested_dict_attack,
|
|
||||||
[MfClassicPollerStateNestedLog] = mf_classic_poller_handler_nested_log,
|
[MfClassicPollerStateNestedLog] = mf_classic_poller_handler_nested_log,
|
||||||
[MfClassicPollerStateSuccess] = mf_classic_poller_handler_success,
|
[MfClassicPollerStateSuccess] = mf_classic_poller_handler_success,
|
||||||
[MfClassicPollerStateFail] = mf_classic_poller_handler_fail,
|
[MfClassicPollerStateFail] = mf_classic_poller_handler_fail,
|
||||||
|
|||||||
Reference in New Issue
Block a user