From eeb62000818372b573f41cca637b546dbf344504 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 7 Feb 2021 13:30:56 -0500 Subject: [PATCH 1/6] hf mf ice - now use cliparser --- client/src/cmdhfmf.c | 82 ++++++++++++++++++------------------------ doc/cliparser_todo.txt | 1 - 2 files changed, 35 insertions(+), 48 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 475c687fb..76d849c05 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -42,18 +42,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf14_ice(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf ice [l ] [f ]"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " l nonces to be collected"); - PrintAndLogEx(NORMAL, " f save nonces to instead of hf-mf--nonces.bin"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf ice")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf ice f nonces.bin")); - return PM3_SUCCESS; -} - static int usage_hf14_dump(void) { PrintAndLogEx(NORMAL, "Usage: hf mf dump [card memory] [k ] [f ]"); PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); @@ -4709,44 +4697,30 @@ static int CmdHf14AMfNack(const char *Cmd) { } static int CmdHF14AMfice(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf ice", + "Collect MIFARE Classic nonces to file", + "hf mf ice\n" + "hf mf ice -f nonces.bin"); - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t trgBlockNo = 0; - uint8_t trgKeyType = 1; - bool slow = false; - bool initialize = true; - bool acquisition_completed = false; - uint8_t cmdp = 0; - uint32_t flags = 0; - uint32_t total_num_nonces = 0; - char ctmp; - char filename[FILE_PATH_SIZE], *fptr; - FILE *fnonces = NULL; - PacketResponseNG resp; + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename of nonce dump"), + arg_u64_0(NULL, "limit", "", "nonces to be collected"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - uint32_t part_limit = 3000; - uint32_t limit = 50000; + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - while ((ctmp = param_getchar(Cmd, cmdp))) { - switch (tolower(ctmp)) { - case 'h': - return usage_hf14_ice(); - case 'f': - param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - cmdp++; - break; - case 'l': - limit = param_get32ex(Cmd, cmdp + 1, 50000, 10); - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp); - usage_hf14_ice(); - return PM3_ESOFT; - } - cmdp++; - } + uint32_t limit = arg_get_u32_def(ctx, 2, 50000); + + CLIParserFree(ctx); + + // Validations + char *fptr; if (filename[0] == '\0') { fptr = GenerateFilename("hf-mf-", "-nonces.bin"); @@ -4756,6 +4730,20 @@ static int CmdHF14AMfice(const char *Cmd) { free(fptr); } + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t trgBlockNo = 0; + uint8_t trgKeyType = 1; + bool slow = false; + bool initialize = true; + bool acquisition_completed = false; + uint32_t flags = 0; + uint32_t total_num_nonces = 0; + FILE *fnonces = NULL; + PacketResponseNG resp; + + uint32_t part_limit = 3000; + PrintAndLogEx(NORMAL, "Collecting "_YELLOW_("%u")" nonces \n", limit); if ((fnonces = fopen(filename, "wb")) == NULL) { diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index c52d35d69..a672d87a9 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -92,7 +92,6 @@ hf mf cview hf mf gen3uid hf mf gen3blk hf mf gen3freeze -hf mf ice lf em 410x lf em 4x05 lf em 4x50 From feb44951244680cb4f8147f11db67a8bbf51bc41 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 7 Feb 2021 15:06:10 -0500 Subject: [PATCH 2/6] hf mf dump - now uses cliparser --- client/luascripts/hf_mf_autopwn.lua | 2 +- client/src/cmdhfmf.c | 95 ++++++++++++++++------------- doc/cheatsheet.md | 19 +++--- doc/cliparser_todo.txt | 1 - 4 files changed, 64 insertions(+), 53 deletions(-) diff --git a/client/luascripts/hf_mf_autopwn.lua b/client/luascripts/hf_mf_autopwn.lua index f7ea2a832..78a701488 100644 --- a/client/luascripts/hf_mf_autopwn.lua +++ b/client/luascripts/hf_mf_autopwn.lua @@ -123,7 +123,7 @@ local function dump_tag(uid, numsectors) local dumpfile = 'hf-mf-'..uid..'-dump' - local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile) + local dmp = ('hf mf dump -t %s -f %s'):format(typ, dumpfile) core.console(dmp) -- Save the global args, those are *our* arguments diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 76d849c05..b0648b3f3 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -42,18 +42,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf14_dump(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf dump [card memory] [k ] [f ]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, " k : key filename, if no given, UID will be used as filename"); - PrintAndLogEx(NORMAL, " f : data filename, if no given, UID will be used as filename"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf dump")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf dump 4")); - return PM3_SUCCESS; -} - static int usage_hf14_mifare(void) { PrintAndLogEx(NORMAL, "Usage: hf mf darkside "); PrintAndLogEx(NORMAL, "Options:"); @@ -650,6 +638,21 @@ static uint8_t NumOfSectors(char card) { } } +static uint8_t NewNumOfSectors(uint8_t card) { + switch (card) { + case 0 : + return MIFARE_MINI_MAXSECTOR; + case 1 : + return MIFARE_1K_MAXSECTOR; + case 2 : + return MIFARE_2K_MAXSECTOR; + case 4 : + return MIFARE_4K_MAXSECTOR; + default : + return 0; + } +} + static uint8_t FirstBlockOfSector(uint8_t sectorNo) { if (sectorNo < 32) { return sectorNo * 4; @@ -942,6 +945,36 @@ static int FastDumpWithEcFill(uint8_t numsectors) { static int CmdHF14AMfDump(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf dump", + "Dump MIFARE Classic tag to binary file\n" + "If no given, UID will be used as filename", + "hf mf dump -t 0 -> MIFARE Mini\n" + "hf mf dump -t 1 -> MIFARE Classic 1k (default)\n" + "hf mf dump -t 2 -> MIFARE 2k\n" + "hf mf dump -t 4 -> MIFARE 4k\n"); + + void *argtable[] = { + arg_param_begin, + arg_int0("t", "type", "<0-4> ", "MIFARE Classic type"), + arg_str0("f", "file", "", "filename of dump"), + arg_str0("k", "keys", "", "filename of keys"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t numSectors = NewNumOfSectors(arg_get_u32_def(ctx, 1, 1)); + + int datafnlen = 0; + char dataFilename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dataFilename, FILE_PATH_SIZE, &datafnlen); + + int keyfnlen = 0; + char keyFilename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen); + + CLIParserFree(ctx); + uint64_t t1 = msclock(); uint8_t sectorNo, blockNo; @@ -949,43 +982,17 @@ static int CmdHF14AMfDump(const char *Cmd) { uint8_t keyB[40][6]; uint8_t rights[40][4]; uint8_t carddata[256][16]; - uint8_t numSectors = 16; - uint8_t cmdp = 0; - - char keyFilename[FILE_PATH_SIZE] = {0}; - char dataFilename[FILE_PATH_SIZE]; - char *fptr; - - memset(keyFilename, 0, sizeof(keyFilename)); - memset(dataFilename, 0, sizeof(dataFilename)); - + FILE *f; PacketResponseNG resp; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf14_dump(); - case 'k': - param_getstr(Cmd, cmdp + 1, keyFilename, FILE_PATH_SIZE); - cmdp += 2; - break; - case 'f': - param_getstr(Cmd, cmdp + 1, dataFilename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - if (cmdp == 0) { - numSectors = NumOfSectors(param_getchar(Cmd, cmdp)); - if (numSectors == 0) return usage_hf14_dump(); - cmdp++; - } else { - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - return usage_hf14_dump(); - } - } + if (numSectors == 0) { + PrintAndLogEx(ERR, "Invalid MIFARE Classic type"); + return PM3_EINVARG; } + char *fptr; + if (keyFilename[0] == 0x00) { fptr = GenerateFilename("hf-mf-", "-key.bin"); if (fptr == NULL) diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 1220bf173..27e893fd3 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -244,14 +244,19 @@ pm3 --> hf mf fchk 1 m Dump MIFARE card contents ``` -Options ---- - : 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K -k : key filename, if no given, UID will be used as filename" -f : data filename, if no given, UID will be used as filename +options: + -t, --type <0-4> MIFARE Classic type + -f, --file filename of dump + -k, --keys filename of keys -pm3 --> hf mf dump 1 -pm3 --> hf mf dump 1 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-dump.bin +examples/notes: + hf mf dump -t 0 -> MIFARE Mini + hf mf dump -t 1 -> MIFARE Classic 1k (default) + hf mf dump -t 2 -> MIFARE 2k + hf mf dump -t 4 -> MIFARE 4k + +pm3 --> hf mf dump -t 1 +pm3 --> hf mf dump -t 1 -k hf-mf-A29558E4-key.bin -f hf-mf-A29558E4-dump.bin ``` Convert .bin to .eml diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index a672d87a9..5d974b637 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -66,7 +66,6 @@ hf mf nack hf mf chk hf mf fchk hf mf decrypt -hf mf dump hf mf rdbl hf mf rdsc hf mf restore From 23de2777c137a979a8990fa3c680087eb9ee19e8 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 7 Feb 2021 15:20:16 -0500 Subject: [PATCH 3/6] hf mf darkside - now use cliparser --- client/src/cmdhfmf.c | 40 +++++++++++++++++++++------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index b0648b3f3..dfcf7e47e 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -42,18 +42,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf14_mifare(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf darkside "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " (Optional) target other block"); - PrintAndLogEx(NORMAL, " (optional) target key type"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf darkside")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf darkside 16")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf darkside 16 B")); - return PM3_SUCCESS; -} static int usage_hf14_mfsim(void) { PrintAndLogEx(NORMAL, "Usage: hf mf sim [u ] [n ] [t] [a ] [s ] [i] [x] [e] [v]"); PrintAndLogEx(NORMAL, "Options:"); @@ -692,17 +680,31 @@ static char GetFormatFromSector(uint8_t sectorNo) { } static int CmdHF14AMfDarkside(const char *Cmd) { - uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA; - uint64_t key = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf darkside", + "Darkside attack", + "hf mf darkside\n" + "hf mf darkside -b 16\n" + "hf mf darkside -b 16 --keyb\n"); - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf14_mifare(); + void *argtable[] = { + arg_param_begin, + arg_int0("b", "block", " ", "Simulation type to use"), + arg_lit0(NULL, "keyb", "Target key B instead of default key A"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - blockno = param_get8(Cmd, 0); + uint8_t blockno = arg_get_u32_def(ctx, 1, 0); - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp == 'b') + uint8_t key_type = MIFARE_AUTH_KEYA; + + if (arg_get_lit(ctx, 2)) { + PrintAndLogEx(INFO, "Targeting key B"); key_type = MIFARE_AUTH_KEYB; + } + + uint64_t key = 0; int isOK = mfDarkside(blockno, key_type, &key); PrintAndLogEx(NORMAL, ""); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 5d974b637..727802ef2 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -57,7 +57,6 @@ hf felica rqspecver hf felica resetmode hf felica litesim hf felica litedump -hf mf darkside hf mf nested hf mf hardnested hf mf staticnested From c04556e69e17ee4b65abcfed7bd0525e53cba54e Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 7 Feb 2021 16:15:22 -0500 Subject: [PATCH 4/6] hf mf sim - now use cliparser --- client/gen_pm3mfsim_script.sh | 2 +- client/luascripts/hf_mf_tnp3_sim.lua | 2 +- client/src/cmdhfmf.c | 252 +++++++++++++-------------- doc/cheatsheet.md | 4 +- doc/cliparser_todo.txt | 1 - 5 files changed, 121 insertions(+), 140 deletions(-) diff --git a/client/gen_pm3mfsim_script.sh b/client/gen_pm3mfsim_script.sh index c3726d69c..14cb37909 100644 --- a/client/gen_pm3mfsim_script.sh +++ b/client/gen_pm3mfsim_script.sh @@ -32,4 +32,4 @@ rm $2 echo "hf mf eclr" >> $2 echo "hf mf eload" $1 >> $2 echo "hf mf ekeyprn" >> $2 -echo "hf mf sim u" `cat $1.eml | (read -n 8 uid; echo $uid)` >> $2 \ No newline at end of file +echo "hf mf sim -u" `cat $1.eml | (read -n 8 uid; echo $uid)` >> $2 \ No newline at end of file diff --git a/client/luascripts/hf_mf_tnp3_sim.lua b/client/luascripts/hf_mf_tnp3_sim.lua index dded9327a..33f82b2d4 100644 --- a/client/luascripts/hf_mf_tnp3_sim.lua +++ b/client/luascripts/hf_mf_tnp3_sim.lua @@ -496,7 +496,7 @@ local function main(args) err = LoadEmulator(uid, blocks) if err then return oops(err) end core.clearCommandBuffer() - print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--') + print('The simulation is now prepared.\n --> run \"hf mf sim -u '..uid..'\" <--') end end main(args) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index dfcf7e47e..0b40120a1 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -42,30 +42,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf14_mfsim(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf sim [u ] [n ] [t] [a ] [s ] [i] [x] [e] [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b/7b from emulator memory will be used"); - PrintAndLogEx(NORMAL, " t (Optional) Enforce ATQA/SAK:"); - PrintAndLogEx(NORMAL, " 0 = MIFARE Mini"); - PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 1k (Default)"); - PrintAndLogEx(NORMAL, " 2 = MIFARE Classic 2k plus in SL0 mode"); - PrintAndLogEx(NORMAL, " 4 = MIFARE Classic 4k"); - PrintAndLogEx(NORMAL, " a (Optional) Provide explicitly ATQA (2 bytes, override option t)"); - PrintAndLogEx(NORMAL, " s (Optional) Provide explicitly SAK (1 byte, override option t)"); - PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after blocks have been read by reader. 0 = infinite"); - PrintAndLogEx(NORMAL, " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); - PrintAndLogEx(NORMAL, " x (Optional) Crack, performs the 'reader attack', nr/ar attack against a reader"); - PrintAndLogEx(NORMAL, " e (Optional) Fill simulator keys from found keys"); - PrintAndLogEx(NORMAL, " v (Optional) Verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf sim u 0a0a0a0a")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf sim u 11223344556677")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf sim u 112233445566778899AA")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf sim u 11223344 i x")); - return PM3_SUCCESS; -} /* * static int usage_hf14_sniff(void) { PrintAndLogEx(NORMAL, "It continuously gets data from the field and saves it to: log, emulator, emulator file."); @@ -946,7 +922,6 @@ static int FastDumpWithEcFill(uint8_t numsectors) { } static int CmdHF14AMfDump(const char *Cmd) { - CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf dump", "Dump MIFARE Classic tag to binary file\n" @@ -3376,125 +3351,132 @@ void readerAttack(sector_t *k_sector, uint8_t k_sectorsCount, nonces_t data, boo } static int CmdHF14AMfSim(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf sim", + "Simulate MIFARE card", + "hf mf sim -t 0 -> MIFARE Mini\n" + "hf mf sim -t 1 -> MIFARE Classic 1k (default)\n" + "hf mf sim -t 1 -u 0a0a0a0a -> MIFARE Classic 1k with 4b UID\n" + "hf mf sim -t 1 -u 11223344556677 -> MIFARE Classic 1k with 7b UID\n" + "hf mf sim -t 1 -u 11223344 -i --crack -> Perform reader attack in interactive mode\n" + "hf mf sim -t 2 -> MIFARE 2k\n" + "hf mf sim -t 4 -> MIFARE 4k"); + + void *argtable[] = { + arg_param_begin, + arg_str0("u", "uid", "", "UID 4,7 or 10bytes. If not specified, the UID 4b/7b from emulator memory will be used"), + arg_int0("t", "type", "<0-4> ", "MIFARE Classic type for ATQA/SAK"), + arg_str0(NULL, "atqa", "", "Provide explicit ATQA (2 bytes, overrides option t)"), + arg_str0(NULL, "sak", "", "Provide explicit SAK (1 bytes, overrides option t)"), + arg_int0("n", "num", " ", "Automatically exit simulation after blocks have been read by reader. 0 = infinite"), + arg_lit0("i", "interactive", "Console will not be returned until simulation finishes or is aborted"), + arg_lit0(NULL, "crack", "Performs the 'reader attack', nr/ar attack against a reader"), + arg_lit0("e", "emukeys", "Fill simulator keys from found keys"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t atqa[2] = {0, 0}; - int atqalen = 0; - uint8_t sak[1] = {0}; - int saklen = 0; - uint8_t exitAfterNReads = 0; uint16_t flags = 0; - int uidlen = 0; - uint8_t cmdp = 0; - bool errors = false, verbose = false, setEmulatorMem = false; - nonces_t data[1]; - char csize[13] = { 0 }; - char uidsize[8] = { 0 }; - sector_t *k_sector = NULL; - uint8_t k_sectorsCount = 40; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'e': - setEmulatorMem = true; - cmdp++; + int uidlen = 0; + uint8_t uid[10] = {0}; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + + char uidsize[8] = {0}; + if (uidlen > 0) { + switch (uidlen) { + case 10: + flags |= FLAG_10B_UID_IN_DATA; + snprintf(uidsize, sizeof(uidsize), "10 byte"); break; - case 'h': - return usage_hf14_mfsim(); - case 'i': - flags |= FLAG_INTERACTIVE; - cmdp++; + case 7: + flags |= FLAG_7B_UID_IN_DATA; + snprintf(uidsize, sizeof(uidsize), "7 byte"); break; - case 'n': - exitAfterNReads = param_get8(Cmd, cmdp + 1); - cmdp += 2; - break; - case 't': - switch (param_get8(Cmd, cmdp + 1)) { - case 0: - flags |= FLAG_MF_MINI; - snprintf(csize, sizeof(csize), "MINI"); - k_sectorsCount = MIFARE_MINI_MAXSECTOR; - break; - case 1: - flags |= FLAG_MF_1K; - snprintf(csize, sizeof(csize), "1K"); - k_sectorsCount = MIFARE_1K_MAXSECTOR; - break; - case 2: - flags |= FLAG_MF_2K; - snprintf(csize, sizeof(csize), "2K with RATS"); - k_sectorsCount = MIFARE_2K_MAXSECTOR; - break; - case 4: - flags |= FLAG_MF_4K; - snprintf(csize, sizeof(csize), "4K"); - k_sectorsCount = MIFARE_4K_MAXSECTOR; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter for option t"); - errors = true; - break; - } - cmdp += 2; - break; - case 'a': - param_gethex_ex(Cmd, cmdp + 1, atqa, &atqalen); - if (atqalen >> 1 != 2) { - PrintAndLogEx(WARNING, "Wrong ATQA length"); - errors = true; - break; - } - flags |= FLAG_FORCED_ATQA; - cmdp += 2; - break; - case 's': - param_gethex_ex(Cmd, cmdp + 1, sak, &saklen); - if (saklen >> 1 != 1) { - PrintAndLogEx(WARNING, "Wrong SAK length"); - errors = true; - break; - } - flags |= FLAG_FORCED_SAK; - cmdp += 2; - break; - case 'u': - param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen); - uidlen >>= 1; - switch (uidlen) { - case 10: - flags |= FLAG_10B_UID_IN_DATA; - snprintf(uidsize, sizeof(uidsize), "10 byte"); - break; - case 7: - flags |= FLAG_7B_UID_IN_DATA; - snprintf(uidsize, sizeof(uidsize), "7 byte"); - break; - case 4: - flags |= FLAG_4B_UID_IN_DATA; - snprintf(uidsize, sizeof(uidsize), "4 byte"); - break; - default: - return usage_hf14_mfsim(); - } - cmdp += 2; - break; - case 'v': - verbose = true; - cmdp++; - break; - case 'x': - flags |= FLAG_NR_AR_ATTACK; - cmdp++; + case 4: + flags |= FLAG_4B_UID_IN_DATA; + snprintf(uidsize, sizeof(uidsize), "4 byte"); break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; + PrintAndLogEx(WARNING, "Invalid parameter for UID"); + return PM3_EINVARG; } } + + uint8_t k_sectorsCount = 40; + char csize[13] = { 0 }; + + switch (arg_get_u32_def(ctx, 2, 1)) { + case 0: + flags |= FLAG_MF_MINI; + snprintf(csize, sizeof(csize), "MINI"); + k_sectorsCount = MIFARE_MINI_MAXSECTOR; + break; + case 1: + flags |= FLAG_MF_1K; + snprintf(csize, sizeof(csize), "1K"); + k_sectorsCount = MIFARE_1K_MAXSECTOR; + break; + case 2: + flags |= FLAG_MF_2K; + snprintf(csize, sizeof(csize), "2K with RATS"); + k_sectorsCount = MIFARE_2K_MAXSECTOR; + break; + case 4: + flags |= FLAG_MF_4K; + snprintf(csize, sizeof(csize), "4K"); + k_sectorsCount = MIFARE_4K_MAXSECTOR; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter for option t"); + return PM3_EINVARG; + } + + int atqalen = 0; + uint8_t atqa[2] = {0}; + CLIGetHexWithReturn(ctx, 3, atqa, &atqalen); + + int saklen = 0; + uint8_t sak[1] = {0}; + CLIGetHexWithReturn(ctx, 4, sak, &saklen); + + uint8_t exitAfterNReads = arg_get_u32_def(ctx, 5, 0); + + if (arg_get_lit(ctx, 6)) { + flags |= FLAG_INTERACTIVE; + } + + if (arg_get_lit(ctx, 7)) { + flags |= FLAG_NR_AR_ATTACK; + } + + bool setEmulatorMem = arg_get_lit(ctx, 8); + bool verbose = arg_get_lit(ctx, 9); + + CLIParserFree(ctx); + + nonces_t data[1]; + + sector_t *k_sector = NULL; + //Validations - if (errors) return usage_hf14_mfsim(); + if (atqalen > 0) { + if (atqalen != 2) { + PrintAndLogEx(WARNING, "Wrong ATQA length"); + return PM3_EINVARG; + + } + flags |= FLAG_FORCED_ATQA; + } + if (saklen > 0) { + if (saklen != 1) { + PrintAndLogEx(WARNING, "Wrong SAK length"); + return PM3_EINVARG; + + } + flags |= FLAG_FORCED_SAK; + } // Use UID, SAK, ATQA from EMUL, if uid not defined if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) { @@ -3834,7 +3816,7 @@ int CmdHF14AMfELoad(const char *Cmd) { return PM3_SUCCESS; } } else { - PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mf sim h`")); + PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mf sim -h`")); // MFC if ((blockNum != numBlocks)) { PrintAndLogEx(WARNING, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", blockNum, numBlocks); diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 27e893fd3..ef511bd85 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -310,7 +310,7 @@ Simulate MIFARE ``` u : (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used -pm3 --> hf mf sim u 353c2aa6 +pm3 --> hf mf sim -u 353c2aa6 ``` Simulate MIFARE Sequence @@ -319,7 +319,7 @@ pm3 --> hf mf chk *1 ? d mfc_default_keys pm3 --> hf mf dump 1 pm3 --> script run data_mf_bin2eml -i dumpdata.bin pm3 --> hf mf eload 353C2AA6 -pm3 --> hf mf sim u 353c2aa6 +pm3 --> hf mf sim -u 353c2aa6 ``` Clone MIFARE 1K Sequence diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 727802ef2..4bf56ab82 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -70,7 +70,6 @@ hf mf rdsc hf mf restore hf mf setmod hf mf wrbl -hf mf sim hf mf ecfill hf mf eclr hf mf egetblk From a82a71b4c879c367e9a3ce1a251818137f594ba7 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 7 Feb 2021 17:32:25 -0500 Subject: [PATCH 5/6] hf mf nested - now use cliparser --- client/luascripts/hf_mf_autopwn.lua | 2 +- client/luascripts/hf_mf_tnp3_dump.lua | 2 +- client/src/cmdhfmf.c | 129 ++++++++++++++------------ doc/cliparser_todo.txt | 1 - 4 files changed, 71 insertions(+), 63 deletions(-) diff --git a/client/luascripts/hf_mf_autopwn.lua b/client/luascripts/hf_mf_autopwn.lua index 78a701488..029d16d7a 100644 --- a/client/luascripts/hf_mf_autopwn.lua +++ b/client/luascripts/hf_mf_autopwn.lua @@ -99,7 +99,7 @@ local function nested(key,sak) else print("I don't know how many sectors there are on this type of card, defaulting to 16") end - local cmd = string.format('hf mf nested %d 0 A %s d', typ, key) + local cmd = string.format('hf mf nested -t %d -b 0 --keya -k %s --dumpkeys', typ, key) core.console(cmd) end diff --git a/client/luascripts/hf_mf_tnp3_dump.lua b/client/luascripts/hf_mf_tnp3_dump.lua index ee59046eb..54a19da82 100644 --- a/client/luascripts/hf_mf_tnp3_dump.lua +++ b/client/luascripts/hf_mf_tnp3_dump.lua @@ -147,7 +147,7 @@ local function main(args) --Trying to find the other keys if useNested then - core.console( ('hf mf nested 1 0 A %s d'):format(keyA) ) + core.console( ('hf mf nested -t 1 -b 0 --keya -k %s --dumpkeys'):format(keyA) ) end core.clearCommandBuffer() diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 0b40120a1..0007c44e5 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -57,23 +57,6 @@ static int CmdHelp(const char *Cmd); return PM3_SUCCESS; } */ -static int usage_hf14_nested(void) { - PrintAndLogEx(NORMAL, "Usage:"); - PrintAndLogEx(NORMAL, " all sectors: hf mf nested [t,d]"); - PrintAndLogEx(NORMAL, " one sector: hf mf nested o [t]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLogEx(NORMAL, " t transfer keys into emulator memory"); - PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf nested 1 0 A FFFFFFFFFFFF")" -- key recovery against 1K, block 0, Key A using key FFFFFFFFFFFF"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf nested 1 0 A FFFFFFFFFFFF t")" -- and transfer keys into emulator memory"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf nested 1 0 A FFFFFFFFFFFF d")" -- or write keys to binary file "); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf nested o 0 A FFFFFFFFFFFF 4 A")" -- one sector key recovery. Use block 0 Key A to find block 4 Key A"); - return PM3_SUCCESS; -} static int usage_hf14_staticnested(void) { PrintAndLogEx(NORMAL, "Usage:"); PrintAndLogEx(NORMAL, " all sectors: hf mf staticnested [t,d]"); @@ -680,6 +663,8 @@ static int CmdHF14AMfDarkside(const char *Cmd) { key_type = MIFARE_AUTH_KEYB; } + CLIParserFree(ctx); + uint64_t key = 0; int isOK = mfDarkside(blockno, key_type, &key); @@ -1294,62 +1279,86 @@ static int CmdHF14AMfRestore(const char *Cmd) { } static int CmdHF14AMfNested(const char *Cmd) { - sector_t *e_sector = NULL; - uint8_t keyType = 0; - uint8_t trgBlockNo = 0; - uint8_t trgKeyType = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf nested", + "Execute Nested attack against MIFARE Classic card for key recovery", + "hf mf nested -t 0 -b 0 --keya -k FFFFFFFFFFFF -> Key recovery against MIFARE Mini\n" + "hf mf nested -t 1 -b 0 --keya -k FFFFFFFFFFFF -> Key recovery against MIFARE Classic 1k\n" + "hf mf nested -t 2 -b 0 --keya -k FFFFFFFFFFFF -> Key recovery against MIFARE 2k\n" + "hf mf nested -t 4 -b 0 --keya -k FFFFFFFFFFFF -> Key recovery against MIFARE 4k\n" + "hf mf nested --single -b 0 --keya FFFFFFFFFFFF --tblock 4 --tkeya -> Single sector key recovery. Use block 0 Key A to find block 4 Key A"); + + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "Key specified as 12 hex symbols"), + arg_int0("t", "type", "<0-4>", "MIFARE Classic type"), + arg_int0("b", "block", "", "Input block number"), + arg_lit0(NULL, "keya", "Input key specified is A key (default)"), + arg_lit0(NULL, "keyb", "Input key specified is B key"), + arg_int0(NULL, "tblock", "", "Target block number"), + arg_lit0(NULL, "tkeya", "Target A key (default)"), + arg_lit0(NULL, "tkeyb", "Target B key"), + arg_lit0("e", "emukeys", "Fill simulator keys from found keys"), + arg_lit0(NULL, "dumpkeys", "Dump found keys to file"), + arg_lit0(NULL, "single", "Single sector (defaults to All)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 1, key, &keylen); + uint8_t SectorsCnt = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6]; - uint64_t key64 = 0; - bool transferToEml = false; - bool createDumpFile = false; + SectorsCnt = NewNumOfSectors(arg_get_u32_def(ctx, 2, 1)); - if (strlen(Cmd) < 3) return usage_hf14_nested(); + uint8_t blockNo = arg_get_u32_def(ctx, 3, 0); - char cmdp, ctmp; - cmdp = tolower(param_getchar(Cmd, 0)); - uint8_t blockNo = param_get8(Cmd, 1); - ctmp = tolower(param_getchar(Cmd, 2)); + uint8_t keyType = 0; - if (ctmp != 'a' && ctmp != 'b') { - PrintAndLogEx(WARNING, "key type must be A or B"); + if (arg_get_lit(ctx, 4) && arg_get_lit(ctx, 5)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); return PM3_EINVARG; - } - - if (ctmp != 'a') + } else if (arg_get_lit(ctx, 5)) { keyType = 1; - - if (param_gethex(Cmd, 3, key, 12)) { - PrintAndLogEx(WARNING, "key must include 12 HEX symbols"); - return PM3_EINVARG; } - if (cmdp == 'o') { - trgBlockNo = param_get8(Cmd, 4); - ctmp = tolower(param_getchar(Cmd, 5)); - if (ctmp != 'a' && ctmp != 'b') { - PrintAndLogEx(WARNING, "target key type must be A or B"); + uint8_t trgBlockNo = arg_get_u32_def(ctx, 6, 0); + + uint8_t trgKeyType = 0; + + if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Target key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 7)) { + trgKeyType = 1; + } + + bool transferToEml = arg_get_lit(ctx, 9); + bool createDumpFile = arg_get_lit(ctx, 10); + bool singleSector = arg_get_lit(ctx, 11); + + CLIParserFree(ctx); + + //validations + if (singleSector == false) { + if (SectorsCnt == 0) { + PrintAndLogEx(WARNING, "Invalid MIFARE Type"); return PM3_EINVARG; } - if (ctmp != 'a') { - trgKeyType = 1; - } - } else { - SectorsCnt = NumOfSectors(cmdp); - if (SectorsCnt == 0) return usage_hf14_nested(); } - uint8_t j = 4; - while (ctmp != 0x00) { - - ctmp = tolower(param_getchar(Cmd, j)); - transferToEml |= (ctmp == 't'); - createDumpFile |= (ctmp == 'd'); - - j++; + if (keylen != 6) { + PrintAndLogEx(WARNING, "Input key must include 12 HEX symbols"); + return PM3_EINVARG; } + sector_t *e_sector = NULL; + uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6]; + uint64_t key64 = 0; + // check if tag doesn't have static nonce if (detect_classic_static_nonce() == NONCE_STATIC) { PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); @@ -1363,7 +1372,7 @@ static int CmdHF14AMfNested(const char *Cmd) { return PM3_EOPABORTED; } - if (cmdp == 'o') { + if (singleSector) { int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true); switch (isOK) { case PM3_ETIMEOUT: diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 4bf56ab82..f3b0d7061 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -57,7 +57,6 @@ hf felica rqspecver hf felica resetmode hf felica litesim hf felica litedump -hf mf nested hf mf hardnested hf mf staticnested hf mf autopwn From 9da310bb3640d63569785a6ac57a5df4a5d2f974 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 7 Feb 2021 17:49:45 -0500 Subject: [PATCH 6/6] hf mf staticnested - now use cliparser --- client/src/cmdhfmf.c | 113 +++++++++++++++++++++-------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 58 insertions(+), 56 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 0007c44e5..f5ef352b1 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -57,21 +57,6 @@ static int CmdHelp(const char *Cmd); return PM3_SUCCESS; } */ -static int usage_hf14_staticnested(void) { - PrintAndLogEx(NORMAL, "Usage:"); - PrintAndLogEx(NORMAL, " all sectors: hf mf staticnested [t,d]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLogEx(NORMAL, " t transfer keys into emulator memory"); - PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf staticnested 1 0 A FFFFFFFFFFFF")" -- key recovery against 1K, block 0, Key A using key FFFFFFFFFFFF"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf staticnested 1 0 A FFFFFFFFFFFF t")" -- and transfer keys into emulator memory"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf staticnested 1 0 A FFFFFFFFFFFF d")" -- or write keys to binary file "); - return PM3_SUCCESS; -} static int usage_hf14_hardnested(void) { PrintAndLogEx(NORMAL, "Usage:"); PrintAndLogEx(NORMAL, " hf mf hardnested "); @@ -1309,8 +1294,7 @@ static int CmdHF14AMfNested(const char *Cmd) { uint8_t key[6] = {0}; CLIGetHexWithReturn(ctx, 1, key, &keylen); - uint8_t SectorsCnt = 0; - SectorsCnt = NewNumOfSectors(arg_get_u32_def(ctx, 2, 1)); + uint8_t SectorsCnt = NewNumOfSectors(arg_get_u32_def(ctx, 2, 1)); uint8_t blockNo = arg_get_u32_def(ctx, 3, 0); @@ -1568,48 +1552,67 @@ jumptoend: } static int CmdHF14AMfNestedStatic(const char *Cmd) { - sector_t *e_sector = NULL; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf staticnested", + "Execute Nested attack against MIFARE Classic card with static nonce for key recovery", + "hf mf staticnested -t 0 -b 0 --keya -k FFFFFFFFFFFF -> Key recovery against MIFARE Mini\n" + "hf mf staticnested -t 1 -b 0 --keya -k FFFFFFFFFFFF -> Key recovery against MIFARE Classic 1k\n" + "hf mf staticnested -t 2 -b 0 --keya -k FFFFFFFFFFFF -> Key recovery against MIFARE 2k\n" + "hf mf staticnested -t 4 -b 0 --keya -k FFFFFFFFFFFF -> Key recovery against MIFARE 4k\n"); + + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "Key specified as 12 hex symbols"), + arg_int0("t", "type", "<0-4>", "MIFARE Classic type"), + arg_int0("b", "block", "", "Input block number"), + arg_lit0(NULL, "keya", "Input key specified is A key (default)"), + arg_lit0(NULL, "keyb", "Input key specified is B key"), + arg_lit0("e", "emukeys", "Fill simulator keys from found keys"), + arg_lit0(NULL, "dumpkeys", "Dump found keys to file"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 1, key, &keylen); + + uint8_t SectorsCnt = NewNumOfSectors(arg_get_u32_def(ctx, 2, 1)); + + uint8_t blockNo = arg_get_u32_def(ctx, 3, 0); + uint8_t keyType = 0; + + if (arg_get_lit(ctx, 4) && arg_get_lit(ctx, 5)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 5)) { + keyType = 1; + } + + bool transferToEml = arg_get_lit(ctx, 6); + bool createDumpFile = arg_get_lit(ctx, 7); + + CLIParserFree(ctx); + + //validations + if (SectorsCnt == 0) { + PrintAndLogEx(WARNING, "Invalid MIFARE Type"); + return PM3_EINVARG; + } + + if (keylen != 6) { + PrintAndLogEx(WARNING, "Input key must include 12 HEX symbols"); + return PM3_EINVARG; + } + + sector_t *e_sector = NULL; + uint8_t trgKeyType = 0; - uint8_t SectorsCnt = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6]; uint64_t key64 = 0; - bool transferToEml = false; - bool createDumpFile = false; - - if (strlen(Cmd) < 3) return usage_hf14_staticnested(); - - char cmdp, ctmp; - cmdp = tolower(param_getchar(Cmd, 0)); - uint8_t blockNo = param_get8(Cmd, 1); - ctmp = tolower(param_getchar(Cmd, 2)); - - if (ctmp != 'a' && ctmp != 'b') { - PrintAndLogEx(WARNING, "key type must be A or B"); - return PM3_EINVARG; - } - - if (ctmp != 'a') - keyType = 1; - - if (param_gethex(Cmd, 3, key, 12)) { - PrintAndLogEx(WARNING, "key must include 12 HEX symbols"); - return PM3_EINVARG; - } - - SectorsCnt = NumOfSectors(cmdp); - if (SectorsCnt == 0) return usage_hf14_staticnested(); - - uint8_t j = 4; - while (ctmp != 0x00) { - - ctmp = tolower(param_getchar(Cmd, j)); - transferToEml |= (ctmp == 't'); - createDumpFile |= (ctmp == 'd'); - - j++; - } // check if tag have static nonce if (detect_classic_static_nonce() != NONCE_STATIC) { diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index f3b0d7061..368afa836 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -58,7 +58,6 @@ hf felica resetmode hf felica litesim hf felica litedump hf mf hardnested -hf mf staticnested hf mf autopwn hf mf nack hf mf chk