From 6b3f12ffe99fdc94bde7e0bedd96de744c5f4393 Mon Sep 17 00:00:00 2001 From: tcprst Date: Wed, 25 Nov 2020 14:02:52 -0500 Subject: [PATCH 1/6] hf iclass dump - now uses cliparser --- client/src/cmdhficlass.c | 222 +++++++++++++++++++-------------------- doc/cheatsheet.md | 15 ++- 2 files changed, 117 insertions(+), 120 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 284317a47..a3eb00e55 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_dump(void) { - PrintAndLogEx(NORMAL, "Dump all memory from a iCLASS tag\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass dump f k c [e|r|v]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " f : specify a filename to save dump to"); - PrintAndLogEx(NORMAL, " k : access Key as 16 hex symbols or 1 hex to select key from memory OR NR/MAC for replay"); - PrintAndLogEx(NORMAL, " c : credit key as 16 hex symbols or 1 hex to select key from memory"); - PrintAndLogEx(NORMAL, " e : elite computations applied to key"); - PrintAndLogEx(NORMAL, " r : raw, the key is interpreted as raw block 3/4"); - PrintAndLogEx(NORMAL, " n : replay of NR/MAC"); - PrintAndLogEx(NORMAL, " v : verbose output"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass dump k 001122334455667B")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass dump k AAAAAAAAAAAAAAAA e")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass dump k 0")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_restore(void) { PrintAndLogEx(NORMAL, "Restore data from dumpfile onto a iCLASS tag\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass restore f b l k c e|r\n"); @@ -1359,104 +1338,115 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool verbose) { } static int CmdHFiClassDump(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass dump", + "Dump all memory from a iCLASS tag", + "hf iclass dump -k 001122334455667B\n" + "hf iclass dump -k AAAAAAAAAAAAAAAA --credit 001122334455667B\n" + "hf iclass dump -k AAAAAAAAAAAAAAAA --elite\n" + "hf iclass dump --ki 0\n" + "hf iclass dump --ki 0 --ci 2"); - uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t CreditKEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t keyNbr = 0; - uint8_t dataLen = 0; - uint8_t app_limit1 = 0, app_limit2 = 0; - uint8_t fileNameLen = 0; + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename to save dump to"), + arg_str0("k", "key", "", "debit key as 16 hex symbols OR NR/MAC for replay"), + arg_int0(NULL, "ki", "", "debit key index to select key from memory 'hf iclass managekeys'"), + arg_str0(NULL, "credit", "", "credit key as 16 hex symbols"), + arg_int0(NULL, "ci", "", "credit key index to select key from memory 'hf iclass managekeys'"), + arg_lit0(NULL, "elite", "elite computations applied to key"), + arg_lit0(NULL, "raw", "raw, the key is interpreted as raw block 3/4"), + arg_lit0(NULL, "nr", "replay of NR/MAC"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; - char tempStr[50] = {0}; - bool have_credit_key = false; - bool elite = false; - bool rawkey = false; - bool use_replay = false; - bool errors = false; - bool auth = false; - uint8_t cmdp = 0; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_dump(); - case 'c': - auth = true; - have_credit_key = true; - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { - errors = param_gethex(tempStr, 0, CreditKEY, dataLen); - } else if (dataLen == 1) { - keyNbr = param_get8(Cmd, cmdp + 1); - if (keyNbr < ICLASS_KEYS_MAX) { - memcpy(CreditKEY, iClass_Key_Table[keyNbr], 8); - PrintAndLogEx(INFO, "AA2 (credit) index %u", keyNbr); - } 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 'e': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); - elite = true; - cmdp++; - break; - case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - if (fileNameLen < 1) { - PrintAndLogEx(WARNING, "no filename found after f"); - errors = true; - } - cmdp += 2; - break; - case 'k': - auth = true; - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { - errors = param_gethex(tempStr, 0, KEY, dataLen); - } else if (dataLen == 1) { - keyNbr = param_get8(Cmd, cmdp + 1); - if (keyNbr < ICLASS_KEYS_MAX) { - memcpy(KEY, iClass_Key_Table[keyNbr], 8); - PrintAndLogEx(INFO, "AA1 (debit) index %u", keyNbr); - } 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 'r': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); - rawkey = true; - cmdp++; - break; - case 'n': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode")); - use_replay = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; + int key_len = 0; + uint8_t key[8] = {0}; + bool have_debit_key = false; + + CLIGetHexWithReturn(ctx, 2, key, &key_len); + + int deb_key_nr = arg_get_int_def(ctx, 3, -1); + + if (key_len > 0 && deb_key_nr >= 0) { + PrintAndLogEx(ERR, "Please specify debit key or index, not both"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (key_len > 0) { + have_debit_key = true; + if (key_len != 8) { + PrintAndLogEx(ERR, "Debit key is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; } } - if ((use_replay + rawkey + elite) > 1) { - PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); - errors = true; + if (deb_key_nr >= 0) { + if (deb_key_nr < ICLASS_KEYS_MAX) { + have_debit_key = true; + memcpy(key, iClass_Key_Table[deb_key_nr], 8); + PrintAndLogEx(INFO, "AA1 (debit) index %u", deb_key_nr); + } else { + PrintAndLogEx(ERR, "Key number is invalid"); + CLIParserFree(ctx); + return PM3_EINVARG; + } } - if (errors) return usage_hf_iclass_dump(); + int credit_key_len = 0; + uint8_t credit_key[8] = {0}; + bool have_credit_key = false; + + CLIGetHexWithReturn(ctx, 4, credit_key, &credit_key_len); + + int credit_key_nr = arg_get_int_def(ctx, 5, -1); + + if (credit_key_len > 0 && credit_key_nr >= 0) { + PrintAndLogEx(ERR, "Please specify credit key or index, not both"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (credit_key_len > 0) { + have_credit_key = true; + if (key_len != 8) { + PrintAndLogEx(ERR, "Credit key is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + + if (credit_key_nr >= 0) { + if (credit_key_nr < ICLASS_KEYS_MAX) { + have_credit_key = true; + memcpy(key, iClass_Key_Table[credit_key_nr], 8); + PrintAndLogEx(INFO, "AA2 (credit) index %u", credit_key_nr); + } else { + PrintAndLogEx(ERR, "Key number is invalid"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + + bool elite = arg_get_lit(ctx, 6); + bool rawkey = arg_get_lit(ctx, 7); + bool use_replay = arg_get_lit(ctx, 8); + + CLIParserFree(ctx); + + if ((use_replay + rawkey + elite) > 1) { + PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); + return PM3_EINVARG; + } + + uint8_t app_limit1 = 0, app_limit2 = 0; uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE); @@ -1511,11 +1501,11 @@ static int CmdHFiClassDump(const char *Cmd) { if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { PrintAndLogEx(INFO, "Dumping all available memory, block 3 - %u (0x%02x)", app_limit1, app_limit1); - if (auth) { + if (have_debit_key) { PrintAndLogEx(INFO, "No keys needed, ignoring user supplied key"); } } else { - if (auth == false) { + if (have_debit_key == false) { PrintAndLogEx(FAILED, "Run command with keys"); return PM3_ESOFT; } @@ -1528,10 +1518,10 @@ static int CmdHFiClassDump(const char *Cmd) { .req.use_credit_key = false, .req.use_replay = use_replay, .req.send_reply = true, - .req.do_auth = auth, + .req.do_auth = have_debit_key, .end_block = app_limit1, }; - memcpy(payload.req.key, KEY, 8); + memcpy(payload.req.key, key, 8); // tags configured for NON SECURE PAGE, acts different if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { @@ -1606,7 +1596,7 @@ static int CmdHFiClassDump(const char *Cmd) { if (have_credit_key && pagemap != 0x01) { // AA2 authenticate credit key - memcpy(payload.req.key, CreditKEY, 8); + memcpy(payload.req.key, credit_key, 8); payload.req.use_credit_key = true; payload.start_block = app_limit1 + 1; diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 9699fabf0..c466a4784 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -62,9 +62,16 @@ Dump iCLASS card contents ``` Options --- -k : *Access Key as 16 hex symbols or 1 hex to select key from memory +-f, --file filename to save dump to +-k, --key debit key as 16 hex symbols OR NR/MAC for replay + --ki debit key index to select key from memory 'hf iclass managekeys' + --credit credit key as 16 hex symbols + --ci credit key index to select key from memory 'hf iclass managekeys' + --elite elite computations applied to key + --raw raw, the key is interpreted as raw block 3/4 + --nr replay of NR/MAC -m3 --> hf iclass dump k 0 +pm3 --> hf iclass dump --ki 0 ``` Read iCLASS Block @@ -161,7 +168,7 @@ pm3 --> hf iclass sim 3 Simulate iCLASS Sequence ``` -pm3 --> hf iclass dump k 0 +pm3 --> hf iclass dump --ki 0 pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin pm3 --> hf iclass sim 3 ``` @@ -177,7 +184,7 @@ 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 managekeys n 7 k -pm3 --> hf iclass dump k 7 e +pm3 --> hf iclass dump --ki 7 --elite ``` Verify custom iCLASS key From 88b7efe69a69d46f96058f3a36f67072509d78a2 Mon Sep 17 00:00:00 2001 From: tcprst Date: Wed, 25 Nov 2020 18:00:32 -0500 Subject: [PATCH 2/6] hf iclass restore - now use cliparser --- armsrc/iclass.c | 4 +- client/src/cmdhficlass.c | 193 ++++++++++++++++----------------------- 2 files changed, 80 insertions(+), 117 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 86d8094b7..f6d338f9c 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1999,10 +1999,10 @@ void iClass_Restore(iclass_restore_req_t *msg) { // data + mac if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac)) { - Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno); + Dbprintf("Write block [%02d] " _GREEN_("successful"), item.blockno); written++; } else { - Dbprintf("Write block [%02x] " _RED_("failed"), item.blockno); + Dbprintf("Write block [%02d] " _RED_("failed"), item.blockno); } } diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index a3eb00e55..f647f6aeb 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -71,25 +71,6 @@ static int usage_hf_iclass_sim(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_restore(void) { - PrintAndLogEx(NORMAL, "Restore data from dumpfile onto a iCLASS tag\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass restore f b l k c e|r\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " f : specify a filename to restore"); - PrintAndLogEx(NORMAL, " b : The first block to restore as 2 hex symbols"); - PrintAndLogEx(NORMAL, " l : The last block to restore as 2 hex symbols"); - PrintAndLogEx(NORMAL, " k : Access key as 16 hex symbols or 1 hex to select key from memory"); - PrintAndLogEx(NORMAL, " c : If 'c' is specified, the key set is assumed to be the credit key\n"); - PrintAndLogEx(NORMAL, " e : If 'e' is specified, elite computations applied to key"); - PrintAndLogEx(NORMAL, " r : If 'r' is specified, no computations applied to key (raw)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass restore f hf-iclass-AA162D30F8FF12F1-dump.bin b 06 l 1A k 1122334455667788 e")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass restore f hf-iclass-AA162D30F8FF12F1-dump b 05 l 19 k 0")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass restore f hf-iclass-AA162D30F8FF12F1-dump b 06 l 19 k 0 e")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_writeblock(void) { PrintAndLogEx(NORMAL, "Write data to a iCLASS tag\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass wrbl b d k [c|e|r|v]\n"); @@ -1821,92 +1802,75 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { } static int CmdHFiClassRestore(const char *Cmd) { - char filename[FILE_PATH_SIZE] = { 0x00 }; - char tempStr[50] = {0}; - uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t keyNbr = 0; - uint8_t fileNameLen = 0; - uint8_t startblock = 0; - uint8_t endblock = 0; - uint8_t dataLen = 0; - bool got_startblk = false, got_endblk = false; - bool use_credit_key = false; - bool elite = false; - bool rawkey = false; - bool errors = false; - bool verbose = false; - uint8_t cmdp = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass restore", + "Restore data from dumpfile onto a iCLASS tag", + "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 06 --last 1A -k 1122334455667788 --elite\n" + "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 05 --last 19 --ki 0\n" + "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 06 --last 19 --ki 0 --elite"); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_restore(); - case 'b': - startblock = param_get8ex(Cmd, cmdp + 1, 07, 16); - got_startblk = true; - cmdp += 2; - break; - case 'c': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); - use_credit_key = true; - cmdp++; - break; - case 'e': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); - elite = true; - cmdp++; - break; - case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - if (fileNameLen < 1) { - PrintAndLogEx(WARNING, "No filename found after f"); - errors = true; - } - cmdp += 2; - break; - case 'k': - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { - errors = param_gethex(tempStr, 0, KEY, dataLen); - } else if (dataLen == 1) { - keyNbr = param_get8(Cmd, cmdp + 1); - if (keyNbr < ICLASS_KEYS_MAX) { - PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8)); - memcpy(KEY, 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 'l': - endblock = param_get8ex(Cmd, cmdp + 1, 07, 16); - got_endblk = true; - cmdp += 2; - break; - case 'r': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); - rawkey = true; - cmdp++; - break; - case 'v': - verbose = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "specify a filename to restore"), + arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), + arg_int1(NULL, "first", "", "The first block number to restore as an integer"), + arg_int1(NULL, "last", "", "The last block number to restore as an integer"), + 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_lit0("v", "verbose", "verbose output"), + 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); + + int key_nr = arg_get_int_def(ctx, 3, -1); + + if (key_len > 0 && key_nr >= 0) { + PrintAndLogEx(ERR, "Please specify key or index, not both"); + CLIParserFree(ctx); + return PM3_EINVARG; } - if (got_endblk == false || got_startblk == false) - errors = true; - if (errors || cmdp < 8) return usage_hf_iclass_restore(); + if (key_len > 0) { + if (key_len != 8) { + PrintAndLogEx(ERR, "Key is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else if (key_nr >= 0) { + if (key_nr < ICLASS_KEYS_MAX) { + memcpy(key, iClass_Key_Table[key_nr], 8); + PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8)); + } else { + PrintAndLogEx(ERR, "Key number is invalid"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else { + PrintAndLogEx(ERR, "Please specify a key or key index"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + int startblock = arg_get_int_def(ctx, 4, 0); + int endblock = arg_get_int_def(ctx, 5, 0); + + bool use_credit_key = arg_get_lit(ctx, 6); + bool elite = arg_get_lit(ctx, 7); + bool rawkey = arg_get_lit(ctx, 8); + bool verbose = arg_get_lit(ctx, 9); + + CLIParserFree(ctx); if (rawkey + elite > 1) { PrintAndLogEx(FAILED, "Can not use both 'e', 'r'"); @@ -1954,7 +1918,7 @@ static int CmdHFiClassRestore(const char *Cmd) { payload->req.blockno = startblock; payload->req.send_reply = true; payload->req.do_auth = true; - memcpy(payload->req.key, KEY, 8); + memcpy(payload->req.key, key, 8); payload->item_cnt = (endblock - startblock + 1); @@ -1971,7 +1935,7 @@ static int CmdHFiClassRestore(const char *Cmd) { free(dump); if (verbose) { - PrintAndLogEx(INFO, "Preparing to restore block range 0x%02x..0x%02x", startblock, endblock); + PrintAndLogEx(INFO, "Preparing to restore block range %02d..%02d", startblock, endblock); PrintAndLogEx(INFO, "------+----------------------"); PrintAndLogEx(INFO, "block | data"); @@ -1979,7 +1943,7 @@ static int CmdHFiClassRestore(const char *Cmd) { for (uint8_t i = 0; i < payload->item_cnt; i++) { iclass_restore_item_t item = payload->blocks[i]; - PrintAndLogEx(INFO, " %02X | %s", item.blockno, sprint_hex_inrow(item.data, sizeof(item.data))); + PrintAndLogEx(INFO, " %02d | %s", item.blockno, sprint_hex_inrow(item.data, sizeof(item.data))); } } @@ -2313,9 +2277,9 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e int i = startblock; PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, " blk| data | ascii |lck| info"); + PrintAndLogEx(INFO, "blk | data | ascii |lck| info"); PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------"); - PrintAndLogEx(INFO, "0x00| " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8)); + PrintAndLogEx(INFO, " 00 | " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8)); if (i != 1) PrintAndLogEx(INFO, "...."); @@ -2368,14 +2332,14 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e s = info_nonks[i]; } - PrintAndLogEx(INFO, "0x%02X| %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); + PrintAndLogEx(INFO, " %02d | %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); } else { const char *info_ks[] = {"CSN", "Config", "E-purse", "Debit", "Credit", "AIA", "User"}; const char *s = info_ks[6]; if (i < 6) { s = info_ks[i]; } - PrintAndLogEx(INFO, "0x%02X| %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); + PrintAndLogEx(INFO, " %02d | %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); } i++; } @@ -2388,14 +2352,14 @@ static int CmdHFiClassView(const char *Cmd) { CLIParserInit(&ctx, "hf iclass view", "Print a iCLASS tag dump file", "hf iclass view -f hf-iclass-AA162D30F8FF12F1-dump.bin\n" - "hf iclass view --startblock 1 --file hf-iclass-AA162D30F8FF12F1-dump.bin\n"); + "hf iclass view --first 1 --file hf-iclass-AA162D30F8FF12F1-dump.bin\n"); void *argtable[] = { arg_param_begin, arg_str1("f", "file", "", "filename of dump"), - arg_int0("s", "startblock", "", "print from this block (default block6)"), - arg_int0("e", "endblock", "", "end printing at this block (default 0, ALL)"), - arg_lit0("v", "verbose", "verbose output"), + arg_int0(NULL, "first", "", "Begin printing from this block (default block6)"), + arg_int0(NULL, "last", "", "End printing at this block (default 0, ALL)"), + arg_lit0("v", "verbose", "verbose output"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2420,8 +2384,7 @@ static int CmdHFiClassView(const char *Cmd) { if (verbose) { PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename); PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, (uint16_t)(bytes_read >> 3), (uint16_t)(bytes_read >> 3)); - PrintAndLogEx(INFO, "Printing blocks from"); - PrintAndLogEx(INFO, "start " _YELLOW_("0x%02x") " end " _YELLOW_("0x%02x"), (startblock == 0) ? 6 : startblock, endblock); + PrintAndLogEx(INFO, "Printing blocks from: " _YELLOW_("%02d") " to: " _YELLOW_("%02d"), (startblock == 0) ? 6 : startblock, endblock); } PrintAndLogEx(NORMAL, ""); From f4b100b0684579646788f15f533f73b959407029 Mon Sep 17 00:00:00 2001 From: tcprst Date: Wed, 25 Nov 2020 18:42:22 -0500 Subject: [PATCH 3/6] show both decimal and hex for iclass blocks --- armsrc/iclass.c | 4 ++-- client/src/cmdhficlass.c | 34 ++++++++++++++++++---------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index f6d338f9c..5cb5d71ae 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1999,10 +1999,10 @@ void iClass_Restore(iclass_restore_req_t *msg) { // data + mac if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac)) { - Dbprintf("Write block [%02d] " _GREEN_("successful"), item.blockno); + Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), item.blockno, item.blockno); written++; } else { - Dbprintf("Write block [%02d] " _RED_("failed"), item.blockno); + Dbprintf("Write block [%3d/0x%02X] " _RED_("failed"), item.blockno, item.blockno); } } diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index f647f6aeb..b55f2801c 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1348,7 +1348,7 @@ static int CmdHFiClassDump(const char *Cmd) { int key_len = 0; uint8_t key[8] = {0}; - bool have_debit_key = false; + bool auth = false; CLIGetHexWithReturn(ctx, 2, key, &key_len); @@ -1361,7 +1361,7 @@ static int CmdHFiClassDump(const char *Cmd) { } if (key_len > 0) { - have_debit_key = true; + auth = true; if (key_len != 8) { PrintAndLogEx(ERR, "Debit key is incorrect length"); CLIParserFree(ctx); @@ -1371,7 +1371,7 @@ static int CmdHFiClassDump(const char *Cmd) { if (deb_key_nr >= 0) { if (deb_key_nr < ICLASS_KEYS_MAX) { - have_debit_key = true; + auth = true; memcpy(key, iClass_Key_Table[deb_key_nr], 8); PrintAndLogEx(INFO, "AA1 (debit) index %u", deb_key_nr); } else { @@ -1396,6 +1396,7 @@ static int CmdHFiClassDump(const char *Cmd) { } if (credit_key_len > 0) { + auth = true; have_credit_key = true; if (key_len != 8) { PrintAndLogEx(ERR, "Credit key is incorrect length"); @@ -1406,6 +1407,7 @@ static int CmdHFiClassDump(const char *Cmd) { if (credit_key_nr >= 0) { if (credit_key_nr < ICLASS_KEYS_MAX) { + auth = true; have_credit_key = true; memcpy(key, iClass_Key_Table[credit_key_nr], 8); PrintAndLogEx(INFO, "AA2 (credit) index %u", credit_key_nr); @@ -1482,11 +1484,11 @@ static int CmdHFiClassDump(const char *Cmd) { if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { PrintAndLogEx(INFO, "Dumping all available memory, block 3 - %u (0x%02x)", app_limit1, app_limit1); - if (have_debit_key) { + if (auth) { PrintAndLogEx(INFO, "No keys needed, ignoring user supplied key"); } } else { - if (have_debit_key == false) { + if (auth == false) { PrintAndLogEx(FAILED, "Run command with keys"); return PM3_ESOFT; } @@ -1499,7 +1501,7 @@ static int CmdHFiClassDump(const char *Cmd) { .req.use_credit_key = false, .req.use_replay = use_replay, .req.send_reply = true, - .req.do_auth = have_debit_key, + .req.do_auth = auth, .end_block = app_limit1, }; memcpy(payload.req.key, key, 8); @@ -1937,13 +1939,13 @@ static int CmdHFiClassRestore(const char *Cmd) { if (verbose) { PrintAndLogEx(INFO, "Preparing to restore block range %02d..%02d", startblock, endblock); - PrintAndLogEx(INFO, "------+----------------------"); - PrintAndLogEx(INFO, "block | data"); - PrintAndLogEx(INFO, "------+----------------------"); + PrintAndLogEx(INFO, "---------+----------------------"); + PrintAndLogEx(INFO, " block# | data"); + PrintAndLogEx(INFO, "---------+----------------------"); for (uint8_t i = 0; i < payload->item_cnt; i++) { iclass_restore_item_t item = payload->blocks[i]; - PrintAndLogEx(INFO, " %02d | %s", item.blockno, sprint_hex_inrow(item.data, sizeof(item.data))); + PrintAndLogEx(INFO, "%3d/0x%02X | %s", item.blockno, item.blockno, sprint_hex_inrow(item.data, sizeof(item.data))); } } @@ -2277,9 +2279,9 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e int i = startblock; PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "blk | data | ascii |lck| info"); - PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------"); - PrintAndLogEx(INFO, " 00 | " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8)); + PrintAndLogEx(INFO, " block# | data | ascii |lck| info"); + PrintAndLogEx(INFO, "---------+-------------------------+----------+---+--------------"); + PrintAndLogEx(INFO, " 0/0x00 | " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8)); if (i != 1) PrintAndLogEx(INFO, "...."); @@ -2332,18 +2334,18 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e s = info_nonks[i]; } - PrintAndLogEx(INFO, " %02d | %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); + PrintAndLogEx(INFO, "%3d/0x%02X | %s | %s | %s ", i, i, sprint_hex_ascii(blk, 8), lockstr, s); } else { const char *info_ks[] = {"CSN", "Config", "E-purse", "Debit", "Credit", "AIA", "User"}; const char *s = info_ks[6]; if (i < 6) { s = info_ks[i]; } - PrintAndLogEx(INFO, " %02d | %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); + PrintAndLogEx(INFO, "%3d/0x%02X | %s | %s | %s ", i, i, sprint_hex_ascii(blk, 8), lockstr, s); } i++; } - PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------"); + PrintAndLogEx(INFO, "---------+-------------------------+----------+---+--------------"); PrintAndLogEx(NORMAL, ""); } From 5130bb24e204a7c18d87f894b51cce733c48bd44 Mon Sep 17 00:00:00 2001 From: tcprst Date: Wed, 25 Nov 2020 21:16:08 -0500 Subject: [PATCH 4/6] hf iclass rdbl - now use cliparser --- client/src/cmdhficlass.c | 181 +++++++++++++++++---------------------- doc/cheatsheet.md | 13 ++- 2 files changed, 87 insertions(+), 107 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index b55f2801c..0ab48a161 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -91,25 +91,6 @@ static int usage_hf_iclass_writeblock(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_readblock(void) { - PrintAndLogEx(NORMAL, "Read a iCLASS block from tag\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass rdbl b k [c|e|r|v]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " b : The block number as 2 hex symbols"); - PrintAndLogEx(NORMAL, " k : access Key as 16 hex symbols or 1 hex to select key from memory OR NR/MAC for replay"); - PrintAndLogEx(NORMAL, " c : credit key assumed\n"); - PrintAndLogEx(NORMAL, " e : elite computations applied to key"); - PrintAndLogEx(NORMAL, " r : raw, no computations applied to key"); - PrintAndLogEx(NORMAL, " n : replay of NR/MAC"); - PrintAndLogEx(NORMAL, " v : verbose output"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass rdbl b 06 k 0011223344556677")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass rdbl b 1B k 0011223344556677 c")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass rdbl b 0A k 0")); - 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"); @@ -1373,7 +1354,7 @@ static int CmdHFiClassDump(const char *Cmd) { if (deb_key_nr < ICLASS_KEYS_MAX) { auth = true; memcpy(key, iClass_Key_Table[deb_key_nr], 8); - PrintAndLogEx(INFO, "AA1 (debit) index %u", deb_key_nr); + PrintAndLogEx(SUCCESS, "Using AA1 (debit) key[%d] " _GREEN_("%s"), deb_key_nr, sprint_hex(iClass_Key_Table[deb_key_nr], 8)); } else { PrintAndLogEx(ERR, "Key number is invalid"); CLIParserFree(ctx); @@ -1410,7 +1391,7 @@ static int CmdHFiClassDump(const char *Cmd) { auth = true; have_credit_key = true; memcpy(key, iClass_Key_Table[credit_key_nr], 8); - PrintAndLogEx(INFO, "AA2 (credit) index %u", credit_key_nr); + PrintAndLogEx(SUCCESS, "Using AA2 (credit) key[%d] " _GREEN_("%s"), credit_key_nr, sprint_hex(iClass_Key_Table[credit_key_nr], 8)); } else { PrintAndLogEx(ERR, "Key number is invalid"); CLIParserFree(ctx); @@ -2019,94 +2000,88 @@ static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, boo } static int CmdHFiClass_ReadBlock(const char *Cmd) { - uint8_t blockno = 0; - uint8_t keyType = 0x88; //debit key - uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t key_idx = 0; - uint8_t key_len = 0; - char tempStr[50] = {0}; - bool got_blockno = false; - bool elite = false; - bool rawkey = false; - bool use_replay = false; - bool errors = false; - bool auth = false; - bool verbose = false; - uint8_t cmdp = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass rdbl", + "Read a iCLASS block from tag", + "hf iclass rdbl -b 6 -k 0011223344556677\n" + "hf iclass rdbl -b 27 -k 0011223344556677 --credit\n" + "hf iclass rdbl -b 10 --ki 0"); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_readblock(); - case 'b': - blockno = param_get8ex(Cmd, cmdp + 1, 7, 16); - got_blockno = true; - cmdp += 2; - break; - case 'c': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("KC credit")); - keyType = 0x18; - cmdp++; - break; - case 'e': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); - elite = true; - cmdp++; - break; - case 'k': - auth = true; - key_len = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (key_len == 16) { - errors = param_gethex(tempStr, 0, KEY, key_len); - } else if (key_len == 1) { - key_idx = param_get8(Cmd, cmdp + 1); - if (key_idx < ICLASS_KEYS_MAX) { - memcpy(KEY, iClass_Key_Table[key_idx], 8); - } else { - PrintAndLogEx(WARNING, "\nERROR: key index is invalid\n"); - errors = true; - } - } else { - PrintAndLogEx(WARNING, "\nERROR: incorrect key length\n"); - errors = true; - } - cmdp += 2; - break; - case 'r': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); - rawkey = true; - cmdp++; - break; - case 'n': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode")); - use_replay = true; - cmdp++; - break; - case 'v': - verbose = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), + arg_int1("b", "block", "", "The block number to read as an integer"), + 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_lit0(NULL, "nr", "replay of NR/MAC"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int key_len = 0; + uint8_t key[8] = {0}; + + CLIGetHexWithReturn(ctx, 1, key, &key_len); + + int key_nr = arg_get_int_def(ctx, 2, -1); + + if (key_len > 0 && key_nr >= 0) { + PrintAndLogEx(ERR, "Please specify key or index, not both"); + CLIParserFree(ctx); + return PM3_EINVARG; } - if (got_blockno == false) - errors = true; + + bool auth = false; + + if (key_len > 0) { + auth = true; + if (key_len != 8) { + PrintAndLogEx(ERR, "Key is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else if (key_nr >= 0) { + if (key_nr < ICLASS_KEYS_MAX) { + auth = true; + memcpy(key, iClass_Key_Table[key_nr], 8); + PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8)); + } else { + PrintAndLogEx(ERR, "Key number is invalid"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else { + PrintAndLogEx(ERR, "Please specify a key or key index"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + int blockno = arg_get_int_def(ctx, 3, 0); + + uint8_t keyType = 0x88; //debit key + if (arg_get_lit(ctx, 4)) { + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("credit") " key"); + keyType = 0x18; //credit key + } + + bool elite = arg_get_lit(ctx, 5); + bool rawkey = arg_get_lit(ctx, 6); + bool use_replay = arg_get_lit(ctx, 7); + bool verbose = arg_get_lit(ctx, 8); + + CLIParserFree(ctx); if ((use_replay + rawkey + elite) > 1) { - PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); - errors = true; + PrintAndLogEx(ERR, "Can not use a combo of 'e', 'r', 'n'"); + return PM3_EINVARG; } - if (errors) return usage_hf_iclass_readblock(); - if (verbose) { - if (key_len == 1) - PrintAndLogEx(SUCCESS, "Using key[%d] %s", key_idx, sprint_hex(KEY, 8)); - else - PrintAndLogEx(SUCCESS, "Using key %s", sprint_hex(KEY, 8)); + if (key_len > 0) + PrintAndLogEx(SUCCESS, "Using key %s", sprint_hex(key, 8)); } if (auth == false && verbose) { @@ -2115,7 +2090,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { } uint8_t data[8] = {0}; - int res = iclass_read_block(KEY, blockno, keyType, elite, rawkey, use_replay, verbose, auth, data); + int res = iclass_read_block(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, data); if (res != PM3_SUCCESS) return res; diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index c466a4784..3e092a173 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -78,10 +78,15 @@ Read iCLASS Block ``` Options --- -b : The block number as 2 hex symbols -k : Access Key as 16 hex symbols or 1 hex to select key from memory +-k, --key Access key as 16 hex symbols +-b, --block The block number to read as an integer + --ki Key index to select key from memory 'hf iclass managekeys' + --credit key is assumed to be the credit key + --elite elite computations applied to key + --raw no computations applied to key (raw) + --nr replay of NR/MAC -pm3 --> hf iclass rdbl b 7 k 0 +pm3 --> hf iclass rdbl -b 7 --ki 0 ``` Write to iCLASS Block @@ -149,7 +154,7 @@ pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin Clone iCLASS Legacy Sequence ``` -pm3 --> hf iclass rdbl b 7 k 0 +pm3 --> hf iclass rdbl -b 7 --ki 0 pm3 --> hf iclass wrbl b 7 d 6ce099fe7e614fd0 k 0 ``` From f723ed03869230d1bcfba1e35206f8b0db628bd7 Mon Sep 17 00:00:00 2001 From: tcprst Date: Thu, 26 Nov 2020 00:11:54 -0500 Subject: [PATCH 5/6] hf iclass wrbl - now use cliparser --- client/src/cmdhficlass.c | 192 ++++++++++++++++----------------------- doc/cheatsheet.md | 15 ++- 2 files changed, 88 insertions(+), 119 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 0ab48a161..6bb215344 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -71,26 +71,6 @@ static int usage_hf_iclass_sim(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_writeblock(void) { - PrintAndLogEx(NORMAL, "Write data to a iCLASS tag\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass wrbl b d k [c|e|r|v]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " b : The block number as 2 hex symbols"); - PrintAndLogEx(NORMAL, " d : set the Data to write as 16 hex symbols"); - PrintAndLogEx(NORMAL, " k : access Key as 16 hex symbols or 1 hex to select key from memory OR NR/MAC for replay"); - PrintAndLogEx(NORMAL, " c : credit key assumed\n"); - PrintAndLogEx(NORMAL, " e : elite computations applied to key"); - PrintAndLogEx(NORMAL, " r : raw, no computations applied to key (raw)"); -// PrintAndLogEx(NORMAL, " n : replay of NR/MAC"); - PrintAndLogEx(NORMAL, " v : verbose output"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass wrbl b 0A d AAAAAAAAAAAAAAAA k 001122334455667B")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass wrbl b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass wrbl b 1B d AAAAAAAAAAAAAAAA k 0")); - 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"); @@ -1675,103 +1655,91 @@ static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bo } static int CmdHFiClass_WriteBlock(const char *Cmd) { - uint8_t blockno = 0; - uint8_t bldata[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t keyNbr = 0; - uint8_t dataLen = 0; - char tempStr[50] = {0}; - bool got_blockno = false; - bool use_credit_key = false; - bool elite = false; - bool rawkey = false; - bool use_replay = false; - bool errors = false; - bool verbose = false; - bool use_secure_pagemode = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_writeblock(); - case 'b': - blockno = param_get8ex(Cmd, cmdp + 1, 07, 16); - got_blockno = true; - cmdp += 2; - break; - case 'c': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); - use_credit_key = true; - cmdp++; - break; - case 'd': - if (param_gethex(Cmd, cmdp + 1, bldata, 16)) { - PrintAndLogEx(WARNING, "Data must include 16 HEX symbols\n"); - errors = true; - } - cmdp += 2; - break; - case 'e': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); - elite = true; - cmdp++; - break; - case 'k': - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { - errors = param_gethex(tempStr, 0, KEY, dataLen); - } else if (dataLen == 1) { - keyNbr = param_get8(Cmd, cmdp + 1); - if (keyNbr < ICLASS_KEYS_MAX) { - PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8)); - memcpy(KEY, 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; - } - use_secure_pagemode = true; - cmdp += 2; - break; - case 'r': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); - rawkey = true; - cmdp++; - break; - /* - case 'n': - PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode")); - use_replay = true; - cmdp++; - break; - */ - case 'v': - verbose = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass wrbl", + "Write data to an iCLASS tag", + "hf iclass wrbl -b 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B\n" + "hf iclass wrbl -b 27 -d AAAAAAAAAAAAAAAA -k 001122334455667B --credit\n" + "hf iclass wrbl -b 11 -d AAAAAAAAAAAAAAAA --ki 0"); + + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), + arg_int1("b", "block", "", "The block number to read as an integer"), + arg_str1("d", "data", "", "data to write as 16 hex symbols"), + 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_lit0(NULL, "nr", "replay of NR/MAC"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int key_len = 0; + uint8_t key[8] = {0}; + + CLIGetHexWithReturn(ctx, 1, key, &key_len); + + int key_nr = arg_get_int_def(ctx, 2, -1); + + if (key_len > 0 && key_nr >= 0) { + PrintAndLogEx(ERR, "Please specify key or index, not both"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool auth = false; + + if (key_len > 0) { + auth = true; + if (key_len != 8) { + PrintAndLogEx(ERR, "Key is incorrect length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } else if (key_nr >= 0) { + if (key_nr < ICLASS_KEYS_MAX) { + auth = true; + memcpy(key, iClass_Key_Table[key_nr], 8); + PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8)); + } else { + PrintAndLogEx(ERR, "Key number is invalid"); + CLIParserFree(ctx); + return PM3_EINVARG; } } - if (got_blockno == false) - errors = true; - if ((use_replay + rawkey + elite) > 1) { - PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); - errors = true; + int blockno = arg_get_int_def(ctx, 3, 0); + + int data_len = 0; + uint8_t data[8] = {0}; + CLIGetHexWithReturn(ctx, 4, data, &data_len); + + if (data_len != 8) { + PrintAndLogEx(ERR, "Data must be 8 bytes (16 hex characters)"); + CLIParserFree(ctx); + return PM3_EINVARG; } - if (errors || cmdp < 4) return usage_hf_iclass_writeblock(); + bool use_credit_key = arg_get_lit(ctx, 5); + bool elite = arg_get_lit(ctx, 6); + bool rawkey = arg_get_lit(ctx, 7); + bool use_replay = arg_get_lit(ctx, 8); + bool verbose = arg_get_lit(ctx, 9); - int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, use_replay, verbose, use_secure_pagemode); + CLIParserFree(ctx); + + if ((use_replay + rawkey + elite) > 1) { + PrintAndLogEx(ERR, "Can not use a combo of 'elite', 'raw', 'nr'"); + return PM3_EINVARG; + } + + int isok = iclass_write_block(blockno, data, key, use_credit_key, elite, rawkey, use_replay, verbose, auth); switch (isok) { case PM3_SUCCESS: - PrintAndLogEx(SUCCESS, "Wrote block %02X successful", blockno); + PrintAndLogEx(SUCCESS, "Wrote block %3d/0x%02X successful", blockno, blockno); break; case PM3_ETEAROFF: if (verbose) @@ -1990,7 +1958,7 @@ static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, boo } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, " block %02X : " _GREEN_("%s"), blockno, sprint_hex(packet->data, sizeof(packet->data))); + PrintAndLogEx(SUCCESS, " block %3d/0x%02X : " _GREEN_("%s"), blockno, blockno, sprint_hex(packet->data, sizeof(packet->data))); PrintAndLogEx(NORMAL, ""); if (out) @@ -2053,10 +2021,6 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { CLIParserFree(ctx); return PM3_EINVARG; } - } else { - PrintAndLogEx(ERR, "Please specify a key or key index"); - CLIParserFree(ctx); - return PM3_EINVARG; } int blockno = arg_get_int_def(ctx, 3, 0); diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 3e092a173..409f7e483 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -93,11 +93,16 @@ Write to iCLASS Block ``` Options --- -b : The block number as 2 hex symbols -d : Set the Data to write as 16 hex symbols -k : Access Key as 16 hex symbols or 1 hex to select key from memory +-k, --key Access key as 16 hex symbols +-b, --block The block number to read as an integer +-d, --data data to write as 16 hex symbols + --ki Key index to select key from memory 'hf iclass managekeys' + --credit key is assumed to be the credit key + --elite elite computations applied to key + --raw no computations applied to key (raw) + --nr replay of NR/MAC -pm3 --> hf iclass wrbl b 07 d 6ce099fe7e614fd0 k 0 +pm3 --> hf iclass wrbl -b 7 -d 6ce099fe7e614fd0 --ki 0 ``` Print keystore @@ -155,7 +160,7 @@ pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin Clone iCLASS Legacy Sequence ``` pm3 --> hf iclass rdbl -b 7 --ki 0 -pm3 --> hf iclass wrbl b 7 d 6ce099fe7e614fd0 k 0 +pm3 --> hf iclass wrbl -b 7 -d 6ce099fe7e614fd0 --ki 0 ``` Simulate iCLASS From 62196c72289f187240a3ac0c1b2cce54a4231257 Mon Sep 17 00:00:00 2001 From: tcprst Date: Thu, 26 Nov 2020 00:34:30 -0500 Subject: [PATCH 6/6] standardize argument types - hex,dec,etc --- client/src/cmdhficlass.c | 44 ++++++++++++++++++++-------------------- doc/cheatsheet.md | 38 +++++++++++++++++----------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 6bb215344..49784c4f5 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -947,8 +947,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "filename of dumpfile"), - arg_str0("d", "data", "", "3DES encrypted data"), - arg_str0("k", "key", "", "3DES transport key"), + arg_str0("d", "data", "", "3DES encrypted data"), + arg_str0("k", "key", "", "3DES transport key"), arg_lit0("v", "verbose", "verbose output"), arg_param_end }; @@ -1183,8 +1183,8 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("d", "data", "", "data to encrypt"), - arg_str0("k", "key", "", "3DES transport key"), + arg_str1("d", "data", "", "data to encrypt"), + arg_str0("k", "key", "", "3DES transport key"), arg_lit0("v", "verbose", "verbose output"), arg_param_end }; @@ -1292,10 +1292,10 @@ static int CmdHFiClassDump(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "filename to save dump to"), - arg_str0("k", "key", "", "debit key as 16 hex symbols OR NR/MAC for replay"), - arg_int0(NULL, "ki", "", "debit key index to select key from memory 'hf iclass managekeys'"), - arg_str0(NULL, "credit", "", "credit key as 16 hex symbols"), - arg_int0(NULL, "ci", "", "credit key index to select key from memory 'hf iclass managekeys'"), + arg_str0("k", "key", "", "debit key as 16 hex symbols OR NR/MAC for replay"), + arg_int0(NULL, "ki", "", "debit key index to select key from memory 'hf iclass managekeys'"), + arg_str0(NULL, "credit", "", "credit key as 16 hex symbols"), + arg_int0(NULL, "ci", "", "credit key index to select key from memory 'hf iclass managekeys'"), arg_lit0(NULL, "elite", "elite computations applied to key"), arg_lit0(NULL, "raw", "raw, the key is interpreted as raw block 3/4"), arg_lit0(NULL, "nr", "replay of NR/MAC"), @@ -1664,10 +1664,10 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("k", "key", "", "Access key as 16 hex symbols"), - arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), - arg_int1("b", "block", "", "The block number to read as an integer"), - arg_str1("d", "data", "", "data to write as 16 hex symbols"), + arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), + arg_int1("b", "block", "", "The block number to read as an integer"), + arg_str1("d", "data", "", "data to write as 16 hex symbols"), 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)"), @@ -1763,10 +1763,10 @@ static int CmdHFiClassRestore(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str1("f", "file", "", "specify a filename to restore"), - arg_str0("k", "key", "", "Access key as 16 hex symbols"), - arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), - arg_int1(NULL, "first", "", "The first block number to restore as an integer"), - arg_int1(NULL, "last", "", "The last block number to restore as an integer"), + arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), + arg_int1(NULL, "first", "", "The first block number to restore as an integer"), + arg_int1(NULL, "last", "", "The last block number to restore as an integer"), 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)"), @@ -1977,9 +1977,9 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("k", "key", "", "Access key as 16 hex symbols"), - arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), - arg_int1("b", "block", "", "The block number to read as an integer"), + arg_str0("k", "key", "", "Access key as 16 hex symbols"), + arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), + arg_int1("b", "block", "", "The block number to read as an integer"), 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)"), @@ -2298,8 +2298,8 @@ static int CmdHFiClassView(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str1("f", "file", "", "filename of dump"), - arg_int0(NULL, "first", "", "Begin printing from this block (default block6)"), - arg_int0(NULL, "last", "", "End printing at this block (default 0, ALL)"), + arg_int0(NULL, "first", "", "Begin printing from this block (default block6)"), + arg_int0(NULL, "last", "", "End printing at this block (default 0, ALL)"), arg_lit0("v", "verbose", "verbose output"), arg_param_end }; @@ -3224,7 +3224,7 @@ static int CmdHFiClassPermuteKey(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_lit0("r", "reverse", "reverse permuted key"), - arg_str1(NULL, "key", "", "input key"), + arg_str1(NULL, "key", "", "input key"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 409f7e483..e725d8d25 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -63,10 +63,10 @@ Dump iCLASS card contents Options --- -f, --file filename to save dump to --k, --key debit key as 16 hex symbols OR NR/MAC for replay - --ki debit key index to select key from memory 'hf iclass managekeys' - --credit credit key as 16 hex symbols - --ci credit key index to select key from memory 'hf iclass managekeys' +-k, --key debit key as 16 hex symbols OR NR/MAC for replay + --ki debit key index to select key from memory 'hf iclass managekeys' + --credit credit key as 16 hex symbols + --ci credit key index to select key from memory 'hf iclass managekeys' --elite elite computations applied to key --raw raw, the key is interpreted as raw block 3/4 --nr replay of NR/MAC @@ -78,9 +78,9 @@ Read iCLASS Block ``` Options --- --k, --key Access key as 16 hex symbols --b, --block The block number to read as an integer - --ki Key index to select key from memory 'hf iclass managekeys' +-k, --key Access key as 16 hex symbols +-b, --block The block number to read as an integer + --ki Key index to select key from memory 'hf iclass managekeys' --credit key is assumed to be the credit key --elite elite computations applied to key --raw no computations applied to key (raw) @@ -93,14 +93,14 @@ Write to iCLASS Block ``` Options --- --k, --key Access key as 16 hex symbols --b, --block The block number to read as an integer --d, --data data to write as 16 hex symbols - --ki Key index to select key from memory 'hf iclass managekeys' - --credit key is assumed to be the credit key - --elite elite computations applied to key - --raw no computations applied to key (raw) - --nr replay of NR/MAC +-k, --key Access key as 16 hex symbols +-b, --block The block number to read as an integer +-d, --data data to write as 16 hex symbols + --ki Key index to select key from memory 'hf iclass managekeys' + --credit key is assumed to be the credit key + --elite elite computations applied to key + --raw no computations applied to key (raw) + --nr replay of NR/MAC pm3 --> hf iclass wrbl -b 7 -d 6ce099fe7e614fd0 --ki 0 ``` @@ -128,8 +128,8 @@ Encrypt iCLASS Block ``` Options --- --d, --data data to encrypt --k, --key 3DES transport key +-d, --data data to encrypt +-k, --key 3DES transport key -v, --verbose verbose output pm3 --> hf iclass encrypt -d 0000000f2aa3dba8 @@ -140,8 +140,8 @@ Decrypt iCLASS Block / file Options --- -f, --file filename of dumpfile --d, --data 3DES encrypted data --k, --key 3DES transport key +-d, --data 3DES encrypted data +-k, --key 3DES transport key -v, --verbose verbose output pm3 --> hf iclass decrypt -d 2AD4C8211F996871