]> cvs.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge pull request #3 from Proxmark/master
authormarshmellow42 <marshmellow42@users.noreply.github.com>
Tue, 6 Jan 2015 16:02:11 +0000 (11:02 -0500)
committermarshmellow42 <marshmellow42@users.noreply.github.com>
Tue, 6 Jan 2015 16:02:11 +0000 (11:02 -0500)
re sync with masterB

armsrc/iclass.c
client/cmdhf.c
client/cmdhf.h
client/cmdhf14a.c
client/cmdhficlass.c
client/loclass/elite_crack.c
client/loclass/fileutils.c
client/loclass/fileutils.h
client/loclass/iclass_dump.bin [new file with mode: 0644]
common/iso15693tools.c
include/usb_cmd.h

index 28bdb3bcf6273c0dad9168340c2d4b1187324022..3844ab143f242d2c4554abb18f0163a14aa6e2b9 100644 (file)
@@ -1474,97 +1474,142 @@ void setupIclassReader()
 
 }
 
+size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
+{
+       while(retries-- > 0)
+       {
+               ReaderTransmitIClass(command, cmdsize);
+               if(expected_size == ReaderReceiveIClass(resp)){
+                       return 0;
+               }
+       }
+       return 1;//Error
+}
+
+/**
+ * @brief Talks to an iclass tag, sends the commands to get CSN and CC.
+ * @param card_data where the CSN and CC are stored for return
+ * @return 0 = fail
+ *         1 = Got CSN
+ *         2 = Got CSN and CC
+ */
+uint8_t handshakeIclassTag(uint8_t *card_data)
+{
+       static uint8_t act_all[]     = { 0x0a };
+       static uint8_t identify[]    = { 0x0c };
+       static uint8_t select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       static uint8_t readcheck_cc[]= { 0x88, 0x02 };
+       uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
+
+       uint8_t read_status = 0;
+
+       // Send act_all
+       ReaderTransmitIClass(act_all, 1);
+       // Card present?
+       if(!ReaderReceiveIClass(resp)) return read_status;//Fail
+       //Send Identify
+       ReaderTransmitIClass(identify, 1);
+       //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC
+       uint8_t len  = ReaderReceiveIClass(resp);
+       if(len != 10) return read_status;//Fail
+
+       //Copy the Anti-collision CSN to our select-packet
+       memcpy(&select[1],resp,8);
+       //Select the card
+       ReaderTransmitIClass(select, sizeof(select));
+       //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC
+       len  = ReaderReceiveIClass(resp);
+       if(len != 10) return read_status;//Fail
+
+       //Success - level 1, we got CSN
+       //Save CSN in response data
+       memcpy(card_data,resp,8);
+
+       //Flag that we got to at least stage 1, read CSN
+       read_status = 1;
+
+       // Card selected, now read e-purse (cc)
+       ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
+       if(ReaderReceiveIClass(resp) == 8) {
+               //Save CC (e-purse) in response data
+               memcpy(card_data+8,resp,8);
+
+               //Got both
+               read_status = 2;
+       }
+
+       return read_status;
+}
+
 // Reader iClass Anticollission
 void ReaderIClass(uint8_t arg0) {
-    uint8_t act_all[]     = { 0x0a };
-    uint8_t identify[]    = { 0x0c };
-    uint8_t select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    uint8_t readcheck_cc[]= { 0x88, 0x02 };
 
     uint8_t card_data[24]={0};
     uint8_t last_csn[8]={0};
-
-    uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
        
     int read_status= 0;
     bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
+       bool get_cc = arg0 & FLAG_ICLASS_READER_GET_CC;
 
     setupIclassReader();
 
     size_t datasize = 0;
     while(!BUTTON_PRESS())
     {
-        WDT_HIT();
 
-        // Send act_all
-        ReaderTransmitIClass(act_all, 1);
-        // Card present?
-        if(ReaderReceiveIClass(resp)) {
-
-            ReaderTransmitIClass(identify, 1);
-
-            if(ReaderReceiveIClass(resp) == 10) {
-                //Copy the Anti-collision CSN to our select-packet
-                memcpy(&select[1],resp,8);
-                //Dbprintf("Anti-collision CSN: %02x %02x %02x %02x %02x %02x %02x %02x",resp[0], resp[1], resp[2],
-                //        resp[3], resp[4], resp[5],
-                //        resp[6], resp[7]);
-                //Select the card
-                ReaderTransmitIClass(select, sizeof(select));
-
-                if(ReaderReceiveIClass(resp) == 10) {
-                    //Save CSN in response data
-                    memcpy(card_data,resp,8);
-                    datasize += 8;
-                    //Flag that we got to at least stage 1, read CSN
-                    read_status = 1;
-
-                    // Card selected
-                    //Dbprintf("Readcheck on Sector 2");
-                    ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
-                    if(ReaderReceiveIClass(resp) == 8) {
-                        //Save CC (e-purse) in response data
-                        memcpy(card_data+8,resp,8);
-                        datasize += 8;
-                        //Got both
-                        read_status = 2;
-                    }
-
-                    LED_B_ON();
-                    //Send back to client, but don't bother if we already sent this
-                    if(memcmp(last_csn, card_data, 8) != 0)
-                        cmd_send(CMD_ACK,read_status,0,0,card_data,datasize);
-
-                    //Save that we already sent this....
-                    if(read_status ==  2)
-                        memcpy(last_csn, card_data, 8);
-
-                    LED_B_OFF();
-
-                    if(abort_after_read) break;
-                }
-            }
-        }
+               if(traceLen > TRACE_SIZE) {
+                       DbpString("Trace full");
+                       break;
+               }
+               WDT_HIT();
 
-        if(traceLen > TRACE_SIZE) {
-            DbpString("Trace full");
-            break;
-        }
+               read_status = handshakeIclassTag(card_data);
+
+               if(read_status == 0) continue;
+               if(read_status == 1) datasize = 8;
+               if(read_status == 2) datasize = 16;
+
+               LED_B_ON();
+               //Send back to client, but don't bother if we already sent this
+               if(memcmp(last_csn, card_data, 8) != 0)
+               {
+
+                       if(!get_cc || (get_cc && read_status == 2))
+                       {
+                               cmd_send(CMD_ACK,read_status,0,0,card_data,datasize);
+                               if(abort_after_read) {
+                                       LED_A_OFF();
+                                       return;
+                               }
+                               //Save that we already sent this....
+                               memcpy(last_csn, card_data, 8);
+                       }
+                       //If 'get_cc' was specified and we didn't get a CC, we'll just keep trying...
+               }
+               LED_B_OFF();
     }
+    cmd_send(CMD_ACK,0,0,0,card_data, 0);
     LED_A_OFF();
 }
 
 void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
