mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
Mifare1ksim logic closer to SimulateIso14443aTag and keep running when using mfkey32v2
This commit is contained in:
parent
c1a038aa56
commit
3b91624ea6
4 changed files with 86 additions and 88 deletions
|
@ -1432,7 +1432,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads, uint8_t *iRATs) {
|
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads, uint8_t *iRATs) {
|
||||||
|
|
||||||
#define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack()
|
#define ATTACK_KEY_COUNT 16
|
||||||
|
|
||||||
tag_response_info_t *responses;
|
tag_response_info_t *responses;
|
||||||
uint32_t cuid = 0;
|
uint32_t cuid = 0;
|
||||||
|
|
|
@ -496,7 +496,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
||||||
uint8_t rats_len = 0;
|
uint8_t rats_len = 0;
|
||||||
|
|
||||||
|
|
||||||
// if fct is called with NULL we need to assign some memory since this pointer is passaed around
|
// if fct is called with NULL we need to assign some memory since this pointer is passed around
|
||||||
uint8_t datain_tmp[10] = {0};
|
uint8_t datain_tmp[10] = {0};
|
||||||
if (datain == NULL) {
|
if (datain == NULL) {
|
||||||
datain = datain_tmp;
|
datain = datain_tmp;
|
||||||
|
@ -505,14 +505,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
||||||
//Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
|
//Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
|
||||||
// This will be used in the reader-only attack.
|
// This will be used in the reader-only attack.
|
||||||
|
|
||||||
//allow collecting up to 7 sets of nonces to allow recovery of up to 7 keys
|
//allow collecting up to 16 sets of nonces to allow recovery of up to 16 keys
|
||||||
#define ATTACK_KEY_COUNT 7 // keep same as define in cmdhfmf.c -> readerAttack() (Cannot be more than 7)
|
#define ATTACK_KEY_COUNT 16
|
||||||
nonces_t ar_nr_resp[ATTACK_KEY_COUNT * 2]; // *2 for 2 separate attack types (nml, moebius) 36 * 7 * 2 bytes = 504 bytes
|
nonces_t ar_nr_resp[ATTACK_KEY_COUNT]; // for moebius attack type
|
||||||
memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
|
memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
|
||||||
|
|
||||||
uint8_t ar_nr_collected[ATTACK_KEY_COUNT ]; // for moebius attack type
|
|
||||||
memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected));
|
|
||||||
|
|
||||||
// Authenticate response - nonce
|
// Authenticate response - nonce
|
||||||
uint8_t rAUTH_NT[4] = {0, 0, 0, 1};
|
uint8_t rAUTH_NT[4] = {0, 0, 0, 1};
|
||||||
uint8_t rAUTH_NT_keystream[4];
|
uint8_t rAUTH_NT_keystream[4];
|
||||||
|
@ -547,7 +544,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
if (counter == 3000) {
|
if (counter == 1000) {
|
||||||
if (data_available()) {
|
if (data_available()) {
|
||||||
Dbprintf("----------- " _GREEN_("BREAKING") " ----------");
|
Dbprintf("----------- " _GREEN_("BREAKING") " ----------");
|
||||||
break;
|
break;
|
||||||
|
@ -1151,36 +1148,33 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
||||||
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
|
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
|
||||||
if (ar_nr_collected[i] == 0 ||
|
if (ar_nr_resp[i].state == EMPTY ||
|
||||||
(
|
(
|
||||||
|
(ar_nr_resp[i].state != EMPTY) &&
|
||||||
(cardAUTHSC == ar_nr_resp[i].sector) &&
|
(cardAUTHSC == ar_nr_resp[i].sector) &&
|
||||||
(cardAUTHKEY == ar_nr_resp[i].keytype) &&
|
(cardAUTHKEY == ar_nr_resp[i].keytype)
|
||||||
(ar_nr_collected[i] > 0)
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
// if first auth for sector, or matches sector and keytype of previous auth
|
// if first auth for sector, or matches sector and keytype of previous auth
|
||||||
if (ar_nr_collected[i] < 2) {
|
if (ar_nr_resp[i].state != SECOND) {
|
||||||
// if we haven't already collected 2 nonces for this sector
|
// if we haven't already collected 2 nonces for this sector
|
||||||
if (ar_nr_resp[ar_nr_collected[i]].ar != ar) {
|
if (ar_nr_resp[i].state == EMPTY) {
|
||||||
// Avoid duplicates... probably not necessary, ar should vary.
|
// first nonce collect
|
||||||
if (ar_nr_collected[i] == 0) {
|
ar_nr_resp[i].cuid = cuid;
|
||||||
// first nonce collect
|
ar_nr_resp[i].sector = cardAUTHSC;
|
||||||
ar_nr_resp[i].cuid = cuid;
|
ar_nr_resp[i].keytype = cardAUTHKEY;
|
||||||
ar_nr_resp[i].sector = cardAUTHSC;
|
ar_nr_resp[i].nonce = nonce;
|
||||||
ar_nr_resp[i].keytype = cardAUTHKEY;
|
ar_nr_resp[i].nr = nr;
|
||||||
ar_nr_resp[i].nonce = nonce;
|
ar_nr_resp[i].ar = ar;
|
||||||
ar_nr_resp[i].nr = nr;
|
ar_nr_resp[i].state = FIRST;
|
||||||
ar_nr_resp[i].ar = ar;
|
} else { // second nonce collect
|
||||||
ar_nr_collected[i]++;
|
// make sure we have different nonces for moebius attack
|
||||||
} else { // second nonce collect
|
if (ar_nr_resp[i].nonce != nonce) {
|
||||||
// make sure we have different nonces for moebius attack
|
ar_nr_resp[i].nonce2 = nonce;
|
||||||
if (ar_nr_resp[i].nonce != nonce) {
|
ar_nr_resp[i].nr2 = nr;
|
||||||
ar_nr_resp[i].nonce2 = nonce;
|
ar_nr_resp[i].ar2 = ar;
|
||||||
ar_nr_resp[i].nr2 = nr;
|
ar_nr_resp[i].state = SECOND;
|
||||||
ar_nr_resp[i].ar2 = ar;
|
finished = true;
|
||||||
ar_nr_collected[i]++;
|
|
||||||
finished = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1326,22 +1320,26 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
|
||||||
// NR AR ATTACK
|
// NR AR ATTACK
|
||||||
if (((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) && (g_dbglevel >= DBG_INFO)) {
|
uint8_t index = 0;
|
||||||
|
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||||
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
|
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
|
||||||
if (ar_nr_collected[i] == 2) {
|
if (ar_nr_resp[i].state == SECOND) {
|
||||||
Dbprintf("Collected two pairs of AR/NR which can be used to extract sector %d " _YELLOW_("%s")
|
index = i;
|
||||||
, ar_nr_resp[i].sector
|
if (g_dbglevel >= DBG_INFO) {
|
||||||
, (ar_nr_resp[i].keytype == AUTHKEYA) ? "key A" : "key B"
|
Dbprintf("Collected two pairs of AR/NR which can be used to extract sector %d " _YELLOW_("%s")
|
||||||
);
|
, ar_nr_resp[i].sector
|
||||||
Dbprintf("../tools/mfc/card_reader/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x",
|
, (ar_nr_resp[i].keytype == AUTHKEYA) ? "key A" : "key B"
|
||||||
ar_nr_resp[i].cuid, //UID
|
);
|
||||||
ar_nr_resp[i].nonce, //NT
|
Dbprintf("../tools/mfc/card_reader/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x",
|
||||||
ar_nr_resp[i].nr, //NR1
|
ar_nr_resp[i].cuid, //UID
|
||||||
ar_nr_resp[i].ar, //AR1
|
ar_nr_resp[i].nonce, //NT
|
||||||
ar_nr_resp[i].nonce2,//NT2
|
ar_nr_resp[i].nr, //NR1
|
||||||
ar_nr_resp[i].nr2, //NR2
|
ar_nr_resp[i].ar, //AR1
|
||||||
ar_nr_resp[i].ar2 //AR2
|
ar_nr_resp[i].nonce2,//NT2
|
||||||
);
|
ar_nr_resp[i].nr2, //NR2
|
||||||
|
ar_nr_resp[i].ar2 //AR2
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1351,7 +1349,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1
|
||||||
|
|
||||||
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
|
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
|
||||||
//Send the collected ar_nr in the response
|
//Send the collected ar_nr in the response
|
||||||
reply_mix(CMD_ACK, CMD_HF_MIFARE_SIMULATE, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp));
|
reply_ng(CMD_HF_MIFARE_SIMULATE, button_pushed ? PM3_EOPABORTED : PM3_SUCCESS, (uint8_t *)&ar_nr_resp[index], sizeof(nonces_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
|
@ -912,11 +912,6 @@ int CmdHF14ASim(const char *Cmd) {
|
||||||
// inform device to break the sim loop since client has exited
|
// inform device to break the sim loop since client has exited
|
||||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) {
|
|
||||||
//iceman: readerAttack call frees k_sector , this call is useless.
|
|
||||||
showSectorTable(k_sector, k_sectors_cnt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Done!");
|
PrintAndLogEx(INFO, "Done!");
|
||||||
|
@ -3799,9 +3794,6 @@ int CmdHF14AAIDSim(const char *Cmd) {
|
||||||
SendCommandNG(CMD_HF_ISO14443A_SIM_AID, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_ISO14443A_SIM_AID, (uint8_t *)&payload, sizeof(payload));
|
||||||
PacketResponseNG resp = {0};
|
PacketResponseNG resp = {0};
|
||||||
|
|
||||||
sector_t *k_sector = NULL;
|
|
||||||
size_t k_sectors_cnt = MIFARE_4K_MAXSECTOR;
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");
|
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");
|
||||||
bool keypress = kbd_enter_pressed();
|
bool keypress = kbd_enter_pressed();
|
||||||
while (keypress == false) {
|
while (keypress == false) {
|
||||||
|
@ -3823,11 +3815,6 @@ int CmdHF14AAIDSim(const char *Cmd) {
|
||||||
// inform device to break the sim loop since client has exited
|
// inform device to break the sim loop since client has exited
|
||||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) {
|
|
||||||
//iceman: readerAttack call frees k_sector , this call is useless.
|
|
||||||
showSectorTable(k_sector, k_sectors_cnt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4251,36 +4251,49 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||||
payload.sak = sak[0];
|
payload.sak = sak[0];
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
|
||||||
PacketResponseNG resp;
|
|
||||||
|
|
||||||
if (flags & FLAG_INTERACTIVE) {
|
if (flags & FLAG_INTERACTIVE) {
|
||||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or send another cmd to abort simulation");
|
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or a key to abort simulation");
|
||||||
|
|
||||||
sector_t *k_sector = NULL;
|
|
||||||
|
|
||||||
while (kbd_enter_pressed() == 0) {
|
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ((resp.oldarg[0] & 0xffff) != CMD_HF_MIFARE_SIMULATE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
nonces_t data[1];
|
|
||||||
memcpy(data, resp.data.asBytes, sizeof(data));
|
|
||||||
readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//iceman: readerAttack call frees k_sector. this call below is useless.
|
|
||||||
showSectorTable(k_sector, k_sectors_cnt);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");
|
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or send another cmd to abort simulation");
|
||||||
}
|
}
|
||||||
|
bool cont;
|
||||||
|
do {
|
||||||
|
cont = false;
|
||||||
|
SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
if (flags & FLAG_INTERACTIVE) {
|
||||||
|
PacketResponseNG resp;
|
||||||
|
sector_t *k_sector = NULL;
|
||||||
|
|
||||||
|
bool keypress = kbd_enter_pressed();
|
||||||
|
while (keypress == false) {
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) {
|
||||||
|
keypress = kbd_enter_pressed();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.status != PM3_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const nonces_t *data = (nonces_t *)resp.data.asBytes;
|
||||||
|
readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
|
||||||
|
cont = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (keypress) {
|
||||||
|
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||||
|
// inform device to break the sim loop since client has exited
|
||||||
|
PrintAndLogEx(INFO, "Key pressed, please wait a few seconds for the pm3 to stop...");
|
||||||
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (cont);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue