]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhficlass.c
Merge branch 'master' of https://github.com/Proxmark/proxmark3
[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
33 static int CmdHelp(const char *Cmd);
34
35 int 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
44 int CmdHFiClassList(const char *Cmd)
45 {
46 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
47 return 0;
48 }
49
50 int CmdHFiClassSnoop(const char *Cmd)
51 {
52 UsbCommand c = {CMD_SNOOP_ICLASS};
53 SendCommand(&c);
54 return 0;
55 }
56 #define NUM_CSNS 15
57 int CmdHFiClassSim(const char *Cmd)
58 {
59 uint8_t simType = 0;
60 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
61
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");
68 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
69 PrintAndLog(" sample: hf iclass sim 2");
70 return 0;
71 }
72
73 simType = param_get8(Cmd, 0);
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 }
84 if(simType > 2)
85 {
86 PrintAndLog("Undefined simptype %d", simType);
87 return 1;
88 }
89 uint8_t numberOfCSNs=0;
90
91 if(simType == 2)
92 {
93 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
94 UsbCommand resp = {0};
95
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
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);
125
126 SendCommand(&c);
127 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
128 PrintAndLog("Command timed out");
129 return 0;
130 }
131
132 uint8_t num_mac_responses = resp.arg[1];
133 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
134
135 size_t datalen = NUM_CSNS*24;
136 /*
137 * Now, time to dump to file. We'll use this format:
138 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
139 * So, it should wind up as
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
145 **/
146 void* dump = malloc(datalen);
147 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
148 uint8_t i = 0;
149 for(i = 0 ; i < NUM_CSNS ; i++)
150 {
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);
155
156 }
157 /** Now, save to dumpfile **/
158 saveFile("iclass_mac_attack", "bin", dump,datalen);
159 free(dump);
160 }else
161 {
162 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
163 memcpy(c.d.asBytes, CSN, 8);
164 SendCommand(&c);
165 }
166
167 return 0;
168 }
169
170 int CmdHFiClassReader(const char *Cmd)
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);
181 if( isOK == 0){
182 //Aborted
183 PrintAndLog("Quitting...");
184 return 0;
185 }
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
204 int CmdHFiClassReader_Replay(const char *Cmd)
205 {
206 uint8_t readerType = 0;
207 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
208
209 if (strlen(Cmd)<1) {
210 PrintAndLog("Usage: hf iclass replay <MAC>");
211 PrintAndLog(" sample: hf iclass replay 00112233");
212 return 0;
213 }
214
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
227 int 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
253 if (param_gethex(Cmd, 0, KEY, 16))
254 {
255 PrintAndLog("KEY must include 16 HEX symbols");
256 return 1;
257 }
258
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
270 UsbCommand resp;
271 uint8_t key_sel[8] = {0};
272 uint8_t key_sel_p[8] = { 0 };
273
274 //HACK -- Below is for testing without access to a tag
275 uint8_t fake_dummy_test = false;
276 if(fake_dummy_test)
277 {
278 uint8_t xdata[16] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0, //CSN from http://www.proxmark.org/forum/viewtopic.php?pid=11230#p11230
279 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Just a random CC. Would be good to add a real testcase here
280 memcpy(resp.d.asBytes,xdata, 16);
281 resp.arg[0] = 2;
282 }
283
284 //End hack
285
286
287 UsbCommand c = {CMD_READER_ICLASS, {0}};
288 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC;
289 if(!fake_dummy_test)
290 SendCommand(&c);
291
292
293
294 if (fake_dummy_test || WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
295 uint8_t isOK = resp.arg[0] & 0xff;
296 uint8_t * data = resp.d.asBytes;
297
298 memcpy(CSN,data,8);
299 memcpy(CCNR,data+8,8);
300
301 PrintAndLog("isOk:%02x", isOK);
302
303 if(isOK > 0)
304 {
305 PrintAndLog("CSN: %s",sprint_hex(CSN,8));
306 }
307 if(isOK > 1)
308 {
309 if(elite)
310 {
311 //Get the key index (hash1)
312 uint8_t key_index[8] = {0};
313
314 hash1(CSN, key_index);
315 printvar("hash1", key_index,8);
316 for(i = 0; i < 8 ; i++)
317 key_sel[i] = keytable[key_index[i]] & 0xFF;
318 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
319 printvar("k_sel", key_sel,8);
320 //Permute from iclass format to standard format
321 permutekey_rev(key_sel,key_sel_p);
322 used_key = key_sel_p;
323 }else{
324 //Perhaps this should also be permuted to std format?
325 // Something like the code below? I have no std system
326 // to test this with /Martin
327
328 //uint8_t key_sel_p[8] = { 0 };
329 //permutekey_rev(KEY,key_sel_p);
330 //used_key = key_sel_p;
331
332 used_key = KEY;
333
334 }
335
336 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
337 printvar("Used key",used_key,8);
338 diversifyKey(CSN,used_key, div_key);
339 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
340 printvar("Div key", div_key, 8);
341 printvar("CC_NR:",CCNR,12);
342 doMAC(CCNR,12,div_key, MAC);
343 printvar("MAC", MAC, 4);
344
345 UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
346 memcpy(d.d.asBytes, MAC, 4);
347 if(!fake_dummy_test) SendCommand(&d);
348
349 }else{
350 PrintAndLog("Failed to obtain CC! Aborting");
351 }
352 } else {
353 PrintAndLog("Command execute timeout");
354 }
355
356 return 0;
357 }
358
359 int CmdHFiClass_iso14443A_write(const char *Cmd)
360 {
361 uint8_t readerType = 0;
362 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
363 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
364 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
365 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
366 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
367
368 uint8_t blockNo=0;
369 uint8_t bldata[8]={0};
370
371 if (strlen(Cmd)<3)
372 {
373 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
374 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
375 return 0;
376 }
377
378 if (param_gethex(Cmd, 0, KEY, 16))
379 {
380 PrintAndLog("KEY must include 16 HEX symbols");
381 return 1;
382 }
383
384 blockNo = param_get8(Cmd, 1);
385 if (blockNo>32)
386 {
387 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
388 return 1;
389 }
390 if (param_gethex(Cmd, 2, bldata, 8))
391 {
392 PrintAndLog("Block data must include 8 HEX symbols");
393 return 1;
394 }
395
396 UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}};
397 SendCommand(&c);
398 UsbCommand resp;
399
400 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
401 uint8_t isOK = resp.arg[0] & 0xff;
402 uint8_t * data = resp.d.asBytes;
403
404 memcpy(CSN,data,8);
405 memcpy(CCNR,data+8,8);
406 PrintAndLog("DEBUG: %s",sprint_hex(CSN,8));
407 PrintAndLog("DEBUG: %s",sprint_hex(CCNR,8));
408 PrintAndLog("isOk:%02x", isOK);
409 } else {
410 PrintAndLog("Command execute timeout");
411 }
412
413 diversifyKey(CSN,KEY, div_key);
414
415 PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
416 doMAC(CCNR, 12,div_key, MAC);
417
418 UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
419 memcpy(c2.d.asBytes, bldata, 8);
420 memcpy(c2.d.asBytes+8, MAC, 4);
421 SendCommand(&c2);
422
423 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
424 uint8_t isOK = resp.arg[0] & 0xff;
425 uint8_t * data = resp.d.asBytes;
426
427 if (isOK)
428 PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
429 else
430 PrintAndLog("isOk:%02x", isOK);
431 } else {
432 PrintAndLog("Command execute timeout");
433 }
434 return 0;
435 }
436 int CmdHFiClass_loclass(const char *Cmd)
437 {
438 char opt = param_getchar(Cmd, 0);
439
440 if (strlen(Cmd)<1 || opt == 'h') {
441 PrintAndLog("Usage: hf iclass loclass [options]");
442 PrintAndLog("Options:");
443 PrintAndLog("h Show this help");
444 PrintAndLog("t Perform self-test");
445 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
446 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
447 PrintAndLog(" malicious CSNs, and their protocol responses");
448 PrintAndLog(" The the binary format of the file is expected to be as follows: ");
449 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
450 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
451 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
452 PrintAndLog(" ... totalling N*24 bytes");
453 return 0;
454 }
455 char fileName[255] = {0};
456 if(opt == 'f')
457 {
458 if(param_getstr(Cmd, 1, fileName) > 0)
459 {
460 return bruteforceFileNoKeys(fileName);
461 }else
462 {
463 PrintAndLog("You must specify a filename");
464 }
465 }
466 else if(opt == 't')
467 {
468 int errors = testCipherUtils();
469 errors += testMAC();
470 errors += doKeyTests(0);
471 errors += testElite();
472 if(errors)
473 {
474 prnlog("OBS! There were errors!!!");
475 }
476 return errors;
477 }
478
479 return 0;
480 }
481
482 static command_t CommandTable[] =
483 {
484 {"help", CmdHelp, 1, "This help"},
485 {"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"},
486 {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
487 {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
488 {"reader",CmdHFiClassReader, 0, "Read an iClass tag"},
489 {"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
490 {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
491 {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
492 {"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"},
493 {NULL, NULL, 0, NULL}
494 };
495
496 int CmdHFiClass(const char *Cmd)
497 {
498 CmdsParse(CommandTable, Cmd);
499 return 0;
500 }
501
502 int CmdHelp(const char *Cmd)
503 {
504 CmdsHelp(CommandTable);
505 return 0;
506 }
Impressum, Datenschutz