X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/a126332a7b3c85274a9988f8a6994fba930b5f52..e869d598719e492ca4bda9d8d2a5f80b7ff9d919:/client/cmdlft55xx.c

diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c
index d864c9ed..75c1a1f8 100644
--- a/client/cmdlft55xx.c
+++ b/client/cmdlft55xx.c
@@ -134,7 +134,7 @@ int usage_t55xx_detect(){
 	PrintAndLog("Examples:");
 	PrintAndLog("      lf t55xx detect");
 	PrintAndLog("      lf t55xx detect 1");
-	PrintAndLog("      lf t55xx detect 11223344");
+	PrintAndLog("      lf t55xx detect p 11223344");
 	PrintAndLog("");
 	return 0;
 }
@@ -149,6 +149,23 @@ int usage_t55xx_wakup(){
     PrintAndLog("      lf t55xx wakeup p 11223344  - send wakeup password");
 	return 0;
 }
+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("       password must be 4 bytes (8 hex symbols)");
+	PrintAndLog("Options:");
+	PrintAndLog("     h			- this help");
+	PrintAndLog("     <start_pwd> - 4 byte hex value to start pwd search at");
+	PrintAndLog("     <end_pwd>   - 4 byte hex value to end pwd search at");
+    PrintAndLog("     i <*.dic>	- loads a default keys dictionary file <*.dic>");
+    PrintAndLog("");
+    PrintAndLog("Examples:");
+    PrintAndLog("       lf t55xx bruteforce aaaaaaaa bbbbbbbb");
+	PrintAndLog("       lf t55xx bruteforce i default_pwd.dic");
+    PrintAndLog("");
+    return 0;
+}
 
 static int CmdHelp(const char *Cmd);
 
