diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ace03f8..df99d61b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] +- Changed `hf mf chk/fchk`: added option `--no-default` to skip loading the usual ~61 hardcoded keys (@doegox) - Fixed `hf mf wipe` to detect properly write errors (@doegox) - Fixed `hf mf fchk` which was leaving the RF field on when interrupted by keyboard (@doegox) - Changed file saving: do not prepend with default path if given path is an absolute path (@doegox) diff --git a/client/pyscripts/fm11rf08s_recovery.py b/client/pyscripts/fm11rf08s_recovery.py index f88001946..4ba48854f 100755 --- a/client/pyscripts/fm11rf08s_recovery.py +++ b/client/pyscripts/fm11rf08s_recovery.py @@ -151,7 +151,8 @@ for sec in range(NUM_SECTORS): # If we have a duplicates dict if found_keys[sec][0] == "" and found_keys[sec][1] == "" and len(keys_filtered[sec][key_type]) > 0: kt = ['a', 'b'][key_type] - cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f keys_{uid:08x}_{sec:02}_{nt[sec][key_type]}_duplicates.dic" + dic = f"keys_{uid:08x}_{sec:02}_{nt[sec][key_type]}_duplicates.dic" + cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f {dic} --no-default" if DEBUG: print(cmd) with out: @@ -176,7 +177,8 @@ for sec in range(NUM_SECTORS): if found_keys[sec][0] == "" and found_keys[sec][1] == "" and nt[sec][0] != nt[sec][1]: # Use filtered dict kt = ['a', 'b'][key_type] - cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f keys_{uid:08x}_{sec:02}_{nt[sec][key_type]}_filtered.dic" + dic = f"keys_{uid:08x}_{sec:02}_{nt[sec][key_type]}_filtered.dic" + cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f {dic} --no-default" if DEBUG: print(cmd) with out: @@ -197,7 +199,8 @@ for sec in range(NUM_SECTORS): key_type = 0 # Use regular dict kt = ['a', 'b'][key_type] - cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f keys_{uid:08x}_{sec:02}_{nt[sec][key_type]}.dic" + dic = f"keys_{uid:08x}_{sec:02}_{nt[sec][key_type]}.dic" + cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f {dic} --no-default" if DEBUG: print(cmd) with out: @@ -237,7 +240,7 @@ for sec in range(NUM_SECTORS): keys.add(line[12:]) if len(keys) > 1: kt = ['a', 'b'][key_type_target] - cmd = f"hf mf fchk --blk {sec * 4} -{kt}" + cmd = f"hf mf fchk --blk {sec * 4} -{kt} --no-default" for k in keys: cmd += f" -k {k}" if DEBUG: @@ -270,7 +273,7 @@ if FINAL_CHECK: with (open(f"keys_{uid:08x}.dic", "w")) as f: for k in keys_set: f.write(f"{k}\n") - cmd = f"hf mf fchk -f keys_{uid:08x}.dic --dump" + cmd = f"hf mf fchk -f keys_{uid:08x}.dic --no-default --dump" if DEBUG: print(cmd) with out: diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 72c6f6636..513f3ef7c 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -764,7 +764,7 @@ static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t n return PM3_SUCCESS ; } -static int mf_load_keys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userkey, int userkeylen, const char *filename, int fnlen) { +static int mf_load_keys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userkey, int userkeylen, const char *filename, int fnlen, bool load_default) { // Handle Keys *pkeycnt = 0; *pkeyBlock = NULL; @@ -790,28 +790,30 @@ static int mf_load_keys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userkey PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") " user keys", numKeys); } - // Handle default keys - p = realloc(*pkeyBlock, (*pkeycnt + ARRAYLEN(g_mifare_default_keys)) * MIFARE_KEY_SIZE); - if (!p) { - PrintAndLogEx(FAILED, "cannot allocate memory for Keys"); - free(*pkeyBlock); - return PM3_EMALLOC; + if (load_default) { + // Handle default keys + p = realloc(*pkeyBlock, (*pkeycnt + ARRAYLEN(g_mifare_default_keys)) * MIFARE_KEY_SIZE); + if (!p) { + PrintAndLogEx(FAILED, "cannot allocate memory for Keys"); + free(*pkeyBlock); + return PM3_EMALLOC; + } + *pkeyBlock = p; + // Copy default keys to list + for (int i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) { + num_to_bytes(g_mifare_default_keys[i], MIFARE_KEY_SIZE, (uint8_t *)(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE)); + PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", *pkeycnt + i, sprint_hex(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE)); + } + *pkeycnt += ARRAYLEN(g_mifare_default_keys); + PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%zu") " keys from hardcoded default array", ARRAYLEN(g_mifare_default_keys)); } - *pkeyBlock = p; - // Copy default keys to list - for (int i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) { - num_to_bytes(g_mifare_default_keys[i], MIFARE_KEY_SIZE, (uint8_t *)(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE)); - PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", *pkeycnt + i, sprint_hex(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE)); - } - *pkeycnt += ARRAYLEN(g_mifare_default_keys); - PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%zu") " keys from hardcoded default array", ARRAYLEN(g_mifare_default_keys)); // Handle user supplied dictionary file if (fnlen > 0) { uint32_t loaded_numKeys = 0; uint8_t *keyBlock_tmp = NULL; int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock_tmp, MIFARE_KEY_SIZE, &loaded_numKeys); - if (res != PM3_SUCCESS || loaded_numKeys == 0 || *pkeyBlock == NULL) { + if (res != PM3_SUCCESS || loaded_numKeys == 0 || keyBlock_tmp == NULL) { PrintAndLogEx(FAILED, "An error occurred while loading the dictionary!"); free(keyBlock_tmp); free(*pkeyBlock); @@ -2761,7 +2763,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Start the timer uint64_t t1 = msclock(); - int ret = mf_load_keys(&keyBlock, &key_cnt, in_keys, in_keys_len, filename, fnlen); + int ret = mf_load_keys(&keyBlock, &key_cnt, in_keys, in_keys_len, filename, fnlen, true); if (ret != PM3_SUCCESS) { free(e_sector); return ret; @@ -3295,6 +3297,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { arg_int0(NULL, "blk", "", "block number (single block recovery mode)"), arg_lit0("a", NULL, "single block recovery key A"), arg_lit0("b", NULL, "single block recovery key B"), + arg_lit0(NULL, "no-default", "Don't add the bunch of extra default keys"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -3325,6 +3328,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { } else if (arg_get_lit(ctx, 12)) { keytype = MF_KEY_B; } + bool load_default = ! arg_get_lit(ctx, 13); CLIParserFree(ctx); @@ -3353,7 +3357,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { uint8_t *keyBlock = NULL; uint32_t keycnt = 0; - int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen); + int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen, load_default); if (ret != PM3_SUCCESS) { return ret; } @@ -3732,6 +3736,7 @@ static int CmdHF14AMfChk(const char *Cmd) { arg_lit0(NULL, "emu", "Fill simulator keys from found keys"), arg_lit0(NULL, "dump", "Dump found keys to binary file"), arg_str0("f", "file", "", "Filename of dictionary"), + arg_lit0(NULL, "no-default", "Don't add the bunch of extra default keys"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -3763,6 +3768,7 @@ static int CmdHF14AMfChk(const char *Cmd) { int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 12), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + bool load_default = ! arg_get_lit(ctx, 13); CLIParserFree(ctx); @@ -3822,7 +3828,7 @@ static int CmdHF14AMfChk(const char *Cmd) { uint8_t *keyBlock = NULL; uint32_t keycnt = 0; - int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen); + int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen, load_default); if (ret != PM3_SUCCESS) { return ret; } @@ -9494,7 +9500,7 @@ static int CmdHF14AMfInfo(const char *Cmd) { int sectorsCnt = 2; uint8_t *keyBlock = NULL; uint32_t keycnt = 0; - res = mf_load_keys(&keyBlock, &keycnt, key, MIFARE_KEY_SIZE * 2, NULL, 0); + res = mf_load_keys(&keyBlock, &keycnt, key, MIFARE_KEY_SIZE * 2, NULL, 0, true); if (res != PM3_SUCCESS) { return res; }