]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Finishing touches on new mifare classic hack rework
authormartin.holst@gmail.com <martin.holst@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Wed, 26 Jun 2013 20:44:44 +0000 (20:44 +0000)
committermartin.holst@gmail.com <martin.holst@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Wed, 26 Jun 2013 20:44:44 +0000 (20:44 +0000)
armsrc/appmain.c
armsrc/apps.h
armsrc/iso14443a.c

index 7fc399a6868c76749092b53d7af483cd5911d5ce..cecf4d35e1156774fa02b26d0c997cdd08f986b8 100644 (file)
@@ -772,7 +772,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        break;
                        
                case CMD_READER_MIFARE:
-                       ReaderMifare(c->arg[0]);
+            ReaderMifare(c);
                        break;
                case CMD_MIFARE_READBL:
                        MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
index 5ebe318fa849ab8abd947cc2ea52d24973977b02..2f003cc49ab0600df0761b1951b5ad19a54d78c3 100644 (file)
@@ -156,7 +156,7 @@ void RAMFUNC SniffMifare(uint8_t param);
 void EPA_PACE_Collect_Nonce(UsbCommand * c);
 
 // mifarecmd.h
-void ReaderMifare(uint32_t parameter);
+void ReaderMifare(UsbCommand *c);
 void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
 void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
 void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
index 0a5512b48ea6bd46c1642ec04f0c8630c00cb389..111d713989caa1abc4d50ffa55513d95f83b6cf0 100644 (file)
@@ -1831,8 +1831,7 @@ int TuneMifare(int time)
 {
     // Mifare AUTH
     uint8_t mf_auth[]    = { 0x60,0x00,0xf5,0x7b };
-    //uint8_t mf_nr_ar[]   = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
-    uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);      // was 3560 - tied to other size changes
+    uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
 
     iso14443a_setup();
     int TIME1=time;
@@ -1840,7 +1839,7 @@ int TuneMifare(int time)
     uint8_t uid[8];
     uint32_t cuid;
     byte_t nt[4];
-    Dbprintf("Tuning... testing a delay of %d ms",time);
+    Dbprintf("Tuning... testing a delay of %d ms (press button to skip)",time);
 
 
     mftest nt_values[TEST_LENGTH];
@@ -1906,7 +1905,6 @@ int TuneMifare(int time)
 #define STATE_SIZE 100
 typedef struct AttackState{
     byte_t nt[4];
-    //byte_t nt_attacked[4];
     byte_t par_list[8];
     byte_t ks_list[8];
     byte_t par;
@@ -1987,40 +1985,84 @@ void reportResults(uint8_t uid[8],AttackState *pState, int isOK)
     if (MF_DBGLEVEL >= 1)      DbpString("COMMAND mifare FINISHED");
 }
 
+void ReaderMifareBegin(uint32_t offset_time, uint32_t powerdown_time);
 
