]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/iclass.c
Experimenting with hacking iclass
[proxmark3-svn] / armsrc / iclass.c
index 6f81526b6ea1d955059ea296fcd1be6993b1faf8..bfa4a730c71e3f726ccbb1da277959d2ab12e1a0 100644 (file)
@@ -691,7 +691,7 @@ void RAMFUNC SnoopIClass(void)
     
     // reset traceLen to 0
     iso14a_set_tracing(TRUE);
-    iso14a_clear_tracelen();
+    iso14a_clear_trace();
     iso14a_set_trigger(FALSE);
 
     // The DMA buffer, used to stream samples from the FPGA
@@ -986,32 +986,71 @@ static void CodeIClassTagSOF()
        ToSendMax++;
 }
 
-//-----------------------------------------------------------------------------
-// Simulate iClass Card
-// Only CSN (Card Serial Number)
-// 
-//-----------------------------------------------------------------------------
-void SimulateIClass(uint8_t arg0, uint8_t *datain)
+/**
+ * @brief SimulateIClass simulates an iClass card.
+ * @param arg0 type of simulation
+ *                     - 0 uses the first 8 bytes in usb data as CSN
+ *                     - 2 "dismantling iclass"-attack. This mode iterates through all CSN's specified
+ *                     in the usb data. This mode collects MAC from the reader, in order to do an offline
+ *                     attack on the keys. For more info, see "dismantling iclass" and proxclone.com.
+ *                     - Other : Uses the default CSN (031fec8af7ff12e0)
+ * @param arg1 - number of CSN's contained in datain (applicable for mode 2 only)
+ * @param arg2
+ * @param datain
+ */
+void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)
 {
-       uint8_t simType = arg0;
+       uint32_t simType = arg0;
+       uint32_t numberOfCSNS = arg1;
 
-  // Enable and clear the trace
-       tracing = TRUE;
-       traceLen = 0;
-  memset(trace, 0x44, TRACE_SIZE);
+       // Enable and clear the trace
+       iso14a_set_tracing(TRUE);
+       iso14a_clear_trace();
+
+       uint8_t csn_crc[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 };
+
+       if(simType == 0) {
+               // Use the CSN from commandline
+               memcpy(csn_crc, datain, 8);
+               doIClassSimulation(csn_crc,0);
+       }else if(simType == 1)
+       {
+               doIClassSimulation(csn_crc,0);
+       }
+       else if(simType == 2)
+       {
+               // In this mode, a number of csns are within datain. We'll simulate each one, one at a time
+               // in order to collect MAC's from the reader. This can later be used in an offlne-attack
+               // in order to obtain the keys, as in the "dismantling iclass"-paper.
+               for(int i = 0 ; i < numberOfCSNS && i*8+8 < USB_CMD_DATA_SIZE; i++)
+               {
+                       // The usb data is 512 bytes, fitting 65 8-byte CSNs in there.
+
+                       memcpy(csn_crc, datain+(i*8), 8);
+                       doIClassSimulation(csn_crc,1);
+               }
+       }else{
+               // We may want a mode here where we hardcode the csns to use (from proxclone).
+               // That will speed things up a little, but not required just yet.
+               Dbprintf("The mode is not implemented, reserved for future use");
+       }
 
+}
+/**
+ * @brief Does the actual simulation
+ * @param csn - csn to use
+ * @param breakAfterMacReceived if true, returns after reader MAC has been received.
+ */
+void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived)
+{
        // CSN followed by two CRC bytes
        uint8_t response2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-       uint8_t response3[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 };
+       uint8_t response3[] = { 0,0,0,0,0,0,0,0,0,0};
+       memcpy(response3,csn,sizeof(response3));
 
        // e-Purse
        uint8_t response4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-       if(simType == 0) {
-               // Use the CSN from commandline
-               memcpy(response3, datain, 8);
-       }
-
        // Construct anticollision-CSN
        rotateCSN(response3,response2);
 
@@ -1019,6 +1058,7 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain)
        ComputeCrc14443(CRC_ICLASS, response2, 8, &response2[8], &response2[9]);
        ComputeCrc14443(CRC_ICLASS, response3, 8, &response3[8], &response3[9]);
 
+       int exitLoop = 0;
        // Reader 0a
        // Tag    0f
        // Reader 0c
@@ -1052,7 +1092,7 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain)
        int resp4Len;
 
        // + 1720..
-  uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+       uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
        memset(receivedCmd, 0x44, RECV_CMD_SIZE);
        int len;
 
@@ -1083,7 +1123,7 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain)
        int cmdsRecvd = 0;
 
        LED_A_ON();
