X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/c0f15a05b36450c0182462d6d9d093c04c602b67..81b7e89434aad94a3cbddd5742341cd75e48efa5:/client/cmdlft55xx.c?ds=inline diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index bc30d7e3..8342bf08 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -42,13 +42,13 @@ void Set_t55xx_Config(t55xx_conf_block_t conf){ int usage_t55xx_config(){ PrintAndLog("Usage: lf t55xx config [d ] [i 1] [o ] [Q5]"); PrintAndLog("Options:"); - PrintAndLog(" h This help"); - PrintAndLog(" b <8|16|32|40|50|64|100|128> Set bitrate"); - PrintAndLog(" d Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A"); - PrintAndLog(" i [1] Invert data signal, defaults to normal"); - PrintAndLog(" o [offset] Set offset, where data should start decode in bitstream"); - PrintAndLog(" Q5 Set as Q5(T5555) chip instead of T55x7"); - PrintAndLog(" ST Set Sequence Terminator on"); + PrintAndLog(" h - This help"); + PrintAndLog(" b <8|16|32|40|50|64|100|128> - Set bitrate"); + PrintAndLog(" d - Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A"); + PrintAndLog(" i [1] - Invert data signal, defaults to normal"); + PrintAndLog(" o [offset] - Set offset, where data should start decode in bitstream"); + PrintAndLog(" Q5 - Set as Q5(T5555) chip instead of T55x7"); + PrintAndLog(" ST - Set Sequence Terminator on"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx config d FSK - FSK demodulation"); @@ -92,7 +92,7 @@ int usage_t55xx_write(){ int usage_t55xx_trace() { PrintAndLog("Usage: lf t55xx trace [1]"); PrintAndLog("Options:"); - PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx trace"); @@ -103,7 +103,7 @@ int usage_t55xx_trace() { int usage_t55xx_info() { PrintAndLog("Usage: lf t55xx info [1]"); PrintAndLog("Options:"); - PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx info"); @@ -150,7 +150,7 @@ int usage_t55xx_wakup(){ int usage_t55xx_bruteforce(){ PrintAndLog("This command uses A) bruteforce to scan a number range"); PrintAndLog(" B) a dictionary attack"); - PrintAndLog("Usage: lf t55xx bruteforce [i <*.dic>]"); + PrintAndLog("Usage: lf t55xx bruteforce [h] [i <*.dic>]"); PrintAndLog(" password must be 4 bytes (8 hex symbols)"); PrintAndLog("Options:"); PrintAndLog(" h - this help"); @@ -164,7 +164,22 @@ int usage_t55xx_bruteforce(){ PrintAndLog(""); return 0; } -int usage_t55xx_wipe(){ +int usage_t55xx_recoverpw(){ + PrintAndLog("This command uses a few tricks to try to recover mangled password"); + PrintAndLog("WARNING: this may brick non-password protected chips!"); + PrintAndLog("Usage: lf t55xx recoverpw [password]"); + PrintAndLog(" password must be 4 bytes (8 hex symbols)"); + PrintAndLog(" default password is 51243648, used by many cloners"); + PrintAndLog("Options:"); + PrintAndLog(" h - this help"); + PrintAndLog(" [password] - 4 byte hex value of password written by cloner"); + PrintAndLog(""); + PrintAndLog("Examples:"); + PrintAndLog(" lf t55xx recoverpw"); + PrintAndLog(" lf t55xx recoverpw 51243648"); + PrintAndLog(""); + return 0; +}int usage_t55xx_wipe(){ PrintAndLog("Usage: lf t55xx wipe [h] [Q5]"); PrintAndLog("This commands wipes a tag, fills blocks 1-7 with zeros and a default configuration block"); PrintAndLog("Options:"); @@ -180,8 +195,8 @@ static int CmdHelp(const char *Cmd); void printT5xxHeader(uint8_t page){ PrintAndLog("Reading Page %d:", page); - PrintAndLog("blk | hex data | binary"); - PrintAndLog("----+----------+---------------------------------"); + PrintAndLog("blk | hex data | binary | ascii"); + PrintAndLog("----+----------+---------------------------------+-------"); } int CmdT55xxSetConfig(const char *Cmd) { @@ -441,6 +456,14 @@ bool DecodeT5555TraceBlock() { return (bool) ASKDemod("64 0 1", FALSE, FALSE, 1); } +// sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf +static int SanityOfflineCheck( bool useGraphBuffer ){ + if ( !useGraphBuffer && offline) { + PrintAndLog("Your proxmark3 device is offline. Specify [1] to use graphbuffer data instead"); + return 0; + } + return 1; +} int CmdT55xxDetect(const char *Cmd){ bool errors = FALSE; @@ -473,15 +496,18 @@ int CmdT55xxDetect(const char *Cmd){ } if (errors) return usage_t55xx_detect(); + // sanity check. + if (!SanityOfflineCheck(useGB)) return 1; + if ( !useGB) { if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password) ) - return 0; + return 1; } if ( !tryDetectModulation() ) PrintAndLog("Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); - return 1; + return 0; } // detect configuration? @@ -521,6 +547,11 @@ bool tryDetectModulation(){ clk = GetAskClock("", FALSE, FALSE); if (clk>0) { tests[hits].ST = TRUE; + // "0 0 1 " == clock auto, invert false, maxError 1. + // false = no verbose + // false = no emSearch + // 1 = Ask/Man + // st = true if ( ASKDemod_ext("0 0 1", FALSE, FALSE, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_ASK; tests[hits].bitrate = bitRate; @@ -529,6 +560,11 @@ bool tryDetectModulation(){ ++hits; } tests[hits].ST = TRUE; + // "0 0 1 " == clock auto, invert true, maxError 1. + // false = no verbose + // false = no emSearch + // 1 = Ask/Man + // st = true if ( ASKDemod_ext("0 1 1", FALSE, FALSE, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_ASK; tests[hits].bitrate = bitRate; @@ -828,16 +864,18 @@ void printT55xxBlock(const char *blockNum){ bits[i - config.offset] = DemodBuffer[i]; blockData = PackBits(0, 32, bits); + uint8_t bytes[4] = {0}; + num_to_bytes(blockData, 4, bytes); - PrintAndLog(" %s | %08X | %s", blockNum, blockData, sprint_bin(bits,32)); + PrintAndLog(" %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}; - PrintAndLog("OFFSET | DATA | BINARY"); - PrintAndLog("----------------------------------------------------"); + PrintAndLog("OFFSET | DATA | BINARY | ASCII"); + PrintAndLog("-------+-------+------------------------------------+------"); int i,j = 0; for (; j < 64; ++j){ @@ -970,17 +1008,21 @@ int CmdT55xxReadTrace(const char *Cmd) { uint32_t password = 0; if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_trace(); - if (strlen(Cmd)==0) + if (strlen(Cmd)==0) { + // sanity check. + if (!SanityOfflineCheck(FALSE)) return 1; + if ( !AquireData( T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password ) ) - return 0; + return 1; + } if ( config.Q5 ){ - if (!DecodeT5555TraceBlock()) return 0; + if (!DecodeT5555TraceBlock()) return 1; } else { - if (!DecodeT55xxBlock()) return 0; + if (!DecodeT55xxBlock()) return 1; } - if ( !DemodBufferLen ) return 0; + if ( !DemodBufferLen ) return 1; RepaintGraphWindow(); uint8_t repeat = (config.offset > 5) ? 32 : 0; @@ -994,7 +1036,7 @@ int CmdT55xxReadTrace(const char *Cmd) { if (hdr != 0x1FF) { PrintAndLog("Invalid Q5 Trace data header (expected 0x1FF, found %X)", hdr); - return 0; + return 1; } t5555_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .icr = 0, .lotidc = '?', .lotid = 0, .wafer = 0, .dw =0}; @@ -1033,7 +1075,7 @@ int CmdT55xxReadTrace(const char *Cmd) { data.acl = PackBits(si, 8, DemodBuffer); si += 8; if ( data.acl != 0xE0 ) { PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. "); - return 0; + return 1; } data.mfc = PackBits(si, 8, DemodBuffer); si += 8; @@ -1133,9 +1175,13 @@ int CmdT55xxInfo(const char *Cmd){ if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_info(); - if (strlen(Cmd)==0) + if (strlen(Cmd)==0){ + // sanity check. + if (!SanityOfflineCheck(FALSE)) return 1; + if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password ) ) return 1; + } if (!DecodeT55xxBlock()) return 1; @@ -1215,21 +1261,26 @@ int CmdT55xxDump(const char *Cmd){ int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){ // arg0 bitmodes: - // bit0 = pwdmode - // bit1 = page to read from + // bit0 = pwdmode + // bit1 = page to read from + // arg1: which block to read + // arg2: password uint8_t arg0 = (page<<1) | pwdmode; UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}}; - clearCommandBuffer(); SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) { + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { PrintAndLog("command execution time out"); return 0; } - uint8_t got[12000]; - GetFromBigBuf(got,sizeof(got),0); - WaitForResponse(CMD_ACK,NULL); + //uint8_t got[12288]; + uint8_t got[7679]; + GetFromBigBuf(got, sizeof(got), 0); + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 8000) ) { + PrintAndLog("command execution time out"); + return 0; + } setGraphBuf(got, sizeof(got)); return 1; } @@ -1416,8 +1467,7 @@ int CmdT55xxBruteForce(const char *Cmd) { if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd+2, len); - FILE * f = fopen( filename , "r"); - + FILE * f = fopen( filename , "r"); if ( !f ) { PrintAndLog("File: %s: not found or locked.", filename); free(keyBlock); @@ -1444,7 +1494,10 @@ int CmdT55xxBruteForce(const char *Cmd) { if (!p) { PrintAndLog("Cannot allocate memory for defaultKeys"); free(keyBlock); - fclose(f); + if (f) { + fclose(f); + f = NULL; + } return 2; } keyBlock = p; @@ -1455,8 +1508,10 @@ int CmdT55xxBruteForce(const char *Cmd) { keycnt++; memset(buf, 0, sizeof(buf)); } - fclose(f); - + if (f) { + fclose(f); + f = NULL; + } if (keycnt == 0) { PrintAndLog("No keys found in file"); free(keyBlock); @@ -1467,7 +1522,13 @@ int CmdT55xxBruteForce(const char *Cmd) { // loop uint64_t testpwd = 0x00; for (uint16_t c = 0; c < keycnt; ++c ) { - + + if ( offline ) { + printf("Device offline\n"); + free(keyBlock); + return 2; + } + if (ukbhit()) { ch = getchar(); (void)ch; @@ -1479,8 +1540,7 @@ int CmdT55xxBruteForce(const char *Cmd) { testpwd = bytes_to_num(keyBlock + 4*c, 4); PrintAndLog("Testing %08X", testpwd); - - + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, TRUE, testpwd)) { PrintAndLog("Aquireing data from device failed. Quitting"); free(keyBlock); @@ -1488,7 +1548,6 @@ int CmdT55xxBruteForce(const char *Cmd) { } found = tryDetectModulation(); - if ( found ) { PrintAndLog("Found valid password: [%08X]", testpwd); free(keyBlock); @@ -1549,15 +1608,106 @@ int CmdT55xxBruteForce(const char *Cmd) { return 0; } +int tryOnePassword(uint32_t password) { + PrintAndLog("Trying password %08x", password); + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, TRUE, password)) { + PrintAndLog("Aquireing data from device failed. Quitting"); + return -1; + } + + if (tryDetectModulation()) + return 1; + else + return 0; +} + +int CmdT55xxRecoverPW(const char *Cmd) { + int bit = 0; + uint32_t orig_password = 0x0; + uint32_t curr_password = 0x0; + uint32_t prev_password = 0xffffffff; + uint32_t mask = 0x0; + int found = 0; + + char cmdp = param_getchar(Cmd, 0); + if (cmdp == 'h' || cmdp == 'H') return usage_t55xx_recoverpw(); + + orig_password = param_get32ex(Cmd, 0, 0x51243648, 16); //password used by handheld cloners + + // first try fliping each bit in the expected password + while ((found != 1) && (bit < 32)) { + curr_password = orig_password ^ ( 1 << bit ); + found = tryOnePassword(curr_password); + if (found == 1) + goto done; + else if (found == -1) + return 0; + bit++; + } + + // now try to use partial original password, since block 7 should have been completely + // erased during the write sequence and it is possible that only partial password has been + // written + // not sure from which end the bit bits are written, so try from both ends + // from low bit to high bit + bit = 0; + while ((found != 1) && (bit < 32)) { + mask += ( 1 << bit ); + curr_password = orig_password & mask; + // if updated mask didn't change the password, don't try it again + if (prev_password == curr_password) { + bit++; + continue; + } + found = tryOnePassword(curr_password); + if (found == 1) + goto done; + else if (found == -1) + return 0; + bit++; + prev_password=curr_password; + } + + // from high bit to low + bit = 0; + mask = 0xffffffff; + while ((found != 1) && (bit < 32)) { + mask -= ( 1 << bit ); + curr_password = orig_password & mask; + // if updated mask didn't change the password, don't try it again + if (prev_password == curr_password) { + bit++; + continue; + } + found = tryOnePassword(curr_password); + if (found == 1) + goto done; + else if (found == -1) + return 0; + bit++; + prev_password=curr_password; + } +done: + PrintAndLog(""); + + if (found == 1) + PrintAndLog("Found valid password: [%08x]", curr_password); + else + PrintAndLog("Password NOT found."); + + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"bruteforce",CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, + {"bruteforce", CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, {"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, {"info", CmdT55xxInfo, 1, "[1] Show T55x7 configuration data (page 0/ blk 0)"}, {"read", CmdT55xxReadBlock, 0, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, {"resetread", CmdResetRead, 0, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, + {"recoverpw", CmdT55xxRecoverPW, 0, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"}, {"special", special, 0, "Show block changes with 64 different offsets"}, {"trace", CmdT55xxReadTrace, 1, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"}, {"wakeup", CmdT55xxWakeUp, 0, "Send AOR wakeup command"},