X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/ab74872d40cf1f6b91344909e307ae788a3f8497..c631b1a216099f929a15193ec5841d980e8be8d0:/client/cmdlft55xx.c diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index f0a6fe94..1b005d96 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -6,28 +6,7 @@ //----------------------------------------------------------------------------- // Low frequency T55xx commands //----------------------------------------------------------------------------- - -#include <stdio.h> -#include <string.h> -#include <inttypes.h> -#include "proxmark3.h" -#include "ui.h" -#include "graph.h" -#include "cmdmain.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdlf.h" #include "cmdlft55xx.h" -#include "util.h" -#include "data.h" -#include "lfdemod.h" -#include "cmdhf14a.h" //for getTagInfo - -#define T55x7_CONFIGURATION_BLOCK 0x00 -#define T55x7_PAGE0 0x00 -#define T55x7_PAGE1 0x01 -#define T55x7_PWD 0x00000010 -#define REGULAR_READ_MODE_BLOCK 0xFF // Default configuration t55xx_conf_block_t config = { .modulation = DEMOD_ASK, .inverted = FALSE, .offset = 0x00, .block0 = 0x00, .Q5 = FALSE }; @@ -42,13 +21,13 @@ void Set_t55xx_Config(t55xx_conf_block_t conf){ int usage_t55xx_config(){ PrintAndLog("Usage: lf t55xx config [d <demodulation>] [i 1] [o <offset>] [Q5]"); PrintAndLog("Options:"); - PrintAndLog(" h This help"); - PrintAndLog(" b <8|16|32|40|50|64|100|128> Set bitrate"); - PrintAndLog(" d <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NRZ|BI|BIa> 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 <FSK|FSK1|FSK1a|FSK2|FSK2a|ASK|PSK1|PSK2|NRZ|BI|BIa> - 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 +71,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 +82,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 +129,8 @@ 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 <start password> <end password> [i <*.dic>]"); + PrintAndLog("press 'enter' to cancel the command"); + PrintAndLog("Usage: lf t55xx bruteforce [h] <start password> <end password> [i <*.dic>]"); PrintAndLog(" password must be 4 bytes (8 hex symbols)"); PrintAndLog("Options:"); PrintAndLog(" h - this help"); @@ -166,13 +146,14 @@ int usage_t55xx_bruteforce(){ } int usage_t55xx_recoverpw(){ PrintAndLog("This command uses a few tricks to try to recover mangled password"); + PrintAndLog("press 'enter' to cancel the command"); 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(" [password] - 4 byte hex value of password written by cloner"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx recoverpw"); @@ -195,8 +176,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) { @@ -547,6 +528,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; @@ -555,6 +541,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; @@ -664,13 +655,46 @@ bool tryDetectModulation(){ return TRUE; } + bool retval = FALSE; if ( hits > 1) { PrintAndLog("Found [%d] possible matches for modulation.",hits); for(int i=0; i<hits; ++i){ - PrintAndLog("--[%d]---------------", i+1); + retval = testKnownConfigBlock(tests[i].block0); + if ( retval ) { + PrintAndLog("--[%d]--------------- << selected this", i+1); + config.modulation = tests[i].modulation; + config.bitrate = tests[i].bitrate; + config.inverted = tests[i].inverted; + config.offset = tests[i].offset; + config.block0 = tests[i].block0; + config.Q5 = tests[i].Q5; + config.ST = tests[i].ST; + } else { + PrintAndLog("--[%d]---------------", i+1); + } printConfiguration( tests[i] ); } } + return retval; +} + +bool testKnownConfigBlock(uint32_t block0) { + switch(block0){ + case T55X7_DEFAULT_CONFIG_BLOCK: + case T55X7_RAW_CONFIG_BLOCK: + case T55X7_EM_UNIQUE_CONFIG_BLOCK: + case T55X7_FDXB_CONFIG_BLOCK: + case T55X7_HID_26_CONFIG_BLOCK: + case T55X7_PYRAMID_CONFIG_BLOCK: + case T55X7_INDALA_64_CONFIG_BLOCK: + case T55X7_INDALA_224_CONFIG_BLOCK: + case T55X7_GUARDPROXII_CONFIG_BLOCK: + case T55X7_VIKING_CONFIG_BLOCK: + case T55X7_NORALYS_CONFIG_BLOCK: + case T55X7_IOPROX_CONFIG_BLOCK: + case T55X7_PRESCO_CONFIG_BLOCK: + return TRUE; + } return FALSE; } @@ -854,16 +878,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){ @@ -983,7 +1009,7 @@ int CmdT55xxWriteBlock(const char *Cmd) { } clearCommandBuffer(); SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){ + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)){ PrintAndLog("Error occurred, device did not ACK write operation. (May be due to old firmware)"); return 0; } @@ -1249,21 +1275,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; } @@ -1379,10 +1410,9 @@ void t55x7_create_config_block( int tagtype ){ int CmdResetRead(const char *Cmd) { UsbCommand c = {CMD_T55XX_RESET_READ, {0,0,0}}; - clearCommandBuffer(); SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) { + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { PrintAndLog("command execution time out"); return 0; } @@ -1406,11 +1436,10 @@ int CmdT55xxWipe(const char *Cmd) { // With a pwd should work even if pwd bit not set PrintAndLog("\nBeginning Wipe of a T55xx tag (assuming the tag is not password protected)\n"); - if ( Q5 ){ + if ( Q5 ) snprintf(ptrData,sizeof(writeData),"b 0 d 6001F004 p 0"); - } else { + else snprintf(ptrData,sizeof(writeData),"b 0 d 000880E0 p 0"); - } if (!CmdT55xxWriteBlock(ptrData)) PrintAndLog("Error writing blk 0"); @@ -1425,23 +1454,34 @@ int CmdT55xxWipe(const char *Cmd) { return 0; } +bool IsCancelled(void) { + if (ukbhit()) { + int ch = getchar(); + (void)ch; + printf("\naborted via keyboard!\n"); + return TRUE; + } + return FALSE; +} + int CmdT55xxBruteForce(const char *Cmd) { // load a default pwd file. - char buf[9]; + char line[9]; char filename[FILE_PATH_SIZE]={0}; int keycnt = 0; - int ch; uint8_t stKeyBlock = 20; uint8_t *keyBlock = NULL, *p = NULL; uint32_t start_password = 0x00000000; //start password uint32_t end_password = 0xFFFFFFFF; //end password bool found = false; + memset(line, 0, sizeof(line)); + char cmdp = param_getchar(Cmd, 0); if (cmdp == 'h' || cmdp == 'H') return usage_t55xx_bruteforce(); - keyBlock = calloc(stKeyBlock, 6); + keyBlock = calloc(stKeyBlock, 4); if (keyBlock == NULL) return 1; if (cmdp == 'i' || cmdp == 'I') { @@ -1450,46 +1490,52 @@ 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); return 1; } - - while( fgets(buf, sizeof(buf), f) ){ - if (strlen(buf) < 8 || buf[7] == '\n') continue; - while (fgetc(f) != '\n' && !feof(f)) ; //goto next line - + while( fgets(line, sizeof(line), f) ){ + if (strlen(line) < 8 || line[7] == '\n') continue; + + //goto next line + while (fgetc(f) != '\n' && !feof(f)) ; + //The line start with # is comment, skip - if( buf[0]=='#' ) continue; + if( line[0]=='#' ) continue; - if (!isxdigit(buf[0])){ - PrintAndLog("File content error. '%s' must include 8 HEX symbols", buf); + if (!isxdigit(line[0])) { + PrintAndLog("File content error. '%s' must include 8 HEX symbols", line); continue; } - buf[8] = 0; - + line[8] = 0; + + // realloc keyblock array size. if ( stKeyBlock - keycnt < 2) { - p = realloc(keyBlock, 6*(stKeyBlock+=10)); + p = realloc(keyBlock, 4 * (stKeyBlock += 10)); if (!p) { PrintAndLog("Cannot allocate memory for defaultKeys"); free(keyBlock); - fclose(f); + if (f) + fclose(f); return 2; } keyBlock = p; } + // clear mem memset(keyBlock + 4 * keycnt, 0, 4); - num_to_bytes(strtoll(buf, NULL, 16), 4, keyBlock + 4*keycnt); - PrintAndLog("chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4*keycnt, 4)); - keycnt++; - memset(buf, 0, sizeof(buf)); + + num_to_bytes( strtoll(line, NULL, 16), 4, keyBlock + 4*keycnt); + + PrintAndLog("chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) ); + keycnt++; + memset(line, 0, sizeof(line)); } - fclose(f); + if (f) + fclose(f); if (keycnt == 0) { PrintAndLog("No keys found in file"); @@ -1501,11 +1547,14 @@ int CmdT55xxBruteForce(const char *Cmd) { // loop uint64_t testpwd = 0x00; for (uint16_t c = 0; c < keycnt; ++c ) { - - if (ukbhit()) { - ch = getchar(); - (void)ch; - printf("\naborted via keyboard!\n"); + + if ( offline ) { + printf("Device offline\n"); + free(keyBlock); + return 2; + } + + if (IsCancelled()) { free(keyBlock); return 0; } @@ -1513,20 +1562,18 @@ 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"); + PrintAndLog("Acquire data from device failed. Quitting"); free(keyBlock); return 0; } found = tryDetectModulation(); - if ( found ) { PrintAndLog("Found valid password: [%08X]", testpwd); - free(keyBlock); - return 0; + //free(keyBlock); + //return 0; } } PrintAndLog("Password NOT found."); @@ -1553,16 +1600,14 @@ int CmdT55xxBruteForce(const char *Cmd) { printf("."); fflush(stdout); - if (ukbhit()) { - ch = getchar(); - (void)ch; - printf("\naborted via keyboard!\n"); + + if (IsCancelled()) { free(keyBlock); return 0; } if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, TRUE, i)) { - PrintAndLog("Aquireing data from device failed. Quitting"); + PrintAndLog("Acquire data from device failed. Quitting"); free(keyBlock); return 0; } @@ -1583,17 +1628,17 @@ int CmdT55xxBruteForce(const char *Cmd) { return 0; } -int tryOnePassword(uint32_t password) -{ +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"); + PrintAndLog("Acquire data from device failed. Quitting"); return -1; } if (tryDetectModulation()) return 1; - else return 0; + else + return 0; } int CmdT55xxRecoverPW(const char *Cmd) { @@ -1603,21 +1648,19 @@ int CmdT55xxRecoverPW(const char *Cmd) { 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)) { + while (bit < 32) { curr_password = orig_password ^ ( 1 << bit ); found = tryOnePassword(curr_password); - if (found == 1) - goto done; - else if (found == -1) - return 0; + if (found == -1) return 0; bit++; + + if (IsCancelled()) return 0; } // now try to use partial original password, since block 7 should have been completely @@ -1626,7 +1669,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { // 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)) { + while (bit < 32) { mask += ( 1 << bit ); curr_password = orig_password & mask; // if updated mask didn't change the password, don't try it again @@ -1635,18 +1678,17 @@ int CmdT55xxRecoverPW(const char *Cmd) { continue; } found = tryOnePassword(curr_password); - if (found == 1) - goto done; - else if (found == -1) - return 0; + if (found == -1) return 0; bit++; - prev_password=curr_password; + prev_password = curr_password; + + if (IsCancelled()) return 0; } // from high bit to low bit = 0; mask = 0xffffffff; - while ((found != 1) && (bit < 32)) { + while (bit < 32) { mask -= ( 1 << bit ); curr_password = orig_password & mask; // if updated mask didn't change the password, don't try it again @@ -1655,14 +1697,14 @@ int CmdT55xxRecoverPW(const char *Cmd) { continue; } found = tryOnePassword(curr_password); - if (found == 1) - goto done; - else if (found == -1) + if (found == -1) return 0; bit++; - prev_password=curr_password; + prev_password = curr_password; + + if (IsCancelled()) return 0; } -done: + PrintAndLog(""); if (found == 1)