-       uint8_t act_all[]     = { 0x0a };
-       uint8_t identify[]    = { 0x0c };
-       uint8_t select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-       uint8_t readcheck_cc[]= { 0x88, 0x02 };
+
+       uint8_t card_data[24]={0};
+       uint16_t block_crc_LUT[255] = {0};
+
+       {//Generate a lookup table for block crc
+               for(int block = 0; block < 255; block++){
+                       char bl = block;
+                       block_crc_LUT[block] = iclass_crc16(&bl ,1);
+               }
+       }
+       //Dbprintf("Lookup table: %02x %02x %02x" ,block_crc_LUT[0],block_crc_LUT[1],block_crc_LUT[2]);
+
        uint8_t check[]       = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        uint8_t read[]        = { 0x0c, 0x00, 0x00, 0x00 };
        
     uint16_t crc = 0;
        uint8_t cardsize=0;
-       bool read_success=false;
        uint8_t mem=0;
        
        static struct memory_t{
@@ -1580,102 +1625,72 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
     setupIclassReader();
 
 
-       for(int i=0;i<1;i++) {
+       while(!BUTTON_PRESS()) {
        
+               WDT_HIT();
+
                if(traceLen > TRACE_SIZE) {
                        DbpString("Trace full");
                        break;
                }
                
-               if (BUTTON_PRESS()) break;
+               uint8_t read_status = handshakeIclassTag(card_data);
+               if(read_status < 2) continue;
 
-               // Send act_all
-               ReaderTransmitIClass(act_all, 1);
-               // Card present?
-               if(ReaderReceiveIClass(resp)) {
-                       ReaderTransmitIClass(identify, 1);
-                       if(ReaderReceiveIClass(resp) == 10) {
-                               // Select card          
-                               memcpy(&select[1],resp,8);
-                               ReaderTransmitIClass(select, sizeof(select));
+               //for now replay captured auth (as cc not updated)
+               memcpy(check+5,MAC,4);
 
-                               if(ReaderReceiveIClass(resp) == 10) {
-                                       Dbprintf("     Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
-                                       resp[0], resp[1], resp[2],
-                                       resp[3], resp[4], resp[5],
-                                       resp[6], resp[7]);
-                               }
-                               // Card selected
-                               Dbprintf("Readcheck on Sector 2");
-                               ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
-                               if(ReaderReceiveIClass(resp) == 8) {
-                                  Dbprintf("     CC: %02x %02x %02x %02x %02x %02x %02x %02x",
-                                       resp[0], resp[1], resp[2],
-                                       resp[3], resp[4], resp[5],
-                                       resp[6], resp[7]);
-                               }else return;
-                               Dbprintf("Authenticate");
-                               //for now replay captured auth (as cc not updated)
-                               memcpy(check+5,MAC,4);
-                //Dbprintf("     AA: %02x %02x %02x %02x",
-                //     check[5], check[6], check[7],check[8]);
-                               ReaderTransmitIClass(check, sizeof(check));
-                               if(ReaderReceiveIClass(resp) == 4) {
-                                  Dbprintf("     AR: %02x %02x %02x %02x",
-                                       resp[0], resp[1], resp[2],resp[3]);
-                               }else {
-                                 Dbprintf("Error: Authentication Fail!");
-                                 return;
-                               }
-                               Dbprintf("Dump Contents");
-                               //first get configuration block
-                               read_success=false;
-                               read[1]=1;
-                               uint8_t *blockno=&read[1];
-                               crc = iclass_crc16((char *)blockno,1);
-                               read[2] = crc >> 8;
-                               read[3] = crc & 0xff;
-                               while(!read_success){
-                                     ReaderTransmitIClass(read, sizeof(read));
-                                     if(ReaderReceiveIClass(resp) == 10) {
-                                        read_success=true;
-                                        mem=resp[5];
-                                        memory.k16= (mem & 0x80);
-                                        memory.book= (mem & 0x20);
-                                        memory.k2= (mem & 0x8);
-                                        memory.lockauth= (mem & 0x2);
-                                        memory.keyaccess= (mem & 0x1);
+               if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
+               {
+                       Dbprintf("Error: Authentication Fail!");
+                       continue;
+               }
 
-                                     }
-                               }
-                               if (memory.k16){
-                                 cardsize=255;
-                               }else cardsize=32;
-                               //then loop around remaining blocks
-                               for(uint8_t j=0; j<cardsize; j++){
-                                   read_success=false;
-                                   uint8_t *blockno=&j;
-                                   //crc_data[0]=j;
-                                   read[1]=j;
-                                   crc = iclass_crc16((char *)blockno,1);
-                                   read[2] = crc >> 8;
-                                   read[3] = crc & 0xff;
-                                   while(!read_success){
-                                     ReaderTransmitIClass(read, sizeof(read));
-                                     if(ReaderReceiveIClass(resp) == 10) {
-                                        read_success=true;
-                                        Dbprintf("     %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
-                                         j, resp[0], resp[1], resp[2],
-                                         resp[3], resp[4], resp[5],
-                                         resp[6], resp[7]);
-                                     }
-                                   }
-                               }
-                       }
+               //first get configuration block (block 1)
+               crc = block_crc_LUT[1];
+               read[1]=1;
+               read[2] = crc >> 8;
+               read[3] = crc & 0xff;
+
+               if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
+               {
+                       Dbprintf("Dump config (block 1) failed");
+                       continue;
                }
+
+               mem=resp[5];
+               memory.k16= (mem & 0x80);
+               memory.book= (mem & 0x20);
+               memory.k2= (mem & 0x8);
+               memory.lockauth= (mem & 0x2);
+               memory.keyaccess= (mem & 0x1);
+
+               cardsize = memory.k16 ? 255 : 32;
                WDT_HIT();
+
+               //then loop around remaining blocks
+               for(int block=0; block < cardsize; block++){
+
+                       read[1]= block;
+                       crc = block_crc_LUT[block];
+                       read[2] = crc >> 8;
+                       read[3] = crc & 0xff;
+
+                       if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
+                       {
+                               Dbprintf("     %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
+                                                block, resp[0], resp[1], resp[2],
+                                               resp[3], resp[4], resp[5],
+                                               resp[6], resp[7]);
+
+                       }else{
+                               Dbprintf("Failed to dump block %d", block);
+
+                       }
+               }
+               //If we got here, let's break
+               break;
        }
-       
        LED_A_OFF();
 }
 
index d955fc8321456ee48f74d935d0c68d511b738357..85cc542583d3339b79584518f654d5c3f6b40766 100644 (file)
@@ -9,6 +9,7 @@
 //-----------------------------------------------------------------------------
 
 #include <stdio.h>
+#include <string.h>
 //#include "proxusb.h"
 #include "proxmark3.h"
 #include "graph.h"
@@ -31,6 +32,279 @@ int CmdHFTune(const char *Cmd)
   SendCommand(&c);
   return 0;
 }
+// for the time being. Need better Bigbuf handling.
+#define TRACE_SIZE 3000
+
+#define ICLASS_CMD_ACTALL 0x0A
+#define ICLASS_CMD_IDENTIFY 0x0C
+#define ICLASS_CMD_READ 0x0C
+#define ICLASS_CMD_SELECT 0x81
+#define ICLASS_CMD_PAGESEL 0x84
+#define ICLASS_CMD_READCHECK 0x88
+#define ICLASS_CMD_CHECK 0x05
+#define ICLASS_CMD_SOF 0x0F
+#define ICLASS_CMD_HALT 0x00
+
+#define iso14443_CMD_WUPA       0x52
+#define iso14443_CMD_SELECT     0x93
+#define iso14443_CMD_SELECT_2   0x95
+#define iso14443_CMD_REQ        0x26
+#define iso14443_CMD_READBLOCK  0x30
+#define iso14443_CMD_WRITEBLOCK 0xA0
+#define iso14443_CMD_INC        0xC0
+#define iso14443_CMD_DEC        0xC1
+#define iso14443_CMD_RESTORE    0xC2
+#define iso14443_CMD_TRANSFER   0xB0
+#define iso14443_CMD_HALT       0x50
+#define iso14443_CMD_RATS       0xE0
+
+
+void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
+{
+       switch(cmd[0])
+       {
+       case iso14443_CMD_WUPA:            snprintf(exp,size,"WUPA"); break;
+       case iso14443_CMD_SELECT:{
+               if(cmdsize > 2)
+               {
+                       snprintf(exp,size,"SELECT_UID"); break;
+               }else
+               {
+                       snprintf(exp,size,"SELECT_ALL"); break;
+               }
+       }
+       case iso14443_CMD_SELECT_2:    snprintf(exp,size,"SELECT_2"); break;
+       case iso14443_CMD_REQ:         snprintf(exp,size,"REW"); break;
+       case iso14443_CMD_READBLOCK:   snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break;
+       case iso14443_CMD_WRITEBLOCK:  snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break;
+       case iso14443_CMD_INC:         snprintf(exp,size,"INC(%d)",cmd[1]); break;
+       case iso14443_CMD_DEC:         snprintf(exp,size,"DEC(%d)",cmd[1]); break;
+       case iso14443_CMD_RESTORE:     snprintf(exp,size,"RESTORE(%d)",cmd[1]); break;
+       case iso14443_CMD_TRANSFER:    snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break;
+       case iso14443_CMD_HALT:        snprintf(exp,size,"HALT"); break;
+       case iso14443_CMD_RATS:        snprintf(exp,size,"RATS"); break;
+       default:                       snprintf(exp,size,"?"); break;
+       }
+       return;
+}
+
+void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
+{
+
+       if(cmdsize > 1 && cmd[0] == ICLASS_CMD_READ)
+       {
+                 snprintf(exp,size,"READ(%d)",cmd[1]);
+                 return;
+       }
+
+       switch(cmd[0])
+       {
+       case ICLASS_CMD_ACTALL:      snprintf(exp,size,"ACTALL"); break;
+       case ICLASS_CMD_IDENTIFY:    snprintf(exp,size,"IDENTIFY"); break;
+       case ICLASS_CMD_SELECT:      snprintf(exp,size,"SELECT"); break;
+       case ICLASS_CMD_PAGESEL:     snprintf(exp,size,"PAGESEL"); break;
+       case ICLASS_CMD_READCHECK:   snprintf(exp,size,"READCHECK"); break;
+       case ICLASS_CMD_CHECK:       snprintf(exp,size,"CHECK"); break;
+       case ICLASS_CMD_SOF:         snprintf(exp,size,"SOF"); break;
+       case ICLASS_CMD_HALT:        snprintf(exp,size,"HALT"); break;
+       default:                     snprintf(exp,size,"?"); break;
+       }
+       return;
+}
+
+
+
+uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool showWaitCycles)
+{
+       bool isResponse;
+       uint16_t duration, data_len,parity_len;
+
+       uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
+       char explanation[30] = {0};
+
+       first_timestamp = *((uint32_t *)(trace));
+       timestamp = *((uint32_t *)(trace + tracepos));
+       // Break and stick with current result if buffer was not completely full
+       if (timestamp == 0x44444444) return TRACE_SIZE;
+
+       tracepos += 4;
+       duration = *((uint16_t *)(trace + tracepos));
+       tracepos += 2;
+       data_len = *((uint16_t *)(trace + tracepos));
+       tracepos += 2;
+
+       if (data_len & 0x8000) {
+         data_len &= 0x7fff;
+         isResponse = true;
+       } else {
+         isResponse = false;
+       }
+       parity_len = (data_len-1)/8 + 1;
+
+       if (tracepos + data_len + parity_len >= TRACE_SIZE) {
+               return TRACE_SIZE;
+       }
+
+       uint8_t *frame = trace + tracepos;
+       tracepos += data_len;
+       uint8_t *parityBytes = trace + tracepos;
+       tracepos += parity_len;
+
+       //--- Draw the data column
+       char line[16][110];
+       for (int j = 0; j < data_len; j++) {
+               int oddparity = 0x01;
+               int k;
+
+               for (k=0 ; k<8 ; k++) {
+                       oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
+               }
+
+               uint8_t parityBits = parityBytes[j>>3];
+
+               if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+                       sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]);
+               } else {
+                       sprintf(line[j/16]+((j%16)*4), "%02x  ", frame[j]);
+               }
+       }
+       //--- Draw the CRC column
+       bool crcError = false;
+
+       if (data_len > 2) {
+               uint8_t b1, b2;
+               if(iclass)
+               {
+                       if(!isResponse && data_len == 4 ) {
+                               // Rough guess that this is a command from the reader
+                               // For iClass the command byte is not part of the CRC
+                               ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2);
+                       }
+                       else {
+                               // For other data.. CRC might not be applicable (UPDATE commands etc.)
+                               ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2);
+                       }
+
+                       if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
+                               crcError = true;
+                       }
+
+               }else{//Iso 14443a
+
+                       ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
+
+                       if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
+                               if(!(isResponse & (data_len < 6)))
+                               {
+                                               crcError = true;
+                               }
+                       }
+               }
+
+       }
+       char *crc = crcError ? "!crc" :"    ";
+
+       EndOfTransmissionTimestamp = timestamp + duration;
+
+       if(!isResponse)
+       {
+               if(iclass)      annotateIclass(explanation,sizeof(explanation),frame,data_len);
+               else annotateIso14443a(explanation,sizeof(explanation),frame,data_len);
+       }
+
+       int num_lines = (data_len - 1)/16 + 1;
+       for (int j = 0; j < num_lines; j++) {
+               if (j == 0) {
+                       PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
+                               (timestamp - first_timestamp),
+                               (EndOfTransmissionTimestamp - first_timestamp),
+                               (isResponse ? "Tag" : "Rdr"),
+                               line[j],
+                               (j == num_lines-1) ? crc : "    ",
+                               (j == num_lines-1) ? explanation : "");
+               } else {
+                       PrintAndLog("           |           |     | %-64s| %s| %s",
+                               line[j],
+                               (j == num_lines-1)?crc:"    ",
+                               (j == num_lines-1) ? explanation : "");
+               }
+       }
+
+       bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
+
+       if (showWaitCycles && !isResponse && next_isResponse) {
+               uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
+               if (next_timestamp != 0x44444444) {
+                       PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
+                               (EndOfTransmissionTimestamp - first_timestamp),
+                               (next_timestamp - first_timestamp),
+                               "   ",
+                               (next_timestamp - EndOfTransmissionTimestamp));
+               }
+       }
+       return tracepos;
+}
+
+int CmdHFList(const char *Cmd)
+{
+       bool showWaitCycles = false;
+       char type[40] = {0};
+       int tlen = param_getstr(Cmd,0,type);
+       char param = param_getchar(Cmd, 1);
+       bool errors = false;
+       bool iclass = false;
+       //Validate params
+       if(tlen == 0 || (strcmp(type, "iclass") != 0 && strcmp(type,"14a") != 0))
+       {
+               errors = true;
+       }
+       if(param == 'h' || (param !=0 && param != 'f'))
+       {
+               errors = true;
+       }
+
+       if (errors) {
+               PrintAndLog("List protocol data in trace buffer.");
+               PrintAndLog("Usage:  hf list [14a|iclass] [f]");
+               PrintAndLog("    14a    - interpret data as iso14443a communications");
+               PrintAndLog("    iclass - interpret data as iclass communications");
+               PrintAndLog("    f      - show frame delay times as well");
+               PrintAndLog("");
+               PrintAndLog("example: hf list 14a f");
+               PrintAndLog("example: hf list iclass");
+               return 0;
+       }
+       if(strcmp(type, "iclass") == 0)
+       {
+               iclass = true;
+       }
+
+       if (param == 'f') {
+               showWaitCycles = true;
+       }
+
+
+       uint8_t trace[TRACE_SIZE];
+       uint16_t tracepos = 0;
+       GetFromBigBuf(trace, TRACE_SIZE, 0);
+       WaitForResponse(CMD_ACK, NULL);
+
+       PrintAndLog("Recorded Activity");
+       PrintAndLog("");
+       PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
+       PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
+       PrintAndLog("iClass    - Timings are not as accurate");
+       PrintAndLog("");
+       PrintAndLog("     Start |       End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
+       PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
+
+       while(tracepos < TRACE_SIZE)
+       {
+               tracepos = printTraceLine(tracepos, trace, iclass, showWaitCycles);
+       }
+       return 0;
+}
+
 
 static command_t CommandTable[] = 
 {
@@ -41,9 +315,10 @@ static command_t CommandTable[] =
   {"epa",         CmdHFEPA,         1, "{ German Identification Card... }"},
   {"legic",       CmdHFLegic,       0, "{ LEGIC RFIDs... }"},
   {"iclass",      CmdHFiClass,      1, "{ ICLASS RFIDs... }"},
-  {"mf",               CmdHFMF,                      1, "{ MIFARE RFIDs... }"},
+  {"mf",               CmdHFMF,                1, "{ MIFARE RFIDs... }"},
   {"tune",        CmdHFTune,        0, "Continuously measure HF antenna tuning"},
-  {NULL, NULL, 0, NULL}
+  {"list",       CmdHFList,         1, "List protocol data in trace buffer"},
+       {NULL, NULL, 0, NULL}
 };
 
 int CmdHF(const char *Cmd)
index ff20a950a1dc63cb3ef5fd87fb13ffe9b5711c0a..026357b5a973b4c133cc2e14fa5d4b8d08737584 100644 (file)
@@ -13,5 +13,5 @@
 
 int CmdHF(const char *Cmd);
 int CmdHFTune(const char *Cmd);
-
+int CmdHFList(const char *Cmd);
 #endif
index c997607652c9c8b632a6dffcf239efd5c23d31e1..36ffe1b805f5c240f3ee78ab22c2c1b7a16e636e 100644 (file)
@@ -29,145 +29,7 @@ static void waitCmd(uint8_t iLen);
 
 int CmdHF14AList(const char *Cmd)
 {
-       bool ShowWaitCycles = false;
-       char param = param_getchar(Cmd, 0);
-       
-       if (param == 'h' || (param != 0 && param != 'f')) {
-               PrintAndLog("List data in trace buffer.");
-               PrintAndLog("Usage:  hf 14a list [f]");
-               PrintAndLog("f - show frame delay times as well");
-               PrintAndLog("sample: hf 14a list f");
-               return 0;
-       }       
-
-       if (param == 'f') {
-               ShowWaitCycles = true;
-       }
-
-// for the time being. Need better Bigbuf handling.    
-#define TRACE_SIZE 3000        
-
-       uint8_t trace[TRACE_SIZE];
-       GetFromBigBuf(trace, TRACE_SIZE, 0);
-       WaitForResponse(CMD_ACK, NULL);
-
-       PrintAndLog("Recorded Activity");
-       PrintAndLog("");
-       PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
-       PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
-       PrintAndLog("");
-       PrintAndLog("     Start |       End | Src | Data (! denotes parity error)                                   | CRC ");
-       PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------");
-
-       uint16_t tracepos = 0;
-       uint16_t duration;
-       uint16_t data_len;
-       uint16_t parity_len;
-       bool isResponse;
-       uint32_t timestamp;
-       uint32_t first_timestamp;
-       uint32_t EndOfTransmissionTimestamp;
-       
-       for (;;) {
-
-               if(tracepos >= TRACE_SIZE) {
-                       break;
-               }
-
-               timestamp = *((uint32_t *)(trace + tracepos));
-               if(tracepos == 0) {
-                       first_timestamp = timestamp;
-               }
-
-               // Break and stick with current result if buffer was not completely full
-               if (timestamp == 0x44444444) break; 
-
-               tracepos += 4;
-               duration = *((uint16_t *)(trace + tracepos));
-               tracepos += 2;
-               data_len = *((uint16_t *)(trace + tracepos));
-               tracepos += 2;
-               
-               if (data_len & 0x8000) {
-                 data_len &= 0x7fff;
-                 isResponse = true;
-               } else {
-                 isResponse = false;
-               }
-
-               parity_len = (data_len-1)/8 + 1;
-
-               if (tracepos + data_len + parity_len >= TRACE_SIZE) {
-                       break;
-               }
-               
-               uint8_t *frame = trace + tracepos;
-               tracepos += data_len;
-               uint8_t *parityBytes = trace + tracepos;
-               tracepos += parity_len;
-
-               char line[16][110];
-               for (int j = 0; j < data_len; j++) {
-                       int oddparity = 0x01;
-                       int k;
-                       
-                       for (k=0;k<8;k++) {
-                               oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
-                       }
-
-                       uint8_t parityBits = parityBytes[j>>3];
-                       if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
-                               sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]);
-                       } else {
-                               sprintf(line[j/16]+((j%16)*4), "%02x  ", frame[j]);
-                       }
-
-               }
-
-               char crc[5] = ""; 
-               if (data_len > 2) {
-               uint8_t b1, b2;
-                       ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
-                       if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
-                               sprintf(crc, (isResponse & (data_len < 6)) ? "" : "!crc");
-                       } else {
-                               sprintf(crc, "");
-                       }
-               }
-
-               EndOfTransmissionTimestamp = timestamp + duration;
-               
-               int num_lines = (data_len - 1)/16 + 1;
-               for (int j = 0; j < num_lines; j++) {
-                       if (j == 0) {
-                               PrintAndLog(" %9d | %9d | %s | %-64s| %s",
-                                       (timestamp - first_timestamp),
-                                       (EndOfTransmissionTimestamp - first_timestamp),
-                                       (isResponse ? "Tag" : "Rdr"),
-                                       line[j], 
-                                       (j == num_lines-1)?crc:"");
-                       } else {
-                               PrintAndLog("           |           |     | %-64s| %s",
-                                       line[j], 
-                                       (j == num_lines-1)?crc:"");
-                       }
-               }                               
-
-               bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
-               
-               if (ShowWaitCycles && !isResponse && next_isResponse) {
-                       uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
-                       if (next_timestamp != 0x44444444) {
-                               PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
-                                       (EndOfTransmissionTimestamp - first_timestamp),
-                                       (next_timestamp - first_timestamp),
-                                       "   ",
-                                       (next_timestamp - EndOfTransmissionTimestamp));
-                       }
-               }
-                       
-       }
-       
+       PrintAndLog("Deprecated command, use 'hf list 14a' instead");
        return 0;
 }
 
