#include "mifare/mad.h"\r
#include "mifare/ndef.h"\r
#include "emv/dump.h"\r
+#include "protocols.h"\r
\r
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up\r
\r
PrintAndLog("--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));\r
PrintAndLog("--data: %s", sprint_hex(bldata, 16));\r
\r
- UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};\r
+ UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};\r
memcpy(c.d.asBytes, key, 6);\r
memcpy(c.d.asBytes + 10, bldata, 16);\r
- SendCommand(&c);\r
+ SendCommand(&c);\r
\r
UsbCommand resp;\r
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
}\r
PrintAndLog("--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6));\r
\r
- UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};\r
+ UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};\r
memcpy(c.d.asBytes, key, 6);\r
- SendCommand(&c);\r
+ SendCommand(&c);\r
\r
UsbCommand resp;\r
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
return 2;\r
}\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
int CmdHF14AMfRdSc(const char *Cmd)\r
PrintAndLog("Command execute timeout");\r
}\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
uint8_t FirstBlockOfSector(uint8_t sectorNo)\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
+\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) SectorsCnt = (blockNo / 4) + 1;\r
- else SectorsCnt = 32 + ((blockNo-128)/16) + 1;\r
-\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
return 1;\r
};\r
}\r
- \r
+\r
parseParamTDS(Cmd, 2, &transferToEml, &createDumpFile, &btimeout14a);\r
\r
if (singleBlock & createDumpFile) {\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
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
}\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
+ bool foundAKey = false;\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
+ 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
+ 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
+\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
+ 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
- // 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
- 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
- }\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
+ keyFoundCount++; // Key found count for information\r
}\r
}\r
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);\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
return 0;\r
}\r
\r
- UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};\r
- SendCommand(&c);\r
+ UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};\r
+ SendCommand(&c);\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
int CmdHF14AMfEGet(const char *Cmd)\r
PrintAndLog("Command execute timeout");\r
}\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
int CmdHF14AMfEClear(const char *Cmd)\r
return 0;\r
}\r
\r
- UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}};\r
- SendCommand(&c);\r
- return 0;\r
+ UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}};\r
+ SendCommand(&c);\r
+ return 0;\r
}\r
\r
\r
\r
PrintAndLog("Saved %d blocks to file: %s", numBlocks, filename);\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
\r
case '\0': numSectors = 16; break;\r
case '2' : numSectors = 32; break;\r
case '4' : numSectors = 40; break;\r
- case 'd' : \r
+ case 'd' :\r
case 'D' : createDumpFile = true; break;\r
}\r
cmdp++;\r
return 0;\r
}\r
\r
-static command_t CommandTable[] =\r
-{\r
- {"help", CmdHelp, 1, "This help"},\r
- {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},\r
- {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},\r
- {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},\r
- {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},\r
- {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},\r
- {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},\r
- {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},\r
- {"chk", CmdHF14AMfChk, 0, "Test block keys"},\r
- {"mifare", CmdHF14AMifare, 0, "Read parity error messages."},\r
- {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},\r
- {"nested", CmdHF14AMfNested, 0, "Test nested authentication"},\r
- {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},\r
- {"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"},\r
- {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory"},\r
- {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},\r
- {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},\r
- {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},\r
- {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},\r
- {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},\r
- {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},\r
- {"cwipe", CmdHF14AMfCWipe, 0, "Wipe magic Chinese card"},\r
- {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},\r
- {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},\r
- {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},\r
- {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},\r
- {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},\r
- {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},\r
- {"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},\r
- {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"},\r
- {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"},\r
- {NULL, NULL, 0, NULL}\r
+int CmdHFMFPersonalize(const char *cmd) {\r
+\r
+ CLIParserInit("hf mf personalize",\r
+ "Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.",\r
+ "Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n"\r
+ "\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n"\r
+ "\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n"\r
+ "\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n"\r
+ "\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n");\r
+\r
+ void *argtable[] = {\r
+ arg_param_begin,\r
+ arg_str0("tT", "keytype", "<A|B>", "key type (A or B) to authenticate sector 0 (default: A)"),\r
+ arg_str0("kK", "key", "<key (hex 6 Bytes)>", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"),\r
+ arg_str1(NULL, NULL, "<UIDF0|UIDF1|UIDF2|UIDF3>", "Personalization Option"),\r
+ arg_param_end\r
+ };\r
+ CLIExecWithReturn(cmd, argtable, true);\r
+\r
+ char keytypestr[2] = "A";\r
+ uint8_t keytype = 0x00;\r
+ int keytypestr_len;\r
+ int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t*)keytypestr, 1, &keytypestr_len);\r
+ if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'A' && keytypestr[0] != 'b' && keytypestr[0] != 'B')) {\r
+ PrintAndLog("ERROR: not a valid key type. Key type must be A or B");\r
+ CLIParserFree();\r
+ return 1;\r
+ }\r
+ if (keytypestr[0] == 'B' || keytypestr[0] == 'b') {\r
+ keytype = 0x01;\r
+ }\r
+\r
+ uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
+ int key_len;\r
+ res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len);\r
+ if (res || (!res && key_len > 0 && key_len != 6)) {\r
+ PrintAndLog("ERROR: not a valid key. Key must be 12 hex digits");\r
+ CLIParserFree();\r
+ return 1;\r
+ }\r
+\r
+ char pers_optionstr[6];\r
+ int opt_len;\r
+ uint8_t pers_option;\r
+ res = CLIParamStrToBuf(arg_get_str(3), (uint8_t*)pers_optionstr, 5, &opt_len);\r
+ if (res || (!res && opt_len > 0 && opt_len != 5)\r
+ || (strncmp(pers_optionstr, "UIDF0", 5) && strncmp(pers_optionstr, "UIDF1", 5) && strncmp(pers_optionstr, "UIDF2", 5) && strncmp(pers_optionstr, "UIDF3", 5))) {\r
+ PrintAndLog("ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3");\r
+ CLIParserFree();\r
+ return 1;\r
+ }\r
+ if (!strncmp(pers_optionstr, "UIDF0", 5)) {\r
+ pers_option = MIFARE_EV1_UIDF0;\r
+ } else if (!strncmp(pers_optionstr, "UIDF1", 5)) {\r
+ pers_option = MIFARE_EV1_UIDF1;\r
+ } else if (!strncmp(pers_optionstr, "UIDF2", 5)) {\r
+ pers_option = MIFARE_EV1_UIDF2;\r
+ } else {\r
+ pers_option = MIFARE_EV1_UIDF3;\r
+ }\r
+\r
+ CLIParserFree();\r
+\r
+ UsbCommand c = {CMD_MIFARE_PERSONALIZE_UID, {keytype, pers_option, 0}};\r
+ memcpy(c.d.asBytes, key, 6);\r
+ SendCommand(&c);\r
+\r
+ UsbCommand resp;\r
+ if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {\r
+ uint8_t isOK = resp.arg[0] & 0xff;\r
+ PrintAndLog("Personalization %s", isOK ? "FAILED" : "SUCCEEDED");\r
+ } else {\r
+ PrintAndLog("Command execute timeout");\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+static command_t CommandTable[] = {\r
+ {"help", CmdHelp, 1, "This help"},\r
+ {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},\r
+ {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},\r
+ {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},\r
+ {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},\r
+ {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},\r
+ {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},\r
+ {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},\r
+ {"chk", CmdHF14AMfChk, 0, "Test block keys"},\r
+ {"mifare", CmdHF14AMifare, 0, "Read parity error messages."},\r
+ {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},\r
+ {"nested", CmdHF14AMfNested, 0, "Test nested authentication"},\r
+ {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},\r
+ {"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"},\r
+ {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory"},\r
+ {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},\r
+ {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},\r
+ {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},\r
+ {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},\r
+ {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},\r
+ {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},\r
+ {"cwipe", CmdHF14AMfCWipe, 0, "Wipe magic Chinese card"},\r
+ {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},\r
+ {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},\r
+ {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},\r
+ {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},\r
+ {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},\r
+ {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},\r
+ {"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},\r
+ {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"},\r
+ {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"},\r
+ {"personalize", CmdHFMFPersonalize, 0, "Personalize UID (Mifare Classic EV1 only)"},\r
+ {NULL, NULL, 0, NULL}\r
};\r
\r
-int CmdHFMF(const char *Cmd)\r
-{\r
+\r
+int CmdHFMF(const char *Cmd) {\r
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);\r
CmdsParse(CommandTable, Cmd);\r
return 0;\r
}\r
\r
-int CmdHelp(const char *Cmd)\r
-{\r
- CmdsHelp(CommandTable);\r
- return 0;\r
+\r
+int CmdHelp(const char *Cmd) {\r
+ CmdsHelp(CommandTable);\r
+ return 0;\r
}\r