hf mf chk - now use cliparser

This commit is contained in:
tcprst 2021-02-13 14:37:47 -05:00
commit 9cca51f61e
No known key found for this signature in database
GPG key ID: 9145EAF5121AED25
4 changed files with 168 additions and 140 deletions

View file

@ -136,25 +136,6 @@ static int usage_hf14_autopwn(void) {
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf autopwn k 0 A FFFFFFFFFFFF * 1 f mfc_default_keys")" -- this command combines the two above (reduce the need for nested / hardnested attacks, by using a dictionary)"); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf autopwn k 0 A FFFFFFFFFFFF * 1 f mfc_default_keys")" -- this command combines the two above (reduce the need for nested / hardnested attacks, by using a dictionary)");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf14_chk(void) {
PrintAndLogEx(NORMAL, "Usage: hf mf chk [h] <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " * all sectors based on card memory, other values then below defaults to 1k");
PrintAndLogEx(NORMAL, " 0 - MINI(320 bytes)");
PrintAndLogEx(NORMAL, " 1 - 1K");
PrintAndLogEx(NORMAL, " 2 - 2K");
PrintAndLogEx(NORMAL, " 4 - 4K");
PrintAndLogEx(NORMAL, " d write keys to binary file");
PrintAndLogEx(NORMAL, " t write keys to emulator memory\n");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk 0 A 1234567890ab")" -- target block 0, Key A using key 1234567890ab");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk 0 A mfc_default_keys.dic")" -- target block 0, Key A using default dictionary file");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk *1 ? t")" -- target all blocks, all keys, 1K, write to emulator memory");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mf chk *1 ? d")" -- target all blocks, all keys, 1K, write to file");
return PM3_SUCCESS;
}
static int usage_hf14_chk_fast(void) { static int usage_hf14_chk_fast(void) {
PrintAndLogEx(NORMAL, "This is a improved checkkeys method speedwise. It checks MIFARE Classic tags sector keys against a dictionary file with keys"); PrintAndLogEx(NORMAL, "This is a improved checkkeys method speedwise. It checks MIFARE Classic tags sector keys against a dictionary file with keys");
PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] <card memory> [t|d|f] [<key (12 hex symbols)>] [<dic (*.dic)>]"); PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] <card memory> [t|d|f] [<key (12 hex symbols)>] [<dic (*.dic)>]");
@ -3000,55 +2981,95 @@ out:
} }
static int CmdHF14AMfChk(const char *Cmd) { static int CmdHF14AMfChk(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf chk",
"Check keys on MIFARE Classic card",
"hf mf chk -* --mini --all -k FFFFFFFFFFFF --> Key recovery against MIFARE Mini\n"
"hf mf chk -* --1k --all -k FFFFFFFFFFFF --> Key recovery against MIFARE Classic 1k\n"
"hf mf chk -* --2k --all -k FFFFFFFFFFFF --> Key recovery against MIFARE 2k\n"
"hf mf chk -* --4k --all -k FFFFFFFFFFFF --> Key recovery against MIFARE 4k\n"
"hf mf chk -* --1k --all --emu --> Check all sectors, all keys, 1K, and write to emulator memory\n"
"hf mf chk -* --1k --all --dump --> Check all sectors, all keys, 1K, and write to file\n"
"hf mf chk -a --blk 0 -f mfc_default_keys.dic --> Check dictionary against block 0 key A");
char ctmp = tolower(param_getchar(Cmd, 0)); void *argtable[] = {
if (strlen(Cmd) < 3 || ctmp == 'h') return usage_hf14_chk(); arg_param_begin,
arg_strx0("k", "key", "<hex>", "Key specified as 12 hex symbols"),
arg_int0(NULL, "blk", "<dec>", "Input block number"),
arg_lit0("*", NULL, "Target all blocks"),
arg_lit0("a", NULL, "Input key specified is A key (default)"),
arg_lit0("b", NULL, "Input key specified is B key"),
arg_lit0(NULL, "all", "Target all keys"),
arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50"),
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
arg_lit0(NULL, "dump", "Dump found keys to file"),
arg_str0("f", "file", "<filename>", "filename of dictionary"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
FILE *f; int keylen = 0;
char filename[FILE_PATH_SIZE] = {0}; uint8_t key[255 * 6] = {0};
char buf[13]; CLIGetHexWithReturn(ctx, 1, key, &keylen);
uint8_t *keyBlock, *p;
sector_t *e_sector = NULL; uint8_t blockNo = arg_get_u32_def(ctx, 2, 0);
bool allBlocks = arg_get_lit(ctx, 3);
uint8_t blockNo = 0;
uint8_t SectorsCnt = 1;
uint8_t keyType = 0; uint8_t keyType = 0;
uint32_t keyitems = ARRAYLEN(g_mifare_default_keys);
uint64_t key64 = 0;
int clen = 0;
int transferToEml = 0;
int createDumpFile = 0;
int i, keycnt = 0;
if (param_getchar(Cmd, 0) == '*') { if ((arg_get_lit(ctx, 4) && arg_get_lit(ctx, 5)) || arg_get_lit(ctx, 6)) {
blockNo = 3; keyType = 2;
SectorsCnt = NumOfSectors(param_getchar(Cmd + 1, 0)); } else if (arg_get_lit(ctx, 5)) {
keyType = 1;
}
bool m0 = arg_get_lit(ctx, 7);
bool m1 = arg_get_lit(ctx, 8);
bool m2 = arg_get_lit(ctx, 9);
bool m4 = arg_get_lit(ctx, 10);
bool transferToEml = arg_get_lit(ctx, 11);
bool createDumpFile = arg_get_lit(ctx, 12);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 13), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
//validations
if ((m0 + m1 + m2 + m4) > 1) {
PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
return PM3_EINVARG;
}
uint8_t SectorsCnt = 1;
if (m0) {
SectorsCnt = MIFARE_MINI_MAXSECTOR;
} else if (m1) {
SectorsCnt = MIFARE_1K_MAXSECTOR;
} else if (m2) {
SectorsCnt = MIFARE_2K_MAXSECTOR;
} else if (m4) {
SectorsCnt = MIFARE_4K_MAXSECTOR;
}
if (allBlocks) {
if (SectorsCnt == 0) { if (SectorsCnt == 0) {
return usage_hf14_chk(); PrintAndLogEx(WARNING, "Invalid MIFARE Type");
return PM3_EINVARG;
} }
} else { blockNo = 3;
blockNo = param_get8(Cmd, 0);
}
ctmp = tolower(param_getchar(Cmd, 1));
clen = param_getlength(Cmd, 1);
if (clen == 1) {
switch (ctmp) {
case 'a':
keyType = 0;
break;
case 'b':
keyType = 1;
break;
case '?':
keyType = 2;
break;
default:
PrintAndLogEx(FAILED, "Key type must be A , B or ?");
return PM3_ESOFT;
};
} }
// Handle Keys
int keycnt = 0;
uint32_t keyitems = ARRAYLEN(g_mifare_default_keys);
uint8_t *keyBlock, *p;
// Allocate memory for keys to be tested // Allocate memory for keys to be tested
keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6);
if (keyBlock == NULL) return PM3_EMALLOC; if (keyBlock == NULL) return PM3_EMALLOC;
@ -3057,93 +3078,90 @@ static int CmdHF14AMfChk(const char *Cmd) {
for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) 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)); num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6));
for (i = 2; param_getchar(Cmd, i); i++) { // Handle user supplied key
if (keylen > 6) {
// if (keylen != 6) {
// PrintAndLogEx(WARNING, "Input key must include 12 HEX symbols");
// return PM3_EINVARG;
// }
int numKeys = keylen / 6;
ctmp = tolower(param_getchar(Cmd, i));
clen = param_getlength(Cmd, i);
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++;
}
if (clen == 12) { }
if (param_gethex(Cmd, i, keyBlock + 6 * keycnt, 12)) { // Handle user supplied dictionary file
PrintAndLogEx(FAILED, "not hex, skipping"); 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; continue;
} }
buf[12] = 0;
if (keyitems - keycnt < 2) { if (keyitems - keycnt < 2) {
p = realloc(keyBlock, 6 * (keyitems += 64)); p = realloc(keyBlock, 6 * (keyitems += 64));
if (!p) { if (!p) {
PrintAndLogEx(FAILED, "cannot allocate memory for Keys"); PrintAndLogEx(FAILED, "Cannot allocate memory for defKeys");
free(keyBlock); free(keyBlock);
fclose(f);
return PM3_EMALLOC; return PM3_EMALLOC;
} }
keyBlock = p; keyBlock = p;
} }
PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex((keyBlock + 6 * keycnt), 6)); 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++; keycnt++;
} else if (clen == 1) { memset(buf, 0, sizeof(buf));
if (ctmp == 't') { transferToEml = 1; continue; }
if (ctmp == 'd') { createDumpFile = 1; continue; }
} else {
// May be a dic file
if (param_getstr(Cmd, i, filename, sizeof(filename)) >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "File name too long");
free(keyBlock);
return PM3_EINVARG;
}
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);
} }
fclose(f);
PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_("%s"), keycnt, filename);
} }
uint64_t key64 = 0;
if (keycnt == 0) { if (keycnt == 0) {
PrintAndLogEx(INFO, "No key specified, trying default keys"); PrintAndLogEx(INFO, "No key specified, trying default keys");
for (; keycnt < ARRAYLEN(g_mifare_default_keys); keycnt++) for (; keycnt < ARRAYLEN(g_mifare_default_keys); keycnt++)
@ -3158,6 +3176,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
} }
// create/initialize key storage structure // create/initialize key storage structure
sector_t *e_sector = NULL;
int32_t res = initSectorTable(&e_sector, SectorsCnt); int32_t res = initSectorTable(&e_sector, SectorsCnt);
if (res != SectorsCnt) { if (res != SectorsCnt) {
free(keyBlock); free(keyBlock);
@ -3181,7 +3200,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
// loop sectors but block is used as to keep track of from which blocks to test // loop sectors but block is used as to keep track of from which blocks to test
int b = blockNo; int b = blockNo;
for (i = 0; i < SectorsCnt; ++i) { for (int i = 0; i < SectorsCnt; ++i) {
// skip already found keys. // skip already found keys.
if (e_sector[i].foundKey[trgKeyType]) continue; if (e_sector[i].foundKey[trgKeyType]) continue;
@ -3218,7 +3237,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
// loop sectors but block is used as to keep track of from which blocks to test // loop sectors but block is used as to keep track of from which blocks to test
int b = blockNo; int b = blockNo;
for (i = 0; i < SectorsCnt; i++) { for (int i = 0; i < SectorsCnt; i++) {
// KEY A but not KEY B // KEY A but not KEY B
if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) { if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
@ -3269,7 +3288,7 @@ out:
// fast push mode // fast push mode
conn.block_after_ACK = true; conn.block_after_ACK = true;
uint8_t block[16] = {0x00}; uint8_t block[16] = {0x00};
for (i = 0; i < SectorsCnt; ++i) { for (int i = 0; i < SectorsCnt; ++i) {
uint8_t blockno = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1; uint8_t blockno = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1;
mfEmlGetMem(block, blockno, 1); mfEmlGetMem(block, blockno, 1);

View file

@ -586,7 +586,7 @@ static void show_help(bool showFullHelp, char *exec_name) {
PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -w -- wait for serial port", exec_name); PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -w -- wait for serial port", exec_name);
PrintAndLogEx(NORMAL, " %s -- runs the pm3 client in OFFLINE mode", exec_name); PrintAndLogEx(NORMAL, " %s -- runs the pm3 client in OFFLINE mode", exec_name);
PrintAndLogEx(NORMAL, "\n to execute different commands from terminal:\n"); PrintAndLogEx(NORMAL, "\n to execute different commands from terminal:\n");
PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -c \"hf mf chk 1* ?\" -- execute cmd and quit client", exec_name); PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -c \"hf mf chk --1k -* --all\" -- execute cmd and quit client", exec_name);
PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -l hf_read -- execute lua script " _YELLOW_("`hf_read`")" and quit client", exec_name); PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -l hf_read -- execute lua script " _YELLOW_("`hf_read`")" and quit client", exec_name);
PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -s mycmds.txt -- execute each pm3 cmd in file and quit client", exec_name); PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -s mycmds.txt -- execute each pm3 cmd in file and quit client", exec_name);
PrintAndLogEx(NORMAL, "\n to flash fullimage and bootloader:\n"); PrintAndLogEx(NORMAL, "\n to flash fullimage and bootloader:\n");

View file

@ -224,12 +224,22 @@ Check for default keys
``` ```
Options Options
--- ---
<*card memory> <key type (A/B/?)> [t|d|s|ss] <dic (*.dic)> -h, --help This help
* : all sectors -k, --key <hex> Key specified as 12 hex symbols
card memory : 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K --blk <dec> Input block number
d : write keys to binary file -* Target all blocks
-a Input key specified is A key (default)
-b Input key specified is B key
--all Target all keys
--mini MIFARE Classic Mini / S20
--1k MIFARE Classic 1k / S50
--2k MIFARE Classic/Plus 2k
--4k MIFARE Classic 4k / S70
--emu Fill simulator keys from found keys
--dump Dump found keys to file
-f, --file <filename> filename of dictionary
pm3 --> hf mf chk *1 ? d mfc_default_keys pm3 --> hf mf chk -* --1k --all -f mfc_default_keys
``` ```
Check for default keys from local memory Check for default keys from local memory
@ -315,7 +325,7 @@ pm3 --> hf mf sim -u 353c2aa6
Simulate MIFARE Sequence Simulate MIFARE Sequence
``` ```
pm3 --> hf mf chk *1 ? d mfc_default_keys pm3 --> hf mf chk -* --1k --all -f mfc_default_keys
pm3 --> hf mf dump 1 pm3 --> hf mf dump 1
pm3 --> script run data_mf_bin2eml -i dumpdata.bin pm3 --> script run data_mf_bin2eml -i dumpdata.bin
pm3 --> hf mf eload 353C2AA6 pm3 --> hf mf eload 353C2AA6
@ -324,7 +334,7 @@ pm3 --> hf mf sim -u 353c2aa6
Clone MIFARE 1K Sequence Clone MIFARE 1K Sequence
``` ```
pm3 --> hf mf chk *1 ? d mfc_default_keys pm3 --> hf mf chk -* --1k --all -f mfc_default_keys
pm3 --> hf mf dump pm3 --> hf mf dump
pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-dump.bin pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-dump.bin
``` ```

View file

@ -60,7 +60,6 @@ hf felica litedump
hf mf hardnested hf mf hardnested
hf mf autopwn hf mf autopwn
hf mf nack hf mf nack
hf mf chk
hf mf fchk hf mf fchk
hf mf decrypt hf mf decrypt
hf mf rdbl hf mf rdbl