mirror of
https://github.com/nfc-tools/mfcuk.git
synced 2025-12-23 18:50:06 +00:00
- Added initial version of Multiple-Sector Authentication detection based on a full PM3 trace log (used trace1.txt as sample)
- Formatting corrections (all tabs to spaces4)
This commit is contained in:
parent
6fde5d8a91
commit
eaa9ff8f1a
94
src/mfcuk.c
94
src/mfcuk.c
@ -348,7 +348,7 @@ uint32_t mfcuk_verify_key_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui64
|
||||
|
||||
if ( !nfc_initiator_transceive_bits(pnd,abtArEnc,64,abtArEncPar,abtRx,&szRx,abtRxPar) )
|
||||
{
|
||||
return MFCUK_FAIL_AUTH;
|
||||
return MFCUK_FAIL_AUTH;
|
||||
}
|
||||
|
||||
crypto1_destroy(pcs);
|
||||
@ -357,8 +357,8 @@ uint32_t mfcuk_verify_key_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui64
|
||||
{
|
||||
for (pos=0; pos<4; pos++)
|
||||
{
|
||||
tag_response = tag_response << 8;
|
||||
tag_response = tag_response | abtRx[pos];
|
||||
tag_response = tag_response << 8;
|
||||
tag_response = tag_response | abtRx[pos];
|
||||
}
|
||||
|
||||
ks2 = reader_response ^ prng_successor(nt_orig, 64);
|
||||
@ -450,9 +450,9 @@ uint32_t mfcuk_key_recovery_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui
|
||||
// Save the tag nonce (nt)
|
||||
nt = bswap_32(*((uint32_t *) &abtRx));
|
||||
|
||||
// zveriu
|
||||
//printf("INFO - Nonce distance %d (from 0x%08x, to 0x%08x)\n", nonce_distance(nt, nt_orig), nt, nt_orig);
|
||||
nt_orig = nt;
|
||||
// zveriu
|
||||
//printf("INFO - Nonce distance %d (from 0x%08x, to 0x%08x)\n", nonce_distance(nt, nt_orig), nt, nt_orig);
|
||||
nt_orig = nt;
|
||||
|
||||
// Max log(2, MAX_TAG_NONCES) searches, i.e. log(2, 65536) = 16
|
||||
ptrFoundTagNonceEntry = (tag_nonce_entry_t *) bsearch((void *)(&nt_orig), arrSpoofEntries, numSpoofEntries, sizeof(arrSpoofEntries[0]), compareTagNonces);
|
||||
@ -638,13 +638,13 @@ uint32_t mfcuk_key_recovery_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui
|
||||
ptrFoundTagNonceEntry->spoofParBitsEnc++;
|
||||
}
|
||||
|
||||
return MFCUK_FAIL_AUTH;
|
||||
return MFCUK_FAIL_AUTH;
|
||||
}
|
||||
|
||||
// zveriu - Successful: either authentication (szRx == 32) either encrypted 0x5 reponse (szRx == 4)
|
||||
if (szRx == 4)
|
||||
{
|
||||
//printf("INFO - 4-bit (szRx=%d) error code 0x5 encrypted (abtRx=0x%02x)\n", szRx, abtRx[0] & 0xf);
|
||||
// zveriu - Successful: either authentication (szRx == 32) either encrypted 0x5 reponse (szRx == 4)
|
||||
if (szRx == 4)
|
||||
{
|
||||
//printf("INFO - 4-bit (szRx=%d) error code 0x5 encrypted (abtRx=0x%02x)\n", szRx, abtRx[0] & 0xf);
|
||||
|
||||
if (ptrFoundTagNonceEntry->current_out_of_8 < 0)
|
||||
{
|
||||
@ -714,7 +714,7 @@ uint32_t mfcuk_key_recovery_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (szRx == 32)
|
||||
{
|
||||
// Are we so MFCUKing lucky (?!), since ui64Key is a "dummy" key
|
||||
@ -976,18 +976,23 @@ int main(int argc, char* argv[])
|
||||
int finger_index_highest;
|
||||
|
||||
// proxmark3 log related
|
||||
#define PM3_UID 0
|
||||
#define PM3_TAG_CHAL 1
|
||||
#define PM3_NR_ENC 2
|
||||
#define PM3_READER_RESP 3
|
||||
#define PM3_TAG_RESP 4
|
||||
#define PM3_UID 0
|
||||
#define PM3_TAG_CHAL 1
|
||||
#define PM3_NR_ENC 2
|
||||
#define PM3_READER_RESP 3
|
||||
#define PM3_TAG_RESP 4
|
||||
#define PM3_MULTISECT_AUTH 5
|
||||
|
||||
uint32_t pm3_full_set_log[5]; // order is: uid, tag_challenge, nr_enc, reader_response, tag_response
|
||||
uint32_t pm3_log_multisect_auth;
|
||||
uint32_t pm3_ks2;
|
||||
uint32_t pm3_ks3;
|
||||
struct Crypto1State *pm3_revstate;
|
||||
struct Crypto1State *pm3_revstate = NULL;
|
||||
struct Crypto1State *pm3_revstate_multisect_auth = NULL;
|
||||
uint64_t pm3_lfsr;
|
||||
unsigned char* pm3_plfsr = (unsigned char*)&pm3_lfsr;
|
||||
uint8_t pm3_log_multisect_decrypted[4];
|
||||
uint8_t pm3_log_multisect_verified[4];
|
||||
|
||||
// various related
|
||||
int i, j, k;
|
||||
@ -1365,7 +1370,7 @@ int main(int argc, char* argv[])
|
||||
// strtoul failed somewhere. WTF?! strtoul() is not properly setting errno... errrrrggh!
|
||||
if (errno != 0)
|
||||
{
|
||||
WARN("Invalid hex literal %s for option -P", optarg);
|
||||
WARN("Invalid hex literal %s for option -P at position %d", optarg, iter);
|
||||
}
|
||||
|
||||
iter++;
|
||||
@ -1385,6 +1390,7 @@ int main(int argc, char* argv[])
|
||||
*/
|
||||
pm3_ks2 = pm3_full_set_log[PM3_READER_RESP] ^ prng_successor(pm3_full_set_log[PM3_TAG_CHAL], 64);
|
||||
pm3_ks3 = pm3_full_set_log[PM3_TAG_RESP] ^ prng_successor(pm3_full_set_log[PM3_TAG_CHAL], 96);
|
||||
|
||||
pm3_revstate = lfsr_recovery64(pm3_ks2, pm3_ks3);
|
||||
lfsr_rollback_word(pm3_revstate, 0, 0);
|
||||
lfsr_rollback_word(pm3_revstate, 0, 0);
|
||||
@ -1393,6 +1399,52 @@ int main(int argc, char* argv[])
|
||||
crypto1_get_lfsr(pm3_revstate, &pm3_lfsr);
|
||||
printf("proxmark3 log key: %02x%02x%02x%02x%02x%02x\n", pm3_plfsr[5], pm3_plfsr[4], pm3_plfsr[3], pm3_plfsr[2], pm3_plfsr[1], pm3_plfsr[0]);
|
||||
crypto1_destroy(pm3_revstate);
|
||||
|
||||
// If all minimum required details from the log were parsed and still there are some more hex tokens, it might be a multi-sector authentication test request
|
||||
if (token)
|
||||
{
|
||||
errno = 0;
|
||||
pm3_log_multisect_auth = strtoul(token, NULL, 16);
|
||||
|
||||
// strtoul failed somewhere. WTF?! strtoul() is not properly setting errno... errrrrggh!
|
||||
if (errno != 0)
|
||||
{
|
||||
WARN("Invalid hex literal %s for option -P at position %d", optarg, iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: what if the multi-sect authentication comes not directly after the first successful plain authentication, i.e. several read/write/incr/decr command occur first then multi-sect auth?! how does this affects the crypto stream/state, what should we do? need to simulate with a nfc-multisect-auth program which has tests with interleaved multi-sect authentications
|
||||
pm3_revstate_multisect_auth = lfsr_recovery64(pm3_ks2, pm3_ks3);
|
||||
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
uint8_t multisect_auth_byte = (pm3_log_multisect_auth >> (8 * (3-i))) & 0xFF;
|
||||
pm3_log_multisect_decrypted[i] = crypto1_byte(pm3_revstate_multisect_auth,0x00,0) ^ multisect_auth_byte;
|
||||
pm3_log_multisect_verified[i] = pm3_log_multisect_decrypted[i];
|
||||
}
|
||||
|
||||
if ( (pm3_log_multisect_decrypted[0] == MC_AUTH_A || pm3_log_multisect_decrypted[0] == MC_AUTH_B)
|
||||
// TODO: This "<= MIFARE_CLASSIC_4K_MAX_BLOCKS" should be properly checked against either MIFARE_CLASSIC_1K_MAX_BLOCKS or MIFARE_CLASSIC_4K_MAX_BLOCKS (depending on card type detected)
|
||||
&& (pm3_log_multisect_decrypted[1] >= 0x00 && pm3_log_multisect_decrypted[1] <= MIFARE_CLASSIC_4K_MAX_BLOCKS)
|
||||
)
|
||||
{
|
||||
iso14443a_crc_append(pm3_log_multisect_verified, 2);
|
||||
int multisect_auth_verified = 1;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (pm3_log_multisect_verified[i] != pm3_log_multisect_decrypted[i])
|
||||
{
|
||||
multisect_auth_verified = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("proxmark3 log multi-sect auth detected: %02X %02X %02X %02X (parity crc %s)\n", pm3_log_multisect_decrypted[0], pm3_log_multisect_decrypted[1], pm3_log_multisect_decrypted[2], pm3_log_multisect_decrypted[3], multisect_auth_verified?"ok":"NOK");
|
||||
}
|
||||
|
||||
crypto1_destroy(pm3_revstate_multisect_auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
@ -1630,7 +1682,7 @@ int main(int argc, char* argv[])
|
||||
WARN("mfcuk_key_arr_to_uint64() failed, verification key will be %012"PRIx64"", crntVerifKey);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
// TODO: make this kind of key verification as part of option -a - advanced verification of keys with crapto1 rollback for double verification
|
||||
// TEST
|
||||
nfc_disconnect(pnd);
|
||||
@ -1669,7 +1721,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Reset advanced settings
|
||||
mfcuk_darkside_reset_advanced(pnd);
|
||||
*/
|
||||
*/
|
||||
memcpy(mp.mpa.abtUid, tag_recover_verify.tag_basic.amb[0].mbm.abtUID, MIFARE_CLASSIC_UID_BYTELENGTH);
|
||||
memcpy(mp.mpa.abtKey, &(current_default_keys[j][0]), MIFARE_CLASSIC_KEY_BYTELENGTH);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user