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