PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d|s|ss] [<key (12 hex symbols)>] [<dic (*.dic)>]");\r
PrintAndLog(" * - all sectors");\r
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");\r
- PrintAndLog("d - write keys to binary file\n");\r
+ PrintAndLog("d - write keys to binary file (not used when <block number> supplied)");\r
PrintAndLog("t - write keys to emulator memory");\r
PrintAndLog("s - slow execute. timeout 1ms");\r
PrintAndLog("ss - very slow execute. timeout 5ms");\r
return 0;\r
}\r
\r
- FILE * f;\r
- char filename[FILE_PATH_SIZE]={0};\r
- char buf[13];\r
- uint8_t *keyBlock = NULL, *p;\r
- uint16_t stKeyBlock = 20;\r
-\r
- int i, res;\r
- int keycnt = 0;\r
- char ctmp = 0x00;\r
- int clen = 0;\r
- uint8_t blockNo = 0;\r
- uint8_t SectorsCnt = 0;\r
- uint8_t keyType = 0;\r
- uint64_t key64 = 0;\r
+ FILE * f;\r
+ char filename[FILE_PATH_SIZE]={0};\r
+ char buf[13];\r
+ uint8_t *keyBlock = NULL, *p;\r
+ uint16_t stKeyBlock = 20;\r
+ int i, res;\r
+ int keycnt = 0;\r
+ char ctmp = 0x00;\r
+ int clen = 0;\r
+ uint8_t blockNo = 0;\r
+ uint8_t SectorsCnt = 0;\r
+ uint8_t keyType = 0;\r
+ uint64_t key64 = 0;\r
// timeout in units. (ms * 106)/10 or us*0.0106\r
- uint8_t btimeout14a = MF_CHKKEYS_DEFTIMEOUT; // fast by default\r
- bool param3InUse = false;\r
-\r
- bool transferToEml = 0;\r
- bool createDumpFile = 0;\r
-\r
+ uint8_t btimeout14a = MF_CHKKEYS_DEFTIMEOUT; // fast by default\r
+ bool param3InUse = false;\r
+ bool transferToEml = 0;\r
+ bool createDumpFile = 0;\r
+ bool singleBlock = false; // Flag to ID if a single or multi key check\r
+ uint8_t keyFoundCount = 0; // Counter to display the number of keys found/transfered to emulator\r
+ \r
sector_t *e_sector = NULL;\r
\r
keyBlock = calloc(stKeyBlock, 6);\r
\r
if (param_getchar(Cmd, 0)=='*') {\r
SectorsCnt = ParamCardSizeSectors(param_getchar(Cmd + 1, 0));\r
- }\r
- else\r
+ } else { \r
blockNo = param_get8(Cmd, 0);\r
+ // Singe Key check, so Set Sector count to cover sectors (1 to sector that contains the block)\r
+ // 1 and 2 Cards : Sector = blockNo/4 + 1\r
+ // Sectors 0 - 31 : 4 blocks per sector : Blocks 0 - 127\r
+ // Sectors 32 - 39 : 16 blocks per sector : Blocks 128 - 255 (4K)\r
+ if (blockNo < 128) {\r
+ SectorsCnt = (blockNo / 4) + 1;\r
+ } else {\r
+ SectorsCnt = 32 + ((blockNo-128)/16) + 1;\r
+ }\r
+ singleBlock = true; // Set flag for single key check\r
+ }\r
\r
ctmp = param_getchar(Cmd, 1);\r
clen = param_getlength(Cmd, 1);\r
return 1;\r
};\r
}\r
-\r
+ \r
parseParamTDS(Cmd, 2, &transferToEml, &createDumpFile, &btimeout14a);\r
\r
+ if (singleBlock & createDumpFile) {\r
+ PrintAndLog (" block key check (<block no>) and write to dump file (d) combination is not supported ");\r
+ PrintAndLog (" please remove option d and try again");\r
+ return 1;\r
+ }\r
+\r
param3InUse = transferToEml | createDumpFile | (btimeout14a != MF_CHKKEYS_DEFTIMEOUT);\r
\r
PrintAndLog("--chk keys. sectors:%2d, block no:%3d, key type:%c, eml:%c, dmp=%c checktimeout=%d us",\r
- SectorsCnt, blockNo, keyType?'B':'A', transferToEml?'y':'n', createDumpFile?'y':'n', ((int)btimeout14a * 10000) / 106);\r
+ SectorsCnt, blockNo, keyType==0?'A':keyType==1?'B':'?', transferToEml?'y':'n', createDumpFile?'y':'n', ((int)btimeout14a * 10000) / 106);\r
\r
for (i = param3InUse; param_getchar(Cmd, 2 + i); i++) {\r
if (!param_gethex(Cmd, 2 + i, keyBlock + 6 * keycnt, 12)) {\r
keyBlock = p;\r
}\r
PrintAndLog("chk key[%2d] %02x%02x%02x%02x%02x%02x", keycnt,\r
- (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],\r
+ (keyBlock + 6*keycnt)[0], (keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],\r
(keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);\r
keycnt++;\r
} else {\r
return 2;\r
}\r
\r
- if ( (f = fopen( filename , "r")) ) {\r
- while( fgets(buf, sizeof(buf), f) ){\r
+ if ((f = fopen( filename , "r"))) {\r
+ while (fgets(buf, sizeof(buf), f)) {\r
if (strlen(buf) < 12 || buf[11] == '\n')\r
continue;\r
\r
\r
if( buf[0]=='#' ) continue; //The line start with # is comment, skip\r
\r
- if (!isxdigit((unsigned char)buf[0])){\r
- PrintAndLog("File content error. '%s' must include 12 HEX symbols",buf);\r
+ bool content_error = false;\r
+ for (int i = 0; i < 12; i++) {\r
+ if (!isxdigit((unsigned char)buf[i])) {\r
+ content_error = true;\r
+ }\r
+ }\r
+ if (content_error) {\r
+ PrintAndLog("File content error. '%s' must include 12 HEX symbols", buf);\r
continue;\r
}\r
\r
buf[12] = 0;\r
\r
- if ( stKeyBlock - keycnt < 2) {\r
+ if (stKeyBlock - keycnt < 2) {\r
p = realloc(keyBlock, 6*(stKeyBlock+=10));\r
if (!p) {\r
PrintAndLog("Cannot allocate memory for defKeys");\r
PrintAndLog("File: %s: not found or locked.", filename);\r
free(keyBlock);\r
return 1;\r
-\r
}\r
}\r
}\r
PrintAndLog("No key specified, trying default keys");\r
for (;keycnt < defaultKeysSize; keycnt++)\r
PrintAndLog("chk default key[%2d] %02x%02x%02x%02x%02x%02x", keycnt,\r
- (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],\r
+ (keyBlock + 6*keycnt)[0], (keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],\r
(keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);\r
}\r
\r
printf("\n");\r
\r
bool foundAKey = false;\r
- uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt;\r
- if (SectorsCnt) {\r
+ bool clearTraceLog = true;\r
+ uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt;\r
+\r
+ // !SingleKey, so all key check (if SectorsCnt > 0)\r
+ if (!singleBlock) { \r
PrintAndLog("To cancel this operation press the button on the proxmark...");\r
printf("--");\r
for (uint32_t c = 0; c < keycnt; c += max_keys) {\r
\r
uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;\r
- res = mfCheckKeysSec(SectorsCnt, keyType, btimeout14a, true, size, &keyBlock[6 * c], e_sector); // timeout is (ms * 106)/10 or us*0.0106\r
+ res = mfCheckKeysSec(SectorsCnt, keyType, btimeout14a, clearTraceLog, size, &keyBlock[6 * c], e_sector); // timeout is (ms * 106)/10 or us*0.0106\r
+ clearTraceLog = false;\r
\r
if (res != 1) {\r
if (!res) {\r
PrintAndLog("Command execute timeout");\r
}\r
}\r
- } else {\r
+ } else { \r
int keyAB = keyType;\r
do {\r
- for (uint32_t c = 0; c < keycnt; c+=max_keys) {\r
+ for (uint32_t c = 0; c < keycnt; c += max_keys) {\r
\r
uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;\r
res = mfCheckKeys(blockNo, keyAB & 0x01, true, size, &keyBlock[6 * c], &key64);\r
+ clearTraceLog = false;\r
\r
if (res != 1) {\r
- if (!res) {\r
- PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64);\r
+ if (!res) { \r
+ // Use the common format below\r
+ // PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64);\r
foundAKey = true;\r
+ \r
+ // Store the Single Key for display list\r
+ // For a single block check, SectorsCnt = Sector that contains the block\r
+ e_sector[SectorsCnt-1].foundKey[(keyAB & 0x01)] = true; // flag key found \r
+ e_sector[SectorsCnt-1].Key[(keyAB & 0x01)] = key64; // Save key data \r
+ \r
}\r
} else {\r
PrintAndLog("Command execute timeout");\r
\r
// print result\r
if (foundAKey) {\r
- if (SectorsCnt) {\r
- PrintAndLog("");\r
- PrintAndLog("|---|----------------|---|----------------|---|");\r
- PrintAndLog("|sec|key A |res|key B |res|");\r
- PrintAndLog("|---|----------------|---|----------------|---|");\r
- for (i = 0; i < SectorsCnt; i++) {\r
- PrintAndLog("|%03d| %012" PRIx64 " | %d | %012" PRIx64 " | %d |", i,\r
- e_sector[i].Key[0], e_sector[i].foundKey[0], e_sector[i].Key[1], e_sector[i].foundKey[1]);\r
+ PrintAndLog("");\r
+ PrintAndLog("|---|----------------|----------------|");\r
+ PrintAndLog("|sec|key A |key B |");\r
+ PrintAndLog("|---|----------------|----------------|");\r
+ for (i = 0; i < SectorsCnt; i++) {\r
+ // If a block key check, only print a line if a key was found.\r
+ if (!singleBlock || e_sector[i].foundKey[0] || e_sector[i].foundKey[1]) {\r
+ char keyAString[13] = " ? ";\r
+ char keyBString[13] = " ? ";\r
+ if (e_sector[i].foundKey[0]) {\r
+ sprintf(keyAString, "%012" PRIx64, e_sector[i].Key[0]);\r
+ }\r
+ if (e_sector[i].foundKey[1]) {\r
+ sprintf(keyBString, "%012" PRIx64, e_sector[i].Key[1]);\r
+ }\r
+ PrintAndLog("|%03d| %s | %s |", i, keyAString, keyBString);\r
}\r
- PrintAndLog("|---|----------------|---|----------------|---|");\r
}\r
+ PrintAndLog("|---|----------------|----------------|");\r
} else {\r
PrintAndLog("");\r
PrintAndLog("No valid keys found.");\r
for (uint16_t t = 0; t < 2; t++) {\r
if (e_sector[sectorNo].foundKey[t]) {\r
num_to_bytes(e_sector[sectorNo].Key[t], 6, block + t * 10);\r
+ keyFoundCount++; // Key found count for information\r
}\r
}\r
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);\r
}\r
}\r
- PrintAndLog("Found keys have been transferred to the emulator memory");\r
+ // Updated to show the actual number of keys found/transfered.\r
+ PrintAndLog("%d keys(s) found have been transferred to the emulator memory",keyFoundCount);\r
}\r
\r
- if (createDumpFile) {\r
+ if (createDumpFile && !singleBlock) {\r
FILE *fkeys = fopen("dumpkeys.bin","wb");\r
if (fkeys == NULL) {\r
PrintAndLog("Could not create file dumpkeys.bin");\r
fclose(fkeys);\r
PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys.");\r
}\r
-\r
+ \r
free(e_sector);\r
free(keyBlock);\r
PrintAndLog("");\r
return 0;\r
}\r
\r
+\r
void readerAttack(nonces_t ar_resp[], bool setEmulatorMem, bool doStandardAttack) {\r
#define ATTACK_KEY_COUNT 7 // keep same as define in iso14443a.c -> Mifare1ksim()\r
// cannot be more than 7 or it will overrun c.d.asBytes(512)\r
break;\r
case 'u':\r
case 'U':\r
- param_gethex_ex(Cmd, cmdp+1, uid, &uidlen);\r
- switch(uidlen) {\r
+ uidlen = 14;\r
+ if (param_gethex_ex(Cmd, cmdp+1, uid, &uidlen)) {\r
+ return usage_hf14_mfsim();\r
+ }\r
+ switch (uidlen) {\r
case 14: flags = FLAG_7B_UID_IN_DATA; break;\r
case 8: flags = FLAG_4B_UID_IN_DATA; break;\r
default: return usage_hf14_mfsim();\r
//needs nt, ar, at, Data to decrypt\r
int CmdDecryptTraceCmds(const char *Cmd){\r
uint8_t data[50];\r
- int len = 0;\r
- param_gethex_ex(Cmd,3,data,&len);\r
- return tryDecryptWord(param_get32ex(Cmd,0,0,16),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),data,len/2);\r
+ int len = 100;\r
+ param_gethex_ex(Cmd, 3, data, &len);\r
+ return tryDecryptWord(param_get32ex(Cmd, 0, 0, 16), param_get32ex(Cmd, 1, 0, 16), param_get32ex(Cmd, 2, 0, 16), data, len/2);\r
}\r
\r
int CmdHF14AMfAuth4(const char *cmd) {\r