mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
ADD: J-Run's 2nd phase tool mf_key_brute ref: https://github.com/J-Run/mf_key_brute Estimated time to search keyspace is ~18min.
J_Run's 2nd phase of multiple sector nested authentication key recovery You have a known 4 last bytes of a key recovered with mf_nonce_brute tool. First 2 bytes of key will be bruteforced Usage: hf mf keybrute [h] <block number> <A|B> <key> options: h this help <block number> target block number <A|B> target key type <key> candidate key from mf_nonce_brute tool samples: hf mf keybrute 1 A 000011223344
This commit is contained in:
parent
e55eda39cd
commit
d9ed4e1914
4 changed files with 102 additions and 0 deletions
|
@ -125,6 +125,21 @@ int usage_hf14_chk(void){
|
||||||
PrintAndLog(" hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file");
|
PrintAndLog(" hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int usage_hf14_keybrute(void){
|
||||||
|
PrintAndLog("J_Run's 2nd phase of multiple sector nested authentication key recovery");
|
||||||
|
PrintAndLog("You have a known 4 last bytes of a key recovered with mf_nonce_brute tool.");
|
||||||
|
PrintAndLog("First 2 bytes of key will be bruteforced");
|
||||||
|
PrintAndLog("");
|
||||||
|
PrintAndLog("Usage: hf mf keybrute [h] <block number> <A|B> <key>");
|
||||||
|
PrintAndLog("options:");
|
||||||
|
PrintAndLog(" h this help");
|
||||||
|
PrintAndLog(" <block number> target block number");
|
||||||
|
PrintAndLog(" <A|B> target key type");
|
||||||
|
PrintAndLog(" <key> candidate key from mf_nonce_brute tool");
|
||||||
|
PrintAndLog("samples:");
|
||||||
|
PrintAndLog(" hf mf keybrute 1 A 000011223344");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int CmdHF14AMifare(const char *Cmd) {
|
int CmdHF14AMifare(const char *Cmd) {
|
||||||
uint32_t uid = 0;
|
uint32_t uid = 0;
|
||||||
|
@ -1639,6 +1654,43 @@ int CmdHF14AMfDbg(const char *Cmd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CmdHF14AMfKeyBrute(const char *Cmd) {
|
||||||
|
|
||||||
|
uint8_t blockNo = 0, keytype = 0;
|
||||||
|
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
uint64_t foundkey = 0;
|
||||||
|
|
||||||
|
char cmdp = param_getchar(Cmd, 0);
|
||||||
|
if ( cmdp == 'H' || cmdp == 'h') return usage_hf14_keybrute();
|
||||||
|
|
||||||
|
// block number
|
||||||
|
blockNo = param_get8(Cmd, 0);
|
||||||
|
|
||||||
|
// keytype
|
||||||
|
cmdp = param_getchar(Cmd, 1);
|
||||||
|
if (cmdp == 'B' || cmdp == 'b') keytype = 1;
|
||||||
|
|
||||||
|
// key
|
||||||
|
if (param_gethex(Cmd, 2, key, 12)) return usage_hf14_keybrute();
|
||||||
|
|
||||||
|
clock_t t1 = clock();
|
||||||
|
time_t start, end;
|
||||||
|
time(&start);
|
||||||
|
|
||||||
|
if (mfKeyBrute( blockNo, keytype, key, &foundkey))
|
||||||
|
PrintAndLog("Found valid key: %012"llx" \n", foundkey);
|
||||||
|
else
|
||||||
|
PrintAndLog("Key not found");
|
||||||
|
|
||||||
|
t1 = clock() - t1;
|
||||||
|
time(&end);
|
||||||
|
unsigned long elapsed_time = difftime(end, start);
|
||||||
|
if ( t1 > 0 )
|
||||||
|
PrintAndLog("\nTime in keybrute: %.0f ticks %u seconds\n", (float)t1, elapsed_time);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void printKeyTable( uint8_t sectorscnt, sector *e_sector ){
|
void printKeyTable( uint8_t sectorscnt, sector *e_sector ){
|
||||||
PrintAndLog("|---|----------------|---|----------------|---|");
|
PrintAndLog("|---|----------------|---|----------------|---|");
|
||||||
PrintAndLog("|sec|key A |res|key B |res|");
|
PrintAndLog("|sec|key A |res|key B |res|");
|
||||||
|
@ -2383,6 +2435,7 @@ static command_t CommandTable[] = {
|
||||||
{"mifare", CmdHF14AMifare, 0, "Read parity error messages."},
|
{"mifare", CmdHF14AMifare, 0, "Read parity error messages."},
|
||||||
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
|
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
|
||||||
{"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},
|
{"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},
|
||||||
|
{"keybrute", CmdHF14AMfKeyBrute, 0, "J_Run's 2nd phase of multiple sector nested authentication key recovery"},
|
||||||
{"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
{"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
||||||
{"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},
|
{"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},
|
||||||
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},
|
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},
|
||||||
|
|
|
@ -44,6 +44,7 @@ int CmdHF14AMfNested(const char* cmd);
|
||||||
int CmdHF14AMfNestedHard(const char *Cmd);
|
int CmdHF14AMfNestedHard(const char *Cmd);
|
||||||
int CmdHF14AMfSniff(const char* cmd);
|
int CmdHF14AMfSniff(const char* cmd);
|
||||||
int CmdHF14AMf1kSim(const char* cmd);
|
int CmdHF14AMf1kSim(const char* cmd);
|
||||||
|
int CmdHF14AMfKeyBrute(const char *Cmd);
|
||||||
int CmdHF14AMfEClear(const char* cmd);
|
int CmdHF14AMfEClear(const char* cmd);
|
||||||
int CmdHF14AMfEGet(const char* cmd);
|
int CmdHF14AMfEGet(const char* cmd);
|
||||||
int CmdHF14AMfESet(const char* cmd);
|
int CmdHF14AMfESet(const char* cmd);
|
||||||
|
|
|
@ -203,6 +203,53 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key
|
||||||
*key = bytes_to_num(resp.d.asBytes, 6);
|
*key = bytes_to_num(resp.d.asBytes, 6);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
// PM3 imp of J-Run mf_key_brute (part 2)
|
||||||
|
// ref: https://github.com/J-Run/mf_key_brute
|
||||||
|
int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey){
|
||||||
|
|
||||||
|
#define KEYS_IN_BLOCK 85
|
||||||
|
#define KEYBLOCK_SIZE 510
|
||||||
|
#define CANDIDATE_SIZE 0xFFFF * 6
|
||||||
|
uint8_t found = FALSE;
|
||||||
|
uint64_t key64 = 0;
|
||||||
|
uint8_t candidates[CANDIDATE_SIZE] = {0x00};
|
||||||
|
uint8_t keyBlock[KEYBLOCK_SIZE] = {0x00};
|
||||||
|
|
||||||
|
memset(candidates, 0, sizeof(candidates));
|
||||||
|
memset(keyBlock, 0, sizeof(keyBlock));
|
||||||
|
|
||||||
|
// Generate all possible keys for the first two unknown bytes.
|
||||||
|
for (uint16_t i = 0; i < 0xFFFF; ++i) {
|
||||||
|
uint32_t j = i * 6;
|
||||||
|
candidates[0 + j] = i >> 8;
|
||||||
|
candidates[1 + j] = i;
|
||||||
|
candidates[2 + j] = key[2];
|
||||||
|
candidates[3 + j] = key[3];
|
||||||
|
candidates[4 + j] = key[4];
|
||||||
|
candidates[5 + j] = key[5];
|
||||||
|
}
|
||||||
|
uint32_t counter, i;
|
||||||
|
for ( i = 0, counter = 1; i < CANDIDATE_SIZE; i += KEYBLOCK_SIZE, ++counter){
|
||||||
|
|
||||||
|
key64 = 0;
|
||||||
|
|
||||||
|
// copy candidatekeys to test key block
|
||||||
|
memcpy(keyBlock, candidates + i, KEYBLOCK_SIZE);
|
||||||
|
|
||||||
|
// check a block of generated candidate keys.
|
||||||
|
if (!mfCheckKeys(blockNo, keyType, TRUE, KEYS_IN_BLOCK, keyBlock, &key64)) {
|
||||||
|
*resultkey = key64;
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// progress
|
||||||
|
if ( counter % 20 == 0 )
|
||||||
|
PrintAndLog("tried : %s.. \t %u keys", sprint_hex(candidates + i, 6), counter * KEYS_IN_BLOCK );
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// EMULATOR
|
// EMULATOR
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ extern char logHexFileName[FILE_PATH_SIZE];
|
||||||
|
|
||||||
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);
|
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);
|
||||||
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);
|
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);
|
||||||
|
int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey);
|
||||||
|
|
||||||
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||||
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
|
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue