mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
FIX: 'hf mf darkside' - no more WDT crashes. plus positive sideeffects (@pwpiwi)
https://github.com/Proxmark/proxmark3/pull/569
This commit is contained in:
parent
dc94fe0c58
commit
fe34cac012
5 changed files with 59 additions and 49 deletions
|
@ -2308,9 +2308,7 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) {
|
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) {
|
||||||
|
|
||||||
if ( first_try ) {
|
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
BigBuf_free(); BigBuf_Clear_ext(false);
|
BigBuf_free(); BigBuf_Clear_ext(false);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
@ -2325,7 +2323,9 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) {
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||||
uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough
|
uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough
|
||||||
uint8_t nt_diff = 0;
|
uint8_t nt_diff = 0;
|
||||||
|
|
||||||
uint32_t nt = 0, previous_nt = 0, cuid = 0;
|
uint32_t nt = 0, previous_nt = 0, cuid = 0;
|
||||||
|
uint32_t sync_time = GetCountSspClk() & 0xfffffff8;
|
||||||
|
|
||||||
int32_t catch_up_cycles = 0;
|
int32_t catch_up_cycles = 0;
|
||||||
int32_t last_catch_up = 0;
|
int32_t last_catch_up = 0;
|
||||||
|
@ -2341,8 +2341,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) {
|
||||||
uint8_t cascade_levels = 0;
|
uint8_t cascade_levels = 0;
|
||||||
|
|
||||||
// static variables here, is re-used in the next call
|
// static variables here, is re-used in the next call
|
||||||
static uint32_t nt_attacked = 0;
|
static uint32_t nt_attacked = 0;
|
||||||
static uint32_t sync_time = 0;
|
|
||||||
static int32_t sync_cycles = 0;
|
static int32_t sync_cycles = 0;
|
||||||
static uint8_t par_low = 0;
|
static uint8_t par_low = 0;
|
||||||
static uint8_t mf_nr_ar3 = 0;
|
static uint8_t mf_nr_ar3 = 0;
|
||||||
|
@ -2350,7 +2349,6 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) {
|
||||||
AddCrc14A(mf_auth, 2);
|
AddCrc14A(mf_auth, 2);
|
||||||
|
|
||||||
if (first_try) {
|
if (first_try) {
|
||||||
sync_time = GetCountSspClk() & 0xfffffff8;
|
|
||||||
sync_cycles = PRNG_SEQUENCE_LENGTH; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
|
sync_cycles = PRNG_SEQUENCE_LENGTH; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
|
||||||
nt_attacked = 0;
|
nt_attacked = 0;
|
||||||
mf_nr_ar3 = 0;
|
mf_nr_ar3 = 0;
|
||||||
|
@ -2403,9 +2401,11 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) {
|
||||||
// Sending timeslot of ISO14443a frame
|
// Sending timeslot of ISO14443a frame
|
||||||
sync_time = (sync_time & 0xfffffff8 ) + sync_cycles + catch_up_cycles;
|
sync_time = (sync_time & 0xfffffff8 ) + sync_cycles + catch_up_cycles;
|
||||||
catch_up_cycles = 0;
|
catch_up_cycles = 0;
|
||||||
|
|
||||||
// if we missed the sync time already, advance to the next nonce repeat
|
#define SYNC_TIME_BUFFER 16 // if there is only SYNC_TIME_BUFFER left before next planned sync, wait for next PRNG cycle
|
||||||
while ( GetCountSspClk() > sync_time) {
|
|
||||||
|
// if we missed the sync time already or are about to miss it, advance to the next nonce repeat
|
||||||
|
while ( sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) {
|
||||||
++elapsed_prng_sequences;
|
++elapsed_prng_sequences;
|
||||||
sync_time = (sync_time & 0xfffffff8 ) + sync_cycles;
|
sync_time = (sync_time & 0xfffffff8 ) + sync_cycles;
|
||||||
}
|
}
|
||||||
|
@ -2548,13 +2548,13 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) {
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 4) Dbprintf("Number of sent auth requestes: %u", i);
|
if (MF_DBGLEVEL >= 4) Dbprintf("Number of sent auth requestes: %u", i);
|
||||||
|
|
||||||
uint8_t buf[28] = {0x00};
|
uint8_t buf[32] = {0x00};
|
||||||
memset(buf, 0x00, sizeof(buf));
|
memset(buf, 0x00, sizeof(buf));
|
||||||
num_to_bytes(cuid, 4, buf);
|
num_to_bytes(cuid, 4, buf);
|
||||||
num_to_bytes(nt, 4, buf + 4);
|
num_to_bytes(nt, 4, buf + 4);
|
||||||
memcpy(buf + 8, par_list, 8);
|
memcpy(buf + 8, par_list, 8);
|
||||||
memcpy(buf + 16, ks_list, 8);
|
memcpy(buf + 16, ks_list, 8);
|
||||||
memcpy(buf + 24, mf_nr_ar, 4);
|
memcpy(buf + 24, mf_nr_ar, 8);
|
||||||
|
|
||||||
cmd_send(CMD_ACK, isOK, 0, 0, buf, sizeof(buf) );
|
cmd_send(CMD_ACK, isOK, 0, 0, buf, sizeof(buf) );
|
||||||
|
|
||||||
|
|
|
@ -461,6 +461,11 @@ char* pb(uint32_t b) {
|
||||||
|
|
||||||
int CmdAnalyseA(const char *Cmd){
|
int CmdAnalyseA(const char *Cmd){
|
||||||
|
|
||||||
|
printf("-- " _BLUE_(its my message) "\n");
|
||||||
|
printf("-- " _RED_(its my message) "\n");
|
||||||
|
printf("-- " _YELLOW_(its my message) "\n");
|
||||||
|
printf("-- " _GREEN_(its my message) "\n");
|
||||||
|
|
||||||
//uint8_t syncBit = 99;
|
//uint8_t syncBit = 99;
|
||||||
// The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
|
// The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
|
||||||
// Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
|
// Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
|
||||||
|
@ -473,37 +478,46 @@ int CmdAnalyseA(const char *Cmd){
|
||||||
// reverse byte
|
// reverse byte
|
||||||
uint8_t rev = reflect8(bt);
|
uint8_t rev = reflect8(bt);
|
||||||
printf("input %02x | %02x \n", bt, rev);
|
printf("input %02x | %02x \n", bt, rev);
|
||||||
printf("shiftreg before %08x \n", shiftReg);
|
|
||||||
// add byte to shift register
|
// add byte to shift register
|
||||||
shiftReg = shiftReg << 8 | rev;
|
shiftReg = shiftReg << 8 | rev;
|
||||||
|
|
||||||
printf("shiftreg after %08x \n", shiftReg);
|
printf("shiftreg after %08x | pattern %08x \n", shiftReg, SYNC_16BIT);
|
||||||
|
|
||||||
printf("reg %04x \n", ( shiftReg >> 7 & 0xFFFF ));
|
/*
|
||||||
printf("reg %04x \n", ( shiftReg >> 6 & 0xFFFF ));
|
hex(0xb24d shr 0) 0xB24D 0b1011001001001101
|
||||||
printf("reg %04x \n", ( shiftReg >> 5 & 0xFFFF ));
|
hex(0xb24d shr 1) 0x5926
|
||||||
printf("reg %04x \n", ( shiftReg >> 4 & 0xFFFF ));
|
hex(0xb24d shr 2) 0x2C93
|
||||||
printf("reg %04x \n", ( shiftReg >> 3 & 0xFFFF ));
|
*/
|
||||||
printf("reg %04x \n", ( shiftReg >> 2 & 0xFFFF ));
|
|
||||||
printf("reg %04x \n", ( shiftReg >> 1 & 0xFFFF ));
|
for ( int i =0; i< 16; i++) {
|
||||||
printf("reg %04x \n", ( shiftReg >> 0 & 0xFFFF ));
|
printf(" (shiftReg >> %d) & 0xFFFF == %08x ---", i, (( shiftReg >> i) & 0xFFFF ));
|
||||||
|
|
||||||
|
// kolla om SYNC_PATTERN finns.
|
||||||
// kolla om SYNC_PATTERN finns.
|
if ((( shiftReg >> 7) & 0xFFFF ) == SYNC_16BIT) byte_offset = 7;
|
||||||
if (( shiftReg >> 7 & 0xFFFF ) == SYNC_16BIT) byte_offset = 7;
|
else if ((( shiftReg >> 6) & 0xFFFF ) == SYNC_16BIT) byte_offset = 6;
|
||||||
else if (( shiftReg >> 6 & 0xFFFF ) == SYNC_16BIT) byte_offset = 6;
|
else if ((( shiftReg >> 5) & 0xFFFF ) == SYNC_16BIT) byte_offset = 5;
|
||||||
else if (( shiftReg >> 5 & 0xFFFF ) == SYNC_16BIT) byte_offset = 5;
|
else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4;
|
||||||
else if (( shiftReg >> 4 & 0xFFFF ) == SYNC_16BIT) byte_offset = 4;
|
else if ((( shiftReg >> 3) & 0xFFFF ) == SYNC_16BIT) byte_offset = 3;
|
||||||
else if (( shiftReg >> 3 & 0xFFFF ) == SYNC_16BIT) byte_offset = 3;
|
else if ((( shiftReg >> 2) & 0xFFFF ) == SYNC_16BIT) byte_offset = 2;
|
||||||
else if (( shiftReg >> 2 & 0xFFFF ) == SYNC_16BIT) byte_offset = 2;
|
else if ((( shiftReg >> 1) & 0xFFFF ) == SYNC_16BIT) byte_offset = 1;
|
||||||
else if (( shiftReg >> 1 & 0xFFFF ) == SYNC_16BIT) byte_offset = 1;
|
else if ((( shiftReg >> 0) & 0xFFFF ) == SYNC_16BIT) byte_offset = 0;
|
||||||
else if (( shiftReg >> 0 & 0xFFFF ) == SYNC_16BIT) byte_offset = 0;
|
|
||||||
|
printf("Offset %u \n", byte_offset);
|
||||||
|
if ( byte_offset != 99 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
shiftReg >>=1;
|
||||||
|
}
|
||||||
|
|
||||||
if (byte_offset == 99 ) return 0;
|
|
||||||
//uint8_t p0 =
|
|
||||||
uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset)));
|
uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset)));
|
||||||
printf("Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1) );
|
printf("Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1) );
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
pm3 --> da hex2bin 4db2 0100110110110010
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
/*
|
/*
|
||||||
// split byte into two parts.
|
// split byte into two parts.
|
||||||
uint8_t offset = 3, n0 = 0, n1 = 0;
|
uint8_t offset = 3, n0 = 0, n1 = 0;
|
||||||
|
@ -529,10 +543,6 @@ return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
pm3 --> da hex2bin 4db2 0100110110110010
|
|
||||||
pm3 --> da hex2bin 926d9 10010010011011011001
|
|
||||||
*/
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// 14443-A
|
// 14443-A
|
||||||
|
@ -616,8 +626,8 @@ uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002)
|
||||||
uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02};
|
uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02};
|
||||||
uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
|
uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
|
||||||
|
|
||||||
keycountA = nonce2key(d1[0], d1[1], d1[2], d1[3], d1[4] ,&keylistA);
|
keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4] ,&keylistA);
|
||||||
keycountB = nonce2key(d2[0], d2[1], d2[2], d2[3], d2[4], &keylistB);
|
keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB);
|
||||||
|
|
||||||
switch (keycountA) {
|
switch (keycountA) {
|
||||||
case 0: printf("Key test A failed\n"); break;
|
case 0: printf("Key test A failed\n"); break;
|
||||||
|
|
|
@ -43,12 +43,12 @@ uint32_t intersection(uint64_t *listA, uint64_t *listB) {
|
||||||
|
|
||||||
// Darkside attack (hf mf mifare)
|
// Darkside attack (hf mf mifare)
|
||||||
// if successful it will return a list of keys, not just one.
|
// if successful it will return a list of keys, not just one.
|
||||||
uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys) {
|
uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t par_info, uint64_t ks_info, uint64_t **keys) {
|
||||||
struct Crypto1State *states;
|
struct Crypto1State *states;
|
||||||
uint32_t i, pos, rr = 0;
|
uint32_t i, pos;
|
||||||
uint8_t bt, ks3x[8], par[8][8];
|
uint8_t bt, ks3x[8], par[8][8];
|
||||||
uint64_t key_recovered;
|
uint64_t key_recovered;
|
||||||
static uint64_t *keylist;
|
uint64_t *keylist;
|
||||||
|
|
||||||
// Reset the last three significant bits of the reader nonce
|
// Reset the last three significant bits of the reader nonce
|
||||||
nr &= 0xFFFFFF1F;
|
nr &= 0xFFFFFF1F;
|
||||||
|
@ -67,7 +67,7 @@ uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, ui
|
||||||
par[7-pos][7] = (bt >> 7) & 1;
|
par[7-pos][7] = (bt >> 7) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
states = lfsr_common_prefix(nr, rr, ks3x, par, (par_info == 0));
|
states = lfsr_common_prefix(nr, ar, ks3x, par, (par_info == 0));
|
||||||
|
|
||||||
if (!states) {
|
if (!states) {
|
||||||
*keys = NULL;
|
*keys = NULL;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
#include "crapto1/crapto1.h"
|
#include "crapto1/crapto1.h"
|
||||||
|
|
||||||
extern uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys);
|
extern uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t par_info, uint64_t ks_info, uint64_t **keys);
|
||||||
extern bool mfkey32(nonces_t data, uint64_t *outputkey);
|
extern bool mfkey32(nonces_t data, uint64_t *outputkey);
|
||||||
extern bool mfkey32_moebius(nonces_t data, uint64_t *outputkey);
|
extern bool mfkey32_moebius(nonces_t data, uint64_t *outputkey);
|
||||||
extern int mfkey64(nonces_t data, uint64_t *outputkey);
|
extern int mfkey64(nonces_t data, uint64_t *outputkey);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
uint32_t uid = 0;
|
uint32_t uid = 0;
|
||||||
uint32_t nt = 0, nr = 0;
|
uint32_t nt = 0, nr = 0, ar = 0;
|
||||||
uint64_t par_list = 0, ks_list = 0;
|
uint64_t par_list = 0, ks_list = 0;
|
||||||
uint64_t *keylist = NULL, *last_keylist = NULL;
|
uint64_t *keylist = NULL, *last_keylist = NULL;
|
||||||
uint32_t keycount = 0;
|
uint32_t keycount = 0;
|
||||||
|
@ -54,6 +54,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
|
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
|
||||||
ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
|
ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
|
||||||
nr = (uint32_t)bytes_to_num(resp.d.asBytes + 24, 4);
|
nr = (uint32_t)bytes_to_num(resp.d.asBytes + 24, 4);
|
||||||
|
ar = (uint32_t)bytes_to_num(resp.d.asBytes + 28, 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,11 +62,10 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
|
||||||
|
|
||||||
if (par_list == 0 && c.arg[0] == true) {
|
if (par_list == 0 && c.arg[0] == true) {
|
||||||
PrintAndLog("[+] Parity is all zero. Most likely this card sends NACK on every authentication.");
|
PrintAndLog("[+] Parity is all zero. Most likely this card sends NACK on every authentication.");
|
||||||
PrintAndLog("[+] Attack will take a few seconds longer because we need two consecutive successful runs.");
|
|
||||||
}
|
}
|
||||||
c.arg[0] = false;
|
c.arg[0] = false;
|
||||||
|
|
||||||
keycount = nonce2key(uid, nt, nr, par_list, ks_list, &keylist);
|
keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist);
|
||||||
|
|
||||||
if (keycount == 0) {
|
if (keycount == 0) {
|
||||||
PrintAndLog("[-] key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
|
PrintAndLog("[-] key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue