diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 7391fd38c..55e4aa478 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -847,6 +847,8 @@ int CmdHF15Restore(const char *Cmd) { return 3; } + PrintAndLogEx(INFO, "Restoring data blocks."); + while (1) { tried = 0; hex[0] = 0x00; @@ -874,15 +876,22 @@ int CmdHF15Restore(const char *Cmd) { snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newCmdPrefix, i, hex); PrintAndLogEx(DEBUG, "Command to be sent| %s", tmpCmd); - for (tried = 0; tried < retries; tried++) - if (!(retval = CmdHF15Write(tmpCmd))) + for (tried = 0; tried < retries; tried++) { + if (!(retval = CmdHF15Write(tmpCmd))) { break; - if (tried >= retries) + } + } + if (tried >= retries) { + fclose(f); + PrintAndLogEx(FAILED, "Restore failed. Too many retries."); return retval; + } i++; } fclose(f); + PrintAndLogEx(INFO, "Finish restore"); + return 0; } int CmdHF15List(const char *Cmd) { diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 99030b85c..fdbaa7563 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1059,8 +1059,8 @@ int CmdHF14AMfRestore(const char *Cmd) { } } } - fclose(fdump); + PrintAndLogEx(INFO, "Finish restore"); return 0; } diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 4097a0a3a..956cc1a70 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2223,6 +2223,7 @@ int CmdHF14AMfURestore(const char *Cmd) { DropField(); free(dump); + PrintAndLogEx(INFO, "Finish restore"); return 0; } // diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 3fcc4fdda..b25054b2d 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -431,7 +431,7 @@ int CmdT55xxReadBlock(const char *Cmd) { return T55xxReadBlock(block, page1, usepwd, override, password); } -bool DecodeT55xxBlock() { +bool DecodeT55xxBlock(void) { char buf[30] = {0x00}; char *cmdStr = buf; @@ -462,7 +462,7 @@ bool DecodeT55xxBlock() { case DEMOD_PSK1: // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) save_restoreGB(GRAPH_SAVE); - CmdLtrim("160"); + CmdLtrim("150"); snprintf(cmdStr, sizeof(buf), "%d %d 6", bitRate[config.bitrate], config.inverted); ans = PSKDemod(cmdStr, false); //undo trim samples @@ -472,7 +472,7 @@ bool DecodeT55xxBlock() { case DEMOD_PSK3: //not fully implemented // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) save_restoreGB(GRAPH_SAVE); - CmdLtrim("160"); + CmdLtrim("150"); snprintf(cmdStr, sizeof(buf), "%d 0 6", bitRate[config.bitrate]); ans = PSKDemod(cmdStr, false); psk1TOpsk2(DemodBuffer, DemodBufferLen); @@ -494,7 +494,7 @@ bool DecodeT55xxBlock() { return (bool) ans; } -bool DecodeT5555TraceBlock() { +bool DecodeT5555TraceBlock(void) { DemodBufferLen = 0x00; // According to datasheet. Always: RF/64, not inverted, Manchester @@ -547,13 +547,13 @@ int CmdT55xxDetect(const char *Cmd) { } if (!tryDetectModulation()) - PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); + PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'") ); return 0; } // detect configuration? -bool tryDetectModulation() { +bool tryDetectModulation(void) { t55xx_conf_block_t tests[15]; int bitRate = 0, clk = 0, firstClockEdge = 0; @@ -754,11 +754,42 @@ bool testKnownConfigBlock(uint32_t block0) { case T55X7_NORALYS_CONFIG_BLOCK: case T55X7_IOPROX_CONFIG_BLOCK: case T55X7_PRESCO_CONFIG_BLOCK: + case T55X7_NEDAP_64_CONFIG_BLOCK: + case T55X7_NEDAP_128_CONFIG_BLOCK: return true; } return false; } +bool GetT55xxBlockData(uint32_t *blockdata) { + + if (DemodBufferLen == 0) + return false; + + uint8_t idx = config.offset; + + if (idx + 32 > DemodBufferLen) { + PrintAndLogEx(WARNING, "The configured offset %d is too big. Possible offset: %d)", idx, DemodBufferLen - 32); + return false; + } + + *blockdata = PackBits(0, 32, DemodBuffer + idx); + return true; +} + +void printT55xxBlock(const char *blockNum) { + + uint32_t blockData = 0; + uint8_t bytes[4] = {0}; + + if (GetT55xxBlockData(&blockData) == false) + return; + + num_to_bytes(blockData, 4, bytes); + + PrintAndLogEx(NORMAL, " %s | %08X | %s | %s", blockNum, blockData, sprint_bin(DemodBuffer + config.offset, 32), sprint_ascii(bytes, 4)); +} + bool testModulation(uint8_t mode, uint8_t modread) { switch (mode) { case DEMOD_FSK: @@ -932,30 +963,6 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) return false; } -void printT55xxBlock(const char *blockNum) { - - uint8_t i = config.offset; - uint8_t endpos = 32 + i; - uint32_t blockData = 0; - uint8_t bits[64] = {0x00}; - - if (!DemodBufferLen) return; - - if (endpos > DemodBufferLen) { - PrintAndLogEx(NORMAL, "The configured offset %d is too big. Possible offset: %d)", i, DemodBufferLen - 32); - return; - } - - for (; i < endpos; ++i) - bits[i - config.offset] = DemodBuffer[i]; - - blockData = PackBits(0, 32, bits); - uint8_t bytes[4] = {0}; - num_to_bytes(blockData, 4, bytes); - - PrintAndLogEx(NORMAL, " %s | %08X | %s | %s", blockNum, blockData, sprint_bin(bits, 32), sprint_ascii(bytes, 4)); -} - int special(const char *Cmd) { uint32_t blockData = 0; uint8_t bits[32] = {0x00}; diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index cd240e5f2..ce990bebd 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -156,19 +156,20 @@ char *GetQ5ModulationStr(uint32_t id); char *GetModulationStr(uint32_t id, bool xmode); char *GetModelStrFromCID(uint32_t cid); char *GetSelectedModulationStr(uint8_t id); -uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream); void printT5xxHeader(uint8_t page); void printT55xxBlock(const char *demodStr); int printConfiguration(t55xx_conf_block_t b); +extern int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password); +bool GetT55xxBlockData(uint32_t *blockdata); bool DecodeT55xxBlock(void); -bool tryDetectModulation(void); +extern bool tryDetectModulation(void); bool testKnownConfigBlock(uint32_t block0); + extern bool tryDetectP1(bool getData); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); int special(const char *Cmd); -bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password); - +extern bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password); int tryOnePassword(uint32_t password); void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat); diff --git a/client/scripting.c b/client/scripting.c index a26db0c19..f3afb18d4 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -95,7 +95,7 @@ static int l_GetFromBigBuf(lua_State *L) { //Push it as a string lua_pushlstring(L, (const char *)data, len); free(data); - return 1;// return 1 to signal one return value + return 1; // return 1 to signal one return value } /** @@ -561,7 +561,7 @@ static int l_reveng_models(lua_State *L) { // endian ,char, 'B','b','L','l','t','r' describing if Big-Endian or Little-Endian should be used in different combinations. // // outputs: string with hex representation of the CRC result -static int l_reveng_RunModel(lua_State *L) { +static int l_reveng_runmodel(lua_State *L) { //-c || -v //inModel = valid model name string - CRC-8 //inHexStr = input hex string to calculate crc on @@ -701,6 +701,145 @@ static int l_keygen_algoD(lua_State *L) { return 2; } +/* +Read T55Xx block. +param1 uint8_t block +param2 bool page1 +param3 bool override +param4 uint32_t password +*/ +static int l_T55xx_readblock(lua_State *L) { + + //Check number of arguments + int n = lua_gettop(L); + if ( n != 4 ) { + return returnToLuaWithError(L, "Wrong number of arguments, got %d bytes, expected 4", n); + } + + uint32_t block, usepage1, override, password; + bool usepwd; + size_t size; + + const char *p_blockno = luaL_checklstring(L, 1, &size); + if (size < 1 || size > 2) return returnToLuaWithError(L, "Wrong size of blockNo, got %d, expected 1 or 2", (int) size); + sscanf(p_blockno, "%x", &block); + + const char *p_usepage1 = luaL_checklstring(L, 2, &size); + if (size != 1) return returnToLuaWithError(L, "Wrong size of usePage1, got %d, expected 1", (int) size); + sscanf(p_usepage1, "%x", &usepage1); + + const char *p_override = luaL_checklstring(L, 3, &size); + if (size != 1) return returnToLuaWithError(L, "Wrong size of override, got %d, expected 1", (int) size); + sscanf(p_override, "%x", &override); + + const char *p_pwd = luaL_checklstring(L, 4, &size); + if ( size == 0 ) { + usepwd = false; + } else { + + if (size != 8) return returnToLuaWithError(L, "Wrong size of pwd, got %d , expected 8", (int) size); + sscanf(p_pwd, "%08x", &password); + usepwd = true; + } + + //Password mode + if (usepwd) { + // try reading the config block and verify that PWD bit is set before doing this! + if (!override) { + + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0)) { + return returnToLuaWithError(L, "Failed to read config block"); + } + + if (!tryDetectModulation()) { + PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits."); + return 0; + } else { + PrintAndLogEx(NORMAL, "Safety Check: PWD bit is NOT set in config block. Reading without password..."); + usepwd = false; + usepage1 = false; + } + } else { + PrintAndLogEx(NORMAL, "Safety Check Overriden - proceeding despite risk"); + } + } + + if (!AquireData(usepage1, block, usepwd, password)) { + return returnToLuaWithError(L, "Failed to aquire data from card"); + } + + if (!DecodeT55xxBlock()) { + return returnToLuaWithError(L, "Failed to decode signal"); + } + + uint32_t blockData = 0; + if (GetT55xxBlockData(&blockData) == false) { + return returnToLuaWithError(L, "Failed to get actual data"); + } + + lua_pushunsigned(L, blockData); + return 1; +} + +// arg 1 = pwd +// arg 2 = use GB +static int l_T55xx_detect(lua_State *L) { + bool useGB = false, usepwd = false, isok; + uint32_t password; + uint32_t gb; + size_t size; + + //Check number of arguments + int n = lua_gettop(L); + + switch (n) { + case 2: { + const char *p_gb = luaL_checklstring(L, 2, &size); + if (size != 1) return returnToLuaWithError(L, "Wrong size of useGB, got %d , expected 1", (int) size); + sscanf(p_gb, "%u", &gb); + useGB = ( gb ) ? true : false; + printf("p_gb size %u | %c \n", size, useGB ? 'Y':'N'); + } + case 1: { + const char *p_pwd = luaL_checklstring(L, 1, &size); + if ( size == 0 ) { + usepwd = false; + } else { + + if (size != 8) return returnToLuaWithError(L, "Wrong size of pwd, got %d , expected 8", (int) size); + sscanf(p_pwd, "%08x", &password); + usepwd = true; + } + break; + } + default : + break; + } + + if (!useGB) { + + isok = AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password); + if ( isok == false ) { + // signal error by returning Nil, errorstring + lua_pushnil(L); + lua_pushstring(L, "Failed to aquire LF signal data"); + return 2; + } + } + + isok = tryDetectModulation(); + if ( isok == false ) { + // signal error by returning Nil, errorstring + lua_pushnil(L); + lua_pushstring(L, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); + return 2; + } + + lua_pushinteger(L, isok); + lua_pushstring(L, "Success"); + return 2; +} + /** * @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be * able to do "require('foobar')" if foobar.lua is within lualibs folder. @@ -747,13 +886,15 @@ int set_pm3_libraries(lua_State *L) { {"crc64_ecma182", l_crc64_ecma182}, {"sha1", l_sha1}, {"reveng_models", l_reveng_models}, - {"reveng_runmodel", l_reveng_RunModel}, + {"reveng_runmodel", l_reveng_runmodel}, {"hardnested", l_hardnested}, {"detect_prng", l_detect_prng}, // {"keygen.algoA", l_keygen_algoA}, // {"keygen.algoB", l_keygen_algoB}, // {"keygen.algoC", l_keygen_algoC}, {"keygen_algo_d", l_keygen_algoD}, + {"t55xx_readblock", l_T55xx_readblock}, + {"t55xx_detect", l_T55xx_detect}, {NULL, NULL} }; diff --git a/client/scripting.h b/client/scripting.h index ca405f43f..75a08605b 100644 --- a/client/scripting.h +++ b/client/scripting.h @@ -29,6 +29,7 @@ #include "cmdhfmfhard.h" #include "cmdhfmfu.h" #include "protocols.h" +#include "cmdlft55xx.h" // read t55xx etc #define LUA_LIBRARIES_DIRECTORY "lualibs/" #define LUA_SCRIPTS_DIRECTORY "scripts/"