@@ -510,7 +372,7 @@ int CmdHF14ASnoop(const char *Cmd) {
        
        if (param_getchar(Cmd, 0) == 'h') {
                PrintAndLog("It get data from the field and saves it into command buffer.");
-               PrintAndLog("Buffer accessible from command hf 14a list.");
+               PrintAndLog("Buffer accessible from command hf list 14a.");
                PrintAndLog("Usage:  hf 14a snoop [c][r]");
                PrintAndLog("c - triggered by first data from card");
                PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)");
@@ -671,7 +533,7 @@ static void waitCmd(uint8_t iSelect)
 static command_t CommandTable[] = 
 {
   {"help",   CmdHelp,              1, "This help"},
-  {"list",   CmdHF14AList,         0, "List ISO 14443a history"},
+  {"list",   CmdHF14AList,         0, "[Deprecated] List ISO 14443a history"},
   {"reader", CmdHF14AReader,       0, "Act like an ISO14443 Type A reader"},
   {"cuids",  CmdHF14ACUIDs,        0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
   {"sim",    CmdHF14ASim,          0, "<UID> -- Fake ISO 14443a tag"},
index 583d518e6d4a3e85a1198d3015303bc1dbf24674..dba4f1132597bb8ff9ed8ad0aef4b6279bbf6966 100644 (file)
@@ -44,150 +44,7 @@ int xorbits_8(uint8_t val)
 
 int CmdHFiClassList(const char *Cmd)
 {
-       bool ShowWaitCycles = false;
-       char param = param_getchar(Cmd, 0);
-       
-       if (param != 0) {
-               PrintAndLog("List data in trace buffer.");
-               PrintAndLog("Usage:  hf iclass list");
-               PrintAndLog("h - help");
-               PrintAndLog("sample: hf iclass list");
-               return 0;
-       }
-
-// for the time being. Need better Bigbuf handling.    
-#define TRACE_SIZE 3000        
-
-       uint8_t trace[TRACE_SIZE];
-       GetFromBigBuf(trace, TRACE_SIZE, 0);
-       WaitForResponse(CMD_ACK, NULL);
-
-       PrintAndLog("Recorded Activity");
-       PrintAndLog("");
-       PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
-       PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
-       PrintAndLog("");
-       PrintAndLog("     Start |       End | Src | Data (! denotes parity error)                                   | CRC ");
-       PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------");
-
-       uint16_t tracepos = 0;
-       uint16_t duration;
-       uint16_t data_len;
-       uint16_t parity_len;
-       bool isResponse;
-       uint32_t timestamp;
-       uint32_t first_timestamp;
-       uint32_t EndOfTransmissionTimestamp;
-       
-       for (;;) {
-
-               if(tracepos >= TRACE_SIZE) {
-                       break;
-               }
-
-               timestamp = *((uint32_t *)(trace + tracepos));
-               if(tracepos == 0) {
-                       first_timestamp = timestamp;
-               }
-
-               // Break and stick with current result if buffer was not completely full
-               if (timestamp == 0x44444444) break; 
-
-               tracepos += 4;
-               duration = *((uint16_t *)(trace + tracepos));
-               tracepos += 2;
-               data_len = *((uint16_t *)(trace + tracepos));
-               tracepos += 2;
-               
-               if (data_len & 0x8000) {
-                 data_len &= 0x7fff;
-                 isResponse = true;
-               } else {
-                 isResponse = false;
-               }
-
-               parity_len = (data_len-1)/8 + 1;
-
-               if (tracepos + data_len + parity_len >= TRACE_SIZE) {
-                       break;
-               }
-               
-               uint8_t *frame = trace + tracepos;
-               tracepos += data_len;
-               uint8_t *parityBytes = trace + tracepos;
-               tracepos += parity_len;
-
-               char line[16][110];
-               for (int j = 0; j < data_len; j++) {
-                       int oddparity = 0x01;
-                       int k;
-                       
-                       for (k=0;k<8;k++) {
-                               oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
-                       }
-
-                       uint8_t parityBits = parityBytes[j>>3];
-                       if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
-                               sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]);
-                       } else {
-                               sprintf(line[j/16]+((j%16)*4), "%02x  ", frame[j]);
-                       }
-
-               }
-
-               char *crc = ""; 
-               if (data_len > 2) {
-                       uint8_t b1, b2;
-                       if(!isResponse && data_len == 4 ) {
-                               // Rough guess that this is a command from the reader
-                               // For iClass the command byte is not part of the CRC
-                               ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2);
-                               if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
-                                       crc = "!crc";
-                               }
-                       }
-                       else {
-                               // For other data.. CRC might not be applicable (UPDATE commands etc.)
-                               ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2);
-                               if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
-                                       crc = "!crc";
-                               }
-                       }
-               }
-
-               EndOfTransmissionTimestamp = timestamp + duration;
-               
-               int num_lines = (data_len - 1)/16 + 1;
-               for (int j = 0; j < num_lines; j++) {
-                       if (j == 0) {
-                               PrintAndLog(" %9d | %9d | %s | %-64s| %s",
-                                       (timestamp - first_timestamp),
-                                       (EndOfTransmissionTimestamp - first_timestamp),
-                                       (isResponse ? "Tag" : "Rdr"),
-                                       line[j], 
-                                       (j == num_lines-1)?crc:"");
-                       } else {
-                               PrintAndLog("           |           |     | %-64s| %s",
-                                       line[j], 
-                                       (j == num_lines-1)?crc:"");
-                       }
-               }                               
-
-               bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
-               
-               if (ShowWaitCycles && !isResponse && next_isResponse) {
-                       uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
-                       if (next_timestamp != 0x44444444) {
-                               PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
-                                       (EndOfTransmissionTimestamp - first_timestamp),
-                                       (next_timestamp - first_timestamp),
-                                       "   ",
-                                       (next_timestamp - EndOfTransmissionTimestamp));
-                       }
-               }
-                       
-       }
-       
+       PrintAndLog("Deprecated command, use 'hf list iclass' instead");
        return 0;
 }
 
@@ -322,7 +179,11 @@ int CmdHFiClassReader(const char *Cmd)
             uint8_t * data  = resp.d.asBytes;
 
             PrintAndLog("isOk:%02x", isOK);
-
+            if( isOK == 0){
+                //Aborted
+                PrintAndLog("Quitting...");
+                return 0;
+            }
             if(isOK > 0)
             {
                 PrintAndLog("CSN: %s",sprint_hex(data,8));
@@ -425,7 +286,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
 
 
   UsbCommand c = {CMD_READER_ICLASS, {0}};
-  c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE;
+  c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC;
   if(!fake_dummy_test)   
     SendCommand(&c);
   
@@ -573,19 +434,64 @@ int CmdHFiClass_iso14443A_write(const char *Cmd)
   }
   return 0;
 }
+int CmdHFiClass_loclass(const char *Cmd)
+{
+       char opt = param_getchar(Cmd, 0);
+
+       if (strlen(Cmd)<1 || opt == 'h') {
+               PrintAndLog("Usage: hf iclass loclass [options]");
+               PrintAndLog("Options:");
+               PrintAndLog("h             Show this help");
+               PrintAndLog("t             Perform self-test");
+               PrintAndLog("f <filename>  Bruteforce iclass dumpfile");
+               PrintAndLog("                   An iclass dumpfile is assumed to consist of an arbitrary number of");
+               PrintAndLog("                   malicious CSNs, and their protocol responses");
+               PrintAndLog("                   The the binary format of the file is expected to be as follows: ");
+               PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
+               PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
+               PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
+               PrintAndLog("                  ... totalling N*24 bytes");
+               return 0;
+       }
+       char fileName[255] = {0};
+       if(opt == 'f')
+       {
+                       if(param_getstr(Cmd, 1, fileName) > 0)
+                       {
+                               return bruteforceFileNoKeys(fileName);
+                       }else
+                       {
+                               PrintAndLog("You must specify a filename");
+                       }
+       }
+       else if(opt == 't')
+       {
+               int errors = testCipherUtils();
+               errors += testMAC();
+               errors += doKeyTests(0);
+               errors += testElite();
+               if(errors)
+               {
+                       prnlog("OBS! There were errors!!!");
+               }
+               return errors;
+       }
 
+       return 0;
+}
 
 static command_t CommandTable[] = 
 {
-  {"help",     CmdHelp,                        1,      "This help"},
-  {"list",     CmdHFiClassList,        0,      "List iClass history"},
-  {"snoop",    CmdHFiClassSnoop,       0,      "Eavesdrop iClass communication"},
-  {"sim",      CmdHFiClassSim,         0,      "Simulate iClass tag"},
-  {"reader",CmdHFiClassReader, 0,      "Read an iClass tag"},
-  {"replay",CmdHFiClassReader_Replay,  0,      "Read an iClass tag via Reply Attack"},
-  {"dump",     CmdHFiClassReader_Dump, 0,              "Authenticate and Dump iClass tag"},
-  {"write",    CmdHFiClass_iso14443A_write,    0,      "Authenticate and Write iClass block"},
-  {NULL, NULL, 0, NULL}
+       {"help",        CmdHelp,                        1,      "This help"},
+       {"list",        CmdHFiClassList,        0,      "[Deprecated] List iClass history"},
+       {"snoop",       CmdHFiClassSnoop,       0,      "Eavesdrop iClass communication"},
+       {"sim", CmdHFiClassSim,         0,      "Simulate iClass tag"},
+       {"reader",CmdHFiClassReader,    0,      "Read an iClass tag"},
+       {"replay",CmdHFiClassReader_Replay,     0,      "Read an iClass tag via Reply Attack"},
+       {"dump",        CmdHFiClassReader_Dump, 0,              "Authenticate and Dump iClass tag"},
+       {"write",       CmdHFiClass_iso14443A_write,    0,      "Authenticate and Write iClass block"},
+       {"loclass",     CmdHFiClass_loclass,    1,      "Use loclass to perform bruteforce of reader attack dump"},
+       {NULL, NULL, 0, NULL}
 };
 
 int CmdHFiClass(const char *Cmd)
