diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 4cd1a02a7..1fb2d48ff 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -179,7 +179,7 @@ static int usage_hf14_autopwn(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " k if a known key for a block is supplied"); - PrintAndLogEx(NORMAL, " f .dic dictionary file for key discovery (the file has to end in .dic)"); + PrintAndLogEx(NORMAL, " f .dic dictionary file for key discovery (the file has to end in .dic) max 2000 entries allowed"); PrintAndLogEx(NORMAL, " s slower acquisition (required by some non standard cards) for hardnested"); PrintAndLogEx(NORMAL, " v verbose output (statistcs)"); PrintAndLogEx(NORMAL, " l legacy mode (use the slow mfchk for the key enumeration)"); @@ -1578,13 +1578,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { bool calibrate = true; // Attack key storage variables uint8_t *keyBlock; - uint16_t keycnt = 0; - sector_t *eSector; - uint8_t sectorsCnt = MIFARE_1K_MAXSECTOR; - int blockCnt = MIFARE_1K_MAXBLOCK; - uint8_t tmpKey[6] = {0}; - size_t datalen = 0; - bool knowTargetKey = false; + uint16_t key_cnt = 0; + sector_t *e_sector; + uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR; + int block_cnt = MIFARE_1K_MAXBLOCK; + uint8_t tmp_key[6] = {0}; + size_t data_length = 0; + bool know_target_key = false; // For the timier uint64_t t1; // Parameters and dictionary file @@ -1607,6 +1607,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { bool legacy_mfchk = false; bool prng_type = false; bool verbose = false; + int max_dictionary_size = 2000; // Parse the options given by the user ctmp = tolower(param_getchar(Cmd, 0)); @@ -1628,8 +1629,8 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { break; case '*': // Get the number of sectors - sectorsCnt = NumOfSectors(param_getchar(Cmd, cmdp + 1)); - blockCnt = NumOfBlocks(param_getchar(Cmd, cmdp + 1)); + sectors_cnt = NumOfSectors(param_getchar(Cmd, cmdp + 1)); + block_cnt = NumOfBlocks(param_getchar(Cmd, cmdp + 1)); cmdp ++; break; case 'k': @@ -1653,7 +1654,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(WARNING, "Key must include 12 HEX symbols"); return 1; } - knowTargetKey = true; + know_target_key = true; cmdp += 3; case 's': slow = true; @@ -1695,13 +1696,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } // Create the key storage stucture - eSector = calloc(sectorsCnt, sizeof(sector_t)); - if (eSector == NULL) return PM3_EMALLOC; + e_sector = calloc(sectors_cnt, sizeof(sector_t)); + if (e_sector == NULL) return PM3_EMALLOC; // Clear the key storage datastructure - for (i=0; i just be nice and correct it ;) - if (knowTargetKey == false) { - num_to_bytes(eSector[i].Key[i2], 6, key); - knowTargetKey = true; + if (know_target_key == false) { + num_to_bytes(e_sector[i].Key[i2], 6, key); + know_target_key = true; blockNo = i; keyType = i2; PrintAndLogEx(SUCCESS, "[ SETTINGS ] The following key will be used for the nested / hardnested attack: sector:" _RED_("%3d") " key type:"_RED_("%c") " key: " _RED_("0x%02x%02x%02x%02x%02x%02x"), @@ -1773,19 +1774,26 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Load the dictionary if (strlen(filename) != 0) { - keyBlock = calloc(6 * 2000, sizeof(uint8_t)); - loadFileDICTIONARY(filename, keyBlock, &datalen, 6, &keycnt); + keyBlock = calloc(6 * max_dictionary_size, sizeof(uint8_t)); + loadFileDICTIONARY(filename, keyBlock, &data_length, 6, &key_cnt); + if ((data_length / 6) > max_dictionary_size) { + // This is not a good solution (loadFileDICTIONARY needs a maxdatalen)! + PrintAndLogEx(FAILED, "The loaded dictionary is too large: %d (allowed: %d)", data_length, max_dictionary_size); + free(keyBlock); // This won't work too well, because data on the stack is already overflown !!! + free(e_sector); + return 1; + } } else { keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); if (keyBlock == NULL) { - free(eSector); + free(e_sector); return 1; } for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) { num_to_bytes(g_mifare_default_keys[cnt], 6, keyBlock + cnt * 6); } - keycnt = ARRAYLEN(g_mifare_default_keys); + key_cnt = ARRAYLEN(g_mifare_default_keys); } // Start the timer @@ -1795,15 +1803,15 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(INFO, "Enumerating the card keys with the dictionary!"); if (legacy_mfchk) { // Check all the sectors - for (i=0; i (PM3_CMD_DATA_SIZE / 6) ? (PM3_CMD_DATA_SIZE / 6) : keycnt; + int chunksize = key_cnt > (PM3_CMD_DATA_SIZE / 6) ? (PM3_CMD_DATA_SIZE / 6) : key_cnt; bool firstChunk = true, lastChunk = false; for (uint8_t strategy = 1; strategy < 3; strategy++) { PrintAndLogEx(INFO, "Running strategy %u", strategy); // main keychunk loop - for (i = 0; i < keycnt; i += chunksize) { + for (i = 0; i < key_cnt; i += chunksize) { if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); - i = keycnt; strategy = 3; break; // Exit the loop + i = key_cnt; strategy = 3; break; // Exit the loop } - uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; + uint32_t size = ((key_cnt - i) > chunksize) ? chunksize : key_cnt - i; // last chunk? - if (size == keycnt - i) + if (size == key_cnt - i) lastChunk = true; - int res = mfCheckKeys_fast(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), eSector, false); + int res = mfCheckKeys_fast(sectors_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); if (firstChunk) firstChunk = false; // all keys, aborted if (res == 0 || res == 2) { - i = keycnt; strategy = 3; break; // Exit the loop + i = key_cnt; strategy = 3; break; // Exit the loop } } // end chunks of keys firstChunk = true; @@ -1841,19 +1849,19 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } // Analyse the dictionary attack - for (i=0; i The fast check --> mfCheckKeys_fast(sectorsCnt, true, true, 2, 1, tmpKey, eSector, false); + if (bytes_to_num(tmp_key, 6) != 0) { + // The fast check --> mfCheckKeys_fast(sectors_cnt, true, true, 2, 1, tmp_key, e_sector, false); // Returns false keys, so we just stick to the slower mfchk. - for (i=0; i