]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhficlass.c
19ec57d2695dcfab758c9fc0cfd7e39545e64cc3
[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 void explain(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
46 {
47
48 switch(cmd[0])
49 {
50 case 0x0a: snprintf(exp,size,"WUP"); break;
51 case 0x0f: snprintf(exp,size,"SOF"); break;
52 case 0x0c: snprintf(exp,size,"Read config"); break;
53 case 0x81: snprintf(exp,size,"SELECT"); break;
54 case 0x88: snprintf(exp,size,"Read E-purse (CC)"); break;
55 case 0x05: snprintf(exp,size,"Reader challenge"); break;
56 case 0x00: snprintf(exp,size,"End"); break;
57 default: snprintf(exp,size,"?"); break;
58 }
59 return;
60 }
61
62 int CmdHFiClassList(const char *Cmd)
63 {
64 bool ShowWaitCycles = false;
65 char param = param_getchar(Cmd, 0);
66
67 if (param != 0) {
68 PrintAndLog("List data in trace buffer.");
69 PrintAndLog("Usage: hf iclass list");
70 PrintAndLog("h - help");
71 PrintAndLog("sample: hf iclass list");
72 return 0;
73 }
74
75 // for the time being. Need better Bigbuf handling.
76 #define TRACE_SIZE 3000
77
78 uint8_t trace[TRACE_SIZE];
79 GetFromBigBuf(trace, TRACE_SIZE, 0);
80 WaitForResponse(CMD_ACK, NULL);
81
82 PrintAndLog("Recorded Activity");
83 PrintAndLog("");
84 PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
85 PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
86 PrintAndLog("");
87 PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Explanation|");
88 PrintAndLog("-----------|-----------|-----|-------------------------------------------------------------------------------------");
89
90 uint16_t tracepos = 0;
91 uint16_t duration;
92 uint16_t data_len;
93 uint16_t parity_len;
94 bool isResponse;
95 uint32_t timestamp;
96 uint32_t first_timestamp;
97 uint32_t EndOfTransmissionTimestamp;
98 char explanation[20] = {0};
99 for (;;) {
100
101 if(tracepos >= TRACE_SIZE) {
102 break;
103 }
104
105 timestamp = *((uint32_t *)(trace + tracepos));
106 if(tracepos == 0) {
107 first_timestamp = timestamp;
108 }
109
110 // Break and stick with current result if buffer was not completely full
111 if (timestamp == 0x44444444) break;
112
113 tracepos += 4;
114 duration = *((uint16_t *)(trace + tracepos));
115 tracepos += 2;
116 data_len = *((uint16_t *)(trace + tracepos));
117 tracepos += 2;
118
119 if (data_len & 0x8000) {
120 data_len &= 0x7fff;
121 isResponse = true;
122 } else {
123 isResponse = false;
124 }
125
126 parity_len = (data_len-1)/8 + 1;
127
128 if (tracepos + data_len + parity_len >= TRACE_SIZE) {
129 break;
130 }
131
132 uint8_t *frame = trace + tracepos;
133 tracepos += data_len;
134 uint8_t *parityBytes = trace + tracepos;
135 tracepos += parity_len;
136
137 char line[16][110];
138 for (int j = 0; j < data_len; j++) {
139 int oddparity = 0x01;
140 int k;
141
142 for (k=0;k<8;k++) {
143 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
144 }
145
146 uint8_t parityBits = parityBytes[j>>3];
147 if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
148 sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]);
149 } else {
150 sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]);
151 }
152
153 }
154
155 char *crc = " ";
156 if (data_len > 2) {
157 uint8_t b1, b2;
158 if(!isResponse && data_len == 4 ) {
159 // Rough guess that this is a command from the reader
160 // For iClass the command byte is not part of the CRC
161 ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2);
162 if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
163 crc = "!crc";
164 }
165 }
166 else {
167 // For other data.. CRC might not be applicable (UPDATE commands etc.)
168 ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2);
169 if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
170 crc = "!crc";
171 }
172 }
173 }
174
175 EndOfTransmissionTimestamp = timestamp + duration;
176 explain(explanation,sizeof(explanation),frame,data_len);
177 int num_lines = (data_len - 1)/16 + 1;
178 for (int j = 0; j < num_lines; j++) {
179 if (j == 0) {
180 PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
181 (timestamp - first_timestamp),
182 (EndOfTransmissionTimestamp - first_timestamp),
183 (isResponse ? "Tag" : "Rdr"),
184 line[j],
185 (j == num_lines-1)?crc:" ",
186 explanation);
187 } else {
188 PrintAndLog(" | | | %-64s| %s",
189 line[j],
190 (j == num_lines-1)?crc:" ");
191 }
192 }
193
194 bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
195
196 if (ShowWaitCycles && !isResponse && next_isResponse) {
197 uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
198 if (next_timestamp != 0x44444444) {
199 PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
200 (EndOfTransmissionTimestamp - first_timestamp),
201 (next_timestamp - first_timestamp),
202 " ",
203 (next_timestamp - EndOfTransmissionTimestamp));
204 }
205 }
206
207 }
208
209 return 0;
210 }
211
212 int CmdHFiClassSnoop(const char *Cmd)
213 {
214 UsbCommand c = {CMD_SNOOP_ICLASS};
215 SendCommand(&c);
216 return 0;
217 }
218 #define NUM_CSNS 15
219 int CmdHFiClassSim(const char *Cmd)
220 {
221 uint8_t simType = 0;
222 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
223
224 if (strlen(Cmd)<1) {
225 PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
226 PrintAndLog(" options");
227 PrintAndLog(" 0 <CSN> simulate the given CSN");
228 PrintAndLog(" 1 simulate default CSN");
229 PrintAndLog(" 2 iterate CSNs, gather MACs");
230 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
231 PrintAndLog(" sample: hf iclass sim 2");
232 return 0;
233 }
234
235 simType = param_get8(Cmd, 0);
236
237 if(simType == 0)
238 {
239 if (param_gethex(Cmd, 1, CSN, 16)) {
240 PrintAndLog("A CSN should consist of 16 HEX symbols");
241 return 1;
242 }
243 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
244
245 }
246 if(simType > 2)
247 {
248 PrintAndLog("Undefined simptype %d", simType);
249 return 1;
250 }
251 uint8_t numberOfCSNs=0;
252
253 if(simType == 2)
254 {
255 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
256 UsbCommand resp = {0};
257
258 /*uint8_t csns[8 * NUM_CSNS] = {
259 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
260 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
261 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
262 0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
263 0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
264 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
265 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
266 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
267 */
268
269 uint8_t csns[8*NUM_CSNS] = {
270 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
271 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
272 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
273 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
274 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
275 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
276 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
277 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
278 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
279 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
280 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
281 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
282 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
283 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
284 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
285
286 memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
287
288 SendCommand(&c);
289 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
290 PrintAndLog("Command timed out");
291 return 0;
292 }
293
294 uint8_t num_mac_responses = resp.arg[1];
295 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
296
297 size_t datalen = NUM_CSNS*24;
298 /*
299 * Now, time to dump to file. We'll use this format:
300 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
301 * So, it should wind up as
302 * 8 * 24 bytes.
303 *
304 * The returndata from the pm3 is on the following format
305 * <4 byte NR><4 byte MAC>
306 * CC are all zeroes, CSN is the same as was sent in
307 **/
308 void* dump = malloc(datalen);
309 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
310 uint8_t i = 0;
311 for(i = 0 ; i < NUM_CSNS ; i++)
312 {
313 memcpy(dump+i*24, csns+i*8,8); //CSN
314 //8 zero bytes here...
315 //Then comes NR_MAC (eight bytes from the response)
316 memcpy(dump+i*24+16,resp.d.asBytes+i*8,8);
317
318 }
319 /** Now, save to dumpfile **/
320 saveFile("iclass_mac_attack", "bin", dump,datalen);
321 free(dump);
322 }else
323 {
324 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
325 memcpy(c.d.asBytes, CSN, 8);
326 SendCommand(&c);
327 }
328
329 return 0;
330 }
331
332 int CmdHFiClassReader(const char *Cmd)
333 {
334 UsbCommand c = {CMD_READER_ICLASS, {0}};
335 SendCommand(&c);
336 UsbCommand resp;
337 while(!ukbhit()){
338 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
339 uint8_t isOK = resp.arg[0] & 0xff;
340 uint8_t * data = resp.d.asBytes;
341
342 PrintAndLog("isOk:%02x", isOK);
343 if( isOK == 0){
344 //Aborted
345 PrintAndLog("Quitting...");
346 return 0;
347 }
348 if(isOK > 0)
349 {
350 PrintAndLog("CSN: %s",sprint_hex(data,8));
351 }
352 if(isOK >= 1)
353 {
354 PrintAndLog("CC: %s",sprint_hex(data+8,8));
355 }else{
356 PrintAndLog("No CC obtained");
357 }
358 } else {
359 PrintAndLog("Command execute timeout");
360 }
361 }
362
363 return 0;
364 }
365
366 int CmdHFiClassReader_Replay(const char *Cmd)
367 {
368 uint8_t readerType = 0;
369 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
370
371 if (strlen(Cmd)<1) {
372 PrintAndLog("Usage: hf iclass replay <MAC>");
373 PrintAndLog(" sample: hf iclass replay 00112233");
374 return 0;
375 }
376
377 if (param_gethex(Cmd, 0, MAC, 8)) {
378 PrintAndLog("MAC must include 8 HEX symbols");
379 return 1;
380 }
381
382 UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
383 memcpy(c.d.asBytes, MAC, 4);
384 SendCommand(&c);
385
386 return 0;
387 }
388
389 int CmdHFiClassReader_Dump(const char *Cmd)
390 {
391 uint8_t readerType = 0;
392 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
393 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
394 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
395 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
396 //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
397 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
398 uint8_t keytable[128] = {0};
399 int elite = 0;
400 uint8_t *used_key;
401 int i;
402 if (strlen(Cmd)<1)
403 {
404 PrintAndLog("Usage: hf iclass dump <Key> [e]");
405 PrintAndLog(" Key - A 16 byte master key");
406 PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
407 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
408 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
409 PrintAndLog(" sample: hf iclass dump 0011223344556677");
410
411
412 return 0;
413 }
414
415 if (param_gethex(Cmd, 0, KEY, 16))
416 {
417 PrintAndLog("KEY must include 16 HEX symbols");
418 return 1;
419 }
420
421 if (param_getchar(Cmd, 1) == 'e')
422 {
423 PrintAndLog("Elite switch on");
424 elite = 1;
425
426 //calc h2
427 hash2(KEY, keytable);
428 printarr_human_readable("keytable", keytable, 128);
429
430 }
431
432 UsbCommand resp;
433 uint8_t key_sel[8] = {0};
434 uint8_t key_sel_p[8] = { 0 };
435
436 //HACK -- Below is for testing without access to a tag
437 uint8_t fake_dummy_test = false;
438 if(fake_dummy_test)
439 {
440 uint8_t xdata[16] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0, //CSN from http://www.proxmark.org/forum/viewtopic.php?pid=11230#p11230
441 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Just a random CC. Would be good to add a real testcase here
442 memcpy(resp.d.asBytes,xdata, 16);
443 resp.arg[0] = 2;
444 }
445
446 //End hack
447
448
449 UsbCommand c = {CMD_READER_ICLASS, {0}};
450 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE;
451 if(!fake_dummy_test)
452 SendCommand(&c);
453
454
455
456 if (fake_dummy_test || WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
457 uint8_t isOK = resp.arg[0] & 0xff;
458 uint8_t * data = resp.d.asBytes;
459
460 memcpy(CSN,data,8);
461 memcpy(CCNR,data+8,8);
462
463 PrintAndLog("isOk:%02x", isOK);
464
465 if(isOK > 0)
466 {
467 PrintAndLog("CSN: %s",sprint_hex(CSN,8));
468 }
469 if(isOK > 1)
470 {
471 if(elite)
472 {
473 //Get the key index (hash1)
474 uint8_t key_index[8] = {0};
475
476 hash1(CSN, key_index);
477 printvar("hash1", key_index,8);
478 for(i = 0; i < 8 ; i++)
479 key_sel[i] = keytable[key_index[i]] & 0xFF;
480 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
481 printvar("k_sel", key_sel,8);
482 //Permute from iclass format to standard format
483 permutekey_rev(key_sel,key_sel_p);
484 used_key = key_sel_p;
485 }else{
486 //Perhaps this should also be permuted to std format?
487 // Something like the code below? I have no std system
488 // to test this with /Martin
489
490 //uint8_t key_sel_p[8] = { 0 };
491 //permutekey_rev(KEY,key_sel_p);
492 //used_key = key_sel_p;
493
494 used_key = KEY;
495
496 }
497
498 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
499 printvar("Used key",used_key,8);
500 diversifyKey(CSN,used_key, div_key);
501 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
502 printvar("Div key", div_key, 8);
503 printvar("CC_NR:",CCNR,12);
504 doMAC(CCNR,12,div_key, MAC);
505 printvar("MAC", MAC, 4);
506
507 UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
508 memcpy(d.d.asBytes, MAC, 4);
509 if(!fake_dummy_test) SendCommand(&d);
510
511 }else{
512 PrintAndLog("Failed to obtain CC! Aborting");
513 }
514 } else {
515 PrintAndLog("Command execute timeout");
516 }
517
518 return 0;
519 }
520
521 int CmdHFiClass_iso14443A_write(const char *Cmd)
522 {
523 uint8_t readerType = 0;
524 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
525 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
526 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
527 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
528 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
529
530 uint8_t blockNo=0;
531 uint8_t bldata[8]={0};
532
533 if (strlen(Cmd)<3)
534 {
535 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
536 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
537 return 0;
538 }
539
540 if (param_gethex(Cmd, 0, KEY, 16))
541 {
542 PrintAndLog("KEY must include 16 HEX symbols");
543 return 1;
544 }
545
546 blockNo = param_get8(Cmd, 1);
547 if (blockNo>32)
548 {
549 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
550 return 1;
551 }
552 if (param_gethex(Cmd, 2, bldata, 8))
553 {
554 PrintAndLog("Block data must include 8 HEX symbols");
555 return 1;
556 }
557
558 UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}};
559 SendCommand(&c);
560 UsbCommand resp;
561
562 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
563 uint8_t isOK = resp.arg[0] & 0xff;
564 uint8_t * data = resp.d.asBytes;
565
566 memcpy(CSN,data,8);
567 memcpy(CCNR,data+8,8);
568 PrintAndLog("DEBUG: %s",sprint_hex(CSN,8));
569 PrintAndLog("DEBUG: %s",sprint_hex(CCNR,8));
570 PrintAndLog("isOk:%02x", isOK);
571 } else {
572 PrintAndLog("Command execute timeout");
573 }
574
575 diversifyKey(CSN,KEY, div_key);
576
577 PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
578 doMAC(CCNR, 12,div_key, MAC);
579
580 UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
581 memcpy(c2.d.asBytes, bldata, 8);
582 memcpy(c2.d.asBytes+8, MAC, 4);
583 SendCommand(&c2);
584
585 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
586 uint8_t isOK = resp.arg[0] & 0xff;
587 uint8_t * data = resp.d.asBytes;
588
589 if (isOK)
590 PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
591 else
592 PrintAndLog("isOk:%02x", isOK);
593 } else {
594 PrintAndLog("Command execute timeout");
595 }
596 return 0;
597 }
598
599
600 static command_t CommandTable[] =
601 {
602 {"help", CmdHelp, 1, "This help"},
603 {"list", CmdHFiClassList, 0, "List iClass history"},
604 {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
605 {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
606 {"reader",CmdHFiClassReader, 0, "Read an iClass tag"},
607 {"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
608 {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
609 {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
610 {NULL, NULL, 0, NULL}
611 };
612
613 int CmdHFiClass(const char *Cmd)
614 {
615 CmdsParse(CommandTable, Cmd);
616 return 0;
617 }
618
619 int CmdHelp(const char *Cmd)
620 {
621 CmdsHelp(CommandTable);
622 return 0;
623 }
Impressum, Datenschutz