Merge pull request #1070 from tcprst/iclass_cliparser

hf iclass dump, restore, rdbl cliparserization and argument normalization
This commit is contained in:
Iceman 2020-11-26 06:35:40 +01:00 committed by GitHub
commit 6066179d35
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 378 additions and 467 deletions

View file

@ -1999,10 +1999,10 @@ void iClass_Restore(iclass_restore_req_t *msg) {
// data + mac // data + mac
if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac)) { if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac)) {
Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno); Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), item.blockno, item.blockno);
written++; written++;
} else { } else {
Dbprintf("Write block [%02x] " _RED_("failed"), item.blockno); Dbprintf("Write block [%3d/0x%02X] " _RED_("failed"), item.blockno, item.blockno);
} }
} }

View file

@ -71,85 +71,6 @@ static int usage_hf_iclass_sim(void) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS; 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 <fileName> k <key> c <creditkey> [e|r|v]\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : Show this help");
PrintAndLogEx(NORMAL, " f <filename> : specify a filename to save dump to");
PrintAndLogEx(NORMAL, " k <key> : access Key as 16 hex symbols or 1 hex to select key from memory OR NR/MAC for replay");
PrintAndLogEx(NORMAL, " c <creditkey>: 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 <tagfile.bin> b <first block> l <last block> k <KEY> c e|r\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : Show this help");
PrintAndLogEx(NORMAL, " f <filename> : specify a filename to restore");
PrintAndLogEx(NORMAL, " b <block> : The first block to restore as 2 hex symbols");
PrintAndLogEx(NORMAL, " l <last blk> : The last block to restore as 2 hex symbols");
PrintAndLogEx(NORMAL, " k <key> : 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 <block> d <data> k <key> [c|e|r|v]\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : Show this help");
PrintAndLogEx(NORMAL, " b <block> : The block number as 2 hex symbols");
PrintAndLogEx(NORMAL, " d <data> : set the Data to write as 16 hex symbols");
PrintAndLogEx(NORMAL, " k <key> : 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_readblock(void) {
PrintAndLogEx(NORMAL, "Read a iCLASS block from tag\n");
PrintAndLogEx(NORMAL, "Usage: hf iclass rdbl b <block> k <key> [c|e|r|v]\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : Show this help");
PrintAndLogEx(NORMAL, " b <block> : The block number as 2 hex symbols");
PrintAndLogEx(NORMAL, " k <key> : 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) { static int usage_hf_iclass_calc_newkey(void) {
PrintAndLogEx(NORMAL, "Calculate new key for updating\n"); PrintAndLogEx(NORMAL, "Calculate new key for updating\n");
PrintAndLogEx(NORMAL, "Usage: hf iclass calc_newkey o <old key> n <new key> s [csn] e\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass calc_newkey o <old key> n <new key> s [csn] e\n");
@ -1026,8 +947,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("f", "file", "<filename>", "filename of dumpfile"), arg_str0("f", "file", "<filename>", "filename of dumpfile"),
arg_str0("d", "data", "<encrypted blk>", "3DES encrypted data"), arg_str0("d", "data", "<hex>", "3DES encrypted data"),
arg_str0("k", "key", "<transport key>", "3DES transport key"), arg_str0("k", "key", "<hex>", "3DES transport key"),
arg_lit0("v", "verbose", "verbose output"), arg_lit0("v", "verbose", "verbose output"),
arg_param_end arg_param_end
}; };
@ -1262,8 +1183,8 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str1("d", "data", "<block data>", "data to encrypt"), arg_str1("d", "data", "<hex>", "data to encrypt"),
arg_str0("k", "key", "<transport key>", "3DES transport key"), arg_str0("k", "key", "<hex>", "3DES transport key"),
arg_lit0("v", "verbose", "verbose output"), arg_lit0("v", "verbose", "verbose output"),
arg_param_end arg_param_end
}; };
@ -1359,104 +1280,117 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool verbose) {
} }
static int CmdHFiClassDump(const char *Cmd) { 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}; void *argtable[] = {
uint8_t CreditKEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; arg_param_begin,
uint8_t keyNbr = 0; arg_str0("f", "file", "<filename>", "filename to save dump to"),
uint8_t dataLen = 0; arg_str0("k", "key", "<hex>", "debit key as 16 hex symbols OR NR/MAC for replay"),
uint8_t app_limit1 = 0, app_limit2 = 0; arg_int0(NULL, "ki", "<dec>", "debit key index to select key from memory 'hf iclass managekeys'"),
uint8_t fileNameLen = 0; arg_str0(NULL, "credit", "<hex>", "credit key as 16 hex symbols"),
arg_int0(NULL, "ci", "<dec>", "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 filename[FILE_PATH_SIZE] = {0};
char tempStr[50] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
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;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { int key_len = 0;
switch (tolower(param_getchar(Cmd, cmdp))) { uint8_t key[8] = {0};
case 'h': bool auth = false;
return usage_hf_iclass_dump();
case 'c': CLIGetHexWithReturn(ctx, 2, key, &key_len);
auth = true;
have_credit_key = true; int deb_key_nr = arg_get_int_def(ctx, 3, -1);
dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr));
if (dataLen == 16) { if (key_len > 0 && deb_key_nr >= 0) {
errors = param_gethex(tempStr, 0, CreditKEY, dataLen); PrintAndLogEx(ERR, "Please specify debit key or index, not both");
} else if (dataLen == 1) { CLIParserFree(ctx);
keyNbr = param_get8(Cmd, cmdp + 1); return PM3_EINVARG;
if (keyNbr < ICLASS_KEYS_MAX) { }
memcpy(CreditKEY, iClass_Key_Table[keyNbr], 8);
PrintAndLogEx(INFO, "AA2 (credit) index %u", keyNbr); if (key_len > 0) {
} else { auth = true;
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); if (key_len != 8) {
errors = true; PrintAndLogEx(ERR, "Debit key is incorrect length");
} CLIParserFree(ctx);
} else { return PM3_EINVARG;
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;
} }
} }
if ((use_replay + rawkey + elite) > 1) { if (deb_key_nr >= 0) {
PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); if (deb_key_nr < ICLASS_KEYS_MAX) {
errors = true; auth = true;
memcpy(key, iClass_Key_Table[deb_key_nr], 8);
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);
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) {
auth = true;
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) {
auth = true;
have_credit_key = true;
memcpy(key, iClass_Key_Table[credit_key_nr], 8);
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);
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); uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
@ -1531,7 +1465,7 @@ static int CmdHFiClassDump(const char *Cmd) {
.req.do_auth = auth, .req.do_auth = auth,
.end_block = app_limit1, .end_block = app_limit1,
}; };
memcpy(payload.req.key, KEY, 8); memcpy(payload.req.key, key, 8);
// tags configured for NON SECURE PAGE, acts different // tags configured for NON SECURE PAGE, acts different
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
@ -1606,7 +1540,7 @@ static int CmdHFiClassDump(const char *Cmd) {
if (have_credit_key && pagemap != 0x01) { if (have_credit_key && pagemap != 0x01) {
// AA2 authenticate credit key // AA2 authenticate credit key
memcpy(payload.req.key, CreditKEY, 8); memcpy(payload.req.key, credit_key, 8);
payload.req.use_credit_key = true; payload.req.use_credit_key = true;
payload.start_block = app_limit1 + 1; payload.start_block = app_limit1 + 1;
@ -1721,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) { static int CmdHFiClass_WriteBlock(const char *Cmd) {
uint8_t blockno = 0; CLIParserContext *ctx;
uint8_t bldata[8] = {0, 0, 0, 0, 0, 0, 0, 0}; CLIParserInit(&ctx, "hf iclass wrbl",
uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; "Write data to an iCLASS tag",
uint8_t keyNbr = 0; "hf iclass wrbl -b 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B\n"
uint8_t dataLen = 0; "hf iclass wrbl -b 27 -d AAAAAAAAAAAAAAAA -k 001122334455667B --credit\n"
char tempStr[50] = {0}; "hf iclass wrbl -b 11 -d AAAAAAAAAAAAAAAA --ki 0");
bool got_blockno = false;
bool use_credit_key = false; void *argtable[] = {
bool elite = false; arg_param_begin,
bool rawkey = false; arg_str0("k", "key", "<hex>", "Access key as 16 hex symbols"),
bool use_replay = false; arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
bool errors = false; arg_int1("b", "block", "<dec>", "The block number to read as an integer"),
bool verbose = false; arg_str1("d", "data", "<hex>", "data to write as 16 hex symbols"),
bool use_secure_pagemode = false; arg_lit0(NULL, "credit", "key is assumed to be the credit key"),
uint8_t cmdp = 0; arg_lit0(NULL, "elite", "elite computations applied to key"),
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { arg_lit0(NULL, "raw", "no computations applied to key (raw)"),
switch (tolower(param_getchar(Cmd, cmdp))) { arg_lit0(NULL, "nr", "replay of NR/MAC"),
case 'h': arg_lit0("v", "verbose", "verbose output"),
return usage_hf_iclass_writeblock(); arg_param_end
case 'b': };
blockno = param_get8ex(Cmd, cmdp + 1, 07, 16); CLIExecWithReturn(ctx, Cmd, argtable, false);
got_blockno = true;
cmdp += 2; int key_len = 0;
break; uint8_t key[8] = {0};
case 'c':
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); CLIGetHexWithReturn(ctx, 1, key, &key_len);
use_credit_key = true;
cmdp++; int key_nr = arg_get_int_def(ctx, 2, -1);
break;
case 'd': if (key_len > 0 && key_nr >= 0) {
if (param_gethex(Cmd, cmdp + 1, bldata, 16)) { PrintAndLogEx(ERR, "Please specify key or index, not both");
PrintAndLogEx(WARNING, "Data must include 16 HEX symbols\n"); CLIParserFree(ctx);
errors = true; return PM3_EINVARG;
} }
cmdp += 2;
break; bool auth = false;
case 'e':
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); if (key_len > 0) {
elite = true; auth = true;
cmdp++; if (key_len != 8) {
break; PrintAndLogEx(ERR, "Key is incorrect length");
case 'k': CLIParserFree(ctx);
dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); return PM3_EINVARG;
if (dataLen == 16) { }
errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (key_nr >= 0) {
} else if (dataLen == 1) { if (key_nr < ICLASS_KEYS_MAX) {
keyNbr = param_get8(Cmd, cmdp + 1); auth = true;
if (keyNbr < ICLASS_KEYS_MAX) { memcpy(key, iClass_Key_Table[key_nr], 8);
PrintAndLogEx(SUCCESS, "Using key[%d] %s", keyNbr, sprint_hex(iClass_Key_Table[keyNbr], 8)); PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8));
memcpy(KEY, iClass_Key_Table[keyNbr], 8); } else {
} else { PrintAndLogEx(ERR, "Key number is invalid");
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); CLIParserFree(ctx);
errors = true; return PM3_EINVARG;
}
} 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;
} }
} }
if (got_blockno == false)
errors = true;
if ((use_replay + rawkey + elite) > 1) { int blockno = arg_get_int_def(ctx, 3, 0);
PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'");
errors = true; 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) { switch (isok) {
case PM3_SUCCESS: case PM3_SUCCESS:
PrintAndLogEx(SUCCESS, "Wrote block %02X successful", blockno); PrintAndLogEx(SUCCESS, "Wrote block %3d/0x%02X successful", blockno, blockno);
break; break;
case PM3_ETEAROFF: case PM3_ETEAROFF:
if (verbose) if (verbose)
@ -1831,92 +1753,75 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) {
} }
static int CmdHFiClassRestore(const char *Cmd) { static int CmdHFiClassRestore(const char *Cmd) {
char filename[FILE_PATH_SIZE] = { 0x00 }; CLIParserContext *ctx;
char tempStr[50] = {0}; CLIParserInit(&ctx, "hf iclass restore",
uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; "Restore data from dumpfile onto a iCLASS tag",
uint8_t keyNbr = 0; "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 06 --last 1A -k 1122334455667788 --elite\n"
uint8_t fileNameLen = 0; "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 05 --last 19 --ki 0\n"
uint8_t startblock = 0; "hf iclass restore -f hf-iclass-AA162D30F8FF12F1-dump.bin --first 06 --last 19 --ki 0 --elite");
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;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { void *argtable[] = {
switch (tolower(param_getchar(Cmd, cmdp))) { arg_param_begin,
case 'h': arg_str1("f", "file", "<filename>", "specify a filename to restore"),
return usage_hf_iclass_restore(); arg_str0("k", "key", "<hex>", "Access key as 16 hex symbols"),
case 'b': arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
startblock = param_get8ex(Cmd, cmdp + 1, 07, 16); arg_int1(NULL, "first", "<dec>", "The first block number to restore as an integer"),
got_startblk = true; arg_int1(NULL, "last", "<dec>", "The last block number to restore as an integer"),
cmdp += 2; arg_lit0(NULL, "credit", "key is assumed to be the credit key"),
break; arg_lit0(NULL, "elite", "elite computations applied to key"),
case 'c': arg_lit0(NULL, "raw", "no computations applied to key (raw)"),
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("CREDIT")); arg_lit0("v", "verbose", "verbose output"),
use_credit_key = true; arg_param_end
cmdp++; };
break; CLIExecWithReturn(ctx, Cmd, argtable, false);
case 'e':
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); int fnlen = 0;
elite = true; char filename[FILE_PATH_SIZE] = {0};
cmdp++; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
break;
case 'f': int key_len = 0;
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); uint8_t key[8] = {0};
if (fileNameLen < 1) {
PrintAndLogEx(WARNING, "No filename found after f"); CLIGetHexWithReturn(ctx, 2, key, &key_len);
errors = true;
} int key_nr = arg_get_int_def(ctx, 3, -1);
cmdp += 2;
break; if (key_len > 0 && key_nr >= 0) {
case 'k': PrintAndLogEx(ERR, "Please specify key or index, not both");
dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); CLIParserFree(ctx);
if (dataLen == 16) { return PM3_EINVARG;
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;
}
} }
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) { if (rawkey + elite > 1) {
PrintAndLogEx(FAILED, "Can not use both 'e', 'r'"); PrintAndLogEx(FAILED, "Can not use both 'e', 'r'");
@ -1964,7 +1869,7 @@ static int CmdHFiClassRestore(const char *Cmd) {
payload->req.blockno = startblock; payload->req.blockno = startblock;
payload->req.send_reply = true; payload->req.send_reply = true;
payload->req.do_auth = true; payload->req.do_auth = true;
memcpy(payload->req.key, KEY, 8); memcpy(payload->req.key, key, 8);
payload->item_cnt = (endblock - startblock + 1); payload->item_cnt = (endblock - startblock + 1);
@ -1981,15 +1886,15 @@ static int CmdHFiClassRestore(const char *Cmd) {
free(dump); free(dump);
if (verbose) { 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, "---------+----------------------");
PrintAndLogEx(INFO, "block | data"); PrintAndLogEx(INFO, " block# | data");
PrintAndLogEx(INFO, "------+----------------------"); PrintAndLogEx(INFO, "---------+----------------------");
for (uint8_t i = 0; i < payload->item_cnt; i++) { for (uint8_t i = 0; i < payload->item_cnt; i++) {
iclass_restore_item_t item = payload->blocks[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, "%3d/0x%02X | %s", item.blockno, item.blockno, sprint_hex_inrow(item.data, sizeof(item.data)));
} }
} }
@ -2053,7 +1958,7 @@ static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, boo
} }
PrintAndLogEx(NORMAL, ""); 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, ""); PrintAndLogEx(NORMAL, "");
if (out) if (out)
@ -2063,94 +1968,84 @@ static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, boo
} }
static int CmdHFiClass_ReadBlock(const char *Cmd) { static int CmdHFiClass_ReadBlock(const char *Cmd) {
uint8_t blockno = 0; CLIParserContext *ctx;
uint8_t keyType = 0x88; //debit key CLIParserInit(&ctx, "hf iclass rdbl",
uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; "Read a iCLASS block from tag",
uint8_t key_idx = 0; "hf iclass rdbl -b 6 -k 0011223344556677\n"
uint8_t key_len = 0; "hf iclass rdbl -b 27 -k 0011223344556677 --credit\n"
char tempStr[50] = {0}; "hf iclass rdbl -b 10 --ki 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;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { void *argtable[] = {
switch (tolower(param_getchar(Cmd, cmdp))) { arg_param_begin,
case 'h': arg_str0("k", "key", "<hex>", "Access key as 16 hex symbols"),
return usage_hf_iclass_readblock(); arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
case 'b': arg_int1("b", "block", "<dec>", "The block number to read as an integer"),
blockno = param_get8ex(Cmd, cmdp + 1, 7, 16); arg_lit0(NULL, "credit", "key is assumed to be the credit key"),
got_blockno = true; arg_lit0(NULL, "elite", "elite computations applied to key"),
cmdp += 2; arg_lit0(NULL, "raw", "no computations applied to key (raw)"),
break; arg_lit0(NULL, "nr", "replay of NR/MAC"),
case 'c': arg_lit0("v", "verbose", "verbose output"),
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("KC credit")); arg_param_end
keyType = 0x18; };
cmdp++; CLIExecWithReturn(ctx, Cmd, argtable, false);
break;
case 'e': int key_len = 0;
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("elite algo")); uint8_t key[8] = {0};
elite = true;
cmdp++; CLIGetHexWithReturn(ctx, 1, key, &key_len);
break;
case 'k': int key_nr = arg_get_int_def(ctx, 2, -1);
auth = true;
key_len = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); if (key_len > 0 && key_nr >= 0) {
if (key_len == 16) { PrintAndLogEx(ERR, "Please specify key or index, not both");
errors = param_gethex(tempStr, 0, KEY, key_len); CLIParserFree(ctx);
} else if (key_len == 1) { return PM3_EINVARG;
key_idx = param_get8(Cmd, cmdp + 1); }
if (key_idx < ICLASS_KEYS_MAX) {
memcpy(KEY, iClass_Key_Table[key_idx], 8); bool auth = false;
} else {
PrintAndLogEx(WARNING, "\nERROR: key index is invalid\n"); if (key_len > 0) {
errors = true; auth = true;
} if (key_len != 8) {
} else { PrintAndLogEx(ERR, "Key is incorrect length");
PrintAndLogEx(WARNING, "\nERROR: incorrect key length\n"); CLIParserFree(ctx);
errors = true; return PM3_EINVARG;
} }
cmdp += 2; } else if (key_nr >= 0) {
break; if (key_nr < ICLASS_KEYS_MAX) {
case 'r': auth = true;
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("raw mode")); memcpy(key, iClass_Key_Table[key_nr], 8);
rawkey = true; PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8));
cmdp++; } else {
break; PrintAndLogEx(ERR, "Key number is invalid");
case 'n': CLIParserFree(ctx);
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode")); return PM3_EINVARG;
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;
} }
} }
if (got_blockno == false)
errors = true;
if ((use_replay + rawkey + elite) > 1) { int blockno = arg_get_int_def(ctx, 3, 0);
PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'");
errors = true; uint8_t keyType = 0x88; //debit key
if (arg_get_lit(ctx, 4)) {
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("credit") " key");
keyType = 0x18; //credit key
} }
if (errors) return usage_hf_iclass_readblock(); 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(ERR, "Can not use a combo of 'e', 'r', 'n'");
return PM3_EINVARG;
}
if (verbose) { if (verbose) {
if (key_len == 1) if (key_len > 0)
PrintAndLogEx(SUCCESS, "Using key[%d] %s", key_idx, sprint_hex(KEY, 8)); PrintAndLogEx(SUCCESS, "Using key %s", sprint_hex(key, 8));
else
PrintAndLogEx(SUCCESS, "Using key %s", sprint_hex(KEY, 8));
} }
if (auth == false && verbose) { if (auth == false && verbose) {
@ -2159,7 +2054,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
} }
uint8_t data[8] = {0}; 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) if (res != PM3_SUCCESS)
return res; return res;
@ -2323,9 +2218,9 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
int i = startblock; int i = startblock;
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, " blk| data | ascii |lck| info"); PrintAndLogEx(INFO, " block# | data | ascii |lck| info");
PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------"); PrintAndLogEx(INFO, "---------+-------------------------+----------+---+--------------");
PrintAndLogEx(INFO, "0x00| " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8)); PrintAndLogEx(INFO, " 0/0x00 | " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8));
if (i != 1) if (i != 1)
PrintAndLogEx(INFO, "...."); PrintAndLogEx(INFO, "....");
@ -2378,18 +2273,18 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
s = info_nonks[i]; s = info_nonks[i];
} }
PrintAndLogEx(INFO, "0x%02X| %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 { } else {
const char *info_ks[] = {"CSN", "Config", "E-purse", "Debit", "Credit", "AIA", "User"}; const char *info_ks[] = {"CSN", "Config", "E-purse", "Debit", "Credit", "AIA", "User"};
const char *s = info_ks[6]; const char *s = info_ks[6];
if (i < 6) { if (i < 6) {
s = info_ks[i]; s = info_ks[i];
} }
PrintAndLogEx(INFO, "0x%02X| %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++; i++;
} }
PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------"); PrintAndLogEx(INFO, "---------+-------------------------+----------+---+--------------");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
} }
@ -2398,14 +2293,14 @@ static int CmdHFiClassView(const char *Cmd) {
CLIParserInit(&ctx, "hf iclass view", CLIParserInit(&ctx, "hf iclass view",
"Print a iCLASS tag dump file", "Print a iCLASS tag dump file",
"hf iclass view -f hf-iclass-AA162D30F8FF12F1-dump.bin\n" "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[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str1("f", "file", "<filename>", "filename of dump"), arg_str1("f", "file", "<filename>", "filename of dump"),
arg_int0("s", "startblock", "<dec>", "print from this block (default block6)"), arg_int0(NULL, "first", "<dec>", "Begin printing from this block (default block6)"),
arg_int0("e", "endblock", "<dec>", "end printing at this block (default 0, ALL)"), arg_int0(NULL, "last", "<dec>", "End printing at this block (default 0, ALL)"),
arg_lit0("v", "verbose", "verbose output"), arg_lit0("v", "verbose", "verbose output"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -2430,8 +2325,7 @@ static int CmdHFiClassView(const char *Cmd) {
if (verbose) { if (verbose) {
PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename); 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, "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, "Printing blocks from: " _YELLOW_("%02d") " to: " _YELLOW_("%02d"), (startblock == 0) ? 6 : startblock, endblock);
PrintAndLogEx(INFO, "start " _YELLOW_("0x%02x") " end " _YELLOW_("0x%02x"), (startblock == 0) ? 6 : startblock, endblock);
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -3330,7 +3224,7 @@ static int CmdHFiClassPermuteKey(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("r", "reverse", "reverse permuted key"), arg_lit0("r", "reverse", "reverse permuted key"),
arg_str1(NULL, "key", "<bytes>", "input key"), arg_str1(NULL, "key", "<hex>", "input key"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);

View file

@ -62,30 +62,47 @@ Dump iCLASS card contents
``` ```
Options Options
--- ---
k <key> : *Access Key as 16 hex symbols or 1 hex to select key from memory -f, --file <filename> filename to save dump to
-k, --key <hex> debit key as 16 hex symbols OR NR/MAC for replay
--ki <dec> debit key index to select key from memory 'hf iclass managekeys'
--credit <hex> credit key as 16 hex symbols
--ci <dec> 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 Read iCLASS Block
``` ```
Options Options
--- ---
b <block> : The block number as 2 hex symbols -k, --key <hex> Access key as 16 hex symbols
k <key> : Access Key as 16 hex symbols or 1 hex to select key from memory -b, --block <dec> The block number to read as an integer
--ki <dec> 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 Write to iCLASS Block
``` ```
Options Options
--- ---
b <block> : The block number as 2 hex symbols -k, --key <hex> Access key as 16 hex symbols
d <data> : Set the Data to write as 16 hex symbols -b, --block <dec> The block number to read as an integer
k <key> : Access Key as 16 hex symbols or 1 hex to select key from memory -d, --data <hex> data to write as 16 hex symbols
--ki <dec> 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 Print keystore
@ -111,8 +128,8 @@ Encrypt iCLASS Block
``` ```
Options Options
--- ---
-d, --data <block data> data to encrypt -d, --data <hex> data to encrypt
-k, --key <transport key> 3DES transport key -k, --key <hex> 3DES transport key
-v, --verbose verbose output -v, --verbose verbose output
pm3 --> hf iclass encrypt -d 0000000f2aa3dba8 pm3 --> hf iclass encrypt -d 0000000f2aa3dba8
@ -123,8 +140,8 @@ Decrypt iCLASS Block / file
Options Options
--- ---
-f, --file <filename> filename of dumpfile -f, --file <filename> filename of dumpfile
-d, --data <encrypted blk> 3DES encrypted data -d, --data <hex> 3DES encrypted data
-k, --key <transport key> 3DES transport key -k, --key <hex> 3DES transport key
-v, --verbose verbose output -v, --verbose verbose output
pm3 --> hf iclass decrypt -d 2AD4C8211F996871 pm3 --> hf iclass decrypt -d 2AD4C8211F996871
@ -142,8 +159,8 @@ pm3 --> hf iclass eload -f hf-iclass-db883702f8ff12e0.bin
Clone iCLASS Legacy Sequence 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 pm3 --> hf iclass wrbl -b 7 -d 6ce099fe7e614fd0 --ki 0
``` ```
Simulate iCLASS Simulate iCLASS
@ -161,7 +178,7 @@ pm3 --> hf iclass sim 3
Simulate iCLASS Sequence 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 eload -f hf-iclass-db883702f8ff12e0.bin
pm3 --> hf iclass sim 3 pm3 --> hf iclass sim 3
``` ```
@ -177,7 +194,7 @@ e : If 'e' is specified, elite computations applied to key
pm3 --> hf iclass sim 2 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 <Kcus> pm3 --> hf iclass managekeys n 7 k <Kcus>
pm3 --> hf iclass dump k 7 e pm3 --> hf iclass dump --ki 7 --elite
``` ```
Verify custom iCLASS key Verify custom iCLASS key