mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-22 14:23:50 -07:00
hf mf chk/fchk: factorize and fix key loading logic, chk: don't loop if one single block
This commit is contained in:
parent
80f768b787
commit
ee7856e9eb
1 changed files with 115 additions and 205 deletions
|
@ -48,6 +48,11 @@
|
||||||
#define MIFARE_2K_MAXSECTOR 32
|
#define MIFARE_2K_MAXSECTOR 32
|
||||||
#define MIFARE_4K_MAXSECTOR 40
|
#define MIFARE_4K_MAXSECTOR 40
|
||||||
|
|
||||||
|
/* On some platforms, max() may already be defined */
|
||||||
|
#ifndef max
|
||||||
|
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2700,6 +2705,73 @@ all_found:
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mfLoadKeys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userkey, int userkeylen, const char *filename, int fnlen) {
|
||||||
|
// Handle Keys
|
||||||
|
*pkeycnt = 0;
|
||||||
|
*pkeyBlock = NULL;
|
||||||
|
uint8_t *p;
|
||||||
|
// Handle user supplied key
|
||||||
|
// (it considers *pkeycnt and *pkeyBlock as possibly non-null so logic can be easily reordered)
|
||||||
|
if (userkeylen >= 6) {
|
||||||
|
int numKeys = userkeylen / 6;
|
||||||
|
p = realloc(*pkeyBlock, (*pkeycnt + numKeys) * 6);
|
||||||
|
if (!p) {
|
||||||
|
PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
|
||||||
|
free(*pkeyBlock);
|
||||||
|
return PM3_EMALLOC;
|
||||||
|
}
|
||||||
|
*pkeyBlock = p;
|
||||||
|
|
||||||
|
memcpy(*pkeyBlock + *pkeycnt * 6, userkey, numKeys * 6);
|
||||||
|
|
||||||
|
for (int i = 0; i < numKeys; i++) {
|
||||||
|
PrintAndLogEx(INFO, "[%2d] key %s", *pkeycnt + i, sprint_hex(*pkeyBlock + (*pkeycnt + i) * 6, 6));
|
||||||
|
}
|
||||||
|
*pkeycnt += numKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle default keys
|
||||||
|
p = realloc(*pkeyBlock, (*pkeycnt + ARRAYLEN(g_mifare_default_keys)) * 6);
|
||||||
|
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], 6, (uint8_t *)(*pkeyBlock + (*pkeycnt + i) * 6));
|
||||||
|
PrintAndLogEx(DEBUG, "[%2d] key %s", *pkeycnt + i, sprint_hex(*pkeyBlock + (*pkeycnt + i) * 6, 6));
|
||||||
|
}
|
||||||
|
*pkeycnt += 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, 6, &loaded_numKeys);
|
||||||
|
if (res != PM3_SUCCESS || loaded_numKeys == 0 || *pkeyBlock == NULL) {
|
||||||
|
PrintAndLogEx(FAILED, "An error occurred while loading the dictionary!");
|
||||||
|
free(keyBlock_tmp);
|
||||||
|
free(*pkeyBlock);
|
||||||
|
return PM3_EFILE;
|
||||||
|
} else {
|
||||||
|
p = realloc(*pkeyBlock, (*pkeycnt + loaded_numKeys) * 6);
|
||||||
|
if (!p) {
|
||||||
|
PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
|
||||||
|
free(keyBlock_tmp);
|
||||||
|
free(*pkeyBlock);
|
||||||
|
return PM3_EMALLOC;
|
||||||
|
}
|
||||||
|
*pkeyBlock = p;
|
||||||
|
memcpy(*pkeyBlock + *pkeycnt * 6, keyBlock_tmp, loaded_numKeys * 6);
|
||||||
|
*pkeycnt += loaded_numKeys;
|
||||||
|
free(keyBlock_tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHF14AMfChk_fast(const char *Cmd) {
|
static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mf fchk",
|
CLIParserInit(&ctx, "hf mf fchk",
|
||||||
|
@ -2770,100 +2842,11 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Keys
|
uint8_t *keyBlock = NULL;
|
||||||
int keycnt = 0;
|
uint32_t keycnt = 0;
|
||||||
uint32_t keyitems = ARRAYLEN(g_mifare_default_keys);
|
int ret = mfLoadKeys(&keyBlock, &keycnt, key, keylen, filename, fnlen);
|
||||||
uint8_t *keyBlock, *p;
|
if (ret != PM3_SUCCESS) {
|
||||||
// Allocate memory for keys to be tested
|
return ret;
|
||||||
keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6);
|
|
||||||
if (keyBlock == NULL) return PM3_EMALLOC;
|
|
||||||
|
|
||||||
// Copy default keys to list
|
|
||||||
for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++)
|
|
||||||
num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6));
|
|
||||||
|
|
||||||
// Handle user supplied key
|
|
||||||
if (keylen >= 6) {
|
|
||||||
int numKeys = keylen / 6;
|
|
||||||
|
|
||||||
p = realloc(keyBlock, 6 * (keyitems + numKeys));
|
|
||||||
if (!p) {
|
|
||||||
PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
|
|
||||||
free(keyBlock);
|
|
||||||
return PM3_EMALLOC;
|
|
||||||
}
|
|
||||||
keyBlock = p;
|
|
||||||
|
|
||||||
memcpy(keyBlock + 6 * keycnt, key, 6 * numKeys);
|
|
||||||
|
|
||||||
for (int i = 0; i < numKeys; i++) {
|
|
||||||
PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex((keyBlock + 6 * keycnt), 6));
|
|
||||||
keycnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle user supplied dictionary file
|
|
||||||
FILE *f;
|
|
||||||
char buf[13];
|
|
||||||
if (fnlen > 0) {
|
|
||||||
char *dict_path;
|
|
||||||
int res = searchFile(&dict_path, DICTIONARIES_SUBDIR, filename, ".dic", false);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
free(keyBlock);
|
|
||||||
return PM3_EFILE;
|
|
||||||
}
|
|
||||||
f = fopen(dict_path, "r");
|
|
||||||
if (!f) {
|
|
||||||
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", dict_path);
|
|
||||||
free(dict_path);
|
|
||||||
free(keyBlock);
|
|
||||||
return PM3_EFILE;
|
|
||||||
}
|
|
||||||
free(dict_path);
|
|
||||||
// load keys from dictionary file
|
|
||||||
while (fgets(buf, sizeof(buf), f)) {
|
|
||||||
if (strlen(buf) < 12 || buf[11] == '\n')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
while (fgetc(f) != '\n' && !feof(f)) ; //goto next line
|
|
||||||
|
|
||||||
if (buf[0] == '#') continue; //The line start with # is comment, skip
|
|
||||||
|
|
||||||
// codesmell, only checks first char?
|
|
||||||
if (!isxdigit(buf[0])) {
|
|
||||||
PrintAndLogEx(FAILED, "File content error. '" _YELLOW_("%s")"' must include 12 HEX symbols", buf);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[12] = 0;
|
|
||||||
|
|
||||||
if (keyitems - keycnt < 2) {
|
|
||||||
p = realloc(keyBlock, 6 * (keyitems += 64));
|
|
||||||
if (!p) {
|
|
||||||
PrintAndLogEx(FAILED, "Cannot allocate memory for defKeys");
|
|
||||||
free(keyBlock);
|
|
||||||
fclose(f);
|
|
||||||
return PM3_EMALLOC;
|
|
||||||
}
|
|
||||||
keyBlock = p;
|
|
||||||
}
|
|
||||||
memset(keyBlock + 6 * keycnt, 0, 6);
|
|
||||||
num_to_bytes(strtoll(buf, NULL, 16), 6, keyBlock + 6 * keycnt);
|
|
||||||
//PrintAndLogEx(NORMAL, "check key[%2d] %012" PRIx64, keycnt, bytes_to_num(keyBlock + 6*keycnt, 6));
|
|
||||||
keycnt++;
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_("%s"), keycnt, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keycnt == 0 && !use_flashmemory) {
|
|
||||||
PrintAndLogEx(SUCCESS, "No key specified, trying default keys");
|
|
||||||
for (; keycnt < ARRAYLEN(g_mifare_default_keys); keycnt++)
|
|
||||||
PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
|
|
||||||
(keyBlock + 6 * keycnt)[0], (keyBlock + 6 * keycnt)[1], (keyBlock + 6 * keycnt)[2],
|
|
||||||
(keyBlock + 6 * keycnt)[3], (keyBlock + 6 * keycnt)[4], (keyBlock + 6 * keycnt)[5]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create/initialize key storage structure
|
// create/initialize key storage structure
|
||||||
|
@ -2874,7 +2857,6 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t chunksize = keycnt > (PM3_CMD_DATA_SIZE / 6) ? (PM3_CMD_DATA_SIZE / 6) : keycnt;
|
uint32_t chunksize = keycnt > (PM3_CMD_DATA_SIZE / 6) ? (PM3_CMD_DATA_SIZE / 6) : keycnt;
|
||||||
bool firstChunk = true, lastChunk = false;
|
bool firstChunk = true, lastChunk = false;
|
||||||
|
|
||||||
|
@ -3051,6 +3033,11 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
||||||
CLIParamStrToBuf(arg_get_str(ctx, 12), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
CLIParamStrToBuf(arg_get_str(ctx, 12), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
bool singleSector = blockNo > -1;
|
||||||
|
if (! singleSector) {
|
||||||
|
// start from first trailer block
|
||||||
|
blockNo = 3;
|
||||||
|
}
|
||||||
|
|
||||||
//validations
|
//validations
|
||||||
if ((m0 + m1 + m2 + m4) > 1) {
|
if ((m0 + m1 + m2 + m4) > 1) {
|
||||||
|
@ -3069,123 +3056,42 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
||||||
SectorsCnt = MIFARE_4K_MAXSECTOR;
|
SectorsCnt = MIFARE_4K_MAXSECTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((blockNo == -1) && (SectorsCnt == 1)) {
|
if (singleSector) {
|
||||||
// Default to 1K if block number not specified
|
uint8_t MinSectorsCnt = 0;
|
||||||
|
// find a MIFARE type that can accommodate the provided block number
|
||||||
|
uint8_t s = mfSectorNum(blockNo);
|
||||||
|
if (s < MIFARE_MINI_MAXSECTOR) {
|
||||||
|
MinSectorsCnt = MIFARE_MINI_MAXSECTOR;
|
||||||
|
} else if (s < MIFARE_1K_MAXSECTOR) {
|
||||||
|
MinSectorsCnt = MIFARE_1K_MAXSECTOR;
|
||||||
|
} else if (s < MIFARE_2K_MAXSECTOR) {
|
||||||
|
MinSectorsCnt = MIFARE_2K_MAXSECTOR;
|
||||||
|
} else if (s < MIFARE_4K_MAXSECTOR) {
|
||||||
|
MinSectorsCnt = MIFARE_4K_MAXSECTOR;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "Provided block out of possible MIFARE Type memory map");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
if (SectorsCnt == 1) {
|
||||||
|
SectorsCnt = MinSectorsCnt;
|
||||||
|
} else if (SectorsCnt < MinSectorsCnt) {
|
||||||
|
PrintAndLogEx(WARNING, "Provided block out of provided MIFARE Type memory map");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (SectorsCnt == 1) {
|
||||||
SectorsCnt = MIFARE_1K_MAXSECTOR;
|
SectorsCnt = MIFARE_1K_MAXSECTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockNo > -1) {
|
uint8_t *keyBlock = NULL;
|
||||||
if (SectorsCnt == 0) {
|
uint32_t keycnt = 0;
|
||||||
PrintAndLogEx(WARNING, "Invalid MIFARE Type");
|
int ret = mfLoadKeys(&keyBlock, &keycnt, key, keylen, filename, fnlen);
|
||||||
return PM3_EINVARG;
|
if (ret != PM3_SUCCESS) {
|
||||||
}
|
return ret;
|
||||||
} else {
|
|
||||||
blockNo = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle Keys
|
|
||||||
int keycnt = 0;
|
|
||||||
uint32_t keyitems = ARRAYLEN(g_mifare_default_keys);
|
|
||||||
uint8_t *keyBlock, *p;
|
|
||||||
// Allocate memory for keys to be tested
|
|
||||||
keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6);
|
|
||||||
if (keyBlock == NULL) return PM3_EMALLOC;
|
|
||||||
|
|
||||||
// Copy default keys to list
|
|
||||||
for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++)
|
|
||||||
num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6));
|
|
||||||
|
|
||||||
// Handle user supplied key
|
|
||||||
if (keylen >= 6) {
|
|
||||||
int numKeys = keylen / 6;
|
|
||||||
|
|
||||||
p = realloc(keyBlock, 6 * (keyitems + numKeys));
|
|
||||||
if (!p) {
|
|
||||||
PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
|
|
||||||
free(keyBlock);
|
|
||||||
return PM3_EMALLOC;
|
|
||||||
}
|
|
||||||
keyBlock = p;
|
|
||||||
|
|
||||||
memcpy(keyBlock + 6 * keycnt, key, 6 * numKeys);
|
|
||||||
|
|
||||||
for (int i = 0; i < numKeys; i++) {
|
|
||||||
PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex((keyBlock + 6 * keycnt), 6));
|
|
||||||
keycnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle user supplied dictionary file
|
|
||||||
FILE *f;
|
|
||||||
char buf[13];
|
|
||||||
if (fnlen > 0) {
|
|
||||||
char *dict_path;
|
|
||||||
int res = searchFile(&dict_path, DICTIONARIES_SUBDIR, filename, ".dic", false);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
free(keyBlock);
|
|
||||||
return PM3_EFILE;
|
|
||||||
}
|
|
||||||
f = fopen(dict_path, "r");
|
|
||||||
if (!f) {
|
|
||||||
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", dict_path);
|
|
||||||
free(dict_path);
|
|
||||||
free(keyBlock);
|
|
||||||
return PM3_EFILE;
|
|
||||||
}
|
|
||||||
free(dict_path);
|
|
||||||
// load keys from dictionary file
|
|
||||||
while (fgets(buf, sizeof(buf), f)) {
|
|
||||||
if (strlen(buf) < 12 || buf[11] == '\n')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
while (fgetc(f) != '\n' && !feof(f)) ; //goto next line
|
|
||||||
|
|
||||||
if (buf[0] == '#') continue; //The line start with # is comment, skip
|
|
||||||
|
|
||||||
// codesmell, only checks first char?
|
|
||||||
if (!isxdigit(buf[0])) {
|
|
||||||
PrintAndLogEx(FAILED, "File content error. '" _YELLOW_("%s")"' must include 12 HEX symbols", buf);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[12] = 0;
|
|
||||||
|
|
||||||
if (keyitems - keycnt < 2) {
|
|
||||||
p = realloc(keyBlock, 6 * (keyitems += 64));
|
|
||||||
if (!p) {
|
|
||||||
PrintAndLogEx(FAILED, "Cannot allocate memory for defKeys");
|
|
||||||
free(keyBlock);
|
|
||||||
fclose(f);
|
|
||||||
return PM3_EMALLOC;
|
|
||||||
}
|
|
||||||
keyBlock = p;
|
|
||||||
}
|
|
||||||
memset(keyBlock + 6 * keycnt, 0, 6);
|
|
||||||
num_to_bytes(strtoll(buf, NULL, 16), 6, keyBlock + 6 * keycnt);
|
|
||||||
//PrintAndLogEx(NORMAL, "check key[%2d] %012" PRIx64, keycnt, bytes_to_num(keyBlock + 6*keycnt, 6));
|
|
||||||
keycnt++;
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_("%s"), keycnt, filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t key64 = 0;
|
uint64_t key64 = 0;
|
||||||
|
|
||||||
if (keycnt == 0) {
|
|
||||||
PrintAndLogEx(INFO, "No key specified, trying default keys");
|
|
||||||
for (; keycnt < ARRAYLEN(g_mifare_default_keys); keycnt++)
|
|
||||||
PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
|
|
||||||
(keyBlock + 6 * keycnt)[0],
|
|
||||||
(keyBlock + 6 * keycnt)[1],
|
|
||||||
(keyBlock + 6 * keycnt)[2],
|
|
||||||
(keyBlock + 6 * keycnt)[3],
|
|
||||||
(keyBlock + 6 * keycnt)[4],
|
|
||||||
(keyBlock + 6 * keycnt)[5]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create/initialize key storage structure
|
// create/initialize key storage structure
|
||||||
sector_t *e_sector = NULL;
|
sector_t *e_sector = NULL;
|
||||||
int32_t res = initSectorTable(&e_sector, SectorsCnt);
|
int32_t res = initSectorTable(&e_sector, SectorsCnt);
|
||||||
|
@ -3239,6 +3145,8 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
||||||
}
|
}
|
||||||
clearLog = false;
|
clearLog = false;
|
||||||
}
|
}
|
||||||
|
if (singleSector)
|
||||||
|
break;
|
||||||
b < 127 ? (b += 4) : (b += 16);
|
b < 127 ? (b += 4) : (b += 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3284,6 +3192,8 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
||||||
e_sector[i].Key[1] = key64;
|
e_sector[i].Key[1] = key64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (singleSector)
|
||||||
|
break;
|
||||||
b < 127 ? (b += 4) : (b += 16);
|
b < 127 ? (b += 4) : (b += 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue