X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/c0f15a05b36450c0182462d6d9d093c04c602b67..3c6542087e2a0f92f5c1024b812aac969253a764:/client/cmdlft55xx.c diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index bc30d7e3..28149eff 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:"); @@ -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; @@ -970,17 +1006,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 +1034,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 +1073,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 +1173,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,8 +1259,11 @@ 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}}; @@ -1549,15 +1596,105 @@ 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"},