PrintAndLog(" hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file");\r
return 0;\r
}\r
+int usage_hf14_keybrute(void){\r
+ PrintAndLog("J_Run's 2nd phase of multiple sector nested authentication key recovery");\r
+ PrintAndLog("You have a known 4 last bytes of a key recovered with mf_nonce_brute tool.");\r
+ PrintAndLog("First 2 bytes of key will be bruteforced");\r
+ PrintAndLog("");\r
+ PrintAndLog("Usage: hf mf keybrute [h] <block number> <A|B> <key>");\r
+ PrintAndLog("options:");\r
+ PrintAndLog(" h this help");\r
+ PrintAndLog(" <block number> target block number");\r
+ PrintAndLog(" <A|B> target key type");\r
+ PrintAndLog(" <key> candidate key from mf_nonce_brute tool");\r
+ PrintAndLog("samples:");\r
+ PrintAndLog(" hf mf keybrute 1 A 000011223344");\r
+ return 0;\r
+}\r
\r
int CmdHF14AMifare(const char *Cmd) {\r
uint32_t uid = 0;\r
return 0;\r
}\r
\r
+int CmdHF14AMfKeyBrute(const char *Cmd) {\r
+\r
+ uint8_t blockNo = 0, keytype = 0;\r
+ uint8_t key[6] = {0, 0, 0, 0, 0, 0};\r
+ uint64_t foundkey = 0;\r
+ \r
+ char cmdp = param_getchar(Cmd, 0); \r
+ if ( cmdp == 'H' || cmdp == 'h') return usage_hf14_keybrute();\r
+ \r
+ // block number\r
+ blockNo = param_get8(Cmd, 0); \r
+ \r
+ // keytype\r
+ cmdp = param_getchar(Cmd, 1);\r
+ if (cmdp == 'B' || cmdp == 'b') keytype = 1;\r
+ \r
+ // key\r
+ if (param_gethex(Cmd, 2, key, 12)) return usage_hf14_keybrute();\r
+ \r
+ clock_t t1 = clock();\r
+ time_t start, end;\r
+ time(&start);\r
+ \r
+ if (mfKeyBrute( blockNo, keytype, key, &foundkey))\r
+ PrintAndLog("Found valid key: %012"llx" \n", foundkey);\r
+ else\r
+ PrintAndLog("Key not found");\r
+ \r
+ t1 = clock() - t1;\r
+ time(&end);\r
+ unsigned long elapsed_time = difftime(end, start); \r
+ if ( t1 > 0 )\r
+ PrintAndLog("\nTime in keybrute: %.0f ticks %u seconds\n", (float)t1, elapsed_time);\r
+ \r
+ return 0; \r
+}\r
+\r
void printKeyTable( uint8_t sectorscnt, sector *e_sector ){\r
PrintAndLog("|---|----------------|---|----------------|---|");\r
PrintAndLog("|sec|key A |res|key B |res|");\r
{"mifare", CmdHF14AMifare, 0, "Read parity error messages."},\r
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},\r
{"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},\r
+ {"keybrute", CmdHF14AMfKeyBrute, 0, "J_Run's 2nd phase of multiple sector nested authentication key recovery"},\r
{"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},\r
{"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},\r
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},\r
*key = bytes_to_num(resp.d.asBytes, 6);\r
return 0;\r
}\r
+// PM3 imp of J-Run mf_key_brute (part 2)\r
+// ref: https://github.com/J-Run/mf_key_brute\r
+int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey){\r
+\r
+ #define KEYS_IN_BLOCK 85\r
+ #define KEYBLOCK_SIZE 510\r
+ #define CANDIDATE_SIZE 0xFFFF * 6\r
+ uint8_t found = FALSE;\r
+ uint64_t key64 = 0;\r
+ uint8_t candidates[CANDIDATE_SIZE] = {0x00};\r
+ uint8_t keyBlock[KEYBLOCK_SIZE] = {0x00};\r
+\r
+ memset(candidates, 0, sizeof(candidates));\r
+ memset(keyBlock, 0, sizeof(keyBlock));\r
+ \r
+ // Generate all possible keys for the first two unknown bytes.\r
+ for (uint16_t i = 0; i < 0xFFFF; ++i) { \r
+ uint32_t j = i * 6; \r
+ candidates[0 + j] = i >> 8; \r
+ candidates[1 + j] = i;\r
+ candidates[2 + j] = key[2];\r
+ candidates[3 + j] = key[3];\r
+ candidates[4 + j] = key[4];\r
+ candidates[5 + j] = key[5];\r
+ }\r
+ uint32_t counter, i;\r
+ for ( i = 0, counter = 1; i < CANDIDATE_SIZE; i += KEYBLOCK_SIZE, ++counter){\r
+\r
+ key64 = 0;\r
+ \r
+ // copy candidatekeys to test key block\r
+ memcpy(keyBlock, candidates + i, KEYBLOCK_SIZE);\r
+\r
+ // check a block of generated candidate keys.\r
+ if (!mfCheckKeys(blockNo, keyType, TRUE, KEYS_IN_BLOCK, keyBlock, &key64)) {\r
+ *resultkey = key64;\r
+ found = TRUE;\r
+ break;\r
+ }\r
+ \r
+ // progress \r
+ if ( counter % 20 == 0 )\r
+ PrintAndLog("tried : %s.. \t %u keys", sprint_hex(candidates + i, 6), counter * KEYS_IN_BLOCK );\r
+ }\r
+ return found;\r
+}\r
+\r
\r
// EMULATOR\r
\r
\r
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);\r
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);\r
+int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey);\r
\r
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);\r
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);\r