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"
32 #include "protocols.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 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
51 int CmdHFiClassSnoop(const char *Cmd
)
53 UsbCommand c
= {CMD_SNOOP_ICLASS
};
57 int usage_hf_iclass_sim()
59 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
60 PrintAndLog(" options");
61 PrintAndLog(" 0 <CSN> simulate the given CSN");
62 PrintAndLog(" 1 simulate default CSN");
63 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
64 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
65 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
66 PrintAndLog(" example: hf iclass sim 2");
67 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
68 PrintAndLog(" hf iclass sim 3");
73 int CmdHFiClassSim(const char *Cmd
)
76 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
79 return usage_hf_iclass_sim();
81 simType
= param_get8ex(Cmd
, 0, 0, 10);
85 if (param_gethex(Cmd
, 1, CSN
, 16)) {
86 PrintAndLog("A CSN should consist of 16 HEX symbols");
87 return usage_hf_iclass_sim();
90 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
94 PrintAndLog("Undefined simptype %d", simType
);
95 return usage_hf_iclass_sim();
98 uint8_t numberOfCSNs
=0;
101 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
102 UsbCommand resp
= {0};
104 uint8_t csns
[8*NUM_CSNS
] = {
105 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
106 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
107 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
108 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
109 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
110 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
111 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
112 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
113 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
114 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
115 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
116 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
117 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
118 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
119 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
121 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
124 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
125 PrintAndLog("Command timed out");
129 uint8_t num_mac_responses
= resp
.arg
[1];
130 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
132 size_t datalen
= NUM_CSNS
*24;
134 * Now, time to dump to file. We'll use this format:
135 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
136 * So, it should wind up as
139 * The returndata from the pm3 is on the following format
140 * <4 byte NR><4 byte MAC>
141 * CC are all zeroes, CSN is the same as was sent in
143 void* dump
= malloc(datalen
);
144 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
146 for(i
= 0 ; i
< NUM_CSNS
; i
++)
148 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
149 //8 zero bytes here...
150 //Then comes NR_MAC (eight bytes from the response)
151 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
154 /** Now, save to dumpfile **/
155 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
159 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
160 memcpy(c
.d
.asBytes
, CSN
, 8);
167 int CmdHFiClassReader(const char *Cmd
)
169 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
173 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
174 uint8_t isOK
= resp
.arg
[0] & 0xff;
175 uint8_t * data
= resp
.d
.asBytes
;
177 PrintAndLog("isOk:%02x", isOK
);
180 PrintAndLog("Quitting...");
185 PrintAndLog("CSN: %s",sprint_hex(data
,8));
189 PrintAndLog("CC: %s",sprint_hex(data
+8,8));
191 PrintAndLog("No CC obtained");
194 PrintAndLog("Command execute timeout");
201 int CmdHFiClassReader_Replay(const char *Cmd
)
203 uint8_t readerType
= 0;
204 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
207 PrintAndLog("Usage: hf iclass replay <MAC>");
208 PrintAndLog(" sample: hf iclass replay 00112233");
212 if (param_gethex(Cmd
, 0, MAC
, 8)) {
213 PrintAndLog("MAC must include 8 HEX symbols");
217 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
218 memcpy(c
.d
.asBytes
, MAC
, 4);
224 int CmdHFiClassReader_Dump(const char *Cmd
)
226 uint8_t readerType
= 0;
227 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
228 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
229 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
230 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
231 //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
232 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
233 uint8_t keytable
[128] = {0};
239 PrintAndLog("Usage: hf iclass dump <Key> [e]");
240 PrintAndLog(" Key - A 16 byte master key");
241 PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
242 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
243 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
244 PrintAndLog(" sample: hf iclass dump 0011223344556677");
250 if (param_gethex(Cmd
, 0, KEY
, 16))
252 PrintAndLog("KEY must include 16 HEX symbols");
256 if (param_getchar(Cmd
, 1) == 'e')
258 PrintAndLog("Elite switch on");
262 hash2(KEY
, keytable
);
263 printarr_human_readable("keytable", keytable
, 128);
268 uint8_t key_sel
[8] = {0};
269 uint8_t key_sel_p
[8] = { 0 };
271 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
272 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_GET_CC
;
277 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
279 PrintAndLog("Command execute timeout");
283 uint8_t isOK
= resp
.arg
[0] & 0xff;
284 uint8_t * data
= resp
.d
.asBytes
;
287 memcpy(CCNR
,data
+8,8);
289 PrintAndLog("isOk:%02x", isOK
);
293 PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
296 PrintAndLog("Failed to obtain CC! Aborting");
303 //Get the key index (hash1)
304 uint8_t key_index
[8] = {0};
306 hash1(CSN
, key_index
);
307 printvar("hash1", key_index
,8);
308 for(i
= 0; i
< 8 ; i
++)
309 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
310 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
311 printvar("k_sel", key_sel
,8);
312 //Permute from iclass format to standard format
313 permutekey_rev(key_sel
,key_sel_p
);
314 used_key
= key_sel_p
;
319 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
320 printvar("Used key",used_key
,8);
321 diversifyKey(CSN
,used_key
, div_key
);
322 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
323 printvar("Div key", div_key
, 8);
324 printvar("CC_NR:",CCNR
,12);
325 doMAC(CCNR
,div_key
, MAC
);
326 printvar("MAC", MAC
, 4);
328 uint8_t iclass_data
[32000] = {0};
329 uint32_t iclass_datalen
= 0;
330 uint32_t iclass_blocksFailed
= 0;//Set to 1 if dump was incomplete
332 UsbCommand d
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
333 memcpy(d
.d
.asBytes
, MAC
, 4);
334 clearCommandBuffer();
336 PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
341 printf("\naborted via keyboard!\n");
344 if(WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
346 uint32_t dataLength
= resp
.arg
[0];
347 iclass_blocksFailed
|= resp
.arg
[1];
350 PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength
,iclass_datalen
);
351 memcpy(iclass_data
, resp
.d
.asBytes
,dataLength
);
352 iclass_datalen
+= dataLength
;
354 {//Last transfer, datalength 0 means the dump is finished
355 PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen
);
356 if(iclass_blocksFailed
)
358 PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
360 if(iclass_datalen
> 0)
362 char filename
[100] = {0};
363 //create a preferred filename
364 snprintf(filename
, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
365 CSN
[0],CSN
[1],CSN
[2],CSN
[3],
366 CSN
[4],CSN
[5],CSN
[6],CSN
[7]);
367 //Place the div_key in block 3
368 memcpy(iclass_data
+(3*8), div_key
, 8);
369 saveFile(filename
,"bin",iclass_data
, iclass_datalen
);
371 //Aaaand we're finished
381 int hf_iclass_eload_usage()
383 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
384 PrintAndLog("Usage: hf iclass eload f <filename>");
386 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
391 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
392 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
393 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
397 int CmdHFiClassELoad(const char *Cmd
)
400 char opt
= param_getchar(Cmd
, 0);
401 if (strlen(Cmd
)<1 || opt
== 'h')
402 return hf_iclass_eload_usage();
404 //File handling and reading
406 char filename
[FILE_PATH_SIZE
];
407 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0)
409 f
= fopen(filename
, "rb");
411 return hf_iclass_eload_usage();
415 PrintAndLog("Failed to read from file '%s'", filename
);
419 fseek(f
, 0, SEEK_END
);
420 long fsize
= ftell(f
);
421 fseek(f
, 0, SEEK_SET
);
423 uint8_t *dump
= malloc(fsize
);
426 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
429 printIclassDumpInfo(dump
);
432 if (bytes_read
< fsize
)
434 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
439 uint32_t bytes_sent
= 0;
440 uint32_t bytes_remaining
= bytes_read
;
442 while(bytes_remaining
> 0){
443 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
444 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
445 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
447 bytes_remaining
-= bytes_in_packet
;
448 bytes_sent
+= bytes_in_packet
;
451 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
455 int usage_hf_iclass_decrypt()
457 PrintAndLog("Usage: hf iclass decrypt f <tagdump> o ");
459 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
460 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
462 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
464 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
465 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
466 PrintAndLog("which is defined by the configuration block.");
470 int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
)
472 FILE *f
= fopen(filename
, "rb");
474 PrintAndLog("Failed to read from file '%s'", filename
);
477 fseek(f
, 0, SEEK_END
);
478 long fsize
= ftell(f
);
479 fseek(f
, 0, SEEK_SET
);
480 size_t bytes_read
= fread(buffer
, 1, len
, f
);
484 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
487 if(bytes_read
!= len
)
489 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
495 int CmdHFiClassDecrypt(const char *Cmd
)
497 uint8_t key
[16] = { 0 };
498 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
500 usage_hf_iclass_decrypt();
503 PrintAndLog("Decryption file found... ");
504 char opt
= param_getchar(Cmd
, 0);
505 if (strlen(Cmd
)<1 || opt
== 'h')
506 return usage_hf_iclass_decrypt();
508 //Open the tagdump-file
510 char filename
[FILE_PATH_SIZE
];
511 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0)
513 f
= fopen(filename
, "rb");
515 return usage_hf_iclass_decrypt();
518 fseek(f
, 0, SEEK_END
);
519 long fsize
= ftell(f
);
520 fseek(f
, 0, SEEK_SET
);
521 uint8_t enc_dump
[8] = {0};
522 uint8_t *decrypted
= malloc(fsize
);
523 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
524 des3_set2key_dec( &ctx
, key
);
525 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
527 //Use the first block (CSN) for filename
528 char outfilename
[FILE_PATH_SIZE
] = { 0 };
529 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
530 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
531 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
534 while(bytes_read
== 8)
538 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
540 des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
542 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
543 bytes_read
= fread(enc_dump
, 1, 8, f
);
548 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
553 int CmdHFiClass_iso14443A_write(const char *Cmd
)
555 uint8_t readerType
= 0;
556 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
557 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
558 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
559 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
560 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
563 uint8_t bldata
[8]={0};
567 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
568 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
572 if (param_gethex(Cmd
, 0, KEY
, 16))
574 PrintAndLog("KEY must include 16 HEX symbols");
578 blockNo
= param_get8(Cmd
, 1);
581 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
584 if (param_gethex(Cmd
, 2, bldata
, 8))
586 PrintAndLog("Block data must include 8 HEX symbols");
590 UsbCommand c
= {CMD_ICLASS_ISO14443A_WRITE
, {0}};
594 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
595 uint8_t isOK
= resp
.arg
[0] & 0xff;
596 uint8_t * data
= resp
.d
.asBytes
;
599 memcpy(CCNR
,data
+8,8);
600 PrintAndLog("DEBUG: %s",sprint_hex(CSN
,8));
601 PrintAndLog("DEBUG: %s",sprint_hex(CCNR
,8));
602 PrintAndLog("isOk:%02x", isOK
);
604 PrintAndLog("Command execute timeout");
607 diversifyKey(CSN
,KEY
, div_key
);
609 PrintAndLog("Div Key: %s",sprint_hex(div_key
,8));
610 doMAC(CCNR
, div_key
, MAC
);
612 UsbCommand c2
= {CMD_ICLASS_ISO14443A_WRITE
, {readerType
,blockNo
}};
613 memcpy(c2
.d
.asBytes
, bldata
, 8);
614 memcpy(c2
.d
.asBytes
+8, MAC
, 4);
617 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
618 uint8_t isOK
= resp
.arg
[0] & 0xff;
619 uint8_t * data
= resp
.d
.asBytes
;
622 PrintAndLog("isOk:%02x data:%s", isOK
, sprint_hex(data
, 4));
624 PrintAndLog("isOk:%02x", isOK
);
626 PrintAndLog("Command execute timeout");
630 int CmdHFiClass_loclass(const char *Cmd
)
632 char opt
= param_getchar(Cmd
, 0);
634 if (strlen(Cmd
)<1 || opt
== 'h') {
635 PrintAndLog("Usage: hf iclass loclass [options]");
636 PrintAndLog("Options:");
637 PrintAndLog("h Show this help");
638 PrintAndLog("t Perform self-test");
639 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
640 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
641 PrintAndLog(" malicious CSNs, and their protocol responses");
642 PrintAndLog(" The the binary format of the file is expected to be as follows: ");
643 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
644 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
645 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
646 PrintAndLog(" ... totalling N*24 bytes");
649 char fileName
[255] = {0};
652 if(param_getstr(Cmd
, 1, fileName
) > 0)
654 return bruteforceFileNoKeys(fileName
);
657 PrintAndLog("You must specify a filename");
662 int errors
= testCipherUtils();
664 errors
+= doKeyTests(0);
665 errors
+= testElite();
668 prnlog("OBS! There were errors!!!");
676 static command_t CommandTable
[] =
678 {"help", CmdHelp
, 1, "This help"},
679 {"list", CmdHFiClassList
, 0, "[Deprecated] List iClass history"},
680 {"snoop", CmdHFiClassSnoop
, 0, "Eavesdrop iClass communication"},
681 {"sim", CmdHFiClassSim
, 0, "Simulate iClass tag"},
682 {"reader",CmdHFiClassReader
, 0, "Read an iClass tag"},
683 {"replay",CmdHFiClassReader_Replay
, 0, "Read an iClass tag via Reply Attack"},
684 {"dump", CmdHFiClassReader_Dump
, 0, "Authenticate and Dump iClass tag"},
685 // {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
686 {"loclass", CmdHFiClass_loclass
, 1, "Use loclass to perform bruteforce of reader attack dump"},
687 {"eload", CmdHFiClassELoad
, 0, "[experimental] Load data into iclass emulator memory"},
688 {"decrypt", CmdHFiClassDecrypt
, 1, "Decrypt tagdump" },
689 {NULL
, NULL
, 0, NULL
}
692 int CmdHFiClass(const char *Cmd
)
694 CmdsParse(CommandTable
, Cmd
);
698 int CmdHelp(const char *Cmd
)
700 CmdsHelp(CommandTable
);