]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Various improvements on the Mifare1kSimulation. Fixed issue with tracebuffer not...
authormartin.holst@gmail.com <martin.holst@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Fri, 31 Jan 2014 21:17:34 +0000 (21:17 +0000)
committermartin.holst@gmail.com <martin.holst@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Fri, 31 Jan 2014 21:17:34 +0000 (21:17 +0000)
armsrc/iso14443a.c
client/cmdhfmf.c
include/usb_cmd.h

index 3966d77ab4150bfa6ad671990e57f4be9fd2f637..aa97e6e9bcc48a721753485297ec56e33da912ca 100644 (file)
@@ -1926,7 +1926,7 @@ void ReaderMifare(bool first_try)
        static uint8_t mf_nr_ar3;
 
        uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
-       traceLen = 0;
+       iso14a_clear_trace();
        tracing = false;
 
        byte_t nt_diff = 0;
@@ -1974,7 +1974,7 @@ void ReaderMifare(bool first_try)
        LED_B_OFF();
        LED_C_OFF();
        
-  
+
        for(uint16_t i = 0; TRUE; i++) {
                
                WDT_HIT();
@@ -2113,18 +2113,22 @@ void ReaderMifare(bool first_try)
        tracing = TRUE;
 }
 
-//-----------------------------------------------------------------------------
-// MIFARE 1K simulate. 
-// 
-//-----------------------------------------------------------------------------
-void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
+/**
+  *MIFARE 1K simulate.
+  *
+  *@param flags :
+  *    FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
+  * 4B_FLAG_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
+  * 7B_FLAG_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
+  *    FLAG_NR_AR_ATTACK  - means we should collect NR_AR responses for bruteforcing later
+  *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is inifite
+  */
+void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain)
 {
        int cardSTATE = MFEMUL_NOFIELD;
        int _7BUID = 0;
        int vHf = 0;    // in mV
-       //int nextCycleTimeout = 0;
        int res;
-//     uint32_t timer = 0;
        uint32_t selTimer = 0;
        uint32_t authTimer = 0;
        uint32_t par = 0;
@@ -2132,60 +2136,83 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        uint8_t cardWRBL = 0;
        uint8_t cardAUTHSC = 0;
        uint8_t cardAUTHKEY = 0xff;  // no authentication
-       //uint32_t cardRn = 0;
        uint32_t cardRr = 0;
        uint32_t cuid = 0;
-       uint32_t rn_enc = 0;
+       //uint32_t rn_enc = 0;
        uint32_t ans = 0;
        uint32_t cardINTREG = 0;
        uint8_t cardINTBLOCK = 0;
        struct Crypto1State mpcs = {0, 0};
        struct Crypto1State *pcs;
        pcs = &mpcs;
-       
+       uint32_t numReads = 0;//Counts numer of times reader read a block
        uint8_t* receivedCmd = eml_get_bigbufptr_recbuf();
        uint8_t *response = eml_get_bigbufptr_sendbuf();
        
-       static uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
+       uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
+       uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
+       uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
+       uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
+       uint8_t rSAK1[] = {0x04, 0xda, 0x17};
 
-       static uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; 
-       static uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
-               
-       static uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
-       static uint8_t rSAK1[] = {0x04, 0xda, 0x17};
+       uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
+       uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
 
-       static uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
-//     static uint8_t rAUTH_NT[] = {0x1a, 0xac, 0xff, 0x4f};
-       static uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
+       //Here, we collect UID,NT,AR,NR,UID2,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;
 
        // clear trace
-       traceLen = 0;
+       iso14a_clear_trace();
+
        tracing = true;
 
   // Authenticate response - nonce
        uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
-       
-       // get UID from emul memory
-       emlGetMemBt(receivedCmd, 7, 1);
-       _7BUID = !(receivedCmd[0] == 0x00);
-       if (!_7BUID) {                     // ---------- 4BUID
-               rATQA[0] = 0x04;
 
-               emlGetMemBt(rUIDBCC1, 0, 4);
+       //-- Determine the UID
+       // Can be set from emulator memory, incoming data
+       // and can be 7 or 4 bytes long
+       if(flags & FLAG_4B_UID_IN_DATA)
+       {
+               // 4B uid comes from data-portion of packet
+               memcpy(rUIDBCC1,datain,4);
                rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
-       } else {                           // ---------- 7BUID
-               rATQA[0] = 0x44;
 
+       }else if(flags & FLAG_7B_UID_IN_DATA)
+       {
+               // 7B uid comes from data-portion of packet
+               memcpy(&rUIDBCC1[1],datain,3);
+               memcpy(rUIDBCC2, datain+3, 4);
+               _7BUID = true;
+       }
+       else
+       {
+               // get UID from emul memory
+               emlGetMemBt(receivedCmd, 7, 1);
+               _7BUID = !(receivedCmd[0] == 0x00);
+               if (!_7BUID) {                     // ---------- 4BUID
+                       emlGetMemBt(rUIDBCC1, 0, 4);
+               } else {                           // ---------- 7BUID
+                       emlGetMemBt(&rUIDBCC1[1], 0, 3);
+                       emlGetMemBt(rUIDBCC2, 3, 4);
+               }
+       }
+       /*
+        * Regardless of what method was used to set the UID, set fifth byte and modify
+        * the ATQA for 4 or 7-byte UID
+        */
+
+       rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
+       if(_7BUID)
+       {
+               rATQA[0] = 0x44;
                rUIDBCC1[0] = 0x88;
-               emlGetMemBt(&rUIDBCC1[1], 0, 3);
-               rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
-               emlGetMemBt(rUIDBCC2, 3, 4);
                rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
        }
 
-// --------------------------------------      test area
-
-// --------------------------------------      END test area
        // start mkseconds counter
        StartCountUS();
 
@@ -2193,19 +2220,23 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
        FpgaSetupSsc();
 
-  FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
        SpinDelay(200);
 
-       if (MF_DBGLEVEL >= 1)   Dbprintf("Started. 7buid=%d", _7BUID);
+       if (MF_DBGLEVEL >= 1)   {
+               if (!_7BUID) {
+                       Dbprintf("4B UID: %02x%02x%02x%02x",rUIDBCC1[0] , rUIDBCC1[1] , rUIDBCC1[2] , rUIDBCC1[3]);
+               }else
+               {
+                       Dbprintf("7B UID: (%02x)%02x%02x%02x%02x%02x%02x%02x",rUIDBCC1[0] , rUIDBCC1[1] , rUIDBCC1[2] , rUIDBCC1[3],rUIDBCC2[0],rUIDBCC2[1] ,rUIDBCC2[2] , rUIDBCC2[3]);
+               }
+       }
        // calibrate mkseconds counter
        GetDeltaCountUS();
-       while (true) {
+       bool finished = false;
+       while (!BUTTON_PRESS() && !finished) {
                WDT_HIT();
 
-               if(BUTTON_PRESS()) {
-                       break;
-               }
-
                // find reader field
                // Vref = 3300mV, and an 10:1 voltage divider on the input
                // can measure voltages up to 33000 mV
@@ -2216,56 +2247,54 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
                                LED_A_ON();
                        }
                } 
+               if(cardSTATE == MFEMUL_NOFIELD) continue;
 
-               if (cardSTATE != MFEMUL_NOFIELD) {
-                       res = EmGetCmd(receivedCmd, &len, RECV_CMD_SIZE); // (+ nextCycleTimeout)
-                       if (res == 2) {
-                               cardSTATE = MFEMUL_NOFIELD;
-                               LEDsoff();
-                               continue;
-                       }
-                       if(res) break;
-               }
-               
-               //nextCycleTimeout = 0;
-               
-//             if (len) Dbprintf("len:%d cmd: %02x %02x %02x %02x", len, receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3]);
-
-               if (len != 4 && cardSTATE != MFEMUL_NOFIELD) { // len != 4 <---- speed up the code 4 authentication
-                       // REQ or WUP request in ANY state and WUP in HALTED state
-                       if (len == 1 && ((receivedCmd[0] == 0x26 && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == 0x52)) {
-                               selTimer = GetTickCount();
-                               EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
-                               cardSTATE = MFEMUL_SELECT1;
-
-                               // init crypto block
-                               LED_B_OFF();
-                               LED_C_OFF();
-                               crypto1_destroy(pcs);
-                               cardAUTHKEY = 0xff;
-                       }
+               //Now, get data
+
+               res = EmGetCmd(receivedCmd, &len, RECV_CMD_SIZE); // (+ nextCycleTimeout)
+               if (res == 2) { //Field is off!
+                       cardSTATE = MFEMUL_NOFIELD;
+                       LEDsoff();
+                       continue;
+               }else if(res == 1) break;//return value 1 means button press
+
+
+               // REQ or WUP request in ANY state and WUP in HALTED state
+               if (len == 1 && ((receivedCmd[0] == 0x26 && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == 0x52)) {
+                       selTimer = GetTickCount();
+                       EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
+                       cardSTATE = MFEMUL_SELECT1;
+
+                       // init crypto block
+                       LED_B_OFF();
+                       LED_C_OFF();
+                       crypto1_destroy(pcs);
+                       cardAUTHKEY = 0xff;
+                       continue;
                }
-               
+
                switch (cardSTATE) {
-                       case MFEMUL_NOFIELD:{
-                               break;
-                       }
-                       case MFEMUL_HALTED:{
-                               break;
-                       }
+                       case MFEMUL_NOFIELD:
+                       case MFEMUL_HALTED:
                        case MFEMUL_IDLE:{
                                break;
                        }
                        case MFEMUL_SELECT1:{
                                // select all
                                if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
+                                       if (MF_DBGLEVEL >= 4)   Dbprintf("SELECT ALL received");
                                        EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
                                        break;
                                }
 
+                               if (MF_DBGLEVEL >= 4 && len == 9 && receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 )
+                               {
+                                       Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
+                               }
                                // select card
                                if (len == 9 && 
                                                (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
+
                                        if (!_7BUID) 
                                                EmSendCmd(rSAK, sizeof(rSAK));
                                        else
@@ -2285,6 +2314,51 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
                                
                                break;
                        }
+                       case MFEMUL_AUTH1:{
+                               if( len != 8)
+                               {
+                                       cardSTATE_TO_IDLE();
+                                       break;
+                               }
+                               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[ar_nr_collected*4+2] != ar)
+                                       {// Avoid duplicates
+                                               ar_nr_collected++;
+                                               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;
+                                       }
+                               }
+
+                               // --- crypto
+                               crypto1_word(pcs, ar , 1);
+                               cardRr = nr ^ crypto1_word(pcs, 0, 0);
+
+                               // test if auth OK
+                               if (cardRr != prng_successor(nonce, 64)){
+                                       if (MF_DBGLEVEL >= 2)   Dbprintf("AUTH FAILED. cardRr=%08x, succ=%08x",cardRr, prng_successor(nonce, 64));
+                                       //Shouldn't we respond anything here?
+                                       // Right now, we don't nack or anything, which causes the
+                                       // reader to do a WUPA after a while. /Martin
+                                       cardSTATE_TO_IDLE();
+                                       break;
+                               }
+
+                               ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
+
+                               num_to_bytes(ans, 4, rAUTH_AT);
+                               // --- crypto
+                               EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
+                               LED_C_ON();
+                               cardSTATE = MFEMUL_WORK;
+                               if (MF_DBGLEVEL >= 4)   Dbprintf("AUTH COMPLETED. sector=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - authTimer);
+                               break;
+                       }
                        case MFEMUL_SELECT2:{
                                if (!len) break;
                        
@@ -2308,86 +2382,44 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
                                // i guess there is a command). go into the work state.
                                if (len != 4) break;
                                cardSTATE = MFEMUL_WORK;
-                               goto lbWORK;
-                       }
-                       case MFEMUL_AUTH1:{
-                               if (len == 8) {
-                                       // --- crypto
-                                       rn_enc = bytes_to_num(receivedCmd, 4);
-                                       crypto1_word(pcs, rn_enc , 1);
-                                       cardRr = bytes_to_num(&receivedCmd[4], 4) ^ crypto1_word(pcs, 0, 0);
-                                       // test if auth OK
-                                       if (cardRr != prng_successor(nonce, 64)){
-                                               if (MF_DBGLEVEL >= 4)   Dbprintf("AUTH FAILED. cardRr=%08x, succ=%08x", cardRr, prng_successor(nonce, 64));
-                                               cardSTATE_TO_IDLE();
-                                               break;
-                                       }
-                                       ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
-                                       num_to_bytes(ans, 4, rAUTH_AT);
-                                       // --- crypto
-                                       EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
-                                       cardSTATE = MFEMUL_AUTH2;
-                               } else {
-                                       cardSTATE_TO_IDLE();
-                               }
-                               if (cardSTATE != MFEMUL_AUTH2) break;
-                       }
-                       case MFEMUL_AUTH2:{
-                               LED_C_ON();
-                               cardSTATE = MFEMUL_WORK;
-                               if (MF_DBGLEVEL >= 4)   Dbprintf("AUTH COMPLETED. sec=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - authTimer);
-                               break;
+                               //goto lbWORK;
+                               //intentional fall-through to the next case-stmt
                        }
                        case MFEMUL_WORK:{
-lbWORK:        if (len == 0) break;
-                               
-                               if (cardAUTHKEY == 0xff) {
-                                       // first authentication
-                                       if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
-                                               authTimer = GetTickCount();
-
-                                               cardAUTHSC = receivedCmd[1] / 4;  // received block num
-                                               cardAUTHKEY = receivedCmd[0] - 0x60;
-
-                                               // --- crypto
-                                               crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
-                                               ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); 
-                                               num_to_bytes(nonce, 4, rAUTH_AT);
-                                               EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
-                                               // --- crypto
-                                               
-//   last working revision 
-//                                             EmSendCmd14443aRaw(resp1, resp1Len, 0);
-//                                             LogTrace(NULL, 0, GetDeltaCountUS(), 0, true);
+                               if (len == 0) break;
 
-                                               cardSTATE = MFEMUL_AUTH1;
-                                               //nextCycleTimeout = 10;
-                                               break;
-                                       }
-                               } else {
+                               bool encrypted_data = (cardAUTHKEY != 0xFF) ;
+
+                               if(encrypted_data)
+                               {
                                        // decrypt seqence
                                        mf_crypto1_decrypt(pcs, receivedCmd, len);
-                                       
-                                       // nested authentication
-                                       if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
-                                               authTimer = GetTickCount();
+                               }
 
-                                               cardAUTHSC = receivedCmd[1] / 4;  // received block num
-                                               cardAUTHKEY = receivedCmd[0] - 0x60;
+                               if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
+                                       authTimer = GetTickCount();
+                                       cardAUTHSC = receivedCmd[1] / 4;  // received block num
+                                       cardAUTHKEY = receivedCmd[0] - 0x60;
+                                       crypto1_destroy(pcs);//Added by martin
+                                       crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
 
-                                               // --- crypto
-                                               crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
-                                               ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); 
-                                               num_to_bytes(ans, 4, rAUTH_AT);
-                                               EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
-                                               // --- crypto
+                                       if (!encrypted_data) { // first authentication
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY  );
 
-                                               cardSTATE = MFEMUL_AUTH1;
-                                               //nextCycleTimeout = 10;
-                                               break;
+                                               crypto1_word(pcs, cuid ^ nonce, 0);//Update crypto state
+                                               num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce
+                                       }
+                                       else{ // nested authentication
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
+                                               ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
+                                               num_to_bytes(ans, 4, rAUTH_AT);
                                        }
+                                       EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
+                                       //Dbprintf("Sending rAUTH %02x%02x%02x%02x", rAUTH_AT[0],rAUTH_AT[1],rAUTH_AT[2],rAUTH_AT[3]);
+                                       cardSTATE = MFEMUL_AUTH1;
+                                       break;
                                }
-                               
+
                                // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued
                                // BUT... ACK --> NACK
                                if (len == 1 && receivedCmd[0] == CARD_ACK) {
@@ -2401,39 +2433,63 @@ lbWORK: if (len == 0) break;
                                        break;
                                }
                                
-                               // read block
-                               if (len == 4 && receivedCmd[0] == 0x30) {
-                                       if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
+                               if(len != 4) break;
+
+                               if(receivedCmd[0] == 0x30 // read block
+                                               || receivedCmd[0] == 0xA0 // write block
+                                               || receivedCmd[0] == 0xC0
+                                               || receivedCmd[0] == 0xC1
+                                               || receivedCmd[0] == 0xC2 // inc dec restore
+                                               || receivedCmd[0] == 0xB0) // transfer
+                               {
+                                       if (receivedCmd[1] >= 16 * 4)
+                                       {
+
+                                               EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+                                               break;
+                                       }
+
+                                       if (receivedCmd[1] / 4 != cardAUTHSC)
+                                       {
                                                EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC);
                                                break;
                                        }
+                               }
+                               // read block
+                               if (receivedCmd[0] == 0x30) {
+                                       if (MF_DBGLEVEL >= 2) {
+                                               Dbprintf("Reader reading block %d (0x%02x)",receivedCmd[1],receivedCmd[1]);
+                                       }
                                        emlGetMem(response, receivedCmd[1], 1);
                                        AppendCrc14443a(response, 16);
                                        mf_crypto1_encrypt(pcs, response, 18, &par);
                                        EmSendCmdPar(response, 18, par);
+                                       numReads++;
+                                       if(exitAfterNReads > 0 && numReads == exitAfterNReads)
+                                       {
+                                               Dbprintf("%d reads done, exiting", numReads);
+                                               finished = true;
+                                       }
                                        break;
                                }
-                               
                                // write block
-                               if (len == 4 && receivedCmd[0] == 0xA0) {
-                                       if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
-                                               EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
-                                               break;
-                                       }
+                               if (receivedCmd[0] == 0xA0) {
+                                       if (MF_DBGLEVEL >= 2) Dbprintf("RECV 0xA0 write block %d (%02x)",receivedCmd[1],receivedCmd[1]);
+
                                        EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
                                        //nextCycleTimeout = 50;
                                        cardSTATE = MFEMUL_WRITEBL2;
                                        cardWRBL = receivedCmd[1];
                                        break;
-                               }
-                       
-                               // works with cardINTREG
-                               
+                               }                               
                                // increment, decrement, restore
-                               if (len == 4 && (receivedCmd[0] == 0xC0 || receivedCmd[0] == 0xC1 || receivedCmd[0] == 0xC2)) {
-                                       if (receivedCmd[1] >= 16 * 4 || 
-                                                       receivedCmd[1] / 4 != cardAUTHSC || 
-                                                       emlCheckValBl(receivedCmd[1])) {
+                               if (receivedCmd[0] == 0xC0 || receivedCmd[0] == 0xC1 || receivedCmd[0] == 0xC2) {
+                                       if (MF_DBGLEVEL >= 2) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+
+                                       if (emlCheckValBl(receivedCmd[1])) {
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking");
                                                EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
                                                break;
                                        }
@@ -2445,17 +2501,13 @@ lbWORK: if (len == 0) break;
                                        if (receivedCmd[0] == 0xC2)
                                                cardSTATE = MFEMUL_INTREG_REST;
                                        cardWRBL = receivedCmd[1];
-                                       
+
                                        break;
                                }
                                
-
                                // transfer
-                               if (len == 4 && receivedCmd[0] == 0xB0) {
-                                       if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
-                                               EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
-                                               break;
-                                       }
+                               if (receivedCmd[0] == 0xB0) {
+                                       if (MF_DBGLEVEL >= 2) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
                                        
                                        if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1]))
                                                EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
@@ -2466,20 +2518,23 @@ lbWORK: if (len == 0) break;
                                }
 
                                // halt
-                               if (len == 4 && (receivedCmd[0] == 0x50 && receivedCmd[1] == 0x00)) {
+                               if (receivedCmd[0] == 0x50 && receivedCmd[1] == 0x00) {
                                        LED_B_OFF();
                                        LED_C_OFF();
                                        cardSTATE = MFEMUL_HALTED;
                                        if (MF_DBGLEVEL >= 4)   Dbprintf("--> HALTED. Selected time: %d ms",  GetTickCount() - selTimer);
                                        break;
                                }
-                               
-                               // command not allowed
-                               if (len == 4) {
+                               // RATS
+                               if (receivedCmd[0] == 0xe0) {//RATS
                                        EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
                                        break;
                                }
 
+                               // command not allowed
+                               if (MF_DBGLEVEL >= 4)   Dbprintf("Received command not allowed, nacking");
+                               EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+
                                // case break
                                break;
                        }
@@ -2541,10 +2596,43 @@ lbWORK: if (len == 0) break;
        // add trace trailer
        memset(rAUTH_NT, 0x44, 4);
        LogTrace(rAUTH_NT, 4, 0, 0, TRUE);
-
+       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(ar_nr_collected > 1)
+               {
+                       Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
+                       Dbprintf("../tools/mfcrack32 %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=%08d, nonce=%08d, AR1=%08d, NR1=%08d",
+                                               ar_nr_responses[0], // UID
+                                               ar_nr_responses[1], //NT
+                                               ar_nr_responses[2], //AR1
+                                               ar_nr_responses[3] //NR1
+                                               );
+                       }
+               }
+       }
        if (MF_DBGLEVEL >= 1)   Dbprintf("Emulator stopped. Tracing: %d  trace length: %d ",    tracing, traceLen);
 }
 
