From c937e3b760e09beb193c871e80376f5dee30d62c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 24 Jun 2023 00:02:50 +0200 Subject: [PATCH] fix tear off to work with topaz wrbl. fix topas wrbl to handle LOCK/OTP block 13,14, which needs write_nonerase command, fixed output for rdbl --- armsrc/iso14443a.c | 34 ++++++++-- client/src/cmdhftopaz.c | 138 +++++++++++++++++++++++++++++++++------- 2 files changed, 143 insertions(+), 29 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 01eed12c1..42b42c180 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1291,7 +1291,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, tag_r { .response = rPPS, .response_n = sizeof(rPPS) }, // PPS response { .response = rPACK, .response_n = sizeof(rPACK) } // PACK response }; - + // "precompile" responses. There are 12 predefined responses with a total of 84 bytes data to transmit. // Coded responses need one byte per bit to transfer (data, parity, start, stop, correction) @@ -3094,13 +3094,33 @@ void ReaderIso14443a(PacketCommandNG *c) { } } - if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred - FpgaDisableTracing(); - reply_mix(CMD_ACK, 0, 0, 0, NULL, 0); + if ((param & ISO14A_TOPAZMODE)) { + + if (cmd[0] == TOPAZ_WRITE_E8 || cmd[0] == TOPAZ_WRITE_NE8) { + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred + FpgaDisableTracing(); + reply_mix(CMD_ACK, 0, 0, 0, NULL, 0); + } else { + arg0 = ReaderReceive(buf, par); + FpgaDisableTracing(); + reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); + } + } else { + arg0 = ReaderReceive(buf, par); + FpgaDisableTracing(); + reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); + } + } else { - arg0 = ReaderReceive(buf, par); - FpgaDisableTracing(); - reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); + + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred + FpgaDisableTracing(); + reply_mix(CMD_ACK, 0, 0, 0, NULL, 0); + } else { + arg0 = ReaderReceive(buf, par); + FpgaDisableTracing(); + reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); + } } } diff --git a/client/src/cmdhftopaz.c b/client/src/cmdhftopaz.c index 6311b50ed..766889438 100644 --- a/client/src/cmdhftopaz.c +++ b/client/src/cmdhftopaz.c @@ -224,6 +224,8 @@ static int topaz_write_erase8_block(uint8_t blockno, uint8_t *block_data) { uint16_t resp_len = 11; uint8_t response[11] = {0}; + // + if (topaz_send_cmd(wr8_cmd, sizeof(wr8_cmd), response, &resp_len, true) == PM3_ETIMEOUT) { topaz_switch_off_field(); return PM3_ESOFT; // WriteErase 8bytes failed @@ -243,6 +245,61 @@ static int topaz_write_erase8_block(uint8_t blockno, uint8_t *block_data) { return PM3_ESOFT; } +// write a block (8 Bytes) of a selected Topaz tag. +static int topaz_write_nonerase8_block(uint8_t blockno, uint8_t *block_data) { + + uint8_t atqa[2] = {0}; + uint8_t rid_response[8] = {0}; + int res = topaz_select(atqa, sizeof(atqa), rid_response, sizeof(rid_response), true); + if (res != PM3_SUCCESS) { + return res; + } + + if (atqa[1] != 0x0c && atqa[0] != 0x00) { + return res; + } + + uint8_t *uid_echo = &rid_response[2]; + uint8_t rall_response[124] = {0}; + + res = topaz_rall(uid_echo, rall_response); + if (res == PM3_ESOFT) { + return res; + } + + // ADD + // 7 6 5 4 3 2 1 0 + // b b b --- Byte 0 - 7 + // B B B B --------- BLOCK + // r ----------------- 0 + // + + uint8_t wr8_cmd[] = {TOPAZ_WRITE_NE8, blockno, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + memcpy(wr8_cmd + 10, uid_echo, 4); + memcpy(wr8_cmd + 2, block_data, 8); + + uint16_t resp_len = 11; + uint8_t response[11] = {0}; + + // + if (topaz_send_cmd(wr8_cmd, sizeof(wr8_cmd), response, &resp_len, true) == PM3_ETIMEOUT) { + topaz_switch_off_field(); + return PM3_ESOFT; + } + + if (resp_len != 11) { + return PM3_EFAILED; + } + + if (blockno != response[0]) { + return PM3_EFAILED; + } + + if (memcmp(block_data, response + 1, 8) == 0) { + return PM3_SUCCESS; + } + return PM3_ESOFT; +} // search for the lock area descriptor for the lockable area including byteno static dynamic_lock_area_t *get_dynamic_lock_area(uint16_t byteno) { @@ -402,6 +459,12 @@ static int topaz_print_CC(uint8_t *data) { return PM3_SUCCESS; } +static void topaz_print_hdr(uint8_t blockno) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | block " _GREEN_("0x%02X") " | ascii", blockno); + PrintAndLogEx(INFO, "----+-------------------------+---------"); +} + // return type, length and value of a TLV, starting at memory position *TLV_ptr static void get_TLV(uint8_t **TLV_ptr, uint8_t *TLV_type, uint16_t *TLV_length, uint8_t **TLV_value) { *TLV_length = 0; @@ -782,6 +845,7 @@ static int CmdHFTopazDump(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "filename of dump"), + arg_lit0(NULL, "ns", "no save to file"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -789,6 +853,8 @@ static int CmdHFTopazDump(const char *Cmd) { int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + bool nosave = arg_get_lit(ctx, 2); + CLIParserFree(ctx); int status = readTopazUid(false, false); @@ -811,9 +877,18 @@ static int CmdHFTopazDump(const char *Cmd) { ); } - PrintAndLogEx(INFO, "-------------------------------------------------------------"); topaz_switch_off_field(); + // Skip saving card data to file + if (nosave) { + PrintAndLogEx(INFO, "Called with no save option"); + if (set_dynamic) { + free(topaz_tag.dynamic_memory); + } + return PM3_SUCCESS; + } + + // user supplied filename? if (fnlen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); @@ -888,13 +963,13 @@ static int CmdHFTopazRdBl(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf topaz rdbl", - "Read a block", - "hf topaz rdbl -b 7\n" + "Read Topaz block", + "hf topaz rdbl --blk 7\n" ); void *argtable[] = { arg_param_begin, - arg_int1("b", "block", "", "Block number to write"), + arg_int1(NULL, "blk", "", "Block number"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -910,7 +985,11 @@ static int CmdHFTopazRdBl(const char *Cmd) { uint8_t data[8] = {0}; int res = topaz_read_block(blockno, data); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, sizeof(data))); + + topaz_print_hdr(blockno); + + PrintAndLogEx(INFO, " %2d | %s", blockno, sprint_hex_ascii(data, sizeof(data))); + PrintAndLogEx(NORMAL, ""); } topaz_switch_off_field(); @@ -922,13 +1001,13 @@ static int CmdHFTopazWrBl(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf topaz wrbl", - "Write a block", - "hf topaz wrbl -b 7 -d 1122334455667788\n" + "Write Topaz block with 8 hex bytes of data", + "hf topaz wrbl --blk 7 -d 1122334455667788\n" ); void *argtable[] = { arg_param_begin, - arg_int1("b", "block", "", "Block number to write"), + arg_int1(NULL, "blk", "", "Block number"), arg_str1("d", "data", "", "Block data (8 hex bytes)"), arg_param_end }; @@ -954,14 +1033,23 @@ static int CmdHFTopazWrBl(const char *Cmd) { PrintAndLogEx(INFO, "Block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, dlen)); - // send write Block - int res = topaz_write_erase8_block(blockno, data); + int res; + if (blockno != 13 && blockno != 14) { + // send write/erase block + res = topaz_write_erase8_block(blockno, data); + } else { + // send write/non erase block + res = topaz_write_nonerase8_block(blockno, data); + } if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )"); + PrintAndLogEx(HINT, "try `" _YELLOW_("hf topaz rdbl --blk %u") "` to verify", blockno); + } else { PrintAndLogEx(WARNING, "Write ( " _RED_("fail") " )"); } + PrintAndLogEx(NORMAL, ""); topaz_switch_off_field(); return res; @@ -970,18 +1058,24 @@ static int CmdHFTopazWrBl(const char *Cmd) { static int CmdHelp(const char *Cmd); static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"dump", CmdHFTopazDump, IfPm3Iso14443a, "Dump TOPAZ family tag to file"}, - {"list", CmdHFTopazList, AlwaysAvailable, "List Topaz history"}, - {"info", CmdHFTopazInfo, IfPm3Iso14443a, "Tag information"}, - {"reader", CmdHFTopazReader, IfPm3Iso14443a, "Act like a Topaz reader"}, - {"sim", CmdHFTopazSim, IfPm3Iso14443a, "Simulate Topaz tag"}, - {"sniff", CmdHFTopazSniff, IfPm3Iso14443a, "Sniff Topaz reader-tag communication"}, - {"raw", CmdHFTopazRaw, IfPm3Iso14443a, "Send raw hex data to tag"}, - {"rdbl", CmdHFTopazRdBl, IfPm3Iso14443a, "Read block"}, - {"view", CmdHFTopazView, AlwaysAvailable, "Display content from tag dump file"}, - {"wrbl", CmdHFTopazWrBl, IfPm3Iso14443a, "Write block"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"list", CmdHFTopazList, AlwaysAvailable, "List Topaz history"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "------------------- " _CYAN_("operations") " ---------------------"}, + {"dump", CmdHFTopazDump, IfPm3Iso14443a, "Dump TOPAZ family tag to file"}, + {"info", CmdHFTopazInfo, IfPm3Iso14443a, "Tag information"}, + {"raw", CmdHFTopazRaw, IfPm3Iso14443a, "Send raw hex data to tag"}, + {"rdbl", CmdHFTopazRdBl, IfPm3Iso14443a, "Read block"}, + {"reader", CmdHFTopazReader, IfPm3Iso14443a, "Act like a Topaz reader"}, + {"sim", CmdHFTopazSim, IfPm3Iso14443a, "Simulate Topaz tag"}, + {"sniff", CmdHFTopazSniff, IfPm3Iso14443a, "Sniff Topaz reader-tag communication"}, + {"view", CmdHFTopazView, AlwaysAvailable, "Display content from tag dump file"}, + {"wrbl", CmdHFTopazWrBl, IfPm3Iso14443a, "Write block"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("ndef") " -----------------------"}, +// {"ndefformat", CmdHFTopazNDEFFormat, IfPm3Iso14443a, "Format Topaz Tag as NFC Tag"}, +// {"ndefread", CmdHFTopazNDEFRead, IfPm3Iso14443a, "Read and print NDEF records from card"}, +// {"ndefwrite", CmdHFTopazNDEFWrite, IfPm3Iso14443a, "Write NDEF records to card"}, + + {NULL, NULL, 0, NULL} }; static int CmdHelp(const char *Cmd) {