index 7dc60396fe777d8218ce9142d5e0af9288dab4ac..f0eb964bc554b2fc5227f8a4626fc8755a34677f 100644 (file)
@@ -526,7 +526,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[])
        fseek(f, 0, SEEK_SET);
 
        uint8_t *dump = malloc(fsize);
-    size_t bytes_read = fread(dump, fsize, 1, f);
+       size_t bytes_read = fread(dump, 1, fsize, f);
 
        fclose(f);
     if (bytes_read < fsize)
@@ -577,9 +577,18 @@ int _testBruteforce()
                        **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
                **/
                uint16_t keytable[128] = {0};
-               //save some time...
-               startvalue = 0x7B0000;
-               errors |= bruteforceFile("iclass_dump.bin",keytable);
+
+               //Test a few variants
+               if(fileExists("iclass_dump.bin"))
+               {
+                       errors |= bruteforceFile("iclass_dump.bin",keytable);
+               }else if(fileExists("loclass/iclass_dump.bin")){
+                       errors |= bruteforceFile("loclass/iclass_dump.bin",keytable);
+               }else if(fileExists("client/loclass/iclass_dump.bin")){
+                       errors |= bruteforceFile("client/loclass/iclass_dump.bin",keytable);
+               }else{
+                       prnlog("Error: The file iclass_dump.bin was not found!");
+               }
        }
        return errors;
 }
