]> cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhficlass.c
Merge pull request #1 from Proxmark/master
[proxmark3-svn] / client / cmdhficlass.c
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
5 //
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
8 // the license.
9 //-----------------------------------------------------------------------------
10 // High frequency iClass commands
11 //-----------------------------------------------------------------------------
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/stat.h>
17 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
18 #include "data.h"
19 //#include "proxusb.h"
20 #include "proxmark3.h"
21 #include "ui.h"
22 #include "cmdparser.h"
23 #include "cmdhficlass.h"
24 #include "common.h"
25 #include "util.h"
26 #include "cmdmain.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"
33
34 static int CmdHelp(const char *Cmd);
35
36 int xorbits_8(uint8_t val)
37 {
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
42 return res & 1;
43 }
44
45 int CmdHFiClassList(const char *Cmd)
46 {
47 bool ShowWaitCycles = false;
48 char param = param_getchar(Cmd, 0);
49
50 if (param != 0) {
51 PrintAndLog("List data in trace buffer.");
52 PrintAndLog("Usage: hf iclass list");
53 PrintAndLog("h - help");
54 PrintAndLog("sample: hf iclass list");
55 return 0;
56 }
57
58 // for the time being. Need better Bigbuf handling.
59 #define TRACE_SIZE 3000
60
61 uint8_t trace[TRACE_SIZE];
62 GetFromBigBuf(trace, TRACE_SIZE, 0);
63 WaitForResponse(CMD_ACK, NULL);
64
65 PrintAndLog("Recorded Activity");
66 PrintAndLog("");
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)");
69 PrintAndLog("");
70 PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC ");
71 PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------");
72
73 uint16_t tracepos = 0;
74 uint16_t duration;
75 uint16_t data_len;
76 uint16_t parity_len;
77 bool isResponse;
78 uint32_t timestamp;
79 uint32_t first_timestamp;
80 uint32_t EndOfTransmissionTimestamp;
81
82 for (;;) {
83
84 if(tracepos >= TRACE_SIZE) {
85 break;
86 }
87
88 timestamp = *((uint32_t *)(trace + tracepos));
89 if(tracepos == 0) {
90 first_timestamp = timestamp;
91 }
92
93 // Break and stick with current result if buffer was not completely full
94 if (timestamp == 0x44444444) break;
95
96 tracepos += 4;
97 duration = *((uint16_t *)(trace + tracepos));
98 tracepos += 2;
99 data_len = *((uint16_t *)(trace + tracepos));
100 tracepos += 2;
101
102 if (data_len & 0x8000) {
103 data_len &= 0x7fff;
104 isResponse = true;
105 } else {
106 isResponse = false;
107 }
108
109 parity_len = (data_len-1)/8 + 1;
110
111 if (tracepos + data_len + parity_len >= TRACE_SIZE) {
112 break;
113 }
114
115 uint8_t *frame = trace + tracepos;
116 tracepos += data_len;
117 uint8_t *parityBytes = trace + tracepos;
118 tracepos += parity_len;
119
120 char line[16][110];
121 for (int j = 0; j < data_len; j++) {
122 int oddparity = 0x01;
123 int k;
124
125 for (k=0;k<8;k++) {
126 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
127 }
128
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]);
132 } else {
133 sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]);
134 }
135
136 }
137
138 char *crc = "";
139 if (data_len > 2) {
140 uint8_t b1, b2;
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]) {
146 crc = "!crc";
147 }
148 }
149 else {
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]) {
153 crc = "!crc";
154 }
155 }
156 }
157
158 EndOfTransmissionTimestamp = timestamp + duration;
159
160 int num_lines = (data_len - 1)/16 + 1;
161 for (int j = 0; j < num_lines; j++) {
162 if (j == 0) {
163 PrintAndLog(" %9d | %9d | %s | %-64s| %s",
164 (timestamp - first_timestamp),
165 (EndOfTransmissionTimestamp - first_timestamp),
166 (isResponse ? "Tag" : "Rdr"),
167 line[j],
168 (j == num_lines-1)?crc:"");
169 } else {
170 PrintAndLog(" | | | %-64s| %s",
171 line[j],
172 (j == num_lines-1)?crc:"");
173 }
174 }
175
176 bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
177
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),
184 " ",
185 (next_timestamp - EndOfTransmissionTimestamp));
186 }
187 }
188
189 }
190
191 return 0;
192 }
193
194 int CmdHFiClassSnoop(const char *Cmd)
195 {
196 UsbCommand c = {CMD_SNOOP_ICLASS};
197 SendCommand(&c);
198 return 0;
199 }
200 #define NUM_CSNS 15
201 int CmdHFiClassSim(const char *Cmd)
202 {
203 uint8_t simType = 0;
204 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
205
206 if (strlen(Cmd)<1) {
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");
214 return 0;
215 }
216
217 simType = param_get8(Cmd, 0);
218
219 if(simType == 0)
220 {
221 if (param_gethex(Cmd, 1, CSN, 16)) {
222 PrintAndLog("A CSN should consist of 16 HEX symbols");
223 return 1;
224 }
225 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
226
227 }
228 if(simType > 2)
229 {
230 PrintAndLog("Undefined simptype %d", simType);
231 return 1;
232 }
233 uint8_t numberOfCSNs=0;
234
235 if(simType == 2)
236 {
237 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
238 UsbCommand resp = {0};
239
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 };
249 */
250
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 };
267
268 memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
269
270 SendCommand(&c);
271 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
272 PrintAndLog("Command timed out");
273 return 0;
274 }
275
276 uint8_t num_mac_responses = resp.arg[1];
277 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
278
279 size_t datalen = NUM_CSNS*24;
280 /*
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
284 * 8 * 24 bytes.
285 *
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
289 **/
290 void* dump = malloc(datalen);
291 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
292 uint8_t i = 0;
293 for(i = 0 ; i < NUM_CSNS ; i++)
294 {
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);
299
300 }
301 /** Now, save to dumpfile **/
302 saveFile("iclass_mac_attack", "bin", dump,datalen);
303 free(dump);
304 }else
305 {
306 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
307 memcpy(c.d.asBytes, CSN, 8);
308 SendCommand(&c);
309 }
310
311 return 0;
312 }
313
314 int CmdHFiClassReader(const char *Cmd)
315 {
316 UsbCommand c = {CMD_READER_ICLASS, {0}};
317 SendCommand(&c);
318 UsbCommand resp;
319 while(!ukbhit()){
320 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
321 uint8_t isOK = resp.arg[0] & 0xff;
322 uint8_t * data = resp.d.asBytes;
323
324 PrintAndLog("isOk:%02x", isOK);
325
326 if(isOK > 0)
327 {
328 PrintAndLog("CSN: %s",sprint_hex(data,8));
329 }
330 if(isOK >= 1)
331 {
332 PrintAndLog("CC: %s",sprint_hex(data+8,8));
333 }else{
334 PrintAndLog("No CC obtained");
335 }
336 } else {
337 PrintAndLog("Command execute timeout");
338 }
339 }
340
341 return 0;
342 }
343
344 int CmdHFiClassReader_Replay(const char *Cmd)
345 {
346 uint8_t readerType = 0;
347 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
348
349 if (strlen(Cmd)<1) {
350 PrintAndLog("Usage: hf iclass replay <MAC>");
351 PrintAndLog(" sample: hf iclass replay 00112233");
352 return 0;
353 }
354
355 if (param_gethex(Cmd, 0, MAC, 8)) {
356 PrintAndLog("MAC must include 8 HEX symbols");
357 return 1;
358 }
359
360 UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
361 memcpy(c.d.asBytes, MAC, 4);
362 SendCommand(&c);
363
364 return 0;
365 }
366
367 int CmdHFiClassReader_Dump(const char *Cmd)
368 {
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};
377 int elite = 0;
378 uint8_t *used_key;
379 int i;
380 if (strlen(Cmd)<1)
381 {
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");
388
389
390 return 0;
391 }
392
393 if (param_gethex(Cmd, 0, KEY, 16))
394 {
395 PrintAndLog("KEY must include 16 HEX symbols");
396 return 1;
397 }
398
399 if (param_getchar(Cmd, 1) == 'e')
400 {
401 PrintAndLog("Elite switch on");
402 elite = 1;
403
404 //calc h2
405 hash2(KEY, keytable);
406 printarr_human_readable("keytable", keytable, 128);
407
408 }
409
410 UsbCommand resp;
411 uint8_t key_sel[8] = {0};
412 uint8_t key_sel_p[8] = { 0 };
413
414 //HACK -- Below is for testing without access to a tag
415 uint8_t fake_dummy_test = false;
416 if(fake_dummy_test)
417 {
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);
421 resp.arg[0] = 2;
422 }
423
424 //End hack
425
426
427 UsbCommand c = {CMD_READER_ICLASS, {0}};
428 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE;
429 if(!fake_dummy_test)
430 SendCommand(&c);
431
432
433
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;
437
438 memcpy(CSN,data,8);
439 memcpy(CCNR,data+8,8);
440
441 PrintAndLog("isOk:%02x", isOK);
442
443 if(isOK > 0)
444 {
445 PrintAndLog("CSN: %s",sprint_hex(CSN,8));
446 }
447 if(isOK > 1)
448 {
449 if(elite)
450 {
451 //Get the key index (hash1)
452 uint8_t key_index[8] = {0};
453
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;
463 }else{
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
467
468 //uint8_t key_sel_p[8] = { 0 };
469 //permutekey_rev(KEY,key_sel_p);
470 //used_key = key_sel_p;
471
472 used_key = KEY;
473
474 }
475
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);
484
485 UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
486 memcpy(d.d.asBytes, MAC, 4);
487 if(!fake_dummy_test) SendCommand(&d);
488
489 }else{
490 PrintAndLog("Failed to obtain CC! Aborting");
491 }
492 } else {
493 PrintAndLog("Command execute timeout");
494 }
495
496 return 0;
497 }
498
499 int CmdHFiClass_iso14443A_write(const char *Cmd)
500 {
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};
507
508 uint8_t blockNo=0;
509 uint8_t bldata[8]={0};
510
511 if (strlen(Cmd)<3)
512 {
513 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
514 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
515 return 0;
516 }
517
518 if (param_gethex(Cmd, 0, KEY, 16))
519 {
520 PrintAndLog("KEY must include 16 HEX symbols");
521 return 1;
522 }
523
524 blockNo = param_get8(Cmd, 1);
525 if (blockNo>32)
526 {
527 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
528 return 1;
529 }
530 if (param_gethex(Cmd, 2, bldata, 8))
531 {
532 PrintAndLog("Block data must include 8 HEX symbols");
533 return 1;
534 }
535
536 UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}};
537 SendCommand(&c);
538 UsbCommand resp;
539
540 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
541 uint8_t isOK = resp.arg[0] & 0xff;
542 uint8_t * data = resp.d.asBytes;
543
544 memcpy(CSN,data,8);
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);
549 } else {
550 PrintAndLog("Command execute timeout");
551 }
552
553 diversifyKey(CSN,KEY, div_key);
554
555 PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
556 doMAC(CCNR, 12,div_key, MAC);
557
558 UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
559 memcpy(c2.d.asBytes, bldata, 8);
560 memcpy(c2.d.asBytes+8, MAC, 4);
561 SendCommand(&c2);
562
563 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
564 uint8_t isOK = resp.arg[0] & 0xff;
565 uint8_t * data = resp.d.asBytes;
566
567 if (isOK)
568 PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
569 else
570 PrintAndLog("isOk:%02x", isOK);
571 } else {
572 PrintAndLog("Command execute timeout");
573 }
574 return 0;
575 }
576
577
578 static command_t CommandTable[] =
579 {
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}
589 };
590
591 int CmdHFiClass(const char *Cmd)
592 {
593 CmdsParse(CommandTable, Cmd);
594 return 0;
595 }
596
597 int CmdHelp(const char *Cmd)
598 {
599 CmdsHelp(CommandTable);
600 return 0;
601 }
Impressum, Datenschutz