]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhfmfhard.c
FIX: 'hf mf mifare' - special zero parity attack vector now works. Thanks to the...
[proxmark3-svn] / client / cmdhfmfhard.c
index cb234e03e89733aa6decefd44c602fa71da86c7f..fb576441bc5271b8ffa093915a684fcab7ac7e37 100644 (file)
@@ -19,6 +19,7 @@
 #define GOOD_BYTES_REQUIRED    13              // default 28, could be smaller == faster
 #define MIN_NONCES_REQUIRED    4000            // 4000-5000 could be good
 #define NONCES_TRIGGER         2500            // every 2500 nonces check if we can crack the key
+#define CRACKING_THRESHOLD     39.00f          // as 2^39
 
 #define END_OF_LIST_MARKER             0xFFFFFFFF
 
@@ -115,7 +116,6 @@ static statelist_t *candidates = NULL;
 
 bool thread_check_started = false;
 bool thread_check_done = false;
-bool cracking = false;
 bool field_off = false;
 
 pthread_t thread_check;
@@ -261,7 +261,10 @@ static double p_hypergeometric(uint16_t N, uint16_t K, uint16_t n, uint16_t k)
                for (int16_t i = N; i >= N-n+1; i--) {
                        log_result -= log(i);
                }
-               return exp(log_result);
+               if ( log_result > 0 )
+                       return exp(log_result);
+               else 
+                       return 0.0;
        } else {
                if (n-k == N-K) {       // special case. The published recursion below would fail with a divide by zero exception
                        double log_result = 0.0;
@@ -762,7 +765,6 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_
        UsbCommand resp;
 
        field_off = false;
-       cracking = false;
        thread_check_started = false;
        thread_check_done = false;
 
@@ -771,7 +773,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_
        clearCommandBuffer();
 
        do {
-               if (cracking) {
+               if (thread_check_started && !thread_check_done) {
                        sleep(3);
                        continue;
                }
@@ -1313,7 +1315,7 @@ static bool generate_candidates(uint16_t sum_a0, uint16_t sum_a8)
 
        if (maximum_states == 0) return false; // prevent keyspace reduction error (2^-inf)
 
-       printf("Number of possible keys with Sum(a0) = %d: %"PRIu64" (2^%1.1f)\n", sum_a0, maximum_states, log(maximum_states)/log(2.0));
+       printf("Number of possible keys with Sum(a0) = %d: %"PRIu64" (2^%1.1f)\n", sum_a0, maximum_states, log(maximum_states)/log(2));
        
        init_statelist_cache();
        
@@ -1330,9 +1332,9 @@ static bool generate_candidates(uint16_t sum_a0, uint16_t sum_a8)
                                                        // and eliminate the need to calculate the other part
                                                        if (MIN(partial_statelist[p].len[ODD_STATE], partial_statelist[r].len[ODD_STATE]) 
                                                                        < MIN(partial_statelist[q].len[EVEN_STATE], partial_statelist[s].len[EVEN_STATE])) { 
-                                                       add_matching_states(current_candidates, p, r, ODD_STATE);
+                                                               add_matching_states(current_candidates, p, r, ODD_STATE);
                                                                if(current_candidates->len[ODD_STATE]) {
-                                                       add_matching_states(current_candidates, q, s, EVEN_STATE);
+                                                                       add_matching_states(current_candidates, q, s, EVEN_STATE);
                                                                } else {
                                                                        current_candidates->len[EVEN_STATE] = 0;
                                                                        uint32_t *p = current_candidates->states[EVEN_STATE] = malloc(sizeof(uint32_t));
@@ -1364,7 +1366,7 @@ static bool generate_candidates(uint16_t sum_a0, uint16_t sum_a8)
 
        if (maximum_states == 0) return false; // prevent keyspace reduction error (2^-inf)
 
-       float kcalc = log(maximum_states)/log(2.0);
+       float kcalc = log(maximum_states)/log(2);
        printf("Number of remaining possible keys: %"PRIu64" (2^%1.1f)\n", maximum_states, kcalc);
        if (write_stats) {
                if (maximum_states != 0) {
@@ -1373,7 +1375,7 @@ static bool generate_candidates(uint16_t sum_a0, uint16_t sum_a8)
                        fprintf(fstats, "%1.1f;", 0.0);
                }
        }
-       if (kcalc < 39.00f) return true;
+       if (kcalc < CRACKING_THRESHOLD) return true;
 
        return false;
 }
@@ -1650,14 +1652,12 @@ static void* check_thread()
        num_good_first_bytes = estimate_second_byte_sum();
 
        clock_t time1 = clock();
-       cracking = generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].Sum8_guess);
+       bool cracking = generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].Sum8_guess);
        time1 = clock() - time1;
-       if ( time1 > 0 ) PrintAndLog("Time for generating key candidates list: %1.0f seconds", ((float)time1)/CLOCKS_PER_SEC);
-       if (known_target_key != -1) brute_force();
+       if (time1 > 0) PrintAndLog("Time for generating key candidates list: %1.0f seconds", ((float)time1)/CLOCKS_PER_SEC);
 
-       if (cracking) {
+       if (cracking || known_target_key != -1) {
                field_off = brute_force(); // switch off field with next SendCommand and then finish
-               cracking = false;
        }
 
        thread_check_done = true;
@@ -1706,7 +1706,7 @@ static bool brute_force(void)
                crypto1_bs_init();
 
                PrintAndLog("Using %u-bit bitslices", MAX_BITSLICES);
-               PrintAndLog("Bitslicing best_first_byte^uid[3] (rollback byte): %02x...", best_first_bytes[0]^(cuid>>24));
+               PrintAndLog("Bitslicing best_first_byte^uid[3] (rollback byte): %02...", best_first_bytes[0]^(cuid>>24));
                // convert to 32 bit little-endian
                crypto1_bs_bitslice_value32((best_first_bytes[0]<<24)^cuid, bitsliced_rollback_byte, 8);
 
@@ -1747,14 +1747,14 @@ static bool brute_force(void)
                }
 
                time(&end);
-               double elapsed_time = difftime(end, start);
+               unsigned long  elapsed_time = difftime(end, start);
 
                if (keys_found && TestIfKeyExists(foundkey)) {
-                       PrintAndLog("Success! Tested %"PRIu32" states, found %u keys after %.f seconds", total_states_tested, keys_found, elapsed_time);
+                       PrintAndLog("Success! Tested %"PRIu32" states, found %u keys after %u seconds", total_states_tested, keys_found, elapsed_time);
                        PrintAndLog("\nFound key: %012"PRIx64"\n", foundkey);
                        ret = true;
                } else {
-                       PrintAndLog("Fail! Tested %"PRIu32" states, in %.f seconds", total_states_tested, elapsed_time);
+                       PrintAndLog("Fail! Tested %"PRIu32" states, in %u seconds", total_states_tested, elapsed_time);
                }
 
                // reset this counter for the next call
@@ -1805,13 +1805,23 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
                fstats = NULL;
        } else {
                init_nonce_memory();
-               if (nonce_file_read) {          // use pre-acquired data from file nonces.bin
+               if (nonce_file_read) { // use pre-acquired data from file nonces.bin
                        if (read_nonce_file() != 0) {
                                return 3;
                        }
                        Check_for_FilterFlipProperties();
                        num_good_first_bytes = MIN(estimate_second_byte_sum(), GOOD_BYTES_REQUIRED);
-               } else {                                        // acquire nonces.
+                       PrintAndLog("Number of first bytes with confidence > %2.1f%%: %d", CONFIDENCE_THRESHOLD*100.0, num_good_first_bytes);
+
+                       clock_t time1 = clock();
+                       bool cracking = generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].Sum8_guess);
+                       time1 = clock() - time1;
+                       if (time1 > 0)
+                               PrintAndLog("Time for generating key candidates list: %1.0f seconds", ((float)time1)/CLOCKS_PER_SEC);
+
+                       if (cracking)
+                               brute_force();
+               } else { // acquire nonces.
                        uint16_t is_OK = acquire_nonces(blockNo, keyType, key, trgBlockNo, trgKeyType, nonce_file_write, slow);
                        if (is_OK != 0) {
                                return is_OK;
@@ -1834,16 +1844,6 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
                        // best_first_bytes[8],
                        // best_first_bytes[9]  );
 
-               //PrintAndLog("Number of first bytes with confidence > %2.1f%%: %d", CONFIDENCE_THRESHOLD*100.0, num_good_first_bytes);
-
-               //clock_t time1 = clock();
-               //generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].Sum8_guess);
-               //time1 = clock() - time1;
-               //if ( time1 > 0 )
-                       //PrintAndLog("Time for generating key candidates list: %1.0f seconds", ((float)time1)/CLOCKS_PER_SEC);
-
-               //brute_force();
-
                free_nonces_memory();
                free_statelist_cache();
                free_candidates_memory(candidates);
Impressum, Datenschutz