+
+
 //-----------------------------------------------------------------------------
 // MIFARE sniffer. 
 // 
index 86fbe8df558fee3729e1a1dddea8b61fe2bfe922..637ef4a1f97a9db98e7a32730e75235096c2ac3b 100644 (file)
@@ -137,86 +137,86 @@ int CmdHF14AMfWrBl(const char *Cmd)
                PrintAndLog("Command execute timeout");\r
        }\r
 \r
-       return 0;
-}
-
-int CmdHF14AMfUWrBl(const char *Cmd)
-{
-        uint8_t blockNo = 0;
-        uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-       UsbCommand resp;
-        
-        if (strlen(Cmd)<3) {
-                PrintAndLog("Usage:  hf mf uwrbl    <block number> <block data (8 hex symbols)>");
-                PrintAndLog("        sample: hf mf uwrbl 0 01020304");
-                return 0;
-        }       
-
-        blockNo = param_get8(Cmd, 0);
-        if (param_gethex(Cmd, 1, bldata, 8)) {
-                PrintAndLog("Block data must include 8 HEX symbols");
-                return 1;
-        }
-
-       switch(blockNo)
-       {
-       case 0:
-               PrintAndLog("Access Denied");
-               break;
-       case 1:
-               PrintAndLog("Access Denied");
-               break;
-       case 2:
-               PrintAndLog("--specialblock no:%02x", blockNo);
-                PrintAndLog("--data: %s", sprint_hex(bldata, 4));
-                UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
-                memcpy(c.d.asBytes, bldata, 4);
-                SendCommand(&c);
-
-                if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                        uint8_t isOK  = resp.arg[0] & 0xff;
-                        PrintAndLog("isOk:%02x", isOK);
-                } else {
-                        PrintAndLog("Command execute timeout");
-                }
-               break;
-       case 3:
-               PrintAndLog("--specialblock no:%02x", blockNo);
-                PrintAndLog("--data: %s", sprint_hex(bldata, 4));
-                UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
-                memcpy(d.d.asBytes,bldata, 4);
-                SendCommand(&d);
-
-                if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                        uint8_t isOK  = resp.arg[0] & 0xff;
-                        PrintAndLog("isOk:%02x", isOK);
-                } else {
-                        PrintAndLog("Command execute timeout");
-                }
-               break;
-       default: 
-               PrintAndLog("--block no:%02x", blockNo);
-               PrintAndLog("--data: %s", sprint_hex(bldata, 4));               
-               //UsbCommand e = {CMD_MIFAREU_WRITEBL_COMPAT, {blockNo}};
-               //memcpy(e.d.asBytes,bldata, 16);
-               UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
-                memcpy(e.d.asBytes,bldata, 4);
-               SendCommand(&e);
-
-               if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                       uint8_t isOK  = resp.arg[0] & 0xff;
-                       PrintAndLog("isOk:%02x", isOK);
-               } else {
-                       PrintAndLog("Command execute timeout");
-               }
-               break;
-       }
-        return 0;
-}
-
-int CmdHF14AMfRdBl(const char *Cmd)
-{
-       uint8_t blockNo = 0;
+       return 0;\r
+}\r
+\r
+int CmdHF14AMfUWrBl(const char *Cmd)\r
+{\r
+        uint8_t blockNo = 0;\r
+        uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\r
+       UsbCommand resp;\r
+        \r
+        if (strlen(Cmd)<3) {\r
+                PrintAndLog("Usage:  hf mf uwrbl    <block number> <block data (8 hex symbols)>");\r
+                PrintAndLog("        sample: hf mf uwrbl 0 01020304");\r
+                return 0;\r
+        }       \r
+\r
+        blockNo = param_get8(Cmd, 0);\r
+        if (param_gethex(Cmd, 1, bldata, 8)) {\r
+                PrintAndLog("Block data must include 8 HEX symbols");\r
+                return 1;\r
+        }\r
+\r
+       switch(blockNo)\r
+       {\r
+       case 0:\r
+               PrintAndLog("Access Denied");\r
+               break;\r
+       case 1:\r
+               PrintAndLog("Access Denied");\r
+               break;\r
+       case 2:\r
+               PrintAndLog("--specialblock no:%02x", blockNo);\r
+                PrintAndLog("--data: %s", sprint_hex(bldata, 4));\r
+                UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};\r
+                memcpy(c.d.asBytes, bldata, 4);\r
+                SendCommand(&c);\r
+\r
+                if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+                        uint8_t isOK  = resp.arg[0] & 0xff;\r
+                        PrintAndLog("isOk:%02x", isOK);\r
+                } else {\r
+                        PrintAndLog("Command execute timeout");\r
+                }\r
+               break;\r
+       case 3:\r
+               PrintAndLog("--specialblock no:%02x", blockNo);\r
+                PrintAndLog("--data: %s", sprint_hex(bldata, 4));\r
+                UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};\r
+                memcpy(d.d.asBytes,bldata, 4);\r
+                SendCommand(&d);\r
+\r
+                if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+                        uint8_t isOK  = resp.arg[0] & 0xff;\r
+                        PrintAndLog("isOk:%02x", isOK);\r
+                } else {\r
+                        PrintAndLog("Command execute timeout");\r
+                }\r
+               break;\r
+       default: \r
+               PrintAndLog("--block no:%02x", blockNo);\r
+               PrintAndLog("--data: %s", sprint_hex(bldata, 4));               \r
+               //UsbCommand e = {CMD_MIFAREU_WRITEBL_COMPAT, {blockNo}};\r
+               //memcpy(e.d.asBytes,bldata, 16);\r
+               UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};\r
+                memcpy(e.d.asBytes,bldata, 4);\r
+               SendCommand(&e);\r
+\r
+               if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+                       uint8_t isOK  = resp.arg[0] & 0xff;\r
+                       PrintAndLog("isOk:%02x", isOK);\r
+               } else {\r
+                       PrintAndLog("Command execute timeout");\r
+               }\r
+               break;\r
+       }\r
+        return 0;\r
+}\r
+\r
+int CmdHF14AMfRdBl(const char *Cmd)\r
+{\r
+       uint8_t blockNo = 0;\r
        uint8_t keyType = 0;\r
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
        \r
@@ -259,135 +259,135 @@ int CmdHF14AMfRdBl(const char *Cmd)
                PrintAndLog("Command execute timeout");\r
        }\r
 \r
