From 1722d2cb43fe15dc70f97ded7da7a288681b00e2 Mon Sep 17 00:00:00 2001 From: tcprst Date: Fri, 27 Nov 2020 15:46:06 -0500 Subject: [PATCH 1/6] hf iclass chk -now use cliparser --- client/src/cmdhficlass.c | 82 ++++++++++++---------------------------- 1 file changed, 24 insertions(+), 58 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 49784c4f5..033f27b02 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -115,21 +115,6 @@ static int usage_hf_iclass_managekeys(void) { 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"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h Show this help"); - PrintAndLogEx(NORMAL, " f Dictionary file with default iclass keys"); - PrintAndLogEx(NORMAL, " r raw"); - PrintAndLogEx(NORMAL, " e elite"); - PrintAndLogEx(NORMAL, " c credit key (if not use, default is debit)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass chk f dictionaries/iclass_default_keys.dic")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass chk f dictionaries/iclass_default_keys.dic e")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_lookup(void) { PrintAndLogEx(NORMAL, "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass lookup [h|e|r] [f (*.dic)] [u ] [p ] [m ]\n"); @@ -2730,60 +2715,41 @@ static int iclass_chk_keys(uint8_t *keyBlock, uint32_t keycount) { */ static int CmdHFiClassCheckKeys(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass chk", + "Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag", + "hf iclass chk -f dictionaries/iclass_default_keys.dic\n" + "hf iclass chk -f dictionaries/iclass_default_keys.dic --elite"); - // empty string - if (strlen(Cmd) == 0) return usage_hf_iclass_chk(); + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "Dictionary file with default iclass keys"), + arg_lit0(NULL, "credit", "key is assumed to be the credit key"), + arg_lit0(NULL, "elite", "elite computations applied to key"), + arg_lit0(NULL, "raw", "no computations applied to key (raw)"), + 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); + + bool use_credit_key = arg_get_lit(ctx, 2); + bool use_elite = arg_get_lit(ctx, 3); + bool use_raw = arg_get_lit(ctx, 4); + + CLIParserFree(ctx); uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - // elite key, raw key, standard key - bool use_elite = false; - bool use_raw = false; - bool use_credit_key = false; bool found_key = false; //bool found_credit = false; bool got_csn = false; - bool errors = false; - uint8_t cmdp = 0x00; - - char filename[FILE_PATH_SIZE] = {0}; - uint8_t fileNameLen = 0; uint64_t t1 = msclock(); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_chk(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - if (fileNameLen < 1) { - PrintAndLogEx(WARNING, _RED_("no filename found after f")); - errors = true; - } - cmdp += 2; - break; - case 'e': - use_elite = true; - cmdp++; - break; - case 'c': - use_credit_key = true; - cmdp++; - break; - case 'r': - use_raw = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors) return usage_hf_iclass_chk(); - uint8_t *keyBlock = NULL; uint32_t keycount = 0; From 4e1c1f96f8540c75d3569fc95612181f8223212e Mon Sep 17 00:00:00 2001 From: tcprst Date: Fri, 27 Nov 2020 18:27:02 -0500 Subject: [PATCH 2/6] hf iclass managekeys - now use cliparser --- client/src/cmdhficlass.c | 160 +++++++++++++++++---------------------- doc/cheatsheet.md | 11 +-- 2 files changed, 77 insertions(+), 94 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 033f27b02..b2b4b306c 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -92,29 +92,6 @@ static int usage_hf_iclass_calc_newkey(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_managekeys(void) { - PrintAndLogEx(NORMAL, "Manage iCLASS Keys in client memory:\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " n : specify the keyNbr to set in memory"); - PrintAndLogEx(NORMAL, " k : set a key in memory"); - PrintAndLogEx(NORMAL, " f : specify a filename to use with load or save operations"); - PrintAndLogEx(NORMAL, " s : save keys in memory to file specified by filename"); - PrintAndLogEx(NORMAL, " l : load keys to memory from file specified by filename"); - PrintAndLogEx(NORMAL, " p : print keys loaded into memory\n"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " -- set key"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass managekeys n 0 k 1122334455667788")); - PrintAndLogEx(NORMAL, " -- save key file"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass managekeys f mykeys.bin s")); - PrintAndLogEx(NORMAL, " -- load key file"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass managekeys f mykeys.bin l")); - PrintAndLogEx(NORMAL, " -- print keys"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass managekeys p")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_lookup(void) { PrintAndLogEx(NORMAL, "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass lookup [h|e|r] [f (*.dic)] [u ] [p ] [m ]\n"); @@ -2505,83 +2482,88 @@ static int printKeys(void) { } static int CmdHFiClassManageKeys(const char *Cmd) { - uint8_t keyNbr = 0; - uint8_t dataLen = 0; - uint8_t KEY[8] = {0}; - char filename[FILE_PATH_SIZE]; - uint8_t fileNameLen = 0; - bool errors = false; - uint8_t operation = 0; - char tempStr[20]; - uint8_t cmdp = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass managekeys", + "Manage iCLASS Keys in client memory", + "hf iclass managekeys --ki 0 -k 1122334455667788 -> set key\n" + "hf iclass managekeys -f mykeys.bin --save -> save key file\n" + "hf iclass managekeys -f mykeys.bin --load -> load key file\n" + "hf iclass managekeys -p -> print keys"); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_managekeys(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - if (fileNameLen < 1) { - PrintAndLogEx(ERR, "No filename found"); - errors = true; - } - cmdp += 2; - break; - case 'n': - keyNbr = param_get8(Cmd, cmdp + 1); - if (keyNbr >= ICLASS_KEYS_MAX) { - PrintAndLogEx(ERR, "Invalid block number, MAX is " _YELLOW_("%d"), ICLASS_KEYS_MAX); - errors = true; - } - cmdp += 2; - break; - case 'k': - operation += 3; //set key - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { //ul-c or ev1/ntag key length - errors = param_gethex(tempStr, 0, KEY, dataLen); - } else { - PrintAndLogEx(WARNING, "\nERROR: Key is incorrect length\n"); - errors = true; - } - cmdp += 2; - break; - case 'p': - operation += 4; //print keys in memory - cmdp++; - break; - case 'l': - operation += 5; //load keys from file - cmdp++; - break; - case 's': - operation += 6; //save keys to file - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "Specify a filename to use with load or save operations"), + arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_int0(NULL, "ki", "", "Specify key index to set key in memory"), + arg_lit0(NULL, "save", "Save keys in memory to file specified by filename"), + arg_lit0(NULL, "load", "Load keys to memory from file specified by filename"), + arg_lit0("p", "print", "Print keys loaded into memory"), + 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); + + int key_len = 0; + uint8_t key[8] = {0}; + CLIGetHexWithReturn(ctx, 2, key, &key_len); + uint8_t operation = 0; + + if (key_len > 0) { + operation += 3; + if (key_len != 8) { + PrintAndLogEx(ERR, "Key is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; } } - if (errors) return usage_hf_iclass_managekeys(); + + int key_nr = arg_get_int_def(ctx, 3, -1); + + if (key_nr >= 0) { + if (key_nr < ICLASS_KEYS_MAX) { + PrintAndLogEx(SUCCESS, "Setting key[%d] " _GREEN_("%s"), key_nr); + } else { + PrintAndLogEx(ERR, "Key number is invalid"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + + if (arg_get_lit(ctx, 4)) { //save + operation += 6; + } + if (arg_get_lit(ctx, 5)) { //load + operation += 5; + } + if (arg_get_lit(ctx, 6)) { //print + operation += 4; + } + + CLIParserFree(ctx); if (operation == 0) { - PrintAndLogEx(WARNING, "no operation specified (load, save, or print)\n"); - return usage_hf_iclass_managekeys(); + PrintAndLogEx(ERR, "No operation specified (load, save, or print)\n"); + return PM3_EINVARG; } if (operation > 6) { - PrintAndLogEx(WARNING, "Too many operations specified\n"); - return usage_hf_iclass_managekeys(); + PrintAndLogEx(ERR, "Too many operations specified\n"); + return PM3_EINVARG; } - if (operation > 4 && fileNameLen == 0) { - PrintAndLogEx(WARNING, "You must enter a filename when loading or saving\n"); - return usage_hf_iclass_managekeys(); + if (operation > 4 && fnlen == 0) { + PrintAndLogEx(ERR, "You must enter a filename when loading or saving\n"); + return PM3_EINVARG; + } + if (key_len > 0 && key_nr == -1) { + PrintAndLogEx(ERR, "Please specify key index when specifying key"); + return PM3_EINVARG; } switch (operation) { case 3: - memcpy(iClass_Key_Table[keyNbr], KEY, 8); + memcpy(iClass_Key_Table[key_nr], key, 8); return PM3_SUCCESS; case 4: return printKeys(); @@ -2613,7 +2595,7 @@ static void add_key(uint8_t *key) { if (i == ICLASS_KEYS_MAX) { PrintAndLogEx(INFO, "Couldn't find an empty keyslot"); } else { - PrintAndLogEx(HINT, "Try " _YELLOW_("`hf iclass managekeys p`") " to view keys"); + PrintAndLogEx(HINT, "Try " _YELLOW_("`hf iclass managekeys -p`") " to view keys"); } } diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index e725d8d25..335084e2a 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -109,19 +109,20 @@ Print keystore ``` Options --- -p : print keys loaded into memory +-p, --print Print keys loaded into memory -pm3 --> hf iclass managekeys p + +pm3 --> hf iclass managekeys -p ``` Add key to keystore [0-7] ``` Options --- -n : specify the keyNbr to set in memory -k : set a key in memory +-f, --file Specify a filename to use with load or save operations + --ki Specify key index to set key in memory -pm3 --> hf iclass managekeys n 3 k AFA785A7DAB33378 +pm3 --> hf iclass managekeys --ki 3 -k AFA785A7DAB33378 ``` Encrypt iCLASS Block From 769e80910456335cf4094705be72e94a67902938 Mon Sep 17 00:00:00 2001 From: tcprst Date: Fri, 27 Nov 2020 19:51:54 -0500 Subject: [PATCH 3/6] hf iclass calcnewkey - now use cliparser --- client/src/cmdhficlass.c | 203 +++++++++++++++++++++------------------ 1 file changed, 110 insertions(+), 93 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index b2b4b306c..47e61a363 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -71,27 +71,6 @@ static int usage_hf_iclass_sim(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_calc_newkey(void) { - PrintAndLogEx(NORMAL, "Calculate new key for updating\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass calc_newkey o n s [csn] e\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " o : *specify a key as 16 hex symbols or a key number as 1 symbol"); - PrintAndLogEx(NORMAL, " n : *specify a key as 16 hex symbols or a key number as 1 symbol"); - PrintAndLogEx(NORMAL, " s : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)"); - PrintAndLogEx(NORMAL, " e : specify new key as elite calc"); - PrintAndLogEx(NORMAL, " ee : specify old and new key as elite calc"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " -- e key to e key given csn"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee")); - PrintAndLogEx(NORMAL, " -- std key to e key read csn"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass calcnewkey o 1122334455667788 n 2233445566778899 e")); - PrintAndLogEx(NORMAL, " -- std to std read csn"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass calcnewkey o 1122334455667788 n 2233445566778899")); - PrintAndLogEx(NORMAL, "\nNOTE: * = required"); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_lookup(void) { PrintAndLogEx(NORMAL, "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass lookup [h|e|r] [f (*.dic)] [u ] [p ] [m ]\n"); @@ -2339,89 +2318,127 @@ static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, u } static int CmdHFiClassCalcNewKey(const char *Cmd) { - uint8_t OLDKEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t NEWKEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t xor_div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t keyNbr = 0; - uint8_t dataLen = 0; - char tempStr[50] = {0}; - bool givenCSN = false; - bool old_elite = false; - bool elite = false; - bool errors = false; - uint8_t cmdp = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass calcnewkey", + "Calculate new keys for updating (blocks 3 & 4)", + "hf iclass calcnewkey --old 1122334455667788 --new 2233445566778899 --csn deadbeafdeadbeaf --elite2 -> e key to e key given csn\n" + "hf iclass calcnewkey --old 1122334455667788 --new 2233445566778899 --elite -> std key to e key read csn\n" + "hf iclass calcnewkey --old 1122334455667788 --new 2233445566778899 -> std to std read csn"); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_calc_newkey(); - case 'e': - dataLen = param_getstr(Cmd, cmdp, tempStr, sizeof(tempStr)); - if (dataLen == 2) - old_elite = true; - elite = true; - cmdp++; - break; - case 'n': - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { - errors = param_gethex(tempStr, 0, NEWKEY, dataLen); - } else if (dataLen == 1) { - keyNbr = param_get8(Cmd, cmdp + 1); - if (keyNbr < ICLASS_KEYS_MAX) { - memcpy(NEWKEY, iClass_Key_Table[keyNbr], 8); - } else { - PrintAndLogEx(WARNING, "\nERROR: NewKey Nbr is invalid\n"); - errors = true; - } - } else { - PrintAndLogEx(WARNING, "\nERROR: NewKey is incorrect length\n"); - errors = true; - } - cmdp += 2; - break; - case 'o': - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { - errors = param_gethex(tempStr, 0, OLDKEY, dataLen); - } else if (dataLen == 1) { - keyNbr = param_get8(Cmd, cmdp + 1); - if (keyNbr < ICLASS_KEYS_MAX) { - memcpy(OLDKEY, iClass_Key_Table[keyNbr], 8); - } else { - PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); - errors = true; - } - } else { - PrintAndLogEx(WARNING, "\nERROR: Credit Key is incorrect length\n"); - errors = true; - } - cmdp += 2; - break; - case 's': - givenCSN = true; - if (param_gethex(Cmd, cmdp + 1, CSN, 16)) - return usage_hf_iclass_calc_newkey(); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; + void *argtable[] = { + arg_param_begin, + arg_str0(NULL, "old", "", "Specify key as 8 bytes (16 hex symbols)"), + arg_int0(NULL, "oki", "", "Old key index to select key from memory 'hf iclass managekeys'"), + arg_str0(NULL, "new", "", "Specify key as 8 bytes (16 hex symbols)"), + arg_int0(NULL, "nki", "", "New key index to select key from memory 'hf iclass managekeys'"), + arg_str0(NULL, "csn", "", "Specify a Card Serial Number (CSN) to diversify the key (if omitted will attempt to read a CSN)"), + arg_lit0(NULL, "elite", "Elite computations applied to new key"), + arg_lit0(NULL, "elite2", "Elite computations applied to both old and new key"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int old_key_len = 0; + uint8_t old_key[8] = {0}; + CLIGetHexWithReturn(ctx, 1, old_key, &old_key_len); + + int old_key_nr = arg_get_int_def(ctx, 2, -1); + + if (old_key_len > 0 && old_key_nr >= 0) { + PrintAndLogEx(ERR, "Please specify old key or index, not both"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (old_key_len > 0) { + if (old_key_len != 8) { + PrintAndLogEx(ERR, "Old key is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else if (old_key_nr >= 0) { + if (old_key_nr < ICLASS_KEYS_MAX) { + memcpy(old_key, iClass_Key_Table[old_key_nr], 8); + PrintAndLogEx(SUCCESS, "Using old key[%d] " _GREEN_("%s"), old_key_nr, sprint_hex(iClass_Key_Table[old_key_nr], 8)); + } else { + PrintAndLogEx(ERR, "Key number is invalid"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else { + PrintAndLogEx(ERR, "Please specify an old key or old key index"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + int new_key_len = 0; + uint8_t new_key[8] = {0}; + CLIGetHexWithReturn(ctx, 3, new_key, &new_key_len); + + int new_key_nr = arg_get_int_def(ctx, 4, -1); + + if (new_key_len > 0 && new_key_nr >= 0) { + PrintAndLogEx(ERR, "Please specify new key or index, not both"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (new_key_len > 0) { + if (new_key_len != 8) { + PrintAndLogEx(ERR, "New key is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else if (new_key_nr >= 0) { + if (new_key_nr < ICLASS_KEYS_MAX) { + memcpy(new_key, iClass_Key_Table[new_key_nr], 8); + PrintAndLogEx(SUCCESS, "Using new key[%d] " _GREEN_("%s"), new_key_nr, sprint_hex(iClass_Key_Table[new_key_nr], 8)); + } else { + PrintAndLogEx(ERR, "Key number is invalid"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else { + PrintAndLogEx(ERR, "Please specify an new key or old key index"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + int csn_len = 0; + uint8_t csn[8] = {0}; + CLIGetHexWithReturn(ctx, 5, csn, &csn_len); + bool givenCSN = false; + + if (csn_len > 0) { + givenCSN = true; + if (csn_len != 8) { + PrintAndLogEx(ERR, "CSN is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; } } - if (errors || cmdp < 4) return usage_hf_iclass_calc_newkey(); + + bool elite = arg_get_lit(ctx, 6); + bool old_elite = false; + + if (arg_get_lit(ctx, 7)) { + elite = true; + old_elite = true; + } + + CLIParserFree(ctx); + + uint8_t xor_div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; if (givenCSN == false) { uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (select_only(CSN, CCNR, true) == false) { + if (select_only(csn, CCNR, true) == false) { DropField(); return PM3_ESOFT; } } - HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, old_elite, true); + HFiClassCalcNewKey(csn, old_key, new_key, xor_div_key, elite, old_elite, true); return PM3_SUCCESS; } From a5ab00357dcf755b8fff18a0b4a63f53d3270014 Mon Sep 17 00:00:00 2001 From: tcprst Date: Fri, 27 Nov 2020 20:28:23 -0500 Subject: [PATCH 4/6] hf iclass lookup - now use cliparser (untested) --- client/src/cmdhficlass.c | 158 +++++++++++++++++---------------------- doc/cheatsheet.md | 13 ++-- 2 files changed, 75 insertions(+), 96 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 47e61a363..7f51da0a9 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -71,23 +71,6 @@ static int usage_hf_iclass_sim(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_lookup(void) { - PrintAndLogEx(NORMAL, "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass lookup [h|e|r] [f (*.dic)] [u ] [p ] [m ]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h Show this help"); - PrintAndLogEx(NORMAL, " f Dictionary file with default iclass keys"); - PrintAndLogEx(NORMAL, " u CSN"); - PrintAndLogEx(NORMAL, " p EPURSE"); - PrintAndLogEx(NORMAL, " m macs"); - PrintAndLogEx(NORMAL, " r raw"); - PrintAndLogEx(NORMAL, " e elite"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f dictionaries/iclass_default_keys.dic")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f dictionaries/iclass_default_keys.dic e")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int cmp_uint32(const void *a, const void *b) { @@ -2900,89 +2883,84 @@ out: // this method tries to identify in which configuration mode a iCLASS / iCLASS SE reader is in. // Standard or Elite / HighSecurity mode. It uses a default key dictionary list in order to work. static int CmdHFiClassLookUp(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass lookup", + "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file", + "hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f dictionaries/iclass_default_keys.dic\n" + "hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f dictionaries/iclass_default_keys.dic --elite"); - uint8_t CSN[8]; - uint8_t EPURSE[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - uint8_t MACS[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - uint8_t CCNR[12]; - uint8_t MAC_TAG[4] = { 0, 0, 0, 0 }; - - // elite key, raw key, standard key - bool use_elite = false; - bool use_raw = false; - bool errors = false; - uint8_t cmdp = 0x00; + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "Dictionary file with default iclass keys"), + arg_str1(NULL, "csn", "", "Specify CSN as 8 bytes (16 hex symbols)"), + arg_str1(NULL, "epurse", "", "Specify ePurse as 8 bytes (16 hex symbols)"), + arg_str1(NULL, "macs", "", "MACs"), + arg_lit0(NULL, "raw", "no computations applied to key (raw)"), + arg_lit0(NULL, "elite", "Elite computations applied to key"), + 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); - iclass_prekey_t *prekey = NULL; - int len = 0; - // if empty string - if (strlen(Cmd) == 0) errors = true; - // time - uint64_t t1 = msclock(); + int csn_len = 0; + uint8_t csn[8] = {0}; + CLIGetHexWithReturn(ctx, 2, csn, &csn_len); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_lookup(); - case 'f': - if (param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)) < 1) { - PrintAndLogEx(WARNING, "No filename found after f"); - errors = true; - } - cmdp += 2; - break; - case 'u': - param_gethex_ex(Cmd, cmdp + 1, CSN, &len); - if (len >> 1 != sizeof(CSN)) { - PrintAndLogEx(WARNING, "Wrong CSN length, expected %zu got [%d]", sizeof(CSN), len >> 1); - errors = true; - } - cmdp += 2; - break; - case 'm': - param_gethex_ex(Cmd, cmdp + 1, MACS, &len); - if (len >> 1 != sizeof(MACS)) { - PrintAndLogEx(WARNING, "Wrong MACS length, expected %zu got [%d] ", sizeof(MACS), len >> 1); - errors = true; - } else { - memcpy(MAC_TAG, MACS + 4, 4); - } - cmdp += 2; - break; - case 'p': - param_gethex_ex(Cmd, cmdp + 1, EPURSE, &len); - if (len >> 1 != sizeof(EPURSE)) { - PrintAndLogEx(WARNING, "Wrong EPURSE length, expected %zu got [%d] ", sizeof(EPURSE), len >> 1); - errors = true; - } - cmdp += 2; - break; - case 'e': - use_elite = true; - cmdp++; - break; - case 'r': - use_raw = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; + if (csn_len > 0) { + if (csn_len != 8) { + PrintAndLogEx(ERR, "CSN is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; } } - if (errors) return usage_hf_iclass_lookup(); + int epurse_len = 0; + uint8_t epurse[8] = {0}; + CLIGetHexWithReturn(ctx, 3, epurse, &epurse_len); + + if (epurse_len > 0) { + if (epurse_len != 8) { + PrintAndLogEx(ERR, "ePurse is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + + int macs_len = 0; + uint8_t macs[8] = {0}; + CLIGetHexWithReturn(ctx, 4, macs, &macs_len); + + if (macs_len > 0) { + if (macs_len != 8) { + PrintAndLogEx(ERR, "MAC is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + + bool use_elite = arg_get_lit(ctx, 5); + bool use_raw = arg_get_lit(ctx, 6); + + CLIParserFree(ctx); + + uint8_t CCNR[12]; + uint8_t MAC_TAG[4] = { 0, 0, 0, 0 }; + + iclass_prekey_t *prekey = NULL; + + // time + uint64_t t1 = msclock(); // stupid copy.. CCNR is a combo of epurse and reader nonce - memcpy(CCNR, EPURSE, 8); - memcpy(CCNR + 8, MACS, 4); + memcpy(CCNR, epurse, 8); + memcpy(CCNR + 8, macs, 4); - PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s"), sprint_hex(CSN, sizeof(CSN))); - PrintAndLogEx(SUCCESS, " Epurse: %s", sprint_hex(EPURSE, sizeof(EPURSE))); - PrintAndLogEx(SUCCESS, " MACS: %s", sprint_hex(MACS, sizeof(MACS))); + PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s"), sprint_hex(csn, sizeof(csn))); + PrintAndLogEx(SUCCESS, " Epurse: %s", sprint_hex(epurse, sizeof(epurse))); + PrintAndLogEx(SUCCESS, " MACS: %s", sprint_hex(macs, sizeof(macs))); PrintAndLogEx(SUCCESS, " CCNR: " _GREEN_("%s"), sprint_hex(CCNR, sizeof(CCNR))); PrintAndLogEx(SUCCESS, "TAG MAC: %s", sprint_hex(MAC_TAG, sizeof(MAC_TAG))); @@ -3004,7 +2982,7 @@ static int CmdHFiClassLookUp(const char *Cmd) { } PrintAndLogEx(SUCCESS, "Generating diversified keys..."); - GenerateMacKeyFrom(CSN, CCNR, use_raw, use_elite, keyBlock, keycount, prekey); + GenerateMacKeyFrom(csn, CCNR, use_raw, use_elite, keyBlock, keycount, prekey); if (use_elite) PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 335084e2a..abdf37ef6 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -202,13 +202,14 @@ Verify custom iCLASS key ``` Options --- -f : Dictionary file with default iCLASS keys -u : CSN -p : EPURSE -m : macs -e : elite +-f, --file Dictionary file with default iclass keys + --csn Specify CSN as 8 bytes (16 hex symbols) + --epurse Specify ePurse as 8 bytes (16 hex symbols) + --macs MACs + --raw no computations applied to key (raw) + --elite Elite computations applied to key -pm3 --> hf iclass lookup u 010a0ffff7ff12e0 p feffffffffffffff m 66348979153c41b9 f iclass_default_keys e +pm3 --> hf iclass lookup --csn 010a0ffff7ff12e0 --epurse feffffffffffffff --macs 66348979153c41b9 -f iclass_default_keys --elite ``` ## MIFARE From 448a0546b1b929c0714afdccc8b639e7476ed1f9 Mon Sep 17 00:00:00 2001 From: tcprst Date: Fri, 27 Nov 2020 21:22:23 -0500 Subject: [PATCH 5/6] hf iclass sim - now use cliparser --- client/src/cmdhficlass.c | 69 +++++++++++++++++--------------- client/src/loclass/elite_crack.c | 2 +- doc/cheatsheet.md | 15 ++++--- doc/loclass_notes.md | 4 +- 4 files changed, 48 insertions(+), 42 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 7f51da0a9..b25cb463f 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -51,27 +51,6 @@ static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; -static int usage_hf_iclass_sim(void) { - PrintAndLogEx(NORMAL, "Simulate a iCLASS legacy/standard tag\n"); - PrintAndLogEx(NORMAL, "Usage: hf iCLASS sim [h]