From 6c76e2ed5b99da876572572fc1937fde16bfb22d Mon Sep 17 00:00:00 2001 From: Matthias Konrath Date: Wed, 28 Aug 2019 14:20:52 +0200 Subject: [PATCH 1/3] Restyled to the autopwn command output. --- client/cmdhfmf.c | 66 ++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 0b7727031..ff0324b34 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1733,8 +1733,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(WARNING, "No known key was supplied, key recovery might fail"); else { if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Using key for the nested / hardnested | sector:" - _RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), + PrintAndLogEx(INFO, "Using valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)", blockNo, keyType ? 'B' : 'A', sprint_hex(key, sizeof(key)) @@ -1745,7 +1744,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { e_sector[blockNo].foundKey[keyType] = 3; } else { know_target_key = false; - PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector:"_RED_("%3d") " key type:"_RED_("%c") " key: " _RED_("%s"), + PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector:"_RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), blockNo, keyType ? 'B' : 'A', sprint_hex(key, sizeof(key)) @@ -1759,11 +1758,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, key, &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num(key, 6); e_sector[i].foundKey[j] = 4; - PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), - i, - j ? 'B' : 'A', - sprint_hex(key, sizeof(key)) - ); // If the user supplied secctor / keytype was wrong --> just be nice and correct it ;) if (know_target_key == false) { @@ -1771,10 +1765,15 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { know_target_key = true; blockNo = i; keyType = j; - PrintAndLogEx(SUCCESS, "using key nested / hardnested attack: sector:" - _RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), - blockNo, - keyType ? 'B' : 'A', + PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)", + i, + j ? 'B' : 'A', + sprint_hex(key, sizeof(key)) + ); + } else { + PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), + i, + j ? 'B' : 'A', sprint_hex(key, sizeof(key)) ); } @@ -1807,7 +1806,7 @@ useDefaultKeys: } // Use the dictionary to find sector keys on the card - PrintAndLogEx(INFO, "Enter dictionary run..."); + PrintAndLogEx(INFO, _YELLOW_("======================= START DICTIONARY ATTACK =======================")); if (legacy_mfchk) { // Check all the sectors @@ -1862,17 +1861,15 @@ useDefaultKeys: lastChunk = false; } // end strategy } + PrintAndLogEx(INFO, _YELLOW_("======================= STOP DICTIONARY ATTACK =======================")); + // Analyse the dictionary attack for (int i = 0; i < sectors_cnt; i++) { for (int j = 0; j < 2; j++) { if (e_sector[i].foundKey[j] == 1) { num_to_bytes(e_sector[i].Key[j], 6, tmp_key); - PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), - i, - j ? 'B' : 'A', - sprint_hex(tmp_key, sizeof(tmp_key)) - ); + // Store valid credentials for the nested / hardnested attack if none exist if (know_target_key == false) { @@ -1880,11 +1877,16 @@ useDefaultKeys: know_target_key = true; blockNo = i; keyType = j; - PrintAndLogEx(SUCCESS, "Using key nested / hardnested attack: sector:" - _RED_("%3d") " key type:"_RED_("%c") " key: " _RED_("%s"), - blockNo, - keyType ? 'B' : 'A', - sprint_hex(key, sizeof(key)) + PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)", + i, + j ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) + ); + } else { + PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), + i, + j ? 'B' : 'A', + sprint_hex(tmp_key, sizeof(tmp_key)) ); } } @@ -1895,8 +1897,9 @@ useDefaultKeys: if (know_target_key == false) { // Check if the darkside attack can be used if (prng_type) { - PrintAndLogEx(INFO, "Enter darkside run..."); + PrintAndLogEx(INFO, _YELLOW_("======================= START DARKSIDE ATTACK =======================")); int isOK = mfDarkside(FirstBlockOfSector(blockNo), keyType, &key64); + PrintAndLogEx(INFO, _YELLOW_("======================= STOP DARKSIDE ATTACK =======================")); switch (isOK) { case -1 : PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); @@ -1932,6 +1935,11 @@ useDefaultKeys: // Store the keys e_sector[blockNo].Key[keyType] = bytes_to_num(key, 6); e_sector[blockNo].foundKey[keyType] = 2; + PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)", + blockNo, + keyType ? 'B' : 'A', + sprint_hex(key, sizeof(key)) + ); } else { noValidKeyFound: PrintAndLogEx(FAILED, "No usable key was found!"); @@ -1980,7 +1988,10 @@ noValidKeyFound: if (current_key_type_i == 1) { if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) { - PrintAndLogEx(INFO, "Reading B key: sector: %3d", current_sector_i); + PrintAndLogEx(INFO, "Reading B key: sector: %3d key type: %c key: ?? ?? ?? ?? ?? ??", + current_sector_i, + current_key_type_i ? 'B' : 'A' + ); uint8_t sectrail = (FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1); mf_readblock_t payload; @@ -2026,6 +2037,7 @@ skipReadBKey: if (prng_type && (! nested_failed)) { uint8_t retries = 0; tryNested: + PrintAndLogEx(INFO, _YELLOW_("======================= START NESTED ATTACK =======================")); PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c", current_sector_i, current_key_type_i ? 'B' : 'A'); @@ -2066,8 +2078,10 @@ tryNested: free(e_sector); return PM3_ESOFT; } + PrintAndLogEx(INFO, _YELLOW_("======================= STOP NESTED ATTACK =======================")); } else { tryHardnested: // If the nested attack fails then we try the hardnested attack + PrintAndLogEx(INFO, _YELLOW_("======================= START HARDNESTED ATTACK =======================")); PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c, Slow: %s", current_sector_i, current_key_type_i ? 'B' : 'A', @@ -2094,6 +2108,8 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack num_to_bytes(foundkey, 6, tmp_key); e_sector[current_sector_i].Key[current_key_type_i] = foundkey; e_sector[current_sector_i].foundKey[current_key_type_i] = 6; + + PrintAndLogEx(INFO, _YELLOW_("======================= STOP HARDNESTED ATTACK =======================")); } // Check if the key was found if (e_sector[current_sector_i].foundKey[current_key_type_i]) { From 2e29b361c540609976f6ad2f3d25e4ec14094937 Mon Sep 17 00:00:00 2001 From: Matthias Konrath Date: Wed, 28 Aug 2019 15:57:21 +0200 Subject: [PATCH 2/3] Restyled the autopwn command output according to @doegox --- client/cmdhfmf.c | 85 +++++++++++++++++++++++++++++++----------------- client/cmdhfmf.h | 1 + 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index ff0324b34..66c50758f 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1741,7 +1741,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Store the key for the nested / hardnested attack (if supplied by the user) e_sector[blockNo].Key[keyType] = bytes_to_num(key, 6); - e_sector[blockNo].foundKey[keyType] = 3; + e_sector[blockNo].foundKey[keyType] = 'U'; } else { know_target_key = false; PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector:"_RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), @@ -1757,7 +1757,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (e_sector[i].foundKey[j] == 0) { if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, key, &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num(key, 6); - e_sector[i].foundKey[j] = 4; + e_sector[i].foundKey[j] = 'U'; // If the user supplied secctor / keytype was wrong --> just be nice and correct it ;) if (know_target_key == false) { @@ -1819,7 +1819,7 @@ useDefaultKeys: fflush(stdout); if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, (keyBlock + (6 * k)), &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num((keyBlock + (6 * k)), 6); - e_sector[i].foundKey[j] = 1; + e_sector[i].foundKey[j] = 'D'; break; } } @@ -1868,6 +1868,7 @@ useDefaultKeys: for (int i = 0; i < sectors_cnt; i++) { for (int j = 0; j < 2; j++) { if (e_sector[i].foundKey[j] == 1) { + e_sector[i].foundKey[j] = 'D'; num_to_bytes(e_sector[i].Key[j], 6, tmp_key); @@ -1934,7 +1935,7 @@ useDefaultKeys: } // Store the keys e_sector[blockNo].Key[keyType] = bytes_to_num(key, 6); - e_sector[blockNo].foundKey[keyType] = 2; + e_sector[blockNo].foundKey[keyType] = 'S'; PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)", blockNo, keyType ? 'B' : 'A', @@ -1973,7 +1974,7 @@ noValidKeyFound: // Check if the key works if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num(tmp_key, 6); - e_sector[i].foundKey[j] = 4; + e_sector[i].foundKey[j] = 'R'; PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), i, j ? 'B' : 'A', @@ -1988,7 +1989,7 @@ noValidKeyFound: if (current_key_type_i == 1) { if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) { - PrintAndLogEx(INFO, "Reading B key: sector: %3d key type: %c key: ?? ?? ?? ?? ?? ??", + PrintAndLogEx(INFO, "Reading B key: sector: %3d key type: %c", current_sector_i, current_key_type_i ? 'B' : 'A' ); @@ -2010,16 +2011,8 @@ noValidKeyFound: uint8_t *data = resp.data.asBytes; key64 = bytes_to_num(data + 10, 6); - if (verbose){ - num_to_bytes(key64, 6, tmp_key); - PrintAndLogEx(INFO, "Discovered key: sector: %3d key type: %c key: " _YELLOW_("%s"), - current_sector_i, - current_key_type_i ? 'B' : 'A', - sprint_hex(tmp_key, sizeof(tmp_key)) - ); - } if (key64) { - e_sector[current_sector_i].foundKey[current_key_type_i] = 7; + e_sector[current_sector_i].foundKey[current_key_type_i] = 'A'; e_sector[current_sector_i].Key[current_key_type_i] = key64; num_to_bytes(key64, 6, tmp_key); PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), @@ -2027,6 +2020,11 @@ noValidKeyFound: current_key_type_i ? 'B' : 'A', sprint_hex(tmp_key, sizeof(tmp_key)) ); + } else { + PrintAndLogEx(WARNING, "Unknown B key: sector: %3d key type: %c (reading the B key was not possible, maybe due to insufficient access rights) ", + current_sector_i, + current_key_type_i ? 'B' : 'A' + ); } } } @@ -2036,8 +2034,9 @@ skipReadBKey: if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { if (prng_type && (! nested_failed)) { uint8_t retries = 0; -tryNested: PrintAndLogEx(INFO, _YELLOW_("======================= START NESTED ATTACK =======================")); + +tryNested: PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c", current_sector_i, current_key_type_i ? 'B' : 'A'); @@ -2071,7 +2070,7 @@ tryNested: case -5 : calibrate = false; e_sector[current_sector_i].Key[current_key_type_i] = bytes_to_num(tmp_key, 6); - e_sector[current_sector_i].foundKey[current_key_type_i] = 5; + e_sector[current_sector_i].foundKey[current_key_type_i] = 'N'; break; default : PrintAndLogEx(ERR, "unknown Error.\n"); @@ -2107,7 +2106,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack // Copy the found key to the tmp_key variale (for the following print statement, and the mfCheckKeys above) num_to_bytes(foundkey, 6, tmp_key); e_sector[current_sector_i].Key[current_key_type_i] = foundkey; - e_sector[current_sector_i].foundKey[current_key_type_i] = 6; + e_sector[current_sector_i].foundKey[current_key_type_i] = 'H'; PrintAndLogEx(INFO, _YELLOW_("======================= STOP HARDNESTED ATTACK =======================")); } @@ -2127,20 +2126,9 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack // Show the results to the user PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "Found Keys:"); - printKeyTable(sectors_cnt, e_sector); - if (verbose) { - PrintAndLogEx(INFO, " Key res types:"); - PrintAndLogEx(INFO, " 1: Dictionary"); - PrintAndLogEx(INFO, " 2: Darkside attack"); - PrintAndLogEx(INFO, " 3: User supplied"); - PrintAndLogEx(INFO, " 4: Reused"); - PrintAndLogEx(INFO, " 5: Nested"); - PrintAndLogEx(INFO, " 6: Hardnested"); - PrintAndLogEx(INFO, " 7: Read B key with A key"); - } + printKeyTableAutopwn(sectors_cnt, e_sector); PrintAndLogEx(INFO, "\nSaving keys"); - createMfcKeyDump(sectors_cnt, e_sector, GenerateFilename("hf-mf-", "-key.bin")); PrintAndLogEx(SUCCESS, "Transferring keys to simulator memory (Cmd Error: 04 can occur)"); @@ -3198,6 +3186,43 @@ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); } +void printKeyTableAutopwn(uint8_t sectorscnt, sector_t *e_sector) { + char strA[12 + 1] = {0}; + char strB[12 + 1] = {0}; + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + for (uint8_t i = 0; i < sectorscnt; ++i) { + + snprintf(strA, sizeof(strA), "------------"); + snprintf(strB, sizeof(strB), "------------"); + + if (e_sector[i].foundKey[0]) + snprintf(strA, sizeof(strA), "%012" PRIx64, e_sector[i].Key[0]); + + if (e_sector[i].foundKey[1]) + snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); + + + PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%c")"| %s | " _YELLOW_("%c")"|" + , i + , strA, e_sector[i].foundKey[0] + , strB, e_sector[i].foundKey[1] + ); + } + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(NORMAL, "( " + _YELLOW_("D") ":Dictionary / " + _YELLOW_("S") ":darkSide / " + _YELLOW_("U") ":User / " + _YELLOW_("R") ":Reused / " + _YELLOW_("N") ":Nested / " + _YELLOW_("H") ":Hardnested / " + _YELLOW_("A") ":keyA " + ")" + ); +} + // EMULATOR COMMANDS static int CmdHF14AMfEGet(const char *Cmd) { char c = tolower(param_getchar(Cmd, 0)); diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index 55997bd87..e9970cfb2 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -22,5 +22,6 @@ int CmdHF14AMfDbg(const char *Cmd); // used by cmd hf mfu dbg void showSectorTable(void); void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); void printKeyTable(uint8_t sectorscnt, sector_t *e_sector); +void printKeyTableAutopwn(uint8_t sectorscnt, sector_t *e_sector); void printKeyTable_fast(uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo); #endif From e4159b7cb3f5ae57d62aeb8cb9c43648ed8f7582 Mon Sep 17 00:00:00 2001 From: Matthias Konrath Date: Wed, 28 Aug 2019 18:39:01 +0200 Subject: [PATCH 3/3] Cleaned up the ouput to be as minimalistic as possible. Now the verbose flag output is realy verbose. --- client/cmdhfmf.c | 127 +++++++++++++++++++++++++---------------------- client/cmdhfmf.h | 1 - 2 files changed, 67 insertions(+), 61 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 66c50758f..aed756278 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1715,6 +1715,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // print parameters if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= SETTINGS =======================")); PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sectors_cnt); PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), know_target_key ? "True" : "False"); PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), blockNo); @@ -1723,6 +1724,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s"), prng_type ? "WEAK" : "HARD"); PrintAndLogEx(INFO, " dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "NONE"); PrintAndLogEx(INFO, " legacy mode ... " _YELLOW_("%s"), legacy_mfchk ? "True" : "False"); + PrintAndLogEx(INFO, _YELLOW_("======================= SETTINGS =======================")); } // Start the timer @@ -1732,6 +1734,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (know_target_key == false) PrintAndLogEx(WARNING, "No known key was supplied, key recovery might fail"); else { + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= START KNOWN KEY ATTACK =======================")); if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) { PrintAndLogEx(INFO, "Using valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)", blockNo, @@ -1781,6 +1784,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } } } + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP KNOWN KEY ATTACK =======================")); } // Load the dictionary @@ -1806,7 +1810,7 @@ useDefaultKeys: } // Use the dictionary to find sector keys on the card - PrintAndLogEx(INFO, _YELLOW_("======================= START DICTIONARY ATTACK =======================")); + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= START DICTIONARY ATTACK =======================")); if (legacy_mfchk) { // Check all the sectors @@ -1861,7 +1865,7 @@ useDefaultKeys: lastChunk = false; } // end strategy } - PrintAndLogEx(INFO, _YELLOW_("======================= STOP DICTIONARY ATTACK =======================")); + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP DICTIONARY ATTACK =======================")); // Analyse the dictionary attack @@ -1898,9 +1902,9 @@ useDefaultKeys: if (know_target_key == false) { // Check if the darkside attack can be used if (prng_type) { - PrintAndLogEx(INFO, _YELLOW_("======================= START DARKSIDE ATTACK =======================")); + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= START DARKSIDE ATTACK =======================")); int isOK = mfDarkside(FirstBlockOfSector(blockNo), keyType, &key64); - PrintAndLogEx(INFO, _YELLOW_("======================= STOP DARKSIDE ATTACK =======================")); + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP DARKSIDE ATTACK =======================")); switch (isOK) { case -1 : PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); @@ -1989,10 +1993,12 @@ noValidKeyFound: if (current_key_type_i == 1) { if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) { - PrintAndLogEx(INFO, "Reading B key: sector: %3d key type: %c", - current_sector_i, - current_key_type_i ? 'B' : 'A' - ); + if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= START READ B KEY ATTACK =======================")); + PrintAndLogEx(INFO, "Reading B key: sector: %3d key type: %c", + current_sector_i, + current_key_type_i ? 'B' : 'A'); + } uint8_t sectrail = (FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1); mf_readblock_t payload; @@ -2021,11 +2027,12 @@ noValidKeyFound: sprint_hex(tmp_key, sizeof(tmp_key)) ); } else { - PrintAndLogEx(WARNING, "Unknown B key: sector: %3d key type: %c (reading the B key was not possible, maybe due to insufficient access rights) ", + if (verbose) PrintAndLogEx(WARNING, "Unknown B key: sector: %3d key type: %c (reading the B key was not possible, maybe due to insufficient access rights) ", current_sector_i, current_key_type_i ? 'B' : 'A' ); } + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP READ B KEY ATTACK =======================")); } } @@ -2034,13 +2041,13 @@ skipReadBKey: if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) { if (prng_type && (! nested_failed)) { uint8_t retries = 0; - PrintAndLogEx(INFO, _YELLOW_("======================= START NESTED ATTACK =======================")); - + if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= START NESTED ATTACK =======================")); + PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c", + current_sector_i, + current_key_type_i ? 'B' : 'A'); + } tryNested: - PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c", - current_sector_i, - current_key_type_i ? 'B' : 'A'); - isOK = mfnested(FirstBlockOfSector(blockNo), keyType, key, FirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate); switch (isOK) { case -1 : @@ -2077,14 +2084,16 @@ tryNested: free(e_sector); return PM3_ESOFT; } - PrintAndLogEx(INFO, _YELLOW_("======================= STOP NESTED ATTACK =======================")); + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP NESTED ATTACK =======================")); } else { tryHardnested: // If the nested attack fails then we try the hardnested attack - PrintAndLogEx(INFO, _YELLOW_("======================= START HARDNESTED ATTACK =======================")); - PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c, Slow: %s", - current_sector_i, - current_key_type_i ? 'B' : 'A', - slow ? "Yes" : "No"); + if (verbose) { + PrintAndLogEx(INFO, _YELLOW_("======================= START HARDNESTED ATTACK =======================")); + PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c, Slow: %s", + current_sector_i, + current_key_type_i ? 'B' : 'A', + slow ? "Yes" : "No"); + } isOK = mfnestedhard(FirstBlockOfSector(blockNo), keyType, key, FirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL); DropField(); @@ -2108,7 +2117,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack e_sector[current_sector_i].Key[current_key_type_i] = foundkey; e_sector[current_sector_i].foundKey[current_key_type_i] = 'H'; - PrintAndLogEx(INFO, _YELLOW_("======================= STOP HARDNESTED ATTACK =======================")); + if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP HARDNESTED ATTACK =======================")); } // Check if the key was found if (e_sector[current_sector_i].foundKey[current_key_type_i]) { @@ -2126,8 +2135,43 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack // Show the results to the user PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "Found Keys:"); - printKeyTableAutopwn(sectors_cnt, e_sector); + char strA[12 + 1] = {0}; + char strB[12 + 1] = {0}; + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + for (uint8_t i = 0; i < sectors_cnt; ++i) { + + snprintf(strA, sizeof(strA), "------------"); + snprintf(strB, sizeof(strB), "------------"); + + if (e_sector[i].foundKey[0]) + snprintf(strA, sizeof(strA), "%012" PRIx64, e_sector[i].Key[0]); + + if (e_sector[i].foundKey[1]) + snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); + + + PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%c")"| %s | " _YELLOW_("%c")"|" + , i + , strA, e_sector[i].foundKey[0] + , strB, e_sector[i].foundKey[1] + ); + } + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(NORMAL, "( " + _YELLOW_("D") ":Dictionary / " + _YELLOW_("S") ":darkSide / " + _YELLOW_("U") ":User / " + _YELLOW_("R") ":Reused / " + _YELLOW_("N") ":Nested / " + _YELLOW_("H") ":Hardnested / " + _YELLOW_("A") ":keyA " + ")" + ); + + // Dump the keys PrintAndLogEx(INFO, "\nSaving keys"); createMfcKeyDump(sectors_cnt, e_sector, GenerateFilename("hf-mf-", "-key.bin")); @@ -3186,43 +3230,6 @@ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); } -void printKeyTableAutopwn(uint8_t sectorscnt, sector_t *e_sector) { - char strA[12 + 1] = {0}; - char strB[12 + 1] = {0}; - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - for (uint8_t i = 0; i < sectorscnt; ++i) { - - snprintf(strA, sizeof(strA), "------------"); - snprintf(strB, sizeof(strB), "------------"); - - if (e_sector[i].foundKey[0]) - snprintf(strA, sizeof(strA), "%012" PRIx64, e_sector[i].Key[0]); - - if (e_sector[i].foundKey[1]) - snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); - - - PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%c")"| %s | " _YELLOW_("%c")"|" - , i - , strA, e_sector[i].foundKey[0] - , strB, e_sector[i].foundKey[1] - ); - } - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - PrintAndLogEx(NORMAL, "( " - _YELLOW_("D") ":Dictionary / " - _YELLOW_("S") ":darkSide / " - _YELLOW_("U") ":User / " - _YELLOW_("R") ":Reused / " - _YELLOW_("N") ":Nested / " - _YELLOW_("H") ":Hardnested / " - _YELLOW_("A") ":keyA " - ")" - ); -} - // EMULATOR COMMANDS static int CmdHF14AMfEGet(const char *Cmd) { char c = tolower(param_getchar(Cmd, 0)); diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index e9970cfb2..55997bd87 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -22,6 +22,5 @@ int CmdHF14AMfDbg(const char *Cmd); // used by cmd hf mfu dbg void showSectorTable(void); void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); void printKeyTable(uint8_t sectorscnt, sector_t *e_sector); -void printKeyTableAutopwn(uint8_t sectorscnt, sector_t *e_sector); void printKeyTable_fast(uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo); #endif