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 "proxmark3.h"
21 #include "cmdparser.h"
22 #include "cmdhficlass.h"
26 #include "loclass/des.h"
27 #include "loclass/cipherutils.h"
28 #include "loclass/cipher.h"
29 #include "loclass/ikeys.h"
30 #include "loclass/elite_crack.h"
31 #include "loclass/fileutils.h"
33 static int CmdHelp(const char *Cmd
);
35 int xorbits_8(uint8_t val
)
37 uint8_t res
= val
^ (val
>> 1); //1st pass
38 res
= res
^ (res
>> 1); // 2nd pass
39 res
= res
^ (res
>> 2); // 3rd pass
40 res
= res
^ (res
>> 4); // 4th pass
44 int CmdHFiClassList(const char *Cmd
)
46 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
50 int CmdHFiClassSnoop(const char *Cmd
)
52 UsbCommand c
= {CMD_SNOOP_ICLASS
};
57 int CmdHFiClassSim(const char *Cmd
)
60 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
63 PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
64 PrintAndLog(" options");
65 PrintAndLog(" 0 <CSN> simulate the given CSN");
66 PrintAndLog(" 1 simulate default CSN");
67 PrintAndLog(" 2 iterate CSNs, gather MACs");
68 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
69 PrintAndLog(" sample: hf iclass sim 2");
73 simType
= param_get8(Cmd
, 0);
77 if (param_gethex(Cmd
, 1, CSN
, 16)) {
78 PrintAndLog("A CSN should consist of 16 HEX symbols");
81 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
86 PrintAndLog("Undefined simptype %d", simType
);
89 uint8_t numberOfCSNs
=0;
93 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
94 UsbCommand resp
= {0};
96 /*uint8_t csns[8 * NUM_CSNS] = {
97 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
98 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
99 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
100 0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
101 0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
102 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
103 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
104 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
107 uint8_t csns
[8*NUM_CSNS
] = {
108 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
109 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
110 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
111 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
112 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
113 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
114 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
115 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
116 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
117 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
118 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
119 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
120 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
121 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
122 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
124 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
127 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
128 PrintAndLog("Command timed out");
132 uint8_t num_mac_responses
= resp
.arg
[1];
133 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
135 size_t datalen
= NUM_CSNS
*24;
137 * Now, time to dump to file. We'll use this format:
138 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
139 * So, it should wind up as
142 * The returndata from the pm3 is on the following format
143 * <4 byte NR><4 byte MAC>
144 * CC are all zeroes, CSN is the same as was sent in
146 void* dump
= malloc(datalen
);
147 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
149 for(i
= 0 ; i
< NUM_CSNS
; i
++)
151 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
152 //8 zero bytes here...
153 //Then comes NR_MAC (eight bytes from the response)
154 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
157 /** Now, save to dumpfile **/
158 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
162 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
163 memcpy(c
.d
.asBytes
, CSN
, 8);
170 int CmdHFiClassReader(const char *Cmd
)
172 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
176 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
177 uint8_t isOK
= resp
.arg
[0] & 0xff;
178 uint8_t * data
= resp
.d
.asBytes
;
180 PrintAndLog("isOk:%02x", isOK
);
183 PrintAndLog("Quitting...");
188 PrintAndLog("CSN: %s",sprint_hex(data
,8));
192 PrintAndLog("CC: %s",sprint_hex(data
+8,8));
194 PrintAndLog("No CC obtained");
197 PrintAndLog("Command execute timeout");
204 int CmdHFiClassReader_Replay(const char *Cmd
)
206 uint8_t readerType
= 0;
207 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
210 PrintAndLog("Usage: hf iclass replay <MAC>");
211 PrintAndLog(" sample: hf iclass replay 00112233");
215 if (param_gethex(Cmd
, 0, MAC
, 8)) {
216 PrintAndLog("MAC must include 8 HEX symbols");
220 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
221 memcpy(c
.d
.asBytes
, MAC
, 4);
227 int CmdHFiClassReader_Dump(const char *Cmd
)
229 uint8_t readerType
= 0;
230 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
231 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
232 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
233 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
234 //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
235 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
236 uint8_t keytable
[128] = {0};
242 PrintAndLog("Usage: hf iclass dump <Key> [e]");
243 PrintAndLog(" Key - A 16 byte master key");
244 PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
245 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
246 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
247 PrintAndLog(" sample: hf iclass dump 0011223344556677");
253 if (param_gethex(Cmd
, 0, KEY
, 16))
255 PrintAndLog("KEY must include 16 HEX symbols");
259 if (param_getchar(Cmd
, 1) == 'e')
261 PrintAndLog("Elite switch on");
265 hash2(KEY
, keytable
);
266 printarr_human_readable("keytable", keytable
, 128);
271 uint8_t key_sel
[8] = {0};
272 uint8_t key_sel_p
[8] = { 0 };
274 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
275 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_GET_CC
;
280 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
282 PrintAndLog("Command execute timeout");
286 uint8_t isOK
= resp
.arg
[0] & 0xff;
287 uint8_t * data
= resp
.d
.asBytes
;
290 memcpy(CCNR
,data
+8,8);
292 PrintAndLog("isOk:%02x", isOK
);
296 PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
299 PrintAndLog("Failed to obtain CC! Aborting");
306 //Get the key index (hash1)
307 uint8_t key_index
[8] = {0};
309 hash1(CSN
, key_index
);
310 printvar("hash1", key_index
,8);
311 for(i
= 0; i
< 8 ; i
++)
312 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
313 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
314 printvar("k_sel", key_sel
,8);
315 //Permute from iclass format to standard format
316 permutekey_rev(key_sel
,key_sel_p
);
317 used_key
= key_sel_p
;
322 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
323 printvar("Used key",used_key
,8);
324 diversifyKey(CSN
,used_key
, div_key
);
325 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
326 printvar("Div key", div_key
, 8);
327 printvar("CC_NR:",CCNR
,12);
328 doMAC(CCNR
,12,div_key
, MAC
);
329 printvar("MAC", MAC
, 4);
331 uint8_t iclass_data
[32000] = {0};
332 uint32_t iclass_datalen
= 0;
333 uint32_t iclass_blocksFailed
= 0;//Set to 1 if dump was incomplete
335 UsbCommand d
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
336 memcpy(d
.d
.asBytes
, MAC
, 4);
337 clearCommandBuffer();
339 PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
344 printf("\naborted via keyboard!\n");
347 if(WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
349 uint32_t dataLength
= resp
.arg
[0];
350 iclass_blocksFailed
|= resp
.arg
[1];
353 PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength
,iclass_datalen
);
354 memcpy(iclass_data
, resp
.d
.asBytes
,dataLength
);
355 iclass_datalen
+= dataLength
;
357 {//Last transfer, datalength 0 means the dump is finished
358 PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen
);
359 if(iclass_blocksFailed
)
361 PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
363 if(iclass_datalen
> 0)
365 char filename
[100] = {0};
366 //create a preferred filename
367 snprintf(filename
, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
368 CSN
[0],CSN
[1],CSN
[2],CSN
[3],
369 CSN
[4],CSN
[5],CSN
[6],CSN
[7]);
370 saveFile(filename
,"bin",iclass_data
, iclass_datalen
);
372 //Aaaand we're finished
382 int hf_iclass_eload_usage()
384 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
385 PrintAndLog("Usage: hf iclass eload f <filename>");
387 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
392 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
393 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
394 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
398 int CmdHFiClassELoad(const char *Cmd
)
401 char opt
= param_getchar(Cmd
, 0);
402 if (strlen(Cmd
)<1 || opt
== 'h')
403 return hf_iclass_eload_usage();
405 //File handling and reading
407 char filename
[FILE_PATH_SIZE
];
408 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0)
410 f
= fopen(filename
, "rb");
412 return hf_iclass_eload_usage();
416 PrintAndLog("Failed to read from file '%s'", filename
);
420 fseek(f
, 0, SEEK_END
);
421 long fsize
= ftell(f
);
422 fseek(f
, 0, SEEK_SET
);
424 uint8_t *dump
= malloc(fsize
);
425 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
430 if (bytes_read
< fsize
)
432 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
437 uint32_t bytes_sent
= 0;
438 uint32_t bytes_remaining
= bytes_read
;
440 while(bytes_remaining
> 0){
441 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
442 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
443 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
445 bytes_remaining
-= bytes_in_packet
;
446 bytes_sent
+= bytes_in_packet
;
449 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
454 int CmdHFiClass_iso14443A_write(const char *Cmd
)
456 uint8_t readerType
= 0;
457 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
458 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
459 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
460 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
461 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
464 uint8_t bldata
[8]={0};
468 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
469 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
473 if (param_gethex(Cmd
, 0, KEY
, 16))
475 PrintAndLog("KEY must include 16 HEX symbols");
479 blockNo
= param_get8(Cmd
, 1);
482 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
485 if (param_gethex(Cmd
, 2, bldata
, 8))
487 PrintAndLog("Block data must include 8 HEX symbols");
491 UsbCommand c
= {CMD_ICLASS_ISO14443A_WRITE
, {0}};
495 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
496 uint8_t isOK
= resp
.arg
[0] & 0xff;
497 uint8_t * data
= resp
.d
.asBytes
;
500 memcpy(CCNR
,data
+8,8);
501 PrintAndLog("DEBUG: %s",sprint_hex(CSN
,8));
502 PrintAndLog("DEBUG: %s",sprint_hex(CCNR
,8));
503 PrintAndLog("isOk:%02x", isOK
);
505 PrintAndLog("Command execute timeout");
508 diversifyKey(CSN
,KEY
, div_key
);
510 PrintAndLog("Div Key: %s",sprint_hex(div_key
,8));
511 doMAC(CCNR
, 12,div_key
, MAC
);
513 UsbCommand c2
= {CMD_ICLASS_ISO14443A_WRITE
, {readerType
,blockNo
}};
514 memcpy(c2
.d
.asBytes
, bldata
, 8);
515 memcpy(c2
.d
.asBytes
+8, MAC
, 4);
518 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
519 uint8_t isOK
= resp
.arg
[0] & 0xff;
520 uint8_t * data
= resp
.d
.asBytes
;
523 PrintAndLog("isOk:%02x data:%s", isOK
, sprint_hex(data
, 4));
525 PrintAndLog("isOk:%02x", isOK
);
527 PrintAndLog("Command execute timeout");
531 int CmdHFiClass_loclass(const char *Cmd
)
533 char opt
= param_getchar(Cmd
, 0);
535 if (strlen(Cmd
)<1 || opt
== 'h') {
536 PrintAndLog("Usage: hf iclass loclass [options]");
537 PrintAndLog("Options:");
538 PrintAndLog("h Show this help");
539 PrintAndLog("t Perform self-test");
540 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
541 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
542 PrintAndLog(" malicious CSNs, and their protocol responses");
543 PrintAndLog(" The the binary format of the file is expected to be as follows: ");
544 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
545 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
546 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
547 PrintAndLog(" ... totalling N*24 bytes");
550 char fileName
[255] = {0};
553 if(param_getstr(Cmd
, 1, fileName
) > 0)
555 return bruteforceFileNoKeys(fileName
);
558 PrintAndLog("You must specify a filename");
563 int errors
= testCipherUtils();
565 errors
+= doKeyTests(0);
566 errors
+= testElite();
569 prnlog("OBS! There were errors!!!");
577 static command_t CommandTable
[] =
579 {"help", CmdHelp
, 1, "This help"},
580 {"list", CmdHFiClassList
, 0, "[Deprecated] List iClass history"},
581 {"snoop", CmdHFiClassSnoop
, 0, "Eavesdrop iClass communication"},
582 {"sim", CmdHFiClassSim
, 0, "Simulate iClass tag"},
583 {"reader",CmdHFiClassReader
, 0, "Read an iClass tag"},
584 {"replay",CmdHFiClassReader_Replay
, 0, "Read an iClass tag via Reply Attack"},
585 {"dump", CmdHFiClassReader_Dump
, 0, "Authenticate and Dump iClass tag"},
586 {"write", CmdHFiClass_iso14443A_write
, 0, "Authenticate and Write iClass block"},
587 {"loclass", CmdHFiClass_loclass
, 1, "Use loclass to perform bruteforce of reader attack dump"},
588 {"eload", CmdHFiClassELoad
, 0, "[experimental] Load data into iclass emulator memory"},
589 {NULL
, NULL
, 0, NULL
}
592 int CmdHFiClass(const char *Cmd
)
594 CmdsParse(CommandTable
, Cmd
);
598 int CmdHelp(const char *Cmd
)
600 CmdsHelp(CommandTable
);