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