-       for(;;) {
+       while(!exitLoop) {
                LED_B_OFF();
                if(!GetIClassCommandFromReader(receivedCmd, &len, 100)) {
                        DbpString("button press");
@@ -1119,24 +1159,21 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain)
                        LED_B_ON();
                } else if(receivedCmd[0] == 0x05) {
                        // Reader random and reader MAC!!!
-                       // Lets store this ;-)
-/*
-                       Dbprintf("                CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
-                       response3[0], response3[1], response3[2],
-                       response3[3], response3[4], response3[5],
-                       response3[6], response3[7]);
-*/                     
-                       Dbprintf("READER AUTH (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x",
-                       len,
-                       receivedCmd[0], receivedCmd[1], receivedCmd[2],
-                       receivedCmd[3], receivedCmd[4], receivedCmd[5],
-                       receivedCmd[6], receivedCmd[7], receivedCmd[8]);
-
                        // Do not respond
                        // We do not know what to answer, so lets keep quit
                        resp = resp1; respLen = 0; //order = 5;
                        respdata = NULL;
                        respsize = 0;
+                       if (breakAfterMacReceived){
+                               // TODO, actually return this to the caller instead of just
+                               // dbprintf:ing ...
+                               Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x");
+                               Dbprintf("RDR:  (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x",len,
+                                                receivedCmd[0], receivedCmd[1], receivedCmd[2],
+                                               receivedCmd[3], receivedCmd[4], receivedCmd[5],
+                                               receivedCmd[6], receivedCmd[7], receivedCmd[8]);
+                               exitLoop = true;
+                       }
                } else if(receivedCmd[0] == 0x00 && len == 1) {
                        // Reader ends the session
                        resp = resp1; respLen = 0; //order = 0;
@@ -1168,12 +1205,15 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain)
                }
                
                if (tracing) {
-                       LogTrace(receivedCmd,len, 0, Uart.parityBits, TRUE);
+                       LogTrace(receivedCmd,len, rsamples, Uart.parityBits, TRUE);
                        if (respdata != NULL) {
-                               LogTrace(respdata,respsize, 0, SwapBits(GetParity(respdata,respsize),respsize), FALSE);
+                               LogTrace(respdata,respsize, rsamples, SwapBits(GetParity(respdata,respsize),respsize), FALSE);
+                       }
+                       if(traceLen > TRACE_SIZE) {
+                               DbpString("Trace full");
+                               break;
                        }
                }
-
                memset(receivedCmd, 0x44, RECV_CMD_SIZE);
        }
 
@@ -1345,7 +1385,7 @@ void ReaderTransmitIClass(uint8_t* frame, int len)
        LED_A_ON();
 
   // Store reader command in buffer
-  if (tracing) LogTrace(frame,len,0,par,TRUE);
+  if (tracing) LogTrace(frame,len,rsamples,par,TRUE);
 }
 
 //-----------------------------------------------------------------------------
@@ -1403,7 +1443,8 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer)
 {
   int samples = 0;
   if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE;
-  if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE);
+  rsamples += samples;
+  if (tracing) LogTrace(receivedAnswer,Demod.len,rsamples,Demod.parityBits,FALSE);
   if(samples == 0) return FALSE;
   return Demod.len;
 }
@@ -1412,12 +1453,12 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer)
 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 select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
        uint8_t* resp = (((uint8_t *)BigBuf) + 3560);   // was 3560 - tied to other size changes
 
        // Reset trace buffer
-       memset(trace, 0x44, RECV_CMD_OFFSET);
+       memset(trace, 0x44, RECV_CMD_OFFSET);
        traceLen = 0;
 
        // Setup SSC
@@ -1438,74 +1479,37 @@ void ReaderIClass(uint8_t arg0) {
        LED_A_ON();
 
        for(;;) {
-               if(traceLen > TRACE_SIZE || BUTTON_PRESS()) break;
+       
+               if(traceLen > TRACE_SIZE) {
+                       DbpString("Trace full");
+                       break;
+               }
+               
+               if (BUTTON_PRESS()) break;
 
                // Send act_all
                ReaderTransmitIClass(act_all, 1);
                // Card present?
                if(ReaderReceiveIClass(resp)) {
                        ReaderTransmitIClass(identify, 1);
-                       if(ReaderReceiveIClass(resp)) {
-                               //ReaderTransmitIClass(select, sizeof(select));
+                       if(ReaderReceiveIClass(resp) == 10) {
+                               // Select card          
+                               memcpy(&select[1],resp,8);
+                               ReaderTransmitIClass(select, sizeof(select));
+
+                               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, whats next... ;-)
                        }
                }
                WDT_HIT();
        }
        
        LED_A_OFF();
-
-/*     if(resp_data)
-               memcpy(resp_data->atqa, resp, 2);
-       
-       // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
-       // which case we need to make a cascade 2 request and select - this is a long UID
-       // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
-       for(; sak & 0x04; cascade_level++)
-       {
-               // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
-               sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
-
-               // SELECT_ALL
-               ReaderTransmit(sel_all,sizeof(sel_all));
-               if (!ReaderReceive(resp)) return 0;
-               if(uid_ptr) memcpy(uid_ptr + cascade_level*4, resp, 4);
-               
-               // calculate crypto UID
-               if(cuid_ptr) *cuid_ptr = bytes_to_num(resp, 4);
-
-               // Construct SELECT UID command
-               memcpy(sel_uid+2,resp,5);
-               AppendCrc14443a(sel_uid,7);
-               ReaderTransmit(sel_uid,sizeof(sel_uid));
-
-               // Receive the SAK
-               if (!ReaderReceive(resp)) return 0;
-               sak = resp[0];
-       }
-       if(resp_data) {
-               resp_data->sak = sak;
-               resp_data->ats_len = 0;
-       }
-       //--  this byte not UID, it CT.  http://www.nxp.com/documents/application_note/AN10927.pdf  page 3
-       if (uid_ptr[0] == 0x88) {  
-               memcpy(uid_ptr, uid_ptr + 1, 7);
-               uid_ptr[7] = 0;
-       }
-
-       if( (sak & 0x20) == 0)
-               return 2; // non iso14443a compliant tag
-
-       // Request for answer to select
-       if(resp_data) {  // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!!
-               AppendCrc14443a(rats, 2);
-               ReaderTransmit(rats, sizeof(rats));
-               
-               if (!(len = ReaderReceive(resp))) return 0;
-               
-               memcpy(resp_data->ats, resp, sizeof(resp_data->ats));
-               resp_data->ats_len = len;
-       }
-*/     
 }
 
 
Impressum, Datenschutz