1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3 // Copyright (C) 2011 Gerhard de Koning Gans
4 // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende
6 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
7 // at your option, any later version. See the LICENSE.txt file for the text of
9 //-----------------------------------------------------------------------------
10 // High frequency iClass commands
11 //-----------------------------------------------------------------------------
17 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
19 //#include "proxusb.h"
20 #include "proxmark3.h"
22 #include "cmdparser.h"
23 #include "cmdhficlass.h"
27 #include "loclass/des.h"
28 #include "loclass/cipherutils.h"
29 #include "loclass/cipher.h"
30 #include "loclass/ikeys.h"
31 #include "loclass/elite_crack.h"
32 #include "loclass/fileutils.h"
34 static int CmdHelp(const char *Cmd
);
36 int xorbits_8(uint8_t val
)
38 uint8_t res
= val
^ (val
>> 1); //1st pass
39 res
= res
^ (res
>> 1); // 2nd pass
40 res
= res
^ (res
>> 2); // 3rd pass
41 res
= res
^ (res
>> 4); // 4th pass
45 #define ICLASS_CMD_ACTALL 0x0A
46 #define ICLASS_CMD_IDENTIFY 0x0C
47 #define ICLASS_CMD_READ 0x0C
49 #define ICLASS_CMD_SELECT 0x81
50 #define ICLASS_CMD_PAGESEL 0x84
51 #define ICLASS_CMD_READCHECK 0x88
52 #define ICLASS_CMD_CHECK 0x05
53 #define ICLASS_CMD_SOF 0x0F
54 #define ICLASS_CMD_HALT 0x00
57 void explain(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
)
60 if(cmdsize
> 1 && cmd
[0] == ICLASS_CMD_READ
)
62 snprintf(exp
,size
,"READ(%d)",cmd
[1]);
68 case ICLASS_CMD_ACTALL
: snprintf(exp
,size
,"ACTALL"); break;
69 case ICLASS_CMD_IDENTIFY
: snprintf(exp
,size
,"IDENTIFY"); break;
70 case ICLASS_CMD_SELECT
: snprintf(exp
,size
,"SELECT"); break;
71 case ICLASS_CMD_PAGESEL
: snprintf(exp
,size
,"PAGESEL"); break;
72 case ICLASS_CMD_READCHECK
: snprintf(exp
,size
,"READCHECK"); break;
73 case ICLASS_CMD_CHECK
: snprintf(exp
,size
,"CHECK"); break;
74 case ICLASS_CMD_SOF
: snprintf(exp
,size
,"SOF"); break;
75 case ICLASS_CMD_HALT
: snprintf(exp
,size
,"HALT"); break;
76 default: snprintf(exp
,size
,"?"); break;
81 int CmdHFiClassList(const char *Cmd
)
83 bool ShowWaitCycles
= false;
84 char param
= param_getchar(Cmd
, 0);
87 PrintAndLog("List data in trace buffer.");
88 PrintAndLog("Usage: hf iclass list");
89 PrintAndLog("h - help");
90 PrintAndLog("sample: hf iclass list");
94 // for the time being. Need better Bigbuf handling.
95 #define TRACE_SIZE 3000
97 uint8_t trace
[TRACE_SIZE
];
98 GetFromBigBuf(trace
, TRACE_SIZE
, 0);
99 WaitForResponse(CMD_ACK
, NULL
);
101 PrintAndLog("Recorded Activity");
103 PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
104 PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
106 PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Explanation|");
107 PrintAndLog("-----------|-----------|-----|-------------------------------------------------------------------------------------");
109 uint16_t tracepos
= 0;
115 uint32_t first_timestamp
;
116 uint32_t EndOfTransmissionTimestamp
;
117 char explanation
[20] = {0};
120 if(tracepos
>= TRACE_SIZE
) {
124 timestamp
= *((uint32_t *)(trace
+ tracepos
));
126 first_timestamp
= timestamp
;
129 // Break and stick with current result if buffer was not completely full
130 if (timestamp
== 0x44444444) break;
133 duration
= *((uint16_t *)(trace
+ tracepos
));
135 data_len
= *((uint16_t *)(trace
+ tracepos
));
138 if (data_len
& 0x8000) {
145 parity_len
= (data_len
-1)/8 + 1;
147 if (tracepos
+ data_len
+ parity_len
>= TRACE_SIZE
) {
151 uint8_t *frame
= trace
+ tracepos
;
152 tracepos
+= data_len
;
153 uint8_t *parityBytes
= trace
+ tracepos
;
154 tracepos
+= parity_len
;
157 for (int j
= 0; j
< data_len
; j
++) {
158 int oddparity
= 0x01;
162 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
165 uint8_t parityBits
= parityBytes
[j
>>3];
166 if (isResponse
&& (oddparity
!= ((parityBits
>> (7-(j
&0x0007))) & 0x01))) {
167 sprintf(line
[j
/16]+((j
%16)*4), "%02x! ", frame
[j
]);
169 sprintf(line
[j
/16]+((j
%16)*4), "%02x ", frame
[j
]);
177 if(!isResponse
&& data_len
== 4 ) {
178 // Rough guess that this is a command from the reader
179 // For iClass the command byte is not part of the CRC
180 ComputeCrc14443(CRC_ICLASS
, &frame
[1], data_len
-3, &b1
, &b2
);
181 if (b1
!= frame
[data_len
-2] || b2
!= frame
[data_len
-1]) {
186 // For other data.. CRC might not be applicable (UPDATE commands etc.)
187 ComputeCrc14443(CRC_ICLASS
, frame
, data_len
-2, &b1
, &b2
);
188 if (b1
!= frame
[data_len
-2] || b2
!= frame
[data_len
-1]) {
194 EndOfTransmissionTimestamp
= timestamp
+ duration
;
195 explain(explanation
,sizeof(explanation
),frame
,data_len
);
196 int num_lines
= (data_len
- 1)/16 + 1;
197 for (int j
= 0; j
< num_lines
; j
++) {
199 PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
200 (timestamp
- first_timestamp
),
201 (EndOfTransmissionTimestamp
- first_timestamp
),
202 (isResponse
? "Tag" : "Rdr"),
204 (j
== num_lines
-1)?crc
:" ",
207 PrintAndLog(" | | | %-64s| %s",
209 (j
== num_lines
-1)?crc
:" ");
213 bool next_isResponse
= *((uint16_t *)(trace
+ tracepos
+ 6)) & 0x8000;
215 if (ShowWaitCycles
&& !isResponse
&& next_isResponse
) {
216 uint32_t next_timestamp
= *((uint32_t *)(trace
+ tracepos
));
217 if (next_timestamp
!= 0x44444444) {
218 PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
219 (EndOfTransmissionTimestamp
- first_timestamp
),
220 (next_timestamp
- first_timestamp
),
222 (next_timestamp
- EndOfTransmissionTimestamp
));
231 int CmdHFiClassSnoop(const char *Cmd
)
233 UsbCommand c
= {CMD_SNOOP_ICLASS
};
238 int CmdHFiClassSim(const char *Cmd
)
241 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
244 PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
245 PrintAndLog(" options");
246 PrintAndLog(" 0 <CSN> simulate the given CSN");
247 PrintAndLog(" 1 simulate default CSN");
248 PrintAndLog(" 2 iterate CSNs, gather MACs");
249 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
250 PrintAndLog(" sample: hf iclass sim 2");
254 simType
= param_get8(Cmd
, 0);
258 if (param_gethex(Cmd
, 1, CSN
, 16)) {
259 PrintAndLog("A CSN should consist of 16 HEX symbols");
262 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
267 PrintAndLog("Undefined simptype %d", simType
);
270 uint8_t numberOfCSNs
=0;
274 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
275 UsbCommand resp
= {0};
277 /*uint8_t csns[8 * NUM_CSNS] = {
278 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
279 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
280 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
281 0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
282 0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
283 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
284 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
285 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
288 uint8_t csns
[8*NUM_CSNS
] = {
289 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
290 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
291 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
292 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
293 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
294 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
295 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
296 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
297 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
298 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
299 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
300 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
301 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
302 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
303 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
305 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
308 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
309 PrintAndLog("Command timed out");
313 uint8_t num_mac_responses
= resp
.arg
[1];
314 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
316 size_t datalen
= NUM_CSNS
*24;
318 * Now, time to dump to file. We'll use this format:
319 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
320 * So, it should wind up as
323 * The returndata from the pm3 is on the following format
324 * <4 byte NR><4 byte MAC>
325 * CC are all zeroes, CSN is the same as was sent in
327 void* dump
= malloc(datalen
);
328 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
330 for(i
= 0 ; i
< NUM_CSNS
; i
++)
332 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
333 //8 zero bytes here...
334 //Then comes NR_MAC (eight bytes from the response)
335 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
338 /** Now, save to dumpfile **/
339 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
343 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
344 memcpy(c
.d
.asBytes
, CSN
, 8);
351 int CmdHFiClassReader(const char *Cmd
)
353 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
357 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
358 uint8_t isOK
= resp
.arg
[0] & 0xff;
359 uint8_t * data
= resp
.d
.asBytes
;
361 PrintAndLog("isOk:%02x", isOK
);
364 PrintAndLog("Quitting...");
369 PrintAndLog("CSN: %s",sprint_hex(data
,8));
373 PrintAndLog("CC: %s",sprint_hex(data
+8,8));
375 PrintAndLog("No CC obtained");
378 PrintAndLog("Command execute timeout");
385 int CmdHFiClassReader_Replay(const char *Cmd
)
387 uint8_t readerType
= 0;
388 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
391 PrintAndLog("Usage: hf iclass replay <MAC>");
392 PrintAndLog(" sample: hf iclass replay 00112233");
396 if (param_gethex(Cmd
, 0, MAC
, 8)) {
397 PrintAndLog("MAC must include 8 HEX symbols");
401 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
402 memcpy(c
.d
.asBytes
, MAC
, 4);
408 int CmdHFiClassReader_Dump(const char *Cmd
)
410 uint8_t readerType
= 0;
411 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
412 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
413 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
414 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
415 //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
416 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
417 uint8_t keytable
[128] = {0};
423 PrintAndLog("Usage: hf iclass dump <Key> [e]");
424 PrintAndLog(" Key - A 16 byte master key");
425 PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
426 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
427 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
428 PrintAndLog(" sample: hf iclass dump 0011223344556677");
434 if (param_gethex(Cmd
, 0, KEY
, 16))
436 PrintAndLog("KEY must include 16 HEX symbols");
440 if (param_getchar(Cmd
, 1) == 'e')
442 PrintAndLog("Elite switch on");
446 hash2(KEY
, keytable
);
447 printarr_human_readable("keytable", keytable
, 128);
452 uint8_t key_sel
[8] = {0};
453 uint8_t key_sel_p
[8] = { 0 };
455 //HACK -- Below is for testing without access to a tag
456 uint8_t fake_dummy_test
= false;
459 uint8_t xdata
[16] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0, //CSN from http://www.proxmark.org/forum/viewtopic.php?pid=11230#p11230
460 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Just a random CC. Would be good to add a real testcase here
461 memcpy(resp
.d
.asBytes
,xdata
, 16);
468 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
469 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_GET_CC
;
475 if (fake_dummy_test
|| WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
476 uint8_t isOK
= resp
.arg
[0] & 0xff;
477 uint8_t * data
= resp
.d
.asBytes
;
480 memcpy(CCNR
,data
+8,8);
482 PrintAndLog("isOk:%02x", isOK
);
486 PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
492 //Get the key index (hash1)
493 uint8_t key_index
[8] = {0};
495 hash1(CSN
, key_index
);
496 printvar("hash1", key_index
,8);
497 for(i
= 0; i
< 8 ; i
++)
498 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
499 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
500 printvar("k_sel", key_sel
,8);
501 //Permute from iclass format to standard format
502 permutekey_rev(key_sel
,key_sel_p
);
503 used_key
= key_sel_p
;
505 //Perhaps this should also be permuted to std format?
506 // Something like the code below? I have no std system
507 // to test this with /Martin
509 //uint8_t key_sel_p[8] = { 0 };
510 //permutekey_rev(KEY,key_sel_p);
511 //used_key = key_sel_p;
517 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
518 printvar("Used key",used_key
,8);
519 diversifyKey(CSN
,used_key
, div_key
);
520 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
521 printvar("Div key", div_key
, 8);
522 printvar("CC_NR:",CCNR
,12);
523 doMAC(CCNR
,12,div_key
, MAC
);
524 printvar("MAC", MAC
, 4);
526 UsbCommand d
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
527 memcpy(d
.d
.asBytes
, MAC
, 4);
528 if(!fake_dummy_test
) SendCommand(&d
);
531 PrintAndLog("Failed to obtain CC! Aborting");
534 PrintAndLog("Command execute timeout");
540 int CmdHFiClass_iso14443A_write(const char *Cmd
)
542 uint8_t readerType
= 0;
543 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
544 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
545 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
546 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
547 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
550 uint8_t bldata
[8]={0};
554 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
555 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
559 if (param_gethex(Cmd
, 0, KEY
, 16))
561 PrintAndLog("KEY must include 16 HEX symbols");
565 blockNo
= param_get8(Cmd
, 1);
568 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
571 if (param_gethex(Cmd
, 2, bldata
, 8))
573 PrintAndLog("Block data must include 8 HEX symbols");
577 UsbCommand c
= {CMD_ICLASS_ISO14443A_WRITE
, {0}};
581 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
582 uint8_t isOK
= resp
.arg
[0] & 0xff;
583 uint8_t * data
= resp
.d
.asBytes
;
586 memcpy(CCNR
,data
+8,8);
587 PrintAndLog("DEBUG: %s",sprint_hex(CSN
,8));
588 PrintAndLog("DEBUG: %s",sprint_hex(CCNR
,8));
589 PrintAndLog("isOk:%02x", isOK
);
591 PrintAndLog("Command execute timeout");
594 diversifyKey(CSN
,KEY
, div_key
);
596 PrintAndLog("Div Key: %s",sprint_hex(div_key
,8));
597 doMAC(CCNR
, 12,div_key
, MAC
);
599 UsbCommand c2
= {CMD_ICLASS_ISO14443A_WRITE
, {readerType
,blockNo
}};
600 memcpy(c2
.d
.asBytes
, bldata
, 8);
601 memcpy(c2
.d
.asBytes
+8, MAC
, 4);
604 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
605 uint8_t isOK
= resp
.arg
[0] & 0xff;
606 uint8_t * data
= resp
.d
.asBytes
;
609 PrintAndLog("isOk:%02x data:%s", isOK
, sprint_hex(data
, 4));
611 PrintAndLog("isOk:%02x", isOK
);
613 PrintAndLog("Command execute timeout");
619 static command_t CommandTable
[] =
621 {"help", CmdHelp
, 1, "This help"},
622 {"list", CmdHFiClassList
, 0, "List iClass history"},
623 {"snoop", CmdHFiClassSnoop
, 0, "Eavesdrop iClass communication"},
624 {"sim", CmdHFiClassSim
, 0, "Simulate iClass tag"},
625 {"reader",CmdHFiClassReader
, 0, "Read an iClass tag"},
626 {"replay",CmdHFiClassReader_Replay
, 0, "Read an iClass tag via Reply Attack"},
627 {"dump", CmdHFiClassReader_Dump
, 0, "Authenticate and Dump iClass tag"},
628 {"write", CmdHFiClass_iso14443A_write
, 0, "Authenticate and Write iClass block"},
629 {NULL
, NULL
, 0, NULL
}
632 int CmdHFiClass(const char *Cmd
)
634 CmdsParse(CommandTable
, Cmd
);
638 int CmdHelp(const char *Cmd
)
640 CmdsHelp(CommandTable
);