hf mf sim code cleanup - update changelog

This commit is contained in:
marshmellow42 2016-06-27 00:09:40 -04:00
commit 76ef5273d8
3 changed files with 77 additions and 73 deletions

View file

@ -5,6 +5,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased] ## [unreleased][unreleased]
### Added ### Added
- Added lf pyramid commands (iceman)
- Added lf presco commands - some bits not fully understood... (iceman)
- Added experimental HitagS support (Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg) - Added experimental HitagS support (Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg)
see https://media.ccc.de/v/32c3-7166-sicherheit_von_125khz_transpondern_am_beispiel_hitag_s see https://media.ccc.de/v/32c3-7166-sicherheit_von_125khz_transpondern_am_beispiel_hitag_s
English video available English video available
@ -16,8 +18,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- `lf t55xx wipe` - sets t55xx back to factory defaults - `lf t55xx wipe` - sets t55xx back to factory defaults
- Added viking demod to `lf search` (marshmellow) - Added viking demod to `lf search` (marshmellow)
- `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow) - `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow)
- `lf t55xx resetread` added reset then read command - should allow determining start - `lf t55xx resetread` added reset then read command - should allow determining start of stream transmissions (marshmellow)
of stream transmissions (marshmellow)
- `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (iceman, marshmellow) - `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (iceman, marshmellow)
- `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow) - `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow)
- `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow) - `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow)
@ -35,21 +36,29 @@ of stream transmissions (marshmellow)
- Added option c to 'hf list' (mark CRC bytes) (piwi) - Added option c to 'hf list' (mark CRC bytes) (piwi)
### Changed ### Changed
- Added `[l] <length>` option to data printdemodbuffer - Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow)
- Adjusted lf awid clone to optionally clone to Q5 tags - Fixed bug in lf viking clone/sim (iceman)
- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7 - Fixed broken `data askedgedetect` (marshmellow)
- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal) - Adjusted hf mf sim command (marshmellow)
- Adjusted lf pskindalademod to reduce false positive reads. added auto run mfkey32 to extract all keys
- Small adjustments to psk, nrz, and ask clock detect routines - more reliable. also added f parameter to allow attacking with UIDs from a file (implies x and i parameters)
- Adjusted lf em410x em410xsim to accept a clock argument also added e parameter to allow adding the extracted keys to emulator memory for the next simulation
added 10 byte uid option
- Added `[l] <length>` option to data printdemodbuffer (marshmellow)
- Adjusted lf awid clone to optionally clone to Q5 tags (marshmellow)
- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7 (marshmellow)
- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal) (marshmellow)
- Adjusted lf pskindalademod to reduce false positive reads. (marshmellow)
- Small adjustments to psk, nrz, and ask clock detect routines - more reliable. (marshmellow)
- Adjusted lf em410x em410xsim to accept a clock argument (marshmellow)
- Adjusted lf t55xx dump to allow overriding the safety check and warning text (marshmellow) - Adjusted lf t55xx dump to allow overriding the safety check and warning text (marshmellow)
- Adjusted lf t55xx write input variables (marshmellow) - Adjusted lf t55xx write input variables (marshmellow)
- Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (marshmellow & iceman) - Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (marshmellow & iceman)
- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate. - Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate. (marshmellow)
- Adjusted timings for t55xx commands. more reliable now. (marshmellow & iceman) - Adjusted timings for t55xx commands. more reliable now. (marshmellow & iceman)
- `lf cmdread` adjusted input methods and added help text (marshmellow & iceman) - `lf cmdread` adjusted input methods and added help text (marshmellow & iceman)
- changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow) - changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow)
- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet) - `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet) (marshmellow)
- Revised workflow for StandAloneMode14a (Craig Young) - Revised workflow for StandAloneMode14a (Craig Young)
- EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers) - EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers)
- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi) - 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi)

View file

@ -2336,7 +2336,6 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
{ {
int cardSTATE = MFEMUL_NOFIELD; int cardSTATE = MFEMUL_NOFIELD;
int _UID_LEN = 0; // 4, 7, 10 int _UID_LEN = 0; // 4, 7, 10
int _7BUID = 0;
int vHf = 0; // in mV int vHf = 0; // in mV
int res; int res;
uint32_t selTimer = 0; uint32_t selTimer = 0;
@ -2360,14 +2359,13 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
uint8_t response[MAX_MIFARE_FRAME_SIZE]; uint8_t response[MAX_MIFARE_FRAME_SIZE];
uint8_t response_par[MAX_MIFARE_PARITY_SIZE]; uint8_t response_par[MAX_MIFARE_PARITY_SIZE];
uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!! uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
uint8_t rSAK[] = {0x08, 0xb6, 0xdd}; uint8_t rSAKfinal[]= {0x08, 0xb6, 0xdd}; // mifare 1k indicated
uint8_t rSAK1[] = {0x04, 0xda, 0x17}; uint8_t rSAK1[] = {0x04, 0xda, 0x17}; // indicate UID not finished
uint8_t rSAK2[] = {0x04, 0xda, 0x17}; //need to look up
uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04}; uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
@ -2375,8 +2373,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
//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 8 sets of nonces to allow recovery of 8 keys //allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys
#define ATTACK_KEY_COUNT 8 #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack()
nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*2 for 2 separate attack types nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*2 for 2 separate attack types
memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
@ -2404,7 +2402,6 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
// 7B uid comes from data-portion of packet // 7B uid comes from data-portion of packet
memcpy(&rUIDBCC1[1],datain,3); memcpy(&rUIDBCC1[1],datain,3);
memcpy(rUIDBCC2, datain+3, 4); memcpy(rUIDBCC2, datain+3, 4);
_7BUID = true;
_UID_LEN = 7; _UID_LEN = 7;
} else if (flags & FLAG_10B_UID_IN_DATA) { } else if (flags & FLAG_10B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3); memcpy(&rUIDBCC1[1], datain, 3);
@ -2414,8 +2411,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
} else { } else {
// get UID from emul memory - guess at length // get UID from emul memory - guess at length
emlGetMemBt(receivedCmd, 7, 1); emlGetMemBt(receivedCmd, 7, 1);
_7BUID = !(receivedCmd[0] == 0x00); if (receivedCmd[0] == 0x00) { // ---------- 4BUID
if (!_7BUID) { // ---------- 4BUID
emlGetMemBt(rUIDBCC1, 0, 4); emlGetMemBt(rUIDBCC1, 0, 4);
_UID_LEN = 4; _UID_LEN = 4;
} else { // ---------- 7BUID } else { // ---------- 7BUID
@ -2550,27 +2546,25 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break; break;
} }
case MFEMUL_SELECT1:{ case MFEMUL_SELECT1:{
// select all // select all - 0x93 0x20
if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) { if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) {
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received"); if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received");
EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1)); EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
break; break;
} }
if (MF_DBGLEVEL >= 4 && len == 9 && receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 ) // select card - 0x93 0x70 ...
{ if (len == 9 &&
Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]); (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
} if (MF_DBGLEVEL >= 4)
// select card Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
// check correct sak values... (marshmellow)
if (len == 9 &&
(receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
switch(_UID_LEN) { switch(_UID_LEN) {
case 4: case 4:
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
LED_B_ON(); LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer); if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
EmSendCmd(rSAK, sizeof(rSAK)); EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
break; break;
case 7: case 7:
cardSTATE = MFEMUL_SELECT2; cardSTATE = MFEMUL_SELECT2;
@ -2578,7 +2572,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break; break;
case 10: case 10:
cardSTATE = MFEMUL_SELECT2; cardSTATE = MFEMUL_SELECT2;
EmSendCmd(rSAK2, sizeof(rSAK2)); EmSendCmd(rSAK1, sizeof(rSAK1));
break; break;
default:break; default:break;
} }
@ -2592,16 +2586,18 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break; break;
} }
// select all cl3 - 0x97 0x20
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) { if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) {
EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3)); EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3));
break; break;
} }
// select card cl3 - 0x97 0x70
if (len == 9 && if (len == 9 &&
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 &&
receivedCmd[1] == 0x70 && receivedCmd[1] == 0x70 &&
memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) { memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) {
EmSendCmd(rSAK2, sizeof(rSAK2)); EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
LED_B_ON(); LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer);
@ -2611,8 +2607,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break; break;
} }
case MFEMUL_AUTH1:{ case MFEMUL_AUTH1:{
if( len != 8) if( len != 8) {
{
cardSTATE_TO_IDLE(); cardSTATE_TO_IDLE();
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break; break;
@ -2621,7 +2616,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
uint32_t nr = bytes_to_num(receivedCmd, 4); uint32_t nr = bytes_to_num(receivedCmd, 4);
uint32_t ar = bytes_to_num(&receivedCmd[4], 4); uint32_t ar = bytes_to_num(&receivedCmd[4], 4);
//Collect AR/NR per keytype & sector // Collect AR/NR per keytype & sector
if(flags & FLAG_NR_AR_ATTACK) { if(flags & 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+mM]==0 || ((cardAUTHSC == ar_nr_resp[i+mM].sector) && (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && (ar_nr_collected[i+mM] > 0)) ) { if ( ar_nr_collected[i+mM]==0 || ((cardAUTHSC == ar_nr_resp[i+mM].sector) && (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && (ar_nr_collected[i+mM] > 0)) ) {
@ -2639,7 +2634,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
ar_nr_resp[i+mM].nr = nr; ar_nr_resp[i+mM].nr = nr;
ar_nr_resp[i+mM].ar = ar; ar_nr_resp[i+mM].ar = ar;
nonce1_count++; nonce1_count++;
//add this nonce to first moebius nonce // add this nonce to first moebius nonce
ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid; ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid;
ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC; ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC;
ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY; ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY;
@ -2647,18 +2642,18 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr; ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr;
ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar; ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar;
ar_nr_collected[i+ATTACK_KEY_COUNT]++; ar_nr_collected[i+ATTACK_KEY_COUNT]++;
} else { //second nonce collect (std and moebius) } else { // second nonce collect (std and moebius)
ar_nr_resp[i+mM].nonce2 = nonce; ar_nr_resp[i+mM].nonce2 = nonce;
ar_nr_resp[i+mM].nr2 = nr; ar_nr_resp[i+mM].nr2 = nr;
ar_nr_resp[i+mM].ar2 = ar; ar_nr_resp[i+mM].ar2 = ar;
if (!gettingMoebius) { if (!gettingMoebius) {
nonce2_count++; nonce2_count++;
//check if this was the last second nonce we need for std attack // check if this was the last second nonce we need for std attack
if ( nonce2_count == nonce1_count ) { if ( nonce2_count == nonce1_count ) {
//done collecting std test switch to moebius // done collecting std test switch to moebius
//finish incrementing last sample // first finish incrementing last sample
ar_nr_collected[i+mM]++; ar_nr_collected[i+mM]++;
//switch to moebius collection // switch to moebius collection
gettingMoebius = true; gettingMoebius = true;
mM = ATTACK_KEY_COUNT; mM = ATTACK_KEY_COUNT;
nonce = nonce*7; nonce = nonce*7;
@ -2666,14 +2661,12 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
} }
} else { } else {
moebius_n_count++; moebius_n_count++;
//if we've collected all the nonces we need - finish. // if we've collected all the nonces we need - finish.
if (nonce1_count == moebius_n_count) finished = true; if (nonce1_count == moebius_n_count) finished = true;
} }
} }
ar_nr_collected[i+mM]++; ar_nr_collected[i+mM]++;
} }
} else { //already collected 2 nonces for sector - dump out
//finished = true;
} }
// we found right spot for this nonce stop looking // we found right spot for this nonce stop looking
break; break;
@ -2716,24 +2709,25 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
if (!len) { if (!len) {
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break; break;
} }
if (len == 2 && (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x20)) { // select all cl2 - 0x95 0x20
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) {
EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2)); EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
break; break;
} }
// select 2 card // select cl2 card - 0x95 0x70 xxxxxxxxxxxx
if (len == 9 && if (len == 9 &&
(receivedCmd[0] == 0x95 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) { (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
//which sak now? (marshmellow)
EmSendCmd(rSAK, sizeof(rSAK));
switch(_UID_LEN) { switch(_UID_LEN) {
case 7: case 7:
EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
LED_B_ON(); LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer); if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
break; break;
case 10: case 10:
EmSendCmd(rSAK1, sizeof(rSAK1));
cardSTATE = MFEMUL_SELECT3; cardSTATE = MFEMUL_SELECT3;
break; break;
default:break; default:break;
@ -2963,8 +2957,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) {
{
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_collected[i] == 2) {
Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector); Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
@ -2995,8 +2988,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
} }
if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen());
if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK if(flags & 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
cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,button_pushed,0,&ar_nr_resp,sizeof(ar_nr_resp)); cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,button_pushed,0,&ar_nr_resp,sizeof(ar_nr_resp));
} }
@ -3004,7 +2996,6 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// MIFARE sniffer. // MIFARE sniffer.
// //

View file

@ -1017,11 +1017,10 @@ int CmdHF14AMfChk(const char *Cmd)
} }
void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) { void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {
#define ATTACK_KEY_COUNT 8 #define ATTACK_KEY_COUNT 8 // keep same as define in iso14443a.c -> Mifare1ksim()
uint64_t key = 0; uint64_t key = 0;
typedef struct { typedef struct {
uint64_t keyA; uint64_t keyA;
uint32_t security;
uint64_t keyB; uint64_t keyB;
} st_t; } st_t;
st_t sector_trailer[ATTACK_KEY_COUNT]; st_t sector_trailer[ATTACK_KEY_COUNT];
@ -1034,9 +1033,9 @@ void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) { for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {
if (ar_resp[i].ar2 > 0) { if (ar_resp[i].ar2 > 0) {
//PrintAndLog("Trying sector %d, cuid %08x, nt %08x, ar %08x, nr %08x, ar2 %08x, nr2 %08x",ar_resp[i].sector, ar_resp[i].cuid,ar_resp[i].nonce,ar_resp[i].ar,ar_resp[i].nr,ar_resp[i].ar2,ar_resp[i].nr2); //PrintAndLog("DEBUG: Trying sector %d, cuid %08x, nt %08x, ar %08x, nr %08x, ar2 %08x, nr2 %08x",ar_resp[i].sector, ar_resp[i].cuid,ar_resp[i].nonce,ar_resp[i].ar,ar_resp[i].nr,ar_resp[i].ar2,ar_resp[i].nr2);
if (mfkey32(ar_resp[i], &key)) { if (mfkey32(ar_resp[i], &key)) {
PrintAndLog("Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF)); PrintAndLog(" Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));
for (uint8_t ii = 0; ii<ATTACK_KEY_COUNT; ii++) { for (uint8_t ii = 0; ii<ATTACK_KEY_COUNT; ii++) {
if (key_cnt[ii]==0 || stSector[ii]==ar_resp[i].sector) { if (key_cnt[ii]==0 || stSector[ii]==ar_resp[i].sector) {
@ -1062,7 +1061,6 @@ void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {
if (setEmulatorMem) { if (setEmulatorMem) {
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) { for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {
if (key_cnt[i]>0) { if (key_cnt[i]>0) {
//PrintAndLog ("block %d, keyA:%04x%08x, keyb:%04x%08x",stSector[i]*4+3, (uint32_t) (sector_trailer[i].keyA>>32), (uint32_t) (sector_trailer[i].keyA &0xFFFFFFFF),(uint32_t) (sector_trailer[i].keyB>>32), (uint32_t) (sector_trailer[i].keyB &0xFFFFFFFF));
uint8_t memBlock[16]; uint8_t memBlock[16];
memset(memBlock, 0x00, sizeof(memBlock)); memset(memBlock, 0x00, sizeof(memBlock));
char cmd1[36]; char cmd1[36];
@ -1092,19 +1090,22 @@ void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {
} }
int usage_hf14_mf1ksim(void) { int usage_hf14_mf1ksim(void) {
PrintAndLog("Usage: hf mf sim [h] u <uid (8,14 hex symbols)> n <numreads> i x"); PrintAndLog("Usage: hf mf sim h u <uid (8, 14, or 20 hex symbols)> n <numreads> i x");
PrintAndLog("options:"); PrintAndLog("options:");
PrintAndLog(" h this help"); PrintAndLog(" h this help");
PrintAndLog(" u (Optional) UID 4,7 bytes. If not specified, the UID 4b from emulator memory will be used"); PrintAndLog(" u (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used");
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite"); PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)"); PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");
PrintAndLog(" e (Optional) set keys found from 'reader attack' to emulator memory"); PrintAndLog(" e (Optional) set keys found from 'reader attack' to emulator memory (implies x and i)");
PrintAndLog(" f (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)"); PrintAndLog(" f (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)");
PrintAndLog("samples:"); PrintAndLog("samples:");
PrintAndLog(" hf mf sim u 0a0a0a0a"); PrintAndLog(" hf mf sim u 0a0a0a0a");
PrintAndLog(" hf mf sim u 11223344556677"); PrintAndLog(" hf mf sim u 11223344556677");
PrintAndLog(" hf mf sim u 112233445566778899AA"); PrintAndLog(" hf mf sim u 112233445566778899AA");
PrintAndLog(" hf mf sim f uids.txt");
PrintAndLog(" hf mf sim u 0a0a0a0a e");
return 0; return 0;
} }
@ -1132,6 +1133,9 @@ int CmdHF14AMf1kSim(const char *Cmd) {
case 'e': case 'e':
case 'E': case 'E':
setEmulatorMem = true; setEmulatorMem = true;
//implies x and i
flags |= FLAG_INTERACTIVE;
flags |= FLAG_NR_AR_ATTACK;
cmdp++; cmdp++;
break; break;
case 'f': case 'f':
@ -1142,7 +1146,10 @@ int CmdHF14AMf1kSim(const char *Cmd) {
return 0; return 0;
} }
attackFromFile = true; attackFromFile = true;
cmdp+=2; //implies x and i
flags |= FLAG_INTERACTIVE;
flags |= FLAG_NR_AR_ATTACK;
cmdp += 2;
break; break;
case 'h': case 'h':
case 'H': case 'H':
@ -1166,7 +1173,7 @@ int CmdHF14AMf1kSim(const char *Cmd) {
case 8: flags = FLAG_4B_UID_IN_DATA; break; case 8: flags = FLAG_4B_UID_IN_DATA; break;
default: return usage_hf14_mf1ksim(); default: return usage_hf14_mf1ksim();
} }
cmdp +=2; cmdp += 2;
break; break;
case 'x': case 'x':
case 'X': case 'X':
@ -1183,9 +1190,6 @@ int CmdHF14AMf1kSim(const char *Cmd) {
//Validations //Validations
if(errors) return usage_hf14_mf1ksim(); if(errors) return usage_hf14_mf1ksim();
// attack from file implies nr ar attack and interactive...
if (!(flags & FLAG_NR_AR_ATTACK) && attackFromFile) flags |= FLAG_NR_AR_ATTACK | FLAG_INTERACTIVE;
//get uid from file //get uid from file
if (attackFromFile) { if (attackFromFile) {
int count = 0; int count = 0;
@ -1243,7 +1247,7 @@ int CmdHF14AMf1kSim(const char *Cmd) {
nonces_t ar_resp[ATTACK_KEY_COUNT*2]; nonces_t ar_resp[ATTACK_KEY_COUNT*2];
memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp)); memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));
readerAttack(ar_resp, setEmulatorMem); readerAttack(ar_resp, setEmulatorMem);
if (resp.arg[1]) { if ((bool)resp.arg[1]) {
PrintAndLog("Device button pressed - quitting"); PrintAndLog("Device button pressed - quitting");
fclose(f); fclose(f);
return 4; return 4;
@ -1251,7 +1255,7 @@ int CmdHF14AMf1kSim(const char *Cmd) {
count++; count++;
} }
fclose(f); fclose(f);
} else { } else { //not from file
PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) ", PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) ",
flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4): flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):