}\r
}\r
\r
+static int ParamCardSizeSectors(const char c) {\r
+ int numBlocks = 16;\r
+ switch (c) {\r
+ case '0' : numBlocks = 5; break;\r
+ case '2' : numBlocks = 32; break;\r
+ case '4' : numBlocks = 40; break;\r
+ default: numBlocks = 16;\r
+ }\r
+ return numBlocks;\r
+}\r
+\r
+static int ParamCardSizeBlocks(const char c) {\r
+ int numBlocks = 16 * 4;\r
+ switch (c) {\r
+ case '0' : numBlocks = 5 * 4; break;\r
+ case '2' : numBlocks = 32 * 4; break;\r
+ case '4' : numBlocks = 32 * 4 + 8 * 16; break;\r
+ default: numBlocks = 16 * 4;\r
+ }\r
+ return numBlocks;\r
+}\r
+\r
int CmdHF14AMfDump(const char *Cmd)\r
{\r
uint8_t sectorNo, blockNo;\r
UsbCommand resp;\r
\r
char cmdp = param_getchar(Cmd, 0);\r
- switch (cmdp) {\r
- case '0' : numSectors = 5; break;\r
- case '1' :\r
- case '\0': numSectors = 16; break;\r
- case '2' : numSectors = 32; break;\r
- case '4' : numSectors = 40; break;\r
- default: numSectors = 16;\r
- }\r
+ numSectors = ParamCardSizeSectors(cmdp);\r
\r
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {\r
PrintAndLog("Usage: hf mf dump [card memory]");\r
} sector_t;\r
\r
\r
+# define NESTED_KEY_COUNT 15\r
int CmdHF14AMfNested(const char *Cmd)\r
{\r
int i, j, res, iterations;\r
uint8_t trgKeyType = 0;\r
uint8_t SectorsCnt = 0;\r
uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
- uint8_t keyBlock[14*6];\r
+ uint8_t keyBlock[NESTED_KEY_COUNT * 6];\r
uint64_t key64 = 0;\r
- bool transferToEml = false;\r
+ \r
+ bool autosearchKey = false;\r
\r
+ bool transferToEml = false;\r
bool createDumpFile = false;\r
FILE *fkeys;\r
uint8_t standart[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\r
if (strlen(Cmd)<3) {\r
PrintAndLog("Usage:");\r
PrintAndLog(" all sectors: hf mf nested <card memory> <block number> <key A/B> <key (12 hex symbols)> [t,d]");\r
+ PrintAndLog(" all sectors autosearch key: hf mf nested <card memory> * [t,d]");\r
PrintAndLog(" one sector: hf mf nested o <block number> <key A/B> <key (12 hex symbols)>");\r
PrintAndLog(" <target block number> <target key A/B> [t]");\r
+ PrintAndLog(" ");\r
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");\r
- PrintAndLog("t - transfer keys into emulator memory");\r
- PrintAndLog("d - write keys to binary file");\r
+ PrintAndLog("t - transfer keys to emulator memory");\r
+ PrintAndLog("d - write keys to binary file dumpkeys.bin");\r
PrintAndLog(" ");\r
PrintAndLog(" sample1: hf mf nested 1 0 A FFFFFFFFFFFF ");\r
PrintAndLog(" sample2: hf mf nested 1 0 A FFFFFFFFFFFF t ");\r
PrintAndLog(" sample3: hf mf nested 1 0 A FFFFFFFFFFFF d ");\r
PrintAndLog(" sample4: hf mf nested o 0 A FFFFFFFFFFFF 4 A");\r
+ PrintAndLog(" sample5: hf mf nested 1 * t");\r
return 0;\r
}\r
\r
+ // <card memory>\r
cmdp = param_getchar(Cmd, 0);\r
- blockNo = param_get8(Cmd, 1);\r
- ctmp = param_getchar(Cmd, 2);\r
-\r
- if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') {\r
- PrintAndLog("Key type must be A or B");\r
- return 1;\r
+ if (cmdp == 'o' || cmdp == 'O') {\r
+ cmdp = 'o';\r
+ SectorsCnt = 1;\r
+ } else {\r
+ SectorsCnt = ParamCardSizeSectors(cmdp);\r
}\r
+ \r
+ // <block number>. number or autosearch key (*)\r
+ if (param_getchar(Cmd, 1) == '*') {\r
+ autosearchKey = true;\r
\r
- if (ctmp != 'A' && ctmp != 'a')\r
- keyType = 1;\r
+ ctmp = param_getchar(Cmd, 2);\r
+ transferToEml |= (ctmp == 't' || ctmp == 'T');\r
+ createDumpFile |= (ctmp == 'd' || ctmp == 'D');\r
\r
- if (param_gethex(Cmd, 3, key, 12)) {\r
- PrintAndLog("Key must include 12 HEX symbols");\r
- return 1;\r
- }\r
+ PrintAndLog("--nested. sectors:%2d, block no:*, eml:%c, dmp=%c ", SectorsCnt, transferToEml?'y':'n', createDumpFile?'y':'n');\r
+ } else {\r
+ blockNo = param_get8(Cmd, 1);\r
\r
- if (cmdp == 'o' || cmdp == 'O') {\r
- cmdp = 'o';\r
- trgBlockNo = param_get8(Cmd, 4);\r
- ctmp = param_getchar(Cmd, 5);\r
+ ctmp = param_getchar(Cmd, 2);\r
if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') {\r
- PrintAndLog("Target key type must be A or B");\r
+ PrintAndLog("Key type must be A or B");\r
return 1;\r
}\r
+\r
if (ctmp != 'A' && ctmp != 'a')\r
- trgKeyType = 1;\r
- } else {\r
+ keyType = 1;\r
\r
- switch (cmdp) {\r
- case '0': SectorsCnt = 05; break;\r
- case '1': SectorsCnt = 16; break;\r
- case '2': SectorsCnt = 32; break;\r
- case '4': SectorsCnt = 40; break;\r
- default: SectorsCnt = 16;\r
+ if (param_gethex(Cmd, 3, key, 12)) {\r
+ PrintAndLog("Key must include 12 HEX symbols");\r
+ return 1;\r
}\r
- }\r
\r
- ctmp = param_getchar(Cmd, 4);\r
- if (ctmp == 't' || ctmp == 'T') transferToEml = true;\r
- else if (ctmp == 'd' || ctmp == 'D') createDumpFile = true;\r
+ // check if we can authenticate to sector\r
+ res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64);\r
+ if (res) {\r
+ PrintAndLog("Can't authenticate to block:%3d key type:%c key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));\r
+ return 3;\r
+ }\r
\r
- ctmp = param_getchar(Cmd, 6);\r
- transferToEml |= (ctmp == 't' || ctmp == 'T');\r
- transferToEml |= (ctmp == 'd' || ctmp == 'D');\r
+ // one sector nested\r
+ if (cmdp == 'o') { \r
+ trgBlockNo = param_get8(Cmd, 4);\r
\r
- if (cmdp == 'o') {\r
+ ctmp = param_getchar(Cmd, 5);\r
+ if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') {\r
+ PrintAndLog("Target key type must be A or B");\r
+ return 1;\r
+ }\r
+ if (ctmp != 'A' && ctmp != 'a')\r
+ trgKeyType = 1;\r
+\r
+ ctmp = param_getchar(Cmd, 6);\r
+ transferToEml |= (ctmp == 't' || ctmp == 'T');\r
+ createDumpFile |= (ctmp == 'd' || ctmp == 'D');\r
+ } else {\r
+ ctmp = param_getchar(Cmd, 4);\r
+ transferToEml |= (ctmp == 't' || ctmp == 'T');\r
+ createDumpFile |= (ctmp == 'd' || ctmp == 'D');\r
+ }\r
+\r
+ PrintAndLog("--nested. sectors:%2d, block no:%3d, key type:%c, eml:%c, dmp=%c ", SectorsCnt, blockNo, keyType?'B':'A', transferToEml?'y':'n', createDumpFile?'y':'n');\r
+ }\r
+\r
+ // one-sector nested\r
+ if (cmdp == 'o') { // ------------------------------------ one sector working\r
PrintAndLog("--target block no:%3d, target key type:%c ", trgBlockNo, trgKeyType?'B':'A');\r
int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true);\r
if (isOK) {\r
else\r
num_to_bytes(key64, 6, &keyBlock[10]);\r
mfEmlSetMem(keyBlock, sectortrailer, 1);\r
+ PrintAndLog("Key transferred to emulator memory.");\r
}\r
} else {\r
PrintAndLog("No valid key found");\r
num_to_bytes(0xa0478cc39091, 6, (uint8_t*)(keyBlock + 11 * 6));\r
num_to_bytes(0x533cb6c723f6, 6, (uint8_t*)(keyBlock + 12 * 6));\r
num_to_bytes(0x8fd0a4f256e9, 6, (uint8_t*)(keyBlock + 13 * 6));\r
+ num_to_bytes(0x1a2b3c4d5e6f, 6, (uint8_t*)(keyBlock + 14 * 6));\r
\r
PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt);\r
for (i = 0; i < SectorsCnt; i++) {\r
for (j = 0; j < 2; j++) {\r
if (e_sector[i].foundKey[j]) continue;\r
\r
- res = mfCheckKeys(FirstBlockOfSector(i), j, true, 6, keyBlock, &key64);\r
+ res = mfCheckKeys(FirstBlockOfSector(i), j, true, NESTED_KEY_COUNT, keyBlock, &key64); \r
\r
if (!res) {\r
e_sector[i].Key[j] = key64;\r
}\r
}\r
}\r
+ \r
+ // get known key from array\r
+ bool keyFound = false;\r
+ if (autosearchKey) {\r
+ for (i = 0; i < SectorsCnt; i++) {\r
+ for (j = 0; j < 2; j++) {\r
+ if (e_sector[i].foundKey[j]) {\r
+ // get known key\r
+ blockNo = i * 4;\r
+ keyType = j;\r
+ num_to_bytes(e_sector[i].Key[j], 6, key);\r
+ \r
+ keyFound = true;\r
+ break;\r
+ }\r
+ }\r
+ if (keyFound) break;\r
+ } \r
+\r
+ // Can't found a key....\r
+ if (!keyFound) {\r
+ PrintAndLog("Can't found any of the known keys.");\r
+ return 4;\r
+ }\r
+ PrintAndLog("--auto key. block no:%3d, key type:%c key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));\r
+ }\r
\r
// nested sectors\r
iterations = 0;\r
}\r
}\r
\r
- printf("Time in nested: %1.3f (%1.3f sec per key)\n\n", ((float)(msclock() - msclock1))/1000.0, ((float)(msclock() - msclock1))/iterations/1000.0);\r
+ // print nested statistic\r
+ PrintAndLog("\n\n-----------------------------------------------\nNested statistic:\nIterations count: %d", iterations);\r
+ PrintAndLog("Time in nested: %1.3f (%1.3f sec per key)", ((float)(msclock() - msclock1))/1000.0, ((float)(msclock() - msclock1))/iterations/1000.0);\r
+ \r
+ // check if we have unrecognized keys\r
+ bool notFoundKeys = false;\r
+ for (i = 0; i < SectorsCnt; i++) {\r
+ for (j = 0; j < 2; j++) {\r
+ if (!e_sector[i].foundKey[j]) {\r
+ notFoundKeys = true;\r
+ break;\r
+ }\r
+ }\r
+ if (notFoundKeys) break;\r
+ } \r
+ \r
+ if (notFoundKeys) {\r
+ PrintAndLog("-----------------------------------------------\n");\r
+ PrintAndLog("We have unrecognized keys. Trying to check if we have this keys on key buffer...");\r
+\r
+ // fill keyBlock with known keys\r
+ int cnt = 0;\r
+ for (i = 0; i < SectorsCnt; i++) {\r
+ for (j = 0; j < 2; j++) {\r
+ if (e_sector[i].foundKey[j]) {\r
+ // try to insert key to keyBlock \r
+ if (cnt < NESTED_KEY_COUNT) {\r
+\r
+ // search for dublicates\r
+ bool dubl = false;\r
+ for (int v = 0; v < NESTED_KEY_COUNT; v++) {\r
+ if (e_sector[i].Key[j] == bytes_to_num((uint8_t*)(keyBlock + v * 6), 6)) {\r
+ dubl = true;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ // insert\r
+ if (!dubl) {\r
+ num_to_bytes(e_sector[i].Key[j], 6, (uint8_t*)(keyBlock + cnt * 6));\r
+ cnt++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
- PrintAndLog("-----------------------------------------------\nIterations count: %d\n\n", iterations);\r
- //print them\r
+ // try to auth with known keys to not recognized sectors keys\r
+ PrintAndLog("Testing keys. Sector count=%d known keys count:%d", SectorsCnt, cnt);\r
+ for (i = 0; i < SectorsCnt; i++) {\r
+ for (j = 0; j < 2; j++) {\r
+ if (e_sector[i].foundKey[j]) continue;\r
+\r
+ res = mfCheckKeys(FirstBlockOfSector(i), j, true, cnt, keyBlock, &key64); \r
+\r
+ if (!res) {\r
+ e_sector[i].Key[j] = key64;\r
+ e_sector[i].foundKey[j] = 1;\r
+ }\r
+ }\r
+ } \r
+ \r
+ } // if (notFoundKeys)\r
+ \r
+ // print result\r
PrintAndLog("|---|----------------|---|----------------|---|");\r
PrintAndLog("|sec|key A |res|key B |res|");\r
PrintAndLog("|---|----------------|---|----------------|---|");\r
}\r
PrintAndLog("|---|----------------|---|----------------|---|");\r
\r
- // transfer them to the emulator\r
+ // transfer keys to the emulator memory\r
if (transferToEml) {\r
for (i = 0; i < SectorsCnt; i++) {\r
mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);\r
num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);\r
mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);\r
}\r
+ PrintAndLog("Keys transferred to emulator memory.");\r
}\r
\r
// Create dump file\r
\r
if (param_getchar(Cmd, 0)=='*') {\r
blockNo = 3;\r
- switch(param_getchar(Cmd+1, 0)) {\r
- case '0': SectorsCnt = 5; break;\r
- case '1': SectorsCnt = 16; break;\r
- case '2': SectorsCnt = 32; break;\r
- case '4': SectorsCnt = 40; break;\r
- default: SectorsCnt = 16;\r
- }\r
+ SectorsCnt = ParamCardSizeSectors(param_getchar(Cmd + 1, 0));\r
}\r
else\r
blockNo = param_get8(Cmd, 0);\r
return 0;\r
}\r
\r
-static int ParamGetCardSize(const char c) {\r
- int numBlocks = 16 * 4;\r
- switch (c) {\r
- case '0' : numBlocks = 5 * 4; break;\r
- case '2' : numBlocks = 32 * 4; break;\r
- case '4' : numBlocks = 32 * 4 + 8 * 16; break;\r
- default: numBlocks = 16 * 4;\r
- }\r
- return numBlocks;\r
-}\r
-\r
int CmdHF14AMfCWipe(const char *Cmd)\r
{\r
int res, gen = 0;\r
if ((gen != 1) && (gen != 2)) \r
return 1;\r
\r
- numBlocks = ParamGetCardSize(param_getchar(Cmd, 0));\r
+ numBlocks = ParamCardSizeBlocks(param_getchar(Cmd, 0));\r
\r
char cmdp = 0;\r
while(param_getchar(Cmd, cmdp) != 0x00){\r