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 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
51 int CmdHFiClassSnoop(const char *Cmd
)
53 UsbCommand c
= {CMD_SNOOP_ICLASS
};
58 int CmdHFiClassSim(const char *Cmd
)
61 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
64 PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
65 PrintAndLog(" options");
66 PrintAndLog(" 0 <CSN> simulate the given CSN");
67 PrintAndLog(" 1 simulate default CSN");
68 PrintAndLog(" 2 iterate CSNs, gather MACs");
69 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
70 PrintAndLog(" sample: hf iclass sim 2");
74 simType
= param_get8(Cmd
, 0);
78 if (param_gethex(Cmd
, 1, CSN
, 16)) {
79 PrintAndLog("A CSN should consist of 16 HEX symbols");
82 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
87 PrintAndLog("Undefined simptype %d", simType
);
90 uint8_t numberOfCSNs
=0;
94 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
95 UsbCommand resp
= {0};
97 /*uint8_t csns[8 * NUM_CSNS] = {
98 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
99 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
100 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
101 0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
102 0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
103 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
104 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
105 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
108 uint8_t csns
[8*NUM_CSNS
] = {
109 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
110 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
111 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
112 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
113 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
114 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
115 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
116 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
117 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
118 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
119 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
120 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
121 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
122 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
123 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
125 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
128 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
129 PrintAndLog("Command timed out");
133 uint8_t num_mac_responses
= resp
.arg
[1];
134 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
136 size_t datalen
= NUM_CSNS
*24;
138 * Now, time to dump to file. We'll use this format:
139 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
140 * So, it should wind up as
143 * The returndata from the pm3 is on the following format
144 * <4 byte NR><4 byte MAC>
145 * CC are all zeroes, CSN is the same as was sent in
147 void* dump
= malloc(datalen
);
148 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
150 for(i
= 0 ; i
< NUM_CSNS
; i
++)
152 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
153 //8 zero bytes here...
154 //Then comes NR_MAC (eight bytes from the response)
155 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
158 /** Now, save to dumpfile **/
159 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
163 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
164 memcpy(c
.d
.asBytes
, CSN
, 8);
171 int CmdHFiClassReader(const char *Cmd
)
173 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
177 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
178 uint8_t isOK
= resp
.arg
[0] & 0xff;
179 uint8_t * data
= resp
.d
.asBytes
;
181 PrintAndLog("isOk:%02x", isOK
);
184 PrintAndLog("Quitting...");
189 PrintAndLog("CSN: %s",sprint_hex(data
,8));
193 PrintAndLog("CC: %s",sprint_hex(data
+8,8));
195 PrintAndLog("No CC obtained");
198 PrintAndLog("Command execute timeout");
205 int CmdHFiClassReader_Replay(const char *Cmd
)
207 uint8_t readerType
= 0;
208 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
211 PrintAndLog("Usage: hf iclass replay <MAC>");
212 PrintAndLog(" sample: hf iclass replay 00112233");
216 if (param_gethex(Cmd
, 0, MAC
, 8)) {
217 PrintAndLog("MAC must include 8 HEX symbols");
221 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
222 memcpy(c
.d
.asBytes
, MAC
, 4);
228 int CmdHFiClassReader_Dump(const char *Cmd
)
230 uint8_t readerType
= 0;
231 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
232 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
233 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
234 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
235 //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
236 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
237 uint8_t keytable
[128] = {0};
243 PrintAndLog("Usage: hf iclass dump <Key> [e]");
244 PrintAndLog(" Key - A 16 byte master key");
245 PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
246 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
247 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
248 PrintAndLog(" sample: hf iclass dump 0011223344556677");
254 if (param_gethex(Cmd
, 0, KEY
, 16))
256 PrintAndLog("KEY must include 16 HEX symbols");
260 if (param_getchar(Cmd
, 1) == 'e')
262 PrintAndLog("Elite switch on");
266 hash2(KEY
, keytable
);
267 printarr_human_readable("keytable", keytable
, 128);
272 uint8_t key_sel
[8] = {0};
273 uint8_t key_sel_p
[8] = { 0 };
275 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
276 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_GET_CC
;
281 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
283 PrintAndLog("Command execute timeout");
287 uint8_t isOK
= resp
.arg
[0] & 0xff;
288 uint8_t * data
= resp
.d
.asBytes
;
291 memcpy(CCNR
,data
+8,8);
293 PrintAndLog("isOk:%02x", isOK
);
297 PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
300 PrintAndLog("Failed to obtain CC! Aborting");
307 //Get the key index (hash1)
308 uint8_t key_index
[8] = {0};
310 hash1(CSN
, key_index
);
311 printvar("hash1", key_index
,8);
312 for(i
= 0; i
< 8 ; i
++)
313 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
314 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
315 printvar("k_sel", key_sel
,8);
316 //Permute from iclass format to standard format
317 permutekey_rev(key_sel
,key_sel_p
);
318 used_key
= key_sel_p
;
323 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
324 printvar("Used key",used_key
,8);
325 diversifyKey(CSN
,used_key
, div_key
);
326 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
327 printvar("Div key", div_key
, 8);
328 printvar("CC_NR:",CCNR
,12);
329 doMAC(CCNR
,12,div_key
, MAC
);
330 printvar("MAC", MAC
, 4);
332 uint8_t iclass_data
[32000] = {0};
333 uint8_t iclass_datalen
= 0;
334 uint8_t iclass_blocksFailed
= 0;//Set to 1 if dump was incomplete
336 UsbCommand d
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
337 memcpy(d
.d
.asBytes
, MAC
, 4);
338 clearCommandBuffer();
340 PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
345 printf("\naborted via keyboard!\n");
348 if(WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
350 uint64_t dataLength
= resp
.arg
[0];
351 iclass_blocksFailed
|= resp
.arg
[1];
355 memcpy(iclass_data
, resp
.d
.asBytes
,dataLength
);
356 iclass_datalen
+= dataLength
;
358 {//Last transfer, datalength 0 means the dump is finished
359 PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen
);
360 if(iclass_blocksFailed
)
362 PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
364 if(iclass_datalen
> 0)
366 char filename
[100] = {0};
367 //create a preferred filename
368 snprintf(filename
, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
369 CSN
[0],CSN
[1],CSN
[2],CSN
[3],
370 CSN
[4],CSN
[5],CSN
[6],CSN
[7]);
371 saveFile(filename
,"bin",iclass_data
, iclass_datalen
);
374 //Aaaand we're finished
384 int CmdHFiClass_iso14443A_write(const char *Cmd
)
386 uint8_t readerType
= 0;
387 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
388 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
389 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
390 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
391 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
394 uint8_t bldata
[8]={0};
398 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
399 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
403 if (param_gethex(Cmd
, 0, KEY
, 16))
405 PrintAndLog("KEY must include 16 HEX symbols");
409 blockNo
= param_get8(Cmd
, 1);
412 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
415 if (param_gethex(Cmd
, 2, bldata
, 8))
417 PrintAndLog("Block data must include 8 HEX symbols");
421 UsbCommand c
= {CMD_ICLASS_ISO14443A_WRITE
, {0}};
425 if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
426 uint8_t isOK
= resp
.arg
[0] & 0xff;
427 uint8_t * data
= resp
.d
.asBytes
;
430 memcpy(CCNR
,data
+8,8);
431 PrintAndLog("DEBUG: %s",sprint_hex(CSN
,8));
432 PrintAndLog("DEBUG: %s",sprint_hex(CCNR
,8));
433 PrintAndLog("isOk:%02x", isOK
);
435 PrintAndLog("Command execute timeout");
438 diversifyKey(CSN
,KEY
, div_key
);
440 PrintAndLog("Div Key: %s",sprint_hex(div_key
,8));
441 doMAC(CCNR
, 12,div_key
, MAC
);
443 UsbCommand c2
= {CMD_ICLASS_ISO14443A_WRITE
, {readerType
,blockNo
}};
444 memcpy(c2
.d
.asBytes
, bldata
, 8);
445 memcpy(c2
.d
.asBytes
+8, MAC
, 4);
448 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) {
449 uint8_t isOK
= resp
.arg
[0] & 0xff;
450 uint8_t * data
= resp
.d
.asBytes
;
453 PrintAndLog("isOk:%02x data:%s", isOK
, sprint_hex(data
, 4));
455 PrintAndLog("isOk:%02x", isOK
);
457 PrintAndLog("Command execute timeout");
461 int CmdHFiClass_loclass(const char *Cmd
)
463 char opt
= param_getchar(Cmd
, 0);
465 if (strlen(Cmd
)<1 || opt
== 'h') {
466 PrintAndLog("Usage: hf iclass loclass [options]");
467 PrintAndLog("Options:");
468 PrintAndLog("h Show this help");
469 PrintAndLog("t Perform self-test");
470 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
471 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
472 PrintAndLog(" malicious CSNs, and their protocol responses");
473 PrintAndLog(" The the binary format of the file is expected to be as follows: ");
474 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
475 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
476 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
477 PrintAndLog(" ... totalling N*24 bytes");
480 char fileName
[255] = {0};
483 if(param_getstr(Cmd
, 1, fileName
) > 0)
485 return bruteforceFileNoKeys(fileName
);
488 PrintAndLog("You must specify a filename");
493 int errors
= testCipherUtils();
495 errors
+= doKeyTests(0);
496 errors
+= testElite();
499 prnlog("OBS! There were errors!!!");
507 static command_t CommandTable
[] =
509 {"help", CmdHelp
, 1, "This help"},
510 {"list", CmdHFiClassList
, 0, "[Deprecated] List iClass history"},
511 {"snoop", CmdHFiClassSnoop
, 0, "Eavesdrop iClass communication"},
512 {"sim", CmdHFiClassSim
, 0, "Simulate iClass tag"},
513 {"reader",CmdHFiClassReader
, 0, "Read an iClass tag"},
514 {"replay",CmdHFiClassReader_Replay
, 0, "Read an iClass tag via Reply Attack"},
515 {"dump", CmdHFiClassReader_Dump
, 0, "Authenticate and Dump iClass tag"},
516 {"write", CmdHFiClass_iso14443A_write
, 0, "Authenticate and Write iClass block"},
517 {"loclass", CmdHFiClass_loclass
, 1, "Use loclass to perform bruteforce of reader attack dump"},
518 {NULL
, NULL
, 0, NULL
}
521 int CmdHFiClass(const char *Cmd
)
523 CmdsParse(CommandTable
, Cmd
);
527 int CmdHelp(const char *Cmd
)
529 CmdsHelp(CommandTable
);