Add option to use SPI flash dictionary for autopwn

This commit is contained in:
Jean-Michel Picod 2025-03-21 18:05:14 +01:00
commit 95e5634388
2 changed files with 73 additions and 58 deletions

View file

@ -1896,32 +1896,33 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
if (exists_in_spiffs(MF_KEYS_FILE)) { if (exists_in_spiffs(MF_KEYS_FILE)) {
size = size_in_spiffs(MF_KEYS_FILE); size = size_in_spiffs(MF_KEYS_FILE);
} }
if (size == 0) { if ((size == 0) || (size < MF_KEY_LENGTH)) {
Dbprintf("Spiffs file: %s does not exists or empty.", MF_KEYS_FILE); Dbprintf("Spiffs file: %s does not exists or empty.", MF_KEYS_FILE);
goto OUT; goto OUT;
} }
keyCount = size / MF_KEY_LENGTH; // Compute how many keys can fit in bigbuff
if (keyCount == 0)
goto OUT;
// limit size of available for keys in bigbuff
// a key is 6bytes // a key is 6bytes
uint16_t key_mem_available = MIN(BigBuf_get_size(), keyCount * MF_KEY_LENGTH); uint16_t key_mem_available = MIN(BigBuf_get_size() / MF_KEY_LENGTH, keyCount + (size / MF_KEY_LENGTH));
keyCount = key_mem_available / MF_KEY_LENGTH; uint8_t *dictkeys = BigBuf_malloc(key_mem_available * MF_KEY_LENGTH);
if (dictkeys == NULL)
datain = BigBuf_malloc(key_mem_available);
if (datain == NULL)
goto OUT; goto OUT;
if (SPIFFS_OK == rdv40_spiffs_read_as_filetype(MF_KEYS_FILE, datain, keyCount * MF_KEY_LENGTH, RDV40_SPIFFS_SAFETY_SAFE)) { // Put user and hard-coded keys first
if (g_dbglevel >= DBG_ERROR) Dbprintf("Loaded %u keys from spiffs file: %s", keyCount, MF_KEYS_FILE); memcpy(dictkeys, datain, keyCount * MF_KEY_LENGTH);
// Now append the SPI flash dictionnary
if (SPIFFS_OK == rdv40_spiffs_read_as_filetype(MF_KEYS_FILE, dictkeys + keyCount * MF_KEY_LENGTH, (key_mem_available - keyCount) * MF_KEY_LENGTH, RDV40_SPIFFS_SAFETY_SAFE)) {
if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Loaded %u keys from spiffs file: %s", key_mem_available, MF_KEYS_FILE);
}
} else { } else {
Dbprintf("Spiffs file: %s cannot be read.", MF_KEYS_FILE); Dbprintf("Spiffs file: %s cannot be read.", MF_KEYS_FILE);
goto OUT; goto OUT;
} }
// Replace client provided keys
datain = dictkeys;
} }
#endif #endif

View file

