diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 9aa65de03..0b274f654 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1512,20 +1512,19 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_ICLASS_SIMULATE: { - SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); - break; - } - case CMD_HF_ICLASS_READER: { - ReaderIClass(packet->oldarg[0]); - break; - } - case CMD_HF_ICLASS_REPLAY: { +/* struct p { uint8_t reader[4]; uint8_t mac[4]; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - ReaderIClass_Replay(payload->reader, payload->mac); +*/ + + SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); + break; + } + case CMD_HF_ICLASS_READER: { + ReaderIClass(packet->oldarg[0]); break; } case CMD_HF_ICLASS_EML_MEMSET: { diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 7f22b59cc..baaff65c5 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1470,101 +1470,6 @@ void ReaderIClass(uint8_t flags) { switch_off(); } -// turn off afterwards -void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac) { - - BigBuf_free(); - - uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - memcpy(check + 1, rnr, 4); - memcpy(check + 5, mac, 4); - - uint8_t *card_data = BigBuf_malloc(ICLASS_16KS_SIZE); - if (card_data == NULL) { - DbpString("fail to allocate memory"); - reply_ng(CMD_HF_ICLASS_REPLAY, PM3_EMALLOC, NULL, 0); - return; - } - memset(card_data, 0xFF, ICLASS_16KS_SIZE); - - uint32_t start_time = 0; - uint32_t eof_time = 0; - - Iso15693InitReader(); - - picopass_hdr hdr = {0}; - bool res = select_iclass_tag((uint8_t *)&hdr, false, &eof_time); - if (res == false) { - reply_ng(CMD_HF_ICLASS_REPLAY, PM3_ETIMEOUT, NULL, 0); - switch_off(); - return; - } - - uint8_t resp[10] = {0}; - - //for now replay captured auth (as cc not updated) - start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; - res = iclass_send_cmd_with_retries(check, sizeof(check), resp, sizeof(resp), 4, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); - if (res == false) { - reply_ng(CMD_HF_ICLASS_REPLAY, PM3_ETIMEOUT, NULL, 0); - switch_off(); - return; - } - - uint8_t mem = hdr.conf.mem_config; - uint8_t cardsize = ((mem & 0x80) == 0x80) ? 255 : 32; - - /* - static struct memory_t { - int k16; - int book; - int k2; - int lockauth; - int keyaccess; - } memory; - - // memory.k16 = ((mem & 0x80) == 0x80); - // memory.book = ((mem & 0x20) == 0x20); - // memory.k2 = ((mem & 0x08) == 0x08); - // memory.lockauth = ((mem & 0x02) == 0x02); - // memory.keyaccess = ((mem & 0x01) == 0x01); - // uint8_t cardsize = memory.k16 ? 255 : 32; - */ - - bool dumpsuccess = true; - - // main read loop - uint16_t i; - for (i = 0; i <= cardsize; i++) { - - uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, i, 0x00, 0x00}; - AddCrc(c + 1, 1); - - res = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time); - if (res) { - memcpy(card_data + (8 * i), resp, 8); - } else { - Dbprintf("failed to read block %u ( 0x%02x)", i, i); - dumpsuccess = false; - } - } - - struct p { - bool isOK; - uint16_t block_cnt; - uint32_t bb_offset; - } PACKED response; - - response.isOK = dumpsuccess; - response.block_cnt = i; - response.bb_offset = card_data - BigBuf_get_addr(); - reply_ng(CMD_HF_ICLASS_REPLAY, PM3_SUCCESS, (uint8_t *)&response, sizeof(response)); - - BigBuf_free(); - switch_off(); -} - // used with function select_and_auth (cmdhficlass.c) // which needs to authenticate before doing more things like read/write // selects and authenticate to a card, sends back div_key and mac to client. @@ -1585,24 +1490,30 @@ bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint memcpy(ccnr, hdr->epurse, sizeof(hdr->epurse)); - if (payload->use_raw) - memcpy(div_key, payload->key, 8); - else - iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite); + if ( payload->use_replay) { - if (payload->use_credit_key) - memcpy(hdr->key_c, div_key, sizeof(hdr->key_c)); - else - memcpy(hdr->key_d, div_key, sizeof(hdr->key_d)); + memcpy(pmac, payload->key + 4, 4); + memcpy(cmd_check + 1, payload->key, 8); - opt_doReaderMAC(ccnr, div_key, pmac); + } else { + if (payload->use_raw) + memcpy(div_key, payload->key, 8); + else + iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite); - // copy MAC to check command (readersignature) - cmd_check[5] = pmac[0]; - cmd_check[6] = pmac[1]; - cmd_check[7] = pmac[2]; - cmd_check[8] = pmac[3]; + if (payload->use_credit_key) + memcpy(hdr->key_c, div_key, sizeof(hdr->key_c)); + else + memcpy(hdr->key_d, div_key, sizeof(hdr->key_d)); + opt_doReaderMAC(ccnr, div_key, pmac); + + // copy MAC to check command (readersignature) + cmd_check[5] = pmac[0]; + cmd_check[6] = pmac[1]; + cmd_check[7] = pmac[2]; + cmd_check[8] = pmac[3]; + } return iclass_send_cmd_with_retries(cmd_check, sizeof(cmd_check), resp_auth, sizeof(resp_auth), 4, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time); } @@ -1937,10 +1848,14 @@ void iClass_WriteBlock(uint8_t *msg) { wb[0] = payload->req.blockno; memcpy(wb + 1, payload->data, 8); - if (payload->req.use_credit_key) - doMAC_N(wb, sizeof(wb), hdr.key_c, mac); - else - doMAC_N(wb, sizeof(wb), hdr.key_d, mac); + if (payload->req.use_replay) { + doMAC_N(wb, sizeof(wb), payload->req.key + 4, mac); + } else { + if (payload->req.use_credit_key) + doMAC_N(wb, sizeof(wb), hdr.key_c, mac); + else + doMAC_N(wb, sizeof(wb), hdr.key_d, mac); + } memcpy(write + 2, payload->data, 8); // data memcpy(write + 10, mac, sizeof(mac)); // mac diff --git a/armsrc/iclass.h b/armsrc/iclass.h index 3776aa385..ec9ff7b15 100644 --- a/armsrc/iclass.h +++ b/armsrc/iclass.h @@ -17,7 +17,6 @@ void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string); void ReaderIClass(uint8_t arg0); -void ReaderIClass_Replay(uint8_t *rnr, uint8_t *mac); void iClass_WriteBlock(uint8_t *msg); void iClass_Dump(uint8_t *msg); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 28b710fe8..81bca140e 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -155,10 +155,11 @@ static int usage_hf_iclass_dump(void) { 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"); + 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:"); @@ -195,10 +196,11 @@ static int usage_hf_iclass_writeblock(void) { 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"); + 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")); @@ -213,10 +215,11 @@ static int usage_hf_iclass_readblock(void) { 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"); + 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")); @@ -280,18 +283,6 @@ static int usage_hf_iclass_reader(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_replay(void) { - PrintAndLogEx(NORMAL, "Replay a collected mac message\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass replay [h] [m ]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h Show this help"); - PrintAndLogEx(NORMAL, " r Reader nonce bytes to replay (8 hexsymbols)"); - PrintAndLogEx(NORMAL, " m Mac bytes to replay (8 hexsymbols)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass replay r 00000000 m 89cb984b")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_loclass(void) { PrintAndLogEx(NORMAL, "Execute the offline part of loclass attack"); PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of"); @@ -346,7 +337,6 @@ static int usage_hf_iclass_lookup(void) { return PM3_SUCCESS; } - static int cmp_uint32(const void *a, const void *b) { const iclass_prekey_t *x = (const iclass_prekey_t *)a; @@ -890,131 +880,6 @@ static int CmdHFiClassReader(const char *Cmd) { return read_iclass_csn(loop_read, true); } -static int CmdHFiClassReader_Replay(const char *Cmd) { - - struct { - uint8_t reader[4]; - uint8_t mac[4]; - } PACKED payload; - - - bool got_rnr, got_mac; - got_rnr = got_mac = false; - bool errors = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': { - return usage_hf_iclass_replay(); - } - case 'r': { - if (param_gethex(Cmd, cmdp + 1, payload.reader, 8)) { - PrintAndLogEx(FAILED, "Reader Nr must include 8 HEX symbols"); - errors = true; - } else { - got_rnr = true; - } - cmdp += 2; - break; - } - case 'm': { - if (param_gethex(Cmd, cmdp + 1, payload.mac, 8)) { - PrintAndLogEx(FAILED, "Reader MAC must include 8 HEX symbols"); - errors = true; - } else { - got_mac = true; - } - cmdp += 2; - break; - } - default: { - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - } - - //Validations - if (errors || cmdp == 0) { - return usage_hf_iclass_replay(); - } - - if (got_rnr == false || got_mac == false) { - PrintAndLogEx(FAILED, "Reader Nr and MAC is needed"); - return PM3_EINVARG; - } - - PacketResponseNG resp; - clearCommandBuffer(); - SendCommandNG(CMD_HF_ICLASS_REPLAY, (uint8_t *)&payload, sizeof(payload)); - - while (true) { - PrintAndLogEx(NORMAL, "." NOLF); - - if (kbd_enter_pressed()) { - PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); - DropField(); - return PM3_EOPABORTED; - } - - if (WaitForResponseTimeout(CMD_HF_ICLASS_REPLAY, &resp, 2000)) - break; - } - - PrintAndLogEx(NORMAL, ""); - if (resp.status != PM3_SUCCESS) { - PrintAndLogEx(ERR, "failed to communicate with card"); - return resp.status; - } - - struct p_resp { - bool isOK; - uint16_t block_cnt; - uint32_t bb_offset; - } PACKED; - struct p_resp *packet = (struct p_resp *)resp.data.asBytes; - - if (packet->isOK == false) { - PrintAndLogEx(WARNING, "replay reading blocks failed"); - return PM3_ESOFT; - } - - uint32_t startindex = packet->bb_offset; - uint32_t bytes_got = (packet->block_cnt * 8); - - uint8_t tag_data[0x100 * 8]; - memset(tag_data, 0xFF, sizeof(tag_data)); - - // response ok - now get bigbuf content of the dump - if (!GetFromDevice(BIG_BUF, tag_data, sizeof(tag_data), startindex, NULL, 0, NULL, 2500, false)) { - PrintAndLogEx(WARNING, "command execution time out"); - return PM3_ETIMEOUT; - } - - // print the dump - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "------+----+-------------------------+----------"); - PrintAndLogEx(INFO, " CSN |0x00| " _GREEN_("%s") "|", sprint_hex(tag_data, 8)); - printIclassDumpContents(tag_data, 1, (bytes_got / 8), bytes_got); - - // use CSN as filename - char filename[FILE_PATH_SIZE] = {0}; - strcat(filename, "hf-iclass-"); - FillFileNameByUID(filename, tag_data, "-dump", 8); - - // save the dump to .bin file - PrintAndLogEx(SUCCESS, "saving dump file - %u blocks read", bytes_got / 8); - saveFile(filename, ".bin", tag_data, bytes_got); - saveFileEML(filename, tag_data, bytes_got, 8); - saveFileJSON(filename, jsfIclass, tag_data, bytes_got, NULL); - - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass decrypt") "` to decrypt dump file"); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view") "` to view dump file"); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - static int CmdHFiClassELoad(const char *Cmd) { DumpFileType_t dftype = BIN; @@ -1271,7 +1136,6 @@ static int CmdHFiClassEView(const char *Cmd) { return PM3_SUCCESS; } - static int CmdHFiClassDecrypt(const char *Cmd) { bool errors = false; @@ -1665,6 +1529,7 @@ static int CmdHFiClassDump(const char *Cmd) { 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; @@ -1732,12 +1597,23 @@ static int CmdHFiClassDump(const char *Cmd) { 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) > 0) { + PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); + errors = true; + } + if (errors) return usage_hf_iclass_dump(); uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE); @@ -1808,6 +1684,7 @@ static int CmdHFiClassDump(const char *Cmd) { .req.use_raw = rawkey, .req.use_elite = elite, .req.use_credit_key = false, + .req.use_replay = use_replay, .req.send_reply = true, .req.do_auth = auth, .end_block = app_limit1, @@ -1974,7 +1851,7 @@ write_dump: return PM3_SUCCESS; } -static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) { +static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose) { /* uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -2017,6 +1894,7 @@ static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bo .req.use_raw = rawkey, .req.use_elite = elite, .req.use_credit_key = use_credit_key, + .req.use_replay = replay, .req.blockno = blockno, .req.send_reply = true, .req.do_auth = true, @@ -2052,6 +1930,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { bool use_credit_key = false; bool elite = false; bool rawkey = false; + bool use_replay = false; bool errors = false; bool verbose = false; uint8_t cmdp = 0; @@ -2105,6 +1984,13 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { rawkey = true; cmdp++; break; +/* + case 'n': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode")); + use_replay = true; + cmdp++; + break; +*/ case 'v': verbose = true; cmdp++; @@ -2118,9 +2004,14 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { if (got_blockno == false) errors = true; + if ((use_replay + rawkey + elite) > 0) { + PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); + errors = true; + } + if (errors || cmdp < 6) return usage_hf_iclass_writeblock(); - int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, verbose); + int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, use_replay, verbose); if (isok == PM3_SUCCESS) PrintAndLogEx(SUCCESS, "Wrote block %02X successful", blockno); else @@ -2337,12 +2228,13 @@ static int CmdHFiClassRestore(const char *Cmd) { return resp.status; } -static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth, uint8_t *out) { +static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool replay, bool verbose, bool auth, uint8_t *out) { iclass_auth_req_t payload = { .use_raw = rawkey, .use_elite = elite, .use_credit_key = (keyType == 0x18), + .use_replay = replay, .blockno = blockno, .send_reply = true, .do_auth = auth, @@ -2391,6 +2283,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { bool got_blockno = false; bool elite = false; bool rawkey = false; + bool use_replay = false; bool errors = false; bool auth = false; bool verbose = false; @@ -2439,6 +2332,11 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { rawkey = true; cmdp++; break; + case 'n': + PrintAndLogEx(SUCCESS, "Using " _YELLOW_("replay NR/MAC mode")); + use_replay = true; + cmdp++; + break; case 'v': verbose = true; cmdp++; @@ -2451,6 +2349,11 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { } if (got_blockno == false) errors = true; + + if ((use_replay + rawkey + elite) > 0) { + PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); + errors = true; + } if (errors) return usage_hf_iclass_readblock(); @@ -2467,7 +2370,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { } uint8_t data[8] = {0}; - int res = iclass_read_block(KEY, blockno, keyType, elite, rawkey, verbose, auth, data); + int res = iclass_read_block(KEY, blockno, keyType, elite, rawkey, use_replay, verbose, auth, data); if (res != PM3_SUCCESS) return res; @@ -3541,8 +3444,6 @@ static command_t CommandTable[] = { {"chk", CmdHFiClassCheckKeys, AlwaysAvailable, "[options..] Check keys"}, {"loclass", CmdHFiClass_loclass, AlwaysAvailable, "[options..] Use loclass to perform bruteforce reader attack"}, {"lookup", CmdHFiClassLookUp, AlwaysAvailable, "[options..] Uses authentication trace to check for key in dictionary file"}, - {"replay", CmdHFiClassReader_Replay, IfPm3Iclass, " Read Picopass / iCLASS tag via replay attack"}, - {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("simulation") " ---------------------"}, {"sim", CmdHFiClassSim, IfPm3Iclass, "[options..] Simulate iCLASS tag"}, {"eload", CmdHFiClassELoad, IfPm3Iclass, "[f ] Load Picopass / iCLASS dump file into emulator memory"}, diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 3bbedd9c7..141f51621 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -306,6 +306,7 @@ typedef struct { bool use_raw; bool use_elite; bool use_credit_key; + bool use_replay; bool send_reply; bool do_auth; uint8_t blockno; @@ -564,7 +565,6 @@ typedef struct { #define CMD_HF_ICLASS_SNIFF 0x0392 #define CMD_HF_ICLASS_SIMULATE 0x0393 #define CMD_HF_ICLASS_READER 0x0394 -#define CMD_HF_ICLASS_REPLAY 0x0395 #define CMD_HF_ICLASS_READBL 0x0396 #define CMD_HF_ICLASS_WRITEBL 0x0397 #define CMD_HF_ICLASS_EML_MEMSET 0x0398