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 #include +#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 ]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " b : 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/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