]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
ADD: @marshmellow42's decrypt crypto-1 method,
authoriceman1001 <iceman@iuse.se>
Sun, 11 Oct 2015 07:07:29 +0000 (09:07 +0200)
committericeman1001 <iceman@iuse.se>
Sun, 11 Oct 2015 07:07:29 +0000 (09:07 +0200)
ADD:  @piwi's latest commit to PM3 Master, aiming at the WDR in "hf mf mifare".

.gitignore
armsrc/iso14443a.c
client/cmdhfmf.c
client/mifarehost.c
client/scripts/mifare_autopwn.lua
client/util.c

index ebfb5d96ef19e0ed1fe5979d40b6527877d2bf52..712edd4638fccc04fc23dff7bbc7a7b00d28599c 100644 (file)
@@ -34,4 +34,5 @@ fpga/*
 !fpga/go.bat
 !fpga/sim.tcl
 
-
+client/*
+.history
index 71f000d00901c9c62b2c4aa28852b365d37c4b31..492e2d6dc13598db95d213f76fa59aa5f5864047 100644 (file)
@@ -2249,9 +2249,10 @@ void ReaderMifare(bool first_try)
 
    #define PRNG_SEQUENCE_LENGTH  (1 << 16);
        static uint32_t sync_time = 0;
-       static uint32_t sync_cycles = 0;
+       static int32_t sync_cycles = 0;
        int catch_up_cycles = 0;
        int last_catch_up = 0;
+       uint16_t elapsed_prng_sequences;
        uint16_t consecutive_resyncs = 0;
        int isOK = 0;
 
@@ -2260,7 +2261,6 @@ void ReaderMifare(bool first_try)
                sync_time = GetCountSspClk() & 0xfffffff8;
                sync_cycles = PRNG_SEQUENCE_LENGTH; //65536;    //0x10000                       // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
                nt_attacked = 0;
-               nt = 0;
                par[0] = 0;
        }
        else {
@@ -2275,12 +2275,17 @@ void ReaderMifare(bool first_try)
        LED_C_OFF();
        
 
-       #define MAX_UNEXPECTED_RANDOM   5               // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up.
-       #define MAX_SYNC_TRIES                  16
+       #define MAX_UNEXPECTED_RANDOM   4               // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up.
+       #define MAX_SYNC_TRIES                  32
+       #define NUM_DEBUG_INFOS                 8               // per strategy
+       #define MAX_STRATEGY                    3
        uint16_t unexpected_random = 0;
        uint16_t sync_tries = 0;
        int16_t debug_info_nr = -1;
-       uint32_t debug_info[MAX_SYNC_TRIES];
+       uint16_t strategy = 0;
+       int32_t debug_info[MAX_STRATEGY][NUM_DEBUG_INFOS];
+       uint32_t select_time;
+       uint32_t halt_time;
   
        for(uint16_t i = 0; TRUE; i++) {
                
@@ -2293,24 +2298,59 @@ void ReaderMifare(bool first_try)
                        break;
                }
                
+               if (strategy == 2) {
+                       // test with additional hlt command
+                       halt_time = 0;
+                       int len = mifare_sendcmd_short(NULL, false, 0x50, 0x00, receivedAnswer, receivedAnswerPar, &halt_time);
+                       if (len && MF_DBGLEVEL >= 3) {
+                               Dbprintf("Unexpected response of %d bytes to hlt command (additional debugging).", len);
+                       }
+               }
+
+               if (strategy == 3) {
+                       // test with FPGA power off/on
+                       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+                       SpinDelay(200);
+                       iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
+                       SpinDelay(100);
+               }
+               
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
                        if (MF_DBGLEVEL >= 1)   Dbprintf("Mifare: Can't select card");
                        continue;
                }
+               select_time = GetCountSspClk();
 
+               elapsed_prng_sequences = 1;
                if (debug_info_nr == -1) {
                        sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
                        catch_up_cycles = 0;
 
                        // if we missed the sync time already, advance to the next nonce repeat
                        while(GetCountSspClk() > sync_time) {
+                               elapsed_prng_sequences++;
                                sync_time = (sync_time & 0xfffffff8) + sync_cycles;
                        }
 
                        // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) 
                        ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
                } else {
-                       ReaderTransmit(mf_auth, sizeof(mf_auth), NULL);
+                       // collect some information on tag nonces for debugging:
+                       #define DEBUG_FIXED_SYNC_CYCLES PRNG_SEQUENCE_LENGTH
+                       if (strategy == 0) {
+                               // nonce distances at fixed time after card select:
+                               sync_time = select_time + DEBUG_FIXED_SYNC_CYCLES;
+                       } else if (strategy == 1) {
+                               // nonce distances at fixed time between authentications:
+                               sync_time = sync_time + DEBUG_FIXED_SYNC_CYCLES;
+                       } else if (strategy == 2) {
+                               // nonce distances at fixed time after halt:
+                               sync_time = halt_time + DEBUG_FIXED_SYNC_CYCLES;
+                       } else {
+                               // nonce_distances at fixed time after power on
+                               sync_time = DEBUG_FIXED_SYNC_CYCLES;
+                       }
+                       ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
                }                       
 
                // Receive the (4 Byte) "random" nonce
@@ -2332,7 +2372,7 @@ void ReaderMifare(bool first_try)
                        } else {
                                if (nt_distance == -99999) { // invalid nonce received
                                        unexpected_random++;
-                                       if (!nt_attacked && unexpected_random > MAX_UNEXPECTED_RANDOM) {
+                                       if (unexpected_random > MAX_UNEXPECTED_RANDOM) {
                                                isOK = -3;              // Card has an unpredictable PRNG. Give up      
                                                break;
                                        } else {
@@ -2340,20 +2380,25 @@ void ReaderMifare(bool first_try)
                                        }
                                }
                                if (++sync_tries > MAX_SYNC_TRIES) {
-                                       if (sync_tries > 2 * MAX_SYNC_TRIES) {
+                                       if (strategy > MAX_STRATEGY || MF_DBGLEVEL < 3) {
                                                isOK = -4;                      // Card's PRNG runs at an unexpected frequency or resets unexpectedly
                                                break;
                                        } else {                                // continue for a while, just to collect some debug info
-                                               debug_info[++debug_info_nr] = nt_distance;
+                                               debug_info[strategy][debug_info_nr] = nt_distance;
+                                               debug_info_nr++;
+                                               if (debug_info_nr == NUM_DEBUG_INFOS) {
+                                                       strategy++;
+                                                       debug_info_nr = 0;
+                                               }
                                                continue;
                                        }
                                }
-                               sync_cycles = (sync_cycles - nt_distance);
+                               sync_cycles = (sync_cycles - nt_distance/elapsed_prng_sequences);
                                if (sync_cycles <= 0) {
                                        sync_cycles += PRNG_SEQUENCE_LENGTH;
                                }
                                if (MF_DBGLEVEL >= 3) {
-                                       Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
+                                       Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles);
                                }
                                continue;
                        }
@@ -2365,6 +2410,7 @@ void ReaderMifare(bool first_try)
                                catch_up_cycles = 0;
                                continue;
                        }
+                       catch_up_cycles /= elapsed_prng_sequences;
                        if (catch_up_cycles == last_catch_up) {
                                consecutive_resyncs++;
                        }
@@ -2378,6 +2424,9 @@ void ReaderMifare(bool first_try)
                        else {  
                                sync_cycles = sync_cycles + catch_up_cycles;
                                if (MF_DBGLEVEL >= 3) Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, -catch_up_cycles, sync_cycles);
+                               last_catch_up = 0;
+                               catch_up_cycles = 0;
+                               consecutive_resyncs = 0;
                        }
                        continue;
                }
@@ -2385,12 +2434,10 @@ void ReaderMifare(bool first_try)
                consecutive_resyncs = 0;
                
                // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
-               if (ReaderReceive(receivedAnswer, receivedAnswerPar))
-               {
+               if (ReaderReceive(receivedAnswer, receivedAnswerPar)) {
                        catch_up_cycles = 8;    // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer
        
-                       if (nt_diff == 0)
-                       {
+                       if (nt_diff == 0) {
                                par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change
                        }
 
@@ -2428,8 +2475,10 @@ void ReaderMifare(bool first_try)
        
        if (isOK == -4) {
                if (MF_DBGLEVEL >= 3) {
-                       for(uint16_t i = 0; i < MAX_SYNC_TRIES; i++) {
-                               Dbprintf("collected debug info[%d] = %d\n", i, debug_info[i]);
+                       for (uint16_t i = 0; i <= MAX_STRATEGY; i++) {
+                               for(uint16_t j = 0; j < NUM_DEBUG_INFOS; j++) {
+                                       Dbprintf("collected debug info[%d][%d] = %d", i, j, debug_info[i][j]);
+                               }
                        }
                }
        }
index ab7d913e1fdb39e3560d0277d9f797451cbc2c27..2b3f77ca0ad76eb6e378fe3173e9b12908d1e811 100644 (file)
@@ -59,7 +59,8 @@ start:
                                case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;\r
                                case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;\r
                                case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break;\r
-                               case -4 : PrintAndLog("The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). This needs to be fixed.\n"); break;\r
+                               case -4 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown");\r
+                                                       PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break;\r
                                default: ;\r
                        }\r
                        break;\r
@@ -1983,9 +1984,21 @@ int CmdHF14AMfSniff(const char *Cmd){
 //needs nt, ar, at, Data to decrypt\r
 int CmdDecryptTraceCmds(const char *Cmd){\r
        uint8_t data[50];\r
+       \r
+       uint32_t nt     = param_get32ex(Cmd,0,0,16);\r
+       uint32_t ar_enc = param_get32ex(Cmd,1,0,16);\r
+       uint32_t at_enc = param_get32ex(Cmd,2,0,16);\r
+\r
        int len = 0;\r
-       param_gethex_ex(Cmd,3,data,&len);\r
-       return tryDecryptWord(param_get32ex(Cmd,0,0,16),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),data,len/2);\r
+       param_gethex_ex(Cmd, 3, data, &len);\r
+       \r
+       len /= 2;       \r
+       int limit = sizeof(data) / 2;\r
+       \r
+       if ( len >= limit )\r
+               len = limit;\r
+       \r
+       return tryDecryptWord( nt, ar_enc, at_enc, data, len);\r
 }\r
 \r
 static command_t CommandTable[] =\r
index 830b61cdff97fdf15a03923e877656b12dcfcc00..dc3b988ae8cddc9367fc3b09ace1a0e454bc6cfa 100644 (file)
@@ -634,19 +634,25 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
 int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){\r
        /*\r
        uint32_t nt;      // tag challenge\r
+       uint32_t nr_enc;  // encrypted reader challenge\r
        uint32_t ar_enc;  // encrypted reader response\r
        uint32_t at_enc;  // encrypted tag response\r
        */\r
