From e435d8a6ff865a29bf001307b3f186a67b968135 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Thu, 10 Oct 2019 21:27:48 +1100 Subject: [PATCH 1/6] t55x7 save and restore eml/bin --- client/cmdlft55xx.c | 199 ++++++++++++++++++++++++++++++++++++++++++-- client/cmdlft55xx.h | 5 +- 2 files changed, 195 insertions(+), 9 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 0fbf348d7..86ec6d0e2 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -51,12 +51,15 @@ t55xx_conf_block_t config = { .block0 = 0x00, .Q5 = false, .usepwd = false, - .downlink_mode = refFixedBit + .downlink_mode = refFixedBit, + .blockData = {0}, // array to hold data blocks + .blockValid = {0} // array to hold data valid status }; t55xx_conf_block_t Get_t55xx_Config() { return config; } + void Set_t55xx_Config(t55xx_conf_block_t conf) { config = conf; } @@ -179,8 +182,9 @@ static int usage_t55xx_info() { static int usage_t55xx_dump() { PrintAndLogEx(NORMAL, "Usage: lf t55xx dump [r ] [p [o]]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex symbols)"); - PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card"); + PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex symbols)"); + PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card"); + PrintAndLogEx(NORMAL, " f - overide filename prefix (optional). Default is based on blk 0"); print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE,config.downlink_mode); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -189,6 +193,20 @@ static int usage_t55xx_dump() { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } +static int usage_t55xx_restore() { + PrintAndLogEx(NORMAL, "Usage: lf t55xx restore f [p password]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " f - filename of the dump file (.bin/.eml)"); + PrintAndLogEx(NORMAL, " p - optional password if target card has password set"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, _YELLOW_(" Assumes lf t55 detect has been run first!")); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx restore f lf-t55xx-00148040-data.bin"); + PrintAndLogEx(NORMAL, ""); + return PM3_SUCCESS; +} + static int usage_t55xx_detect() { PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [r ] [p ]"); PrintAndLogEx(NORMAL, "Options:"); @@ -339,6 +357,19 @@ static int usage_t55xx_protect() { static int CmdHelp(const char *Cmd); +void T55x7_SaveBlockData (uint8_t idx,uint32_t data) { + if (idx < T55x7_BLOCK_COUNT) { + config.blockValid[idx] = true; + config.blockData[idx] = data; + } +} +void T55x7_ClearAllBlockData (void) { + for (uint8_t idx = 0; idx < T55x7_BLOCK_COUNT; idx++) { + config.blockValid[idx] = false; + config.blockData[idx] = 0x00; + } +} + int clone_t55xx_tag(uint32_t *blockdata, uint8_t numblocks) { if (blockdata == NULL) @@ -785,7 +816,7 @@ int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, u return PM3_EWRONGANSVER; if (verbose) - printT55xxBlock(block); + printT55xxBlock(block,page1); return PM3_SUCCESS; } @@ -988,6 +1019,9 @@ static int CmdT55xxDetect(const char *Cmd) { } if (errors) return usage_t55xx_detect(); + // detect called so clear data blocks + T55x7_ClearAllBlockData (); + // sanity check. if (SanityOfflineCheck(useGB) != PM3_SUCCESS) return PM3_ESOFT; @@ -1300,7 +1334,7 @@ bool GetT55xxBlockData(uint32_t *blockdata) { return true; } -void printT55xxBlock(uint8_t blockNum) { +void printT55xxBlock(uint8_t blockNum, bool page1) { uint32_t blockData = 0; uint8_t bytes[4] = {0}; @@ -1310,6 +1344,8 @@ void printT55xxBlock(uint8_t blockNum) { num_to_bytes(blockData, 4, bytes); + T55x7_SaveBlockData ((page1)?blockNum+8 : blockNum,blockData); + PrintAndLogEx(SUCCESS, " %02d | %08X | %s | %s", blockNum, blockData, sprint_bin(DemodBuffer + config.offset, 32), sprint_ascii(bytes, 4)); } @@ -2091,6 +2127,8 @@ static int CmdT55xxDump(const char *Cmd) { bool usepwd = false; bool errors = false; uint8_t cmdp = 0; + char preferredName[FILE_PATH_SIZE] = {0}; + bool success = true; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -2112,6 +2150,12 @@ static int CmdT55xxDump(const char *Cmd) { override = 1; cmdp++; break; + case 'f': + param_getstr(Cmd, cmdp + 1, preferredName, FILE_PATH_SIZE); + cmdp+=2; + if (strlen (preferredName) == 0) + errors = true; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -2120,16 +2164,154 @@ static int CmdT55xxDump(const char *Cmd) { } if (errors) return usage_t55xx_dump(); + // Due to the few different T55xx cards and number of blocks supported + // will save the dump file if ALL page 0 is OK printT5xxHeader(0); for (uint8_t i = 0; i < 8; ++i) { - T55xxReadBlock(i, 0, usepwd, override, password, downlink_mode); + if (T55xxReadBlock(i, 0, usepwd, override, password, downlink_mode) != PM3_SUCCESS) + success = false; // idea for better user experience and display. // only show override warning on the first block read if (override == 1) override++; // flag not to show safty for 2nd and on. } printT5xxHeader(1); - for (uint8_t i = 0; i < 4; i++) - T55xxReadBlock(i, 1, usepwd, override, password, downlink_mode); + for (uint8_t i = 0; i < 4; i++) + if (T55xxReadBlock(i, 1, usepwd, override, password, downlink_mode) != PM3_SUCCESS) + T55x7_SaveBlockData (8+i,0x00); + + + if (success) { // all ok save dump to file + // saveFileEML will add .eml extension to filename + // saveFile (binary) passes in the .bin extension. + if (strcmp (preferredName,"") == 0) { // Set default filename, if not set by user + strcpy (preferredName,"lf-t55xx"); + for (uint8_t i = 1; i <= 7; i++) { + if ((config.blockData[i] != 0x00) && (config.blockData[i] != 0xFFFFFFFF)) + sprintf (preferredName,"%s-%08X",preferredName,config.blockData[i]); + else + break; + } + sprintf (preferredName,"%s-data",preferredName); + } + + // Swap endian so the files match the txt display + uint32_t data[T55x7_BLOCK_COUNT]; + + for (int i = 0; i < T55x7_BLOCK_COUNT; i++) + data[i] = BSWAP_32(config.blockData[i]); + + saveFileEML(preferredName, (uint8_t *)data, T55x7_BLOCK_COUNT*sizeof(uint32_t), sizeof(uint32_t)); + saveFile (preferredName, ".bin", data, sizeof(data)); + } + + return PM3_SUCCESS; +} + +static int CmdT55xxRestore(const char *Cmd) { + bool errors = false; + uint8_t cmdp = 0; + char preferredName[FILE_PATH_SIZE] = {0}; + char ext[FILE_PATH_SIZE] = {0}; + int success = PM3_ESOFT; + uint32_t password = 0x00; + bool usepwd = false; + uint32_t data[12] = {0}; + size_t datalen = 0; + uint8_t blockidx; + uint8_t downlink_mode; + char writeCmdOpt[100]; + char pwdOpt [11] = {0}; // p XXXXXXXX + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_t55xx_restore(); + case 'f': + param_getstr(Cmd, cmdp + 1, preferredName, FILE_PATH_SIZE); + if (strlen (preferredName) == 0) + errors = true; + cmdp+=2; + break; + case 'p': + password = param_get32ex(Cmd, cmdp + 1, 0, 16); + usepwd = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + // File name expected to be .eml .bin or .json so sould be at least 4 + if (errors || (strlen (preferredName) == 0)) return usage_t55xx_restore(); + + // split file name into prefix and ext. + int fnLength; + + fnLength = strlen (preferredName); + + if (fnLength > 4) { // Holds .EXT [.bin|.eml] + memcpy (ext,&preferredName[fnLength - 4],4); + ext[5] = 0x00; + + if (memcmp (ext,".bin",4) == 0) { + preferredName[fnLength-4] = 0x00; + success = loadFile (preferredName, ".bin", data, sizeof(data),&datalen); + } + if (memcmp (ext,".eml",4) == 0) { + preferredName[fnLength-4] = 0x00; + datalen = 12; + success = loadFileEML(preferredName, (uint8_t *)data, &datalen); + } + } + + if (success == PM3_SUCCESS) { // Got data, so write to cards + if (datalen == T55x7_BLOCK_COUNT * 4) { // 12 blocks * 4 bytes per block + if (usepwd) + sprintf (pwdOpt,"p %08X",password); + + // Restore endien for writing to card + for (blockidx = 0; blockidx < 12; blockidx++) + data[blockidx] = BSWAP_32(data[blockidx]); + + // Have data ready, lets write + // Order + // write blocks 1..7 page 0 + // write blocks 1..3 page 1 + // update downlink mode (if needed) and write b 0 + downlink_mode = 0; + if ((((data[11] >> 28) & 0xf) == 6) || (((data[11] >> 28) & 0xf) == 9)) + downlink_mode = (data[11] >> 10) & 3; + + // write out blocks 1-7 page 0 + for (blockidx = 1; blockidx <= 7; blockidx++) { + sprintf (writeCmdOpt,"b %d d %08X %s",blockidx,data[blockidx],pwdOpt); + if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) + PrintAndLogEx(WARNING, "Warning: error writing blk %d",blockidx); + } + + // if password was set on the "blank" update as we may have just changed it + if (usepwd) + sprintf (pwdOpt,"p %08X",data[7]); + + // write out blocks 1-3 page 1 + for (blockidx = 9; blockidx <= 11; blockidx++) { + sprintf (writeCmdOpt,"b %d 1 d %08X %s",blockidx-8,data[blockidx],pwdOpt); + if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) + PrintAndLogEx(WARNING, "Warning: error writing blk %d",blockidx); + } + + // Update downlink mode for the page 0 config write. + config.downlink_mode = downlink_mode; + + // Write the page 0 config + sprintf (writeCmdOpt,"b 0 d %08X %s",data[0],pwdOpt); + if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) + PrintAndLogEx(WARNING, "Warning: error writing blk 0"); + } + } return PM3_SUCCESS; } @@ -3324,6 +3506,7 @@ static command_t CommandTable[] = { {"detect", CmdT55xxDetect, AlwaysAvailable, "[1] Try detecting the tag modulation from reading the configuration block."}, {"deviceconfig", CmdT55xxSetDeviceConfig, IfPm3Lf, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"}, {"dump", CmdT55xxDump, IfPm3Lf, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, + {"restore", CmdT55xxRestore, IfPm3Lf, "f [p ] -- Restore a dump file of a T55xx card"}, {"info", CmdT55xxInfo, AlwaysAvailable, "[1] Show T55x7 configuration data (page 0/ blk 0)"}, {"p1detect", CmdT55xxDetectPage1, IfPm3Lf, "[1] Try detecting if this is a t55xx tag by reading page 1"}, {"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index d7791466c..06c9399f1 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -20,6 +20,7 @@ #define T55x7_PAGE1 0x01 #define T55x7_PWD 0x00000010 #define REGULAR_READ_MODE_BLOCK 0xFF +#define T55x7_BLOCK_COUNT 12 // config blocks #define T55X7_DEFAULT_CONFIG_BLOCK 0x000880E8 // ASK, compat mode, data rate 32, manchester, STT, 7 data blocks @@ -125,6 +126,8 @@ typedef struct { refLeading0 = 0x02, ref1of4 = 0x03, } downlink_mode; + uint32_t blockData [T55x7_BLOCK_COUNT]; // the dump/read will save data here. + bool blockValid [T55x7_BLOCK_COUNT]; // this will allow easy access to the data for display etc. } t55xx_conf_block_t; t55xx_conf_block_t Get_t55xx_Config(void); @@ -144,7 +147,7 @@ char *GetModelStrFromCID(uint32_t cid); char *GetSelectedModulationStr(uint8_t id); char *GetDownlinkModeStr(uint8_t dlmode); void printT5xxHeader(uint8_t page); -void printT55xxBlock(uint8_t blockNum); +void printT55xxBlock(uint8_t blockNum,bool page1); int printConfiguration(t55xx_conf_block_t b); bool t55xxAquireAndCompareBlock0(bool usepwd, uint32_t password, uint32_t known_block0, bool verbose); From 92639c9df8b52acf5cf95d493c7e21120e2f4f7b Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Thu, 10 Oct 2019 21:38:53 +1100 Subject: [PATCH 2/6] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f6996545..140c072c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 lf t55xx dump save and lf t55xx restore for .bin and .eml files (@mwalker33) - Added lf t55xx detected to try without password first (@mwalker33) - Display high bit for detected Kastle HIDs to allow `lf hid clone [id]` to work properly (@swg0101) - Add option `-n` to scripts pm3* (@doegox) From 18520a5dfd3eeb1b3855e44b8235f83d3a16bdda Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Thu, 10 Oct 2019 22:07:57 +1100 Subject: [PATCH 3/6] Update cmdlft55xx.c --- client/cmdlft55xx.c | 195 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 157 insertions(+), 38 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 98767eda3..796179ad9 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -340,7 +340,8 @@ static int usage_t55xx_deviceconfig() { return PM3_SUCCESS; } static int usage_t55xx_protect() { - PrintAndLogEx(NORMAL, "This command set or unsets the pwd bit on T5577."); + PrintAndLogEx(NORMAL, "This command sets the pwd bit on T5577."); + PrintAndLogEx(NORMAL, _RED_("WARNING:") " this locks the tag!"); PrintAndLogEx(NORMAL, "Usage: lf t55xx protect [r ] [p ] [o] [n ]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); @@ -371,8 +372,8 @@ void T55x7_ClearAllBlockData (void) { } int clone_t55xx_tag(uint32_t *blockdata, uint8_t numblocks) { - - if (blockdata == NULL) + + if (blockdata == NULL) return PM3_EINVARG; if (numblocks < 1 || numblocks > 8) return PM3_EINVARG; @@ -403,7 +404,7 @@ int clone_t55xx_tag(uint32_t *blockdata, uint8_t numblocks) { return PM3_ETIMEOUT; } } - + uint8_t res = 0; for (int8_t i = 0; i < numblocks; i++) { @@ -419,7 +420,7 @@ int clone_t55xx_tag(uint32_t *blockdata, uint8_t numblocks) { if (res == 0) PrintAndLogEx(SUCCESS, "Success writing to tag"); - + return PM3_SUCCESS; } @@ -496,7 +497,7 @@ bool t55xxAquireAndCompareBlock0(bool usepwd, uint32_t password, uint32_t known_ PrintAndLogEx(INFO, "Block0 write detected, running `detect` to see if validation is possible"); for (uint8_t m = 0; m < 4; m++) { - if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false) { + if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false) { continue; } @@ -529,7 +530,7 @@ bool t55xxAquireAndDetect(bool usepwd, uint32_t password, uint32_t known_block0, config.pwd = 0x00; for (uint8_t m = 0; m < 4; m++) { - if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false) + if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false) continue; if (tryDetectModulationEx(m, verbose, known_block0) == false) @@ -793,7 +794,7 @@ int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, u // override = 1 (override and display) // override = 2 (override and no display) if (override == 0) { - if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0, downlink_mode) == false) + if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0, downlink_mode) == false) return PM3_ERFTRANS; if (tryDetectModulation(downlink_mode, false) == false) { @@ -809,7 +810,7 @@ int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, u } } - if (AquireData(page1, block, usepwd, password, downlink_mode) == false) + if (AcquireData(page1, block, usepwd, password, downlink_mode) == false) return PM3_ERFTRANS; if (DecodeT55xxBlock() == false) @@ -1033,7 +1034,7 @@ static int CmdT55xxDetect(const char *Cmd) { if (try_all_dl_modes) { for (uint8_t m = downlink_mode; m < 4; m++) { - if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, try_with_pwd & usepwd, password, m) == false) + if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, try_with_pwd & usepwd, password, m) == false) continue; // pre fill to save passing in. @@ -1056,7 +1057,7 @@ static int CmdT55xxDetect(const char *Cmd) { else config.pwd = 0x00; - if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) { + if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) { found = tryDetectModulation(downlink_mode, T55XX_PrintConfig); } } @@ -1694,6 +1695,69 @@ static int CmdT55xxWriteBlock(const char *Cmd) { return PM3_SUCCESS; } +static int CmdT55xxDangerousRaw(const char *Cmd) { + // supports only default downlink mode + t55xx_test_block_t ng; + ng.time = 0; + ng.bitlen = 0; + memset(ng.data, 0x00, sizeof(ng.data)); + bool errors = false; + uint8_t cmdp = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 't': + ng.time = param_get32ex(Cmd, cmdp + 1, 0, 10); + if (ng.time == 0 || ng.time > 200000) { + PrintAndLogEx(ERR, "Timing off 1..200000 limits, got %i", ng.time); + errors = true; + break; + } + cmdp += 2; + break; + case 'b': { + uint32_t n = param_getlength(Cmd, cmdp + 1); + if (n > 128) { + PrintAndLogEx(ERR, "Bitstream too long, max 128 bits, got %i", n); + errors = true; + break; + } + for (uint8_t i = 0; i < n; i++) { + char c = param_getchar_indx(Cmd, i, cmdp + 1); + if (c == '0') + ng.data[i] = 0; + else if (c == '1') + ng.data[i] = 1; + else { + PrintAndLogEx(ERR, "Unknown bit char '%c'", c); + errors = true; + break; + } + } + ng.bitlen = n; + cmdp += 2; + break; + } + default: + PrintAndLogEx(ERR, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors || ng.bitlen == 0 || ng.time == 0) { + PrintAndLogEx(ERR, "Error occurred, abort. " _RED_("DANGEROUS COMMAND, DO NOT USE!")); + return PM3_EINVARG; + } + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_LF_T55XX_DANGERRAW, (uint8_t *)&ng, sizeof(ng)); + if (!WaitForResponseTimeout(CMD_LF_T55XX_DANGERRAW, &resp, 2000)) { + PrintAndLogEx(ERR, "Error occurred, device did not ACK write operation."); + return PM3_ETIMEOUT; + } + return resp.status; +} + static int CmdT55xxReadTrace(const char *Cmd) { bool frombuff = false; @@ -1733,7 +1797,7 @@ static int CmdT55xxReadTrace(const char *Cmd) { uint32_t password = 0; // REGULAR_READ_MODE_BLOCK - yeilds correct Page 1 Block 2 data i.e. + 32 bit offset. - if (!AquireData(T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password, downlink_mode)) + if (!AcquireData(T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password, downlink_mode)) return PM3_ENODATA; } @@ -2036,7 +2100,7 @@ static int CmdT55xxInfo(const char *Cmd) { // sanity check. if (SanityOfflineCheck(false) != PM3_SUCCESS) return PM3_ENODATA; - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) + if (!AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) return PM3_ENODATA; } @@ -2327,7 +2391,60 @@ static int CmdT55xxRestore(const char *Cmd) { return PM3_SUCCESS; } -bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint8_t downlink_mode) { +static int CmdT55xxRestore(const char *Cmd) { + + uint32_t password = 0; + uint8_t override = 0; + uint8_t downlink_mode = config.downlink_mode;; + bool usepwd = false; + bool errors = false; + uint8_t cmdp = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_t55xx_restore(); + case 'r': + downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); + if (downlink_mode > 3) + downlink_mode = 0; + + cmdp += 2; + break; + case 'p': + password = param_get32ex(Cmd, cmdp + 1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case 'o': + override = 1; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors) return usage_t55xx_restore(); + + PrintAndLogEx(INFO, "Work in progress. To be implemented"); + if (usepwd || password || override ) { + + } + // load file name (json/eml/bin) + + // Print dump data? + + uint32_t res = PM3_SUCCESS; + +// page0. +// res = clone_t55xx_tag(blockdata, numblocks); + + return res; +} + +bool AcquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint8_t downlink_mode) { // arg0 bitmodes: // b0 = pwdmode // b1 = page to read from @@ -2670,18 +2787,19 @@ static int CmdResetRead(const char *Cmd) { if (resp.status == PM3_SUCCESS) { - uint8_t *got = calloc(BIGBUF_SIZE - 1, sizeof(uint8_t)); + uint16_t gotsize = BIGBUF_SIZE - 1; + uint8_t *got = calloc(gotsize, sizeof(uint8_t)); if (got == NULL) { PrintAndLogEx(WARNING, "failed to allocate memory"); return PM3_EMALLOC; } - if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 0, NULL, 2500, false)) { + if (!GetFromDevice(BIG_BUF, got, gotsize, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); free(got); return PM3_ETIMEOUT; } - setGraphBuf(got, sizeof(got)); + setGraphBuf(got, gotsize); free(got); } return PM3_SUCCESS; @@ -2826,7 +2944,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { } } - if (errors) return usage_t55xx_chk(); + if (errors || cmdp == 0) return usage_t55xx_chk(); /* // block 7, page1 = false, usepwd = false, override = false, pwd = 00000000 @@ -2859,10 +2977,10 @@ static int CmdT55xxChkPwds(const char *Cmd) { if (resp.oldarg[0]) { PrintAndLogEx(SUCCESS, "\nFound a candidate [ " _YELLOW_("%08"PRIX64) " ]. Trying to validate", resp.oldarg[1]); - if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.oldarg[1], downlink_mode)) { + if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.oldarg[1], downlink_mode)) { found = tryDetectModulation(downlink_mode, T55XX_PrintConfig); if (found) { - PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08"PRIX64) " ]", resp.oldarg[1]); + PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08"PRIX64) "]", resp.oldarg[1]); } else { PrintAndLogEx(WARNING, "Check pwd failed"); @@ -2908,13 +3026,13 @@ static int CmdT55xxChkPwds(const char *Cmd) { PrintAndLogEx(INFO, "Testing %08"PRIX64, curr_password); for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) { - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr_password, dl_mode)) { + if (!AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr_password, dl_mode)) { continue; } found = tryDetectModulation(dl_mode, T55XX_PrintConfig); if (found) { - PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08"PRIX64) " ]", curr_password); + PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08"PRIX64) "]", curr_password); dl_mode = 4; // Exit other downlink mode checks c = keycount; // Exit loop } @@ -2970,11 +3088,11 @@ static int CmdT55xxBruteForce(const char *Cmd) { break; } } - if (start_password >= end_password) { - return usage_t55xx_bruteforce(); - } - if (errors) return usage_t55xx_bruteforce(); + if (start_password >= end_password) + errors = true; + + if (errors || cmdp == 0) return usage_t55xx_bruteforce(); uint64_t t1 = msclock(); @@ -3005,7 +3123,7 @@ static int CmdT55xxBruteForce(const char *Cmd) { PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") "]", curr - 1); T55xx_Print_DownlinkMode((found >> 1) & 3); } else - PrintAndLogEx(WARNING, "Bruteforce failed, last tried: [ " _YELLOW_("%08X") " ]", curr); + PrintAndLogEx(WARNING, "Bruteforce failed, last tried: [ " _YELLOW_("%08X") "]", curr); t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1 / 1000.0); @@ -3026,14 +3144,14 @@ uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode) { // check if dl mode 4 and loop if needed for (dl_mode = downlink_mode; dl_mode < 4; dl_mode++) { - AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password, dl_mode); - - // if (getSignalProperties()->isnoise == false) { - // } else { - if (tryDetectModulation(dl_mode, T55XX_PrintConfig)) { - return 1 + (dl_mode << 1); + if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password, dl_mode)) { + // if (getSignalProperties()->isnoise == false) { + // } else { + if (tryDetectModulation(dl_mode, T55XX_PrintConfig)) { + return 1 + (dl_mode << 1); + } + // } } - // } if (!try_all_dl_modes) dl_mode = 4; } return 0; @@ -3073,8 +3191,7 @@ static int CmdT55xxRecoverPW(const char *Cmd) { } } - if (errors) return usage_t55xx_recoverpw(); - + if (errors || cmdp == 0) return usage_t55xx_recoverpw(); // first try fliping each bit in the expected password while (bit < 32) { @@ -3161,7 +3278,7 @@ bool tryDetectP1(bool getData) { bool st = true; if (getData) { - if (!AquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, false, 0, 0)) + if (!AcquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, false, 0, 0)) return false; } @@ -3311,7 +3428,7 @@ static int CmdT55xxDetectPage1(const char *Cmd) { if (!useGB) { for (dl_mode = downlink_mode; dl_mode < 4; dl_mode++) { - found = AquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, usepwd, password, dl_mode); + found = AcquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, usepwd, password, dl_mode); //return PM3_ENODATA; if (tryDetectP1(false)) { //tryDetectModulation()) found = true; @@ -3515,6 +3632,7 @@ static command_t CommandTable[] = { {"bruteforce", CmdT55xxBruteForce, IfPm3Lf, " Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, AlwaysAvailable, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"}, + {"dangerraw", CmdT55xxDangerousRaw, IfPm3Lf, "Sends raw bitstream. Dangerous, do not use!! b t "}, {"detect", CmdT55xxDetect, AlwaysAvailable, "[1] Try detecting the tag modulation from reading the configuration block."}, {"deviceconfig", CmdT55xxSetDeviceConfig, IfPm3Lf, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"}, {"dump", CmdT55xxDump, IfPm3Lf, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, @@ -3524,6 +3642,7 @@ static command_t CommandTable[] = { {"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"}, {"read", CmdT55xxReadBlock, IfPm3Lf, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, {"resetread", CmdResetRead, IfPm3Lf, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, + {"restore", CmdT55xxRestore, IfPm3Lf, "[password] Restore T55xx card Page 0 / Page 1 blocks"}, {"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"}, {"special", special, IfPm3Lf, "Show block changes with 64 different offsets"}, {"trace", CmdT55xxReadTrace, AlwaysAvailable, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"}, From f109915ebdbbbbd483fa662691809f07a564c03d Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Fri, 11 Oct 2019 20:29:20 +1100 Subject: [PATCH 4/6] T55xx Save and Restore --- client/cmdlft55xx.c | 42 +++++++++++++++++++++++------------------- client/cmdlft55xx.h | 7 +++++-- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 4cffd059a..7bfadf790 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -52,10 +52,10 @@ t55xx_conf_block_t config = { .Q5 = false, .usepwd = false, .downlink_mode = refFixedBit, - .blockData = {0}, // array to hold data blocks - .blockValid = {0} // array to hold data valid status }; +t55xx_memory_item_t cardmem[T55x7_BLOCK_COUNT] = {0}; + t55xx_conf_block_t Get_t55xx_Config() { return config; } @@ -360,14 +360,14 @@ static int CmdHelp(const char *Cmd); void T55x7_SaveBlockData (uint8_t idx,uint32_t data) { if (idx < T55x7_BLOCK_COUNT) { - config.blockValid[idx] = true; - config.blockData[idx] = data; + cardmem[idx].valid = true; + cardmem[idx].blockdata = data; } } void T55x7_ClearAllBlockData (void) { for (uint8_t idx = 0; idx < T55x7_BLOCK_COUNT; idx++) { - config.blockValid[idx] = false; - config.blockData[idx] = 0x00; + cardmem[idx].valid = false; + cardmem[idx].blockdata = 0x00; } } @@ -2261,8 +2261,8 @@ static int CmdT55xxDump(const char *Cmd) { if (strcmp (preferredName,"") == 0) { // Set default filename, if not set by user strcpy (preferredName,"lf-t55xx"); for (uint8_t i = 1; i <= 7; i++) { - if ((config.blockData[i] != 0x00) && (config.blockData[i] != 0xFFFFFFFF)) - sprintf (preferredName,"%s-%08X",preferredName,config.blockData[i]); + if ((cardmem[i].blockdata != 0x00) && (cardmem[i].blockdata != 0xFFFFFFFF)) + sprintf (preferredName,"%s-%08X",preferredName,cardmem[i].blockdata); else break; } @@ -2273,7 +2273,7 @@ static int CmdT55xxDump(const char *Cmd) { uint32_t data[T55x7_BLOCK_COUNT]; for (int i = 0; i < T55x7_BLOCK_COUNT; i++) - data[i] = BSWAP_32(config.blockData[i]); + data[i] = BSWAP_32(cardmem[i].blockdata); saveFileEML(preferredName, (uint8_t *)data, T55x7_BLOCK_COUNT*sizeof(uint32_t), sizeof(uint32_t)); saveFile (preferredName, ".bin", data, sizeof(data)); @@ -2327,19 +2327,24 @@ static int CmdT55xxRestore(const char *Cmd) { fnLength = strlen (preferredName); - if (fnLength > 4) { // Holds .EXT [.bin|.eml] + success = PM3_ESOFT; + if (fnLength > 4) { // Holds extension [.bin|.eml] memcpy (ext,&preferredName[fnLength - 4],4); ext[5] = 0x00; - + + // check if valid file extension and attempt to load data + if (memcmp (ext,".bin",4) == 0) { preferredName[fnLength-4] = 0x00; success = loadFile (preferredName, ".bin", data, sizeof(data),&datalen); - } - if (memcmp (ext,".eml",4) == 0) { + + } else if (memcmp (ext,".eml",4) == 0) { preferredName[fnLength-4] = 0x00; datalen = 12; success = loadFileEML(preferredName, (uint8_t *)data, &datalen); - } + + } else + PrintAndLogEx(WARNING,"\nWarning: invalid dump filename "_YELLOW_("%s")"to restore!\n",preferredName); } if (success == PM3_SUCCESS) { // Got data, so write to cards @@ -2390,7 +2395,7 @@ static int CmdT55xxRestore(const char *Cmd) { return PM3_SUCCESS; } - +/* static int CmdT55xxRestore(const char *Cmd) { uint32_t password = 0; @@ -2443,7 +2448,7 @@ static int CmdT55xxRestore(const char *Cmd) { return res; } - +*/ bool AcquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint8_t downlink_mode) { // arg0 bitmodes: // b0 = pwdmode @@ -3494,7 +3499,6 @@ static int CmdT55xxSetDeviceConfig(const char *Cmd) { downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); if (downlink_mode > 3) downlink_mode = 0; - cmdp += 2; break; case 'p': @@ -3636,13 +3640,13 @@ static command_t CommandTable[] = { {"detect", CmdT55xxDetect, AlwaysAvailable, "[1] Try detecting the tag modulation from reading the configuration block."}, {"deviceconfig", CmdT55xxSetDeviceConfig, IfPm3Lf, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"}, {"dump", CmdT55xxDump, IfPm3Lf, "[password] [o] Dump T55xx card Page 0 block 0-7. Optional [password], [override]"}, - {"restore", CmdT55xxRestore, IfPm3Lf, "f [p ] -- Restore a dump file of a T55xx card"}, + {"restore", CmdT55xxRestore, IfPm3Lf, "f [p ] Restore T55xx card Page 0 / Page 1 blocks"}, {"info", CmdT55xxInfo, AlwaysAvailable, "[1] Show T55x7 configuration data (page 0/ blk 0)"}, {"p1detect", CmdT55xxDetectPage1, IfPm3Lf, "[1] Try detecting if this is a t55xx tag by reading page 1"}, {"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"}, {"read", CmdT55xxReadBlock, IfPm3Lf, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, {"resetread", CmdResetRead, IfPm3Lf, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, - {"restore", CmdT55xxRestore, IfPm3Lf, "[password] Restore T55xx card Page 0 / Page 1 blocks"}, +// {"restore", CmdT55xxRestore, IfPm3Lf, "[password] Restore T55xx card Page 0 / Page 1 blocks"}, {"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"}, {"special", special, IfPm3Lf, "Show block changes with 64 different offsets"}, {"trace", CmdT55xxReadTrace, AlwaysAvailable, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 59b8dc3f0..7b980c042 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -126,10 +126,13 @@ typedef struct { refLeading0 = 0x02, ref1of4 = 0x03, } downlink_mode; - uint32_t blockData [T55x7_BLOCK_COUNT]; // the dump/read will save data here. - bool blockValid [T55x7_BLOCK_COUNT]; // this will allow easy access to the data for display etc. } t55xx_conf_block_t; +typedef struct { + uint32_t blockdata; + bool valid; +} t55xx_memory_item_t ; + t55xx_conf_block_t Get_t55xx_Config(void); void Set_t55xx_Config(t55xx_conf_block_t conf); From 25182d8e2fbb92e3e374773a8f2540a898f65c34 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Fri, 11 Oct 2019 21:16:28 +1100 Subject: [PATCH 5/6] Update cmdlft55xx.c Fix travis initilisation error. --- client/cmdlft55xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 7bfadf790..c2a62dc6e 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -54,7 +54,7 @@ t55xx_conf_block_t config = { .downlink_mode = refFixedBit, }; -t55xx_memory_item_t cardmem[T55x7_BLOCK_COUNT] = {0}; +t55xx_memory_item_t cardmem[T55x7_BLOCK_COUNT] = {{0}}; t55xx_conf_block_t Get_t55xx_Config() { return config; From 44b25cc6ac3d6a9f283b7b0bd040c076e7cf4014 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sat, 12 Oct 2019 17:55:23 +1100 Subject: [PATCH 6/6] Update cmdlft55xx.c removed extra comma. --- client/cmdlft55xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index c2a62dc6e..2894faa46 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -51,7 +51,7 @@ t55xx_conf_block_t config = { .block0 = 0x00, .Q5 = false, .usepwd = false, - .downlink_mode = refFixedBit, + .downlink_mode = refFixedBit }; t55xx_memory_item_t cardmem[T55x7_BLOCK_COUNT] = {{0}};