Skip to content

Commit 3650991

Browse files
committed
1.4.0 - Huge update
Changes: - Changed scenes, now they are more informative and beautiful (closes #6) - Check if sector is alive in Nested attacks (closes #5) - Now tag PRNG detected at sector, where key is available (fix not working with dead 0 sector, closes #4) - Detect hard PRNG from start, hardnested doesn't require calibration now - Settings menu: ability to always run Hard Nested (regardless of PRNG) - Minor code refactoring, a lot of bug fixes (memory leaks, stability improvements) - Fallback to Hard Nested now after 25 failed tries (was 10) Hope I didn't break everything, but who knows...
1 parent fb317df commit 3650991

21 files changed

+466
-224
lines changed

application.fam

+4-10
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,13 @@ App(
1313
fap_icon="assets/icon.png",
1414
fap_category="NFC",
1515
fap_private_libs=[
16-
Lib(
17-
name="nested",
18-
),
19-
Lib(
20-
name="parity",
21-
),
22-
Lib(
23-
name="crypto1",
24-
)
16+
Lib(name="nested"),
17+
Lib(name="parity"),
18+
Lib(name="crypto1")
2519
],
2620
fap_icon_assets="assets",
2721
fap_author="AloneLiberty",
2822
fap_description="Recover Mifare Classic keys",
2923
fap_weburl="https://github.com/AloneLiberty/FlipperNested",
30-
fap_version=(1,3)
24+
fap_version=(1, 4)
3125
)

lib/nested/nested.c

+76-18
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,42 @@ static int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, const uint8_t*
169169
0;
170170
}
171171

172-
MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx) {
172+
void nonce_distance_notable(uint32_t* msb, uint32_t* lsb) {
173+
uint16_t x = 1, pos;
174+
uint8_t calc_ok = 0;
175+
176+
for(uint16_t i = 1; i; ++i) {
177+
pos = (x & 0xff) << 8 | x >> 8;
178+
179+
if((pos == *msb) & !(calc_ok >> 0 & 0x01)) {
180+
*msb = i;
181+
calc_ok |= 0x01;
182+
}
183+
184+
if((pos == *lsb) & !(calc_ok >> 1 & 0x01)) {
185+
*lsb = i;
186+
calc_ok |= 0x02;
187+
}
188+
189+
if(calc_ok == 0x03) {
190+
return;
191+
}
192+
193+
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
194+
}
195+
}
196+
197+
bool validate_prng_nonce_notable(uint32_t nonce) {
198+
uint32_t msb = nonce >> 16;
199+
uint32_t lsb = nonce & 0xffff;
200+
nonce_distance_notable(&msb, &lsb);
201+
return ((65535 - msb + lsb) % 65535) == 16;
202+
}
203+
204+
MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo) {
173205
uint32_t nonces[5] = {};
174-
uint16_t sameNonces = 0;
206+
uint8_t sameNonces = 0;
207+
uint8_t hardNonces = 0;
175208
Crypto1 crypt;
176209
Crypto1* crypto = {&crypt};
177210

@@ -181,15 +214,15 @@ MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx) {
181214
furi_hal_nfc_activate_nfca(100, NULL);
182215

183216
// Start communication
184-
bool success = mifare_sendcmd_short(crypto, tx_rx, false, 0x60, 0);
217+
bool success = mifare_sendcmd_short(crypto, tx_rx, false, 0x60, blockNo);
185218
if(!success) {
186219
continue;
187220
};
188221

189-
uint32_t byte = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4);
190-
191-
if(byte == 0) continue;
192-
nonces[i] = byte;
222+
uint32_t nt = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4);
223+
if(nt == 0) continue;
224+
if(!validate_prng_nonce_notable(nt)) hardNonces++;
225+
nonces[i] = nt;
193226

194227
nfc_deactivate();
195228
}
@@ -208,9 +241,13 @@ MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx) {
208241

209242
if(sameNonces > 3) {
210243
return MifareNestedNonceStatic;
211-
} else {
212-
return MifareNestedNonce;
213244
}
245+
246+
if(hardNonces > 3) {
247+
return MifareNestedNonceHard;
248+
}
249+
250+
return MifareNestedNonceWeak;
214251
}
215252

