]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdlf.c
26bd5e4fd6b0d1a00c71da5d4cdc234db9bfe9d0
[proxmark3-svn] / client / cmdlf.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "proxusb.h"
4 #include "data.h"
5 #include "graph.h"
6 #include "ui.h"
7 #include "cmdparser.h"
8 #include "cmddata.h"
9 #include "cmdlf.h"
10 #include "cmdlfhid.h"
11 #include "cmdlfti.h"
12 #include "cmdlfem4x.h"
13
14 static int CmdHelp(const char *Cmd);
15
16 /* send a command before reading */
17 int CmdLFCommandRead(const char *Cmd)
18 {
19 static char dummy[3];
20
21 dummy[0]= ' ';
22
23 UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
24 sscanf(Cmd, "%i %i %i %s %s", &c.arg[0], &c.arg[1], &c.arg[2], (char *) &c.d.asBytes,(char *) &dummy+1);
25 // in case they specified 'h'
26 strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
27 SendCommand(&c);
28 return 0;
29 }
30
31 int CmdFlexdemod(const char *Cmd)
32 {
33 int i;
34 for (i = 0; i < GraphTraceLen; ++i) {
35 if (GraphBuffer[i] < 0) {
36 GraphBuffer[i] = -1;
37 } else {
38 GraphBuffer[i] = 1;
39 }
40 }
41
42 #define LONG_WAIT 100
43 int start;
44 for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
45 int first = GraphBuffer[start];
46 for (i = start; i < start + LONG_WAIT; i++) {
47 if (GraphBuffer[i] != first) {
48 break;
49 }
50 }
51 if (i == (start + LONG_WAIT)) {
52 break;
53 }
54 }
55 if (start == GraphTraceLen - LONG_WAIT) {
56 PrintAndLog("nothing to wait for");
57 return 0;
58 }
59
60 GraphBuffer[start] = 2;
61 GraphBuffer[start+1] = -2;
62
63 uint8_t bits[64];
64
65 int bit;
66 i = start;
67 for (bit = 0; bit < 64; bit++) {
68 int j;
69 int sum = 0;
70 for (j = 0; j < 16; j++) {
71 sum += GraphBuffer[i++];
72 }
73 if (sum > 0) {
74 bits[bit] = 1;
75 } else {
76 bits[bit] = 0;
77 }
78 PrintAndLog("bit %d sum %d", bit, sum);
79 }
80
81 for (bit = 0; bit < 64; bit++) {
82 int j;
83 int sum = 0;
84 for (j = 0; j < 16; j++) {
85 sum += GraphBuffer[i++];
86 }
87 if (sum > 0 && bits[bit] != 1) {
88 PrintAndLog("oops1 at %d", bit);
89 }
90 if (sum < 0 && bits[bit] != 0) {
91 PrintAndLog("oops2 at %d", bit);
92 }
93 }
94
95 GraphTraceLen = 32*64;
96 i = 0;
97 int phase = 0;
98 for (bit = 0; bit < 64; bit++) {
99 if (bits[bit] == 0) {
100 phase = 0;
101 } else {
102 phase = 1;
103 }
104 int j;
105 for (j = 0; j < 32; j++) {
106 GraphBuffer[i++] = phase;
107 phase = !phase;
108 }
109 }
110
111 RepaintGraphWindow();
112 return 0;
113 }
114
115 int CmdIndalaDemod(const char *Cmd)
116 {
117 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
118
119 int state = -1;
120 int count = 0;
121 int i, j;
122 // worst case with GraphTraceLen=64000 is < 4096
123 // under normal conditions it's < 2048
124 uint8_t rawbits[4096];
125 int rawbit = 0;
126 int worst = 0, worstPos = 0;
127 PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
128 for (i = 0; i < GraphTraceLen-1; i += 2) {
129 count += 1;
130 if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
131 if (state == 0) {
132 for (j = 0; j < count - 8; j += 16) {
133 rawbits[rawbit++] = 0;
134 }
135 if ((abs(count - j)) > worst) {
136 worst = abs(count - j);
137 worstPos = i;
138 }
139 }
140 state = 1;
141 count = 0;
142 } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
143 if (state == 1) {
144 for (j = 0; j < count - 8; j += 16) {
145 rawbits[rawbit++] = 1;
146 }
147 if ((abs(count - j)) > worst) {
148 worst = abs(count - j);
149 worstPos = i;
150 }
151 }
152 state = 0;
153 count = 0;
154 }
155 }
156 PrintAndLog("Recovered %d raw bits", rawbit);
157 PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
158
159 // Finding the start of a UID
160 int uidlen, long_wait;
161 if (strcmp(Cmd, "224") == 0) {
162 uidlen = 224;
163 long_wait = 30;
164 } else {
165 uidlen = 64;
166 long_wait = 29;
167 }
168 int start;
169 int first = 0;
170 for (start = 0; start <= rawbit - uidlen; start++) {
171 first = rawbits[start];
172 for (i = start; i < start + long_wait; i++) {
173 if (rawbits[i] != first) {
174 break;
175 }
176 }
177 if (i == (start + long_wait)) {
178 break;
179 }
180 }
181 if (start == rawbit - uidlen + 1) {
182 PrintAndLog("nothing to wait for");
183 return 0;
184 }
185
186 // Inverting signal if needed
187 if (first == 1) {
188 for (i = start; i < rawbit; i++) {
189 rawbits[i] = !rawbits[i];
190 }
191 }
192
193 // Dumping UID
194 uint8_t bits[224];
195 char showbits[225];
196 showbits[uidlen]='\0';
197 int bit;
198 i = start;
199 int times = 0;
200 if (uidlen > rawbit) {
201 PrintAndLog("Warning: not enough raw bits to get a full UID");
202 for (bit = 0; bit < rawbit; bit++) {
203 bits[bit] = rawbits[i++];
204 // As we cannot know the parity, let's use "." and "/"
205 showbits[bit] = '.' + bits[bit];
206 }
207 showbits[bit+1]='\0';
208 PrintAndLog("Partial UID=%s", showbits);
209 return 0;
210 } else {
211 for (bit = 0; bit < uidlen; bit++) {
212 bits[bit] = rawbits[i++];
213 showbits[bit] = '0' + bits[bit];
214 }
215 times = 1;
216 }
217 PrintAndLog("UID=%s", showbits);
218
219 // Checking UID against next occurences
220 for (; i + uidlen <= rawbit;) {
221 int failed = 0;
222 for (bit = 0; bit < uidlen; bit++) {
223 if (bits[bit] != rawbits[i++]) {
224 failed = 1;
225 break;
226 }
227 }
228 if (failed == 1) {
229 break;
230 }
231 times += 1;
232 }
233 PrintAndLog("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen);
234
235 // Remodulating for tag cloning
236 GraphTraceLen = 32*uidlen;
237 i = 0;
238 int phase = 0;
239 for (bit = 0; bit < uidlen; bit++) {
240 if (bits[bit] == 0) {
241 phase = 0;
242 } else {
243 phase = 1;
244 }
245 int j;
246 for (j = 0; j < 32; j++) {
247 GraphBuffer[i++] = phase;
248 phase = !phase;
249 }
250 }
251
252 RepaintGraphWindow();
253 return 0;
254 }
255
256 int CmdLFRead(const char *Cmd)
257 {
258 UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
259 // 'h' means higher-low-frequency, 134 kHz
260 if(*Cmd == 'h') {
261 c.arg[0] = 1;
262 } else if (*Cmd == '\0') {
263 c.arg[0] = 0;
264 } else {
265 PrintAndLog("use 'read' or 'read h'");
266 return 0;
267 }
268 SendCommand(&c);
269 WaitForResponse(CMD_ACK);
270 return 0;
271 }
272
273 static void ChkBitstream(const char *str)
274 {
275 int i;
276
277 /* convert to bitstream if necessary */
278 for (i = 0; i < (int)(GraphTraceLen / 2); i++)
279 {
280 if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0)
281 {
282 CmdBitstream(str);
283 break;
284 }
285 }
286 }
287
288 int CmdLFSim(const char *Cmd)
289 {
290 int i;
291 static int gap;
292
293 sscanf(Cmd, "%i", &gap);
294
295 /* convert to bitstream if necessary */
296 ChkBitstream(Cmd);
297
298 PrintAndLog("Sending data, please wait...");
299 for (i = 0; i < GraphTraceLen; i += 48) {
300 UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
301 int j;
302 for (j = 0; j < 48; j++) {
303 c.d.asBytes[j] = GraphBuffer[i+j];
304 }
305 SendCommand(&c);
306 WaitForResponse(CMD_ACK);
307 }
308
309 PrintAndLog("Starting simulator...");
310 UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
311 SendCommand(&c);
312 return 0;
313 }
314
315 int CmdLFSimBidir(const char *Cmd)
316 {
317 /* Set ADC to twice the carrier for a slight supersampling */
318 UsbCommand c = {CMD_LF_SIMULATE_BIDIR, {47, 384, 0}};
319 SendCommand(&c);
320 return 0;
321 }
322
323 /* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */
324 int CmdLFSimManchester(const char *Cmd)
325 {
326 static int clock, gap;
327 static char data[1024], gapstring[8];
328
329 /* get settings/bits */
330 sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
331
332 /* clear our graph */
333 ClearGraph(0);
334
335 /* fill it with our bitstream */
336 for (int i = 0; i < strlen(data) ; ++i)
337 AppendGraph(0, clock, data[i]- '0');
338
339 /* modulate */
340 CmdManchesterMod("");
341
342 /* show what we've done */
343 RepaintGraphWindow();
344
345 /* simulate */
346 sprintf(&gapstring[0], "%i", gap);
347 CmdLFSim(gapstring);
348 return 0;
349 }
350
351 int CmdVchDemod(const char *Cmd)
352 {
353 // Is this the entire sync pattern, or does this also include some
354 // data bits that happen to be the same everywhere? That would be
355 // lovely to know.
356 static const int SyncPattern[] = {
357 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
358 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
359 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
360 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
361 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
362 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
363 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
364 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
365 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
366 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
367 };
368
369 // So first, we correlate for the sync pattern, and mark that.
370 int bestCorrel = 0, bestPos = 0;
371 int i;
372 // It does us no good to find the sync pattern, with fewer than
373 // 2048 samples after it...
374 for (i = 0; i < (GraphTraceLen-2048); i++) {
375 int sum = 0;
376 int j;
377 for (j = 0; j < arraylen(SyncPattern); j++) {
378 sum += GraphBuffer[i+j]*SyncPattern[j];
379 }
380 if (sum > bestCorrel) {
381 bestCorrel = sum;
382 bestPos = i;
383 }
384 }
385 PrintAndLog("best sync at %d [metric %d]", bestPos, bestCorrel);
386
387 char bits[257];
388 bits[256] = '\0';
389
390 int worst = INT_MAX;
391 int worstPos;
392
393 for (i = 0; i < 2048; i += 8) {
394 int sum = 0;
395 int j;
396 for (j = 0; j < 8; j++) {
397 sum += GraphBuffer[bestPos+i+j];
398 }
399 if (sum < 0) {
400 bits[i/8] = '.';
401 } else {
402 bits[i/8] = '1';
403 }
404 if(abs(sum) < worst) {
405 worst = abs(sum);
406 worstPos = i;
407 }
408 }
409 PrintAndLog("bits:");
410 PrintAndLog("%s", bits);
411 PrintAndLog("worst metric: %d at pos %d", worst, worstPos);
412
413 if (strcmp(Cmd, "clone")==0) {
414 GraphTraceLen = 0;
415 char *s;
416 for(s = bits; *s; s++) {
417 int j;
418 for(j = 0; j < 16; j++) {
419 GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
420 }
421 }
422 RepaintGraphWindow();
423 }
424 return 0;
425 }
426
427 static command_t CommandTable[] =
428 {
429 {"help", CmdHelp, 1, "This help"},
430 {"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
431 {"em4x", CmdLFEM4X, 1, "EM4X RFIDs"},
432 {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
433 {"hid", CmdLFHID, 1, "HID RFIDs"},
434 {"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
435 {"read", CmdLFRead, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},
436 {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
437 {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
438 {"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
439 {"ti", CmdLFTI, 1, "TI RFIDs"},
440 {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
441 {NULL, NULL, 0, NULL}
442 };
443
444 int CmdLF(const char *Cmd)
445 {
446 CmdsParse(CommandTable, Cmd);
447 return 0;
448 }
449
450 int CmdHelp(const char *Cmd)
451 {
452 CmdsHelp(CommandTable);
453 return 0;
454 }
Impressum, Datenschutz