]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhficlass.c
db3de20577a718a78999eba5158a5c15d96b8387
[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 "proxmark3.h"
20 #include "ui.h"
21 #include "cmdparser.h"
22 #include "cmdhficlass.h"
23 #include "common.h"
24 #include "util.h"
25 #include "cmdmain.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"
33 #include "usb_cmd.h"
34 #include "cmdhfmfu.h"
35
36 #define llX PRIx64
37
38 static int CmdHelp(const char *Cmd);
39
40 #define ICLASS_KEYS_MAX 8
41 static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
42 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
43 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
44 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
45 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
46 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
47 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
48 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
49 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
50 };
51
52 typedef struct iclass_block {
53 uint8_t d[8];
54 } iclass_block_t;
55
56 int xorbits_8(uint8_t val)
57 {
58 uint8_t res = val ^ (val >> 1); //1st pass
59 res = res ^ (res >> 1); // 2nd pass
60 res = res ^ (res >> 2); // 3rd pass
61 res = res ^ (res >> 4); // 4th pass
62 return res & 1;
63 }
64
65 int CmdHFiClassList(const char *Cmd)
66 {
67 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
68 return 0;
69 }
70
71 int CmdHFiClassSnoop(const char *Cmd)
72 {
73 UsbCommand c = {CMD_SNOOP_ICLASS};
74 SendCommand(&c);
75 return 0;
76 }
77 int usage_hf_iclass_sim()
78 {
79 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
80 PrintAndLog(" options");
81 PrintAndLog(" 0 <CSN> simulate the given CSN");
82 PrintAndLog(" 1 simulate default CSN");
83 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
84 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
85 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
86 PrintAndLog(" example: hf iclass sim 2");
87 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
88 PrintAndLog(" hf iclass sim 3");
89 return 0;
90 }
91
92 #define NUM_CSNS 15
93 int CmdHFiClassSim(const char *Cmd)
94 {
95 uint8_t simType = 0;
96 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
97
98 if (strlen(Cmd)<1) {
99 return usage_hf_iclass_sim();
100 }
101 simType = param_get8ex(Cmd, 0, 0, 10);
102
103 if(simType == 0)
104 {
105 if (param_gethex(Cmd, 1, CSN, 16)) {
106 PrintAndLog("A CSN should consist of 16 HEX symbols");
107 return usage_hf_iclass_sim();
108 }
109
110 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
111 }
112 if(simType > 3)
113 {
114 PrintAndLog("Undefined simptype %d", simType);
115 return usage_hf_iclass_sim();
116 }
117
118 uint8_t numberOfCSNs=0;
119 if(simType == 2)
120 {
121 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
122 UsbCommand resp = {0};
123
124 uint8_t csns[8*NUM_CSNS] = {
125 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
126 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
127 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
128 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
129 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
130 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
131 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
132 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
133 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
134 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
135 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
136 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
137 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
138 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
139 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
140
141 memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
142
143 SendCommand(&c);
144 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
145 PrintAndLog("Command timed out");
146 return 0;
147 }
148
149 uint8_t num_mac_responses = resp.arg[1];
150 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
151
152 size_t datalen = NUM_CSNS*24;
153 /*
154 * Now, time to dump to file. We'll use this format:
155 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
156 * So, it should wind up as
157 * 8 * 24 bytes.
158 *
159 * The returndata from the pm3 is on the following format
160 * <4 byte NR><4 byte MAC>
161 * CC are all zeroes, CSN is the same as was sent in
162 **/
163 void* dump = malloc(datalen);
164 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
165 uint8_t i = 0;
166 for(i = 0 ; i < NUM_CSNS ; i++)
167 {
168 memcpy(dump+i*24, csns+i*8,8); //CSN
169 //8 zero bytes here...
170 //Then comes NR_MAC (eight bytes from the response)
171 memcpy(dump+i*24+16,resp.d.asBytes+i*8,8);
172
173 }
174 /** Now, save to dumpfile **/
175 saveFile("iclass_mac_attack", "bin", dump,datalen);
176 free(dump);
177 }else
178 {
179 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
180 memcpy(c.d.asBytes, CSN, 8);
181 SendCommand(&c);
182 }
183
184 return 0;
185 }
186
187 int HFiClassReader(const char *Cmd, bool loop, bool verbose)
188 {
189 bool tagFound = false;
190 UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN|
191 FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_AA}};
192 // loop in client not device - else on windows have a communication error
193 c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY;
194 UsbCommand resp;
195 while(!ukbhit()){
196 SendCommand(&c);
197 if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
198 uint8_t readStatus = resp.arg[0] & 0xff;
199 uint8_t *data = resp.d.asBytes;
200
201 if (verbose)
202 PrintAndLog("Readstatus:%02x", readStatus);
203 if( readStatus == 0){
204 //Aborted
205 if (verbose) PrintAndLog("Quitting...");
206 return 0;
207 }
208 if( readStatus & FLAG_ICLASS_READER_CSN){
209 PrintAndLog("CSN: %s",sprint_hex(data,8));
210 tagFound = true;
211 }
212 if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s",sprint_hex(data+16,8));
213 if( readStatus & FLAG_ICLASS_READER_CONF){
214 printIclassDumpInfo(data);
215 }
216 if (tagFound && !loop) return 1;
217 } else {
218 if (verbose) PrintAndLog("Command execute timeout");
219 }
220 if (!loop) break;
221 }
222 return 0;
223 }
224
225 int CmdHFiClassReader(const char *Cmd)
226 {
227 return HFiClassReader(Cmd, true, true);
228 }
229
230 int CmdHFiClassReader_Replay(const char *Cmd)
231 {
232 uint8_t readerType = 0;
233 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
234
235 if (strlen(Cmd)<1) {
236 PrintAndLog("Usage: hf iclass replay <MAC>");
237 PrintAndLog(" sample: hf iclass replay 00112233");
238 return 0;
239 }
240
241 if (param_gethex(Cmd, 0, MAC, 8)) {
242 PrintAndLog("MAC must include 8 HEX symbols");
243 return 1;
244 }
245
246 UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
247 memcpy(c.d.asBytes, MAC, 4);
248 SendCommand(&c);
249
250 return 0;
251 }
252
253 int hf_iclass_eload_usage()
254 {
255 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
256 PrintAndLog("Usage: hf iclass eload f <filename>");
257 PrintAndLog("");
258 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
259 return 0;
260 }
261
262 int iclassEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
263 UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};
264 memcpy(c.d.asBytes, data, blocksCount * 16);
265 SendCommand(&c);
266 return 0;
267 }
268 int CmdHFiClassELoad(const char *Cmd)
269 {
270
271 char opt = param_getchar(Cmd, 0);
272 if (strlen(Cmd)<1 || opt == 'h')
273 return hf_iclass_eload_usage();
274
275 //File handling and reading
276 FILE *f;
277 char filename[FILE_PATH_SIZE];
278 if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0)
279 {
280 f = fopen(filename, "rb");
281 }else{
282 return hf_iclass_eload_usage();
283 }
284
285 if(!f) {
286 PrintAndLog("Failed to read from file '%s'", filename);
287 return 1;
288 }
289
290 fseek(f, 0, SEEK_END);
291 long fsize = ftell(f);
292 fseek(f, 0, SEEK_SET);
293
294 uint8_t *dump = malloc(fsize);
295
296
297 size_t bytes_read = fread(dump, 1, fsize, f);
298 fclose(f);
299
300 printIclassDumpInfo(dump);
301 //Validate
302
303 if (bytes_read < fsize)
304 {
305 prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
306 free(dump);
307 return 1;
308 }
309 //Send to device
310 uint32_t bytes_sent = 0;
311 uint32_t bytes_remaining = bytes_read;
312
313 while(bytes_remaining > 0){
314 uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining);
315 UsbCommand c = {CMD_ICLASS_EML_MEMSET, {bytes_sent,bytes_in_packet,0}};
316 memcpy(c.d.asBytes, dump, bytes_in_packet);
317 SendCommand(&c);
318 bytes_remaining -= bytes_in_packet;
319 bytes_sent += bytes_in_packet;
320 }
321 free(dump);
322 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent);
323 return 0;
324 }
325
326 int readKeyfile(const char *filename, size_t len, uint8_t* buffer)
327 {
328 FILE *f = fopen(filename, "rb");
329 if(!f) {
330 PrintAndLog("Failed to read from file '%s'", filename);
331 return 1;
332 }
333 fseek(f, 0, SEEK_END);
334 long fsize = ftell(f);
335 fseek(f, 0, SEEK_SET);
336 size_t bytes_read = fread(buffer, 1, len, f);
337 fclose(f);
338 if(fsize != len)
339 {
340 PrintAndLog("Warning, file size is %d, expected %d", fsize, len);
341 return 1;
342 }
343 if(bytes_read != len)
344 {
345 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len);
346 return 1;
347 }
348 return 0;
349 }
350
351 int usage_hf_iclass_decrypt()
352 {
353 PrintAndLog("Usage: hf iclass decrypt f <tagdump> o ");
354 PrintAndLog("");
355 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
356 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
357 PrintAndLog("");
358 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
359 PrintAndLog("");
360 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
361 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
362 PrintAndLog("which is defined by the configuration block.");
363 return 1;
364 }
365
366 int CmdHFiClassDecrypt(const char *Cmd)
367 {
368 uint8_t key[16] = { 0 };
369 if(readKeyfile("iclass_decryptionkey.bin", 16, key))
370 {
371 usage_hf_iclass_decrypt();
372 return 1;
373 }
374 PrintAndLog("Decryption file found... ");
375 char opt = param_getchar(Cmd, 0);
376 if (strlen(Cmd)<1 || opt == 'h')
377 return usage_hf_iclass_decrypt();
378
379 //Open the tagdump-file
380 FILE *f;
381 char filename[FILE_PATH_SIZE];
382 if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0)
383 {
384 f = fopen(filename, "rb");
385 }else{
386 return usage_hf_iclass_decrypt();
387 }
388
389 fseek(f, 0, SEEK_END);
390 long fsize = ftell(f);
391 fseek(f, 0, SEEK_SET);
392 uint8_t enc_dump[8] = {0};
393 uint8_t *decrypted = malloc(fsize);
394 des3_context ctx = { DES_DECRYPT ,{ 0 } };
395 des3_set2key_dec( &ctx, key);
396 size_t bytes_read = fread(enc_dump, 1, 8, f);
397
398 //Use the first block (CSN) for filename
399 char outfilename[FILE_PATH_SIZE] = { 0 };
400 snprintf(outfilename,FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
401 enc_dump[0],enc_dump[1],enc_dump[2],enc_dump[3],
402 enc_dump[4],enc_dump[5],enc_dump[6],enc_dump[7]);
403
404 size_t blocknum =0;
405 while(bytes_read == 8)
406 {
407 if(blocknum < 7)
408 {
409 memcpy(decrypted+(blocknum*8), enc_dump, 8);
410 }else{
411 des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
412 }
413 printvar("decrypted block", decrypted +(blocknum*8), 8);
414 bytes_read = fread(enc_dump, 1, 8, f);
415 blocknum++;
416 }
417 fclose(f);
418
419 saveFile(outfilename,"bin", decrypted, blocknum*8);
420
421 return 0;
422 }
423
424 int usage_hf_iclass_encrypt(){
425 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
426 PrintAndLog("");
427 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
428 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
429 PrintAndLog("");
430 PrintAndLog("example: hf iclass encrypt 0102030405060708");
431 PrintAndLog("");
432 return 0;
433 }
434
435 int iClassEncryptBlkData(uint8_t *blkData)
436 {
437 uint8_t key[16] = { 0 };
438 if(readKeyfile("iclass_decryptionkey.bin", 16, key))
439 {
440 usage_hf_iclass_encrypt();
441 return 1;
442 }
443 PrintAndLog("Decryption file found... ");
444
445 uint8_t decryptedData[16];
446 uint8_t *decrypted = decryptedData;
447 des3_context ctx = { DES_DECRYPT ,{ 0 } };
448 des3_set2key_enc( &ctx, key);
449
450 des3_crypt_ecb(&ctx, blkData,decrypted);
451 //printvar("decrypted block", decrypted, 8);
452 memcpy(blkData,decrypted,8);
453
454 return 1;
455 }
456
457 int CmdHFiClassEncryptBlk(const char *Cmd)
458 {
459 uint8_t blkData[8] = {0};
460 char opt = param_getchar(Cmd, 0);
461 if (strlen(Cmd)<1 || opt == 'h')
462 return usage_hf_iclass_encrypt();
463
464 //get the bytes to encrypt
465 if (param_gethex(Cmd, 0, blkData, 16))
466 {
467 PrintAndLog("BlockData must include 16 HEX symbols");
468 return 0;
469 }
470 if (!iClassEncryptBlkData(blkData)) return 0;
471
472 printvar("encrypted block", blkData, 8);
473 return 1;
474 }
475
476 void Calc_wb_mac(uint8_t blockno,uint8_t *data,uint8_t *div_key,uint8_t MAC[4]){
477 uint8_t WB[9];
478 WB[0] = blockno;
479 memcpy(WB + 1,data,8);
480 doMAC_N(WB,sizeof(WB),div_key,MAC);
481 //printf("Cal wb mac block [%02x][%02x%02x%02x%02x%02x%02x%02x%02x] : MAC [%02x%02x%02x%02x]",WB[0],WB[1],WB[2],WB[3],WB[4],WB[5],WB[6],WB[7],WB[8],MAC[0],MAC[1],MAC[2],MAC[3]);
482 }
483
484 static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose){
485 UsbCommand resp;
486
487 UsbCommand c = {CMD_READER_ICLASS, {0}};
488 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
489 if (use_credit_key)
490 c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
491
492 clearCommandBuffer();
493 SendCommand(&c);
494 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
495 {
496 PrintAndLog("Command execute timeout");
497 return false;
498 }
499
500 uint8_t isOK = resp.arg[0] & 0xff;
501 uint8_t *data = resp.d.asBytes;
502
503 memcpy(CSN,data,8);
504 if (CCNR!=NULL)memcpy(CCNR,data+16,8);
505 //PrintAndLog("isOk:%02x", isOK);
506 if(isOK > 0)
507 {
508 if (verbose) PrintAndLog("CSN: %s",sprint_hex(CSN,8));
509 }
510 if(isOK <= 1){
511 PrintAndLog("Failed to obtain CC! Aborting");
512 return false;
513 }
514 return true;
515 }
516
517 static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool use_credit_key, bool elite, bool verbose) {
518 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
519 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
520 uint8_t keytable[128] = {0};
521 uint8_t *used_key;
522 uint8_t key_sel[8] = {0};
523 uint8_t key_sel_p[8] = { 0 };
524
525 if (!select_only(CSN, CCNR, use_credit_key, verbose))
526 return false;
527
528 if(elite) {
529 hash2(KEY, keytable);
530 //Get the key index (hash1)
531 uint8_t key_index[8] = {0};
532 hash1(CSN, key_index);
533 //printvar("hash1", key_index,8);
534 for(uint8_t i = 0; i < 8 ; i++)
535 key_sel[i] = keytable[key_index[i]] & 0xFF;
536 //PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
537 //printvar("k_sel", key_sel,8);
538 //Permute from iclass format to standard format
539 permutekey_rev(key_sel, key_sel_p);
540 used_key = key_sel_p;
541 } else {
542 used_key = KEY;
543 }
544 //PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
545 //printvar("Used key",KEY,8);
546 diversifyKey(CSN, used_key, div_key);
547 //PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
548 //printvar("Div key", div_key, 8);
549 //printvar("CC_NR:",CCNR,8);
550 doMAC(CCNR, div_key, MAC);
551 //printvar("MAC", MAC, 4);
552 UsbCommand resp;
553 UsbCommand d = {CMD_ICLASS_AUTHENTICATION, {0}};
554 memcpy(d.d.asBytes, MAC, 4);
555 clearCommandBuffer();
556 SendCommand(&d);
557 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
558 {
559 PrintAndLog("Auth Command execute timeout");
560 return false;
561 }
562 uint8_t isOK = resp.arg[0] & 0xff;
563 if (!isOK) {
564 PrintAndLog("Authentication error");
565 return false;
566 }
567 return true;
568 }
569
570 int usage_hf_iclass_dump(){
571 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e\n");
572 PrintAndLog("Options:");
573 PrintAndLog(" f <filename> : specify a filename to save dump to");
574 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
575 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
576 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
577 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
578 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
579 PrintAndLog(" NOTE: * = required");
580 PrintAndLog("Samples:");
581 PrintAndLog(" hf iclass dump k 001122334455667B");
582 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
583 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
584 return 0;
585 }
586
587 int CmdHFiClassReader_Dump(const char *Cmd){
588
589 uint8_t MAC[4] = {0x00,0x00,0x00,0x00};
590 uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
591 uint8_t c_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
592 uint8_t blockno = 0;
593 uint8_t numblks = 0;
594 uint8_t maxBlk = 32;
595 uint8_t KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
596 uint8_t CreditKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
597 uint8_t keyNbr = 0;
598 uint8_t dataLen = 0;
599 uint8_t fileNameLen = 0;
600 char filename[FILE_PATH_SIZE]={0};
601 char tempStr[50] = {0};
602 bool have_credit_key = false;
603 bool elite = false;
604 bool errors = false;
605 uint8_t cmdp = 0;
606
607 while(param_getchar(Cmd, cmdp) != 0x00)
608 {
609 switch(param_getchar(Cmd, cmdp))
610 {
611 case 'h':
612 case 'H':
613 return usage_hf_iclass_dump();
614 case 'c':
615 case 'C':
616 have_credit_key = true;
617 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
618 if (dataLen == 16) {
619 errors = param_gethex(tempStr, 0, CreditKEY, dataLen);
620 } else if (dataLen == 1) {
621 keyNbr = param_get8(Cmd, cmdp+1);
622 if (keyNbr <= ICLASS_KEYS_MAX) {
623 memcpy(CreditKEY, iClass_Key_Table[keyNbr], 8);
624 } else {
625 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
626 errors = true;
627 }
628 } else {
629 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
630 errors = true;
631 }
632 cmdp += 2;
633 break;
634 case 'e':
635 case 'E':
636 elite = true;
637 cmdp++;
638 break;
639 case 'f':
640 case 'F':
641 fileNameLen = param_getstr(Cmd, cmdp+1, filename);
642 if (fileNameLen < 1) {
643 PrintAndLog("No filename found after f");
644 errors = true;
645 }
646 cmdp += 2;
647 break;
648 case 'k':
649 case 'K':
650 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
651 if (dataLen == 16) {
652 errors = param_gethex(tempStr, 0, KEY, dataLen);
653 } else if (dataLen == 1) {
654 keyNbr = param_get8(Cmd, cmdp+1);
655 if (keyNbr <= ICLASS_KEYS_MAX) {
656 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
657 } else {
658 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
659 errors = true;
660 }
661 } else {
662 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
663 errors = true;
664 }
665 cmdp += 2;
666 break;
667 default:
668 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
669 errors = true;
670 break;
671 }
672 if(errors) return usage_hf_iclass_dump();
673 }
674
675 if (cmdp < 2) return usage_hf_iclass_dump();
676
677 //get config and first 3 blocks
678 UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
679 FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY}};
680 UsbCommand resp;
681 uint8_t tag_data[255*8];
682 clearCommandBuffer();
683 SendCommand(&c);
684 if (WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
685 uint8_t readStatus = resp.arg[0] & 0xff;
686 uint8_t *data = resp.d.asBytes;
687
688 if( readStatus == 0){
689 //Aborted
690 PrintAndLog("No tag found...");
691 return 0;
692 }
693 if( readStatus & (FLAG_ICLASS_READER_CSN|FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_CC)){
694 memcpy(tag_data, data, 8*3);
695 /*for (; blockno < 3; blockno++) {
696 PrintAndLog(" | %02X | %02X%02X%02X%02X%02X%02X%02X%02X |", blockno,
697 data[(blockno*8)+0],data[(blockno*8)+1],data[(blockno*8)+2],data[(blockno*8)+3],
698 data[(blockno*8)+4],data[(blockno*8)+5],data[(blockno*8)+6],data[(blockno*8)+7]);
699 }*/
700 blockno+=2;
701 numblks = data[8];
702
703 if (data[13] & 0x80) {
704 // large memory - not able to dump pages currently
705 maxBlk = 255;
706 } else {
707 maxBlk = 32;
708 }
709 //PrintAndLog("maxBlk: %02X",maxBlk);
710 }
711 } else {
712 PrintAndLog("Command execute timeout");
713 return 0;
714 }
715
716 if (!select_and_auth(KEY, MAC, div_key, false, elite, false)){
717 //try twice - for some reason it sometimes fails the first time...
718 if (!select_and_auth(KEY, MAC, div_key, false, elite, false)){
719 ul_switch_off_field();
720 return 0;
721 }
722 }
723 //print debit div_key
724 //PrintAndLog(" | 03 | %02X%02X%02X%02X%02X%02X%02X%02X |",
725 // div_key[0],div_key[1],div_key[2],div_key[3],
726 // div_key[4],div_key[5],div_key[6],div_key[7]);
727
728 if (have_credit_key){
729 //turn off hf field
730 //PrintAndLog("attempt 1 to auth with credit key");
731 ul_switch_off_field();
732 memset(c_div_key,0,8);
733 memset(MAC,0,4);
734 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false)){
735 //try twice - for some reason it sometimes fails the first time...
736 memset(c_div_key,0,8);
737 memset(MAC,0,4);
738 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false)){
739 ul_switch_off_field();
740 return 0;
741 }
742 }
743 //print credit div_key
744 //PrintAndLog(" | 04 | %02X%02X%02X%02X%02X%02X%02X%02X |",
745 // div_key[0],div_key[1],div_key[2],div_key[3],
746 // div_key[4],div_key[5],div_key[6],div_key[7]);
747
748 //turn off hf field
749 //PrintAndLog("attempt 2 to auth with debit key");
750 ul_switch_off_field();
751 memset(div_key,0,8);
752 memset(MAC,0,4);
753 if (!select_and_auth(KEY, MAC, div_key, false, elite, false)){
754 //try twice - for some reason it sometimes fails the first time...
755 if (!select_and_auth(KEY, MAC, div_key, false, elite, false)){
756 ul_switch_off_field();
757 return 0;
758 }
759 }
760 }
761 //PrintAndLog("have %d blocks",blockno);
762
763 UsbCommand w = {CMD_ICLASS_DUMP, {blockno, numblks-blockno+1, 0x88}};
764 clearCommandBuffer();
765 SendCommand(&w);
766 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
767 PrintAndLog("Command execute time-out 1");
768 return 1;
769 }
770 uint32_t blocksRead = resp.arg[1];
771 uint8_t isOK = resp.arg[0] & 0xff;
772 if (!isOK && !blocksRead) {
773 PrintAndLog("Read Block Failed");
774 return 0;
775 }
776 uint32_t startindex = resp.arg[2];
777 if (blocksRead*8 > sizeof(tag_data)-(blockno*8)) {
778 PrintAndLog("Data exceeded Buffer size!");
779 blocksRead = (sizeof(tag_data)/8) - blockno;
780 }
781 //PrintAndLog("blocksread: %d, blockno: %d, startindex: %x",blocksRead,blockno,startindex);
782 GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex);
783 WaitForResponse(CMD_ACK,NULL);
784 uint32_t gotBytes = blocksRead*8 + blockno*8;
785
786 //PrintAndLog("have %d blocks",gotBytes/8);
787
788 if (have_credit_key && maxBlk > blockno+numblks+1) {
789 //turn off hf field
790 ul_switch_off_field();
791 //PrintAndLog("attempt 2 to auth with credit key");
792 memset(c_div_key,0,8);
793 memset(MAC,0,4);
794 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false)){
795 //try twice - for some reason it sometimes fails the first time...
796 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false)){
797 ul_switch_off_field();
798 return 0;
799 }
800 }
801 w.arg[0] = blockno + blocksRead;
802 w.arg[1] = maxBlk - (blockno + blocksRead);
803 w.arg[2] = 0x18;
804 clearCommandBuffer();
805 SendCommand(&w);
806 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
807 PrintAndLog("Command execute timeout 2");
808 return 0;
809 }
810 uint8_t isOK = resp.arg[0] & 0xff;
811 blocksRead = resp.arg[1];
812 if (!isOK && !blocksRead) {
813 PrintAndLog("Read Block Failed 2");
814 return 0;
815 }
816
817 startindex = resp.arg[2];
818 if (blocksRead*8 > sizeof(tag_data)-gotBytes) {
819 PrintAndLog("Data exceeded Buffer size!");
820 blocksRead = (sizeof(tag_data) - gotBytes)/8;
821 }
822 GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex);
823 WaitForResponse(CMD_ACK,NULL);
824
825 gotBytes += blocksRead*8;
826 //PrintAndLog("have %d blocks",gotBytes/8);
827 }
828
829 memcpy(tag_data+(3*8),div_key,8);
830 memcpy(tag_data+(4*8),c_div_key,8);
831
832 for (blockno = 0; blockno < gotBytes/8; blockno++){
833 PrintAndLog(" | %02X | %02X%02X%02X%02X%02X%02X%02X%02X |", blockno,
834 tag_data[(blockno*8)+0],tag_data[(blockno*8)+1],tag_data[(blockno*8)+2],tag_data[(blockno*8)+3],
835 tag_data[(blockno*8)+4],tag_data[(blockno*8)+5],tag_data[(blockno*8)+6],tag_data[(blockno*8)+7]);
836 }
837 if (filename[0] == 0){
838 snprintf(filename, FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
839 tag_data[0],tag_data[1],tag_data[2],tag_data[3],
840 tag_data[4],tag_data[5],tag_data[6],tag_data[7]);
841 }
842 saveFile(filename,"bin",tag_data, gotBytes );
843 PrintAndLog("Saving dump file - %d blocks read", gotBytes/8);
844 return 1;
845 }
846
847 /*
848 int CmdHFiClassReader_Dump(const char *Cmd)
849 {
850 uint8_t readerType = 0;
851 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
852 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
853 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
854 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
855 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
856 uint8_t keytable[128] = {0};
857 bool elite = false;
858 bool use_credit_key = false;
859 uint8_t *used_key;
860 int i;
861 if (strlen(Cmd) < 1)
862 {
863 return usage_hf_iclass_dump();
864 }
865
866 if (param_gethex(Cmd, 0, KEY, 16))
867 {
868 PrintAndLog("KEY must include 16 HEX symbols");
869 return 1;
870 }
871
872 if (param_getchar(Cmd, 1) == 'e')
873 {
874 PrintAndLog("Elite switch on");
875 elite = true;
876
877 //calc h2
878 hash2(KEY, keytable);
879 printarr_human_readable("keytable", keytable, 128);
880
881 if (param_getchar(Cmd, 2) == 'c')
882 use_credit_key = true;
883 } else if (param_getchar(Cmd, 1) == 'c'){
884 use_credit_key = true;
885 }
886
887 UsbCommand resp;
888 uint8_t key_sel[8] = {0};
889 uint8_t key_sel_p[8] = { 0 };
890
891 UsbCommand c = {CMD_READER_ICLASS, {0}};
892 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
893 if (use_credit_key)
894 c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
895 clearCommandBuffer();
896 SendCommand(&c);
897
898 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
899 {
900 PrintAndLog("Command execute timeout");
901 return 0;
902 }
903
904 uint8_t isOK = resp.arg[0] & 0xff;
905 uint8_t * data = resp.d.asBytes;
906
907 memcpy(CSN,data,8);
908 memcpy(CCNR,data+16,8);
909
910 PrintAndLog("isOk:%02x", isOK);
911
912 if(isOK > 0)
913 {
914 PrintAndLog("CSN: %s",sprint_hex(CSN,8));
915 }
916 if(isOK <= 1){
917 PrintAndLog("Failed to obtain CC! Aborting");
918 return 0;
919 }
920 //Status 2 or higher
921
922 if(elite)
923 {
924 //Get the key index (hash1)
925 uint8_t key_index[8] = {0};
926
927 hash1(CSN, key_index);
928 printvar("hash1", key_index,8);
929 for(i = 0; i < 8 ; i++)
930 key_sel[i] = keytable[key_index[i]] & 0xFF;
931 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
932 printvar("k_sel", key_sel,8);
933 //Permute from iclass format to standard format
934 permutekey_rev(key_sel,key_sel_p);
935 used_key = key_sel_p;
936 }else{
937 used_key = KEY;
938 }
939
940 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
941 printvar("Used key",used_key,8);
942 diversifyKey(CSN,used_key, div_key);
943 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
944 printvar("Div key", div_key, 8);
945 printvar("CC_NR:",CCNR,12);
946 doMAC(CCNR,div_key, MAC);
947 printvar("MAC", MAC, 4);
948
949 uint8_t iclass_data[32000] = {0};
950 uint32_t iclass_datalen = 0;
951 uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
952
953 UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
954 memcpy(d.d.asBytes, MAC, 4);
955 clearCommandBuffer();
956 SendCommand(&d);
957 PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
958 while (true) {
959 printf(".");
960 if (ukbhit()) {
961 getchar();
962 printf("\naborted via keyboard!\n");
963 break;
964 }
965 if(WaitForResponseTimeout(CMD_ACK,&resp,4500))
966 {
967 uint32_t dataLength = resp.arg[0];
968 iclass_blocksFailed |= resp.arg[1];
969 if(dataLength > 0)
970 {
971 PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
972 memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
973 iclass_datalen += dataLength;
974 }else
975 {//Last transfer, datalength 0 means the dump is finished
976 PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen);
977 if(iclass_blocksFailed)
978 {
979 PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
980 }
981 if(iclass_datalen > 0)
982 {
983 char filename[100] = {0};
984 //create a preferred filename
985 snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
986 CSN[0],CSN[1],CSN[2],CSN[3],
987 CSN[4],CSN[5],CSN[6],CSN[7]);
988 //Place the div_key in block 3
989 memcpy(iclass_data+(3*8), div_key, 8);
990 saveFile(filename,"bin",iclass_data, iclass_datalen );
991 }
992 //Aaaand we're finished
993 return 0;
994 }
995 }
996 }
997 return 0;
998 }
999 */
1000
1001 int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool verbose){
1002 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1003 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1004 uint8_t keyType = (use_credit_key) ? 0x18 : 0x88;
1005 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, verbose))
1006 return 0;
1007
1008 UsbCommand resp;
1009
1010 Calc_wb_mac(blockno,bldata,div_key,MAC);
1011 UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno, keyType}};
1012 memcpy(w.d.asBytes, bldata, 8);
1013 memcpy(w.d.asBytes + 8,MAC, 4);
1014
1015 clearCommandBuffer();
1016 SendCommand(&w);
1017 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1018 {
1019 PrintAndLog("Write Command execute timeout");
1020 return 0;
1021 }
1022 uint8_t isOK = resp.arg[0] & 0xff;
1023 if (!isOK) {
1024 PrintAndLog("Write Block Failed");
1025 return 0;
1026 }
1027 PrintAndLog("Write Block Successful");
1028
1029 return 1;
1030 }
1031
1032 int usage_hf_iclass_writeblock() {
1033 PrintAndLog("Options:");
1034 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1035 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
1036 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1037 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1038 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1039 PrintAndLog("Samples:");
1040 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
1041 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
1042 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
1043 return 0;
1044 }
1045
1046 int CmdHFiClass_WriteBlock(const char *Cmd) {
1047 uint8_t blockno=0;
1048 uint8_t bldata[8]={0};
1049 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1050 uint8_t keyNbr = 0;
1051 uint8_t dataLen = 0;
1052 char tempStr[50] = {0};
1053 bool use_credit_key = false;
1054 bool elite = false;
1055 bool errors = false;
1056 uint8_t cmdp = 0;
1057 while(param_getchar(Cmd, cmdp) != 0x00)
1058 {
1059 switch(param_getchar(Cmd, cmdp))
1060 {
1061 case 'h':
1062 case 'H':
1063 return usage_hf_iclass_writeblock();
1064 case 'b':
1065 case 'B':
1066 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
1067 PrintAndLog("Block No must include 2 HEX symbols\n");
1068 errors = true;
1069 }
1070 cmdp += 2;
1071 break;
1072 case 'c':
1073 case 'C':
1074 use_credit_key = true;
1075 cmdp++;
1076 break;
1077 case 'd':
1078 case 'D':
1079 if (param_gethex(Cmd, cmdp+1, bldata, 16))
1080 {
1081 PrintAndLog("KEY must include 16 HEX symbols\n");
1082 errors = true;
1083 }
1084 cmdp += 2;
1085 break;
1086 case 'e':
1087 case 'E':
1088 elite = true;
1089 cmdp++;
1090 break;
1091 case 'k':
1092 case 'K':
1093 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1094 if (dataLen == 16) {
1095 errors = param_gethex(tempStr, 0, KEY, dataLen);
1096 } else if (dataLen == 1) {
1097 keyNbr = param_get8(Cmd, cmdp+1);
1098 if (keyNbr <= ICLASS_KEYS_MAX) {
1099 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1100 } else {
1101 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1102 errors = true;
1103 }
1104 } else {
1105 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1106 errors = true;
1107 }
1108 cmdp += 2;
1109 break;
1110 default:
1111 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1112 errors = true;
1113 break;
1114 }
1115 if(errors) return usage_hf_iclass_writeblock();
1116 }
1117
1118 if (cmdp < 6) return usage_hf_iclass_writeblock();
1119
1120 return WriteBlock(blockno, bldata, KEY, use_credit_key, elite, true);
1121 }
1122
1123 int usage_hf_iclass_clone() {
1124 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> e c");
1125 PrintAndLog("Options:");
1126 PrintAndLog(" f <filename>: specify a filename to clone from");
1127 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
1128 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
1129 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1130 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1131 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1132 PrintAndLog("Samples:");
1133 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
1134 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
1135 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
1136 return -1;
1137 }
1138
1139 int CmdHFiClassCloneTag(const char *Cmd) {
1140 char filename[FILE_PATH_SIZE];
1141 char tempStr[50]={0};
1142 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1143 uint8_t keyNbr = 0;
1144 uint8_t fileNameLen = 0;
1145 uint8_t startblock = 0;
1146 uint8_t endblock = 0;
1147 uint8_t dataLen = 0;
1148 bool use_credit_key = false;
1149 bool elite = false;
1150 bool errors = false;
1151 uint8_t cmdp = 0;
1152 while(param_getchar(Cmd, cmdp) != 0x00)
1153 {
1154 switch(param_getchar(Cmd, cmdp))
1155 {
1156 case 'h':
1157 case 'H':
1158 return usage_hf_iclass_clone();
1159 case 'b':
1160 case 'B':
1161 if (param_gethex(Cmd, cmdp+1, &startblock, 2)) {
1162 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1163 errors = true;
1164 }
1165 cmdp += 2;
1166 break;
1167 case 'c':
1168 case 'C':
1169 use_credit_key = true;
1170 cmdp++;
1171 break;
1172 case 'e':
1173 case 'E':
1174 elite = true;
1175 cmdp++;
1176 break;
1177 case 'f':
1178 case 'F':
1179 fileNameLen = param_getstr(Cmd, cmdp+1, filename);
1180 if (fileNameLen < 1) {
1181 PrintAndLog("No filename found after f");
1182 errors = true;
1183 }
1184 cmdp += 2;
1185 break;
1186 case 'k':
1187 case 'K':
1188 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1189 if (dataLen == 16) {
1190 errors = param_gethex(tempStr, 0, KEY, dataLen);
1191 } else if (dataLen == 1) {
1192 keyNbr = param_get8(Cmd, cmdp+1);
1193 if (keyNbr <= ICLASS_KEYS_MAX) {
1194 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1195 } else {
1196 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1197 errors = true;
1198 }
1199 } else {
1200 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1201 errors = true;
1202 }
1203 cmdp += 2;
1204 break;
1205 case 'l':
1206 case 'L':
1207 if (param_gethex(Cmd, cmdp+1, &endblock, 2)) {
1208 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1209 errors = true;
1210 }
1211 cmdp += 2;
1212 break;
1213 default:
1214 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1215 errors = true;
1216 break;
1217 }
1218 if(errors) return usage_hf_iclass_clone();
1219 }
1220
1221 if (cmdp < 8) return usage_hf_iclass_clone();
1222
1223 FILE *f;
1224
1225 iclass_block_t tag_data[USB_CMD_DATA_SIZE/12];
1226
1227 if ((endblock-startblock+1)*12 > USB_CMD_DATA_SIZE) {
1228 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE/8);
1229 }
1230 // file handling and reading
1231 f = fopen(filename,"rb");
1232 if(!f) {
1233 PrintAndLog("Failed to read from file '%s'", filename);
1234 return 1;
1235 }
1236
1237 if (startblock<5) {
1238 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1239 return 0;
1240 }
1241 // now read data from the file from block 6 --- 19
1242 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1243 // then copy to usbcommand->asbytes; the max is 32 - 6 = 24 block 12 bytes each block 288 bytes then we can only accept to clone 21 blocks at the time,
1244 // else we have to create a share memory
1245 int i;
1246 fseek(f,startblock*8,SEEK_SET);
1247 fread(tag_data,sizeof(iclass_block_t),endblock - startblock + 1,f);
1248 /*
1249 for (i = 0; i < endblock - startblock+1; i++){
1250 printf("block [%02x] [%02x%02x%02x%02x%02x%02x%02x%02x]\n",i + startblock,tag_data[i].d[0],tag_data[i].d[1],tag_data[i].d[2],tag_data[i].d[3],tag_data[i].d[4],tag_data[i].d[5],tag_data[i].d[6],tag_data[i].d[7]);
1251 }*/
1252
1253 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1254 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1255
1256 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, true))
1257 return 0;
1258
1259 UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock,((use_credit_key) ? 0x18 : 0x88)}};
1260 uint8_t *ptr;
1261 // calculate all mac for every the block we will write
1262 for (i = startblock; i <= endblock; i++){
1263 Calc_wb_mac(i,tag_data[i - startblock].d,div_key,MAC);
1264 // usb command d start pointer = d + (i - 6) * 12
1265 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1266 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1267 // next one
1268 ptr = w.d.asBytes + (i - startblock) * 12;
1269 memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
1270 memcpy(ptr + 8,MAC, 4);
1271 }
1272 uint8_t p[12];
1273 for (i = 0; i <= endblock - startblock;i++){
1274 memcpy(p,w.d.asBytes + (i * 12),12);
1275 printf("block [%02x]",i + startblock);
1276 printf(" [%02x%02x%02x%02x%02x%02x%02x%02x]",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]);
1277 printf(" MAC [%02x%02x%02x%02x]\n",p[8],p[9],p[10],p[11]);
1278 }
1279 UsbCommand resp;
1280 SendCommand(&w);
1281 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1282 {
1283 PrintAndLog("Command execute timeout");
1284 return 0;
1285 }
1286 return 1;
1287 }
1288
1289 int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool verbose){
1290 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1291 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1292
1293 if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, verbose))
1294 return 0;
1295
1296 UsbCommand resp;
1297 UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno, keyType}};
1298 clearCommandBuffer();
1299 SendCommand(&w);
1300 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1301 {
1302 PrintAndLog("Command execute timeout");
1303 return 0;
1304 }
1305 uint8_t isOK = resp.arg[0] & 0xff;
1306 if (!isOK) {
1307 PrintAndLog("Read Block Failed");
1308 return 0;
1309 }
1310 //data read is stored in: resp.d.asBytes[0-15]
1311 if (verbose) PrintAndLog("Block %02X: %s\n",blockno, sprint_hex(resp.d.asBytes,8));
1312 return 1;
1313 }
1314
1315 int usage_hf_iclass_readblock(){
1316 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e\n");
1317 PrintAndLog("Options:");
1318 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1319 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1320 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1321 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1322 PrintAndLog("Samples:");
1323 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1324 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1325 PrintAndLog(" hf iclass readblk b 0A k 0");
1326 return 0;
1327 }
1328
1329 int CmdHFiClass_ReadBlock(const char *Cmd)
1330 {
1331 uint8_t blockno=0;
1332 uint8_t keyType = 0x88; //debit key
1333 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1334 uint8_t keyNbr = 0;
1335 uint8_t dataLen = 0;
1336 char tempStr[50] = {0};
1337 bool elite = false;
1338 bool errors = false;
1339 uint8_t cmdp = 0;
1340 while(param_getchar(Cmd, cmdp) != 0x00)
1341 {
1342 switch(param_getchar(Cmd, cmdp))
1343 {
1344 case 'h':
1345 case 'H':
1346 return usage_hf_iclass_readblock();
1347 case 'b':
1348 case 'B':
1349 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
1350 PrintAndLog("Block No must include 2 HEX symbols\n");
1351 errors = true;
1352 }
1353 cmdp += 2;
1354 break;
1355 case 'c':
1356 case 'C':
1357 keyType = 0x18;
1358 cmdp++;
1359 break;
1360 case 'e':
1361 case 'E':
1362 elite = true;
1363 cmdp++;
1364 break;
1365 case 'k':
1366 case 'K':
1367 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1368 if (dataLen == 16) {
1369 errors = param_gethex(tempStr, 0, KEY, dataLen);
1370 } else if (dataLen == 1) {
1371 keyNbr = param_get8(Cmd, cmdp+1);
1372 if (keyNbr <= ICLASS_KEYS_MAX) {
1373 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1374 } else {
1375 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1376 errors = true;
1377 }
1378 } else {
1379 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1380 errors = true;
1381 }
1382 cmdp += 2;
1383 break;
1384 default:
1385 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1386 errors = true;
1387 break;
1388 }
1389 if(errors) return usage_hf_iclass_readblock();
1390 }
1391
1392 if (cmdp < 4) return usage_hf_iclass_readblock();
1393
1394 return ReadBlock(KEY, blockno, keyType, elite, true);
1395 }
1396
1397 int CmdHFiClass_loclass(const char *Cmd)
1398 {
1399 char opt = param_getchar(Cmd, 0);
1400
1401 if (strlen(Cmd)<1 || opt == 'h') {
1402 PrintAndLog("Usage: hf iclass loclass [options]");
1403 PrintAndLog("Options:");
1404 PrintAndLog("h Show this help");
1405 PrintAndLog("t Perform self-test");
1406 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1407 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1408 PrintAndLog(" malicious CSNs, and their protocol responses");
1409 PrintAndLog(" The the binary format of the file is expected to be as follows: ");
1410 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1411 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1412 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1413 PrintAndLog(" ... totalling N*24 bytes");
1414 return 0;
1415 }
1416 char fileName[255] = {0};
1417 if(opt == 'f')
1418 {
1419 if(param_getstr(Cmd, 1, fileName) > 0)
1420 {
1421 return bruteforceFileNoKeys(fileName);
1422 }else
1423 {
1424 PrintAndLog("You must specify a filename");
1425 }
1426 }
1427 else if(opt == 't')
1428 {
1429 int errors = testCipherUtils();
1430 errors += testMAC();
1431 errors += doKeyTests(0);
1432 errors += testElite();
1433 if(errors)
1434 {
1435 prnlog("OBS! There were errors!!!");
1436 }
1437 return errors;
1438 }
1439
1440 return 0;
1441 }
1442
1443 int usage_hf_iclass_readtagfile(){
1444 PrintAndLog("Usage: hf iclass readtagfile <filename>");
1445 return 1;
1446 }
1447
1448 void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize){
1449 uint8_t blockdata[8];
1450 uint8_t mem_config;
1451 memcpy(&mem_config, iclass_dump + 13,1);
1452 uint8_t maxmemcount;
1453 uint8_t filemaxblock = filesize / 8;
1454 if (mem_config == 0x80)
1455 maxmemcount = 255;
1456 else
1457 maxmemcount = 32;
1458
1459 if (startblock == 0)
1460 startblock = 6;
1461 if ((endblock > maxmemcount) || (endblock == 0))
1462 endblock = maxmemcount;
1463 if (endblock > filemaxblock)
1464 endblock = filemaxblock;
1465 int i = startblock;
1466 int j;
1467 while (i < endblock){
1468 printf("block[%02X]: ",i);
1469 memcpy(blockdata,iclass_dump + (i * 8),8);
1470 for (j = 0;j < 8;j++)
1471 printf("%02X ",blockdata[j]);
1472 printf("\n");
1473 i++;
1474 }
1475 if ((i < filemaxblock) && (i < maxmemcount)){
1476 printf("block[%02X]: ",i);
1477 memcpy(blockdata,iclass_dump + (i * 8),8);
1478 for (j = 0;j < 8;j++)
1479 printf("%02X",blockdata[j]);
1480 printf("\n");
1481 }
1482 }
1483
1484 int CmdHFiClassReadTagFile(const char *Cmd)
1485 {
1486 int startblock = 0;
1487 int endblock = 0;
1488 char tempnum[5];
1489 FILE *f;
1490 char filename[FILE_PATH_SIZE];
1491 if (param_getstr(Cmd, 0, filename) < 1)
1492 return usage_hf_iclass_readtagfile();
1493 if (param_getstr(Cmd,1,(char *)&tempnum) < 1)
1494 startblock = 0;
1495 else
1496 sscanf(tempnum,"%d",&startblock);
1497
1498 if (param_getstr(Cmd,2,(char *)&tempnum) < 1)
1499 endblock = 0;
1500 else
1501 sscanf(tempnum,"%d",&endblock);
1502 // file handling and reading
1503 f = fopen(filename,"rb");
1504 if(!f) {
1505 PrintAndLog("Failed to read from file '%s'", filename);
1506 return 1;
1507 }
1508 fseek(f, 0, SEEK_END);
1509 long fsize = ftell(f);
1510 fseek(f, 0, SEEK_SET);
1511
1512 uint8_t *dump = malloc(fsize);
1513
1514
1515 size_t bytes_read = fread(dump, 1, fsize, f);
1516 fclose(f);
1517 uint8_t *csn = dump;
1518 printf("CSN : %02X %02X %02X %02X %02X %02X %02X %02X\n",csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
1519 // printIclassDumpInfo(dump);
1520 printIclassDumpContents(dump,startblock,endblock,bytes_read);
1521 free(dump);
1522 return 0;
1523 }
1524
1525 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv){
1526 uint64_t new_div = 0x00;
1527 new_div ^= sdiv;
1528 new_div ^= hdiv;
1529 return new_div;
1530 }
1531
1532 uint64_t hexarray_to_uint64(uint8_t *key){
1533 char temp[17];
1534 uint64_t uint_key;
1535 for (int i = 0;i < 8;i++)
1536 sprintf(&temp[(i *2)],"%02X",key[i]);
1537 temp[16] = '\0';
1538 if (sscanf(temp,"%016"llX,&uint_key) < 1)
1539 return 0;
1540 return uint_key;
1541 }
1542
1543 int usage_hf_iclass_calc_ekey(){
1544 PrintAndLog("Usage: hf iclass calc_ekey <STDKEY> <ELITE key> [c]");
1545 return 1;
1546 }
1547
1548 int CmdHFiClassCalcEKey(const char *Cmd){
1549 uint8_t STDKEY[8];
1550 uint8_t ELITEKEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1551 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1552 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1553 uint8_t std_div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1554 uint8_t elite_div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1555 uint8_t keytable[128] = {0};
1556 uint8_t key_index[8] = {0};
1557 uint64_t new_div_key;
1558 uint64_t i_elite_div_key;
1559 uint64_t i_std_div_key;
1560 bool use_credit_key = false;
1561 //memcpy(STDKEY,GLOBAL_KEY,sizeof(STDKEY));
1562 int i;
1563 if (strlen(Cmd) < 2)
1564 return usage_hf_iclass_calc_ekey();
1565
1566 if (param_gethex(Cmd, 0, STDKEY, 16))
1567 return usage_hf_iclass_calc_ekey();
1568
1569 if (param_gethex(Cmd, 1, ELITEKEY, 16) != 0)
1570 return usage_hf_iclass_calc_ekey();
1571
1572 if (param_getchar(Cmd, 2)=='c')
1573 use_credit_key = true;
1574
1575 hash2(ELITEKEY, keytable);
1576
1577 uint8_t key_sel[8] = { 0 };
1578 uint8_t key_sel_p[8] = { 0 };
1579
1580 if (!select_only(CSN, CCNR, use_credit_key, true))
1581 return 0;
1582
1583 diversifyKey(CSN, STDKEY, std_div_key);
1584
1585 // printvar("(S)Div key", std_div_key, 8);
1586 hash1(CSN, key_index);
1587 for(i = 0; i < 8 ; i++)
1588 key_sel[i] = keytable[key_index[i]] & 0xFF;
1589
1590 //Permute from iclass format to standard format
1591 permutekey_rev(key_sel, key_sel_p);
1592 diversifyKey(CSN, key_sel_p, elite_div_key);
1593 // printvar("(E)Div key", elite_div_key, 8);
1594 i_elite_div_key = hexarray_to_uint64(elite_div_key);
1595 i_std_div_key = hexarray_to_uint64(std_div_key);
1596 new_div_key = xorcheck(i_std_div_key, i_elite_div_key);
1597 printf("New Div Key : %016"llX"\n",new_div_key);
1598 return 0;
1599 }
1600
1601 int loadKeys(char *filename){
1602 FILE *f;
1603 f = fopen(filename,"rb");
1604 if(!f) {
1605 PrintAndLog("Failed to read from file '%s'", filename);
1606 return 0;
1607 }
1608 fseek(f, 0, SEEK_END);
1609 long fsize = ftell(f);
1610 fseek(f, 0, SEEK_SET);
1611
1612 uint8_t *dump = malloc(fsize);
1613
1614 size_t bytes_read = fread(dump, 1, fsize, f);
1615 fclose(f);
1616 if (bytes_read > ICLASS_KEYS_MAX * 8){
1617 PrintAndLog("File is too long to load - bytes: %u", bytes_read);
1618 free(dump);
1619 return 0;
1620 }
1621 uint8_t i = 0;
1622 for (; i < bytes_read/8; i++){
1623 memcpy(iClass_Key_Table[i],dump+(i*8),8);
1624 }
1625 free(dump);
1626 PrintAndLog("%u keys loaded", i);
1627 return 1;
1628 }
1629
1630 int saveKeys(char *filename){
1631 FILE *f;
1632 f = fopen(filename,"wb");
1633 if (f == NULL) {
1634 printf("error opening file %s\n",filename);
1635 return 0;
1636 }
1637 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1638 if (fwrite(iClass_Key_Table[i],8,1,f) != 1){
1639 PrintAndLog("save key failed to write to file: %s", filename);
1640 break;
1641 }
1642 }
1643 fclose(f);
1644 return 0;
1645 }
1646
1647 int printKeys(){
1648 PrintAndLog("");
1649 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1650 PrintAndLog("%u: %s",i,sprint_hex(iClass_Key_Table[i],8));
1651 }
1652 PrintAndLog("");
1653 return 0;
1654 }
1655
1656 int usage_hf_iclass_managekeys(){
1657 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1658 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1659 PrintAndLog(" Options:");
1660 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1661 PrintAndLog(" k <key> : set a key in memory");
1662 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1663 PrintAndLog(" s : save keys in memory to file specified by filename");
1664 PrintAndLog(" l : load keys to memory from file specified by filename");
1665 PrintAndLog(" p : print keys loaded into memory\n");
1666 PrintAndLog("Samples:");
1667 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1668 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1669 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1670 PrintAndLog(" print keys : hf iclass managekeys p\n");
1671 return 0;
1672 }
1673
1674 int CmdManageKeys(const char *Cmd){
1675 uint8_t keyNbr = 0;
1676 uint8_t dataLen = 0;
1677 uint8_t KEY[8] = {0};
1678 char filename[FILE_PATH_SIZE];
1679 uint8_t fileNameLen = 0;
1680 bool errors = false;
1681 uint8_t operation = 0;
1682 char tempStr[20];
1683 uint8_t cmdp = 0;
1684
1685 while(param_getchar(Cmd, cmdp) != 0x00)
1686 {
1687 switch(param_getchar(Cmd, cmdp))
1688 {
1689 case 'h':
1690 case 'H':
1691 return usage_hf_iclass_managekeys();
1692 case 'f':
1693 case 'F':
1694 fileNameLen = param_getstr(Cmd, cmdp+1, filename);
1695 if (fileNameLen < 1) {
1696 PrintAndLog("No filename found after f");
1697 errors = true;
1698 }
1699 cmdp += 2;
1700 break;
1701 case 'n':
1702 case 'N':
1703 keyNbr = param_get8(Cmd, cmdp+1);
1704 if (keyNbr < 0) {
1705 PrintAndLog("Wrong block number");
1706 errors = true;
1707 }
1708 cmdp += 2;
1709 break;
1710 case 'k':
1711 case 'K':
1712 operation += 3; //set key
1713 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1714 if (dataLen == 16) { //ul-c or ev1/ntag key length
1715 errors = param_gethex(tempStr, 0, KEY, dataLen);
1716 } else {
1717 PrintAndLog("\nERROR: Key is incorrect length\n");
1718 errors = true;
1719 }
1720 cmdp += 2;
1721 break;
1722 case 'p':
1723 case 'P':
1724 operation += 4; //print keys in memory
1725 cmdp++;
1726 break;
1727 case 'l':
1728 case 'L':
1729 operation += 5; //load keys from file
1730 cmdp++;
1731 break;
1732 case 's':
1733 case 'S':
1734 operation += 6; //save keys to file
1735 cmdp++;
1736 break;
1737 default:
1738 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1739 errors = true;
1740 break;
1741 }
1742 if(errors) return usage_hf_iclass_managekeys();
1743 }
1744 if (operation == 0){
1745 PrintAndLog("no operation specified (load, save, or print)\n");
1746 return usage_hf_iclass_managekeys();
1747 }
1748 if (operation > 6){
1749 PrintAndLog("Too many operations specified\n");
1750 return usage_hf_iclass_managekeys();
1751 }
1752 if (operation > 4 && fileNameLen == 0){
1753 PrintAndLog("You must enter a filename when loading or saving\n");
1754 return usage_hf_iclass_managekeys();
1755 }
1756
1757 switch (operation){
1758 case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); return 1;
1759 case 4: return printKeys();
1760 case 5: return loadKeys(filename);
1761 case 6: return saveKeys(filename);
1762 break;
1763 }
1764 return 0;
1765 }
1766
1767 static command_t CommandTable[] =
1768 {
1769 {"help", CmdHelp, 1, "This help"},
1770 {"calc_ekey", CmdHFiClassCalcEKey, 0, "Get Elite Diversified key (block 3) to write to convert std to elite"},
1771 {"clone", CmdHFiClassCloneTag, 0, "Authenticate and Clone from iClass bin file"},
1772 {"decrypt", CmdHFiClassDecrypt, 1, "Decrypt tagdump" },
1773 {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag's AA1"},
1774 {"eload", CmdHFiClassELoad, 0, "[experimental] Load data into iClass emulator memory"},
1775 {"encryptblk", CmdHFiClassEncryptBlk, 1, "[blockData] Encrypt given block data"},
1776 {"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"},
1777 //{"load", CmdHFiClass_load, 0, "Load from tagfile to iClass card"},
1778 {"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"},
1779 {"managekeys", CmdManageKeys, 1, "Manage the keys to use with iClass"},
1780 {"readblk", CmdHFiClass_ReadBlock, 0, "Authenticate and Read iClass block"},
1781 {"reader", CmdHFiClassReader, 0, "Read an iClass tag"},
1782 {"readtagfile", CmdHFiClassReadTagFile, 1, "Display Content from tagfile"},
1783 {"replay", CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
1784 {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
1785 {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
1786 {"writeblk", CmdHFiClass_WriteBlock, 0, "Authenticate and Write iClass block"},
1787 {NULL, NULL, 0, NULL}
1788 };
1789
1790 int CmdHFiClass(const char *Cmd)
1791 {
1792 CmdsParse(CommandTable, Cmd);
1793 return 0;
1794 }
1795
1796 int CmdHelp(const char *Cmd)
1797 {
1798 CmdsHelp(CommandTable);
1799 return 0;
1800 }
Impressum, Datenschutz