216253
struct nonce_info_static nested_static_nonce_attack(
@@ -404,12 +441,10 @@ struct distance_info nested_calibrate_distance_info(
404441
if(i != 65565) {
405442
if(rtr != 0) {
406443
davg += i;
407-
if(i != 0) {
408-
if(dmin == 0) {
409-
dmin = i;
410-
} else {
411-
dmin = MIN(dmin, i);
412-
}
444+
if(dmin == 0) {
445+
dmin = i;
446+
} else {
447+
dmin = MIN(dmin, i);
413448
}
414449
dmax = MAX(dmax, i);
415450
}
@@ -469,7 +504,10 @@ struct nonce_info nested_attack(
469504

470505
while(r.target_nt[i] == 0) { // continue until we have an unambiguous nonce
471506
nfc_activate();
472-
if(!furi_hal_nfc_activate_nfca(200, &cuid)) return r;
507+
if(!furi_hal_nfc_activate_nfca(200, &cuid)) {
508+
free(crypto);
509+
return r;
510+
}
473511

474512
r.cuid = cuid;
475513

@@ -524,7 +562,7 @@ struct nonce_info nested_attack(
524562
break;
525563
}
526564

527-
FURI_LOG_D(TAG, "Nonce#%lu: valid, ntdist=%li", i + 1, j);
565+
FURI_LOG_D(TAG, "Nonce#%lu: valid, ntdist=%lu", i + 1, j);
528566
}
529567
}
530568

@@ -635,22 +673,42 @@ NestedCheckKeyResult nested_check_key(
635673
uint64_t ui64Key) {
636674
uint32_t cuid = 0;
637675
uint32_t nt;
638-
Crypto1* crypto = malloc(sizeof(Crypto1));
639676

640677
nfc_activate();
641678
if(!furi_hal_nfc_activate_nfca(200, &cuid)) return NestedCheckKeyNoTag;
642679

643680
FURI_LOG_D(
644681
TAG, "Checking %c key %012llX for block %u", !keyType ? 'A' : 'B', ui64Key, blockNo);
645682

683+
Crypto1* crypto = malloc(sizeof(Crypto1));
684+
646685
bool success =
647686
mifare_classic_authex(crypto, tx_rx, cuid, blockNo, keyType, ui64Key, false, &nt);
648687

688+
free(crypto);
689+
649690
nfc_deactivate();
650691

651692
return success ? NestedCheckKeyValid : NestedCheckKeyInvalid;
652693
}
653694

695+
bool nested_check_block(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo, uint8_t keyType) {
696+
uint32_t cuid = 0;
697+
698+
nfc_activate();
699+
if(!furi_hal_nfc_activate_nfca(200, &cuid)) return false;
700+
701+
Crypto1* crypto = malloc(sizeof(Crypto1));
702+
703+
bool success = mifare_sendcmd_short(crypto, tx_rx, false, 0x60 + (keyType & 0x01), blockNo);
704+
705+
free(crypto);
706+
707+
nfc_deactivate();
708+
709+
return success;
710+
}
711+
654712
void nested_get_data(FuriHalNfcDevData* dev_data) {
655713
nfc_activate();
656714
furi_hal_nfc_detect(dev_data, 400);

lib/nested/nested.h

+6-4
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010

1111
typedef enum {
1212
MifareNestedNonceNoTag,
13-
14-
MifareNestedNonce,
15-
MifareNestedNonceStatic
13+
MifareNestedNonceWeak,
14+
MifareNestedNonceStatic,
15+
MifareNestedNonceHard,
1616
} MifareNestedNonceType;
1717

18-
MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx);
18+
MifareNestedNonceType nested_check_nonce_type(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo);
1919

2020
struct nonce_info_static {
2121
uint32_t cuid;
@@ -99,6 +99,8 @@ NestedCheckKeyResult nested_check_key(
9999
uint8_t keyType,
100100
uint64_t ui64Key);
101101

102+
bool nested_check_block(FuriHalNfcTxRxContext* tx_rx, uint8_t blockNo, uint8_t keyType);
103+
102104
void nested_get_data();
103105

104106
bool mifare_classic_authex(

mifare_nested.c

+22
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,13 @@ MifareNested* mifare_nested_alloc() {
270270
MifareNestedViewWidget,
271271
widget_get_view(mifare_nested->widget));
272272

273+
// Variable Item List
274+
mifare_nested->variable_item_list = variable_item_list_alloc();
275+
view_dispatcher_add_view(
276+
mifare_nested->view_dispatcher,
277+
MifareNestedViewVariableList,
278+
variable_item_list_get_view(mifare_nested->variable_item_list));
279+
273280
// Nested attack state
274281
NestedState* plugin_state = collection_alloc();
275282
view_set_context(plugin_state->view, mifare_nested);
@@ -287,6 +294,10 @@ MifareNested* mifare_nested_alloc() {
287294
KeyInfo_t* key_info = malloc(sizeof(KeyInfo_t));
288295
mifare_nested->keys = key_info;
289296

297+
MifareNestedSettings* settings = malloc(sizeof(MifareNestedSettings));
298+
settings->only_hardnested = false;
299+
mifare_nested->settings = settings;
300+
290301
view_set_draw_callback(plugin_state->view, nested_draw_callback);
291302
view_set_input_callback(plugin_state->view, nested_input_callback);
292303

@@ -325,15 +336,26 @@ void mifare_nested_free(MifareNested* mifare_nested) {
325336
view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewWidget);
326337
widget_free(mifare_nested->widget);
327338

339+
// Variable Item List
340+
view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewVariableList);
341+
variable_item_list_free(mifare_nested->variable_item_list);
342+
328343
// Nested
329344
view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewCollecting);
330345

331346
// Check keys
332347
view_dispatcher_remove_view(mifare_nested->view_dispatcher, MifareNestedViewCheckKeys);
333348

349+
// Nonces states
334350
free(mifare_nested->nonces);
335351
free(mifare_nested->nested_state);
336352

353+
// Keys
354+
free(mifare_nested->keys);
355+
356+
// Settings
357+
free(mifare_nested->settings);
358+
337359
// Worker
338360
mifare_nested_worker_stop(mifare_nested->worker);
339361
mifare_nested_worker_free(mifare_nested->worker);

mifare_nested_i.h

+11-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
#include <storage/storage.h>
1818
#include <lib/toolbox/path.h>
1919
#include <lib/nfc/nfc_device.h>
20+
#include <lib/toolbox/value_index.h>
21+
#include <gui/modules/variable_item_list.h>
2022
#include "mifare_nested_icons.h"
2123

22-
#define NESTED_VERSION_APP "1.3.0"
24+
#define NESTED_VERSION_APP "1.4.0"
2325
#define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested"
2426
#define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery"
2527
#define NESTED_NONCE_FORMAT_VERSION "3"
@@ -33,6 +35,7 @@ enum MifareNestedCustomEvent {
3335
MifareNestedCustomEventWorkerExit,
3436
MifareNestedCustomEventByteInputDone,
3537
MifareNestedCustomEventTextInputDone,
38+
MifareNestedCustomEventSceneSettingLock
3639
};
3740

3841
typedef void (*NestedCallback)(void* context);
@@ -67,6 +70,10 @@ typedef struct {
6770
InputEvent input;
6871
} PluginEvent;
6972

73+
typedef struct {
74+
bool only_hardnested;
75+
} MifareNestedSettings;
76+
7077
typedef enum { NestedRunIdle, NestedRunCheckKeys, NestedRunAttack } NestedRunNext;
7178

7279
struct MifareNested {
@@ -76,7 +83,8 @@ struct MifareNested {
7683
NotificationApp* notifications;
7784
SceneManager* scene_manager;
7885
NfcDevice* nfc_dev;
79-
86+
VariableItemList* variable_item_list;
87+
MifareNestedSettings* settings;
8088
FuriString* text_box_store;
8189

8290
// Common Views
@@ -103,6 +111,7 @@ typedef enum {
103111
MifareNestedViewLoading,
104112
MifareNestedViewTextInput,
105113
MifareNestedViewWidget,
114+
MifareNestedViewVariableList,
106115
MifareNestedViewCollecting,
107116
MifareNestedViewCheckKeys,
108117
} MifareNestedView;

0 commit comments

Comments
 (0)