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