]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhficlass.c
Added Pm3-master changes from Holiman.
[proxmark3-svn] / client / cmdhficlass.c
CommitLineData
cee5a30d 1//-----------------------------------------------------------------------------
2// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3// Copyright (C) 2011 Gerhard de Koning Gans
f38a1528 4// Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende
cee5a30d 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>
9f6e9d15 16#include <sys/stat.h>
cee5a30d 17#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
18#include "data.h"
902cb3c0 19#include "proxmark3.h"
cee5a30d 20#include "ui.h"
21#include "cmdparser.h"
22#include "cmdhficlass.h"
f38a1528 23#include "../include/common.h"
14006804 24#include "util.h"
17cba269 25#include "cmdmain.h"
f38a1528 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"
cee5a30d 32
33static int CmdHelp(const char *Cmd);
34
17cba269
MHS
35int xorbits_8(uint8_t val)
36{
37 uint8_t res = val ^ (val >> 1); //1st pass
38 res = res ^ (res >> 1); // 2nd pass
39 res = res ^ (res >> 2); // 3rd pass
40 res = res ^ (res >> 4); // 4th pass
41 return res & 1;
42}
43
d3a22c7d 44int CmdHFiClassList(const char *Cmd)
45{
46 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
cee5a30d 47 return 0;
48}
49
cee5a30d 50int CmdHFiClassSnoop(const char *Cmd)
51{
52 UsbCommand c = {CMD_SNOOP_ICLASS};
53 SendCommand(&c);
54 return 0;
55}
a501c82b 56#define NUM_CSNS 15
1e262141 57int CmdHFiClassSim(const char *Cmd)
58{
59 uint8_t simType = 0;
60 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
61
17cba269
MHS
62 if (strlen(Cmd)<1) {
63 PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
64 PrintAndLog(" options");
65 PrintAndLog(" 0 <CSN> simulate the given CSN");
66 PrintAndLog(" 1 simulate default CSN");
67 PrintAndLog(" 2 iterate CSNs, gather MACs");
1e262141 68 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
17cba269 69 PrintAndLog(" sample: hf iclass sim 2");
1e262141 70 return 0;
71 }
72
73 simType = param_get8(Cmd, 0);
17cba269
MHS
74
75 if(simType == 0)
76 {
77 if (param_gethex(Cmd, 1, CSN, 16)) {
78 PrintAndLog("A CSN should consist of 16 HEX symbols");
79 return 1;
80 }
81 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
82
83 }
77abe781 84 if(simType > 2)
17cba269
MHS
85 {
86 PrintAndLog("Undefined simptype %d", simType);
87 return 1;
1e262141 88 }
17cba269 89 uint8_t numberOfCSNs=0;
1e262141 90
9f6e9d15
MHS
91 if(simType == 2)
92 {
a501c82b 93 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
9f6e9d15 94 UsbCommand resp = {0};
17cba269 95
f5ed4d12 96 /*uint8_t csns[8 * NUM_CSNS] = {
97 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
98 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
99 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
100 0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
101 0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
102 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
103 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
104 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
105*/
106
a501c82b 107 uint8_t csns[8*NUM_CSNS] = {
108 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
109 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
110 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
111 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
112 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
113 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
114 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
115 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
116 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
117 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
118 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
119 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
120 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
121 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
122 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
123
124 memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
9f6e9d15
MHS
125
126 SendCommand(&c);
127 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
128 PrintAndLog("Command timed out");
129 return 0;
130 }
1e262141 131
77abe781 132 uint8_t num_mac_responses = resp.arg[1];
a501c82b 133 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses, NUM_CSNS);
9f6e9d15 134
a501c82b 135 size_t datalen = NUM_CSNS*24;
9f6e9d15
MHS
136 /*
137 * Now, time to dump to file. We'll use this format:
77abe781 138 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
9f6e9d15 139 * So, it should wind up as
77abe781
MHS
140 * 8 * 24 bytes.
141 *
142 * The returndata from the pm3 is on the following format
143 * <4 byte NR><4 byte MAC>
144 * CC are all zeroes, CSN is the same as was sent in
9f6e9d15 145 **/
77abe781
MHS
146 void* dump = malloc(datalen);
147 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
9f6e9d15 148 uint8_t i = 0;
a501c82b 149 for(i = 0 ; i < NUM_CSNS ; i++)
9f6e9d15 150 {
77abe781
MHS
151 memcpy(dump+i*24, csns+i*8,8); //CSN
152 //8 zero bytes here...
153 //Then comes NR_MAC (eight bytes from the response)
154 memcpy(dump+i*24+16,resp.d.asBytes+i*8,8);
1e262141 155
9f6e9d15
MHS
156 }
157 /** Now, save to dumpfile **/
77abe781
MHS
158 saveFile("iclass_mac_attack", "bin", dump,datalen);
159 free(dump);
9f6e9d15
MHS
160 }else
161 {
162 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
163 memcpy(c.d.asBytes, CSN, 8);
164 SendCommand(&c);
165 }
f38a1528 166
1e262141 167 return 0;
168}
169
170int CmdHFiClassReader(const char *Cmd)
f38a1528 171{
172 UsbCommand c = {CMD_READER_ICLASS, {0}};
173 SendCommand(&c);
174 UsbCommand resp;
175 while(!ukbhit()){
176 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
177 uint8_t isOK = resp.arg[0] & 0xff;
178 uint8_t * data = resp.d.asBytes;
179
180 PrintAndLog("isOk:%02x", isOK);
d3a22c7d 181 if( isOK == 0){
182 //Aborted
183 PrintAndLog("Quitting...");
184 return 0;
185 }
f38a1528 186 if(isOK > 0)
187 {
188 PrintAndLog("CSN: %s",sprint_hex(data,8));
189 }
190 if(isOK >= 1)
191 {
192 PrintAndLog("CC: %s",sprint_hex(data+8,8));
193 }else{
194 PrintAndLog("No CC obtained");
195 }
196 } else {
197 PrintAndLog("Command execute timeout");
198 }
199 }
200
201 return 0;
202}
203
204int CmdHFiClassReader_Replay(const char *Cmd)
1e262141 205{
206 uint8_t readerType = 0;
f38a1528 207 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
1e262141 208
209 if (strlen(Cmd)<1) {
f38a1528 210 PrintAndLog("Usage: hf iclass replay <MAC>");
211 PrintAndLog(" sample: hf iclass replay 00112233");
1e262141 212 return 0;
c3963755 213 }
1e262141 214
f38a1528 215 if (param_gethex(Cmd, 0, MAC, 8)) {
216 PrintAndLog("MAC must include 8 HEX symbols");
217 return 1;
218 }
219
220 UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
221 memcpy(c.d.asBytes, MAC, 4);
222 SendCommand(&c);
223
224 return 0;
225}
226
227int CmdHFiClassReader_Dump(const char *Cmd)
228{
229 uint8_t readerType = 0;
230 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
231 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
232 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
233 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
234 //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
235 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
236 uint8_t keytable[128] = {0};
237 int elite = 0;
238 uint8_t *used_key;
239 int i;
240 if (strlen(Cmd)<1)
241 {
242 PrintAndLog("Usage: hf iclass dump <Key> [e]");
243 PrintAndLog(" Key - A 16 byte master key");
244 PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
245 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
246 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
247 PrintAndLog(" sample: hf iclass dump 0011223344556677");
248
249
250 return 0;
251 }
252
fecd8202 253 if (param_gethex(Cmd, 0, KEY, 16))
254 {
f38a1528 255 PrintAndLog("KEY must include 16 HEX symbols");
256 return 1;
257 }
9b82de75 258
f38a1528 259 if (param_getchar(Cmd, 1) == 'e')
260 {
261 PrintAndLog("Elite switch on");
262 elite = 1;
263
264 //calc h2
265 hash2(KEY, keytable);
266 printarr_human_readable("keytable", keytable, 128);
267
268 }
269
f5ed4d12 270 UsbCommand resp;
271 uint8_t key_sel[8] = {0};
272 uint8_t key_sel_p[8] = { 0 };
273
f38a1528 274 UsbCommand c = {CMD_READER_ICLASS, {0}};
d3a22c7d 275 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC;
1e262141 276 SendCommand(&c);
f38a1528 277
f5ed4d12 278
279
1d660bb9 280 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
281 {
282 PrintAndLog("Command execute timeout");
283 return 0;
284 }
285
f38a1528 286 uint8_t isOK = resp.arg[0] & 0xff;
287 uint8_t * data = resp.d.asBytes;
288
289 memcpy(CSN,data,8);
290 memcpy(CCNR,data+8,8);
291
292 PrintAndLog("isOk:%02x", isOK);
293
294 if(isOK > 0)
295 {
296 PrintAndLog("CSN: %s",sprint_hex(CSN,8));
297 }
1d660bb9 298 if(isOK <= 1){
299 PrintAndLog("Failed to obtain CC! Aborting");
300 return 0;
301 }
302 //Status 2 or higher
303
f38a1528 304 if(elite)
305 {
f38a1528 306 //Get the key index (hash1)
307 uint8_t key_index[8] = {0};
308
309 hash1(CSN, key_index);
310 printvar("hash1", key_index,8);
311 for(i = 0; i < 8 ; i++)
312 key_sel[i] = keytable[key_index[i]] & 0xFF;
f5ed4d12 313 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
f38a1528 314 printvar("k_sel", key_sel,8);
315 //Permute from iclass format to standard format
316 permutekey_rev(key_sel,key_sel_p);
317 used_key = key_sel_p;
318 }else{
f38a1528 319 used_key = KEY;
f38a1528 320 }
f5ed4d12 321
322 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
f38a1528 323 printvar("Used key",used_key,8);
324 diversifyKey(CSN,used_key, div_key);
f5ed4d12 325 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
f38a1528 326 printvar("Div key", div_key, 8);
327 printvar("CC_NR:",CCNR,12);
328 doMAC(CCNR,12,div_key, MAC);
329 printvar("MAC", MAC, 4);
330
1d660bb9 331 uint8_t iclass_data[32000] = {0};
332 uint8_t iclass_datalen = 0;
333 uint8_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
334
f38a1528 335 UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
336 memcpy(d.d.asBytes, MAC, 4);
1d660bb9 337 clearCommandBuffer();
338 SendCommand(&d);
339 PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
340 while (true) {
341 printf(".");
342 if (ukbhit()) {
343 getchar();
344 printf("\naborted via keyboard!\n");
345 break;
346 }
347 if(WaitForResponseTimeout(CMD_ACK,&resp,4500))
348 {
349 uint64_t dataLength = resp.arg[0];
350 iclass_blocksFailed |= resp.arg[1];
351
352 if(dataLength > 0)
353 {
354 memcpy(iclass_data, resp.d.asBytes,dataLength);
355 iclass_datalen += dataLength;
356 }else
357 {//Last transfer, datalength 0 means the dump is finished
358 PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen);
359 if(iclass_blocksFailed)
360 {
361 PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
362 }
363 if(iclass_datalen > 0)
364 {
365 char filename[100] = {0};
366 //create a preferred filename
367 snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
368 CSN[0],CSN[1],CSN[2],CSN[3],
369 CSN[4],CSN[5],CSN[6],CSN[7]);
370 saveFile(filename,"bin",iclass_data, iclass_datalen );
371
372 }
373 //Aaaand we're finished
374 return 0;
375 }
376 }
377 }
f38a1528 378
f38a1528 379
380 return 0;
381}
1e262141 382
f38a1528 383int CmdHFiClass_iso14443A_write(const char *Cmd)
384{
385 uint8_t readerType = 0;
386 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
387 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
388 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
389 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
390 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
391
392 uint8_t blockNo=0;
393 uint8_t bldata[8]={0};
394
395 if (strlen(Cmd)<3)
396 {
397 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
398 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
399 return 0;
400 }
401
402 if (param_gethex(Cmd, 0, KEY, 16))
403 {
404 PrintAndLog("KEY must include 16 HEX symbols");
405 return 1;
406 }
407
408 blockNo = param_get8(Cmd, 1);
409 if (blockNo>32)
410 {
411 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
fecd8202 412 return 1;
f38a1528 413 }
414 if (param_gethex(Cmd, 2, bldata, 8))
415 {
416 PrintAndLog("Block data must include 8 HEX symbols");
417 return 1;
418 }
419
420 UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}};
421 SendCommand(&c);
422 UsbCommand resp;
423
424 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
425 uint8_t isOK = resp.arg[0] & 0xff;
426 uint8_t * data = resp.d.asBytes;
427
428 memcpy(CSN,data,8);
429 memcpy(CCNR,data+8,8);
430 PrintAndLog("DEBUG: %s",sprint_hex(CSN,8));
431 PrintAndLog("DEBUG: %s",sprint_hex(CCNR,8));
1e262141 432 PrintAndLog("isOk:%02x", isOK);
433 } else {
434 PrintAndLog("Command execute timeout");
f38a1528 435 }
436
437 diversifyKey(CSN,KEY, div_key);
438
439 PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
440 doMAC(CCNR, 12,div_key, MAC);
441
442 UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
443 memcpy(c2.d.asBytes, bldata, 8);
444 memcpy(c2.d.asBytes+8, MAC, 4);
445 SendCommand(&c2);
446
447 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
448 uint8_t isOK = resp.arg[0] & 0xff;
449 uint8_t * data = resp.d.asBytes;
1e262141 450
f38a1528 451 if (isOK)
452 PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
453 else
454 PrintAndLog("isOk:%02x", isOK);
455 } else {
456 PrintAndLog("Command execute timeout");
457 }
1e262141 458 return 0;
459}
10403a6a 460int CmdHFiClass_loclass(const char *Cmd)
461{
462 char opt = param_getchar(Cmd, 0);
463
464 if (strlen(Cmd)<1 || opt == 'h') {
465 PrintAndLog("Usage: hf iclass loclass [options]");
466 PrintAndLog("Options:");
467 PrintAndLog("h Show this help");
468 PrintAndLog("t Perform self-test");
469 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
470 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
471 PrintAndLog(" malicious CSNs, and their protocol responses");
472 PrintAndLog(" The the binary format of the file is expected to be as follows: ");
473 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
474 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
475 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
476 PrintAndLog(" ... totalling N*24 bytes");
477 return 0;
478 }
479 char fileName[255] = {0};
480 if(opt == 'f')
481 {
482 if(param_getstr(Cmd, 1, fileName) > 0)
483 {
484 return bruteforceFileNoKeys(fileName);
485 }else
486 {
487 PrintAndLog("You must specify a filename");
488 }
489 }
490 else if(opt == 't')
491 {
492 int errors = testCipherUtils();
493 errors += testMAC();
494 errors += doKeyTests(0);
495 errors += testElite();
496 if(errors)
497 {
498 prnlog("OBS! There were errors!!!");
499 }
500 return errors;
501 }
1e262141 502
10403a6a 503 return 0;
504}
f38a1528 505
cee5a30d 506static command_t CommandTable[] =
507{
508 {"help", CmdHelp, 1, "This help"},
d3a22c7d 509 {"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"},
cee5a30d 510 {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
1e262141 511 {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
fecd8202 512 {"reader",CmdHFiClassReader, 0, "Read an iClass tag"},
f38a1528 513 {"replay", CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
514 {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
515 {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
10403a6a 516 {"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"},
cee5a30d 517 {NULL, NULL, 0, NULL}
518};
519
520int CmdHFiClass(const char *Cmd)
521{
522 CmdsParse(CommandTable, Cmd);
523 return 0;
524}
525
526int CmdHelp(const char *Cmd)
527{
528 CmdsHelp(CommandTable);
9f6e9d15
MHS
529 return 0;
530}
Impressum, Datenschutz