-  return 0;
-}
-
-int CmdHF14AMfURdBl(const char *Cmd)
-{
-        uint8_t blockNo = 0;
-
-        if (strlen(Cmd)<1) {
-                PrintAndLog("Usage:  hf mf urdbl    <block number>");
-                PrintAndLog("        sample: hf mf urdbl 0");
-                return 0;
-        }       
-        
-        blockNo = param_get8(Cmd, 0);
-        PrintAndLog("--block no:%02x", blockNo);
-        
-  UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
-  SendCommand(&c);
-
-        UsbCommand resp;
-        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                uint8_t                isOK  = resp.arg[0] & 0xff;
-                uint8_t              * data  = resp.d.asBytes;
-
-                if (isOK)
-                        PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
-                else
-                        PrintAndLog("isOk:%02x", isOK);
-        } else {
-                PrintAndLog("Command execute timeout");
-        }
-
-  return 0;
-}
-
-int CmdHF14AMfURdCard(const char *Cmd)
-{
-        int i;
-        uint8_t sectorNo = 0;
-       uint8_t *lockbytes_t=NULL;
-       uint8_t lockbytes[2]={0,0};
-       bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-        
-        uint8_t isOK  = 0;
-        uint8_t * data  = NULL;
-
-        if (sectorNo > 15) {
-                PrintAndLog("Sector number must be less than 16");
-                return 1;
-        }
-        PrintAndLog("Attempting to Read Ultralight... ");
-        
-       UsbCommand c = {CMD_MIFAREU_READCARD, {sectorNo}};
-       SendCommand(&c);
-
-        UsbCommand resp;
-        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                isOK  = resp.arg[0] & 0xff;
-                data  = resp.d.asBytes;
-
-                PrintAndLog("isOk:%02x", isOK);
-                if (isOK) 
-                        for (i = 0; i < 16; i++) {
-                               switch(i){
-                                 case 2:
-                                       //process lock bytes
-                                       lockbytes_t=data+(i*4);
-                                       lockbytes[0]=lockbytes_t[2];
-                                       lockbytes[1]=lockbytes_t[3];
-                                       for(int j=0; j<16; j++){
-                                               bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
-                                       }
-                                       //PrintAndLog("LB %02x %02x", lockbytes[0],lockbytes[1]);
-                                       //PrintAndLog("LB2b %02x %02x %02x %02x %02x %02x %02x %02x",bit[8],bit[9],bit[10],bit[11],bit[12],bit[13],bit[14],bit[15]);            
-                                       PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
-                                       break;
-                                 case 3: 
-                                       PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]);
-                                       break;
-                                 case 4:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]);
-                                       break;
-                                 case 5:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]);
-                                       break;
-                                 case 6:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]);
-                                       break;
-                                 case 7:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]);
-                                       break;
-                                 case 8:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]);
-                                       break;
-                                 case 9:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]);
-                                       break;
-                                 case 10:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]);
-                                       break;
-                                 case 11:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]);
-                                       break;
-                                 case 12:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]);
-                                       break;
-                                 case 13:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]);
-                                       break;
-                                 case 14:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]);
-                                       break;
-                                 case 15:
-                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]);
-                                       break;
-                                 default:
-                                       PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
-                                       break;
-                               }
-                        }
-        } else {
-                PrintAndLog("Command1 execute timeout");
-        }
-  return 0;
-}
-
-int CmdHF14AMfRdSc(const char *Cmd)
-{
-       int i;
+  return 0;\r
+}\r
+\r
+int CmdHF14AMfURdBl(const char *Cmd)\r
+{\r
+        uint8_t blockNo = 0;\r
+\r
+        if (strlen(Cmd)<1) {\r
+                PrintAndLog("Usage:  hf mf urdbl    <block number>");\r
+                PrintAndLog("        sample: hf mf urdbl 0");\r
+                return 0;\r
+        }       \r
+        \r
+        blockNo = param_get8(Cmd, 0);\r
+        PrintAndLog("--block no:%02x", blockNo);\r
+        \r
+  UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};\r
+  SendCommand(&c);\r
+\r
+        UsbCommand resp;\r
+        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+                uint8_t                isOK  = resp.arg[0] & 0xff;\r
+                uint8_t              * data  = resp.d.asBytes;\r
+\r
+                if (isOK)\r
+                        PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));\r
+                else\r
+                        PrintAndLog("isOk:%02x", isOK);\r
+        } else {\r
+                PrintAndLog("Command execute timeout");\r
+        }\r
+\r
+  return 0;\r
+}\r
+\r
+int CmdHF14AMfURdCard(const char *Cmd)\r
+{\r
+        int i;\r
+        uint8_t sectorNo = 0;\r
+       uint8_t *lockbytes_t=NULL;\r
+       uint8_t lockbytes[2]={0,0};\r
+       bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\r
+        \r
+        uint8_t isOK  = 0;\r
+        uint8_t * data  = NULL;\r
+\r
+        if (sectorNo > 15) {\r
+                PrintAndLog("Sector number must be less than 16");\r
+                return 1;\r
+        }\r
+        PrintAndLog("Attempting to Read Ultralight... ");\r
+        \r
+       UsbCommand c = {CMD_MIFAREU_READCARD, {sectorNo}};\r
+       SendCommand(&c);\r
+\r
+        UsbCommand resp;\r
+        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+                isOK  = resp.arg[0] & 0xff;\r
+                data  = resp.d.asBytes;\r
+\r
+                PrintAndLog("isOk:%02x", isOK);\r
+                if (isOK) \r
+                        for (i = 0; i < 16; i++) {\r
+                               switch(i){\r
+                                 case 2:\r
+                                       //process lock bytes\r
+                                       lockbytes_t=data+(i*4);\r
+                                       lockbytes[0]=lockbytes_t[2];\r
+                                       lockbytes[1]=lockbytes_t[3];\r
+                                       for(int j=0; j<16; j++){\r
+                                               bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));\r
+                                       }\r
+                                       //PrintAndLog("LB %02x %02x", lockbytes[0],lockbytes[1]);\r
+                                       //PrintAndLog("LB2b %02x %02x %02x %02x %02x %02x %02x %02x",bit[8],bit[9],bit[10],bit[11],bit[12],bit[13],bit[14],bit[15]);            \r
+                                       PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));\r
+                                       break;\r
+                                 case 3: \r
+                                       PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]);\r
+                                       break;\r
+                                 case 4:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]);\r
+                                       break;\r
+                                 case 5:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]);\r
+                                       break;\r
+                                 case 6:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]);\r
+                                       break;\r
+                                 case 7:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]);\r
+                                       break;\r
+                                 case 8:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]);\r
+                                       break;\r
+                                 case 9:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]);\r
+                                       break;\r
+                                 case 10:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]);\r
+                                       break;\r
+                                 case 11:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]);\r
+                                       break;\r
+                                 case 12:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]);\r
+                                       break;\r
+                                 case 13:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]);\r
+                                       break;\r
+                                 case 14:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]);\r
+                                       break;\r
+                                 case 15:\r
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]);\r
+                                       break;\r
+                                 default:\r
+                                       PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));\r
+                                       break;\r
+                               }\r
+                        }\r
+        } else {\r
+                PrintAndLog("Command1 execute timeout");\r
+        }\r
+  return 0;\r
+}\r
+\r
+int CmdHF14AMfRdSc(const char *Cmd)\r
+{\r
+       int i;\r
        uint8_t sectorNo = 0;\r
        uint8_t keyType = 0;\r
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
@@ -1144,24 +1144,68 @@ int CmdHF14AMfChk(const char *Cmd)
 \r
 int CmdHF14AMf1kSim(const char *Cmd)\r
 {\r
-       uint8_t uid[4] = {0, 0, 0, 0};\r
-       \r
+       uint8_t uid[7] = {0, 0, 0, 0,0,0,0};\r
+       uint8_t exitAfterNReads = 0;\r
+       uint8_t flags = 0;\r
+\r
        if (param_getchar(Cmd, 0) == 'h') {\r
-               PrintAndLog("Usage:  hf mf sim  <uid (8 hex symbols)>");\r
+               PrintAndLog("Usage:  hf mf sim  u <uid (8 hex symbols)> n <numreads> i x");\r
+               PrintAndLog("           u    (Optional) UID. If not specified, the UID from emulator memory will be used");\r
+               PrintAndLog("           n    (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");\r
+               PrintAndLog("           i    (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");\r
+               PrintAndLog("           x    (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");\r
                PrintAndLog("           sample: hf mf sim 0a0a0a0a ");\r
                return 0;\r
-       }       \r
-       \r
-       if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, uid, 8)) {\r
-               PrintAndLog("UID must include 8 HEX symbols");\r
-               return 1;\r
        }\r