index 255aa313700ef12ced86f1b79d9c2f0584bd3277..9ea9d1454df2af9861fcb20fc061ce5bdd8e53fa 100644 (file)
@@ -57,11 +57,11 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
  */
 void prnlog(char *fmt, ...)
 {
-
+       char buffer[2048] = {0};
        va_list args;
        va_start(args,fmt);
-    PrintAndLog(fmt, args);
-    //vprintf(fmt,args);
+       vsprintf (buffer,fmt, args);
        va_end(args);
-    //printf("\n");
+       PrintAndLog(buffer);
+
 }
index a0f5a799e246e4f7a9a80fb1d3545098b14a0b8e..e02079d52a91c6d40ee8c60f13efb1ea2486cf43 100644 (file)
@@ -21,4 +21,5 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
  * @param fmt
  */
 void prnlog(char *fmt, ...);
+int fileExists(const char *filename);
 #endif // FILEUTILS_H
diff --git a/client/loclass/iclass_dump.bin b/client/loclass/iclass_dump.bin
new file mode 100644 (file)
index 0000000..bfecd1b
Binary files /dev/null and b/client/loclass/iclass_dump.bin differ
index 0f7a250bf94c54651ec048474c3ced3d2b56c0f9..26e636ca7b0c27d90dee14bf3f79d70168fd546c 100644 (file)
@@ -66,11 +66,11 @@ char* Iso15693sprintUID(char *target,uint8_t *uid) {
   return target;
 }
 
-unsigned short iclass_crc16(char *data_p, unsigned short length)
+uint16_t iclass_crc16(char *data_p, unsigned short length)
 {
       unsigned char i;
       unsigned int data;
-      unsigned int crc = 0xffff;
+         uint16_t crc = 0xffff;
 
       if (length == 0)
             return (~crc);
index 3e00c0a64b5144eb100d0e4e15a3dbf1008be13d..4d50de5941537c465e0237527099b6debcc6887e 100644 (file)
@@ -167,7 +167,8 @@ typedef struct {
 
 
 //Iclass reader flags
-#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
+#define FLAG_ICLASS_READER_ONLY_ONCE    0x01
+#define FLAG_ICLASS_READER_GET_CC       0x02
 
 // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
 /* Whether a bootloader that understands the common_area is present */
Impressum, Datenschutz