-
-
-void ReaderMifare(uint32_t parameter)
+/**
+ * @brief New implementation of ReaderMifare, the classic mifare attack.
+ *  This implementation is backwards-compatible, but has some added parameters.
+ * @param c the usbcommand in complete
+ *  c->arg[0] - nt_noattack (deprecated)
+ *  c->arg[1] - offset_time us (0 => random)
+ *  c->arg[2] - powerdown_time ms (0=> tuning)
+ *
+ */
+void ReaderMifare(UsbCommand *c)
 {
-    /**
-     *First, we tune it.
-     **/
-    int entropy = 100;
-    int time = 25;
-    entropy = TuneMifare(time);
+    /*
+     * The 'no-attack' is not used anymore, with the introduction of
+     * state tables. Instead, we use an offset which is random. This means that we
+     * should not get stuck on a 'bad' nonce, so no-attack is not needed.
+     * Anyway, arg[0] is reserved for backwards compatibility
+    uint32_t nt_noattack_uint = c->arg[0];
+    byte_t nt_noattack[4];
+    num_to_bytes(parameter, 4, nt_noattack_uint);
 
-    while(entropy > 50 && time < 2000){
-        //Increase timeout, but never more than 500ms at a time
-        time = MIN(time*2, time+500);
-        entropy = TuneMifare(time);
+     */
+    /*
+     *IF, for some reason, you want to attack a specific nonce or whatever,
+     *you can specify the offset time yourself, in which case it won't be random.
+     *
+     * The offset time is microseconds, MICROSECONDS, not ms.
+     */
+    uint32_t offset_time = c->arg[1];
+    if(offset_time == 0)
+    {
+        //[Martin:]I would like to have used rand(), but linking problems prevented it
+        //offset_time = rand() % 4000;
+        //So instead, I found this nifty thingy, which seems to fit the bill
+        offset_time = GetTickCount() % 2000;
     }
+    /*
+     * There is an implementation of tuning. Tuning will try to determine
+     * a good power-down time, which is different for different cards.
+     * If a value is specified from the packet, we won't do any tuning.
+     * A value of zero will initialize a tuning.
+     * The power-down time is milliseconds, that MILLI-seconds .
+     */
+    uint32_t powerdown_time = c->arg[2];
+    if(powerdown_time == 0)
+    {
+        //Tuning required
+        int entropy = 100;
+        int time = 25;
+        entropy = TuneMifare(time);
 
-    if(entropy > 50){
-        Dbprintf("OBS! This card has high entropy (%d) and slow power-down. This may take a while", entropy);
+        while(entropy > 50 && time < 2000){
+            //Increase timeout, but never more than 500ms at a time
+            time = MIN(time*2, time+500);
+            entropy = TuneMifare(time);
+        }
+        if(entropy > 50){
+            Dbprintf("OBS! This card has high entropy (%d) and slow power-down. This may take a while", entropy);
+        }
+        powerdown_time = time;
     }
-    Dbprintf("Using power-down-time of %d ms, entropy %d", time, entropy);
+    //The actual attack
+    ReaderMifareBegin(offset_time, powerdown_time);
+}
+void ReaderMifareBegin(uint32_t offset_time, uint32_t powerdown_time)
+{
+    Dbprintf("Using power-down-time of %d ms, offset time %d us", powerdown_time, offset_time);
 
     /**
      *Allocate our state-table and initialize with zeroes
      **/
 
-
     AttackState states[STATE_SIZE] ;
-
-
-    Dbprintf("Memory allocated ok! (%d bytes)",STATE_SIZE*sizeof(AttackState) );
+    //Dbprintf("Memory allocated ok! (%d bytes)",STATE_SIZE*sizeof(AttackState) );
     memset(states, 0, STATE_SIZE*sizeof(AttackState));
-       // Mifare AUTH
+
+    // Mifare AUTH
        uint8_t mf_auth[]    = { 0x60,0x00,0xf5,0x7b };
        uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);   // was 3560 - tied to other size changes
 
@@ -2028,7 +2070,6 @@ void ReaderMifare(uint32_t parameter)
        tracing = false;
 
        iso14443a_setup();
-
        LED_A_ON();
        LED_B_OFF();
        LED_C_OFF();
@@ -2037,8 +2078,6 @@ void ReaderMifare(uint32_t parameter)
        uint8_t uid[8];
        uint32_t cuid;
 
-    byte_t nt_noattack[4];
-    num_to_bytes(parameter, 4, nt_noattack);
     byte_t nt[4];
     int nts_attacked= 0;
     //Keeps track of progress (max value of nt_diff for our states)
@@ -2048,10 +2087,10 @@ void ReaderMifare(uint32_t parameter)
        {
                LED_C_OFF();
                FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-        SpinDelay(time);
+        SpinDelay(powerdown_time);
                FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
                LED_C_ON();
-               SpinDelay(2);
+        SpinDelayUs(offset_time);
 
                if(!iso14443a_select_card(uid, NULL, &cuid)) continue;
 
@@ -2096,9 +2135,6 @@ void ReaderMifare(uint32_t parameter)
                 high_entropy_warning_issued = 1;
             }
         }
-
-
-
         if(pState == NULL) continue;
 
         int result = continueAttack(pState, receivedAnswer);
@@ -2117,19 +2153,8 @@ void ReaderMifare(uint32_t parameter)
             //Dbprintf("Continue attack no answer, par is now %d", pState->par);
         }
         else if(result == 0){
-            //uint64_t par_list = bytes_to_num((uint8_t*)&pState->par_list, 8);
-            //uint64_t ks_list = bytes_to_num((uint8_t*)&pState->ks_list, 8);
-            //uint32_t xnt = bytes_to_num((uint8_t*)&pState->nt,4 );
-            //uint32_t xuid = (uint32_t)bytes_to_num((uint8_t*)&uid, 4);
-            //Dbprintf("\n#nuid(%08x) nt(%08x) par(%016x) ks(%016x)",xuid,xnt,par_list,ks_list);
-            //Dbprintf("\n./nonce2key %08x %08x %016x %016x\n",xuid,xnt,par_list,ks_list);
-            //Dbprintf("Finished");
             reportResults(uid,pState,1);
             return;
-            //memset(pState, 0, sizeof(AttackState));
-            //memcpy(pState->nt, nt, 4);
-            //Dbprintf("State reset for state %d!", i);
-            //return;
         }
     }
     reportResults(uid,NULL,0);
Impressum, Datenschutz