@ -2490,6 +2490,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
arg_lit0(NULL, "slow", "Slower acquisition (required by some non standard cards)"), arg_lit0(NULL, "slow", "Slower acquisition (required by some non standard cards)"),
arg_lit0("l", "legacy", "legacy mode (use the slow `hf mf chk`)"), arg_lit0("l", "legacy", "legacy mode (use the slow `hf mf chk`)"),
arg_lit0("v", "verbose", "verbose output"), arg_lit0("v", "verbose", "verbose output"),
arg_lit0(NULL, "mem", "Use dictionary from flashmemory"),
arg_lit0(NULL, "ns", "No save to file"), arg_lit0(NULL, "ns", "No save to file"),
@ -2542,26 +2543,27 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
bool slow = arg_get_lit(ctx, 7); bool slow = arg_get_lit(ctx, 7);
bool legacy_mfchk = arg_get_lit(ctx, 8); bool legacy_mfchk = arg_get_lit(ctx, 8);
bool verbose = arg_get_lit(ctx, 9); bool verbose = arg_get_lit(ctx, 9);
bool use_flashmemory = arg_get_lit(ctx, 10);
bool no_save = arg_get_lit(ctx, 10); bool no_save = arg_get_lit(ctx, 11);
bool m0 = arg_get_lit(ctx, 11); bool m0 = arg_get_lit(ctx, 12);
bool m1 = arg_get_lit(ctx, 12); bool m1 = arg_get_lit(ctx, 13);
bool m2 = arg_get_lit(ctx, 13); bool m2 = arg_get_lit(ctx, 14);
bool m4 = arg_get_lit(ctx, 14); bool m4 = arg_get_lit(ctx, 15);
bool in = arg_get_lit(ctx, 15); bool in = arg_get_lit(ctx, 16);
#if defined(COMPILER_HAS_SIMD_X86) #if defined(COMPILER_HAS_SIMD_X86)
bool im = arg_get_lit(ctx, 16); bool im = arg_get_lit(ctx, 17);
bool is = arg_get_lit(ctx, 17); bool is = arg_get_lit(ctx, 1);
bool ia = arg_get_lit(ctx, 18); bool ia = arg_get_lit(ctx, 19);
bool i2 = arg_get_lit(ctx, 19); bool i2 = arg_get_lit(ctx, 20);
#endif #endif
#if defined(COMPILER_HAS_SIMD_AVX512) #if defined(COMPILER_HAS_SIMD_AVX512)
bool i5 = arg_get_lit(ctx, 20); bool i5 = arg_get_lit(ctx, 21);
#endif #endif
#if defined(COMPILER_HAS_SIMD_NEON) #if defined(COMPILER_HAS_SIMD_NEON)
bool ie = arg_get_lit(ctx, 16); bool ie = arg_get_lit(ctx, 17);
#endif #endif
CLIParserFree(ctx); CLIParserFree(ctx);
@ -2784,6 +2786,11 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
// Start the timer // Start the timer
uint64_t t1 = msclock(); uint64_t t1 = msclock();
// If we use the dictionary in flash memory, we don't want to load keys
// from hard drive dictionary as it could exceed BigBuf capacity
if (use_flashmemory) {
fnlen = 0;
}
int ret = mf_load_keys(&keyBlock, &key_cnt, in_keys, in_keys_len, filename, fnlen, true); int ret = mf_load_keys(&keyBlock, &key_cnt, in_keys, in_keys_len, filename, fnlen, true);
if (ret != PM3_SUCCESS) { if (ret != PM3_SUCCESS) {
free(e_sector); free(e_sector);
@ -2793,7 +2800,9 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
int32_t res = PM3_SUCCESS; int32_t res = PM3_SUCCESS;
// Use the dictionary to find sector keys on the card // Use the dictionary to find sector keys on the card
if (verbose) PrintAndLogEx(INFO, "======================= " _YELLOW_("START DICTIONARY ATTACK") " ======================="); if (verbose) {
PrintAndLogEx(INFO, "======================= " _YELLOW_("START DICTIONARY ATTACK") " =======================");
}
if (legacy_mfchk) { if (legacy_mfchk) {
PrintAndLogEx(INFO, "." NOLF); PrintAndLogEx(INFO, "." NOLF);
@ -2817,41 +2826,46 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
} else { } else {
if (use_flashmemory) {
PrintAndLogEx(SUCCESS, "Using dictionary in flash memory");
res = mf_check_keys_fast(sector_cnt, true, true, 1, key_cnt, keyBlock, e_sector, use_flashmemory, verbose);
} else {
uint32_t chunksize = key_cnt > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : key_cnt; uint32_t chunksize = key_cnt > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : key_cnt;
bool firstChunk = true, lastChunk = false; bool firstChunk = true, lastChunk = false;
for (uint8_t strategy = 1; strategy < 3; strategy++) { for (uint8_t strategy = 1; strategy < 3; strategy++) {
PrintAndLogEx(INFO, "running strategy %u", strategy); PrintAndLogEx(INFO, "Running strategy %u", strategy);
// main keychunk loop // main keychunk loop
for (uint32_t i = 0; i < key_cnt; i += chunksize) { for (uint32_t i = 0; i < key_cnt; i += chunksize) {
if (kbd_enter_pressed()) { if (kbd_enter_pressed()) {
PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
i = key_cnt; i = key_cnt;
strategy = 3; strategy = 3;
break; // Exit the loop break; // Exit the loop
} }
uint32_t size = ((key_cnt - i) > chunksize) ? chunksize : key_cnt - i; uint32_t size = ((key_cnt - i) > chunksize) ? chunksize : key_cnt - i;
// last chunk? // last chunk?
if (size == key_cnt - i) { if (size == key_cnt - i) {
lastChunk = true; lastChunk = true;
} }
res = mf_check_keys_fast(sector_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, verbose); res = mf_check_keys_fast(sector_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, verbose);
if (firstChunk) { if (firstChunk) {
firstChunk = false; firstChunk = false;
} }
// all keys, aborted // all keys, aborted
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
i = key_cnt; i = key_cnt;
strategy = 3; strategy = 3;
break; // Exit the loop break; // Exit the loop
} }
} // end chunks of keys } // end chunks of keys
firstChunk = true; firstChunk = true;
lastChunk = false; lastChunk = false;
} // end strategy } // end strategy
}
} }
// Analyse the dictionary attack // Analyse the dictionary attack