uniformize tools/mfc/card_reader

This commit is contained in:
Philippe Teuwen 2024-09-02 11:11:40 +02:00
commit 5b6a898fe7
7 changed files with 60 additions and 54 deletions

View file

@ -645,11 +645,11 @@ static void *brute_key_thread(void *arguments) {
static int usage(void) {
printf("\n");
printf("syntax: mf_nonce_brute <uid> <nt> <nt_par_err> <nr> <ar> <ar_par_err> <at> <at_par_err> [<next_command>]\n\n");
printf("syntax: mf_nonce_brute <uid> <{nt}> <nt_par_err> <{nr}> <{ar}> <ar_par_err> <{at}> <at_par_err> [<{next_command}>]\n\n");
printf("how to convert trace data to needed input:\n");
printf(" nt in trace = 8c! 42 e6! 4e!\n");
printf(" nt = 8c42e64e\n");
printf(" nt_par_err = 1011\n\n");
printf(" {nt} in trace = 8c! 42 e6! 4e!\n");
printf(" => {nt} = 8c42e64e\n");
printf(" => nt_par_err = 1011\n\n");
printf("samples:\n");
printf("\n");
printf(" ./mf_nonce_brute fa247164 fb47c594 0000 71909d28 0c254817 1000 0dc7cfbd 1110\n");

View file

@ -20,8 +20,8 @@ Sample trace:
TAG 08 b6 dd // sak
60 04 d1 3d // wanna auth block 0x04 with A key
TAG ed 12 9c 74 // 1st auth clear text nt
55 53 9f cc 41 8d e8 f3 // nr', ar' (nr^ks1, ar^ks2 )
TAG 05 49 e1 65 // at' ( at^ks3 )
55 53 9f cc 41 8d e8 f3 // {nr}, {ar} (nr^ks1, ar^ks2 )
TAG 05 49 e1 65 // {at} ( at^ks3 )
03 24 26 56 // wanna read block 0x04
TAG ac 69 ef 58 45 e1 c2 1d a9 47 a5 94 54 ef 5d c7 1e a9 // block 0x04 content
d4 3e a8 aa
@ -35,8 +35,8 @@ TAG a3 76 dc df c1 42 e0 ee c6 75 a4 ca eb 0c da eb 46 a0 // 18 bytes = 16 byte
-------Until this line we can recover key or decrypt communication with no troubles (see mfkey64 tool)--------------------------------
TAG 52 6e af 8b // nested auth encrypted tag nonce that we don't know
8e 21 3a 29 a4 80 7e 02 // nr_enc = nr^ks1, ar_enc = ar^ks2
TAG b9 43 74 8d // at_enc = at^ks3
8e 21 3a 29 a4 80 7e 02 // {nr} = nr^ks1, {ar} = ar^ks2
TAG b9 43 74 8d // {at} = at^ks3
e2 25 f8 32 // probably next command (actually is read block cmd, but we don't know it yet)
TAG 1f 26 82 8d 12 21 dd 42 c2 84 3e d0 26 7f 6b 2a 81 a9 // probably data
ba 85 1d 36 // probably read cmd
@ -54,7 +54,7 @@ Phase 1
Syntax:
`mf_nonce_brute <uid> <{nt}> <nt_par_err> <{nr}> <{ar}> <ar_par_err> <{at}> <at_par_err> [<{next_command}>]`
Example: if `nt` in trace is `8c! 42 e6! 4e!`, then `nt` is `8c42e64e` and `nt_par_err` is `1011`
Example: if `{nt}` in trace is `8c! 42 e6! 4e!`, then `{nt}` is `8c42e64e` and `nt_par_err` is `1011`
Example with parity (from this trace http://www.proxmark.org/forum/viewtopic.php?pid=550#p550) :
@ -66,13 +66,13 @@ Example with parity (from this trace http://www.proxmark.org/forum/viewtopic.php
+ 12313: 9 : 93 70 9c 59 9b 32 6c 6b 30
+ 64: 3 : TAG 08 b6 dd
+ 923318: 4 : 60 00 f5 7b AUTH Block 0
+ 112: 4 : TAG 82 a4 16 6c Nonce Tag (NT)
+ 6985: 8 : a1 e4! 58 ce! 6e ea! 41 e0! NR , AR
+ 64: 4 : TAG 5c! ad f4 39! AT
+ 112: 4 : TAG 82 a4 16 6c Nonce Tag (nt)
+ 6985: 8 : a1 e4! 58 ce! 6e ea! 41 e0! {nr}, {ar}
+ 64: 4 : TAG 5c! ad f4 39! {at}
+ 811513: 4 : 8e 0e! 5d! b9 AUTH Block 0 (nested)
+ 112: 4 : TAG 5a! 92 0d! 85! Nonce Tag (NT)
+ 6946: 8 : 98! d7 6b! 77 d6 c6 e8 70 NR , AR
+ 64: 4 : TAG ca 7e! 0b! 63! AT
+ 112: 4 : TAG 5a! 92 0d! 85! Nonce Tag ({nt})
+ 6946: 8 : 98! d7 6b! 77 d6 c6 e8 70 {nr}, {ar}
+ 64: 4 : TAG ca 7e! 0b! 63! {at}
+ 670868: 4 : 3e! 70 9c! 8a
+ 112: 4 : TAG 36! 41 24! 79
+ 9505: 8 : 1b! 8c 3a! 48! 83 5a 4a! 27
@ -87,7 +87,7 @@ Example with parity (from this trace http://www.proxmark.org/forum/viewtopic.php
```
./mf_nonce_brute 9c599b32 82a4166c 0000 a1e458ce 6eea41e0 0101 5cadf439 1001 8e0e5db9
| | | | | | | | |
+UID +nt_enc | +nr_enc +ar_enc | +at_enc | +encrypted next cmd
+UID +nt | +{nr} +{ar} | +{at} | +{next cmd}
+nt_par_err +at_par_err +at_par_err
```
@ -97,12 +97,12 @@ These two taken from above use the plaintext tagnonce `nt`=`82a4166c`, they sti
./mf_nonce_brute 9c599b32 82a4166c 0000 98d76b77 d6c6e870 0000 ca7e0b63 0111
```
This one uses the encrypted tagnonce `nt`=`5a920d85`, it finds a valid key.
This one uses the encrypted tagnonce `{nt}`=`5a920d85`, it finds a valid key.
```
./mf_nonce_brute 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111
```
This one uses the encrypted tagnonce `nt`=`5a920d85` and the encrypted cmd `3e709c8a` to validate , it finds a valid key.
This one uses the encrypted tagnonce `{nt}`=`5a920d85` and the encrypted cmd `3e709c8a` to validate , it finds a valid key.
```
./mf_nonce_brute 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111 3e709c8a
```

View file

@ -243,7 +243,7 @@ static void *brute_thread(void *arguments) {
}
static int usage(void) {
printf(" syntax: mf_trace_brute <uid> <partial key> <nt enc> <nr enc> [<next_command + 18 bytes>]\n\n");
printf(" syntax: mf_trace_brute <uid> <partial key> <{nt}> <{nr}> [<{next_command + 18 bytes}>]\n\n");
return 1;
}

View file

@ -15,13 +15,14 @@ int main(int argc, char *argv[]) {
uint32_t ar0_enc; // first encrypted reader response
uint32_t nr1_enc; // second encrypted reader challenge
uint32_t ar1_enc; // second encrypted reader response
uint32_t ks2; // keystream used to encrypt reader response
uint32_t ks2_0; // first keystream used to encrypt reader response
uint32_t ks2_1; // second keystream used to encrypt reader response
printf("MIFARE Classic key recovery - based on 32 bits of keystream\n");
printf("Recover key from two 32-bit reader authentication answers only!\n\n");
if (argc < 7) {
printf(" syntax: %s <uid> <nt> <nr_0> <ar_0> <nr_1> <ar_1>\n\n", argv[0]);
printf(" syntax: %s <uid> <nt> <{nr_0}> <{ar}_0> <{nr_1}> <{ar}_0>\n\n", argv[0]);
return 1;
}
@ -36,22 +37,23 @@ int main(int argc, char *argv[]) {
printf(" uid: %08x\n", uid);
printf(" nt: %08x\n", nt);
printf(" {nr_0}: %08x\n", nr0_enc);
printf(" {ar_0}: %08x\n", ar0_enc);
printf(" {ar}_0: %08x\n", ar0_enc);
printf(" {nr_1}: %08x\n", nr1_enc);
printf(" {ar_1}: %08x\n", ar1_enc);
printf(" {ar}_1: %08x\n", ar1_enc);
// Generate lfsr successors of the tag challenge
printf("\nLFSR successors of the tag challenge:\n");
uint32_t p64 = prng_successor(nt, 64);
printf(" nt': %08x\n", p64);
printf(" nt'': %08x\n", prng_successor(p64, 32));
printf("\nLFSR successor of the tag challenge:\n");
uint32_t ar = prng_successor(nt, 64);
printf(" ar: %08x\n", ar);
// Extract the keystream from the messages
printf("\nKeystream used to generate {ar} and {at}:\n");
ks2 = ar0_enc ^ p64;
printf(" ks2: %08x\n", ks2);
printf("\nKeystreams used to generate {ar}_0 and {ar}_1:\n");
ks2_0 = ar0_enc ^ ar;
printf(" ks2_0: %08x\n", ks2_0);
ks2_1 = ar1_enc ^ ar;
printf(" ks2_1: %08x\n", ks2_1);
s = lfsr_recovery32(ar0_enc ^ p64, 0);
s = lfsr_recovery32(ks2_0, 0);
for (t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
@ -60,7 +62,7 @@ int main(int argc, char *argv[]) {
crypto1_get_lfsr(t, &key);
crypto1_word(t, uid ^ nt, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ p64)) {
if (ks2_1 == crypto1_word(t, 0, 0)) {
printf("\nFound Key: [%012" PRIx64 "]\n\n", key);
break;
}

View file

@ -16,14 +16,15 @@ int main(int argc, char *argv[]) {
uint32_t ar0_enc; // first encrypted reader response
uint32_t nr1_enc; // second encrypted reader challenge
uint32_t ar1_enc; // second encrypted reader response
uint32_t ks2; // keystream used to encrypt reader response
uint32_t ks2_0; // first keystream used to encrypt reader response
uint32_t ks2_1; // second keystream used to encrypt reader response
printf("MIFARE Classic key recovery - based 32 bits of keystream VERSION2\n");
printf("Recover key from two 32-bit reader authentication answers only\n");
printf("This version implements Moebius two different nonce solution (like the supercard)\n\n");
if (argc < 8) {
printf("syntax: %s <uid> <nt> <nr_0> <ar_0> <nt1> <nr_1> <ar_1>\n\n", argv[0]);
printf("syntax: %s <uid> <{nt_0}> <{nr_0}> <{ar_0}> <{nt_1}> <{nr_1}> <{ar_1}>\n\n", argv[0]);
return 1;
}
@ -45,19 +46,21 @@ int main(int argc, char *argv[]) {
printf(" {ar_1}: %08x\n", ar1_enc);
// Generate lfsr successors of the tag challenge
printf("\nLFSR successors of the tag challenge:\n");
uint32_t p64 = prng_successor(nt0, 64);
uint32_t p64b = prng_successor(nt1, 64);
printf("\nLFSR successors of the tag challenges:\n");
uint32_t ar0 = prng_successor(nt0, 64);
uint32_t ar1 = prng_successor(nt1, 64);
printf(" nt': %08x\n", p64);
printf(" nt'': %08x\n", prng_successor(p64, 32));
printf(" ar_0: %08x\n", ar0);
printf(" ar_1: %08x\n", ar1);
// Extract the keystream from the messages
printf("\nKeystream used to generate {ar} and {at}:\n");
ks2 = ar0_enc ^ p64;
printf(" ks2: %08x\n", ks2);
printf("\nKeystreams used to generate {ar_0} and {ar_1}:\n");
ks2_0 = ar0_enc ^ ar0;
printf(" ks2_0: %08x\n", ks2_0);
ks2_1 = ar1_enc ^ ar1;
printf(" ks2_1: %08x\n", ks2_1);
s = lfsr_recovery32(ar0_enc ^ p64, 0);
s = lfsr_recovery32(ks2_0, 0);
for (t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
@ -67,7 +70,7 @@ int main(int argc, char *argv[]) {
crypto1_word(t, uid ^ nt1, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ p64b)) {
if (ks2_1 == crypto1_word(t, 0, 0)) {
printf("\nFound Key: [%012" PRIx64 "]\n\n", key);
break;
}

View file

@ -60,14 +60,15 @@ int main(int argc, char *argv[]) {
// Generate lfsr successors of the tag challenge
printf("\nLFSR successors of the tag challenge:\n");
uint32_t p64 = prng_successor(nt, 64);
printf(" nt': %08x\n", p64);
printf(" nt'': %08x\n", prng_successor(p64, 32));
uint32_t ar = prng_successor(nt, 64);
uint32_t at = prng_successor(ar, 32);
printf(" ar: %08x\n", ar);
printf(" at: %08x\n", at);
// Extract the keystream from the messages
printf("\nKeystream used to generate {ar} and {at}:\n");
ks2 = ar_enc ^ p64;
ks3 = at_enc ^ prng_successor(p64, 32);
printf("\nKeystreams used to generate {ar} and {at}:\n");
ks2 = ar_enc ^ ar;
ks3 = at_enc ^ at;
printf(" ks2: %08x\n", ks2);
printf(" ks3: %08x\n", ks3);

View file

@ -19,8 +19,8 @@ Usage with sample trace:
For mfkey32, you want to get two different NR_0/NR_1 values.
```
# <uid> <nt> <nr_0> <ar_0> <nr_1> <ar_1>
./mfkey32 52B0F519 5417D1F8 4D545EA7 E15AC8C2 DAC1A7F4 5AE5C37F
# <uid> <nt> <{nr_0}> <{ar}_0> <{nr_1}> <{ar}_1>
./mfkey32 57DA41DA 01200145 7B70C62C 909121F2 F9206A8B 908B8981
```
For mfkey32v2 (moebius), you want to get two different NT/NT1 values. (like in the SIM commands)
@ -83,8 +83,8 @@ Recovering key for:
{enc8}: 9f9149ea
LFSR successors of the tag challenge:
nt': 76d4468d
nt'': d5f3c476
ar: 76d4468d
at: d5f3c476
Keystream used to generate {ar} and {at}:
ks2: 73f18ec2