From 3868b0b4e69fdd316d3f0664edb1f367c263d1d7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Oct 2020 22:43:28 +0200 Subject: [PATCH] hf iclass write, hf 15 raw, write, etc supports tear off trigger --- armsrc/iclass.c | 30 +++++++- armsrc/iso15693.c | 148 ++++++++++++++++++++------------------- client/src/cmdhf15.c | 44 ++++++++++-- client/src/cmdhficlass.c | 19 +++-- 4 files changed, 156 insertions(+), 85 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index baaff65c5..00e88f405 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1864,8 +1864,34 @@ void iClass_WriteBlock(uint8_t *msg) { start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; uint8_t resp[10] = {0}; - res = iclass_send_cmd_with_retries(write, sizeof(write), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time); - if (res == false) { + + uint8_t tries = 3; + while (tries-- > 0) { + + iclass_send_as_reader(write, sizeof(write), &start_time, &eof_time); + + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured + res = false; + switch_off(); + if (payload->req.send_reply) + reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t)); + return; + } else { + + if (resp == NULL) { + res = true; + break; + } + + if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time) == 10) { + res = true; + break; + } + } + } + + if (tries == 0) { + res = false; goto out; } diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index e84edd8a0..00af14c4f 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -290,6 +290,7 @@ void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) { LED_B_OFF(); *start_time = *start_time + DELAY_ARM_TO_TAG; + FpgaDisableTracing(); } //----------------------------------------------------------------------------- @@ -732,6 +733,7 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo } FpgaDisableSscDma(); + FpgaDisableTracing(); uint32_t sof_time = *eof_time - (dt->len * 8 * 8 * 16) // time for byte transfers @@ -1469,17 +1471,22 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t // low speed (1 out of 256) CodeIso15693AsReader256(send, sendlen); } - + int res = 0; tosend_t *ts = get_tosend(); TransmitTo15693Tag(ts->buf, ts->max, &start_time); - *eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF - LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true); + + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured - int res = 0; - if (recv != NULL) { - res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time); + res = PM3_ETEAROFF; + + } else { + + *eof_time = start_time + 32 * ((8 * ts->max) - 4); // substract the 4 padding bits after EOF + LogTrace_ISO15693(send, sendlen, (start_time * 4), (*eof_time * 4), NULL, true); + if (recv != NULL) { + res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time); + } } - FpgaDisableTracing(); return res; } @@ -1495,7 +1502,6 @@ int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, ui if (recv != NULL) { res = GetIso15693AnswerFromTag(recv, max_recv_len, timeout, eof_time); } - FpgaDisableTracing(); return res; } @@ -1588,41 +1594,49 @@ void ReaderIso15693(uint32_t parameter) { BuildIdentifyRequest(cmd); uint32_t start_time = 0; uint32_t eof_time; - int answerLen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time); - start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + int recvlen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time); + + if (recvlen == PM3_ETEAROFF) { // tearoff occured + reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0); + } else { + + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; - // we should do a better check than this - if (answerLen >= 12) { - uint8_t uid[8]; - uid[0] = answer[9]; // always E0 - uid[1] = answer[8]; // IC Manufacturer code - uid[2] = answer[7]; - uid[3] = answer[6]; - uid[4] = answer[5]; - uid[5] = answer[4]; - uid[6] = answer[3]; - uid[7] = answer[2]; + // we should do a better check than this + if (recvlen >= 12) { + uint8_t uid[8]; + uid[0] = answer[9]; // always E0 + uid[1] = answer[8]; // IC Manufacturer code + uid[2] = answer[7]; + uid[3] = answer[6]; + uid[4] = answer[5]; + uid[5] = answer[4]; + uid[6] = answer[3]; + uid[7] = answer[2]; - if (DBGLEVEL >= DBG_EXTENDED) { - Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X", - uid[0], uid[1], uid[2], uid[3], - uid[4], uid[5], uid[5], uid[6] - ); + if (DBGLEVEL >= DBG_EXTENDED) { + Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X", + uid[0], uid[1], uid[2], uid[3], + uid[4], uid[5], uid[5], uid[6] + ); + } + // send UID back to client. + // arg0 = 1 = OK + // arg1 = len of response (12 bytes) + // arg2 = rtf + // asbytes = uid. + reply_mix(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid)); + + if (DBGLEVEL >= DBG_EXTENDED) { + Dbprintf("[+] %d octets read from IDENTIFY request:", recvlen); + DbdecodeIso15693Answer(recvlen, answer); + Dbhexdump(recvlen, answer, true); + } + } else { + DbpString("Failed to select card"); + reply_mix(CMD_ACK, 0, 0, 0, NULL, 0); } - // send UID back to client. - // arg0 = 1 = OK - // arg1 = len of response (12 bytes) - // arg2 = rtf - // asbytes = uid. - reply_mix(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid)); } - - if (DBGLEVEL >= DBG_EXTENDED) { - Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen); - DbdecodeIso15693Answer(answerLen, answer); - Dbhexdump(answerLen, answer, true); - } - switch_off(); BigBuf_free(); } @@ -1767,6 +1781,11 @@ void BruteforceIso15693Afi(uint32_t speed) { if (recvlen >= 12) { Dbprintf("NoAFI UID = %s", iso15693_sprintUID(NULL, recv + 2)); + } else { + DbpString("Failed to select card"); + reply_ng(CMD_ACK, PM3_ESOFT, NULL, 0); + switch_off(); + return; } // now with AFI @@ -1816,10 +1835,9 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint LED_A_ON(); - int recvlen = 0; uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; - uint32_t eof_time = 0; uint16_t timeout; + uint32_t eof_time = 0; bool request_answer = false; switch (data[1]) { @@ -1837,43 +1855,29 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint timeout = ISO15693_READER_TIMEOUT; } - if (DBGLEVEL >= DBG_EXTENDED) { - Dbprintf("SEND:"); - Dbhexdump(datalen, data, false); - } - uint32_t start_time = 0; - recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time); + int recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time); - // send a single EOF to get the tag response - if (request_answer) { - start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; - recvlen = SendDataTagEOF((recv ? recvbuf : NULL), sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT, &eof_time); + if (recvlen == PM3_ETEAROFF) { // tearoff occured + reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0); + } else { + + // send a single EOF to get the tag response + if (request_answer) { + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + recvlen = SendDataTagEOF((recv ? recvbuf : NULL), sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT, &eof_time); + } + + if (recv) { + recvlen = MIN(recvlen,ISO15693_MAX_RESPONSE_LENGTH); + reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen); + } else { + reply_mix(CMD_ACK, 1, 0, 0, NULL, 0); + } } - - // for the time being, switch field off to protect rdv4.0 // note: this prevents using hf 15 cmd with s option - which isn't implemented yet anyway FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); - - if (recv) { - - if (recvlen > ISO15693_MAX_RESPONSE_LENGTH) { - recvlen = ISO15693_MAX_RESPONSE_LENGTH; - } - reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen); - - if (DBGLEVEL >= DBG_EXTENDED) { - - Dbprintf("RECV:"); - if (recvlen > 0) { - Dbhexdump(recvlen, recvbuf, false); - DbdecodeIso15693Answer(recvlen, recvbuf); - } - } - } else { - reply_mix(CMD_ACK, 1, 0, 0, 0, 0); - } } /* diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 238aad435..407815a93 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -323,7 +323,7 @@ static int usage_15_raw(void) { return PM3_SUCCESS; } static int usage_15_read(void) { - PrintAndLogEx(NORMAL, "Usage: hf 15 read [options] \n" + PrintAndLogEx(NORMAL, "Usage: hf 15 rdbl [options] \n" "Options:\n" "\t-2 use slower '1 out of 256' mode\n" "\tuid (either): \n" @@ -334,7 +334,7 @@ static int usage_15_read(void) { return PM3_SUCCESS; } static int usage_15_write(void) { - PrintAndLogEx(NORMAL, "Usage: hf 15 write [options] \n" + PrintAndLogEx(NORMAL, "Usage: hf 15 wrbl [options] \n" "Options:\n" "\t-2 use slower '1 out of 256' mode\n" "\t-o set OPTION Flag (needed for TI)\n" @@ -816,6 +816,10 @@ static int NxpSysInfo(uint8_t *uid) { DropField(); int status = resp.oldarg[0]; + if (status == PM3_ETEAROFF) { + return status; + } + if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command"); return PM3_EWRONGANSWER; @@ -975,6 +979,9 @@ static int CmdHF15Info(const char *Cmd) { DropField(); int status = resp.oldarg[0]; + if (status == PM3_ETEAROFF) { + return status; + } if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command (%d)", status); return PM3_EWRONGANSWER; @@ -1153,9 +1160,13 @@ static int CmdHF15WriteAfi(const char *Cmd) { DropField(); return PM3_ETIMEOUT; } - DropField(); + int status = resp.oldarg[0]; + if (status == PM3_ETEAROFF) { + return status; + } + uint8_t *data = resp.data.asBytes; if ((data[0] & ISO15_RES_ERROR) == ISO15_RES_ERROR) { @@ -1212,6 +1223,10 @@ static int CmdHF15WriteDsfid(const char *Cmd) { } DropField(); + int status = resp.oldarg[0]; + if (status == PM3_ETEAROFF) { + return status; + } uint8_t *data = resp.data.asBytes; @@ -1296,6 +1311,9 @@ static int CmdHF15Dump(const char *Cmd) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { int len = resp.oldarg[0]; + if (len == PM3_ETEAROFF) { + continue; + } if (len < 2) { PrintAndLogEx(FAILED, "iso15693 command failed"); continue; @@ -1321,6 +1339,7 @@ static int CmdHF15Dump(const char *Cmd) { blocknum++; PrintAndLogEx(NORMAL, "." NOLF); + fflush(stdout); } } @@ -1419,6 +1438,10 @@ static int CmdHF15Raw(const char *Cmd) { if (reply) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { int len = resp.oldarg[0]; + if (len == PM3_ETEAROFF) { + DropField(); + return len; + } if (len < 2) { PrintAndLogEx(WARNING, "command failed"); } else { @@ -1491,6 +1514,10 @@ static int CmdHF15Readmulti(const char *Cmd) { DropField(); int status = resp.oldarg[0]; + if (status == PM3_ETEAROFF) { + return status; + } + if (status < 2) { PrintAndLogEx(FAILED, "iso15693 card readmulti failed"); return PM3_EWRONGANSWER; @@ -1574,6 +1601,9 @@ static int CmdHF15Read(const char *Cmd) { DropField(); int status = resp.oldarg[0]; + if (status == PM3_ETEAROFF) { + return status; + } if (status < 2) { PrintAndLogEx(ERR, "iso15693 command failed"); return PM3_EWRONGANSWER; @@ -1661,6 +1691,10 @@ static int CmdHF15Write(const char *Cmd) { DropField(); int status = resp.oldarg[0]; + if (status == PM3_ETEAROFF) { + return status; + } + if (status < 2) { PrintAndLogEx(FAILED, "iso15693 command failed"); return PM3_EWRONGANSWER; @@ -1876,13 +1910,13 @@ static command_t CommandTable[] = { {"info", CmdHF15Info, IfPm3Iso15693, "Tag information"}, {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"}, {"raw", CmdHF15Raw, IfPm3Iso15693, "Send raw hex data to tag"}, - {"read", CmdHF15Read, IfPm3Iso15693, "Read a block"}, + {"rdbl", CmdHF15Read, IfPm3Iso15693, "Read a block"}, {"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO15693 reader"}, {"readmulti", CmdHF15Readmulti, IfPm3Iso15693, "Reads multiple Blocks"}, {"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO15693 tag"}, {"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire Samples as Reader (enables carrier, sends inquiry)"}, {"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO15693 tag"}, - {"write", CmdHF15Write, IfPm3Iso15693, "Write a block"}, + {"wrbl", CmdHF15Write, IfPm3Iso15693, "Write a block"}, {"-----------", CmdHF15Help, IfPm3Iso15693, "----------------------- " _CYAN_("afi") " -----------------------"}, {"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"}, {"writeafi", CmdHF15WriteAfi, IfPm3Iso15693, "Writes the AFI on an ISO15693 tag"}, diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 81bca140e..bf40e2d1e 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1913,9 +1913,8 @@ static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bo if (resp.status != PM3_SUCCESS) { if (verbose) PrintAndLogEx(ERR, "failed to communicate with card"); - return PM3_EWRONGANSWER; + return resp.status; } - return (resp.data.asBytes[0] == 1) ? PM3_SUCCESS : PM3_ESOFT; } @@ -2012,10 +2011,18 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { if (errors || cmdp < 6) return usage_hf_iclass_writeblock(); 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 - PrintAndLogEx(FAILED, "Writing failed"); + switch(isok) { + case PM3_SUCCESS: + PrintAndLogEx(SUCCESS, "Wrote block %02X successful", blockno); + break; + case PM3_ETEAROFF: + if (verbose) + PrintAndLogEx(INFO, "Writing tear off triggered"); + break; + default: + PrintAndLogEx(FAILED, "Writing failed"); + break; + } return isok; }