]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhfmf.c
Merge pull request #46 from micolous/fix-nonce
[proxmark3-svn] / client / cmdhfmf.c
index ec542eb3f00800865cdca8aaa1a60aeedb1bf910..99a91ced7a8418e95665ffdc6eae7dc218cffae7 100644 (file)
@@ -31,6 +31,7 @@ int usage_hf14_mf1ksim(void){
        PrintAndLog("      n    (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");\r
        PrintAndLog("      i    (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");\r
        PrintAndLog("      x    (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");\r
+       PrintAndLog("      e    (Optional) Fill simulator keys from what we crack");\r
        PrintAndLog("samples:");\r
        PrintAndLog("           hf mf sim u 0a0a0a0a");\r
        PrintAndLog("           hf mf sim u 11223344556677");\r
@@ -125,6 +126,21 @@ int usage_hf14_chk(void){
        PrintAndLog("      hf mf chk *1 ? d                        -- target all blocks, all keys, 1K, write to file");\r
        return 0;\r
 }\r
+int usage_hf14_keybrute(void){\r
+       PrintAndLog("J_Run's 2nd phase of multiple sector nested authentication key recovery");\r
+       PrintAndLog("You have a known 4 last bytes of a key recovered with mf_nonce_brute tool.");\r
+       PrintAndLog("First 2 bytes of key will be bruteforced");\r
+       PrintAndLog("");\r
+       PrintAndLog("Usage:  hf mf keybrute [h] <block number> <A|B> <key>");\r
+       PrintAndLog("options:");\r
+       PrintAndLog("      h               this help");\r
+       PrintAndLog("      <block number>  target block number");\r
+       PrintAndLog("      <A|B>           target key type");\r
+       PrintAndLog("      <key>           candidate key from mf_nonce_brute tool");\r
+       PrintAndLog("samples:");\r
+       PrintAndLog("           hf mf keybrute 1 A 000011223344");\r
+       return 0;\r
+}\r
 \r
 int CmdHF14AMifare(const char *Cmd) {\r
        uint32_t uid = 0;\r
@@ -198,9 +214,16 @@ start:
        }       \r
        printf("\n");\r
        \r
-       // par == 0\r
-       if (isOK == -1 && par_list == 0) {\r
-               if (!nonce2key_ex(uid, nt, nr, ks_list, &r_key) ){\r
+       // par == 0,  and -4\r
+       if (isOK == -4 && par_list == 0) {\r
+               // this special attack when parities is zero, uses checkkeys. Which now with block/keytype option also needs. \r
+               // but it uses 0|1 instead of 0x60|0x61...\r
+               if (nonce2key_ex(blockNo, keytype - 0x60 , uid, nt, nr, ks_list, &r_key) ){\r
+                       PrintAndLog("Key not found (lfsr_common_prefix list is null).");        \r
+                       PrintAndLog("Failing is expected to happen in 25%% of all cases. Trying again with a different reader nonce...");\r
+                       c.arg[0] = false;\r
+                       goto start;\r
+               } else {\r
                        PrintAndLog("Found valid key: %012"llx" \n", r_key);\r
                        goto END;\r
                }\r
@@ -217,6 +240,16 @@ start:
                c.arg[0] = false;\r
                goto start;\r
        } else {\r
+               \r
+               // nonce2key found a candidate key.  Lets verify it.\r
+               uint8_t keyblock[] = {0,0,0,0,0,0};\r
+               num_to_bytes(r_key, 6, keyblock);\r
+               uint64_t key64 = 0;\r
+               int res = mfCheckKeys(blockNo, keytype - 0x60 , false, 1, keyblock, &key64);\r
+               if ( res > 0 ) {\r
+                       PrintAndLog("Candidate Key found (%012"llx") - Test authentication failed. Starting over darkside attack", r_key);      \r
+                       goto start;\r
+               }\r
                PrintAndLog("Found valid key: %012"llx" \n", r_key);\r
        }\r
 END:\r
@@ -443,6 +476,7 @@ int CmdHF14AMfDump(const char *Cmd) {
                if ( bytes_read == 0) {\r
                        PrintAndLog("File reading error.");\r
                        fclose(fin);\r
+                       fin = NULL;\r
                        return 2;\r
                }\r
        }\r
@@ -453,12 +487,14 @@ int CmdHF14AMfDump(const char *Cmd) {
                if ( bytes_read == 0) {\r
                        PrintAndLog("File reading error.");\r
                        fclose(fin);\r
+                       fin = NULL;\r
                        return 2;\r
                }\r
        }\r
        \r
        fclose(fin);\r
-\r
+       fin = NULL;\r
+                       \r
        PrintAndLog("|-----------------------------------------|");\r
        PrintAndLog("|------ Reading sector access bits...-----|");\r
        PrintAndLog("|-----------------------------------------|");\r
@@ -564,6 +600,7 @@ int CmdHF14AMfDump(const char *Cmd) {
                uint16_t numblocks = FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1);\r
                fwrite(carddata, 1, 16*numblocks, fout);\r
                fclose(fout);\r
+               fout = NULL;            \r
                PrintAndLog("Dumped %d blocks (%d bytes) to file dumpdata.bin", numblocks, 16*numblocks);\r
        }\r
                \r
@@ -612,6 +649,7 @@ int CmdHF14AMfRestore(const char *Cmd) {
                if ( bytes_read == 0) {\r
                        PrintAndLog("File reading error (dumpkeys.bin).");\r
                        fclose(fkeys);\r
+                       fkeys = NULL;\r
                        return 2;\r
                }\r
        }\r
@@ -621,6 +659,7 @@ int CmdHF14AMfRestore(const char *Cmd) {
                if ( bytes_read == 0) {\r
                        PrintAndLog("File reading error (dumpkeys.bin).");\r
                        fclose(fkeys);\r
+                       fkeys = NULL;\r
                        return 2;\r
                }\r
        }\r
@@ -641,6 +680,7 @@ int CmdHF14AMfRestore(const char *Cmd) {
                        if ( bytes_read == 0) {\r
                                PrintAndLog("File reading error (dumpdata.bin).");\r
                                fclose(fdump);\r
+                               fdump = NULL;                           \r
                                return 2;\r
                        }\r
                                        \r
@@ -676,6 +716,7 @@ int CmdHF14AMfRestore(const char *Cmd) {
        }\r
        \r
        fclose(fdump);\r
+       fdump = NULL;   \r
        return 0;\r
 }\r
 \r
@@ -1018,7 +1059,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
                        slow ? "Yes" : "No",\r
                        tests);\r
 \r
-       int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key?trgkey:NULL, nonce_file_read, nonce_file_write, slow, tests);\r
+       int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests);\r
 \r
        if (isOK) {\r
                switch (isOK) {\r
@@ -1344,7 +1385,9 @@ void readerAttack(nonces_t data[], bool setEmulatorMem) {
        printf("enter reader attack\n");\r
        for (uint8_t i = 0; i < ATTACK_KEY_COUNT; ++i) {\r
                if (data[i].ar2 > 0) {\r
-                       \r
+\r
+                       // We can probably skip this, mfkey32v2 is more reliable.\r
+#ifdef HFMF_TRYMFK32\r
                        if (tryMfk32(data[i], &key)) {\r
                                PrintAndLog("Found Key%s for sector %02d: [%012"llx"]"\r
                                        , (data[i].keytype) ? "B" : "A"\r
@@ -1360,22 +1403,43 @@ void readerAttack(nonces_t data[], bool setEmulatorMem) {
                                        uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0};\r
                                        num_to_bytes( k_sector[i].Key[0], 6, memBlock);\r
                                        num_to_bytes( k_sector[i].Key[1], 6, memBlock+10);\r
-                                       mfEmlSetMem( memBlock, i*4 + 3, 1);\r
                                        PrintAndLog("Setting Emulator Memory Block %02d: [%s]"\r
-                                               , i*4 + 3\r
+                                               , ((data[i].sector)*4) + 3\r
                                                , sprint_hex( memBlock, sizeof(memBlock))\r
                                                );\r
+                                       mfEmlSetMem( memBlock, ((data[i].sector)*4) + 3, 1);\r
                                }\r
-                               break;\r
+                               continue;\r
                        }\r
+#endif\r
                        //moebius attack                        \r
-                       // if (tryMfk32_moebius(data[i+ATTACK_KEY_COUNT], &key)) {\r
-                               // PrintAndLog("M-Found Key%s for sector %02d: [%012"llx"]"\r
-                                       // ,(data[i+ATTACK_KEY_COUNT].keytype) ? "B" : "A"\r
-                                       // , data[i+ATTACK_KEY_COUNT].sector\r
-                                       // , key\r
-                               // );\r
-                       // }\r
+                       if (tryMfk32_moebius(data[i+ATTACK_KEY_COUNT], &key)) {\r
+                               uint8_t sectorNum = data[i+ATTACK_KEY_COUNT].sector;\r
+                               uint8_t keyType = data[i+ATTACK_KEY_COUNT].keytype;\r
+\r
+                               PrintAndLog("M-Found Key%s for sector %02d: [%012"llx"]"\r
+                                       , keyType ? "B" : "A"\r
+                                       , sectorNum\r
+                                       , key\r
+                               );\r
+\r
+                               k_sector[sectorNum].Key[keyType] = key;\r
+                               k_sector[sectorNum].foundKey[keyType] = TRUE;\r
+\r
+                               //set emulator memory for keys\r
+                               if (setEmulatorMem) {\r
+                                       uint8_t memBlock[16] = {0,0,0,0,0,0, 0xff, 0x0F, 0x80, 0x69, 0,0,0,0,0,0};\r
+                                       num_to_bytes( k_sector[sectorNum].Key[0], 6, memBlock);\r
+                                       num_to_bytes( k_sector[sectorNum].Key[1], 6, memBlock+10);\r
+                                       PrintAndLog("Setting Emulator Memory Block %02d: [%s]"\r
+                                               , (sectorNum*4) + 3\r
+                                               , sprint_hex( memBlock, sizeof(memBlock))\r
+                                               );\r
+                                       mfEmlSetMem( memBlock, (sectorNum*4) + 3, 1);\r
+                               }\r
+                               continue;\r
+                       }\r
+\r
                }\r
        }\r
 }\r
@@ -1466,6 +1530,7 @@ int CmdHF14AMf1kSim(const char *Cmd) {
                if (k_sector != NULL) {\r
                        printKeyTable(k_sectorsCount, k_sector );\r
                        free(k_sector);\r
+                       k_sector = NULL;\r
                }\r
        }\r
        return 0;\r
@@ -1639,6 +1704,43 @@ int CmdHF14AMfDbg(const char *Cmd) {
        return 0;\r
 }\r
 \r
+int CmdHF14AMfKeyBrute(const char *Cmd) {\r
+\r
+       uint8_t blockNo = 0, keytype = 0;\r
+       uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
+       uint64_t foundkey = 0;\r
+       \r
+       char cmdp = param_getchar(Cmd, 0);      \r
+       if ( cmdp == 'H' || cmdp == 'h') return usage_hf14_keybrute();\r
+       \r
+       // block number\r
+       blockNo = param_get8(Cmd, 0);    \r
+       \r
+       // keytype\r
+       cmdp = param_getchar(Cmd, 1);\r
+       if (cmdp == 'B' || cmdp == 'b') keytype = 1;\r
+       \r
+       // key\r
+       if (param_gethex(Cmd, 2, key, 12)) return usage_hf14_keybrute();\r
+       \r
+       clock_t t1 = clock();\r
+       time_t start, end;\r
+       time(&start);\r
+       \r
+       if (mfKeyBrute( blockNo, keytype, key, &foundkey))\r
+               PrintAndLog("Found valid key: %012"llx" \n", foundkey);\r
+       else\r
+               PrintAndLog("Key not found");\r
+       \r
+       t1 = clock() - t1;\r
+       time(&end);\r
+       unsigned long elapsed_time = difftime(end, start);      \r
+       if ( t1 > 0 )\r
+               PrintAndLog("\nTime in keybrute: %.0f ticks %u seconds\n", (float)t1, elapsed_time);\r
+       \r
+       return 0;       \r
+}\r
+\r
 void printKeyTable( uint8_t sectorscnt, sector *e_sector ){\r
        PrintAndLog("|---|----------------|---|----------------|---|");\r
        PrintAndLog("|sec|key A           |res|key B           |res|");\r
@@ -2379,10 +2481,11 @@ static command_t CommandTable[] = {
        {"dump",                CmdHF14AMfDump,                 0, "Dump MIFARE classic tag to binary file"},\r
        {"restore",             CmdHF14AMfRestore,              0, "Restore MIFARE classic binary file to BLANK tag"},\r
        {"wrbl",                CmdHF14AMfWrBl,                 0, "Write MIFARE classic block"},\r
-       {"chk",                 CmdHF14AMfChk,                  0, "Test block keys"},\r
-       {"mifare",              CmdHF14AMifare,                 0, "Read parity error messages."},\r
-       {"nested",              CmdHF14AMfNested,               0, "Test nested authentication"},\r
+       {"chk",                 CmdHF14AMfChk,                  0, "Check keys"},\r
+       {"mifare",              CmdHF14AMifare,                 0, "Darkside attack. read parity error messages."},\r
+       {"nested",              CmdHF14AMfNested,               0, "Nested attack. Test nested authentication"},\r
        {"hardnested",  CmdHF14AMfNestedHard,   0, "Nested attack for hardened Mifare cards"},\r
+       {"keybrute",    CmdHF14AMfKeyBrute,             0, "J_Run's 2nd phase of multiple sector nested authentication key recovery"},\r
        {"sniff",               CmdHF14AMfSniff,                0, "Sniff card-reader communication"},\r
        {"sim",                 CmdHF14AMf1kSim,                0, "Simulate MIFARE card"},\r
        {"eclr",                CmdHF14AMfEClear,               0, "Clear simulator memory block"},\r
Impressum, Datenschutz