diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 7c483f2e1..b778fa785 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1032,7 +1032,13 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_MIFARE_READER: { - ReaderMifare(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]); + struct p { + uint8_t first_run; + uint8_t blockno; + uint8_t key_type; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + ReaderMifare(payload->first_run, payload->blockno, payload->key_type); break; } case CMD_HF_MIFARE_READBL: { diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 348317a8a..81bada416 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2791,6 +2791,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { static uint8_t par_low = 0; static uint8_t mf_nr_ar3 = 0; + int return_status = PM3_SUCCESS; + AddCrc14A(mf_auth, 2); if (first_try) { @@ -2807,6 +2809,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { } LED_C_ON(); + uint16_t checkbtn_cnt = 0; uint16_t i; for (i = 0; true; ++i) { @@ -2815,10 +2818,15 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { WDT_HIT(); // Test if the action was cancelled - if (BUTTON_PRESS()) { - isOK = -1; - break; + if (checkbtn_cnt == 2000) { + if (BUTTON_PRESS() || data_available()) { + isOK = -1; + return_status = PM3_EOPABORTED; + break; + } + checkbtn_cnt = 0; } + ++checkbtn_cnt; // this part is from Piwi's faster nonce collecting part in Hardnested. if (!have_uid) { // need a full select cycle to get the uid first @@ -2876,8 +2884,16 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding - if (ReaderReceive(receivedAnswer, receivedAnswerPar)) + int resp_res = ReaderReceive(receivedAnswer, receivedAnswerPar); + if (resp_res == 1) received_nack = true; + else if (resp_res == 4) { + // did we get lucky and got our dummykey to be valid? + // however we dont feed key w uid it the prng.. + isOK = -6; + break; + } + // we didn't calibrate our clock yet, // iceman: has to be calibrated every time. @@ -3000,26 +3016,36 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Number of sent auth requests: %u", i); - uint8_t buf[32] = {0x00}; - memset(buf, 0x00, sizeof(buf)); - num_to_bytes(cuid, 4, buf); - num_to_bytes(nt, 4, buf + 4); - memcpy(buf + 8, par_list, 8); - memcpy(buf + 16, ks_list, 8); - memcpy(buf + 24, mf_nr_ar, 8); + struct { + int32_t isOK; + uint8_t cuid[4]; + uint8_t nt[4]; + uint8_t par_list[8]; + uint8_t ks_list[8]; + uint8_t nr[4]; + uint8_t ar[4]; + } PACKED payload; - reply_mix(CMD_ACK, isOK, 0, 0, buf, sizeof(buf)); + payload.isOK = isOK; + num_to_bytes(cuid, 4, payload.cuid); + num_to_bytes(nt, 4, payload.nt); + memcpy(payload.par_list, par_list, sizeof(payload.par_list)); + memcpy(payload.ks_list, ks_list, sizeof(payload.ks_list)); + memcpy(payload.nr, mf_nr_ar, sizeof(payload.nr)); + memcpy(payload.ar, mf_nr_ar + 4, sizeof(payload.ar)); + + reply_ng(CMD_HF_MIFARE_READER, return_status, (uint8_t*)&payload, sizeof(payload)); hf_field_off(); set_tracing(false); } /* -* Mifare Classic NACK-bug detection -* Thanks to @doegox for the feedback and new approaches. + * Mifare Classic NACK-bug detection + * Thanks to @doegox for the feedback and new approaches. */ void DetectNACKbug(void) { - uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B}; + uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B}; uint8_t mf_nr_ar[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; @@ -3050,6 +3076,8 @@ void DetectNACKbug(void) { sync_time = GetCountSspClk() & 0xfffffff8; LED_C_ON(); + uint16_t checkbtn_cnt = 0; + uint16_t i; for (i = 1; true; ++i) { @@ -3064,10 +3092,14 @@ void DetectNACKbug(void) { WDT_HIT(); // Test if the action was cancelled - if (BUTTON_PRESS() || data_available()) { - status = PM3_EOPABORTED; - break; + if (checkbtn_cnt == 2000) { + if (BUTTON_PRESS() || data_available()) { + status = PM3_EOPABORTED; + break; + } + checkbtn_cnt = 0; } + ++checkbtn_cnt; // this part is from Piwi's faster nonce collecting part in Hardnested. if (!have_uid) { // need a full select cycle to get the uid first @@ -3127,10 +3159,11 @@ void DetectNACKbug(void) { // Transmit reader nonce with fake par ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); + // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding if (ReaderReceive(receivedAnswer, receivedAnswerPar)) { received_nack = true; num_nacks++; - // ALWAYS leak Detection. + // ALWAYS leak Detection. Well, we could be lucky and get a response nack on first try. if (i == num_nacks) { continue; } @@ -3247,7 +3280,6 @@ void DetectNACKbug(void) { num_to_bytes(i, 2, data + 2); reply_ng(CMD_HF_MIFARE_NACK_DETECT, status, data, 4); - //reply_mix(CMD_ACK, isOK, num_nacks, i, 0, 0); BigBuf_free(); hf_field_off(); set_tracing(false); diff --git a/client/cmddata.c b/client/cmddata.c index 2e28eeb03..e55b34909 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -532,7 +532,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, invert = 1; clk = 0; } - uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); + uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); if (bits == NULL) { return PM3_EMALLOC; } @@ -1119,13 +1119,13 @@ int FSKrawDemod(const char *Cmd, bool verbose) { if (bits == NULL) { return PM3_EMALLOC; } - + size_t BitLen = getFromGraphBuf(bits); if (BitLen == 0) { free(bits); return PM3_ESOFT; } - + //get field clock lengths if (!fchigh || !fclow) { uint16_t fcs = countFC(bits, BitLen, true); @@ -2243,7 +2243,7 @@ static command_t CommandTable[] = { {"tune", CmdTuneSamples, IfPm3Present, "Get hw tune samples for graph window"}, {"undec", CmdUndec, AlwaysAvailable, "Un-decimate samples by 2"}, {"zerocrossings", CmdZerocrossings, AlwaysAvailable, "Count time between zero-crossings"}, - {"iir", CmdDataIIR, IfPm3Present, "apply IIR buttersworth filter on plotdata"}, + {"iir", CmdDataIIR, AlwaysAvailable, "apply IIR buttersworth filter on plotdata"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/cmdhw.c b/client/cmdhw.c index c363fdc25..a6f242b8f 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -467,10 +467,14 @@ static int CmdSetMux(const char *Cmd) { str_lower((char *)Cmd); uint8_t arg = 0; - if (strcmp(Cmd, "lopkd") == 0) arg = 0; - else if (strcmp(Cmd, "loraw") == 0) arg = 1; - else if (strcmp(Cmd, "hipkd") == 0) arg = 2; - else if (strcmp(Cmd, "hiraw") == 0) arg = 3; + if (strcmp(Cmd, "lopkd") == 0) + arg = 0; + else if (strcmp(Cmd, "loraw") == 0) + arg = 1; + else if (strcmp(Cmd, "hipkd") == 0) + arg = 2; + else if (strcmp(Cmd, "hiraw") == 0) + arg = 3; else { usage_hw_setmux(); return PM3_EINVARG; @@ -570,8 +574,6 @@ static int CmdConnect(const char *Cmd) { memcpy(port, conn.serial_port_name, sizeof(port)); } - printf("Port:: %s Baud:: %u\n", port, baudrate); - if (session.pm3_present) { CloseProxmark(); } @@ -582,14 +584,15 @@ static int CmdConnect(const char *Cmd) { if (session.pm3_present && (TestProxmark() != PM3_SUCCESS)) { PrintAndLogEx(ERR, _RED_("ERROR:") "cannot communicate with the Proxmark3\n"); CloseProxmark(); + return PM3_ENOTTY; } return PM3_SUCCESS; } static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"dbg", CmdDbg, IfPm3Present, "Set Proxmark3 debug level"}, {"connect", CmdConnect, AlwaysAvailable, "connect Proxmark3 to serial port"}, + {"dbg", CmdDbg, IfPm3Present, "Set Proxmark3 debug level"}, {"detectreader", CmdDetectReader, IfPm3Present, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, {"fpgaoff", CmdFPGAOff, IfPm3Present, "Set FPGA off"}, {"lcd", CmdLCD, IfPm3Lcd, "<HEX command> <count> -- Send command/data to LCD"}, @@ -690,14 +693,22 @@ void pm3_version(bool verbose, bool oneliner) { PrintAndLogEx(NORMAL, "\n [ CLIENT ]"); PrintAndLogEx(NORMAL, " client: RRG/Iceman"); // TODO version info? PrintAndLogEx(NORMAL, " compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH); - PrintAndLogEx(NORMAL, "\n [ PROXMARK RDV4 ]"); - PrintAndLogEx(NORMAL, " external flash: %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent")); - PrintAndLogEx(NORMAL, " smartcard reader: %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent")); - PrintAndLogEx(NORMAL, "\n [ PROXMARK RDV4 Extras ]"); - PrintAndLogEx(NORMAL, " FPC USART for BT add-on support: %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent")); - if (IfPm3FpcUsartDevFromUsb()) - PrintAndLogEx(NORMAL, " FPC USART for developer support: %s", _GREEN_("present")); +//#if PLATFORM == PM3RDV4 + if ( IfPm3Flash() == false && IfPm3Smartcard() == false && IfPm3FpcUsartHost() == false) { + PrintAndLogEx(NORMAL, "\n [ PROXMARK3 ]"); + } else { + PrintAndLogEx(NORMAL, "\n [ PROXMARK3 RDV4 ]"); + PrintAndLogEx(NORMAL, " external flash: %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent")); + PrintAndLogEx(NORMAL, " smartcard reader: %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent")); + PrintAndLogEx(NORMAL, "\n [ PROXMARK3 RDV4 Extras ]"); + PrintAndLogEx(NORMAL, " FPC USART for BT add-on support: %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent")); + + if (IfPm3FpcUsartDevFromUsb()) { + PrintAndLogEx(NORMAL, " FPC USART for developer support: %s", _GREEN_("present")); + } + } +//#endif PrintAndLogEx(NORMAL, ""); diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 85529609d..992eabdd8 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -264,12 +264,7 @@ static int CmdFdxRead(const char *Cmd) { static int CmdFdxClone(const char *Cmd) { uint32_t countryid = 0; - uint64_t animalid = 0; - uint32_t blocks[5] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0, 0}; - uint8_t bits[128]; - uint8_t *bs = bits; - memset(bs, 0, sizeof(bits)); - + uint64_t animalid = 0; char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_fdx_clone(); @@ -278,63 +273,32 @@ static int CmdFdxClone(const char *Cmd) { verify_values(countryid, animalid); - // getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits) - if (getFDXBits(animalid, countryid, 1, 0, 0, bs) != PM3_SUCCESS) { + uint8_t *bits = calloc(128, sizeof(uint8_t)); + + if (getFDXBits(animalid, countryid, 1, 0, 0, bits) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Error with tag bitstream generation."); + free(bits); return PM3_ESOFT; } + uint32_t blocks[5] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0, 0}; + //Q5 if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q') blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT; // convert from bit stream to block data - blocks[1] = bytebits_to_byte(bs, 32); - blocks[2] = bytebits_to_byte(bs + 32, 32); - blocks[3] = bytebits_to_byte(bs + 64, 32); - blocks[4] = bytebits_to_byte(bs + 96, 32); + blocks[1] = bytebits_to_byte(bits, 32); + blocks[2] = bytebits_to_byte(bits + 32, 32); + blocks[3] = bytebits_to_byte(bits + 64, 32); + blocks[4] = bytebits_to_byte(bits + 96, 32); + free(bits); + PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid); - print_blocks(blocks, 5); + print_blocks(blocks, ARRAYLEN(blocks)); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (int i = 4; i >= 0; --i) { - if (i == 0) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdFdxSim(const char *Cmd) { diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index fe00d1187..366fe77e3 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -14,6 +14,7 @@ #include <stdlib.h> #include <ctype.h> +#include "commonutil.h" // ARRAYLEN #include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" @@ -156,20 +157,20 @@ static int CmdGuardClone(const char *Cmd) { if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_guard_clone(); uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0, fmtlen = 0; - uint8_t bs[96]; - memset(bs, 0x00, sizeof(bs)); - - //GuardProxII - compat mode, ASK/Biphase, data rate 64, 3 data blocks - uint32_t blocks[4] = {T55x7_MODULATION_BIPHASE | T55x7_BITRATE_RF_64 | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0}; if (sscanf(Cmd, "%u %u %u", &fmtlen, &fc, &cn) != 3) return usage_lf_guard_clone(); - + fmtlen &= 0x7f; facilitycode = (fc & 0x000000FF); cardnumber = (cn & 0x0000FFFF); + //GuardProxII - compat mode, ASK/Biphase, data rate 64, 3 data blocks + uint32_t blocks[4] = {T55x7_MODULATION_BIPHASE | T55x7_BITRATE_RF_64 | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0}; + uint8_t *bs = calloc(96, sizeof(uint8_t)); + if (getGuardBits(fmtlen, facilitycode, cardnumber, bs) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Error with tag bitstream generation."); + free(bs); return PM3_ESOFT; } @@ -181,47 +182,12 @@ static int CmdGuardClone(const char *Cmd) { blocks[2] = bytebits_to_byte(bs + 32, 32); blocks[3] = bytebits_to_byte(bs + 64, 32); + free(bs); + PrintAndLogEx(INFO, "Preparing to clone Guardall to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); - print_blocks(blocks, 4); + print_blocks(blocks, ARRAYLEN(blocks)); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < 4; i++) { - if (i == 3) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdGuardSim(const char *Cmd) { diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h index 2b61861ff..5ae2d7753 100644 --- a/client/cmdlfhid.h +++ b/client/cmdlfhid.h @@ -16,6 +16,5 @@ int CmdLFHID(const char *Cmd); int demodHID(void); -//void calc26(uint16_t fc, uint32_t cardno, uint8_t *out); -void calcWiegand(uint8_t fmtlen, uint16_t fc, uint64_t cardno, uint8_t *bits, uint8_t oem); + #endif diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 673ed1438..eae80564d 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -505,43 +505,7 @@ static int CmdIndalaClone(const char *Cmd) { print_blocks(blocks, max); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < max; i++) { - if (i == max - 1) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, max); } static command_t CommandTable[] = { diff --git a/client/cmdlfio.c b/client/cmdlfio.c index e17ae82d1..74a9ef92d 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -16,6 +16,7 @@ #include <ctype.h> +#include "commonutil.h" //ARRAYLEN #include "cmdparser.h" // command_t #include "comms.h" #include "graph.h" @@ -272,45 +273,9 @@ static int CmdIOProxClone(const char *Cmd) { blocks[2] = bytebits_to_byte(bits + 32, 32); PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn); - print_blocks(blocks, 3); + print_blocks(blocks, ARRAYLEN(blocks)); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < 3; i++) { - if (i == 2) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static command_t CommandTable[] = { diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c index 13a1d6e1f..d2a0d9967 100644 --- a/client/cmdlfjablotron.c +++ b/client/cmdlfjablotron.c @@ -18,7 +18,7 @@ #include "cmdparser.h" // command_t #include "comms.h" -#include "commonutil.h" +#include "commonutil.h" // ARRAYLEN #include "ui.h" #include "cmddata.h" #include "cmdlf.h" @@ -169,46 +169,9 @@ static int CmdJablotronClone(const char *Cmd) { blocks[2] = bytebits_to_byte(bits + 32, 32); PrintAndLogEx(INFO, "Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode); - print_blocks(blocks, 3); + print_blocks(blocks, ARRAYLEN(blocks)); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < 3; i++) { - if (i == 2) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdJablotronSim(const char *Cmd) { diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 49d3c2a33..e36388041 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -15,6 +15,7 @@ #include <ctype.h> #include <stdlib.h> +#include "commonutil.h" // ARRAYLEN #include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" @@ -155,49 +156,12 @@ static int CmdKeriClone(const char *Cmd) { uint64_t data = ((uint64_t)internalid << 3) + 7; PrintAndLogEx(INFO, "Preparing to clone KERI to T55x7 with Internal Id: %" PRIx64, internalid); - // blocks[1] = data >> 32; blocks[2] = data & 0xFFFFFFFF; - print_blocks(blocks, 3); - uint8_t res = 0; - PacketResponseNG resp; + print_blocks(blocks, ARRAYLEN(blocks)); - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < 3; i++) { - if (i == 2) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdKeriSim(const char *Cmd) { diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index b186a1354..cab5e55c6 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -9,6 +9,19 @@ #include "cmdlfnedap.h" +#include <string.h> + +#include <ctype.h> +#include <stdlib.h> +#include "cmdparser.h" // command_t +#include "comms.h" +#include "crc16.h" +#include "cmdlft55xx.h" // verifywrite +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" + #define FIXED_71 0x71 #define FIXED_40 0x40 #define UNKNOWN_A 0x00 @@ -431,7 +444,7 @@ int CmdLFNedapClone(const char *Cmd) { return PM3_ESOFT; } - CmdPrintDemodBuff("x"); + //CmdPrintDemodBuff("x"); // What we had before in commented code: //NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks @@ -455,47 +468,14 @@ int CmdLFNedapClone(const char *Cmd) { PrintAndLogEx(SUCCESS, "Preparing to clone NEDAP to T55x7"); print_blocks(blocks, max); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < max; i++) { - if (i == max - 1) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - else { - PrintAndLogEx(NORMAL, ""); + int res = clone_t55xx_tag(blocks, max); + if (res == PM3_SUCCESS) { PrintAndLogEx(INFO, "The block 0 was changed (eXtended) which can be hard to detect."); PrintAndLogEx(INFO, " Configure it manually " _YELLOW_("`lf t55xx config b 64 d BI i 1 o 32`")); + } else { + PrintAndLogEx(NORMAL, ""); } - return PM3_SUCCESS; + return res; } static int CmdLFNedapSim(const char *Cmd) { diff --git a/client/cmdlfnedap.h b/client/cmdlfnedap.h index 74fdd30fb..fda0e130e 100644 --- a/client/cmdlfnedap.h +++ b/client/cmdlfnedap.h @@ -11,19 +11,6 @@ #include "common.h" -#include <string.h> - -#include <ctype.h> -#include <stdlib.h> -#include "cmdparser.h" // command_t -#include "comms.h" -#include "crc16.h" -#include "cmdlft55xx.h" // verifywrite -#include "ui.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "lfdemod.h" - int CmdLFNedap(const char *Cmd); int demodNedap(void); diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 5a5e127b1..d4069547b 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -9,16 +9,33 @@ //----------------------------------------------------------------------------- #include "cmdlfnexwatch.h" +#include <ctype.h> // tolower +#include "commonutil.h" // ARRAYLEN #include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" #include "cmddata.h" // preamblesearch #include "cmdlf.h" #include "lfdemod.h" +#include "protocols.h" // t55xx defines +#include "cmdlft55xx.h" // clone.. static int CmdHelp(const char *Cmd); +static int usage_lf_nexwatch_clone(void) { + PrintAndLogEx(NORMAL, "clone a Nexwatch tag to a T55x7 tag."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf nexwatch clone [h] [b <raw hex>]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf nexwatch clone b 5600000000213C9F8F150C0000000000"); + return PM3_SUCCESS; +} + static int CmdNexWatchDemod(const char *Cmd) { (void)Cmd; // Cmd is not used so far @@ -37,7 +54,7 @@ static int CmdNexWatchDemod(const char *Cmd) { // else if (idx == -3) // PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch problem during PSK demod"); else if (idx == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch preamble not found"); + PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch preamble not found"); // else if (idx == -5) // PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch size not correct: %d", size); else @@ -47,7 +64,7 @@ static int CmdNexWatchDemod(const char *Cmd) { } setDemodBuff(DemodBuffer, size, idx + 4); - setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 4)*g_DemodClock)); + setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 4) * g_DemodClock)); // idx = 8 + 32; // 8 = preamble, 32 = reserved bits (always 0) @@ -82,10 +99,47 @@ static int CmdNexWatchRead(const char *Cmd) { } static int CmdNexWatchClone(const char *Cmd) { + + // 56000000 00213C9F 8F150C00 00000000 + uint32_t blocks[5]; + bool errors = false; + uint8_t cmdp = 0; + int datalen = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_nexwatch_clone(); + case 'b': { + // skip first block, 4*4 = 16 bytes left + uint8_t rawhex[16] = {0}; + int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen); + if ( res != 0 ) + errors = true; + + for(uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(rawhex + ( (i - 1) * 4 ), sizeof(uint32_t)); + } + cmdp += 2; + break; + } + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + if (errors || cmdp == 0) return usage_lf_nexwatch_clone(); + + //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks + blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT; + + PrintAndLogEx(INFO, "Preparing to clone NexWatch to T55x7 with raw hex"); + print_blocks(blocks, ARRAYLEN(blocks)); + + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); - // should be able to clone the raw hex. - PrintAndLogEx(INFO, " To be implemented, feel free to contribute!"); - return PM3_SUCCESS; } static int CmdNexWatchSim(const char *Cmd) { diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index fe469720b..9cec6767e 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -9,6 +9,20 @@ //----------------------------------------------------------------------------- #include "cmdlfnoralsy.h" +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "commonutil.h" // ARRAYLEN +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest +#include "cmdlft55xx.h" // verifywrite + static int CmdHelp(const char *Cmd); static int usage_lf_noralsy_clone(void) { @@ -128,8 +142,7 @@ static int CmdNoralsyClone(const char *Cmd) { uint16_t year = 0; uint32_t id = 0; uint32_t blocks[4] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | T55x7_ST_TERMINATOR | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0}; - uint8_t bits[96]; - memset(bits, 0, sizeof(bits)); + uint8_t *bits = calloc(96, sizeof(uint8_t)); char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_noralsy_clone(); @@ -146,52 +159,16 @@ static int CmdNoralsyClone(const char *Cmd) { return PM3_ESOFT; } - // blocks[1] = bytebits_to_byte(bits, 32); blocks[2] = bytebits_to_byte(bits + 32, 32); blocks[3] = bytebits_to_byte(bits + 64, 32); + free(bits); + PrintAndLogEx(INFO, "Preparing to clone Noralsy to T55x7 with CardId: %u", id); - print_blocks(blocks, 4); + print_blocks(blocks, ARRAYLEN(blocks)); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < 4; i++) { - if (i == 3) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; -} + return clone_t55xx_tag(blocks, ARRAYLEN(blocks));} static int CmdNoralsySim(const char *Cmd) { diff --git a/client/cmdlfnoralsy.h b/client/cmdlfnoralsy.h index 56ae31372..f76accab7 100644 --- a/client/cmdlfnoralsy.h +++ b/client/cmdlfnoralsy.h @@ -11,19 +11,6 @@ #include "common.h" -#include <string.h> -#include <stdlib.h> -#include <ctype.h> - -#include "cmdparser.h" // command_t -#include "comms.h" -#include "ui.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest -#include "cmdlft55xx.h" // verifywrite - int CmdLFNoralsy(const char *Cmd); int demodNoralsy(void); diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 175d56ad4..1977224e5 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -9,8 +9,34 @@ //----------------------------------------------------------------------------- #include "cmdlfpac.h" +#include <ctype.h> //tolower + +#include "commonutil.h" // ARRAYLEN +#include "common.h" +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" // preamble test +#include "protocols.h" // t55xx defines +#include "cmdlft55xx.h" // clone.. + static int CmdHelp(const char *Cmd); +static int usage_lf_pac_clone(void) { + PrintAndLogEx(NORMAL, "clone a Stanley/PAC tag to a T55x7 tag."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf pac clone [h] [b <raw hex>]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf pac clone b FF2049906D8511C593155B56D5B2649F "); + return PM3_SUCCESS; +} + //see NRZDemod for what args are accepted static int CmdPacDemod(const char *Cmd) { @@ -46,8 +72,8 @@ static int CmdPacDemod(const char *Cmd) { // 11111111001000000 10 01001100 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 10001100 10 100000001 // unknown checksum 9 bits at the end - PrintAndLogEx(NORMAL, "PAC/Stanley Tag Found -- Raw: %08X%08X%08X%08X", raw1, raw2, raw3, raw4); - PrintAndLogEx(NORMAL, "\nHow the Raw ID is translated by the reader is unknown"); + PrintAndLogEx(SUCCESS, "PAC/Stanley Tag Found -- Raw: %08X%08X%08X%08X", raw1, raw2, raw3, raw4); + PrintAndLogEx(INFO, "How the Raw ID is translated by the reader is unknown. Share your trace file on forum"); return PM3_SUCCESS; } @@ -57,9 +83,45 @@ static int CmdPacRead(const char *Cmd) { } static int CmdPacClone(const char *Cmd) { - // possible to raw hex and clone - PrintAndLogEx(INFO, " To be implemented, feel free to contribute!"); - return PM3_SUCCESS; + + uint32_t blocks[5]; + bool errors = false; + uint8_t cmdp = 0; + int datalen = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_pac_clone(); + case 'b': { + // skip first block, 4*4 = 16 bytes left + uint8_t rawhex[16] = {0}; + int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen); + if ( res != 0 ) + errors = true; + + for(uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(rawhex + ( (i - 1) * 4 ), sizeof(uint32_t)); + } + cmdp += 2; + break; + } + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + if (errors || cmdp == 0) return usage_lf_pac_clone(); + + //Pac - compat mode, NRZ, data rate 40, 3 data blocks + blocks[0] = T55x7_MODULATION_DIRECT | T55x7_BITRATE_RF_40 | 4 << T55x7_MAXBLOCK_SHIFT; + + PrintAndLogEx(INFO, "Preparing to clone Securakey to T55x7 with raw hex"); + print_blocks(blocks, ARRAYLEN(blocks)); + + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdPacSim(const char *Cmd) { diff --git a/client/cmdlfpac.h b/client/cmdlfpac.h index edb05b7a5..3c9c4fbda 100644 --- a/client/cmdlfpac.h +++ b/client/cmdlfpac.h @@ -10,12 +10,6 @@ #define CMDLFPAC_H__ #include "common.h" -#include "cmdparser.h" // command_t -#include "comms.h" -#include "ui.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "lfdemod.h" // preamble test int CmdLFPac(const char *Cmd); diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index 440f47ced..b3307b8a8 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -14,6 +14,7 @@ #include <stdlib.h> #include <ctype.h> +#include "commonutil.h" // ARRAYLEN #include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" @@ -21,7 +22,24 @@ #include "cmddata.h" #include "cmdlf.h" #include "lfdemod.h" +#include "protocols.h" // t55xx defines +#include "cmdlft55xx.h" // clone.. + static int CmdHelp(const char *Cmd); + +static int usage_lf_paradox_clone(void) { + PrintAndLogEx(NORMAL, "clone a Paradox tag to a T55x7 tag."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf paradox clone [h] [b <raw hex>]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf paradox clone 0f55555695596a6a9999a59a"); + return PM3_SUCCESS; +} + /* static int usage_lf_paradox_sim(void) { PrintAndLogEx(NORMAL, "Enables simulation of Paradox card with specified card number."); @@ -113,8 +131,45 @@ static int CmdParadoxRead(const char *Cmd) { } static int CmdParadoxClone(const char *Cmd) { - PrintAndLogEx(INFO, " To be implemented, feel free to contribute!"); - return PM3_SUCCESS; + + uint32_t blocks[4]; + bool errors = false; + uint8_t cmdp = 0; + int datalen = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_paradox_clone(); + case 'b': { + // skip first block, 3*4 =12 bytes left + uint8_t rawhex[12] = {0}; + int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen); + if ( res != 0 ) + errors = true; + + for(uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(rawhex + ( (i - 1) * 4 ), sizeof(uint32_t)); + } + cmdp += 2; + break; + } + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + if (errors || cmdp == 0) return usage_lf_paradox_clone(); + + //Securakey - compat mode, ASK/Man, data rate 40, 3 data blocks + blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 3 << T55x7_MAXBLOCK_SHIFT; + + PrintAndLogEx(INFO, "Preparing to clone Paradox to T55x7 with raw hex"); + print_blocks(blocks, ARRAYLEN(blocks)); + + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdParadoxSim(const char *Cmd) { diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index f563e2ef8..cfe56ad5e 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -9,6 +9,21 @@ #include "cmdlfpresco.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#include "commonutil.h" // ARRAYLEN +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest +#include "cmdlft55xx.h" // verifywrite + static int CmdHelp(const char *Cmd); static int usage_lf_presco_clone(void) { @@ -119,46 +134,9 @@ static int CmdPrescoClone(const char *Cmd) { blocks[4] = fullcode; PrintAndLogEx(INFO, "Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode); - print_blocks(blocks, 5); + print_blocks(blocks, ARRAYLEN(blocks)); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < 5; i++) { - if (i == 4) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } // takes base 12 ID converts to hex diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h index 8f7c7eb31..098a98342 100644 --- a/client/cmdlfpresco.h +++ b/client/cmdlfpresco.h @@ -11,20 +11,6 @@ #include "common.h" -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> - -#include "cmdparser.h" // command_t -#include "comms.h" -#include "ui.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest -#include "cmdlft55xx.h" // verifywrite - int CmdLFPresco(const char *Cmd); int demodPresco(void); diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 216e0834e..fa93a395c 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -8,6 +8,23 @@ // FSK2a, rf/50, 128 bits (complete) //----------------------------------------------------------------------------- #include "cmdlfpyramid.h" +#include "common.h" +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +#include "commonutil.h" // ARRAYLEN +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "graph.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest +#include "crc.h" +#include "cmdlft55xx.h" // verifywrite static int CmdHelp(const char *Cmd); @@ -203,8 +220,10 @@ static int CmdPyramidClone(const char *Cmd) { uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0; uint32_t blocks[5]; - uint8_t bs[128]; - memset(bs, 0x00, sizeof(bs)); + uint8_t *bs = calloc(128, sizeof(uint8_t)); + if (bs == NULL) { + return PM3_EMALLOC; + } if (sscanf(Cmd, "%u %u", &fc, &cn) != 2) return usage_lf_pyramid_clone(); @@ -228,47 +247,12 @@ static int CmdPyramidClone(const char *Cmd) { blocks[3] = bytebits_to_byte(bs + 64, 32); blocks[4] = bytebits_to_byte(bs + 96, 32); + free(bs); + PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); - print_blocks(blocks, 5); + print_blocks(blocks, ARRAYLEN(blocks)); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (int8_t i = 0; i < 5; i++) { - if (i == 4) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdPyramidSim(const char *Cmd) { diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h index 0a9e2674a..2d717fbb3 100644 --- a/client/cmdlfpyramid.h +++ b/client/cmdlfpyramid.h @@ -10,21 +10,6 @@ #define CMDLFPYRAMID_H__ #include "common.h" -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> - -#include "cmdparser.h" // command_t -#include "comms.h" -#include "ui.h" -#include "graph.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest -#include "crc.h" -#include "cmdlft55xx.h" // verifywrite int CmdLFPyramid(const char *Cmd); diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index e14a679f2..784286e41 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -9,18 +9,35 @@ //----------------------------------------------------------------------------- #include "cmdlfsecurakey.h" -#include <string.h> +#include <string.h> // memcpy +#include <ctype.h> // tolower -#include "cmdparser.h" // command_t +#include "commonutil.h" // ARRAYLEN +#include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" #include "cmddata.h" #include "cmdlf.h" #include "lfdemod.h" // preamble test #include "parity.h" // for wiegand parity test +#include "protocols.h" // t55xx defines +#include "cmdlft55xx.h" // clone.. static int CmdHelp(const char *Cmd); +static int usage_lf_securakey_clone(void) { + PrintAndLogEx(NORMAL, "clone a Securakey tag to a T55x7 tag."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf securakey clone [h] [b <raw hex>]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf securakey clone 7FCB400001ADEA5344300000"); + return PM3_SUCCESS; +} + //see ASKDemod for what args are accepted static int CmdSecurakeyDemod(const char *Cmd) { (void)Cmd; // Cmd is not used so far @@ -100,6 +117,7 @@ static int CmdSecurakeyDemod(const char *Cmd) { PrintAndLogEx(SUCCESS, "Securakey Tag Found--BitLen: %u, Card ID: %u, FC: 0x%X, Raw: %08X%08X%08X", bitLen, cardid, fc, raw1, raw2, raw3); if (bitLen <= 32) PrintAndLogEx(SUCCESS, "Wiegand: %08X, Parity: %s", (lWiegand << (bitLen / 2)) | rWiegand, parity ? "Passed" : "Failed"); + PrintAndLogEx(INFO, "\nHow the FC translates to printed FC is unknown"); PrintAndLogEx(INFO, "How the checksum is calculated is unknown"); PrintAndLogEx(INFO, "Help the community identify this format further\n by sharing your tag on the pm3 forum or with forum members"); @@ -112,8 +130,45 @@ static int CmdSecurakeyRead(const char *Cmd) { } static int CmdSecurakeyClone(const char *Cmd) { - PrintAndLogEx(INFO, " To be implemented, feel free to contribute!"); - return PM3_SUCCESS; + + uint32_t blocks[4]; + bool errors = false; + uint8_t cmdp = 0; + int datalen = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_securakey_clone(); + case 'b': { + // skip first block, 3*4 = 12 bytes left + uint8_t rawhex[12] = {0}; + int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen); + if ( res != 0 ) + errors = true; + + for(uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(rawhex + ( (i - 1) * 4 ), sizeof(uint32_t)); + } + cmdp += 2; + break; + } + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + if (errors || cmdp == 0) return usage_lf_securakey_clone(); + + //Securakey - compat mode, ASK/Man, data rate 40, 3 data blocks + blocks[0] = T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_40 | 3 << T55x7_MAXBLOCK_SHIFT; + + PrintAndLogEx(INFO, "Preparing to clone Securakey to T55x7 with raw hex"); + print_blocks(blocks, ARRAYLEN(blocks)); + + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdSecurakeySim(const char *Cmd) { diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index a41cd9f40..8cc8142a7 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -338,6 +338,59 @@ static int usage_t55xx_protect() { static int CmdHelp(const char *Cmd); +int clone_t55xx_tag(uint32_t *blockdata, uint8_t numblocks) { + + if (blockdata == NULL) + return PM3_EINVARG; + if (numblocks < 1 || numblocks > 7) + return PM3_EINVARG; + + PacketResponseNG resp; + + // fast push mode + conn.block_after_ACK = true; + + for (int8_t i = 0; i < numblocks; i++) { + + // Disable fast mode on last packet + if (i == numblocks - 1) { + conn.block_after_ACK = false; + } + + clearCommandBuffer(); + + t55xx_write_block_t ng; + ng.data = blockdata[i]; + ng.pwd = 0; + ng.blockno = i; + ng.flags = 0; + + SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { + PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); + return PM3_ETIMEOUT; + } + } + + uint8_t res = 0; + for (int8_t i = 0; i < numblocks; i++) { + + if (i == 0) { + SetConfigWithBlock0(blockdata[0]); + if (t55xxAquireAndCompareBlock0(false, 0, blockdata[0], false)) + continue; + } + + if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blockdata[i]) == false) + res++; + } + + if (res == 0) + PrintAndLogEx(SUCCESS, "Success writing to tag"); + + return PM3_SUCCESS; +} + static bool t55xxProtect(bool lock, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, uint32_t new_password) { PrintAndLogEx(INFO, "Checking current configuration"); diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 1b70ca9ca..dce3a1b16 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -169,4 +169,5 @@ uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode); void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat); void printT5555Trace(t5555_tracedata_t data, uint8_t repeat); +int clone_t55xx_tag(uint32_t *blockdata, uint8_t numblocks); #endif diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 9bbbeaa7e..3a2ad6a5d 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -9,6 +9,20 @@ //----------------------------------------------------------------------------- #include "cmdlfviking.h" +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "common.h" + +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "lfdemod.h" +#include "commonutil.h" // num_to_bytes + static int CmdHelp(const char *Cmd); static int usage_lf_viking_clone(void) { diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h index 344bb3c0c..156d57c7d 100644 --- a/client/cmdlfviking.h +++ b/client/cmdlfviking.h @@ -9,21 +9,8 @@ #ifndef CMDLFVIKING_H__ #define CMDLFVIKING_H__ -#include <string.h> -#include <stdlib.h> -#include <ctype.h> - #include "common.h" -#include "cmdparser.h" // command_t -#include "comms.h" -#include "ui.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "lfdemod.h" -#include "commonutil.h" // num_to_bytes - - int CmdLFViking(const char *Cmd); int demodViking(void); diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 9f80a830d..f60510f23 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -11,6 +11,22 @@ #include "cmdlfvisa2000.h" +#include <string.h> +#include <ctype.h> +#include <stdlib.h> + +#include "commonutil.h" // ARRAYLEN +#include "common.h" +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "graph.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest +#include "cmdlft55xx.h" // write verify + #define BL0CK1 0x56495332 static int CmdHelp(const char *Cmd); @@ -165,46 +181,9 @@ static int CmdVisa2kClone(const char *Cmd) { blocks[3] = (visa_parity(id) << 4) | visa_chksum(id); PrintAndLogEx(INFO, "Preparing to clone Visa2000 to T55x7 with CardId: %u", id); - print_blocks(blocks, 4); + print_blocks(blocks, ARRAYLEN(blocks)); - uint8_t res = 0; - PacketResponseNG resp; - - // fast push mode - conn.block_after_ACK = true; - for (uint8_t i = 0; i < 4; i++) { - if (i == 3) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - t55xx_write_block_t ng; - ng.data = blocks[i]; - ng.pwd = 0; - ng.blockno = i; - ng.flags = 0; - - SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) { - - PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); - return PM3_ETIMEOUT; - } - - if (i == 0) { - SetConfigWithBlock0(blocks[0]); - if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false)) - continue; - } - - if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) - res++; - } - - if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); - - return PM3_SUCCESS; + return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); } static int CmdVisa2kSim(const char *Cmd) { diff --git a/client/cmdlfvisa2000.h b/client/cmdlfvisa2000.h index e8995cbdd..63e7fdc67 100644 --- a/client/cmdlfvisa2000.h +++ b/client/cmdlfvisa2000.h @@ -9,19 +9,7 @@ #ifndef CMDLFVISA2000_H__ #define CMDLFVISA2000_H__ -#include <string.h> -#include <ctype.h> -#include <stdlib.h> #include "common.h" -#include "cmdparser.h" // command_t -#include "comms.h" -#include "ui.h" -#include "graph.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest -#include "cmdlft55xx.h" // write verify int CmdLFVisa2k(const char *Cmd); diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index a12291199..376676f1a 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1020,3 +1020,9 @@ e6849fcc324b 39ad2963d3d1 34b16cd59ff8 # Hotel Berlin Classic room A KEY bb2c0007d022 # Hotel Berlin Classic room B KEY +# +# Coinmatic laundry Smart card +# data from: https://pastebin.com/XZQiLtUf +# +0734bfb93dab +85a438f72a8a diff --git a/client/graph.c b/client/graph.c index 7031da5e2..be1d64920 100644 --- a/client/graph.c +++ b/client/graph.c @@ -84,6 +84,8 @@ void setGraphBuf(uint8_t *buff, size_t size) { size_t getFromGraphBuf(uint8_t *buff) { if (buff == NULL) return 0; + if (GraphTraceLen == 0) return 0; + size_t i; for (i = 0; i < GraphTraceLen; ++i) { //trim @@ -134,6 +136,11 @@ void convertGraphFromBitstreamEx(int hi, int low) { } size_t size = getFromGraphBuf(bits); + if (size == 0) { + PrintAndLogEx(WARNING, "Failed to copy from graphbuffer"); + free(bits); + return; + } // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index e4cec00c0..7cfabf3ee 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -30,7 +30,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t nt = 0, nr = 0, ar = 0; uint64_t par_list = 0, ks_list = 0; uint64_t *keylist = NULL, *last_keylist = NULL; - bool arg0 = true; + bool first_run = true; // message PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n"); @@ -40,7 +40,15 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { while (true) { clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_READER, arg0, blockno, key_type, NULL, 0); + struct { + uint8_t first_run; + uint8_t blockno; + uint8_t key_type; + } PACKED payload; + payload.first_run = first_run; + payload.blockno = blockno; + payload.key_type = key_type; + SendCommandNG(CMD_HF_MIFARE_READER, (uint8_t*)&payload, sizeof(payload)); //flush queue while (kbd_enter_pressed()) { @@ -56,26 +64,47 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { } PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - int16_t isOK = resp.oldarg[0]; - if (isOK < 0) - return isOK; + if (WaitForResponseTimeout(CMD_HF_MIFARE_READER, &resp, 2000)) { + if (resp.status == PM3_EOPABORTED) { + return -1; + } - uid = (uint32_t)bytes_to_num(resp.data.asBytes + 0, 4); - nt = (uint32_t)bytes_to_num(resp.data.asBytes + 4, 4); - par_list = bytes_to_num(resp.data.asBytes + 8, 8); - ks_list = bytes_to_num(resp.data.asBytes + 16, 8); - nr = (uint32_t)bytes_to_num(resp.data.asBytes + 24, 4); - ar = (uint32_t)bytes_to_num(resp.data.asBytes + 28, 4); + struct p { + int32_t isOK; + uint8_t cuid[4]; + uint8_t nt[4]; + uint8_t par_list[8]; + uint8_t ks_list[8]; + uint8_t nr[4]; + uint8_t ar[4]; + } PACKED; + + struct p* package = (struct p*) resp.data.asBytes; + + if (package->isOK == -6) { + *key = 0101; + return 1; + } + + if (package->isOK < 0) + return package->isOK; + + + uid = (uint32_t)bytes_to_num(package->cuid, sizeof(package->cuid)); + nt = (uint32_t)bytes_to_num(package->nt, sizeof(package->nr)); + par_list = bytes_to_num(package->par_list, sizeof(package->par_list)); + ks_list = bytes_to_num(package->ks_list, sizeof(package->ks_list)); + nr = (uint32_t)bytes_to_num(package->nr, 4); + ar = (uint32_t)bytes_to_num(package->ar, 4); break; } } PrintAndLogEx(NORMAL, "\n"); - if (par_list == 0 && arg0 == true) { + if (par_list == 0 && first_run == true) { PrintAndLogEx(SUCCESS, "Parity is all zero. Most likely this card sends NACK on every authentication."); } - arg0 = false; + first_run = false; uint32_t keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); @@ -124,7 +153,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { PrintAndLogEx(FAILED, "all candidate keys failed. Restarting darkside attack"); free(last_keylist); last_keylist = keylist; - arg0 = true; + first_run = true; } } free(last_keylist);