]>
Commit | Line | Data |
---|---|---|
cee5a30d | 1 | //----------------------------------------------------------------------------- |
2 | // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch | |
3 | // Copyright (C) 2011 Gerhard de Koning Gans | |
4 | // | |
5 | // This code is licensed to you under the terms of the GNU GPL, version 2 or, | |
6 | // at your option, any later version. See the LICENSE.txt file for the text of | |
7 | // the license. | |
8 | //----------------------------------------------------------------------------- | |
9 | // High frequency iClass commands | |
10 | //----------------------------------------------------------------------------- | |
11 | ||
12 | #include <stdio.h> | |
13 | #include <stdlib.h> | |
14 | #include <string.h> | |
9f6e9d15 | 15 | #include <sys/stat.h> |
cee5a30d | 16 | #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type |
17 | #include "data.h" | |
28fdb04f | 18 | //#include "proxusb.h" |
902cb3c0 | 19 | #include "proxmark3.h" |
cee5a30d | 20 | #include "ui.h" |
21 | #include "cmdparser.h" | |
22 | #include "cmdhficlass.h" | |
23 | #include "common.h" | |
14006804 | 24 | #include "util.h" |
17cba269 | 25 | #include "cmdmain.h" |
cee5a30d | 26 | |
27 | static int CmdHelp(const char *Cmd); | |
28 | ||
17cba269 MHS |
29 | int xorbits_8(uint8_t val) |
30 | { | |
31 | uint8_t res = val ^ (val >> 1); //1st pass | |
32 | res = res ^ (res >> 1); // 2nd pass | |
33 | res = res ^ (res >> 2); // 3rd pass | |
34 | res = res ^ (res >> 4); // 4th pass | |
35 | return res & 1; | |
36 | } | |
37 | ||
cee5a30d | 38 | int CmdHFiClassList(const char *Cmd) |
17cba269 MHS |
39 | { |
40 | ||
41 | bool ShowWaitCycles = false; | |
42 | char param = param_getchar(Cmd, 0); | |
43 | ||
44 | if (param != 0) { | |
45 | PrintAndLog("List data in trace buffer."); | |
46 | PrintAndLog("Usage: hf iclass list"); | |
47 | PrintAndLog("h - help"); | |
48 | PrintAndLog("sample: hf iclass list"); | |
49 | return 0; | |
50 | } | |
51 | ||
52 | uint8_t got[1920]; | |
53 | GetFromBigBuf(got,sizeof(got),0); | |
54 | WaitForResponse(CMD_ACK,NULL); | |
55 | ||
56 | PrintAndLog("Recorded Activity"); | |
57 | PrintAndLog(""); | |
58 | PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); | |
59 | PrintAndLog("All times are in carrier periods (1/13.56Mhz)"); | |
60 | PrintAndLog(""); | |
61 | PrintAndLog(" Start | End | Src | Data"); | |
62 | PrintAndLog("-----------|-----------|-----|--------"); | |
63 | ||
64 | int i; | |
65 | uint32_t first_timestamp = 0; | |
66 | uint32_t timestamp; | |
67 | bool tagToReader; | |
68 | uint32_t parityBits; | |
69 | uint8_t len; | |
70 | uint8_t *frame; | |
71 | uint32_t EndOfTransmissionTimestamp = 0; | |
72 | ||
17cba269 MHS |
73 | |
74 | for( i=0; i < 1900;) | |
75 | { | |
76 | //First 32 bits contain | |
77 | // isResponse (1 bit) | |
78 | // timestamp (remaining) | |
79 | //Then paritybits | |
80 | //Then length | |
81 | timestamp = *((uint32_t *)(got+i)); | |
82 | parityBits = *((uint32_t *)(got+i+4)); | |
83 | len = got[i+8]; | |
84 | frame = (got+i+9); | |
85 | uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff; | |
86 | ||
87 | tagToReader = timestamp & 0x80000000; | |
88 | timestamp &= 0x7fffffff; | |
89 | ||
90 | if(i==0) { | |
91 | first_timestamp = timestamp; | |
92 | } | |
93 | ||
f83cc126 MHS |
94 | // Break and stick with current result if buffer was not completely full |
95 | if (frame[0] == 0x44 && frame[1] == 0x44 && frame[2] == 0x44 && frame[3] == 0x44) break; | |
17cba269 MHS |
96 | |
97 | char line[1000] = ""; | |
98 | ||
99 | if(len)//We have some data to display | |
100 | { | |
101 | int j,oddparity; | |
102 | ||
103 | for(j = 0; j < len ; j++) | |
104 | { | |
105 | oddparity = 0x01 ^ xorbits_8(frame[j] & 0xFF); | |
106 | ||
107 | if (tagToReader && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { | |
108 | sprintf(line+(j*4), "%02x! ", frame[j]); | |
109 | } else { | |
110 | sprintf(line+(j*4), "%02x ", frame[j]); | |
111 | } | |
112 | } | |
113 | }else | |
114 | { | |
115 | if (ShowWaitCycles) { | |
116 | sprintf(line, "fdt (Frame Delay Time): %d", (next_timestamp - timestamp)); | |
117 | } | |
118 | } | |
119 | ||
120 | char *crc = ""; | |
121 | ||
122 | if(len > 2) | |
123 | { | |
124 | uint8_t b1, b2; | |
125 | if(!tagToReader && len == 4) { | |
126 | // Rough guess that this is a command from the reader | |
127 | // For iClass the command byte is not part of the CRC | |
128 | ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2); | |
129 | } | |
130 | else { | |
131 | // For other data.. CRC might not be applicable (UPDATE commands etc.) | |
132 | ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2); | |
133 | } | |
134 | ||
135 | if (b1 != frame[len-2] || b2 != frame[len-1]) { | |
136 | crc = (tagToReader & (len < 8)) ? "" : " !crc"; | |
137 | } | |
138 | } | |
139 | ||
140 | i += (len + 9); | |
141 | EndOfTransmissionTimestamp = (*((uint32_t *)(got+i))) & 0x7fffffff; | |
142 | ||
143 | // Not implemented for iclass on the ARM-side | |
144 | //if (!ShowWaitCycles) i += 9; | |
145 | ||
146 | PrintAndLog(" %9d | %9d | %s | %s %s", | |
147 | (timestamp - first_timestamp), | |
148 | (EndOfTransmissionTimestamp - first_timestamp), | |
149 | (len?(tagToReader ? "Tag" : "Rdr"):" "), | |
150 | line, crc); | |
151 | } | |
152 | return 0; | |
153 | } | |
154 | ||
155 | int CmdHFiClassListOld(const char *Cmd) | |
cee5a30d | 156 | { |
157 | uint8_t got[1920]; | |
db09cb3a | 158 | GetFromBigBuf(got,sizeof(got),0); |
cee5a30d | 159 | |
160 | PrintAndLog("recorded activity:"); | |
161 | PrintAndLog(" ETU :rssi: who bytes"); | |
162 | PrintAndLog("---------+----+----+-----------"); | |
163 | ||
164 | int i = 0; | |
165 | int prev = -1; | |
166 | ||
167 | for (;;) { | |
168 | if(i >= 1900) { | |
169 | break; | |
170 | } | |
171 | ||
172 | bool isResponse; | |
173 | int timestamp = *((uint32_t *)(got+i)); | |
174 | if (timestamp & 0x80000000) { | |
175 | timestamp &= 0x7fffffff; | |
176 | isResponse = 1; | |
177 | } else { | |
178 | isResponse = 0; | |
179 | } | |
180 | ||
17cba269 | 181 | |
cee5a30d | 182 | int metric = 0; |
17cba269 | 183 | |
cee5a30d | 184 | int parityBits = *((uint32_t *)(got+i+4)); |
185 | // 4 bytes of additional information... | |
186 | // maximum of 32 additional parity bit information | |
187 | // | |
188 | // TODO: | |
189 | // at each quarter bit period we can send power level (16 levels) | |
190 | // or each half bit period in 256 levels. | |
191 | ||
192 | ||
193 | int len = got[i+8]; | |
194 | ||
195 | if (len > 100) { | |
196 | break; | |
197 | } | |
198 | if (i + len >= 1900) { | |
199 | break; | |
200 | } | |
201 | ||
202 | uint8_t *frame = (got+i+9); | |
203 | ||
204 | // Break and stick with current result if buffer was not completely full | |
205 | if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; } | |
206 | ||
207 | char line[1000] = ""; | |
208 | int j; | |
209 | for (j = 0; j < len; j++) { | |
210 | int oddparity = 0x01; | |
211 | int k; | |
212 | ||
213 | for (k=0;k<8;k++) { | |
214 | oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); | |
215 | } | |
216 | ||
217 | //if((parityBits >> (len - j - 1)) & 0x01) { | |
218 | if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { | |
219 | sprintf(line+(j*4), "%02x! ", frame[j]); | |
220 | } | |
221 | else { | |
222 | sprintf(line+(j*4), "%02x ", frame[j]); | |
223 | } | |
224 | } | |
225 | ||
226 | char *crc; | |
227 | crc = ""; | |
228 | if (len > 2) { | |
229 | uint8_t b1, b2; | |
230 | for (j = 0; j < (len - 1); j++) { | |
231 | // gives problems... search for the reason.. | |
232 | /*if(frame[j] == 0xAA) { | |
233 | switch(frame[j+1]) { | |
234 | case 0x01: | |
235 | crc = "[1] Two drops close after each other"; | |
236 | break; | |
237 | case 0x02: | |
238 | crc = "[2] Potential SOC with a drop in second half of bitperiod"; | |
239 | break; | |
240 | case 0x03: | |
241 | crc = "[3] Segment Z after segment X is not possible"; | |
242 | break; | |
243 | case 0x04: | |
244 | crc = "[4] Parity bit of a fully received byte was wrong"; | |
245 | break; | |
246 | default: | |
247 | crc = "[?] Unknown error"; | |
248 | break; | |
249 | } | |
250 | break; | |
251 | }*/ | |
252 | } | |
253 | ||
254 | if (strlen(crc)==0) { | |
255 | if(!isResponse && len == 4) { | |
256 | // Rough guess that this is a command from the reader | |
257 | // For iClass the command byte is not part of the CRC | |
258 | ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2); | |
259 | } | |
260 | else { | |
261 | // For other data.. CRC might not be applicable (UPDATE commands etc.) | |
262 | ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2); | |
263 | } | |
264 | //printf("%1x %1x",(unsigned)b1,(unsigned)b2); | |
265 | if (b1 != frame[len-2] || b2 != frame[len-1]) { | |
266 | crc = (isResponse & (len < 8)) ? "" : " !crc"; | |
267 | } else { | |
268 | crc = ""; | |
269 | } | |
270 | } | |
271 | } else { | |
272 | crc = ""; // SHORT | |
273 | } | |
274 | ||
275 | char metricString[100]; | |
276 | if (isResponse) { | |
277 | sprintf(metricString, "%3d", metric); | |
278 | } else { | |
279 | strcpy(metricString, " "); | |
280 | } | |
281 | ||
282 | PrintAndLog(" +%7d: %s: %s %s %s", | |
283 | (prev < 0 ? 0 : (timestamp - prev)), | |
284 | metricString, | |
285 | (isResponse ? "TAG" : " "), line, crc); | |
286 | ||
287 | prev = timestamp; | |
288 | i += (len + 9); | |
289 | } | |
290 | return 0; | |
291 | } | |
292 | ||
293 | /*void iso14a_set_timeout(uint32_t timeout) { | |
294 | UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_SET_TIMEOUT, 0, timeout}}; | |
295 | SendCommand(&c); | |
296 | }*/ | |
297 | ||
298 | int CmdHFiClassSnoop(const char *Cmd) | |
299 | { | |
300 | UsbCommand c = {CMD_SNOOP_ICLASS}; | |
301 | SendCommand(&c); | |
302 | return 0; | |
303 | } | |
304 | ||
1e262141 | 305 | int CmdHFiClassSim(const char *Cmd) |
306 | { | |
307 | uint8_t simType = 0; | |
308 | uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | |
309 | ||
17cba269 MHS |
310 | if (strlen(Cmd)<1) { |
311 | PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x"); | |
312 | PrintAndLog(" options"); | |
313 | PrintAndLog(" 0 <CSN> simulate the given CSN"); | |
314 | PrintAndLog(" 1 simulate default CSN"); | |
315 | PrintAndLog(" 2 iterate CSNs, gather MACs"); | |
1e262141 | 316 | PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0"); |
17cba269 | 317 | PrintAndLog(" sample: hf iclass sim 2"); |
1e262141 | 318 | return 0; |
319 | } | |
320 | ||
321 | simType = param_get8(Cmd, 0); | |
17cba269 MHS |
322 | |
323 | if(simType == 0) | |
324 | { | |
325 | if (param_gethex(Cmd, 1, CSN, 16)) { | |
326 | PrintAndLog("A CSN should consist of 16 HEX symbols"); | |
327 | return 1; | |
328 | } | |
329 | PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8)); | |
330 | ||
331 | } | |
9f6e9d15 | 332 | if(simType > 5) |
17cba269 MHS |
333 | { |
334 | PrintAndLog("Undefined simptype %d", simType); | |
335 | return 1; | |
1e262141 | 336 | } |
17cba269 | 337 | uint8_t numberOfCSNs=0; |
1e262141 | 338 | |
9f6e9d15 MHS |
339 | if(simType == 2) |
340 | { | |
341 | UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,63}}; | |
342 | UsbCommand resp = {0}; | |
17cba269 | 343 | |
9f6e9d15 | 344 | uint8_t csns1[] ={ |
17cba269 MHS |
345 | /* Order Simulated CSN HASH1 Recovered key bytes */ |
346 | /* 1 */ 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0,// 0101000045014545 00,01 45 | |
347 | /* 2 */ 0x03,0x0B,0x0E,0xFE,0xF7,0xFF,0x12,0xE0,// 0202000045014545 02 | |
348 | /* 3 */ 0x04,0x0D,0x0D,0xFD,0xF7,0xFF,0x12,0xE0,// 0303000045014545 03 | |
349 | /* 4 */ 0x04,0x0F,0x0F,0xF7,0xF7,0xFF,0x12,0xE0,// 0901000045014545 09 | |
350 | /* 5 */ 0x01,0x13,0x10,0xF4,0xF7,0xFF,0x12,0xE0,// 0C00000045014545 0C | |
351 | /* 6 */ 0x02,0x14,0x10,0xF2,0xF7,0xFF,0x12,0xE0,// 0E00000045014545 0E | |
352 | /* 7 */ 0x05,0x17,0x10,0xEC,0xF7,0xFF,0x12,0xE0,// 1400000045014545 14 | |
353 | /* 8 */ 0x00,0x6B,0x6F,0xDF,0xF7,0xFF,0x12,0xE0,// 2121000045014545 21 | |
354 | /* 9 */ 0x03,0x6B,0x6E,0xDE,0xF7,0xFF,0x12,0xE0,// 2222000045014545 22 | |
355 | /* 10 */ 0x04,0x6D,0x6D,0xDD,0xF7,0xFF,0x12,0xE0,// 2323000045014545 23 | |
356 | /* 11 */ 0x00,0x4F,0x4B,0x43,0xF7,0xFF,0x12,0xE0,// 3D45000045014545 3D | |
357 | /* 12 */ 0x00,0x4B,0x4F,0x3F,0xF7,0xFF,0x12,0xE0,// 4141000045014545 41 | |
358 | /* 13 */ 0x03,0x4B,0x4E,0x3E,0xF7,0xFF,0x12,0xE0,// 4242000045014545 42 | |
359 | /* 14 */ 0x04,0x4D,0x4D,0x3D,0xF7,0xFF,0x12,0xE0,// 4343000045014545 43 | |
360 | /* 15 */ 0x04,0x37,0x37,0x7F,0xF7,0xFF,0x12,0xE0,// 0159000045014545 59 | |
361 | /* 16 */ 0x00,0x2B,0x2F,0x9F,0xF7,0xFF,0x12,0xE0,// 6161000045014545 61 | |
362 | /* 17 */ 0x03,0x2B,0x2E,0x9E,0xF7,0xFF,0x12,0xE0,// 6262000045014545 62 | |
363 | /* 18 */ 0x04,0x2D,0x2D,0x9D,0xF7,0xFF,0x12,0xE0,// 6363000045014545 63 | |
364 | /* 19 */ 0x00,0x27,0x23,0xBB,0xF7,0xFF,0x12,0xE0,// 456D000045014545 6D | |
365 | /* 20 */ 0x02,0x52,0xAA,0x80,0xF7,0xFF,0x12,0xE0,// 0066000045014545 66 | |
366 | /* 21 */ 0x00,0x5C,0xA6,0x80,0xF7,0xFF,0x12,0xE0,// 006A000045014545 6A | |
367 | /* 22 */ 0x01,0x5F,0xA4,0x80,0xF7,0xFF,0x12,0xE0,// 006C000045014545 6C | |
368 | /* 23 */ 0x06,0x5E,0xA2,0x80,0xF7,0xFF,0x12,0xE0,// 006E000045014545 6E | |
369 | /* 24 */ 0x02,0x0E,0x0E,0xFC,0xF7,0xFF,0x12,0xE0,// 0402000045014545 04 | |
370 | /* 25 */ 0x05,0x0D,0x0E,0xFA,0xF7,0xFF,0x12,0xE0,// 0602000045014545 06 | |
371 | /* 26 */ 0x06,0x0F,0x0D,0xF9,0xF7,0xFF,0x12,0xE0,// 0703000045014545 07 | |
372 | /* 27 */ 0x00,0x01,0x05,0x1D,0xF7,0xFF,0x12,0xE0,// 630B000045014545 0B | |
373 | /* 28 */ 0x02,0x07,0x01,0x1D,0xF7,0xFF,0x12,0xE0,// 630F000045014545 0F | |
374 | /* 29 */ 0x04,0x7F,0x7F,0xA7,0xF7,0xFF,0x12,0xE0,// 5911000045014545 11 | |
375 | /* 30 */ 0x04,0x60,0x6E,0xE8,0xF7,0xFF,0x12,0xE0,// 1822000045014545 18 | |
9f6e9d15 MHS |
376 | /*31*/ 0x04,0x77,0x77,0xBF,0xF7,0xFF,0x12,0xE0, // 4119000045014545 19 |
377 | /*32*/ 0x00,0x69,0x6D,0xE5,0xF7,0xFF,0x12,0xE0, // 1B23000045014545 1B | |
378 | /*33*/ 0x01,0x69,0x6E,0xE2,0xF7,0xFF,0x12,0xE0, // 1E22000045014545 1E | |
379 | /*34*/ 0x02,0x6B,0x6D,0xE1,0xF7,0xFF,0x12,0xE0, // 1F23000045014545 1F | |
380 | /*35*/ 0x01,0x3F,0x04,0xE0,0xF7,0xFF,0x12,0xE0, // 200C000045014545 20 | |
381 | /*36*/ 0x02,0x6E,0x6E,0xDC,0xF7,0xFF,0x12,0xE0, // 2422000045014545 24 | |
382 | /*37*/ 0x05,0x6D,0x6E,0xDA,0xF7,0xFF,0x12,0xE0, // 2622000045014545 26 | |
383 | /*38*/ 0x06,0x6F,0x6D,0xD9,0xF7,0xFF,0x12,0xE0, // 2723000045014545 27 | |
384 | /*39*/ 0x01,0x6B,0x68,0xEC,0xF7,0xFF,0x12,0xE0, // 1428000045014545 28 | |
385 | /*40*/ 0x04,0x6F,0x6F,0xD7,0xF7,0xFF,0x12,0xE0, // 2921000045014545 29 | |
386 | /*41*/ 0x02,0x66,0x66,0xF4,0xF7,0xFF,0x12,0xE0, // 0C2A000045014545 2A | |
387 | /*42*/ 0x00,0x61,0x65,0xFD,0xF7,0xFF,0x12,0xE0, // 032B000045014545 2B | |
388 | /*43*/ 0x00,0x62,0x64,0xFE,0xF7,0xFF,0x12,0xE0, // 022C000045014545 2C | |
389 | /*44*/ 0x01,0x65,0x62,0xFE,0xF7,0xFF,0x12,0xE0, // 022E000045014545 2E | |
390 | /*45*/ 0x02,0x67,0x61,0xFD,0xF7,0xFF,0x12,0xE0, // 032F000045014545 2F | |
391 | /*46*/ 0x00,0x5F,0x5B,0x13,0xF7,0xFF,0x12,0xE0, // 6D35000045014545 35 | |
392 | /*47*/ 0x00,0x44,0x4E,0x48,0xF7,0xFF,0x12,0xE0, // 3842000045014545 38 | |
393 | /*48*/ 0x00,0x53,0x57,0x27,0xF7,0xFF,0x12,0xE0, // 5939000045014545 39 | |
394 | /*49*/ 0x00,0x49,0x4D,0x45,0xF7,0xFF,0x12,0xE0, // 3B43000045014545 3B | |
395 | /*50*/ 0x01,0x49,0x4E,0x42,0xF7,0xFF,0x12,0xE0, // 3E42000045014545 3E | |
396 | /*51*/ 0x02,0x4B,0x4D,0x41,0xF7,0xFF,0x12,0xE0, // 3F43000045014545 3F | |
397 | /*52*/ 0x02,0x4E,0x4E,0x3C,0xF7,0xFF,0x12,0xE0, // 4442000045014545 44 | |
398 | /*53*/ 0x05,0x4D,0x4E,0x3A,0xF7,0xFF,0x12,0xE0, // 4642000045014545 46 | |
399 | /*54*/ 0x06,0x4F,0x4D,0x39,0xF7,0xFF,0x12,0xE0, // 4743000045014545 47 | |
400 | /*55*/ 0x01,0x77,0x7C,0xB8,0xF7,0xFF,0x12,0xE0, // 4814000045014545 48 | |
401 | /*56*/ 0x04,0x4F,0x4F,0x37,0xF7,0xFF,0x12,0xE0, // 4941000045014545 49 | |
402 | /*57*/ 0x00,0x7A,0x7C,0xB6,0xF7,0xFF,0x12,0xE0, // 4A14000045014545 4A | |
403 | /*58*/ 0x00,0x41,0x45,0x5D,0xF7,0xFF,0x12,0xE0, // 234B000045014545 4B | |
404 | /*59*/ 0x00,0x42,0x44,0x5E,0xF7,0xFF,0x12,0xE0, // 224C000045014545 4C | |
405 | /*60*/ 0x01,0x45,0x42,0x5E,0xF7,0xFF,0x12,0xE0, // 224E000045014545 4E | |
406 | /*61*/ 0x02,0x47,0x41,0x5D,0xF7,0xFF,0x12,0xE0, // 234F000045014545 4F | |
407 | /*62*/ 0x04,0x7E,0x7C,0xAE,0xF7,0xFF,0x12,0xE0, // 5214000045014545 52 | |
408 | /*63*/ 0x00,0x57,0x53,0x2B,0xF7,0xFF,0x12,0xE0, // 553D000045014545 55 | |
409 | }; | |
410 | memcpy(c.d.asBytes, csns1, sizeof(c.d.asBytes)); | |
411 | ||
412 | SendCommand(&c); | |
413 | if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) { | |
414 | PrintAndLog("Command timed out"); | |
415 | return 0; | |
416 | } | |
1e262141 | 417 | |
9f6e9d15 MHS |
418 | uint8_t num_mac_responses_1 = resp.arg[1]; |
419 | PrintAndLog("Mac responses, first part : %d MACs obtained (should be 63)", num_mac_responses_1); | |
420 | ||
421 | UsbCommand c2 = {CMD_SIMULATE_TAG_ICLASS, {simType,63}}; | |
422 | UsbCommand resp2 = {0}; | |
423 | ||
424 | uint8_t csns2[] ={ | |
425 | /*64*/ 0x04,0x3C,0x3A,0x74,0xF7,0xFF,0x12,0xE0, // 0C56000045014545 56 | |
426 | /*65*/ 0x00,0x24,0x2E,0xA8,0xF7,0xFF,0x12,0xE0, // 5862000045014545 58 | |
427 | /*66*/ 0x00,0x29,0x2D,0xA5,0xF7,0xFF,0x12,0xE0, // 5B63000045014545 5B | |
428 | /*67*/ 0x00,0x00,0x02,0x24,0xF7,0xFF,0x12,0xE0, // 5C0E000045014545 5C | |
429 | /*68*/ 0x01,0x29,0x2E,0xA2,0xF7,0xFF,0x12,0xE0, // 5E62000045014545 5E | |
430 | /*69*/ 0x02,0x2B,0x2D,0xA1,0xF7,0xFF,0x12,0xE0, // 5F63000045014545 5F | |
431 | /*70*/ 0x02,0x2E,0x2E,0x9C,0xF7,0xFF,0x12,0xE0, // 6462000045014545 64 | |
432 | /*71*/ 0x02,0x0A,0x02,0x18,0xF7,0xFF,0x12,0xE0, // 680E000045014545 68 | |
433 | /*72*/ 0x00,0x03,0x07,0x17,0xF7,0xFF,0x12,0xE0, // 6909000045014545 69 | |
434 | /*73*/ 0x00,0x21,0x25,0xBD,0xF7,0xFF,0x12,0xE0, // 436B000045014545 6B | |
435 | /*74*/ 0x02,0x27,0x21,0xBD,0xF7,0xFF,0x12,0xE0, // 436F000045014545 6F | |
436 | /*75*/ 0x04,0x07,0x07,0x0F,0xF7,0xFF,0x12,0xE0, // 7109000045014545 71 | |
437 | /*76*/ 0x00,0x04,0x0E,0x08,0xF7,0xFF,0x12,0xE0, // 7802000045014545 78 | |
438 | /*77*/ 0x00,0x33,0x37,0x87,0xF7,0xFF,0x12,0xE0, // 7959000045014545 79 | |
439 | /*78*/ 0x00,0x09,0x0D,0x05,0xF7,0xFF,0x12,0xE0, // 7B03000045014545 7B | |
440 | /*79*/ 0x01,0x09,0x0E,0x02,0xF7,0xFF,0x12,0xE0, // 7E02000045014545 7E | |
441 | /*80*/ 0x02,0x0B,0x0D,0x01,0xF7,0xFF,0x12,0xE0, // 7F03000045014545 7F | |
442 | /*81*/ 0x00,0x34,0x3E,0x78,0xF7,0xFF,0x12,0xE0, // 0852000045014545 08 | |
443 | /*82*/ 0x04,0x66,0x64,0xF6,0xF7,0xFF,0x12,0xE0, // 0A2C000045014545 0A | |
444 | /*83*/ 0x00,0x3F,0x3B,0x73,0xF7,0xFF,0x12,0xE0, // 0D55000045014545 0D | |
445 | /*84*/ 0x03,0x3B,0x3E,0x6E,0xF7,0xFF,0x12,0xE0, // 1252000045014545 12 | |
446 | /*85*/ 0x00,0x11,0x15,0xED,0xF7,0xFF,0x12,0xE0, // 137B000045014545 13 | |
447 | /*86*/ 0x00,0x6E,0x68,0xEA,0xF7,0xFF,0x12,0xE0, // 1628000045014545 16 | |
448 | /*87*/ 0x00,0x6D,0x69,0xE9,0xF7,0xFF,0x12,0xE0, // 1727000045014545 17 | |
449 | /*88*/ 0x00,0x6A,0x6C,0xE6,0xF7,0xFF,0x12,0xE0, // 1A24000045014545 1A | |
450 | /*89*/ 0x00,0x40,0x42,0x64,0xF7,0xFF,0x12,0xE0, // 1C4E000045014545 1C | |
451 | /*90*/ 0x00,0x77,0x73,0xCB,0xF7,0xFF,0x12,0xE0, // 351D000045014545 1D | |
452 | /*91*/ 0x06,0x6E,0x72,0xD0,0xF7,0xFF,0x12,0xE0, // 301E000045014545 30 | |
453 | /*92*/ 0x00,0x1B,0x1F,0xCF,0xF7,0xFF,0x12,0xE0, // 3171000045014545 31 | |
454 | /*93*/ 0x01,0x75,0x72,0xCE,0xF7,0xFF,0x12,0xE0, // 321E000045014545 32 | |
455 | /*94*/ 0x00,0x71,0x75,0xCD,0xF7,0xFF,0x12,0xE0, // 331B000045014545 33 | |
456 | /*95*/ 0x00,0x48,0x4A,0x4C,0xF7,0xFF,0x12,0xE0, // 3446000045014545 34 | |
457 | /*96*/ 0x00,0x4E,0x48,0x4A,0xF7,0xFF,0x12,0xE0, // 3648000045014545 36 | |
458 | /*97*/ 0x00,0x4D,0x49,0x49,0xF7,0xFF,0x12,0xE0, // 3747000045014545 37 | |
459 | /*98*/ 0x00,0x4A,0x4C,0x46,0xF7,0xFF,0x12,0xE0, // 3A44000045014545 3A | |
460 | /*99*/ 0x00,0x20,0x22,0xC4,0xF7,0xFF,0x12,0xE0, // 3C6E000045014545 3C | |
461 | /*100*/ 0x00,0x1C,0x66,0x40,0xF7,0xFF,0x12,0xE0, // 402A000045014545 40 | |
462 | /*101*/ 0x06,0x4E,0x52,0x30,0xF7,0xFF,0x12,0xE0, // 503E000045014545 50 | |
463 | /*102*/ 0x00,0x7B,0x7F,0xAF,0xF7,0xFF,0x12,0xE0, // 5111000045014545 51 | |
464 | /*103*/ 0x00,0x51,0x55,0x2D,0xF7,0xFF,0x12,0xE0, // 533B000045014545 53 | |
465 | /*104*/ 0x00,0x28,0x2A,0xAC,0xF7,0xFF,0x12,0xE0, // 5466000045014545 54 | |
466 | /*105*/ 0x02,0x53,0x55,0x29,0xF7,0xFF,0x12,0xE0, // 573B000045014545 57 | |
467 | /*106*/ 0x00,0x2A,0x2C,0xA6,0xF7,0xFF,0x12,0xE0, // 5A64000045014545 5A | |
468 | /*107*/ 0x00,0x7C,0x46,0x20,0xF7,0xFF,0x12,0xE0, // 604A000045014545 60 | |
469 | /*108*/ 0x02,0x03,0x05,0x19,0xF7,0xFF,0x12,0xE0, // 670B000045014545 67 | |
470 | /*109*/ 0x01,0x2F,0x34,0x90,0xF7,0xFF,0x12,0xE0, // 705C000045014545 70 | |
471 | /*110*/ 0x00,0x32,0x34,0x8E,0xF7,0xFF,0x12,0xE0, // 725C000045014545 72 | |
472 | /*111*/ 0x00,0x31,0x35,0x8D,0xF7,0xFF,0x12,0xE0, // 735B000045014545 73 | |
473 | /*112*/ 0x00,0x08,0x0A,0x0C,0xF7,0xFF,0x12,0xE0, // 7406000045014545 74 | |
474 | /*113*/ 0x03,0x37,0x32,0x8A,0xF7,0xFF,0x12,0xE0, // 765E000045014545 76 | |
475 | /*114*/ 0x00,0x0D,0x09,0x09,0xF7,0xFF,0x12,0xE0, // 7707000045014545 77 | |
476 | /*115*/ 0x00,0x0A,0x0C,0x06,0xF7,0xFF,0x12,0xE0, // 7A04000045014545 7A | |
477 | /*116*/ 0x00,0x60,0x62,0x04,0xF7,0xFF,0x12,0xE0, // 7C2E000045014545 7C | |
478 | /*117*/ 0x00,0x07,0x03,0x1B,0xF7,0xFF,0x12,0xE0, // 650D000045014545 65 | |
479 | /*118*/ 0x00,0x0C,0x16,0xF0,0xF7,0xFF,0x12,0xE0, // 107A000045014545 10 | |
480 | /*119*/ 0x00,0x6F,0x6B,0xE3,0xF7,0xFF,0x12,0xE0, // 1D25000045014545 25 | |
481 | /*120*/ 0x00,0x2F,0x2B,0xA3,0xF7,0xFF,0x12,0xE0, // 5D65000045014545 5D | |
482 | /*121*/ 0x00,0x47,0x43,0x5B,0xF7,0xFF,0x12,0xE0, // 254D000045014545 4D | |
483 | /*122*/ 0x00,0x37,0x33,0x8B,0xF7,0xFF,0x12,0xE0, // 755D000045014545 75 | |
484 | /*123*/ 0x00,0x1F,0x1B,0xD3,0xF7,0xFF,0x12,0xE0, // 2D75000045014545 2D | |
485 | /*124*/ 0x00,0x67,0x63,0xFB,0xF7,0xFF,0x12,0xE0, // 052D000045014545 05 | |
486 | /*125*/ 0x00,0x0F,0x0B,0x03,0xF7,0xFF,0x12,0xE0, // 7D05000045014545 7D | |
487 | /*126*/ 0x00,0x17,0x13,0xEB,0xF7,0xFF,0x12,0xE0, // 157D000045014545 15 | |
488 | }; | |
489 | ||
490 | memcpy(c2.d.asBytes, csns2, sizeof(c2.d.asBytes)); | |
491 | ||
492 | SendCommand(&c); | |
493 | if (!WaitForResponseTimeout(CMD_ACK, &resp2, -1)) { | |
494 | PrintAndLog("Command timed out"); | |
495 | return 0; | |
496 | } | |
497 | uint8_t num_mac_responses_2 = resp2.arg[1]; | |
498 | PrintAndLog("Mac responses, second part : %d MACs obtained (should be 63)", num_mac_responses_2); | |
499 | size_t datalen = 126 * 16; | |
500 | /* | |
501 | * Now, time to dump to file. We'll use this format: | |
502 | * <8-byte CSN><8-byte MAC>.... | |
503 | * So, it should wind up as | |
504 | * (63+63) * (8 + 8 ) bytes. | |
505 | **/ | |
506 | void* macs = malloc(datalen); | |
507 | uint8_t i = 0; | |
508 | while(i < 63) | |
509 | { | |
510 | memcpy(macs+i*16, csns1+i*8,8); | |
511 | memcpy(macs+i*16+8, resp.d.asBytes+i*8,8); | |
1e262141 | 512 | |
9f6e9d15 MHS |
513 | memcpy(macs+i*16+63*16, csns2+i*8,8); |
514 | memcpy(macs+i*16+8+63*16, resp2.d.asBytes+i*8,8); | |
515 | i++; | |
516 | } | |
517 | /** Now, save to dumpfile **/ | |
518 | saveFile("iclass_mac_attack", "bin", macs,datalen); | |
519 | free(macs); | |
520 | }else | |
521 | { | |
522 | UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}}; | |
523 | memcpy(c.d.asBytes, CSN, 8); | |
524 | SendCommand(&c); | |
525 | } | |
1e262141 | 526 | return 0; |
527 | } | |
528 | ||
529 | int CmdHFiClassReader(const char *Cmd) | |
530 | { | |
531 | uint8_t readerType = 0; | |
532 | ||
533 | if (strlen(Cmd)<1) { | |
534 | PrintAndLog("Usage: hf iclass reader <reader type>"); | |
535 | PrintAndLog(" sample: hf iclass reader 0"); | |
536 | return 0; | |
537 | } | |
538 | ||
539 | readerType = param_get8(Cmd, 0); | |
540 | PrintAndLog("--readertype:%02x", readerType); | |
541 | ||
542 | UsbCommand c = {CMD_READER_ICLASS, {readerType}}; | |
543 | //memcpy(c.d.asBytes, CSN, 8); | |
544 | SendCommand(&c); | |
545 | ||
546 | /*UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500); | |
547 | if (resp != NULL) { | |
548 | uint8_t isOK = resp->arg[0] & 0xff; | |
549 | PrintAndLog("isOk:%02x", isOK); | |
550 | } else { | |
551 | PrintAndLog("Command execute timeout"); | |
552 | }*/ | |
553 | ||
554 | return 0; | |
555 | } | |
556 | ||
cee5a30d | 557 | static command_t CommandTable[] = |
558 | { | |
559 | {"help", CmdHelp, 1, "This help"}, | |
560 | {"list", CmdHFiClassList, 0, "List iClass history"}, | |
561 | {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"}, | |
1e262141 | 562 | {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"}, |
563 | {"reader", CmdHFiClassReader, 0, "Read an iClass tag"}, | |
cee5a30d | 564 | {NULL, NULL, 0, NULL} |
565 | }; | |
566 | ||
567 | int CmdHFiClass(const char *Cmd) | |
568 | { | |
569 | CmdsParse(CommandTable, Cmd); | |
570 | return 0; | |
571 | } | |
572 | ||
573 | int CmdHelp(const char *Cmd) | |
574 | { | |
575 | CmdsHelp(CommandTable); | |
576 | return 0; | |
577 | } | |
9f6e9d15 MHS |
578 | |
579 | /** | |
580 | * @brief checks if a file exists | |
581 | * @param filename | |
582 | * @return | |
583 | */ | |
584 | int fileExists(const char *filename) { | |
585 | struct stat st; | |
586 | int result = stat(filename, &st); | |
587 | return result == 0; | |
588 | } | |
589 | /** | |
590 | * @brief Utility function to save data to a file. This method takes a preferred name, but if that | |
591 | * file already exists, it tries with another name until it finds something suitable. | |
592 | * E.g. dumpdata-15.txt | |
593 | * @param preferredName | |
594 | * @param suffix the file suffix. Leave out the ".". | |
595 | * @param data The binary data to write to the file | |
596 | * @param datalen the length of the data | |
597 | * @return | |
598 | */ | |
599 | int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen) | |
600 | { | |
601 | FILE *f = fopen(preferredName, "wb"); | |
602 | int size = sizeof(char) * (strlen(preferredName)+strlen(suffix)+5); | |
603 | char * fileName = malloc(size); | |
604 | ||
605 | memset(fileName,0,size); | |
606 | int num = 1; | |
607 | sprintf(fileName,"%s.%s", preferredName, suffix); | |
608 | while(fileExists(fileName)) | |
609 | { | |
610 | sprintf(fileName,"%s-%d.%s", preferredName, num, suffix); | |
611 | num++; | |
612 | } | |
613 | /* We should have a valid filename now, e.g. dumpdata-3.bin */ | |
614 | ||
615 | /*Opening file for writing in binary mode*/ | |
616 | FILE *fileHandle=fopen(fileName,"wb"); | |
617 | if(!f) { | |
618 | PrintAndLog("Failed to write to file '%s'", fileName); | |
619 | return 0; | |
620 | } | |
621 | fwrite(data, 1, datalen, fileHandle); | |
622 | fclose(fileHandle); | |
623 | PrintAndLog("Saved data to '%s'", fileName); | |
624 | ||
625 | free(fileName); | |
626 | return 0; | |
627 | } |