X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/1c611bbd26066e1a8dd36ffd389b57040a7dfad6..65e344df3e787e8bf2fbc13d3859ca1a6e2292c3:/client/cmdhfmf.c

diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c
index 96eb8007..74382886 100644
--- a/client/cmdhfmf.c
+++ b/client/cmdhfmf.c
@@ -137,12 +137,86 @@ int CmdHF14AMfWrBl(const char *Cmd)
 		PrintAndLog("Command execute timeout");
 	}
 
-	return 0;
-}
-
-int CmdHF14AMfRdBl(const char *Cmd)
-{
-	uint8_t blockNo = 0;
+	return 0;
+}
+
+int CmdHF14AMfUWrBl(const char *Cmd)
+{
+        uint8_t blockNo = 0;
+        uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	UsbCommand resp;
+        
+        if (strlen(Cmd)<3) {
+                PrintAndLog("Usage:  hf mf uwrbl    <block number> <block data (8 hex symbols)>");
+                PrintAndLog("        sample: hf mf uwrbl 0 01020304");
+                return 0;
+        }       
+
+        blockNo = param_get8(Cmd, 0);
+        if (param_gethex(Cmd, 1, bldata, 8)) {
+                PrintAndLog("Block data must include 8 HEX symbols");
+                return 1;
+        }
+
+	switch(blockNo)
+	{
+	case 0:
+		PrintAndLog("Access Denied");
+		break;
+	case 1:
+		PrintAndLog("Access Denied");
+		break;
+	case 2:
+		PrintAndLog("--specialblock no:%02x", blockNo);
+                PrintAndLog("--data: %s", sprint_hex(bldata, 4));
+                UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
+                memcpy(c.d.asBytes, bldata, 4);
+                SendCommand(&c);
+
+                if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+                        uint8_t isOK  = resp.arg[0] & 0xff;
+                        PrintAndLog("isOk:%02x", isOK);
+                } else {
+                        PrintAndLog("Command execute timeout");
+                }
+		break;
+	case 3:
+	        PrintAndLog("--specialblock no:%02x", blockNo);
+                PrintAndLog("--data: %s", sprint_hex(bldata, 4));
+                UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
+                memcpy(d.d.asBytes,bldata, 4);
+                SendCommand(&d);
+
+                if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+                        uint8_t isOK  = resp.arg[0] & 0xff;
+                        PrintAndLog("isOk:%02x", isOK);
+                } else {
+                        PrintAndLog("Command execute timeout");
+                }
+		break;
+	default: 
+        	PrintAndLog("--block no:%02x", blockNo);
+        	PrintAndLog("--data: %s", sprint_hex(bldata, 4));        	
+  		//UsbCommand e = {CMD_MIFAREU_WRITEBL_COMPAT, {blockNo}};
+        	//memcpy(e.d.asBytes,bldata, 16);
+  		UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
+                memcpy(e.d.asBytes,bldata, 4);
+		SendCommand(&e);
+
+        	if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+        	        uint8_t isOK  = resp.arg[0] & 0xff;
+                	PrintAndLog("isOk:%02x", isOK);
+        	} else {
+                	PrintAndLog("Command execute timeout");
+        	}
+		break;
+	}
+        return 0;
+}
+
+int CmdHF14AMfRdBl(const char *Cmd)
+{
+	uint8_t blockNo = 0;
 	uint8_t keyType = 0;
 	uint8_t key[6] = {0, 0, 0, 0, 0, 0};
 	
@@ -185,12 +259,135 @@ int CmdHF14AMfRdBl(const char *Cmd)
 		PrintAndLog("Command execute timeout");
 	}
 
