From 5b6a898fe7189c26bfccba7d2b3d360451c2caa1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 2 Sep 2024 11:11:40 +0200 Subject: [PATCH] uniformize tools/mfc/card_reader --- tools/mfc/card_reader/mf_nonce_brute.c | 8 +++--- .../card_reader/mf_nonce_brute_examples.md | 28 +++++++++---------- tools/mfc/card_reader/mf_trace_brute.c | 2 +- tools/mfc/card_reader/mfkey32.c | 28 ++++++++++--------- tools/mfc/card_reader/mfkey32v2.c | 27 ++++++++++-------- tools/mfc/card_reader/mfkey64.c | 13 +++++---- tools/mfc/card_reader/mfkey_examples.md | 8 +++--- 7 files changed, 60 insertions(+), 54 deletions(-) diff --git a/tools/mfc/card_reader/mf_nonce_brute.c b/tools/mfc/card_reader/mf_nonce_brute.c index 36652a685..8f812960d 100644 --- a/tools/mfc/card_reader/mf_nonce_brute.c +++ b/tools/mfc/card_reader/mf_nonce_brute.c @@ -645,11 +645,11 @@ static void *brute_key_thread(void *arguments) { static int usage(void) { printf("\n"); - printf("syntax: mf_nonce_brute []\n\n"); + printf("syntax: mf_nonce_brute <{nt}> <{nr}> <{ar}> <{at}> [<{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"); diff --git a/tools/mfc/card_reader/mf_nonce_brute_examples.md b/tools/mfc/card_reader/mf_nonce_brute_examples.md index a5d95f864..a13ade916 100644 --- a/tools/mfc/card_reader/mf_nonce_brute_examples.md +++ b/tools/mfc/card_reader/mf_nonce_brute_examples.md @@ -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 <{nt}> <{nr}> <{ar}> <{at}> [<{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 ``` diff --git a/tools/mfc/card_reader/mf_trace_brute.c b/tools/mfc/card_reader/mf_trace_brute.c index c416c006f..1a8ce84c8 100644 --- a/tools/mfc/card_reader/mf_trace_brute.c +++ b/tools/mfc/card_reader/mf_trace_brute.c @@ -243,7 +243,7 @@ static void *brute_thread(void *arguments) { } static int usage(void) { - printf(" syntax: mf_trace_brute []\n\n"); + printf(" syntax: mf_trace_brute <{nt}> <{nr}> [<{next_command + 18 bytes}>]\n\n"); return 1; } diff --git a/tools/mfc/card_reader/mfkey32.c b/tools/mfc/card_reader/mfkey32.c index 8c40af205..154e80784 100644 --- a/tools/mfc/card_reader/mfkey32.c +++ b/tools/mfc/card_reader/mfkey32.c @@ -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 \n\n", argv[0]); + printf(" syntax: %s <{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; } diff --git a/tools/mfc/card_reader/mfkey32v2.c b/tools/mfc/card_reader/mfkey32v2.c index 3f922de36..4c5986c50 100644 --- a/tools/mfc/card_reader/mfkey32v2.c +++ b/tools/mfc/card_reader/mfkey32v2.c @@ -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 \n\n", argv[0]); + printf("syntax: %s <{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; } diff --git a/tools/mfc/card_reader/mfkey64.c b/tools/mfc/card_reader/mfkey64.c index 1756c7fc9..d1aa06dfb 100644 --- a/tools/mfc/card_reader/mfkey64.c +++ b/tools/mfc/card_reader/mfkey64.c @@ -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); diff --git a/tools/mfc/card_reader/mfkey_examples.md b/tools/mfc/card_reader/mfkey_examples.md index f2e3e137f..559285456 100644 --- a/tools/mfc/card_reader/mfkey_examples.md +++ b/tools/mfc/card_reader/mfkey_examples.md @@ -19,8 +19,8 @@ Usage with sample trace: For mfkey32, you want to get two different NR_0/NR_1 values. ``` -# -./mfkey32 52B0F519 5417D1F8 4D545EA7 E15AC8C2 DAC1A7F4 5AE5C37F +# <{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