mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 07:16:14 +08:00
added a new command "hf 15 wipe" which zeros out a card memory with writeblocks. Improved restore and wipe time. Also identified TI tags and their quirks. On device side when getting a error response from tag it doesnt care about eof package. So we send that one too. Which leads to a spurious package we ignore on client side.
This commit is contained in:
parent
52241eff9e
commit
02f5e729ca
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Added `hf 15 wipe` - fills card memory with zeros (@iceman1001)
|
||||
- Changed `hf xerox info` - now prints some part info (@iceman1001)
|
||||
- Added `hf xerox view` - view dump files of fuji/xerox tags (@iceman1001)
|
||||
- Changed `hf 15 findafi` - improved the params (@iceman1001)
|
||||
|
|
|
@ -1739,7 +1739,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
}
|
||||
|
||||
// no need to try decoding reader data if the tag is sending
|
||||
if (!tag_is_active) {
|
||||
if (tag_is_active == false) {
|
||||
|
||||
int extra_8s = 1;
|
||||
if (Handle15693SampleFromReader((sniffdata & 0x02) >> 1, &dreader) ||
|
||||
|
@ -1756,7 +1756,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
// sof/eof_times * 4 here to bring from ssp_clk freq to RF carrier freq
|
||||
LogTrace_ISO15693(dreader.output, dreader.byteCount, (sof_time * 4), (eof_time * 4), NULL, true);
|
||||
|
||||
if (!iclass) { // Those flags don't exist in iClass
|
||||
if (iclass == false) { // Those flags don't exist in iClass
|
||||
expect_fsk_answer = dreader.output[0] & ISO15_REQ_SUBCARRIER_TWO;
|
||||
expect_fast_answer = dreader.output[0] & ISO15_REQ_DATARATE_HIGH;
|
||||
}
|
||||
|
@ -1774,17 +1774,19 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
}
|
||||
|
||||
// no need to try decoding tag data if the reader is currently sending or no answer expected yet
|
||||
if (!reader_is_active && expect_tag_answer) {
|
||||
if ((reader_is_active == false) && expect_tag_answer) {
|
||||
|
||||
if (!expect_fsk_answer) {
|
||||
if (expect_fsk_answer == false) {
|
||||
// single subcarrier tag response
|
||||
if (Handle15693SamplesFromTag((sniffdata >> 4) << 2, &dtag, expect_fast_answer)) {
|
||||
|
||||
// sof/eof_times are in ssp_clk, which is 13.56MHz / 4
|
||||
uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
|
||||
|
||||
if (dtag.lastBit == SOF_PART2) {
|
||||
eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS)
|
||||
}
|
||||
|
||||
uint32_t sof_time = eof_time
|
||||
- dtag.len * 1024 // time for byte transfers (4096/fc / 4)
|
||||
- 512 // time for SOF transfer (2048/fc / 4)
|
||||
|
@ -1802,18 +1804,22 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string, bool icla
|
|||
} else {
|
||||
tag_is_active = (dtag.state >= STATE_TAG_RECEIVING_DATA);
|
||||
}
|
||||
|
||||
} else {
|
||||
// dual subcarrier tag response
|
||||
if (FREQ_IS_0((sniffdata >> 2) & 0x3)) // tolerate 1 00
|
||||
if (FREQ_IS_0((sniffdata >> 2) & 0x3)) { // tolerate 1 00
|
||||
sniffdata = sniffdata_prev;
|
||||
}
|
||||
|
||||
if (Handle15693FSKSamplesFromTag((sniffdata >> 2) & 0x3, &dtagfsk, expect_fast_answer)) {
|
||||
if (dtagfsk.len > 0) {
|
||||
// sof/eof_times are in ssp_clk, which is 13.56MHz / 4
|
||||
uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF
|
||||
|
||||
if (dtagfsk.lastBit == SOF) {
|
||||
eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS)
|
||||
}
|
||||
|
||||
uint32_t sof_time = eof_time
|
||||
- dtagfsk.len * 1016 // time for byte transfers (4064/fc / 4) - FSK is slightly different
|
||||
- 512 // time for SOF transfer (2048/fc / 4)
|
||||
|
@ -2490,6 +2496,12 @@ void SendRawCommand15693(iso15_raw_cmd_t *packet) {
|
|||
reply_ng(CMD_HF_ISO15693_COMMAND, res, NULL, 0);
|
||||
} else {
|
||||
|
||||
// if tag answers with an error code, it don't care about EOF packet
|
||||
if (recvlen) {
|
||||
recvlen = MIN(recvlen, ISO15693_MAX_RESPONSE_LENGTH);
|
||||
reply_ng(CMD_HF_ISO15693_COMMAND, res, buf, recvlen);
|
||||
}
|
||||
|
||||
// looking at the first byte of the RAW bytes to determine Subcarrier, datarate, request option
|
||||
bool fsk = ((packet->raw[0] & ISO15_REQ_SUBCARRIER_TWO) == ISO15_REQ_SUBCARRIER_TWO);
|
||||
bool recv_speed = ((packet->raw[0] & ISO15_REQ_DATARATE_HIGH) == ISO15_REQ_DATARATE_HIGH);
|
||||
|
|
|
@ -82,8 +82,13 @@
|
|||
#define ISO15_ERROR_HANDLING_CARD_RESPONSE(data, len) { \
|
||||
if ((check_crc(CRC_15693, (data), (len))) == false) { \
|
||||
PrintAndLogEx(FAILED, "crc ( " _RED_("fail") " )"); \
|
||||
return PM3_ESOFT; \
|
||||
return PM3_ECRC; \
|
||||
} \
|
||||
\
|
||||
if (data[1] == 0x0F || data[1] == 0x10) { \
|
||||
return PM3_EOUTOFBOUND; \
|
||||
} \
|
||||
\
|
||||
if ((d[0] & ISO15_RES_ERROR) == ISO15_RES_ERROR) { \
|
||||
PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", d[0], TagErrorStr(d[0])); \
|
||||
return PM3_EWRONGANSWER; \
|
||||
|
@ -2305,7 +2310,7 @@ static int CmdHF15Readblock(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int hf_15_write_blk(uint16_t flags, uint8_t *uid, bool fast, uint8_t blockno, uint8_t *data, uint8_t dlen) {
|
||||
static int hf_15_write_blk(uint8_t *pm3flags, uint16_t flags, uint8_t *uid, bool fast, uint8_t blockno, uint8_t *data, uint8_t dlen) {
|
||||
|
||||
// request to be sent to device/card
|
||||
// 2 + 8 + 1 + (4|8) + 2
|
||||
|
@ -2335,9 +2340,13 @@ static int hf_15_write_blk(uint16_t flags, uint8_t *uid, bool fast, uint8_t bloc
|
|||
packet->rawlen += 2;
|
||||
|
||||
// PM3 params
|
||||
packet->flags = (ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_LONG_WAIT);
|
||||
if (fast) {
|
||||
packet->flags |= ISO15_HIGH_SPEED;
|
||||
if (pm3flags ) {
|
||||
packet->flags = *pm3flags;
|
||||
} else {
|
||||
packet->flags = (ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_LONG_WAIT);
|
||||
if (fast) {
|
||||
packet->flags |= ISO15_HIGH_SPEED;
|
||||
}
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
|
@ -2407,16 +2416,6 @@ static int CmdHF15Write(const char *Cmd) {
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// enforcing add_option since we are writing.
|
||||
/*
|
||||
if (add_option == false) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Overriding OPTION param since we are writing (ENFORCE)");
|
||||
}
|
||||
add_option = true;
|
||||
}
|
||||
*/
|
||||
|
||||
// default fallback to scan for tag.
|
||||
// overriding unaddress parameter :)
|
||||
if (unaddressed == false) {
|
||||
|
@ -2434,7 +2433,6 @@ static int CmdHF15Write(const char *Cmd) {
|
|||
}
|
||||
|
||||
// TI needs OPTION
|
||||
PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), sprint_hex_inrow(uid, 8));
|
||||
if (uid[7] == 0xE0 && uid[6] == 0x07) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Overriding OPTION param, writing to TI tag");
|
||||
|
@ -2444,7 +2442,7 @@ static int CmdHF15Write(const char *Cmd) {
|
|||
|
||||
uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option);
|
||||
|
||||
int res = hf_15_write_blk(flags, ((unaddressed) ? NULL : uid), fast, (uint8_t)blockno, d, dlen);
|
||||
int res = hf_15_write_blk(NULL, flags, ((unaddressed) ? NULL : uid), fast, (uint8_t)blockno, d, dlen);
|
||||
|
||||
if (res == PM3_SUCCESS)
|
||||
PrintAndLogEx(SUCCESS, "Writing to page %02d (0x%02X) | %s ( " _GREEN_("ok") " )", blockno, blockno, sprint_hex(d, dlen));
|
||||
|
@ -2507,14 +2505,6 @@ static int CmdHF15Restore(const char *Cmd) {
|
|||
scan = true;
|
||||
}
|
||||
|
||||
// enforcing add_option since we are writing.
|
||||
if (add_option == false) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Overriding OPTION param since we are writing (ENFORCE)");
|
||||
}
|
||||
add_option = true;
|
||||
}
|
||||
|
||||
if (unaddressed == false) {
|
||||
if (scan) {
|
||||
if (getUID(verbose, false, uid) != PM3_SUCCESS) {
|
||||
|
@ -2531,6 +2521,14 @@ static int CmdHF15Restore(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "Using block size... " _YELLOW_("%d"), blocksize);
|
||||
|
||||
// TI needs OPTION
|
||||
if (uid[7] == 0xE0 && uid[6] == 0x07) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Overriding OPTION param, writing to TI tag");
|
||||
}
|
||||
add_option = true;
|
||||
}
|
||||
|
||||
// read dump file
|
||||
uint8_t *dump = NULL;
|
||||
size_t bytes_read = 0;
|
||||
|
@ -2547,11 +2545,14 @@ static int CmdHF15Restore(const char *Cmd) {
|
|||
}
|
||||
|
||||
PrintAndLogEx(INFO, "restoring data blocks");
|
||||
PrintAndLogEx(INFO, "." NOLF);
|
||||
fflush(stdout);
|
||||
|
||||
uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option);
|
||||
|
||||
uint8_t pm3flags = (ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_LONG_WAIT | ISO15_NO_DISCONNECT);
|
||||
if (fast) {
|
||||
pm3flags |= ISO15_HIGH_SPEED;
|
||||
}
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
size_t bytes = 0;
|
||||
uint16_t i = 0;
|
||||
|
@ -2565,10 +2566,21 @@ static int CmdHF15Restore(const char *Cmd) {
|
|||
uint32_t tried = 0;
|
||||
for (tried = 0; tried < retries; tried++) {
|
||||
|
||||
retval = hf_15_write_blk(flags, uid, fast, i, data, blocksize);
|
||||
retval = hf_15_write_blk(&pm3flags, flags, uid, fast, i, data, blocksize);
|
||||
if (retval == PM3_SUCCESS) {
|
||||
PrintAndLogEx(NORMAL, "." NOLF);
|
||||
fflush(stdout);
|
||||
|
||||
PrintAndLogEx(INPLACE, "blk %3d", i);
|
||||
|
||||
if (i == 0) {
|
||||
pm3flags = (ISO15_READ_RESPONSE | ISO15_LONG_WAIT | ISO15_NO_DISCONNECT);
|
||||
if (fast) {
|
||||
pm3flags |= ISO15_HIGH_SPEED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (retval == PM3_EOUTOFBOUND) {
|
||||
// we only get this when we reached end of tag memory
|
||||
// break out of retry loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2577,12 +2589,22 @@ static int CmdHF15Restore(const char *Cmd) {
|
|||
free(dump);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(FAILED, "restore failed. Too many retries.");
|
||||
DropField();
|
||||
return retval;
|
||||
}
|
||||
|
||||
bytes += blocksize;
|
||||
i++;
|
||||
|
||||
if (retval == PM3_EOUTOFBOUND) {
|
||||
// we only get this when we reached end of tag memory
|
||||
// break out of while loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(dump);
|
||||
DropField();
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "done");
|
||||
|
@ -3166,6 +3188,100 @@ static int CmdHF15View(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF15Wipe(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf 15 wipe",
|
||||
"Wipe a ISO-15693 tag by filled memory with zeros",
|
||||
"hf 15 wipe\n"
|
||||
);
|
||||
void *argtable[6 + 3] = {0};
|
||||
uint8_t arglen = arg_add_default(argtable);
|
||||
argtable[arglen++] = arg_int0(NULL, "bs", "<dec>", "block size (def 4)"),
|
||||
argtable[arglen++] = arg_lit0("v", "verbose", "verbose output");
|
||||
argtable[arglen++] = arg_param_end;
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
uint8_t uid[HF15_UID_LENGTH];
|
||||
int uidlen = 0;
|
||||
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||
bool uid_set = (uidlen == HF15_UID_LENGTH) ? true : false;
|
||||
|
||||
bool unaddressed = arg_get_lit(ctx, 2);
|
||||
bool scan = (arg_get_lit(ctx, 3) || (!uid_set && !unaddressed)) ? true : false; // Default fallback to scan for tag. Overriding unaddressed parameter.
|
||||
bool fast = (arg_get_lit(ctx, 4) == false);
|
||||
bool add_option = arg_get_lit(ctx, 5);
|
||||
|
||||
int blocksize = arg_get_int_def(ctx, 6, 4);
|
||||
bool verbose = arg_get_lit(ctx, 7);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// sanity checks
|
||||
if ((scan + unaddressed + uid_set) > 1) {
|
||||
PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (blocksize < 4) {
|
||||
PrintAndLogEx(WARNING, "Blocksize too small, using default 4 bytes");
|
||||
blocksize = 4;
|
||||
}
|
||||
|
||||
// default fallback to scan for tag.
|
||||
// overriding unaddress parameter :)
|
||||
if (unaddressed == false) {
|
||||
if (scan) {
|
||||
if (getUID(verbose, false, uid) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "no tag found");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
} else {
|
||||
reverse_array(uid, HF15_UID_LENGTH);
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "Using unaddressed mode");
|
||||
}
|
||||
|
||||
// TI needs OPTION
|
||||
if (uid[7] == 0xE0 && uid[6] == 0x07) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Overriding OPTION param, writing to TI tag");
|
||||
}
|
||||
add_option = true;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Wiping tag...");
|
||||
|
||||
uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option);
|
||||
uint8_t empty[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t pm3flags = (ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_LONG_WAIT | ISO15_NO_DISCONNECT);
|
||||
if (fast) {
|
||||
pm3flags |= ISO15_HIGH_SPEED;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < 0x100; i++) {
|
||||
|
||||
PrintAndLogEx(INPLACE, "blk %3d", i);
|
||||
|
||||
int res = hf_15_write_blk(&pm3flags, flags, ((unaddressed) ? NULL : uid), fast, i, empty, blocksize);
|
||||
if (res == PM3_SUCCESS) {
|
||||
if (i == 0) {
|
||||
pm3flags = (ISO15_READ_RESPONSE | ISO15_LONG_WAIT | ISO15_NO_DISCONNECT);
|
||||
if (fast) {
|
||||
pm3flags |= ISO15_HIGH_SPEED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DropField();
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "done");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHF15Help, AlwaysAvailable, "This help"},
|
||||
{"list", CmdHF15List, AlwaysAvailable, "List ISO-15693 history"},
|
||||
|
@ -3181,6 +3297,7 @@ static command_t CommandTable[] = {
|
|||
{"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO-15693 tag"},
|
||||
{"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire samples as reader (enables carrier, sends inquiry)"},
|
||||
{"view", CmdHF15View, AlwaysAvailable, "Display content from tag dump file"},
|
||||
{"wipe", CmdHF15Wipe, IfPm3Iso15693, "Wipe card to zeros"},
|
||||
{"wrbl", CmdHF15Write, IfPm3Iso15693, "Write a block"},
|
||||
{"-----------", CmdHF15Help, IfPm3Iso15693, "--------------------- " _CYAN_("simulation") " ----------------------"},
|
||||
{"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO-15693 tag"},
|
||||
|
|
Loading…
Reference in a new issue