-  return 0;
-}
-
-int CmdHF14AMfRdSc(const char *Cmd)
-{
-	int i;
+  return 0;
+}
+
+int CmdHF14AMfURdBl(const char *Cmd)
+{
+        uint8_t blockNo = 0;
+
+        if (strlen(Cmd)<1) {
+                PrintAndLog("Usage:  hf mf urdbl    <block number>");
+                PrintAndLog("        sample: hf mf urdbl 0");
+                return 0;
+        }       
+        
+        blockNo = param_get8(Cmd, 0);
+        PrintAndLog("--block no:%02x", blockNo);
+        
+  UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
+  SendCommand(&c);
+
+        UsbCommand resp;
+        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+                uint8_t                isOK  = resp.arg[0] & 0xff;
+                uint8_t              * data  = resp.d.asBytes;
+
+                if (isOK)
+                        PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
+                else
+                        PrintAndLog("isOk:%02x", isOK);
+        } else {
+                PrintAndLog("Command execute timeout");
+        }
+
+  return 0;
+}
+
+int CmdHF14AMfURdCard(const char *Cmd)
+{
+        int i;
+        uint8_t sectorNo = 0;
+	uint8_t *lockbytes_t=NULL;
+	uint8_t lockbytes[2]={0,0};
+	bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+        
+        uint8_t isOK  = 0;
+        uint8_t * data  = NULL;
+
+        if (sectorNo > 15) {
+                PrintAndLog("Sector number must be less than 16");
+                return 1;
+        }
+        PrintAndLog("Attempting to Read Ultralight... ");
+        
+  	UsbCommand c = {CMD_MIFAREU_READCARD, {sectorNo}};
+  	SendCommand(&c);
+
+        UsbCommand resp;
+        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+                isOK  = resp.arg[0] & 0xff;
+                data  = resp.d.asBytes;
+
+                PrintAndLog("isOk:%02x", isOK);
+                if (isOK) 
+                        for (i = 0; i < 16; i++) {
+				switch(i){
+				  case 2:
+					//process lock bytes
+					lockbytes_t=data+(i*4);
+					lockbytes[0]=lockbytes_t[2];
+					lockbytes[1]=lockbytes_t[3];
+					for(int j=0; j<16; j++){
+						bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
+					}
+					//PrintAndLog("LB %02x %02x", lockbytes[0],lockbytes[1]);
+					//PrintAndLog("LB2b %02x %02x %02x %02x %02x %02x %02x %02x",bit[8],bit[9],bit[10],bit[11],bit[12],bit[13],bit[14],bit[15]);		
+					PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
+					break;
+				  case 3: 
+					PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]);
+					break;
+				  case 4:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]);
+					break;
+				  case 5:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]);
+					break;
+				  case 6:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]);
+					break;
+				  case 7:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]);
+					break;
+				  case 8:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]);
+					break;
+				  case 9:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]);
+					break;
+				  case 10:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]);
+					break;
+				  case 11:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]);
+					break;
+				  case 12:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]);
+					break;
+				  case 13:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]);
+					break;
+				  case 14:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]);
+					break;
+				  case 15:
+                                        PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]);
+					break;
+				  default:
+					PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
+					break;
+				}
+                        }
+        } else {
+                PrintAndLog("Command1 execute timeout");
+        }
+  return 0;
+}
+
+int CmdHF14AMfRdSc(const char *Cmd)
+{
+	int i;
 	uint8_t sectorNo = 0;
 	uint8_t keyType = 0;
 	uint8_t key[6] = {0, 0, 0, 0, 0, 0};
@@ -380,6 +577,8 @@ int CmdHF14AMfDump(const char *Cmd)
 				}
 				if (isOK) {
 					fwrite ( data, 1, 16, fout );
+                    PrintAndLog("Dumped card data into 'dumpdata.bin'");
+
 				}
 				else {
 					PrintAndLog("Could not get access rights for block %d", i);
@@ -393,7 +592,6 @@ int CmdHF14AMfDump(const char *Cmd)
 	
 	fclose(fin);
 	fclose(fout);
-	
   return 0;
 }
 
@@ -500,7 +698,7 @@ int CmdHF14AMfNested(const char *Cmd)
 	uint8_t blDiff = 0;
 	int  SectorsCnt = 0;
 	uint8_t key[6] = {0, 0, 0, 0, 0, 0};
-	uint8_t keyBlock[16 * 6];
+	uint8_t keyBlock[6*6];
 	uint64_t key64 = 0;
 	int transferToEml = 0;
 	
