mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 05:13:46 -07:00
hf mf isen: add collect_fm11rf08s_without_backdoor option
This commit is contained in:
parent
c4b8569d87
commit
830549b474
6 changed files with 239 additions and 104 deletions
|
@ -1778,7 +1778,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_ACQ_STATIC_ENCRYPTED_NONCES: {
|
case CMD_HF_MIFARE_ACQ_STATIC_ENCRYPTED_NONCES: {
|
||||||
MifareAcquireStaticEncryptedNonces(packet->oldarg[0], packet->data.asBytes, true);
|
MifareAcquireStaticEncryptedNonces(packet->oldarg[0], packet->data.asBytes, true, packet->oldarg[1], packet->oldarg[2]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_ACQ_NONCES: {
|
case CMD_HF_MIFARE_ACQ_NONCES: {
|
||||||
|
|
|
@ -1036,7 +1036,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
// acquire static encrypted nonces in order to perform the attack described in
|
// acquire static encrypted nonces in order to perform the attack described in
|
||||||
// Philippe Teuwen, "MIFARE Classic: exposing the static encrypted nonce variant"
|
// Philippe Teuwen, "MIFARE Classic: exposing the static encrypted nonce variant"
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int MifareAcquireStaticEncryptedNonces(uint32_t flags, const uint8_t *key, bool reply) {
|
int MifareAcquireStaticEncryptedNonces(uint32_t flags, const uint8_t *key, bool reply, uint8_t first_block_no, uint8_t first_key_type) {
|
||||||
struct Crypto1State mpcs = {0, 0};
|
struct Crypto1State mpcs = {0, 0};
|
||||||
struct Crypto1State *pcs;
|
struct Crypto1State *pcs;
|
||||||
pcs = &mpcs;
|
pcs = &mpcs;
|
||||||
|
@ -1055,6 +1055,10 @@ int MifareAcquireStaticEncryptedNonces(uint32_t flags, const uint8_t *key, bool
|
||||||
uint8_t buf[MIFARE_BLOCK_SIZE] = {0x00};
|
uint8_t buf[MIFARE_BLOCK_SIZE] = {0x00};
|
||||||
uint64_t ui64Key = bytes_to_num(key, 6);
|
uint64_t ui64Key = bytes_to_num(key, 6);
|
||||||
bool with_data = flags & 1;
|
bool with_data = flags & 1;
|
||||||
|
bool without_backdoor = (flags >> 1) & 1;
|
||||||
|
if (with_data && without_backdoor) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
uint32_t cuid = 0;
|
uint32_t cuid = 0;
|
||||||
int16_t isOK = PM3_SUCCESS;
|
int16_t isOK = PM3_SUCCESS;
|
||||||
uint8_t cascade_levels = 0;
|
uint8_t cascade_levels = 0;
|
||||||
|
@ -1072,121 +1076,230 @@ int MifareAcquireStaticEncryptedNonces(uint32_t flags, const uint8_t *key, bool
|
||||||
|
|
||||||
LED_C_ON();
|
LED_C_ON();
|
||||||
|
|
||||||
for (uint16_t sec = 0; sec < MIFARE_1K_MAXSECTOR + 1; sec++) {
|
if (without_backdoor) {
|
||||||
uint16_t sec_gap = sec;
|
uint32_t nt1 = 0;
|
||||||
if (sec >= MIFARE_1K_MAXSECTOR) {
|
|
||||||
// gap between user blocks and advanced verification method blocks
|
iso14a_card_select_t card_info;
|
||||||
sec_gap += 16;
|
if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == 0) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (ALL)");
|
||||||
|
isOK = PM3_ERFTRANS;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
uint16_t blockNo = sec_gap * 4;
|
switch (card_info.uidlen) {
|
||||||
for (uint8_t keyType = 0; keyType < 2; keyType++) {
|
case 4 :
|
||||||
// Test if the action was cancelled
|
cascade_levels = 1;
|
||||||
if (BUTTON_PRESS()) {
|
|
||||||
isOK = PM3_EOPABORTED;
|
|
||||||
break;
|
break;
|
||||||
|
case 7 :
|
||||||
|
cascade_levels = 2;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
cascade_levels = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mifare_classic_authex_cmd(pcs, cuid, first_block_no, MIFARE_AUTH_KEYA + first_key_type, ui64Key, AUTH_FIRST, &nt1, NULL, NULL, NULL, false, false)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth1 error");
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
|
goto out;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, MIFARE_AUTH_KEYA + first_key_type, first_block_no, receivedAnswer, sizeof(receivedAnswer), par_enc, NULL);
|
||||||
|
if (len != 4) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth2 error len=%d", len);
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
uint32_t nt_enc = bytes_to_num(receivedAnswer, 4);
|
||||||
|
|
||||||
|
// send some crap to fail auth
|
||||||
|
CHK_TIMEOUT();
|
||||||
|
|
||||||
|
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (UID)");
|
||||||
|
isOK = PM3_ERFTRANS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (mifare_classic_authex_cmd(pcs, cuid, first_block_no, MIFARE_AUTH_KEYA + first_key_type, ui64Key, AUTH_FIRST, &nt1, NULL, NULL, NULL, false, false)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth1 error");
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
|
goto out;
|
||||||
|
};
|
||||||
|
// Recover clear nt
|
||||||
|
struct Crypto1State mpcs_tmp = {0, 0};
|
||||||
|
struct Crypto1State *pcs_tmp = &mpcs_tmp;
|
||||||
|
crypto1_init(pcs_tmp, ui64Key);
|
||||||
|
uint32_t nt = crypto1_word(pcs_tmp, nt_enc ^ cuid, 1) ^ nt_enc;
|
||||||
|
int dist = nonce_distance(nt, nt1);
|
||||||
|
// ref dist is not always stable. Adjust physical distance to maximise ref dist, and try values around estimated nonces...
|
||||||
|
Dbprintf("Block %2i key %i nested nT=%08x first nT=%08x dist=%i", first_block_no, first_key_type, nt, nt1, dist);
|
||||||
|
|
||||||
|
for (uint16_t sec = 0; sec < MIFARE_1K_MAXSECTOR + 1; sec++) {
|
||||||
|
uint16_t sec_gap = sec;
|
||||||
|
if (sec >= MIFARE_1K_MAXSECTOR) {
|
||||||
|
// gap between user blocks and advanced verification method blocks
|
||||||
|
sec_gap += 16;
|
||||||
}
|
}
|
||||||
if (have_uid == false) { // need a full select cycle to get the uid first
|
uint16_t blockNo = sec_gap * 4;
|
||||||
iso14a_card_select_t card_info;
|
for (uint8_t keyType = 0; keyType < 2; keyType++) {
|
||||||
if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == 0) {
|
// Test if the action was cancelled
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (ALL)");
|
if (BUTTON_PRESS()) {
|
||||||
isOK = PM3_ERFTRANS;
|
isOK = PM3_EOPABORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = mifare_sendcmd_short(pcs, AUTH_NESTED, MIFARE_AUTH_KEYA + keyType, blockNo, receivedAnswer, sizeof(receivedAnswer), par_enc, NULL);
|
||||||
|
if (len != 4) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth2 error len=%d", len);
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
switch (card_info.uidlen) {
|
// store nt_enc
|
||||||
case 4 :
|
memcpy(buf + (keyType * 8) + 4, receivedAnswer, 4);
|
||||||
cascade_levels = 1;
|
nt_enc = bytes_to_num(receivedAnswer, 4);
|
||||||
break;
|
uint8_t nt_par_err = ((((par_enc[0] >> 7) & 1) ^ oddparity8((nt_enc >> 24) & 0xFF)) << 3 |
|
||||||
case 7 :
|
(((par_enc[0] >> 6) & 1) ^ oddparity8((nt_enc >> 16) & 0xFF)) << 2 |
|
||||||
cascade_levels = 2;
|
(((par_enc[0] >> 5) & 1) ^ oddparity8((nt_enc >> 8) & 0xFF)) << 1 |
|
||||||
break;
|
(((par_enc[0] >> 4) & 1) ^ oddparity8((nt_enc >> 0) & 0xFF)));
|
||||||
case 10:
|
// Dbprintf("Sec %2i key %i {nT}=%02x%02x%02x%02x perr=%x", sec, keyType, receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], nt_par_err);
|
||||||
cascade_levels = 3;
|
// store nt_par_err
|
||||||
break;
|
buf[(keyType * 8) + 2] = nt_par_err;
|
||||||
default:
|
buf[(keyType * 8) + 3] = 0xAA; // extra check to tell we have nt/nt_enc/par_err
|
||||||
break;
|
|
||||||
}
|
// send some crap to fail auth
|
||||||
have_uid = true;
|
CHK_TIMEOUT();
|
||||||
} else { // no need for anticollision. We can directly select the card
|
|
||||||
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (UID)");
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (UID)");
|
||||||
isOK = PM3_ERFTRANS;
|
isOK = PM3_ERFTRANS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (mifare_classic_authex_cmd(pcs, cuid, first_block_no, MIFARE_AUTH_KEYA + first_key_type, ui64Key, AUTH_FIRST, &nt1, NULL, NULL, NULL, false, false)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth1 error");
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
|
goto out;
|
||||||
|
};
|
||||||
|
nt1 = rewind_nonce(nt1, dist);
|
||||||
|
num_to_bytes(nt1 >> 16, 2, buf + (keyType * 8));
|
||||||
|
emlSetMem_xt(buf, (CARD_MEMORY_RF08S_OFFSET / MIFARE_BLOCK_SIZE) + sec, 1, MIFARE_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
uint32_t nt1 = 0;
|
} else {
|
||||||
if (mifare_classic_authex_cmd(pcs, cuid, blockNo, MIFARE_AUTH_KEYA + keyType + 4, ui64Key, AUTH_FIRST, &nt1, NULL, NULL, NULL, false, false)) {
|
for (uint16_t sec = 0; sec < MIFARE_1K_MAXSECTOR + 1; sec++) {
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth1 error");
|
uint16_t sec_gap = sec;
|
||||||
isOK = PM3_ESOFT;
|
if (sec >= MIFARE_1K_MAXSECTOR) {
|
||||||
goto out;
|
// gap between user blocks and advanced verification method blocks
|
||||||
};
|
sec_gap += 16;
|
||||||
if ((with_data) && (keyType == 0)) {
|
}
|
||||||
uint8_t data[16];
|
uint16_t blockNo = sec_gap * 4;
|
||||||
uint8_t blocks = 4;
|
for (uint8_t keyType = 0; keyType < 2; keyType++) {
|
||||||
if (blockNo >= MIFARE_1K_MAXSECTOR * 4) {
|
// Test if the action was cancelled
|
||||||
// special RF08S advanced authentication blocks, let's dump in emulator just in case
|
if (BUTTON_PRESS()) {
|
||||||
blocks = 8;
|
isOK = PM3_EOPABORTED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
for (uint16_t tb = blockNo; tb < blockNo + blocks; tb++) {
|
if (have_uid == false) { // need a full select cycle to get the uid first
|
||||||
memset(data, 0x00, sizeof(data));
|
iso14a_card_select_t card_info;
|
||||||
int res = mifare_classic_readblock(pcs, tb, data);
|
if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == 0) {
|
||||||
if (res == 1) {
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (ALL)");
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Read error");
|
isOK = PM3_ERFTRANS;
|
||||||
isOK = PM3_ESOFT;
|
goto out;
|
||||||
|
}
|
||||||
|
switch (card_info.uidlen) {
|
||||||
|
case 4 :
|
||||||
|
cascade_levels = 1;
|
||||||
|
break;
|
||||||
|
case 7 :
|
||||||
|
cascade_levels = 2;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
cascade_levels = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
have_uid = true;
|
||||||
|
} else { // no need for anticollision. We can directly select the card
|
||||||
|
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (UID)");
|
||||||
|
isOK = PM3_ERFTRANS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
emlSetMem_xt(data, tb, 1, 16);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// nested authentication
|
|
||||||
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, MIFARE_AUTH_KEYA + keyType + 4, blockNo, receivedAnswer, sizeof(receivedAnswer), par_enc, NULL);
|
|
||||||
if (len != 4) {
|
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth2 error len=%d", len);
|
|
||||||
isOK = PM3_ESOFT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
uint32_t nt_enc = bytes_to_num(receivedAnswer, 4);
|
|
||||||
crypto1_init(pcs, ui64Key);
|
|
||||||
uint32_t nt = crypto1_word(pcs, nt_enc ^ cuid, 1) ^ nt_enc;
|
|
||||||
// Dbprintf("Sec %2i key %i nT=%08x", sec, keyType + 4, nt);
|
|
||||||
// store nt (first half)
|
|
||||||
num_to_bytes(nt >> 16, 2, buf + (keyType * 8));
|
|
||||||
// send some crap to fail auth
|
|
||||||
uint8_t nack[] = {0x04};
|
|
||||||
ReaderTransmit(nack, sizeof(nack), NULL);
|
|
||||||
|
|
||||||
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
uint32_t nt1 = 0;
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (UID)");
|
if (mifare_classic_authex_cmd(pcs, cuid, blockNo, MIFARE_AUTH_KEYA + keyType + 4, ui64Key, AUTH_FIRST, &nt1, NULL, NULL, NULL, false, false)) {
|
||||||
isOK = PM3_ERFTRANS;
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth1 error");
|
||||||
goto out;
|
isOK = PM3_ESOFT;
|
||||||
}
|
goto out;
|
||||||
if (mifare_classic_authex_cmd(pcs, cuid, blockNo, MIFARE_AUTH_KEYA + keyType + 4, ui64Key, AUTH_FIRST, &nt1, NULL, NULL, NULL, false, false)) {
|
};
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth1 error");
|
if ((with_data) && (keyType == 0)) {
|
||||||
isOK = PM3_ESOFT;
|
uint8_t data[16];
|
||||||
goto out;
|
uint8_t blocks = 4;
|
||||||
};
|
if (blockNo >= MIFARE_1K_MAXSECTOR * 4) {
|
||||||
|
// special RF08S advanced authentication blocks, let's dump in emulator just in case
|
||||||
|
blocks = 8;
|
||||||
|
}
|
||||||
|
for (uint16_t tb = blockNo; tb < blockNo + blocks; tb++) {
|
||||||
|
memset(data, 0x00, sizeof(data));
|
||||||
|
int res = mifare_classic_readblock(pcs, tb, data);
|
||||||
|
if (res == 1) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Read error");
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
emlSetMem_xt(data, tb, 1, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// nested authentication
|
||||||
|
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, MIFARE_AUTH_KEYA + keyType + 4, blockNo, receivedAnswer, sizeof(receivedAnswer), par_enc, NULL);
|
||||||
|
if (len != 4) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth2 error len=%d", len);
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
uint32_t nt_enc = bytes_to_num(receivedAnswer, 4);
|
||||||
|
crypto1_init(pcs, ui64Key);
|
||||||
|
uint32_t nt = crypto1_word(pcs, nt_enc ^ cuid, 1) ^ nt_enc;
|
||||||
|
// Dbprintf("Sec %2i key %i nT=%08x", sec, keyType + 4, nt);
|
||||||
|
// store nt (first half)
|
||||||
|
num_to_bytes(nt >> 16, 2, buf + (keyType * 8));
|
||||||
|
// send some crap to fail auth
|
||||||
|
CHK_TIMEOUT();
|
||||||
|
|
||||||
// nested authentication on regular keytype
|
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||||
len = mifare_sendcmd_short(pcs, AUTH_NESTED, MIFARE_AUTH_KEYA + keyType, blockNo, receivedAnswer, sizeof(receivedAnswer), par_enc, NULL);
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Can't select card (UID)");
|
||||||
if (len != 4) {
|
isOK = PM3_ERFTRANS;
|
||||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth2 error len=%d", len);
|
goto out;
|
||||||
isOK = PM3_ESOFT;
|
}
|
||||||
goto out;
|
if (mifare_classic_authex_cmd(pcs, cuid, blockNo, MIFARE_AUTH_KEYA + keyType + 4, ui64Key, AUTH_FIRST, &nt1, NULL, NULL, NULL, false, false)) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth1 error");
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
|
goto out;
|
||||||
|
};
|
||||||
|
|
||||||
|
// nested authentication on regular keytype
|
||||||
|
len = mifare_sendcmd_short(pcs, AUTH_NESTED, MIFARE_AUTH_KEYA + keyType, blockNo, receivedAnswer, sizeof(receivedAnswer), par_enc, NULL);
|
||||||
|
if (len != 4) {
|
||||||
|
if (g_dbglevel >= DBG_ERROR) Dbprintf("AcquireStaticEncryptedNonces: Auth2 error len=%d", len);
|
||||||
|
isOK = PM3_ESOFT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
// store nt_enc
|
||||||
|
memcpy(buf + (keyType * 8) + 4, receivedAnswer, 4);
|
||||||
|
nt_enc = bytes_to_num(receivedAnswer, 4);
|
||||||
|
uint8_t nt_par_err = ((((par_enc[0] >> 7) & 1) ^ oddparity8((nt_enc >> 24) & 0xFF)) << 3 |
|
||||||
|
(((par_enc[0] >> 6) & 1) ^ oddparity8((nt_enc >> 16) & 0xFF)) << 2 |
|
||||||
|
(((par_enc[0] >> 5) & 1) ^ oddparity8((nt_enc >> 8) & 0xFF)) << 1 |
|
||||||
|
(((par_enc[0] >> 4) & 1) ^ oddparity8((nt_enc >> 0) & 0xFF)));
|
||||||
|
// Dbprintf("Sec %2i key %i {nT}=%02x%02x%02x%02x perr=%x", sec, keyType, receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], nt_par_err);
|
||||||
|
// store nt_par_err
|
||||||
|
buf[(keyType * 8) + 2] = nt_par_err;
|
||||||
|
buf[(keyType * 8) + 3] = 0xAA; // extra check to tell we have nt/nt_enc/par_err
|
||||||
|
emlSetMem_xt(buf, (CARD_MEMORY_RF08S_OFFSET / MIFARE_BLOCK_SIZE) + sec, 1, MIFARE_BLOCK_SIZE);
|
||||||
|
// send some crap to fail auth
|
||||||
|
CHK_TIMEOUT();
|
||||||
}
|
}
|
||||||
// store nt_enc
|
|
||||||
memcpy(buf + (keyType * 8) + 4, receivedAnswer, 4);
|
|
||||||
nt_enc = bytes_to_num(receivedAnswer, 4);
|
|
||||||
uint8_t nt_par_err = ((((par_enc[0] >> 7) & 1) ^ oddparity8((nt_enc >> 24) & 0xFF)) << 3 |
|
|
||||||
(((par_enc[0] >> 6) & 1) ^ oddparity8((nt_enc >> 16) & 0xFF)) << 2 |
|
|
||||||
(((par_enc[0] >> 5) & 1) ^ oddparity8((nt_enc >> 8) & 0xFF)) << 1 |
|
|
||||||
(((par_enc[0] >> 4) & 1) ^ oddparity8((nt_enc >> 0) & 0xFF)));
|
|
||||||
// Dbprintf("Sec %2i key %i {nT}=%02x%02x%02x%02x perr=%x", sec, keyType, receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], nt_par_err);
|
|
||||||
// store nt_par_err
|
|
||||||
buf[(keyType * 8) + 2] = nt_par_err;
|
|
||||||
buf[(keyType * 8) + 3] = 0xAA; // extra check to tell we have nt/nt_enc/par_err
|
|
||||||
emlSetMem_xt(buf, (CARD_MEMORY_RF08S_OFFSET / MIFARE_BLOCK_SIZE) + sec, 1, MIFARE_BLOCK_SIZE);
|
|
||||||
// send some crap to fail auth
|
|
||||||
ReaderTransmit(nack, sizeof(nack), NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
@ -3127,7 +3240,8 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
|
||||||
goto OUT;
|
goto OUT;
|
||||||
};
|
};
|
||||||
first_nt_counter++;
|
first_nt_counter++;
|
||||||
} else for (uint8_t i = 0; i < nr_nested; i++) {
|
} else {
|
||||||
|
for (uint8_t i = 0; i < nr_nested; i++) {
|
||||||
if (need_first_auth) {
|
if (need_first_auth) {
|
||||||
cuid = 0;
|
cuid = 0;
|
||||||
|
|
||||||
|
@ -3204,6 +3318,7 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
|
||||||
}
|
}
|
||||||
oldntenc = ntenc;
|
oldntenc = ntenc;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data[1] = (cuid >> 24) & 0xFF;
|
data[1] = (cuid >> 24) & 0xFF;
|
||||||
data[2] = (cuid >> 16) & 0xFF;
|
data[2] = (cuid >> 16) & 0xFF;
|
||||||
|
|
|
@ -37,7 +37,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8
|
||||||
void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, 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 MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
||||||
int MifareAcquireStaticEncryptedNonces(uint32_t flags, const uint8_t *key, bool reply);
|
int MifareAcquireStaticEncryptedNonces(uint32_t flags, const uint8_t *key, bool reply, uint8_t first_block_no, uint8_t first_key_type);
|
||||||
void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
|
void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
|
||||||
void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem);
|
void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem);
|
||||||
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
|
|
|
@ -983,3 +983,12 @@ int nonce_distance(uint32_t from, uint32_t to) {
|
||||||
int nonce16_index(uint16_t nt) {
|
int nonce16_index(uint16_t nt) {
|
||||||
return nonce16_distance(0x0100, nt) + 1;
|
return nonce16_distance(0x0100, nt) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t rewind_nonce(uint32_t from, uint16_t dist) {
|
||||||
|
uint16_t x = from >> 16;
|
||||||
|
for (uint16_t i = 0; i < dist; i++) {
|
||||||
|
x = ((x << 1 | x >> 15) & 0xffff) ^ ((x >> 1 ^ x >> 2 ^ x >> 4) & 0x100);
|
||||||
|
}
|
||||||
|
uint32_t nt = x;
|
||||||
|
return nt << 16 | prng_successor(nt, 16);
|
||||||
|
}
|
||||||
|
|
|
@ -128,4 +128,5 @@ bool validate_parity_nonce(uint32_t ntenc, uint8_t ntparenc, uint32_t nt);
|
||||||
int nonce_distance(uint32_t from, uint32_t to);
|
int nonce_distance(uint32_t from, uint32_t to);
|
||||||
int nonce16_distance(uint16_t x, uint16_t y);
|
int nonce16_distance(uint16_t x, uint16_t y);
|
||||||
int nonce16_index(uint16_t nt);
|
int nonce16_index(uint16_t nt);
|
||||||
|
uint32_t rewind_nonce(uint32_t from, uint16_t dist);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9883,6 +9883,7 @@ static int CmdHF14AMfISEN(const char *Cmd) {
|
||||||
arg_rem("FM11RF08S specific options:", "Incompatible with above options, except -k; output in JSON"),
|
arg_rem("FM11RF08S specific options:", "Incompatible with above options, except -k; output in JSON"),
|
||||||
arg_lit0(NULL, "collect_fm11rf08s", "collect all nT/{nT}/par_err."),
|
arg_lit0(NULL, "collect_fm11rf08s", "collect all nT/{nT}/par_err."),
|
||||||
arg_lit0(NULL, "collect_fm11rf08s_with_data", "collect all nT/{nT}/par_err and data blocks."),
|
arg_lit0(NULL, "collect_fm11rf08s_with_data", "collect all nT/{nT}/par_err and data blocks."),
|
||||||
|
arg_lit0(NULL, "collect_fm11rf08s_without_backdoor", "collect all nT/{nT}/par_err without backdoor. Requires first auth keytype and block"),
|
||||||
arg_str0("f", "file", "<fn>", "Specify a filename for collected data"),
|
arg_str0("f", "file", "<fn>", "Specify a filename for collected data"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
|
@ -9954,9 +9955,18 @@ static int CmdHF14AMfISEN(const char *Cmd) {
|
||||||
if (collect_fm11rf08s_with_data) {
|
if (collect_fm11rf08s_with_data) {
|
||||||
collect_fm11rf08s = 1;
|
collect_fm11rf08s = 1;
|
||||||
}
|
}
|
||||||
|
bool collect_fm11rf08s_without_backdoor = arg_get_lit(ctx, 23);
|
||||||
|
if (collect_fm11rf08s_without_backdoor) {
|
||||||
|
collect_fm11rf08s = 1;
|
||||||
|
}
|
||||||
|
if (collect_fm11rf08s_with_data && collect_fm11rf08s_without_backdoor) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(WARNING, "Don't mix with_data and without_backdoor options");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
int fnlen = 0;
|
int fnlen = 0;
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
CLIParamStrToBuf(arg_get_str(ctx, 23), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
CLIParamStrToBuf(arg_get_str(ctx, 24), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
@ -10005,8 +10015,8 @@ static int CmdHF14AMfISEN(const char *Cmd) {
|
||||||
|
|
||||||
if (collect_fm11rf08s) {
|
if (collect_fm11rf08s) {
|
||||||
uint64_t t1 = msclock();
|
uint64_t t1 = msclock();
|
||||||
uint32_t flags = collect_fm11rf08s_with_data;
|
uint32_t flags = collect_fm11rf08s_with_data | (collect_fm11rf08s_without_backdoor << 1);
|
||||||
SendCommandMIX(CMD_HF_MIFARE_ACQ_STATIC_ENCRYPTED_NONCES, flags, 0, 0, key, sizeof(key));
|
SendCommandMIX(CMD_HF_MIFARE_ACQ_STATIC_ENCRYPTED_NONCES, flags, blockn, keytype, key, sizeof(key));
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
|
||||||
if (resp.oldarg[0] != PM3_SUCCESS) {
|
if (resp.oldarg[0] != PM3_SUCCESS) {
|
||||||
return NONCE_FAIL;
|
return NONCE_FAIL;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue