## [unreleased][unreleased]
### 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)
see https://media.ccc.de/v/32c3-7166-sicherheit_von_125khz_transpondern_am_beispiel_hitag_s
English video available
- `lf t55xx wipe` - sets t55xx back to factory defaults
- Added viking demod to `lf search` (marshmellow)
- `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow)
-- `lf t55xx resetread` added reset then read command - should allow determining start
-of stream transmissions (marshmellow)
+- `lf t55xx resetread` added reset then read command - should allow determining start of stream transmissions (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 readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow)
- Added option c to 'hf list' (mark CRC bytes) (piwi)
### Changed
-- Added `[l] <length>` option to data printdemodbuffer
-- Adjusted lf awid clone to optionally clone to Q5 tags
-- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7
-- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal)
-- Adjusted lf pskindalademod to reduce false positive reads.
-- Small adjustments to psk, nrz, and ask clock detect routines - more reliable.
-- Adjusted lf em410x em410xsim to accept a clock argument
+- Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow)
+- Fixed bug in lf viking clone/sim (iceman)
+- Fixed broken `data askedgedetect` (marshmellow)
+- Adjusted hf mf sim command (marshmellow)
+ added auto run mfkey32 to extract all keys
+ also added f parameter to allow attacking with UIDs from a file (implies x and i parameters)
+ 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 write input variables (marshmellow)
- 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)
- `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)
-- `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)
- 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)
{
int cardSTATE = MFEMUL_NOFIELD;
int _UID_LEN = 0; // 4, 7, 10
- int _7BUID = 0;
int vHf = 0; // in mV
int res;
uint32_t selTimer = 0;
uint8_t response[MAX_MIFARE_FRAME_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 rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
- uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
- uint8_t rSAK1[] = {0x04, 0xda, 0x17};
- uint8_t rSAK2[] = {0x04, 0xda, 0x17}; //need to look up
+ uint8_t rSAKfinal[]= {0x08, 0xb6, 0xdd}; // mifare 1k indicated
+ uint8_t rSAK1[] = {0x04, 0xda, 0x17}; // indicate UID not finished
uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
//Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
// This will be used in the reader-only attack.
- //allow collecting up to 8 sets of nonces to allow recovery of 8 keys
- #define ATTACK_KEY_COUNT 8
+ //allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys
+ #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
memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
// 7B uid comes from data-portion of packet
memcpy(&rUIDBCC1[1],datain,3);
memcpy(rUIDBCC2, datain+3, 4);
- _7BUID = true;
_UID_LEN = 7;
} else if (flags & FLAG_10B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3);
} else {
// get UID from emul memory - guess at length
emlGetMemBt(receivedCmd, 7, 1);
- _7BUID = !(receivedCmd[0] == 0x00);
- if (!_7BUID) { // ---------- 4BUID
+ if (receivedCmd[0] == 0x00) { // ---------- 4BUID
emlGetMemBt(rUIDBCC1, 0, 4);
_UID_LEN = 4;
} else { // ---------- 7BUID
break;
}
case MFEMUL_SELECT1:{
- // select all
- if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
+ // select all - 0x93 0x20
+ if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) {
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received");
EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
break;
}
- if (MF_DBGLEVEL >= 4 && len == 9 && receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 )
- {
- Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
- }
- // select card
- // check correct sak values... (marshmellow)
- if (len == 9 &&
- (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
+ // select card - 0x93 0x70 ...
+ if (len == 9 &&
+ (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
+ if (MF_DBGLEVEL >= 4)
+ Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
+
switch(_UID_LEN) {
case 4:
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
- EmSendCmd(rSAK, sizeof(rSAK));
+ EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
break;
case 7:
cardSTATE = MFEMUL_SELECT2;
break;
case 10:
cardSTATE = MFEMUL_SELECT2;
- EmSendCmd(rSAK2, sizeof(rSAK2));
+ EmSendCmd(rSAK1, sizeof(rSAK1));
break;
default:break;
}
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break;
}
+ // select all cl3 - 0x97 0x20
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) {
EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3));
break;
}
+ // select card cl3 - 0x97 0x70
if (len == 9 &&
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 &&
receivedCmd[1] == 0x70 &&
memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) {
- EmSendCmd(rSAK2, sizeof(rSAK2));
+ EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer);
break;
}
case MFEMUL_AUTH1:{
- if( len != 8)
- {
+ if( len != 8) {
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);
break;
uint32_t nr = bytes_to_num(receivedCmd, 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) {
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)) ) {
ar_nr_resp[i+mM].nr = nr;
ar_nr_resp[i+mM].ar = ar;
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].sector = cardAUTHSC;
ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY;
ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr;
ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar;
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].nr2 = nr;
ar_nr_resp[i+mM].ar2 = ar;
if (!gettingMoebius) {
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 ) {
- //done collecting std test switch to moebius
- //finish incrementing last sample
+ // done collecting std test switch to moebius
+ // first finish incrementing last sample
ar_nr_collected[i+mM]++;
- //switch to moebius collection
+ // switch to moebius collection
gettingMoebius = true;
mM = ATTACK_KEY_COUNT;
nonce = nonce*7;
}
} else {
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;
}
}
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
break;
if (!len) {
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
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));
break;
}
- // select 2 card
+ // select cl2 card - 0x95 0x70 xxxxxxxxxxxx
if (len == 9 &&
- (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
- //which sak now? (marshmellow)
- EmSendCmd(rSAK, sizeof(rSAK));
+ (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
switch(_UID_LEN) {
case 7:
+ EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
break;
case 10:
+ EmSendCmd(rSAK1, sizeof(rSAK1));
cardSTATE = MFEMUL_SELECT3;
break;
default:break;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
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++) {
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);
}
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
cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,button_pushed,0,&ar_nr_resp,sizeof(ar_nr_resp));
}
}
-
//-----------------------------------------------------------------------------
// MIFARE sniffer.
//
}\r
\r
void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {\r
- #define ATTACK_KEY_COUNT 8\r
+ #define ATTACK_KEY_COUNT 8 // keep same as define in iso14443a.c -> Mifare1ksim()\r
uint64_t key = 0;\r
typedef struct {\r
uint64_t keyA;\r
- uint32_t security;\r
uint64_t keyB;\r
} st_t;\r
st_t sector_trailer[ATTACK_KEY_COUNT];\r
\r
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {\r
if (ar_resp[i].ar2 > 0) {\r
- //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);\r
+ //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);\r
if (mfkey32(ar_resp[i], &key)) {\r
- 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));\r
+ 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));\r
\r
for (uint8_t ii = 0; ii<ATTACK_KEY_COUNT; ii++) {\r
if (key_cnt[ii]==0 || stSector[ii]==ar_resp[i].sector) {\r
if (setEmulatorMem) {\r
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {\r
if (key_cnt[i]>0) {\r
- //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));\r
uint8_t memBlock[16];\r
memset(memBlock, 0x00, sizeof(memBlock));\r
char cmd1[36];\r
}\r
\r
int usage_hf14_mf1ksim(void) {\r
- PrintAndLog("Usage: hf mf sim [h] u <uid (8,14 hex symbols)> n <numreads> i x");\r
+ PrintAndLog("Usage: hf mf sim h u <uid (8, 14, or 20 hex symbols)> n <numreads> i x");\r
PrintAndLog("options:");\r
PrintAndLog(" h this help");\r
- PrintAndLog(" u (Optional) UID 4,7 bytes. If not specified, the UID 4b from emulator memory will be used");\r
+ PrintAndLog(" u (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used");\r
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");\r
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");\r
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");\r
- PrintAndLog(" e (Optional) set keys found from 'reader attack' to emulator memory");\r
+ PrintAndLog(" e (Optional) set keys found from 'reader attack' to emulator memory (implies x and i)");\r
PrintAndLog(" f (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)");\r
PrintAndLog("samples:");\r
PrintAndLog(" hf mf sim u 0a0a0a0a");\r
PrintAndLog(" hf mf sim u 11223344556677");\r
- PrintAndLog(" hf mf sim u 112233445566778899AA"); \r
+ PrintAndLog(" hf mf sim u 112233445566778899AA");\r
+ PrintAndLog(" hf mf sim f uids.txt");\r
+ PrintAndLog(" hf mf sim u 0a0a0a0a e");\r
+ \r
return 0;\r
}\r
\r
case 'e':\r
case 'E':\r
setEmulatorMem = true;\r
+ //implies x and i\r
+ flags |= FLAG_INTERACTIVE;\r
+ flags |= FLAG_NR_AR_ATTACK;\r
cmdp++;\r
break;\r
case 'f':\r
return 0;\r
}\r
attackFromFile = true;\r
- cmdp+=2;\r
+ //implies x and i\r
+ flags |= FLAG_INTERACTIVE;\r
+ flags |= FLAG_NR_AR_ATTACK;\r
+ cmdp += 2;\r
break;\r
case 'h':\r
case 'H':\r
case 8: flags = FLAG_4B_UID_IN_DATA; break;\r
default: return usage_hf14_mf1ksim();\r
}\r
- cmdp +=2;\r
+ cmdp += 2;\r
break;\r
case 'x':\r
case 'X':\r
//Validations\r
if(errors) return usage_hf14_mf1ksim();\r
\r
- // attack from file implies nr ar attack and interactive...\r
- if (!(flags & FLAG_NR_AR_ATTACK) && attackFromFile) flags |= FLAG_NR_AR_ATTACK | FLAG_INTERACTIVE;\r
- \r
//get uid from file\r
if (attackFromFile) {\r
int count = 0;\r
nonces_t ar_resp[ATTACK_KEY_COUNT*2];\r
memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));\r
readerAttack(ar_resp, setEmulatorMem);\r
- if (resp.arg[1]) {\r
+ if ((bool)resp.arg[1]) {\r
PrintAndLog("Device button pressed - quitting");\r
fclose(f);\r
return 4;\r
count++;\r
}\r
fclose(f);\r
- } else {\r
+ } else { //not from file\r
\r
PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) ",\r
flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):\r