@@ -572,20 +770,12 @@ int CmdHF14AMfNested(const char *Cmd)
 		PrintAndLog("--target block no:%02x target key type:%02x ", trgBlockNo, trgKeyType);
 
 	if (cmdp == 'o') {
-		if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) {
+		if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true)) {
 			PrintAndLog("Nested error.");
 			return 2;
 		}
-
-		for (i = 0; i < 16; i++) {
-			PrintAndLog("count=%d key= %s", i, sprint_hex(keyBlock + i * 6, 6));
-		}
-	
-		// test keys
-		res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64);
-		if (res)
-			res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64);
-		if (!res) {
+		key64 = bytes_to_num(keyBlock, 6);
+		if (key64) {
 			PrintAndLog("Found valid key:%012"llx, key64);
 
 			// transfer key to the emulator
@@ -603,6 +793,9 @@ int CmdHF14AMfNested(const char *Cmd)
 		}
 	}
 	else { // ------------------------------------  multiple sectors working
+		clock_t time1;
+		time1 = clock();
+
 		blDiff = blockNo % 4;
 		PrintAndLog("Block shift=%d", blDiff);
 		e_sector = calloc(SectorsCnt, sizeof(sector));
@@ -610,10 +803,10 @@ int CmdHF14AMfNested(const char *Cmd)
 		
 		//test current key 4 sectors
 		memcpy(keyBlock, key, 6);
-		num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 1 * 6));
-		num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 2 * 6));
-		num_to_bytes(0xffffffffffff, 6, (uint8_t*)(keyBlock + 3 * 6));
-		num_to_bytes(0x000000000000, 6, (uint8_t*)(keyBlock + 4 * 6));
+		num_to_bytes(0xffffffffffff, 6, (uint8_t*)(keyBlock + 1 * 6));
+		num_to_bytes(0x000000000000, 6, (uint8_t*)(keyBlock + 2 * 6));
+		num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 3 * 6));
+		num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 4 * 6));
 		num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6));
 
 		PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt);
@@ -628,32 +821,41 @@ int CmdHF14AMfNested(const char *Cmd)
 					e_sector[i].foundKey[j] = 1;
 				}
 			}
-		} 
+		}
+		
 		
 		// nested sectors
 		iterations = 0;
 		PrintAndLog("nested...");
+		bool calibrate = true;
 		for (i = 0; i < NESTED_SECTOR_RETRY; i++) {
-			for (trgBlockNo = blDiff; trgBlockNo < SectorsCnt * 4; trgBlockNo = trgBlockNo + 4) 
+			for (trgBlockNo = blDiff; trgBlockNo < SectorsCnt * 4; trgBlockNo = trgBlockNo + 4) {
 				for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) { 
 					if (e_sector[trgBlockNo / 4].foundKey[trgKeyType]) continue;
-					if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) continue;
+					PrintAndLog("-----------------------------------------------");
+					if(mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, calibrate)) {
+						PrintAndLog("Nested error.\n");
+						return 2;
+					}
+					else {
+						calibrate = false;
+					}
 					
 					iterations++;
-					
-					//try keys from nested
-					res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64);
-					if (res)
-						res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64);
-					if (!res) {
+
+					key64 = bytes_to_num(keyBlock, 6);
+					if (key64) {
 						PrintAndLog("Found valid key:%012"llx, key64);
 						e_sector[trgBlockNo / 4].foundKey[trgKeyType] = 1;
 						e_sector[trgBlockNo / 4].Key[trgKeyType] = key64;
 					}
 				}
+			}
 		}
 
-		PrintAndLog("Iterations count: %d", iterations);
+		printf("Time in nested: %1.3f (%1.3f sec per key)\n\n", ((float)clock() - time1)/1000.0, ((float)clock() - time1)/iterations/1000.0);
+		
+		PrintAndLog("-----------------------------------------------\nIterations count: %d\n\n", iterations);
 		//print them
 		PrintAndLog("|---|----------------|---|----------------|---|");
 		PrintAndLog("|sec|key A           |res|key B           |res|");
