diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 708a92190..44ffa5d15 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -34,6 +34,7 @@ #include "aidsearch.h" #include "fileutils.h" // saveFile #include "iclass_cmd.h" // picopass defines +#include "cmdhf.h" // handle HF plot #define MAX_14B_TIMEOUT_MS (4949U) @@ -1575,7 +1576,7 @@ static int CmdHF14BSriWrbl(const char *Cmd) { arg_int0("b", "block", "", "block number"), arg_str1("d", "data", "", "4 hex bytes"), arg_lit0(NULL, "512", "target SRI 512 tag"), - arg_lit0(NULL, "4k", "target SRIX 4k tag"), + arg_lit0(NULL, "4k", "target SRIX 4k tag (def)"), arg_lit0(NULL, "sb", "special block write at end of memory (0xFF)"), arg_lit0(NULL, "force", "overrides block range checks"), arg_param_end @@ -1606,6 +1607,11 @@ static int CmdHF14BSriWrbl(const char *Cmd) { return PM3_EINVARG; } + // Set default + if (use_sri512 == false) { + use_srix4k = true; + } + if (use_srix4k && blockno > 0x7F) { PrintAndLogEx(FAILED, "block number out of range, max 127 (0x7F), got " _RED_("%u"), blockno); if (override) { @@ -1846,6 +1852,120 @@ static int CmdHF14BDump(const char *Cmd) { return PM3_ESOFT; } + +static int CmdHF14BRestore(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14b restore", + "Restore data from (bin/eml/json) dump file to tag\n" + "If the dump file includes the special block at the end it will be ignored\n", + "hf 14b restore --4k -f myfilename\n" + "hf 14b restore --512 -f myfilename\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "(optional) filename, if no UID will be used as filename"), + arg_lit0(NULL, "512", "target SRI 512 tag"), + arg_lit0(NULL, "4k", "target SRIX 4k tag (def)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + bool use_sri512 = arg_get_lit(ctx, 2); + bool use_srix4k = arg_get_lit(ctx, 3); + CLIParserFree(ctx); + + if (use_sri512 + use_srix4k > 1) { + PrintAndLogEx(FAILED, "Select only one card type"); + return PM3_EINVARG; + } + + // Set default + if (use_sri512 == false) { + use_srix4k = true; + } + + char s[7]; + memset(s, 0, sizeof(s)); + uint16_t block_cnt = 0; + if (use_sri512) { + block_cnt = 16; + memcpy(s, "SRI512", 7); + } else if (use_srix4k) { + block_cnt = 128; + memcpy(s, "SRIX4K", 7); + } + + // reserve memory + uint8_t *data = NULL; + size_t bytes_read = 0; + int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (4 * block_cnt)); + if (res != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "Failed to load file"); + return res; + } + + // Ignore remaining 4 bytes if the file is 4 bytes larger than the expected size + // (because hf 14b dump also saves the special block at the end of the memory, it will be ignored by the restore command) + if (bytes_read != (block_cnt * 4) && bytes_read != (block_cnt * 4 + 4)) { + PrintAndLogEx(ERR, "File content error. Read %zu", bytes_read); + free(data); + return PM3_EFILE; + } + PrintAndLogEx(INFO, "Copying to %s", s); + + int blockno = 0; + while (bytes_read) { + + int status = write_sr_block(blockno, 4, data+blockno*4); + if (status != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "Write failed shutting down"); + return status; + } + + // verify + uint8_t out[4] = {0}; + status = read_sr_block(blockno, out); + if (status == PM3_SUCCESS) { + if (memcmp(data+blockno*ST25TB_SR_BLOCK_SIZE, out, 4) == 0) { + printf("\33[2K\r"); + PrintAndLogEx(INFO, "SRx write block %d/%d ( " _GREEN_("ok") " )" NOLF, blockno, block_cnt-1); + }else { + printf("\n"); + PrintAndLogEx(INFO, "SRx write block %d/%d ( " _RED_("different") " )",blockno, block_cnt-1); + } + }else{ + printf("\n"); + PrintAndLogEx(INFO, "Verifying block %d/%d ( " _RED_("failed") " )",blockno, block_cnt-1); + } + + fflush(stdout); + + bytes_read -= ST25TB_SR_BLOCK_SIZE; + blockno++; + if (blockno >= block_cnt) break; + } + + PrintAndLogEx(NORMAL, "\n"); + free(data); + + // confirm number written blocks. + if (blockno != block_cnt) { + PrintAndLogEx(ERR, "File content error. There must be %d blocks", block_cnt); + return PM3_EFILE; + } + + PrintAndLogEx(SUCCESS, "Card loaded " _YELLOW_("%d") " blocks from file", block_cnt); + PrintAndLogEx(INFO, "Done!"); + + + return PM3_SUCCESS; +} + /* static uint32_t srix4kEncode(uint32_t value) { @@ -2533,7 +2653,7 @@ static command_t CommandTable[] = { {"raw", CmdHF14BRaw, IfPm3Iso14443b, "Send raw hex data to tag"}, {"rdbl", CmdHF14BSriRdBl, IfPm3Iso14443b, "Read SRI512/SRIX4 block"}, {"reader", CmdHF14BReader, IfPm3Iso14443b, "Act as a ISO-14443-B reader to identify a tag"}, -// {"restore", CmdHF14BRestore, IfPm3Iso14443b, "Restore from file to all memory pages of an ISO-14443-B tag"}, + {"restore", CmdHF14BRestore, IfPm3Iso14443b, "Restore from file to all memory pages of an ISO-14443-B tag"}, {"sim", CmdHF14BSim, IfPm3Iso14443b, "Fake ISO ISO-14443-B tag"}, {"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO-14443-B"}, {"wrbl", CmdHF14BSriWrbl, IfPm3Iso14443b, "Write data to a SRI512/SRIX4 tag"}, @@ -2573,44 +2693,39 @@ int infoHF14B(bool verbose, bool do_aid_search) { // get and print general info about all known 14b chips int readHF14B(bool loop, bool verbose) { bool found = false; + int res = PM3_SUCCESS; do { found = false; // try std 14b (atqb) found |= HF14B_std_reader(verbose); - if (found && loop) - continue; - else if (found) - return PM3_SUCCESS; + if (found) + goto plot; // try ST Microelectronics 14b found |= HF14B_st_reader(verbose); - if (found && loop) - continue; - else if (found) - return PM3_SUCCESS; + if (found) + goto plot; // Picopass - found |= HF14B_picopass_reader(verbose) ; - if (found && loop) - continue; - else if (found) - return PM3_SUCCESS; + found |= HF14B_picopass_reader(verbose); + if (found) + goto plot; // try ASK CT 14b found |= HF14B_ask_ct_reader(verbose); - if (found && loop) - continue; - else if (found) - return PM3_SUCCESS; + if (found) + goto plot; // try unknown 14b read commands (to be identified later) // could be read of calypso, CEPAS, moneo, or pico pass. found |= HF14B_other_reader(verbose); - if (found && loop) - continue; - else if (found) - return PM3_SUCCESS; + if (found) + goto plot; +plot: + res = handle_hf_plot(); + if (res != PM3_SUCCESS) + break; } while (loop && kbd_enter_pressed() == false); diff --git a/client/src/pm3line_vocabulary.h b/client/src/pm3line_vocabulary.h index 63bd38af7..3719c4e52 100644 --- a/client/src/pm3line_vocabulary.h +++ b/client/src/pm3line_vocabulary.h @@ -166,6 +166,7 @@ const static vocabulary_t vocabulary[] = { { 0, "hf 14b raw" }, { 0, "hf 14b rdbl" }, { 0, "hf 14b reader" }, + { 0, "hf 14b restore" }, { 0, "hf 14b sim" }, { 0, "hf 14b sniff" }, { 0, "hf 14b wrbl" },