-       PrintAndLog(" uid:%s ", sprint_hex(uid, 4));\r
-       \r
-  UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {0, 0, 0}};\r
-       memcpy(c.d.asBytes, uid, 4);\r
+       uint8_t pnr = 0;\r
+       if (param_getchar(Cmd, pnr) == 'u') {\r
+               if(param_gethex(Cmd, pnr+1, uid, 8) == 0)\r
+               {\r
+                       flags |=FLAG_4B_UID_IN_DATA; // UID from packet\r
+               }else if(param_gethex(Cmd,pnr+1,uid,14) == 0)\r
+               {\r
+                       flags |= FLAG_7B_UID_IN_DATA;// UID from packet\r
+               }else\r
+               {\r
+                               PrintAndLog("UID, if specified, must include 8 or 14 HEX symbols");\r
+                               return 1;\r
+               }\r
+               pnr +=2;\r
+       }\r
+       if (param_getchar(Cmd, pnr) == 'n') {\r
+               exitAfterNReads = param_get8(Cmd,pnr+1);\r
+               pnr += 2;\r
+       }\r
+       if (param_getchar(Cmd, pnr) == 'i' ) {\r
+               //Using a flag to signal interactiveness, least significant bit\r
+               flags |= FLAG_INTERACTIVE;\r
+               pnr++;\r
+       }\r
+\r
+       if (param_getchar(Cmd, pnr) == 'x' ) {\r
+               //Using a flag to signal interactiveness, least significant bit\r
+               flags |= FLAG_NR_AR_ATTACK;\r
+       }\r
+       PrintAndLog(" uid:%s, numreads:%d, flags:%d (0x%02x) ",\r
+                               flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):\r
+                                                                                         flags & FLAG_7B_UID_IN_DATA   ? sprint_hex(uid,7): "N/A"\r
+                               , exitAfterNReads, flags,flags);\r
+\r
+\r
+  UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};\r
+  memcpy(c.d.asBytes, uid, sizeof(uid));\r
   SendCommand(&c);\r
 \r
