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 int CmdHFiClassList(const char *Cmd
)
47 bool ShowWaitCycles
= false;
48 char param
= param_getchar(Cmd
, 0);
51 PrintAndLog("List data in trace buffer.");
52 PrintAndLog("Usage: hf iclass list");
53 PrintAndLog("h - help");
54 PrintAndLog("sample: hf iclass list");
58 // for the time being. Need better Bigbuf handling.
59 #define TRACE_SIZE 3000
61 uint8_t trace
[TRACE_SIZE
];
62 GetFromBigBuf(trace
, TRACE_SIZE
, 0);
63 WaitForResponse(CMD_ACK
, NULL
);
65 PrintAndLog("Recorded Activity");
67 PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
68 PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
70 PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC ");
71 PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------");
73 uint16_t tracepos
= 0;
79 uint32_t first_timestamp
;
80 uint32_t EndOfTransmissionTimestamp
;
84 if(tracepos
>= TRACE_SIZE
) {
88 timestamp
= *((uint32_t *)(trace
+ tracepos
));
90 first_timestamp
= timestamp
;
93 // Break and stick with current result if buffer was not completely full
94 if (timestamp
== 0x44444444) break;
97 duration
= *((uint16_t *)(trace
+ tracepos
));
99 data_len
= *((uint16_t *)(trace
+ tracepos
));
102 if (data_len
& 0x8000) {
109 parity_len
= (data_len
-1)/8 + 1;
111 if (tracepos
+ data_len
+ parity_len
>= TRACE_SIZE
) {
115 uint8_t *frame
= trace
+ tracepos
;
116 tracepos
+= data_len
;
117 uint8_t *parityBytes
= trace
+ tracepos
;
118 tracepos
+= parity_len
;
121 for (int j
= 0; j
< data_len
; j
++) {
122 int oddparity
= 0x01;
126 oddparity
^= (((frame
[j
] & 0xFF) >> k
) & 0x01);
129 uint8_t parityBits
= parityBytes
[j
>>3];
130 if (isResponse
&& (oddparity
!= ((parityBits
>> (7-(j
&0x0007))) & 0x01))) {
131 sprintf(line
[j
/16]+((j
%16)*4), "%02x! ", frame
[j
]);
133 sprintf(line
[j
/16]+((j
%16)*4), "%02x ", frame
[j
]);
141 if(!isResponse
&& data_len
== 4 ) {
142 // Rough guess that this is a command from the reader
143 // For iClass the command byte is not part of the CRC
144 ComputeCrc14443(CRC_ICLASS
, &frame
[1], data_len
-3, &b1
, &b2
);
145 if (b1
!= frame
[data_len
-2] || b2
!= frame
[data_len
-1]) {
150 // For other data.. CRC might not be applicable (UPDATE commands etc.)
151 ComputeCrc14443(CRC_ICLASS
, frame
, data_len
-2, &b1
, &b2
);
152 if (b1
!= frame
[data_len
-2] || b2
!= frame
[data_len
-1]) {
158 EndOfTransmissionTimestamp
= timestamp
+ duration
;
160 int num_lines
= (data_len
- 1)/16 + 1;
161 for (int j
= 0; j
< num_lines
; j
++) {
163 PrintAndLog(" %9d | %9d | %s | %-64s| %s",
164 (timestamp
- first_timestamp
),
165 (EndOfTransmissionTimestamp
- first_timestamp
),
166 (isResponse
? "Tag" : "Rdr"),
168 (j
== num_lines
-1)?crc
:"");
170 PrintAndLog(" | | | %-64s| %s",
172 (j
== num_lines
-1)?crc
:"");
176 bool next_isResponse
= *((uint16_t *)(trace
+ tracepos
+ 6)) & 0x8000;
178 if (ShowWaitCycles
&& !isResponse
&& next_isResponse
) {
179 uint32_t next_timestamp
= *((uint32_t *)(trace
+ tracepos
));
180 if (next_timestamp
!= 0x44444444) {
181 PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
182 (EndOfTransmissionTimestamp
- first_timestamp
),
183 (next_timestamp
- first_timestamp
),
185 (next_timestamp
- EndOfTransmissionTimestamp
));
194 int CmdHFiClassSnoop(const char *Cmd
)
196 UsbCommand c
= {CMD_SNOOP_ICLASS
};
201 int CmdHFiClassSim(const char *Cmd
)
204 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
207 PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
208 PrintAndLog(" options");
209 PrintAndLog(" 0 <CSN> simulate the given CSN");
210 PrintAndLog(" 1 simulate default CSN");
211 PrintAndLog(" 2 iterate CSNs, gather MACs");
212 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
213 PrintAndLog(" sample: hf iclass sim 2");
217 simType
= param_get8(Cmd
, 0);
221 if (param_gethex(Cmd
, 1, CSN
, 16)) {
222 PrintAndLog("A CSN should consist of 16 HEX symbols");
225 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
230 PrintAndLog("Undefined simptype %d", simType
);
233 uint8_t numberOfCSNs
=0;
237 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
238 UsbCommand resp
= {0};
240 /*uint8_t csns[8 * NUM_CSNS] = {
241 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
242 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
243 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
244 0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
245 0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
246 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
247 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
248 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
251 uint8_t csns
[8*NUM_CSNS
] = {
252 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
253 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
254 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
255 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
256 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
257 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
258 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
259 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
260 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
261 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
262 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
263 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
264 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
265 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
266 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
268 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
271 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
272 PrintAndLog("Command timed out");
276 uint8_t num_mac_responses
= resp
.arg
[1];
277 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
279 size_t datalen
= NUM_CSNS
*24;
281 * Now, time to dump to file. We'll use this format:
282 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
283 * So, it should wind up as
286 * The returndata from the pm3 is on the following format
287 * <4 byte NR><4 byte MAC>
288 * CC are all zeroes, CSN is the same as was sent in
290 void* dump
= malloc(datalen
);
291 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
293 for(i
= 0 ; i
< NUM_CSNS
; i
++)
295 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
296 //8 zero bytes here...
297 //Then comes NR_MAC (eight bytes from the response)
298 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
301 /** Now, save to dumpfile **/
302 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
306 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
307 memcpy(c
.d
.asBytes
, CSN
, 8);
314 int CmdHFiClassReader(const char *Cmd
)
316 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
320 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
321 uint8_t isOK
= resp
.arg
[0] & 0xff;
322 uint8_t * data
= resp
.d
.asBytes
;
324 PrintAndLog("isOk:%02x", isOK
);
328 PrintAndLog("CSN: %s",sprint_hex(data
,8));
332 PrintAndLog("CC: %s",sprint_hex(data
+8,8));
334 PrintAndLog("No CC obtained");
337 PrintAndLog("Command execute timeout");
344 int CmdHFiClassReader_Replay(const char *Cmd
)
346 uint8_t readerType
= 0;
347 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
350 PrintAndLog("Usage: hf iclass replay <MAC>");
351 PrintAndLog(" sample: hf iclass replay 00112233");
355 if (param_gethex(Cmd
, 0, MAC
, 8)) {
356 PrintAndLog("MAC must include 8 HEX symbols");
360 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
361 memcpy(c
.d
.asBytes
, MAC
, 4);
367 int CmdHFiClassReader_Dump(const char *Cmd
)
369 uint8_t readerType
= 0;
370 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
371 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
372 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
373 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
374 //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
375 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
376 uint8_t keytable
[128] = {0};
382 PrintAndLog("Usage: hf iclass dump <Key> [e]");
383 PrintAndLog(" Key - A 16 byte master key");
384 PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
385 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
386 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
387 PrintAndLog(" sample: hf iclass dump 0011223344556677");
393 if (param_gethex(Cmd
, 0, KEY
, 16))
395 PrintAndLog("KEY must include 16 HEX symbols");
399 if (param_getchar(Cmd
, 1) == 'e')
401 PrintAndLog("Elite switch on");
405 hash2(KEY
, keytable
);
406 printarr_human_readable("keytable", keytable
, 128);
411 uint8_t key_sel
[8] = {0};
412 uint8_t key_sel_p
[8] = { 0 };
414 //HACK -- Below is for testing without access to a tag
415 uint8_t fake_dummy_test
= false;
418 uint8_t xdata
[16] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0, //CSN from http://www.proxmark.org/forum/viewtopic.php?pid=11230#p11230
419 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Just a random CC. Would be good to add a real testcase here
420 memcpy(resp
.d
.asBytes
,xdata
, 16);
427 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
428 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
;
434 if (fake_dummy_test
|| WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
435 uint8_t isOK
= resp
.arg
[0] & 0xff;
436 uint8_t * data
= resp
.d
.asBytes
;
439 memcpy(CCNR
,data
+8,8);
441 PrintAndLog("isOk:%02x", isOK
);
445 PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
451 //Get the key index (hash1)
452 uint8_t key_index
[8] = {0};
454 hash1(CSN
, key_index
);
455 printvar("hash1", key_index
,8);
456 for(i
= 0; i
< 8 ; i
++)
457 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
458 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
459 printvar("k_sel", key_sel
,8);
460 //Permute from iclass format to standard format
461 permutekey_rev(key_sel
,key_sel_p
);
462 used_key
= key_sel_p
;
464 //Perhaps this should also be permuted to std format?
465 // Something like the code below? I have no std system
466 // to test this with /Martin
468 //uint8_t key_sel_p[8] = { 0 };
469 //permutekey_rev(KEY,key_sel_p);
470 //used_key = key_sel_p;
476 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
477 printvar("Used key",used_key
,8);
478 diversifyKey(CSN
,used_key
, div_key
);
479 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
480 printvar("Div key", div_key
, 8);
481 printvar("CC_NR:",CCNR
,12);
482 doMAC(CCNR
,12,div_key
, MAC
);
483 printvar("MAC", MAC
, 4);
485 UsbCommand d
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
486 memcpy(d
.d
.asBytes
, MAC
, 4);
487 if(!fake_dummy_test
) SendCommand(&d
);
490 PrintAndLog("Failed to obtain CC! Aborting");
493 PrintAndLog("Command execute timeout");
499 int CmdHFiClass_iso14443A_write(const char *Cmd
)
501 uint8_t readerType
= 0;
502 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
503 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
504 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
505 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
506 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
509 uint8_t bldata
[8]={0};
513 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
514 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
518 if (param_gethex(Cmd
, 0, KEY
, 16))
520 PrintAndLog("KEY must include 16 HEX symbols");
524 blockNo
= param_get8(Cmd
, 1);
527 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
530 if (param_gethex(Cmd
, 2, bldata
, 8))
532 PrintAndLog("Block data must include 8 HEX symbols");
536 UsbCommand c
= {CMD_ICLASS_ISO14443A_WRITE
, {0}};
540 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
541 uint8_t isOK
= resp
.arg
[0] & 0xff;
542 uint8_t * data
= resp
.d
.asBytes
;
545 memcpy(CCNR
,data
+8,8);
546 PrintAndLog("DEBUG: %s",sprint_hex(CSN
,8));
547 PrintAndLog("DEBUG: %s",sprint_hex(CCNR
,8));
548 PrintAndLog("isOk:%02x", isOK
);
550 PrintAndLog("Command execute timeout");
553 diversifyKey(CSN
,KEY
, div_key
);
555 PrintAndLog("Div Key: %s",sprint_hex(div_key
,8));
556 doMAC(CCNR
, 12,div_key
, MAC
);
558 UsbCommand c2
= {CMD_ICLASS_ISO14443A_WRITE
, {readerType
,blockNo
}};
559 memcpy(c2
.d
.asBytes
, bldata
, 8);
560 memcpy(c2
.d
.asBytes
+8, MAC
, 4);
563 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
564 uint8_t isOK
= resp
.arg
[0] & 0xff;
565 uint8_t * data
= resp
.d
.asBytes
;
568 PrintAndLog("isOk:%02x data:%s", isOK
, sprint_hex(data
, 4));
570 PrintAndLog("isOk:%02x", isOK
);
572 PrintAndLog("Command execute timeout");
578 static command_t CommandTable
[] =
580 {"help", CmdHelp
, 1, "This help"},
581 {"list", CmdHFiClassList
, 0, "List iClass history"},
582 {"snoop", CmdHFiClassSnoop
, 0, "Eavesdrop iClass communication"},
583 {"sim", CmdHFiClassSim
, 0, "Simulate iClass tag"},
584 {"reader",CmdHFiClassReader
, 0, "Read an iClass tag"},
585 {"replay",CmdHFiClassReader_Replay
, 0, "Read an iClass tag via Reply Attack"},
586 {"dump", CmdHFiClassReader_Dump
, 0, "Authenticate and Dump iClass tag"},
587 {"write", CmdHFiClass_iso14443A_write
, 0, "Authenticate and Write iClass block"},
588 {NULL
, NULL
, 0, NULL
}
591 int CmdHFiClass(const char *Cmd
)
593 CmdsParse(CommandTable
, Cmd
);
597 int CmdHelp(const char *Cmd
)
599 CmdsHelp(CommandTable
);