@@ -166,7 +183,6 @@ int CmdT55xxSetConfig(const char *Cmd) {
 	uint8_t bitRate = 0;
 	uint8_t rates[9] = {8,16,32,40,50,64,100,128,0};
 	uint8_t cmdp = 0;
-	config.Q5 = FALSE;
 	bool errors = FALSE;
 	while(param_getchar(Cmd, cmdp) != 0x00 && !errors)
 	{
@@ -370,17 +386,23 @@ bool DecodeT55xxBlock(){
 			break;
 		case DEMOD_PSK1:
 			// skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
+			save_restoreGB(1);
 			CmdLtrim("160");
 			snprintf(cmdStr, sizeof(buf),"%d %d 6", bitRate[config.bitrate], config.inverted );
 			ans = PSKDemod(cmdStr, FALSE);
+			//undo trim samples
+			save_restoreGB(0);
 			break;
 		case DEMOD_PSK2: //inverted won't affect this
 		case DEMOD_PSK3: //not fully implemented
 			// skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
+			save_restoreGB(1);
 			CmdLtrim("160");
 			snprintf(cmdStr, sizeof(buf),"%d 0 6", bitRate[config.bitrate] );
 			ans = PSKDemod(cmdStr, FALSE);
 			psk1TOpsk2(DemodBuffer, DemodBufferLen);
+			//undo trim samples
+			save_restoreGB(0);
 			break;
 		case DEMOD_NRZ:
 			snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted );
@@ -398,7 +420,6 @@ bool DecodeT55xxBlock(){
 }
 
 int CmdT55xxDetect(const char *Cmd){
-
 	bool errors = FALSE;
 	bool useGB = FALSE;
 	bool usepwd = FALSE;
@@ -446,7 +467,6 @@ bool tryDetectModulation(){
 	t55xx_conf_block_t tests[15];
 	int bitRate=0;
 	uint8_t fc1 = 0, fc2 = 0, clk=0;
-	save_restoreGB(1);
 	
 	if (GetFskClock("", FALSE, FALSE)){ 
 		fskClocks(&fc1, &fc2, &clk, FALSE);
@@ -467,7 +487,6 @@ bool tryDetectModulation(){
 				tests[hits].modulation = DEMOD_FSK1;
 			else if (fc1 == 10 && fc2 == 8)
 				tests[hits].modulation = DEMOD_FSK2a;
-
 			tests[hits].bitrate = bitRate;
 			tests[hits].inverted = TRUE;
 			tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
@@ -506,7 +525,7 @@ bool tryDetectModulation(){
 			}
 		}
 		//undo trim from ask
-		save_restoreGB(0);
+		//save_restoreGB(0);
 		clk = GetNrzClock("", FALSE, FALSE);
 		if (clk>0) {
 			if ( NRZrawDemod("0 0 1", FALSE)  && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {
@@ -526,9 +545,9 @@ bool tryDetectModulation(){
 			}
 		}
 		
-		//undo trim from nrz
-		save_restoreGB(0);
+		// allow undo
 		// skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
+		save_restoreGB(1);
 		CmdLtrim("160");
 		clk = GetPskClock("", FALSE, FALSE);
 		if (clk>0) {
@@ -569,14 +588,16 @@ bool tryDetectModulation(){
 				}
 			} // inverse waves does not affect this demod
 		}
+		//undo trim samples
+		save_restoreGB(0);
 	}		
-	save_restoreGB(0);	
 	if ( hits == 1) {
 		config.modulation = tests[0].modulation;
 		config.bitrate = tests[0].bitrate;
 		config.inverted = tests[0].inverted;
 		config.offset = tests[0].offset;
 		config.block0 = tests[0].block0;
+		config.Q5 = tests[0].Q5;
 		printConfiguration( config );
 		return TRUE;
 	}
@@ -652,6 +673,15 @@ bool testQ5Modulation(uint8_t	mode, uint8_t	modread){
 	return FALSE;
 }
 
+int convertQ5bitRate(uint8_t bitRateRead) {
+	uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128};
+	for (int i=0; i<8; i++)
+		if (expected[i] == bitRateRead)
+			return i;
+
+	return -1;
+}
+
 bool testQ5(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t	clk){
 
 	if ( DemodBufferLen < 64 ) return FALSE;
@@ -663,12 +693,12 @@ bool testQ5(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t	clk){
 		uint8_t safer     = PackBits(si, 4, DemodBuffer); si += 4;     //master key
 		uint8_t resv      = PackBits(si, 8, DemodBuffer); si += 8;
 		// 2nibble must be zeroed.
-		if (safer != 0x6) continue;
+		if (safer != 0x6 && safer != 0x9) continue;
 		if ( resv > 0x00) continue;
 		//uint8_t	pageSel   = PackBits(si, 1, DemodBuffer); si += 1;
 		//uint8_t fastWrite = PackBits(si, 1, DemodBuffer); si += 1;
 		si += 1+1;
-		int bitRate       = PackBits(si, 5, DemodBuffer)*2 + 2; si += 5;     //bit rate
+		int bitRate       = PackBits(si, 6, DemodBuffer)*2 + 2; si += 6;     //bit rate
 		if (bitRate > 128 || bitRate < 8) continue;
 
 		//uint8_t AOR       = PackBits(si, 1, DemodBuffer); si += 1;   
@@ -683,7 +713,8 @@ bool testQ5(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t	clk){
 		//test modulation
 		if (!testQ5Modulation(mode, modread)) continue;
 		if (bitRate != clk) continue;
-		*fndBitRate = bitRate;
+		*fndBitRate = convertQ5bitRate(bitRate);
+		if (*fndBitRate < 0) continue;
 		*offset = idx;
 
 		return TRUE;
@@ -996,8 +1027,14 @@ int CmdT55xxInfo(const char *Cmd){
 
 	if (!DecodeT55xxBlock()) return 1;
 
+	// too little space to start with
 	if ( DemodBufferLen < 32) return 1;
 
+	// 
+	PrintAndLog("Offset+32 ==%d\n DemodLen == %d", config.offset + 32,DemodBufferLen );
+		
+
+	
 	uint8_t si = config.offset;
 	uint32_t bl0      = PackBits(si, 32, DemodBuffer);
 	
@@ -1092,35 +1129,16 @@ char * GetBitRateStr(uint32_t id){
 
 	char *retStr = buf;
 		switch (id){
-		case 0: 
-			snprintf(retStr,sizeof(buf),"%d - RF/8",id);
-			break;
-		case 1:
-			snprintf(retStr,sizeof(buf),"%d - RF/16",id);
-			break;
-		case 2:		
-			snprintf(retStr,sizeof(buf),"%d - RF/32",id);
-			break;
-		case 3:
-			snprintf(retStr,sizeof(buf),"%d - RF/40",id);
-			break;
-		case 4:
-			snprintf(retStr,sizeof(buf),"%d - RF/50",id);
-			break;
-		case 5:
-			snprintf(retStr,sizeof(buf),"%d - RF/64",id);
-			break;
-		case 6:
-			snprintf(retStr,sizeof(buf),"%d - RF/100",id);
-			break;
-		case 7:
-			snprintf(retStr,sizeof(buf),"%d - RF/128",id);
-			break;
-		default:
-			snprintf(retStr,sizeof(buf),"%d - (Unknown)",id);
-			break;
+		case 0:   snprintf(retStr,sizeof(buf),"%d - RF/8",id);   break;
+		case 1:   snprintf(retStr,sizeof(buf),"%d - RF/16",id);  break;
+		case 2:   snprintf(retStr,sizeof(buf),"%d - RF/32",id);  break;
+		case 3:   snprintf(retStr,sizeof(buf),"%d - RF/40",id);  break;
+		case 4:   snprintf(retStr,sizeof(buf),"%d - RF/50",id);  break;
+		case 5:   snprintf(retStr,sizeof(buf),"%d - RF/64",id);  break;
+		case 6:   snprintf(retStr,sizeof(buf),"%d - RF/100",id); break;
+		case 7:   snprintf(retStr,sizeof(buf),"%d - RF/128",id); break;
+		default:  snprintf(retStr,sizeof(buf),"%d - (Unknown)",id); break;
 		}
-
 	return buf;
 }
 
@@ -1302,25 +1320,168 @@ int CmdT55xxWipe(const char *Cmd) {
 		if (!CmdT55xxWriteBlock(ptrData)) 
 			PrintAndLog("Error writing blk %d", blk);
 		
-		memset(writeData, sizeof(writeData), 0x00);
+		memset(writeData,0x00, sizeof(writeData));
 	}
 	return 0;
 }
 
+int CmdT55xxBruteForce(const char *Cmd) {
+	
+	// load a default pwd file.
+	char buf[9];
+	char filename[FILE_PATH_SIZE]={0};
+	int	keycnt = 0;
+	uint8_t stKeyBlock = 20;
+	uint8_t *keyBlock = NULL, *p;
+	keyBlock = calloc(stKeyBlock, 6);
+	if (keyBlock == NULL) return 1;
+	
+    uint32_t start_password = 0x00000000; //start password
+    uint32_t end_password   = 0xFFFFFFFF; //end   password
+    bool found = false;
+
+    char cmdp = param_getchar(Cmd, 0);
+    if (cmdp == 'h' || cmdp == 'H') return usage_t55xx_bruteforce();
+
+	if (cmdp == 'i' || cmdp == 'I') {
+	
+		int len = strlen(Cmd+2);
+		if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
+		memcpy(filename, Cmd+2, len);
+	
+		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
+			
+			//The line start with # is comment, skip
+			if( buf[0]=='#' ) continue;
+
+			if (!isxdigit(buf[0])){
+				PrintAndLog("File content error. '%s' must include 8 HEX symbols", buf);
+				continue;
+			}
+			
+			buf[8] = 0;
+
+			if ( stKeyBlock - keycnt < 2) {
+				p = realloc(keyBlock, 6*(stKeyBlock+=10));
+				if (!p) {
+					PrintAndLog("Cannot allocate memory for defaultKeys");
+					free(keyBlock);
+					return 2;
+				}
+				keyBlock = p;
+			}
+			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));
+		}		
+		fclose(f);
+		
+		if (keycnt == 0) {
+			PrintAndLog("No keys found in file");
+			return 1;
+		}
+		PrintAndLog("Loaded %d keys", keycnt);
+		
+		// loop
+		uint64_t testpwd = 0x00;
+		for (uint16_t c = 0; c < keycnt; ++c ) {
+	
+			if (ukbhit()) {
+				getchar();
+				printf("\naborted via keyboard!\n");
+				return 0;
+			}
+		
+			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");
+				return 0;
+			}
+			
+			found = tryDetectModulation();
+
+			if ( found ) {
+				PrintAndLog("Found valid password: [%08X]", testpwd);
+				return 0;
+			} 
+		}
+		PrintAndLog("Password NOT found.");
+		return 0;
+	}
+	
+	// Try to read Block 7, first :)
+	
+	// incremental pwd range search
+    start_password = param_get32ex(Cmd, 0, 0, 16);
+	end_password = param_get32ex(Cmd, 1, 0, 16);
+	
+	if ( start_password >= end_password ) return usage_t55xx_bruteforce();
+	
+    PrintAndLog("Search password range [%08X -> %08X]", start_password, end_password);
+	
+    uint32_t i = start_password;
+
+    while ((!found) && (i <= end_password)){
+
+		printf(".");
+		fflush(stdout);
+		if (ukbhit()) {
+			getchar();
+			printf("\naborted via keyboard!\n");
+			return 0;
+		}
+			
+		if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, TRUE, i)) {
+			PrintAndLog("Aquireing data from device failed. Quitting");
+			return 0;
+		}
+		found = tryDetectModulation();
+        
+		if (found) break;
+		i++;
+    }
+    
+    PrintAndLog("");
+	
+    if (found)
+		PrintAndLog("Found valid password: [%08x]", i);
+    else
+		PrintAndLog("Password NOT found. Last tried: [%08x]", --i);
+    return 0;
+}
+
 static command_t CommandTable[] = {
-  {"help",   CmdHelp,           1, "This help"},
-  {"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."},
-  {"read",     CmdT55xxReadBlock, 0, "b <block> 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)"},
-  {"write",    CmdT55xxWriteBlock,0, "b <block> d <data> p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"},
-  {"trace",    CmdT55xxReadTrace, 1, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"},
-  {"info",     CmdT55xxInfo,      1, "[1] Show T55x7 configuration data (page 0/ blk 0)"},
-  {"dump",     CmdT55xxDump,      0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"},
-  {"special", special,          0, "Show block changes with 64 different offsets"},
-  {"wakeup", CmdT55xxWakeUp,    0, "Send AOR wakeup command"},
-  {"wipe",     CmdT55xxWipe,      0, "Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
-  {NULL, NULL, 0, NULL}
+	{"help",		CmdHelp,           1, "This help"},
+	{"bruteforce",CmdT55xxBruteForce,0, "<start password> <end password> [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 <block> 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)"},
+	{"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"},
+	{"wipe",		CmdT55xxWipe,      0, "Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
+	{"write",		CmdT55xxWriteBlock,0, "b <block> d <data> p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"},
+	{NULL, NULL, 0, NULL}
 };
 
 int CmdLFT55XX(const char *Cmd) {