-       if (traceCrypto1) {\r
-               crypto1_destroy(traceCrypto1);\r
-       }\r
+\r
+       struct Crypto1State *pcs = NULL;\r
+       \r
        ks2 = ar_enc ^ prng_successor(nt, 64);\r
        ks3 = at_enc ^ prng_successor(nt, 96);\r
-       traceCrypto1 = lfsr_recovery64(ks2, ks3);\r
-\r
-       mf_crypto1_decrypt(traceCrypto1, data, len, 0);\r
-\r
+       \r
+       PrintAndLog("Decrypting data with:");\r
+       PrintAndLog("      nt: %08x",nt);\r
+       PrintAndLog("  ar_enc: %08x",ar_enc);\r
+       PrintAndLog("  at_enc: %08x",at_enc);\r
+       PrintAndLog("\nEncrypted data: [%s]", sprint_hex(data,len) );\r
+\r
+       pcs = lfsr_recovery64(ks2, ks3);\r
+       mf_crypto1_decrypt(pcs, data, len, FALSE);\r
        PrintAndLog("Decrypted data: [%s]", sprint_hex(data,len) );\r
-       crypto1_destroy(traceCrypto1);\r
+       crypto1_destroy(pcs);\r
        return 0;\r
 }\r
index 77f36ae453550e5d4542df8f405bcf58eefe58a6..ce6db3c00767091c2ab5cd3a61e7d643bcea8d5a 100644 (file)
@@ -113,7 +113,7 @@ function mfcrack_inner()
                        elseif isOK == 0xFFFFFFFD then
                                return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
                        elseif isOK == 0xFFFFFFFC then
-                               return nil, "The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
+                               return nil, "The card's random number generator behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
                        elseif isOK ~= 1 then 
                                return nil, "Error occurred" 
                        end
index 4a3b747607102475bd1a9e58bb4bbf9f600745bd..79744d1eb42ce807600a4c3c7217b969223f1347 100644 (file)
@@ -20,7 +20,6 @@ int ukbhit(void)
   int error;
   static struct termios Otty, Ntty;
 
-
   tcgetattr( 0, &Otty);
   Ntty = Otty;
 
@@ -347,7 +346,7 @@ int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt)
                return 1;
 
        for(i = 0; i < *hexcnt; i += 2) {
-               if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) )   return 1;
+               if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) ) return 1;
                
                sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
                data[i / 2] = temp & 0xff;
Impressum, Datenschutz