+  if(flags & 1)\r
+  {\r
+         UsbCommand resp;\r
+         PrintAndLog("Press pm3-button to abort simulation");\r
+         while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+               //We're waiting only 1.5 s at a time, otherwise we get the\r
+                 // annoying message about "Waiting for a response... "\r
+         }\r
+  }\r
+\r
   return 0;\r
 }\r
 \r
@@ -1291,7 +1335,11 @@ int CmdHF14AMfELoad(const char *Cmd)
        while(!feof(f)){\r
                memset(buf, 0, sizeof(buf));\r
                if (fgets(buf, sizeof(buf), f) == NULL) {\r
-      PrintAndLog("File reading error.");\r
+                       if(blockNum == 16 * 4)\r
+                       {\r
+                               break;\r
+                       }\r
+                       PrintAndLog("File reading error.");\r
                        return 2;\r
     }\r
 \r
@@ -1319,7 +1367,7 @@ int CmdHF14AMfELoad(const char *Cmd)
                PrintAndLog("File content error. There must be 64 blocks");\r
                return 4;\r
        }\r
-       PrintAndLog("Loaded from file: %s", filename);\r
+       PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename);\r
   return 0;\r
 }\r
 \r
@@ -1864,15 +1912,15 @@ int CmdHF14AMfSniff(const char *Cmd){
 \r
 static command_t CommandTable[] =\r
 {\r
-  {"help",             CmdHelp,                                                1, "This help"},
-  {"dbg",                      CmdHF14AMfDbg,                  0, "Set default debug mode"},
-  {"rdbl",             CmdHF14AMfRdBl,                 0, "Read MIFARE classic block"},
-  {"urdbl",              CmdHF14AMfURdBl,                 0, "Read MIFARE Ultralight block"},
-  {"urdcard",           CmdHF14AMfURdCard,               0,"Read MIFARE Ultralight Card"},
-  {"uwrbl",            CmdHF14AMfUWrBl,                0,"Write MIFARE Ultralight block"},
-  {"rdsc",             CmdHF14AMfRdSc,                 0, "Read MIFARE classic sector"},
-  {"dump",             CmdHF14AMfDump,                 0, "Dump MIFARE classic tag to binary file"},
-  {"restore",  CmdHF14AMfRestore,      0, "Restore MIFARE classic binary file to BLANK tag"},
+  {"help",             CmdHelp,                                                1, "This help"},\r
+  {"dbg",                      CmdHF14AMfDbg,                  0, "Set default debug mode"},\r
+  {"rdbl",             CmdHF14AMfRdBl,                 0, "Read MIFARE classic block"},\r
+  {"urdbl",              CmdHF14AMfURdBl,                 0, "Read MIFARE Ultralight block"},\r
+  {"urdcard",           CmdHF14AMfURdCard,               0,"Read MIFARE Ultralight Card"},\r
+  {"uwrbl",            CmdHF14AMfUWrBl,                0,"Write MIFARE Ultralight block"},\r
+  {"rdsc",             CmdHF14AMfRdSc,                 0, "Read MIFARE classic sector"},\r
+  {"dump",             CmdHF14AMfDump,                 0, "Dump MIFARE classic tag to binary file"},\r
+  {"restore",  CmdHF14AMfRestore,      0, "Restore MIFARE classic binary file to BLANK tag"},\r
   {"wrbl",             CmdHF14AMfWrBl,                 0, "Write MIFARE classic block"},\r
   {"chk",                      CmdHF14AMfChk,                  0, "Test block keys"},\r
   {"mifare",   CmdHF14AMifare,                 0, "Read parity error messages. param - <used card nonce>"},\r
index 2673dcacb6f53e68943af70e45c4758ad9221029..a107e3929e98339585b9c036d0d85e93a55b432b 100644 (file)
@@ -151,6 +151,15 @@ typedef struct {
 
 #define CMD_UNKNOWN                                                       0xFFFF
 
+
+//Mifare simulation flags
+#define FLAG_INTERACTIVE 0x01
+#define FLAG_4B_UID_IN_DATA 0x02
+#define FLAG_7B_UID_IN_DATA 0x04
+#define FLAG_NR_AR_ATTACK 0x08
+
+
+
 // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
 /* Whether a bootloader that understands the common_area is present */
 #define DEVICE_INFO_FLAG_BOOTROM_PRESENT               (1<<0)
Impressum, Datenschutz