@@ -830,16 +1032,16 @@ int CmdHF14AMfChk(const char *Cmd)
 				while( !feof(f) ){
 					memset(buf, 0, sizeof(buf));
 					if (fgets(buf, sizeof(buf), f) == NULL) {
-            PrintAndLog("File reading error.");
-            return 2;
-          }
+						PrintAndLog("File reading error.");
+						return 2;
+					}
           
 					if (strlen(buf) < 12 || buf[11] == '\n')
 						continue;
 				
 					while (fgetc(f) != '\n' && !feof(f)) ;  //goto next line
 					
-					if( buf[0]=='#' ) continue;	//The line start with # is remcommnet,skip
+					if( buf[0]=='#' ) continue;	//The line start with # is comment, skip
 
 					if (!isxdigit(buf[0])){
 						PrintAndLog("File content error. '%s' must include 12 HEX symbols",buf);
@@ -883,10 +1085,10 @@ int CmdHF14AMfChk(const char *Cmd)
 		int b=blockNo;
 		for (int i=0; i<SectorsCnt; ++i) {
 			PrintAndLog("--SectorsCnt:%d block no:0x%02x key type:%C key count:%d ", i,	 b, t?'B':'A', keycnt);
-			int size = keycnt>8?8:keycnt;
-			for (int c = 0; c < keycnt; c+=size) {
-				size=keycnt-c>8?8:keycnt-c;			
-				res = mfCheckKeys(b, t, size, keyBlock +6*c, &key64);
+			uint32_t max_keys = keycnt>USB_CMD_DATA_SIZE/6?USB_CMD_DATA_SIZE/6:keycnt;
+			for (uint32_t c = 0; c < keycnt; c+=max_keys) {
+				uint32_t size = keycnt-c>max_keys?max_keys:keycnt-c;
+				res = mfCheckKeys(b, t, size, &keyBlock[6*c], &key64);
 				if (res !=1) {
 					if (!res) {
 						PrintAndLog("Found valid key:[%012"llx"]",key64);
@@ -896,11 +1098,6 @@ int CmdHF14AMfChk(const char *Cmd)
 							num_to_bytes(key64, 6, block + t*10);
 							mfEmlSetMem(block, get_trailer_block(b), 1);
 						}
-						break;
-					}
-					else {
-						printf("Not found yet, keycnt:%d\r", c+size);
-						fflush(stdout);
 					}
 				} else {
 					PrintAndLog("Command execute timeout");
@@ -1667,12 +1864,15 @@ int CmdHF14AMfSniff(const char *Cmd){
 
 static command_t CommandTable[] =
 {
-  {"help",		CmdHelp,						1, "This help"},
-  {"dbg",			CmdHF14AMfDbg,			0, "Set default debug mode"},
-  {"rdbl",		CmdHF14AMfRdBl,			0, "Read MIFARE classic block"},
-  {"rdsc",		CmdHF14AMfRdSc,			0, "Read MIFARE classic sector"},
-  {"dump",		CmdHF14AMfDump,			0, "Dump MIFARE classic tag to binary file"},
-  {"restore",	CmdHF14AMfRestore,	0, "Restore MIFARE classic binary file to BLANK tag"},
+  {"help",		CmdHelp,						1, "This help"},
+  {"dbg",			CmdHF14AMfDbg,			0, "Set default debug mode"},
+  {"rdbl",		CmdHF14AMfRdBl,			0, "Read MIFARE classic block"},
+  {"urdbl",              CmdHF14AMfURdBl,                 0, "Read MIFARE Ultralight block"},
+  {"urdcard",           CmdHF14AMfURdCard,               0,"Read MIFARE Ultralight Card"},
+  {"uwrbl",		CmdHF14AMfUWrBl,		0,"Write MIFARE Ultralight block"},
+  {"rdsc",		CmdHF14AMfRdSc,			0, "Read MIFARE classic sector"},
+  {"dump",		CmdHF14AMfDump,			0, "Dump MIFARE classic tag to binary file"},
+  {"restore",	CmdHF14AMfRestore,	0, "Restore MIFARE classic binary file to BLANK tag"},
   {"wrbl",		CmdHF14AMfWrBl,			0, "Write MIFARE classic block"},
   {"chk",			CmdHF14AMfChk,			0, "Test block keys"},
   {"mifare",	CmdHF14AMifare,			0, "Read parity error messages. param - <used card nonce>"},