]> cvs.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdlft55xx.c
CHG: this timing should be quite good. needs to be verified.
[proxmark3-svn] / client / cmdlft55xx.c
index 2efe0c22d07a011e0cc2ce7ef9a12357f9ae023b..f8865c8da89898488265e90f382024de18f0d452 100644 (file)
@@ -42,13 +42,13 @@ void Set_t55xx_Config(t55xx_conf_block_t conf){
 int usage_t55xx_config(){\r
        PrintAndLog("Usage: lf t55xx config [d <demodulation>] [i 1] [o <offset>] [Q5]");\r
        PrintAndLog("Options:");\r
-       PrintAndLog("       h                        This help");\r
-       PrintAndLog("       b <8|16|32|40|50|64|100|128>     Set bitrate");\r
-       PrintAndLog("       d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NRZ|BI|BIa>  Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A");\r
-       PrintAndLog("       i [1]                            Invert data signal, defaults to normal");\r
-       PrintAndLog("       o [offset]                       Set offset, where data should start decode in bitstream");\r
-       PrintAndLog("       Q5                            Set as Q5(T5555) chip instead of T55x7");\r
-       PrintAndLog("       ST                            Set Sequence Terminator on");\r
+       PrintAndLog("       h                                - This help");\r
+       PrintAndLog("       b <8|16|32|40|50|64|100|128>     Set bitrate");\r
+       PrintAndLog("       d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NRZ|BI|BIa>  Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A");\r
+       PrintAndLog("       i [1]                            Invert data signal, defaults to normal");\r
+       PrintAndLog("       o [offset]                       Set offset, where data should start decode in bitstream");\r
+       PrintAndLog("       Q5                               - Set as Q5(T5555) chip instead of T55x7");\r
+       PrintAndLog("       ST                               - Set Sequence Terminator on");\r
        PrintAndLog("");\r
        PrintAndLog("Examples:");\r
        PrintAndLog("      lf t55xx config d FSK          - FSK demodulation");\r
@@ -92,7 +92,7 @@ int usage_t55xx_write(){
 int usage_t55xx_trace() {\r
        PrintAndLog("Usage:  lf t55xx trace [1]");\r
        PrintAndLog("Options:");\r
-       PrintAndLog("     [graph buffer data]  - if set, use Graphbuffer otherwise read data from tag.");\r
+       PrintAndLog("     1             - if set, use Graphbuffer otherwise read data from tag.");\r
        PrintAndLog("");\r
        PrintAndLog("Examples:");\r
        PrintAndLog("      lf t55xx trace");\r
@@ -103,7 +103,7 @@ int usage_t55xx_trace() {
 int usage_t55xx_info() {\r
        PrintAndLog("Usage:  lf t55xx info [1]");\r
        PrintAndLog("Options:");\r
-       PrintAndLog("     [graph buffer data]  - if set, use Graphbuffer otherwise read data from tag.");\r
+       PrintAndLog("     1             - if set, use Graphbuffer otherwise read data from tag.");\r
        PrintAndLog("");\r
        PrintAndLog("Examples:");\r
        PrintAndLog("      lf t55xx info");\r
@@ -150,7 +150,7 @@ int usage_t55xx_wakup(){
 int usage_t55xx_bruteforce(){\r
        PrintAndLog("This command uses A) bruteforce to scan a number range");\r
        PrintAndLog("                  B) a dictionary attack");\r
-    PrintAndLog("Usage: lf t55xx bruteforce <start password> <end password> [i <*.dic>]");\r
+    PrintAndLog("Usage: lf t55xx bruteforce [h] <start password> <end password> [i <*.dic>]");\r
     PrintAndLog("       password must be 4 bytes (8 hex symbols)");\r
        PrintAndLog("Options:");\r
        PrintAndLog("     h                     - this help");\r
@@ -164,7 +164,22 @@ int usage_t55xx_bruteforce(){
     PrintAndLog("");\r
     return 0;\r
 }\r
-int usage_t55xx_wipe(){\r
+int usage_t55xx_recoverpw(){\r
+       PrintAndLog("This command uses a few tricks to try to recover mangled password");\r
+       PrintAndLog("WARNING: this may brick non-password protected chips!");\r
+       PrintAndLog("Usage: lf t55xx recoverpw [password]");\r
+       PrintAndLog("       password must be 4 bytes (8 hex symbols)");\r
+       PrintAndLog("       default password is 51243648, used by many cloners");\r
+       PrintAndLog("Options:");\r
+       PrintAndLog("     h           - this help");\r
+       PrintAndLog("     [password]  - 4 byte hex value of password written by cloner");\r
+       PrintAndLog("");\r
+       PrintAndLog("Examples:");\r
+       PrintAndLog("       lf t55xx recoverpw");\r
+       PrintAndLog("       lf t55xx recoverpw 51243648");\r
+       PrintAndLog("");\r
+       return 0;\r
+}int usage_t55xx_wipe(){\r
        PrintAndLog("Usage:  lf t55xx wipe [h] [Q5]");\r
        PrintAndLog("This commands wipes a tag, fills blocks 1-7 with zeros and a default configuration block");\r
        PrintAndLog("Options:");\r
@@ -441,6 +456,14 @@ bool DecodeT5555TraceBlock() {
        return (bool) ASKDemod("64 0 1", FALSE, FALSE, 1);\r
 }\r
 \r
+// sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf\r
+static int SanityOfflineCheck( bool useGraphBuffer ){\r
+       if ( !useGraphBuffer && offline) {\r
+               PrintAndLog("Your proxmark3 device is offline. Specify [1] to use graphbuffer data instead");\r
+               return 0;\r
+       }\r
+       return 1;\r
+}\r
 \r
 int CmdT55xxDetect(const char *Cmd){\r
        bool errors = FALSE;\r
@@ -473,15 +496,18 @@ int CmdT55xxDetect(const char *Cmd){
        }\r
        if (errors) return usage_t55xx_detect();\r
        \r
+       // sanity check.\r
+       if (!SanityOfflineCheck(useGB)) return 1;\r
+       \r
        if ( !useGB) {\r
                if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password) )\r
-                       return 0;\r
+                       return 1;\r
        }\r
        \r
        if ( !tryDetectModulation() )\r
                PrintAndLog("Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'");\r
 \r
-       return 1;\r
+       return 0;\r
 }\r
 \r
 // detect configuration?\r
@@ -970,17 +996,21 @@ int CmdT55xxReadTrace(const char *Cmd) {
        uint32_t password = 0;  \r
        if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_trace();\r
 \r
-       if (strlen(Cmd)==0)\r
+       if (strlen(Cmd)==0) {\r
+               // sanity check.\r
+               if (!SanityOfflineCheck(FALSE)) return 1;\r
+\r
                if ( !AquireData( T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password ) )\r
-                       return 0;\r
+                       return 1;\r
+       }\r
 \r
        if ( config.Q5 ){\r
-               if (!DecodeT5555TraceBlock()) return 0;\r
+               if (!DecodeT5555TraceBlock()) return 1;\r
        } else {\r
-               if (!DecodeT55xxBlock()) return 0;\r
+               if (!DecodeT55xxBlock()) return 1;\r
        }\r
        \r
-       if ( !DemodBufferLen ) return 0;\r
+       if ( !DemodBufferLen ) return 1;\r
        \r
        RepaintGraphWindow();\r
        uint8_t repeat = (config.offset > 5) ? 32 : 0;\r
@@ -994,7 +1024,7 @@ int CmdT55xxReadTrace(const char *Cmd) {
     \r
                if (hdr != 0x1FF) {\r
                  PrintAndLog("Invalid Q5 Trace data header (expected 0x1FF, found %X)", hdr);\r
-                 return 0;\r
+                 return 1;\r
                }\r
     \r
                t5555_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .icr = 0, .lotidc = '?', .lotid = 0, .wafer = 0, .dw =0};\r
@@ -1033,7 +1063,7 @@ int CmdT55xxReadTrace(const char *Cmd) {
                data.acl = PackBits(si, 8,  DemodBuffer); si += 8;\r
                if ( data.acl != 0xE0 ) {\r
                        PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. ");\r
-                       return 0;\r
+                       return 1;\r
                }\r
 \r
                data.mfc     = PackBits(si, 8,  DemodBuffer); si += 8;\r
@@ -1133,9 +1163,13 @@ int CmdT55xxInfo(const char *Cmd){
 \r
        if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_info();\r
        \r
-       if (strlen(Cmd)==0)\r
+       if (strlen(Cmd)==0){\r
+                               // sanity check.\r
+               if (!SanityOfflineCheck(FALSE)) return 1;\r
+               \r
                if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password ) )\r
                        return 1;\r
+       }\r
 \r
        if (!DecodeT55xxBlock()) return 1;\r
 \r
@@ -1397,21 +1431,18 @@ int CmdT55xxBruteForce(const char *Cmd) {
        char buf[9];\r
        char filename[FILE_PATH_SIZE]={0};\r
        int     keycnt = 0;\r
-       int c;\r
+       int ch;\r
        uint8_t stKeyBlock = 20;\r
        uint8_t *keyBlock = NULL, *p = NULL;\r
-       keyBlock = calloc(stKeyBlock, 6);\r
-       if (keyBlock == NULL) return 1;\r
-       \r
     uint32_t start_password = 0x00000000; //start password\r
     uint32_t end_password   = 0xFFFFFFFF; //end   password\r
     bool found = false;\r
 \r
     char cmdp = param_getchar(Cmd, 0);\r
-    if (cmdp == 'h' || cmdp == 'H') {\r
-               free(keyBlock);\r
-               return usage_t55xx_bruteforce();\r
-       }\r
+       if (cmdp == 'h' || cmdp == 'H') return usage_t55xx_bruteforce();\r
+\r
+       keyBlock = calloc(stKeyBlock, 6);\r
+       if (keyBlock == NULL) return 1;\r
 \r
        if (cmdp == 'i' || cmdp == 'I') {\r
        \r
@@ -1472,8 +1503,8 @@ int CmdT55xxBruteForce(const char *Cmd) {
                for (uint16_t c = 0; c < keycnt; ++c ) {\r
        \r
                        if (ukbhit()) {\r
-                               c = getchar();\r
-                               (void)c;\r
+                               ch = getchar();\r
+                               (void)ch;\r
                                printf("\naborted via keyboard!\n");\r
                                free(keyBlock);\r
                                return 0;\r
@@ -1523,8 +1554,8 @@ int CmdT55xxBruteForce(const char *Cmd) {
                printf(".");\r
                fflush(stdout);\r
                if (ukbhit()) {\r
-                       c = getchar();\r
-                       (void)c;\r
+                       ch = getchar();\r
+                       (void)ch;\r
                        printf("\naborted via keyboard!\n");\r
                        free(keyBlock);\r
                        return 0;\r
@@ -1552,15 +1583,106 @@ int CmdT55xxBruteForce(const char *Cmd) {
     return 0;\r
 }\r
 \r
+int tryOnePassword(uint32_t password)\r
+{\r
+       PrintAndLog("Trying password %08x", password);\r
+       if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, TRUE, password)) {\r
+               PrintAndLog("Aquireing data from device failed. Quitting");\r
+               return -1;\r
+       }\r
+\r
+       if (tryDetectModulation())\r
+               return 1;\r
+       else return 0;\r
+}\r
+\r
+int CmdT55xxRecoverPW(const char *Cmd) {\r
+       int bit = 0;\r
+       uint32_t orig_password = 0x0;\r
+       uint32_t curr_password = 0x0;\r
+       uint32_t prev_password = 0xffffffff;\r
+       uint32_t mask = 0x0;\r
+       int found = 0;\r
+\r
+       char cmdp = param_getchar(Cmd, 0);\r
+       if (cmdp == 'h' || cmdp == 'H') return usage_t55xx_recoverpw();\r
+\r
+       orig_password = param_get32ex(Cmd, 0, 0x51243648, 16); //password used by handheld cloners\r
+\r
+       // first try fliping each bit in the expected password\r
+       while ((found != 1) && (bit < 32)) {\r
+               curr_password = orig_password ^ ( 1 << bit );\r
+               found = tryOnePassword(curr_password);\r
+               if (found == 1)\r
+                       goto done;\r
+               else if (found == -1)\r
+                       return 0;\r
+               bit++;\r
+       }\r
+\r
+       // now try to use partial original password, since block 7 should have been completely\r
+       // erased during the write sequence and it is possible that only partial password has been\r
+       // written\r
+       // not sure from which end the bit bits are written, so try from both ends \r
+       // from low bit to high bit\r
+       bit = 0;\r
+       while ((found != 1) && (bit < 32)) {\r
+               mask += ( 1 << bit );\r
+               curr_password = orig_password & mask;\r
+               // if updated mask didn't change the password, don't try it again\r
+               if (prev_password == curr_password) {\r
+                       bit++;\r
+                       continue;\r
+               }\r
+               found = tryOnePassword(curr_password);\r
+               if (found == 1)\r
+                       goto done;\r
+               else if (found == -1)\r
+                       return 0;\r
+               bit++;\r
+               prev_password=curr_password;\r
+       }\r
+\r
+       // from high bit to low\r
+       bit = 0;\r
+       mask = 0xffffffff;\r
+       while ((found != 1) && (bit < 32)) {\r
+               mask -= ( 1 << bit );\r
+               curr_password = orig_password & mask;\r
+               // if updated mask didn't change the password, don't try it again\r
+               if (prev_password == curr_password) {\r
+                       bit++;\r
+                       continue;\r
+               }\r
+               found = tryOnePassword(curr_password);\r
+               if (found == 1)\r
+                       goto done;\r
+               else if (found == -1)\r
+                       return 0;\r
+               bit++;\r
+               prev_password=curr_password;\r
+       }\r
+done:\r
+       PrintAndLog("");\r
+\r
+       if (found == 1)\r
+               PrintAndLog("Found valid password: [%08x]", curr_password);\r
+       else\r
+               PrintAndLog("Password NOT found.");\r
+\r
+       return 0;\r
+}\r
+\r
 static command_t CommandTable[] = {\r
        {"help",                CmdHelp,           1, "This help"},\r
-       {"bruteforce",CmdT55xxBruteForce,0, "<start password> <end password> [i <*.dic>] Simple bruteforce attack to find password"},\r
+       {"bruteforce",  CmdT55xxBruteForce,0, "<start password> <end password> [i <*.dic>] Simple bruteforce attack to find password"},\r
        {"config",              CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},\r
        {"detect",              CmdT55xxDetect,    1, "[1] Try detecting the tag modulation from reading the configuration block."},\r
        {"dump",                CmdT55xxDump,      0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"},\r
        {"info",                CmdT55xxInfo,      1, "[1] Show T55x7 configuration data (page 0/ blk 0)"},\r
        {"read",                CmdT55xxReadBlock, 0, "b <block> p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"},\r
        {"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)"},\r
+       {"recoverpw",   CmdT55xxRecoverPW, 0, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"},\r
        {"special",             special,           0, "Show block changes with 64 different offsets"},  \r
        {"trace",               CmdT55xxReadTrace, 1, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"},\r
        {"wakeup",              CmdT55xxWakeUp,    0, "Send AOR wakeup command"},\r
Impressum, Datenschutz