diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 326d77298..c4dcb10b8 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1846,6 +1846,10 @@ void iClass_WriteBlock(uint8_t *msg) { AddCrc(write + 1, 9); write_len -= 2; } else { + + if (payload->req.use_replay) { + memcpy(write + 10, payload->mac, sizeof(payload->mac)); + } else { // Secure tags uses MAC uint8_t wb[9]; wb[0] = payload->req.blockno; @@ -1857,6 +1861,7 @@ void iClass_WriteBlock(uint8_t *msg) { doMAC_N(wb, sizeof(wb), hdr.key_d, mac); memcpy(write + 10, mac, sizeof(mac)); + } } start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index cc53ff77e..495e30ef4 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1909,7 +1909,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 replay, bool verbose, bool use_secure_pagemode) { +static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *macdata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose, bool use_secure_pagemode) { iclass_writeblock_req_t payload = { .req.use_raw = rawkey, @@ -1923,6 +1923,10 @@ static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bo memcpy(payload.req.key, KEY, 8); memcpy(payload.data, bldata, sizeof(payload.data)); + if (replay) { + memcpy(payload.mac, macdata, sizeof(payload.mac)); + } + clearCommandBuffer(); SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; @@ -1953,6 +1957,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), arg_int1("b", "block", "", "The block number to read"), arg_str1("d", "data", "", "data to write as 8 hex bytes"), + arg_str0("m", "mac", "", "replay mac data (4 hex bytes)"), 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"), @@ -2008,11 +2013,24 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { return PM3_EINVARG; } - 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 mac_len = 0; + uint8_t mac[4] = {0}; + CLIGetHexWithReturn(ctx, 5, mac, &mac_len); + + if (mac_len) { + if (mac_len != 4) { + PrintAndLogEx(ERR, "MAC must be 4 hex bytes (8 hex symbols)"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + + + bool use_credit_key = arg_get_lit(ctx, 6); + bool elite = arg_get_lit(ctx, 7); + bool rawkey = arg_get_lit(ctx, 8); + bool use_replay = arg_get_lit(ctx, 9); + bool verbose = arg_get_lit(ctx, 10); CLIParserFree(ctx); @@ -2021,7 +2039,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { return PM3_EINVARG; } - int isok = iclass_write_block(blockno, data, key, use_credit_key, elite, rawkey, use_replay, verbose, auth); + int isok = iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, verbose, auth); switch (isok) { case PM3_SUCCESS: PrintAndLogEx(SUCCESS, "Wrote block %3d/0x%02X successful", blockno, blockno); @@ -3891,7 +3909,7 @@ static int CmdHFiClassEncode(const char *Cmd) { int isok = PM3_SUCCESS; // write for (uint8_t i = 0; i < 4; i++) { - isok = iclass_write_block(6 + i, credential + (i * 8), key, use_credit_key, elite, rawkey, false, false, auth); + isok = iclass_write_block(6 + i, credential + (i * 8), NULL, key, use_credit_key, elite, rawkey, false, false, auth); switch (isok) { case PM3_SUCCESS: PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _GREEN_("ok") " ) --> " _YELLOW_("%s"), 6 + i, 6 + i, sprint_hex_inrow(credential + (i * 8), 8)); diff --git a/include/iclass_cmd.h b/include/iclass_cmd.h index e78531868..5a2f90226 100644 --- a/include/iclass_cmd.h +++ b/include/iclass_cmd.h @@ -82,6 +82,7 @@ typedef struct { typedef struct { iclass_auth_req_t req; uint8_t data[8]; + uint8_t mac[4]; } PACKED iclass_writeblock_req_t; // iCLASS dump data structure