- 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:
zveriu@gmail.com 2011-10-04 12:33:16 +00:00
parent 6fde5d8a91
commit eaa9ff8f1a

View File

@ -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);