From 71cf7da4c2b00cfe48173039c828ed5cfa834169 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 1 Nov 2020 20:10:13 -0500 Subject: [PATCH 1/4] hf iclass eload - now uses cliparser --- client/src/cmdhficlass.c | 69 +++++++++++++++------------------------- doc/cheatsheet.md | 4 +-- 2 files changed, 27 insertions(+), 46 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 00c0010b2..44592aca2 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -66,22 +66,12 @@ static int usage_hf_iclass_sim(void) { PrintAndLogEx(NORMAL, " -- execute loclass attack online part"); PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass sim 2")); PrintAndLogEx(NORMAL, " -- simulate full iCLASS 2k tag"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass eload f hf-iclass-AA162D30F8FF12F1-dump.bin")); + PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin")); PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass sim 3")); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_eload(void) { - PrintAndLogEx(NORMAL, "Loads iCLASS tag dump into emulator memory on device\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass eload [h] f \n"); - PrintAndLogEx(NORMAL, "Options"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " f : filename of dump"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass eload f hf-iclass-AA162D30F8FF12F1-dump.bin")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} + static int usage_hf_iclass_esave(void) { PrintAndLogEx(NORMAL, "Save emulator memory to file."); PrintAndLogEx(NORMAL, "if not filename is supplied, CSN will be used."); @@ -884,42 +874,33 @@ static int CmdHFiClassReader(const char *Cmd) { } static int CmdHFiClassELoad(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass eload", + "Loads iCLASS tag dump into emulator memory on device", + "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin\n"); + + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "filename of dump"), + arg_lit0(NULL, "json", "print from this block (default block6)"), + arg_lit0(NULL, "eml", "end printing at this block (default 0, ALL)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); DumpFileType_t dftype = BIN; - char filename[FILE_PATH_SIZE] = {0}; - bool errors = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_eload(); - case 'f': - if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - cmdp += 2; - break; - case 'j': - dftype = JSON; - cmdp++; - break; - case 'e': - dftype = EML; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + + if (arg_get_lit(ctx, 2)) { + dftype = JSON; + } else if (arg_get_lit(ctx, 3)) { + dftype = EML; } - //Validations - if (errors || cmdp == 0) { - return usage_hf_iclass_eload(); - } + CLIParserFree(ctx); uint8_t *dump = calloc(2048, sizeof(uint8_t)); if (!dump) { diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index a239b6af4..234c39ffb 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -135,7 +135,7 @@ Options --- f : load iCLASS tag-dump filename -pm3 --> hf iclass eload f hf-iclass-db883702f8ff12e0.bin +pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin ``` Clone iCLASS Legacy Sequence @@ -160,7 +160,7 @@ pm3 --> hf iclass sim 3 Simulate iCLASS Sequence ``` pm3 --> hf iclass dump k 0 -pm3 --> hf iclass eload f hf-iclass-db883702f8ff12e0.bin +pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin pm3 --> hf iclass sim 3 ``` From 2648ed035474a59096f7a776589113c228ecb33d Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 1 Nov 2020 20:15:32 -0500 Subject: [PATCH 2/4] update eload argument text --- client/src/cmdhficlass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 44592aca2..d2b7045a6 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -882,8 +882,8 @@ static int CmdHFiClassELoad(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str1("f", "file", "", "filename of dump"), - arg_lit0(NULL, "json", "print from this block (default block6)"), - arg_lit0(NULL, "eml", "end printing at this block (default 0, ALL)"), + arg_lit0(NULL, "json", "load JSON type dump"), + arg_lit0(NULL, "eml", "load EML type dump"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); From 9ec126a80b39cb5c4f6bbe5cbcb047212c32c745 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 1 Nov 2020 20:58:14 -0500 Subject: [PATCH 3/4] hf iclass loclass - now uses cliparser --- client/src/cmdhficlass.c | 67 +++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index d2b7045a6..f0c4c0f43 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -262,27 +262,6 @@ static int usage_hf_iclass_managekeys(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_loclass(void) { - PrintAndLogEx(NORMAL, "Execute the offline part of loclass attack"); - PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of"); - PrintAndLogEx(NORMAL, " malicious CSNs, and their protocol responses"); - PrintAndLogEx(NORMAL, " The binary format of the file is expected to be as follows: "); - PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); - PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); - PrintAndLogEx(NORMAL, " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); - PrintAndLogEx(NORMAL, " ... totalling N*24 bytes\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass loclass [h] [t [l]] [f ]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h Show this help"); - PrintAndLogEx(NORMAL, " t Perform self-test"); - PrintAndLogEx(NORMAL, " t l Perform self-test, including long ones"); - PrintAndLogEx(NORMAL, " f Bruteforce iclass dumpfile"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass loclass f iclass-dump.bin")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass loclass t")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_chk(void) { PrintAndLogEx(NORMAL, "Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass chk [h|e|r] [f (*.dic)]\n"); @@ -2306,26 +2285,42 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { } static int CmdHFiClass_loclass(const char *Cmd) { - char opt = tolower(param_getchar(Cmd, 0)); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass loclass", + "Execute the offline part of loclass attack\n" + " An iclass dumpfile is assumed to consist of an arbitrary number of\n" + " malicious CSNs, and their protocol responses\n" + " The binary format of the file is expected to be as follows: \n" + " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>\n" + " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>\n" + " <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>\n" + " ... totalling N*24 bytes", + "hf iclass loclass -f iclass-dump.bin\n" + "hf iclass loclass --test"); - if (strlen(Cmd) < 1 || opt == 'h') - return usage_hf_iclass_loclass(); + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename of Bruteforce iclass dumpfile"), + arg_lit0(NULL, "test", "Perform self-test"), + arg_lit0(NULL, "long", "Perform self-test, including long ones"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - if (opt == 'f') { - char fileName[FILE_PATH_SIZE] = {0}; - if (param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0) { - return bruteforceFileNoKeys(fileName); - } else { - PrintAndLogEx(WARNING, "You must specify a filename"); - return PM3_EFILE; - } - } else if (opt == 't') { - char opt2 = tolower(param_getchar(Cmd, 1)); + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + bool test = arg_get_lit(ctx, 2); + bool longtest = arg_get_lit(ctx, 3); + + CLIParserFree(ctx); + + if (test || longtest) { int errors = testCipherUtils(); errors += testMAC(); errors += doKeyTests(); - errors += testElite(opt2 == 'l'); + errors += testElite(longtest); if (errors != PM3_SUCCESS) PrintAndLogEx(ERR, "There were errors!!!"); @@ -2333,7 +2328,7 @@ static int CmdHFiClass_loclass(const char *Cmd) { return PM3_ESOFT; } - return usage_hf_iclass_loclass(); + return bruteforceFileNoKeys(filename); } void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) { From 4c333ff02f36eb4bb4fc231c144d8e741770759b Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 1 Nov 2020 21:02:51 -0500 Subject: [PATCH 4/4] Update references to hf iclass loclass --- armsrc/Standalone/hf_iceclass.c | 2 +- client/src/cmdhficlass.c | 4 ++-- doc/cheatsheet.md | 2 +- doc/loclass_notes.md | 6 +++--- tools/pm3_tests.sh | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/armsrc/Standalone/hf_iceclass.c b/armsrc/Standalone/hf_iceclass.c index 0c06bc90b..8490ea628 100644 --- a/armsrc/Standalone/hf_iceclass.c +++ b/armsrc/Standalone/hf_iceclass.c @@ -132,7 +132,7 @@ static void download_instructions(uint8_t t) { DbpString("The collected data was saved to SPIFFS. The file names below may differ"); DbpString("1. " _YELLOW_("mem spiffs tree")); DbpString("2. " _YELLOW_("mem spiffs dump o " HF_ICLASS_ATTACK_BIN " f " HF_ICLASS_ATTACK_BIN)); - DbpString("3. " _YELLOW_("hf iclass loclass f " HF_ICLASS_ATTACK_BIN)); + DbpString("3. " _YELLOW_("hf iclass loclass -f " HF_ICLASS_ATTACK_BIN)); break; } case ICE_STATE_READER: { diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index f0c4c0f43..d37baac48 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -699,7 +699,7 @@ static int CmdHFiClassSim(const char *Cmd) { saveFile("iclass_mac_attack", ".bin", dump, datalen); free(dump); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass h") "` to recover elite key"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -h") "` to recover elite key"); break; } case ICLASS_SIM_MODE_READER_ATTACK_KEYROLL: { @@ -765,7 +765,7 @@ static int CmdHFiClassSim(const char *Cmd) { saveFile("iclass_mac_attack_keyroll_B", ".bin", dump, datalen); free(dump); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass h") "` to recover elite key"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -h") "` to recover elite key"); break; } case ICLASS_SIM_MODE_CSN: diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 234c39ffb..a3ea9c579 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -173,7 +173,7 @@ k : Access Key as 16 hex symbols or 1 hex to select key from memory e : If 'e' is specified, elite computations applied to key pm3 --> hf iclass sim 2 -pm3 --> hf iclass loclass f iclass_mac_attack.bin +pm3 --> hf iclass loclass -f iclass_mac_attack.bin pm3 --> hf iclass managekeys n 7 k pm3 --> hf iclass dump k 7 e ``` diff --git a/doc/loclass_notes.md b/doc/loclass_notes.md index 643e0d84e..f9280119b 100644 --- a/doc/loclass_notes.md +++ b/doc/loclass_notes.md @@ -8,15 +8,15 @@ LOCLASS, is a two part attack. First is the online part where you gather needed The second part is offline, where the information gathered from the first step is used in a series of DES operations to figure out the used masterkey. - run `hf iclass loclass f abc.bin` + run `hf iclass loclass -f abc.bin` If you don't have access to a iClass SE reader configured in Elite mode there is a test file which you can use. - `hf iclass loclass f iclass_dump.bin` + `hf iclass loclass -f iclass_dump.bin` # Unit testing In order to verify that loclass is actually working, there is a "unit" test mode. -run `hf iclass loclass t`. +run `hf iclass loclass --test`. This test mode uses two files. diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index 41ebe1951..d4aa7d89a 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -450,10 +450,10 @@ while true; do echo -e "\n${C_BLUE}Testing HF:${C_NC}" if ! CheckExecute "hf mf offline text" "$CLIENTBIN -c 'hf mf'" "at_enc"; then break; fi if ! CheckExecute slow retry ignore "hf mf hardnested long test" "$CLIENTBIN -c 'hf mf hardnested t 1 000000000000'" "found:"; then break; fi - if ! CheckExecute slow "hf iclass long test" "$CLIENTBIN -c 'hf iclass loclass t l'" "verified ok"; then break; fi + if ! CheckExecute slow "hf iclass long test" "$CLIENTBIN -c 'hf iclass loclass --long'" "verified ok"; then break; fi if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Test(s) \[ ok"; then break; fi if ! $SLOWTESTS; then - if ! CheckExecute "hf iclass test" "$CLIENTBIN -c 'hf iclass loclass t'" "key diversification (ok)"; then break; fi + if ! CheckExecute "hf iclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification (ok)"; then break; fi if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test(s) \[ ok"; then break; fi fi fi