]> cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdlfem4x.c
Client code cleanup:
[proxmark3-svn] / client / cmdlfem4x.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Low frequency EM4x commands
9 //-----------------------------------------------------------------------------
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <inttypes.h>
14 #include "proxmark3.h"
15 #include "ui.h"
16 #include "util.h"
17 #include "graph.h"
18 #include "cmdparser.h"
19 #include "cmddata.h"
20 #include "cmdlf.h"
21 #include "cmdmain.h"
22 #include "cmdlfem4x.h"
23 #include "lfdemod.h"
24
25 char *global_em410xId;
26
27 static int CmdHelp(const char *Cmd);
28
29 int CmdEMdemodASK(const char *Cmd)
30 {
31 char cmdp = param_getchar(Cmd, 0);
32 int findone = (cmdp == '1') ? 1 : 0;
33 UsbCommand c={CMD_EM410X_DEMOD};
34 c.arg[0]=findone;
35 SendCommand(&c);
36 return 0;
37 }
38
39 /* Read the ID of an EM410x tag.
40 * Format:
41 * 1111 1111 1 <-- standard non-repeatable header
42 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
43 * ....
44 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
45 * 0 <-- stop bit, end of tag
46 */
47 int CmdEM410xRead(const char *Cmd)
48 {
49 uint32_t hi=0;
50 uint64_t lo=0;
51
52 if(!AskEm410xDemod("", &hi, &lo, false)) return 0;
53 PrintAndLog("EM410x pattern found: ");
54 printEM410x(hi, lo);
55 if (hi){
56 PrintAndLog ("EM410x XL pattern found");
57 return 0;
58 }
59 char id[12] = {0x00};
60 sprintf(id, "%010"PRIx64,lo);
61
62 global_em410xId = id;
63 return 1;
64 }
65
66 int usage_lf_em410x_sim(void) {
67 PrintAndLog("Simulating EM410x tag");
68 PrintAndLog("");
69 PrintAndLog("Usage: lf em 410xsim [h] <uid> <clock>");
70 PrintAndLog("Options:");
71 PrintAndLog(" h - this help");
72 PrintAndLog(" uid - uid (10 HEX symbols)");
73 PrintAndLog(" clock - clock (32|64) (optional)");
74 PrintAndLog("samples:");
75 PrintAndLog(" lf em 410xsim 0F0368568B");
76 PrintAndLog(" lf em 410xsim 0F0368568B 32");
77 return 0;
78 }
79
80 // emulate an EM410X tag
81 int CmdEM410xSim(const char *Cmd)
82 {
83 int i, n, j, binary[4], parity[4];
84
85 char cmdp = param_getchar(Cmd, 0);
86 uint8_t uid[5] = {0x00};
87
88 if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_sim();
89 /* clock is 64 in EM410x tags */
90 uint8_t clock = 64;
91
92 if (param_gethex(Cmd, 0, uid, 10)) {
93 PrintAndLog("UID must include 10 HEX symbols");
94 return 0;
95 }
96 param_getdec(Cmd,1, &clock);
97
98 PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X clock: %d", uid[0],uid[1],uid[2],uid[3],uid[4],clock);
99 PrintAndLog("Press pm3-button to about simulation");
100
101
102 /* clear our graph */
103 ClearGraph(0);
104
105 /* write 9 start bits */
106 for (i = 0; i < 9; i++)
107 AppendGraph(0, clock, 1);
108
109 /* for each hex char */
110 parity[0] = parity[1] = parity[2] = parity[3] = 0;
111 for (i = 0; i < 10; i++)
112 {
113 /* read each hex char */
114 sscanf(&Cmd[i], "%1x", &n);
115 for (j = 3; j >= 0; j--, n/= 2)
116 binary[j] = n % 2;
117
118 /* append each bit */
119 AppendGraph(0, clock, binary[0]);
120 AppendGraph(0, clock, binary[1]);
121 AppendGraph(0, clock, binary[2]);
122 AppendGraph(0, clock, binary[3]);
123
124 /* append parity bit */
125 AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
126
127 /* keep track of column parity */
128 parity[0] ^= binary[0];
129 parity[1] ^= binary[1];
130 parity[2] ^= binary[2];
131 parity[3] ^= binary[3];
132 }
133
134 /* parity columns */
135 AppendGraph(0, clock, parity[0]);
136 AppendGraph(0, clock, parity[1]);
137 AppendGraph(0, clock, parity[2]);
138 AppendGraph(0, clock, parity[3]);
139
140 /* stop bit */
141 AppendGraph(1, clock, 0);
142
143 CmdLFSim("0"); //240 start_gap.
144 return 0;
145 }
146
147 /* Function is equivalent of lf read + data samples + em410xread
148 * looped until an EM410x tag is detected
149 *
150 * Why is CmdSamples("16000")?
151 * TBD: Auto-grow sample size based on detected sample rate. IE: If the
152 * rate gets lower, then grow the number of samples
153 * Changed by martin, 4000 x 4 = 16000,
154 * see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235
155 */
156 int CmdEM410xWatch(const char *Cmd)
157 {
158 do {
159 if (ukbhit()) {
160 printf("\naborted via keyboard!\n");
161 break;
162 }
163
164 CmdLFRead("s");
165 getSamples("8201",true); //capture enough to get 2 complete preambles (4096*2+9)
166 } while (!CmdEM410xRead(""));
167
168 return 0;
169 }
170
171 //currently only supports manchester modulations
172 int CmdEM410xWatchnSpoof(const char *Cmd)
173 {
174 CmdEM410xWatch(Cmd);
175 PrintAndLog("# Replaying captured ID: %s",global_em410xId);
176 CmdLFaskSim("");
177 return 0;
178 }
179
180 int CmdEM410xWrite(const char *Cmd)
181 {
182 uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value
183 int card = 0xFF; // invalid card value
184 unsigned int clock = 0; // invalid clock value
185
186 sscanf(Cmd, "%" SCNx64 " %d %d", &id, &card, &clock);
187
188 // Check ID
189 if (id == 0xFFFFFFFFFFFFFFFF) {
190 PrintAndLog("Error! ID is required.\n");
191 return 0;
192 }
193 if (id >= 0x10000000000) {
194 PrintAndLog("Error! Given EM410x ID is longer than 40 bits.\n");
195 return 0;
196 }
197
198 // Check Card
199 if (card == 0xFF) {
200 PrintAndLog("Error! Card type required.\n");
201 return 0;
202 }
203 if (card < 0) {
204 PrintAndLog("Error! Bad card type selected.\n");
205 return 0;
206 }
207
208 // Check Clock
209 // Default: 64
210 if (clock == 0)
211 clock = 64;
212
213 // Allowed clock rates: 16, 32, 40 and 64
214 if ((clock != 16) && (clock != 32) && (clock != 64) && (clock != 40)) {
215 PrintAndLog("Error! Clock rate %d not valid. Supported clock rates are 16, 32, 40 and 64.\n", clock);
216 return 0;
217 }
218
219 if (card == 1) {
220 PrintAndLog("Writing %s tag with UID 0x%010" PRIx64 " (clock rate: %d)", "T55x7", id, clock);
221 // NOTE: We really should pass the clock in as a separate argument, but to
222 // provide for backwards-compatibility for older firmware, and to avoid
223 // having to add another argument to CMD_EM410X_WRITE_TAG, we just store
224 // the clock rate in bits 8-15 of the card value
225 card = (card & 0xFF) | ((clock << 8) & 0xFF00);
226 } else if (card == 0) {
227 PrintAndLog("Writing %s tag with UID 0x%010" PRIx64, "T5555", id, clock);
228 card = (card & 0xFF) | ((clock << 8) & 0xFF00);
229 } else {
230 PrintAndLog("Error! Bad card type selected.\n");
231 return 0;
232 }
233
234 UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}};
235 SendCommand(&c);
236
237 return 0;
238 }
239
240 //**************** Start of EM4x50 Code ************************
241 bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
242 {
243 if (rows*cols>size) return false;
244 uint8_t colP=0;
245 //assume last col is a parity and do not test
246 for (uint8_t colNum = 0; colNum < cols-1; colNum++) {
247 for (uint8_t rowNum = 0; rowNum < rows; rowNum++) {
248 colP ^= BitStream[(rowNum*cols)+colNum];
249 }
250 if (colP != pType) return false;
251 }
252 return true;
253 }
254
255 bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
256 {
257 if (rows*cols>size) return false;
258 uint8_t rowP=0;
259 //assume last row is a parity row and do not test
260 for (uint8_t rowNum = 0; rowNum < rows-1; rowNum++) {
261 for (uint8_t colNum = 0; colNum < cols; colNum++) {
262 rowP ^= BitStream[(rowNum*cols)+colNum];
263 }
264 if (rowP != pType) return false;
265 }
266 return true;
267 }
268
269 uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest)
270 {
271 if (size<45) return 0;
272 uint32_t code = bytebits_to_byte(BitStream,8);
273 code = code<<8 | bytebits_to_byte(BitStream+9,8);
274 code = code<<8 | bytebits_to_byte(BitStream+18,8);
275 code = code<<8 | bytebits_to_byte(BitStream+27,8);
276 if (verbose || g_debugMode){
277 for (uint8_t i = 0; i<5; i++){
278 if (i == 4) PrintAndLog(""); //parity byte spacer
279 PrintAndLog("%d%d%d%d%d%d%d%d %d -> 0x%02x",
280 BitStream[i*9],
281 BitStream[i*9+1],
282 BitStream[i*9+2],
283 BitStream[i*9+3],
284 BitStream[i*9+4],
285 BitStream[i*9+5],
286 BitStream[i*9+6],
287 BitStream[i*9+7],
288 BitStream[i*9+8],
289 bytebits_to_byte(BitStream+i*9,8)
290 );
291 }
292 if (pTest)
293 PrintAndLog("Parity Passed");
294 else
295 PrintAndLog("Parity Failed");
296 }
297 return code;
298 }
299 /* Read the transmitted data of an EM4x50 tag from the graphbuffer
300 * Format:
301 *
302 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
303 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
304 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
305 * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
306 * CCCCCCCC <- column parity bits
307 * 0 <- stop bit
308 * LW <- Listen Window
309 *
310 * This pattern repeats for every block of data being transmitted.
311 * Transmission starts with two Listen Windows (LW - a modulated
312 * pattern of 320 cycles each (32/32/128/64/64)).
313 *
314 * Note that this data may or may not be the UID. It is whatever data
315 * is stored in the blocks defined in the control word First and Last
316 * Word Read values. UID is stored in block 32.
317 */
318 //completed by Marshmellow
319 int EM4x50Read(const char *Cmd, bool verbose)
320 {
321 uint8_t fndClk[] = {8,16,32,40,50,64,128};
322 int clk = 0;
323 int invert = 0;
324 int tol = 0;
325 int i, j, startblock, skip, block, start, end, low, high, minClk;
326 bool complete = false;
327 int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
328 uint32_t Code[6];
329 char tmp[6];
330 char tmp2[20];
331 int phaseoff;
332 high = low = 0;
333 memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
334
335 // get user entry if any
336 sscanf(Cmd, "%i %i", &clk, &invert);
337
338 // save GraphBuffer - to restore it later
339 save_restoreGB(1);
340
341 // first get high and low values
342 for (i = 0; i < GraphTraceLen; i++) {
343 if (GraphBuffer[i] > high)
344 high = GraphBuffer[i];
345 else if (GraphBuffer[i] < low)
346 low = GraphBuffer[i];
347 }
348
349 i = 0;
350 j = 0;
351 minClk = 255;
352 // get to first full low to prime loop and skip incomplete first pulse
353 while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
354 ++i;
355 while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
356 ++i;
357 skip = i;
358
359 // populate tmpbuff buffer with pulse lengths
360 while (i < GraphTraceLen) {
361 // measure from low to low
362 while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
363 ++i;
364 start= i;
365 while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
366 ++i;
367 while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
368 ++i;
369 if (j>=(MAX_GRAPH_TRACE_LEN/64)) {
370 break;
371 }
372 tmpbuff[j++]= i - start;
373 if (i-start < minClk && i < GraphTraceLen) {
374 minClk = i - start;
375 }
376 }
377 // set clock
378 if (!clk) {
379 for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
380 tol = fndClk[clkCnt]/8;
381 if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) {
382 clk=fndClk[clkCnt];
383 break;
384 }
385 }
386 if (!clk) return 0;
387 } else tol = clk/8;
388
389 // look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2)
390 start = -1;
391 for (i= 0; i < j - 4 ; ++i) {
392 skip += tmpbuff[i];
393 if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks
394 if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks
395 if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
396 if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following
397 {
398 start= i + 4;
399 break;
400 }
401 }
402 startblock = i + 4;
403
404 // skip over the remainder of LW
405 skip += tmpbuff[i+1] + tmpbuff[i+2] + clk;
406 if (tmpbuff[i+3]>clk)
407 phaseoff = tmpbuff[i+3]-clk;
408 else
409 phaseoff = 0;
410 // now do it again to find the end
411 end = skip;
412 for (i += 3; i < j - 4 ; ++i) {
413 end += tmpbuff[i];
414 if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks
415 if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks
416 if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
417 if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following
418 {
419 complete= true;
420 break;
421 }
422 }
423 end = i;
424 // report back
425 if (verbose || g_debugMode) {
426 if (start >= 0) {
427 PrintAndLog("\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)");
428 } else {
429 PrintAndLog("No data found!, clock tried:%d",clk);
430 PrintAndLog("Try again with more samples.");
431 PrintAndLog(" or after a 'data askedge' command to clean up the read");
432 return 0;
433 }
434 } else if (start < 0) return 0;
435 start = skip;
436 snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47);
437 // get rid of leading crap
438 snprintf(tmp, sizeof(tmp), "%i", skip);
439 CmdLtrim(tmp);
440 bool pTest;
441 bool AllPTest = true;
442 // now work through remaining buffer printing out data blocks
443 block = 0;
444 i = startblock;
445 while (block < 6) {
446 if (verbose || g_debugMode) PrintAndLog("\nBlock %i:", block);
447 skip = phaseoff;
448
449 // look for LW before start of next block
450 for ( ; i < j - 4 ; ++i) {
451 skip += tmpbuff[i];
452 if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)
453 if (tmpbuff[i+1] >= clk-tol)
454 break;
455 }
456 if (i >= j-4) break; //next LW not found
457 skip += clk;
458 if (tmpbuff[i+1]>clk)
459 phaseoff = tmpbuff[i+1]-clk;
460 else
461 phaseoff = 0;
462 i += 2;
463 if (ASKDemod(tmp2, false, false, 1) < 1) {
464 save_restoreGB(0);
465 return 0;
466 }
467 //set DemodBufferLen to just one block
468 DemodBufferLen = skip/clk;
469 //test parities
470 pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen,5,9,0);
471 pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen,5,9,0);
472 AllPTest &= pTest;
473 //get output
474 Code[block] = OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest);
475 if (g_debugMode) PrintAndLog("\nskipping %d samples, bits:%d", skip, skip/clk);
476 //skip to start of next block
477 snprintf(tmp,sizeof(tmp),"%i",skip);
478 CmdLtrim(tmp);
479 block++;
480 if (i >= end) break; //in case chip doesn't output 6 blocks
481 }
482 //print full code:
483 if (verbose || g_debugMode || AllPTest){
484 if (!complete) {
485 PrintAndLog("*** Warning!");
486 PrintAndLog("Partial data - no end found!");
487 PrintAndLog("Try again with more samples.");
488 }
489 PrintAndLog("Found data at sample: %i - using clock: %i", start, clk);
490 end = block;
491 for (block=0; block < end; block++){
492 PrintAndLog("Block %d: %08x",block,Code[block]);
493 }
494 if (AllPTest) {
495 PrintAndLog("Parities Passed");
496 } else {
497 PrintAndLog("Parities Failed");
498 PrintAndLog("Try cleaning the read samples with 'data askedge'");
499 }
500 }
501
502 //restore GraphBuffer
503 save_restoreGB(0);
504 return (int)AllPTest;
505 }
506
507 int CmdEM4x50Read(const char *Cmd)
508 {
509 return EM4x50Read(Cmd, true);
510 }
511
512 //**************** Start of EM4x05/EM4x69 Code ************************
513 int usage_lf_em_read(void) {
514 PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. ");
515 PrintAndLog("");
516 PrintAndLog("Usage: lf em 4x05readword [h] <address> <pwd>");
517 PrintAndLog("Options:");
518 PrintAndLog(" h - this help");
519 PrintAndLog(" address - memory address to read. (0-15)");
520 PrintAndLog(" pwd - password (hex) (optional)");
521 PrintAndLog("samples:");
522 PrintAndLog(" lf em 4x05readword 1");
523 PrintAndLog(" lf em 4x05readword 1 11223344");
524 return 0;
525 }
526
527 // for command responses from em4x05 or em4x69
528 // download samples from device and copy them to the Graphbuffer
529 bool downloadSamplesEM() {
530 // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
531 uint8_t got[6000];
532 GetFromBigBuf(got, sizeof(got), 0);
533 if ( !WaitForResponseTimeout(CMD_ACK, NULL, 4000) ) {
534 PrintAndLog("command execution time out");
535 return false;
536 }
537 setGraphBuf(got, sizeof(got));
538 return true;
539 }
540
541 bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) {
542 // em4x05/em4x69 command response preamble is 00001010
543 // skip first two 0 bits as they might have been missed in the demod
544 uint8_t preamble[] = {0,0,1,0,1,0};
545 size_t startIdx = 0;
546
547 // set size to 20 to only test first 14 positions for the preamble or less if not a read command
548 size_t size = (readCmd) ? 20 : 11;
549 // sanity check
550 size = (size > DemodBufferLen) ? DemodBufferLen : size;
551 // test preamble
552 if ( !preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &size, &startIdx, true) ) {
553 if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
554 return false;
555 }
556 // if this is a readword command, get the read bytes and test the parities
557 if (readCmd) {
558 if (!EM_EndParityTest(DemodBuffer + startIdx + sizeof(preamble), 45, 5, 9, 0)) {
559 if (g_debugMode) PrintAndLog("DEBUG: Error - End Parity check failed");
560 return false;
561 }
562 // test for even parity bits and remove them. (leave out the end row of parities so 36 bits)
563 if ( removeParity(DemodBuffer, startIdx + sizeof(preamble),9,0,36) == 0 ) {
564 if (g_debugMode) PrintAndLog("DEBUG: Error - Parity not detected");
565 return false;
566 }
567
568 setDemodBuf(DemodBuffer, 32, 0);
569 *word = bytebits_to_byteLSBF(DemodBuffer, 32);
570 }
571 return true;
572 }
573
574 // FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE
575 // should cover 90% of known used configs
576 // the rest will need to be manually demoded for now...
577 int demodEM4x05resp(uint32_t *word, bool readCmd) {
578 int ans = 0;
579
580 // test for FSK wave (easiest to 99% ID)
581 if (GetFskClock("", false, false)) {
582 //valid fsk clocks found
583 ans = FSKrawDemod("0 0", false);
584 if (!ans) {
585 if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: FSK Demod failed, ans: %d", ans);
586 } else {
587 if (EM4x05testDemodReadData(word, readCmd)) {
588 return 1;
589 }
590 }
591 }
592 // PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... )
593 ans = GetPskClock("", false, false);
594 if (ans>0) {
595 //try psk1
596 ans = PSKDemod("0 0 6", false);
597 if (!ans) {
598 if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans);
599 } else {
600 if (EM4x05testDemodReadData(word, readCmd)) {
601 return 1;
602 } else {
603 //try psk2
604 psk1TOpsk2(DemodBuffer, DemodBufferLen);
605 if (EM4x05testDemodReadData(word, readCmd)) {
606 return 1;
607 }
608 }
609 //try psk1 inverted
610 ans = PSKDemod("0 1 6", false);
611 if (!ans) {
612 if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans);
613 } else {
614 if (EM4x05testDemodReadData(word, readCmd)) {
615 return 1;
616 } else {
617 //try psk2
618 psk1TOpsk2(DemodBuffer, DemodBufferLen);
619 if (EM4x05testDemodReadData(word, readCmd)) {
620 return 1;
621 }
622 }
623 }
624 }
625 }
626
627 // manchester is more common than biphase... try first
628 bool stcheck = false;
629 // try manchester - NOTE: ST only applies to T55x7 tags.
630 ans = ASKDemod_ext("0,0,1", false, false, 1, &stcheck);
631 if (!ans) {
632 if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed, ans: %d", ans);
633 } else {
634 if (EM4x05testDemodReadData(word, readCmd)) {
635 return 1;
636 }
637 }
638
639 //try biphase
640 ans = ASKbiphaseDemod("0 0 1", false);
641 if (!ans) {
642 if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans);
643 } else {
644 if (EM4x05testDemodReadData(word, readCmd)) {
645 return 1;
646 }
647 }
648
649 //try diphase (differential biphase or inverted)
650 ans = ASKbiphaseDemod("0 1 1", false);
651 if (!ans) {
652 if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans);
653 } else {
654 if (EM4x05testDemodReadData(word, readCmd)) {
655 return 1;
656 }
657 }
658
659 return -1;
660 }
661
662 int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *wordData) {
663 UsbCommand c = {CMD_EM4X_READ_WORD, {addr, pwd, usePwd}};
664 clearCommandBuffer();
665 SendCommand(&c);
666 UsbCommand resp;
667 if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)){
668 PrintAndLog("Command timed out");
669 return -1;
670 }
671 if ( !downloadSamplesEM() ) {
672 return -1;
673 }
674 int testLen = (GraphTraceLen < 1000) ? GraphTraceLen : 1000;
675 if (graphJustNoise(GraphBuffer, testLen)) {
676 PrintAndLog("no tag not found");
677 return -1;
678 }
679 //attempt demod:
680 return demodEM4x05resp(wordData, true);
681 }
682
683 int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) {
684 uint32_t wordData = 0;
685 int success = EM4x05ReadWord_ext(addr, pwd, usePwd, &wordData);
686 if (success == 1)
687 PrintAndLog("%s Address %02d | %08X", (addr>13) ? "Lock":" Got",addr,wordData);
688 else
689 PrintAndLog("Read Address %02d | failed",addr);
690
691 return success;
692 }
693
694 int CmdEM4x05ReadWord(const char *Cmd) {
695 uint8_t addr;
696 uint32_t pwd;
697 bool usePwd = false;
698 uint8_t ctmp = param_getchar(Cmd, 0);
699 if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_read();
700
701 addr = param_get8ex(Cmd, 0, 50, 10);
702 // for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
703 pwd = param_get32ex(Cmd, 1, 1, 16);
704
705 if ( (addr > 15) ) {
706 PrintAndLog("Address must be between 0 and 15");
707 return 1;
708 }
709 if ( pwd == 1 ) {
710 PrintAndLog("Reading address %02u", addr);
711 } else {
712 usePwd = true;
713 PrintAndLog("Reading address %02u | password %08X", addr, pwd);
714 }
715
716 return EM4x05ReadWord(addr, pwd, usePwd);
717 }
718
719 int usage_lf_em_dump(void) {
720 PrintAndLog("Dump EM4x05/EM4x69. Tag must be on antenna. ");
721 PrintAndLog("");
722 PrintAndLog("Usage: lf em 4x05dump [h] <pwd>");
723 PrintAndLog("Options:");
724 PrintAndLog(" h - this help");
725 PrintAndLog(" pwd - password (hex) (optional)");
726 PrintAndLog("samples:");
727 PrintAndLog(" lf em 4x05dump");
728 PrintAndLog(" lf em 4x05dump 11223344");
729 return 0;
730 }
731
732 int CmdEM4x05dump(const char *Cmd) {
733 uint8_t addr = 0;
734 uint32_t pwd;
735 bool usePwd = false;
736 uint8_t ctmp = param_getchar(Cmd, 0);
737 if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_dump();
738
739 // for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
740 pwd = param_get32ex(Cmd, 0, 1, 16);
741
742 if ( pwd != 1 ) {
743 usePwd = true;
744 }
745 int success = 1;
746 for (; addr < 16; addr++) {
747 if (addr == 2) {
748 if (usePwd) {
749 PrintAndLog(" PWD Address %02u | %08X",addr,pwd);
750 } else {
751 PrintAndLog(" PWD Address 02 | cannot read");
752 }
753 } else {
754 success &= EM4x05ReadWord(addr, pwd, usePwd);
755 }
756 }
757
758 return success;
759 }
760
761
762 int usage_lf_em_write(void) {
763 PrintAndLog("Write EM4x05/EM4x69. Tag must be on antenna. ");
764 PrintAndLog("");
765 PrintAndLog("Usage: lf em 4x05writeword [h] <address> <data> <pwd>");
766 PrintAndLog("Options:");
767 PrintAndLog(" h - this help");
768 PrintAndLog(" address - memory address to write to. (0-15)");
769 PrintAndLog(" data - data to write (hex)");
770 PrintAndLog(" pwd - password (hex) (optional)");
771 PrintAndLog("samples:");
772 PrintAndLog(" lf em 4x05writeword 1");
773 PrintAndLog(" lf em 4x05writeword 1 deadc0de 11223344");
774 return 0;
775 }
776
777 int CmdEM4x05WriteWord(const char *Cmd) {
778 uint8_t ctmp = param_getchar(Cmd, 0);
779 if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_write();
780
781 bool usePwd = false;
782
783 uint8_t addr = 16; // default to invalid address
784 uint32_t data = 0xFFFFFFFF; // default to blank data
785 uint32_t pwd = 0xFFFFFFFF; // default to blank password
786
787 addr = param_get8ex(Cmd, 0, 16, 10);
788 data = param_get32ex(Cmd, 1, 0, 16);
789 pwd = param_get32ex(Cmd, 2, 1, 16);
790
791
792 if ( (addr > 15) ) {
793 PrintAndLog("Address must be between 0 and 15");
794 return 1;
795 }
796 if ( pwd == 1 )
797 PrintAndLog("Writing address %d data %08X", addr, data);
798 else {
799 usePwd = true;
800 PrintAndLog("Writing address %d data %08X using password %08X", addr, data, pwd);
801 }
802
803 uint16_t flag = (addr << 8 ) | usePwd;
804
805 UsbCommand c = {CMD_EM4X_WRITE_WORD, {flag, data, pwd}};
806 clearCommandBuffer();
807 SendCommand(&c);
808 UsbCommand resp;
809 if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)){
810 PrintAndLog("Error occurred, device did not respond during write operation.");
811 return -1;
812 }
813 if ( !downloadSamplesEM() ) {
814 return -1;
815 }
816 //check response for 00001010 for write confirmation!
817 //attempt demod:
818 uint32_t dummy = 0;
819 int result = demodEM4x05resp(&dummy,false);
820 if (result == 1) {
821 PrintAndLog("Write Verified");
822 } else {
823 PrintAndLog("Write could not be verified");
824 }
825 return result;
826 }
827
828 void printEM4x05config(uint32_t wordData) {
829 uint16_t datarate = (((wordData & 0x3F)+1)*2);
830 uint8_t encoder = ((wordData >> 6) & 0xF);
831 char enc[14];
832 memset(enc,0,sizeof(enc));
833
834 uint8_t PSKcf = (wordData >> 10) & 0x3;
835 char cf[10];
836 memset(cf,0,sizeof(cf));
837 uint8_t delay = (wordData >> 12) & 0x3;
838 char cdelay[33];
839 memset(cdelay,0,sizeof(cdelay));
840 uint8_t LWR = (wordData >> 14) & 0xF; //last word read
841
842 switch (encoder) {
843 case 0: snprintf(enc,sizeof(enc),"NRZ"); break;
844 case 1: snprintf(enc,sizeof(enc),"Manchester"); break;
845 case 2: snprintf(enc,sizeof(enc),"Biphase"); break;
846 case 3: snprintf(enc,sizeof(enc),"Miller"); break;
847 case 4: snprintf(enc,sizeof(enc),"PSK1"); break;
848 case 5: snprintf(enc,sizeof(enc),"PSK2"); break;
849 case 6: snprintf(enc,sizeof(enc),"PSK3"); break;
850 case 7: snprintf(enc,sizeof(enc),"Unknown"); break;
851 case 8: snprintf(enc,sizeof(enc),"FSK1"); break;
852 case 9: snprintf(enc,sizeof(enc),"FSK2"); break;
853 default: snprintf(enc,sizeof(enc),"Unknown"); break;
854 }
855
856 switch (PSKcf) {
857 case 0: snprintf(cf,sizeof(cf),"RF/2"); break;
858 case 1: snprintf(cf,sizeof(cf),"RF/8"); break;
859 case 2: snprintf(cf,sizeof(cf),"RF/4"); break;
860 case 3: snprintf(cf,sizeof(cf),"unknown"); break;
861 }
862
863 switch (delay) {
864 case 0: snprintf(cdelay, sizeof(cdelay),"no delay"); break;
865 case 1: snprintf(cdelay, sizeof(cdelay),"BP/8 or 1/8th bit period delay"); break;
866 case 2: snprintf(cdelay, sizeof(cdelay),"BP/4 or 1/4th bit period delay"); break;
867 case 3: snprintf(cdelay, sizeof(cdelay),"no delay"); break;
868 }
869 PrintAndLog("ConfigWord: %08X (Word 4)\n", wordData);
870 PrintAndLog("Config Breakdown:", wordData);
871 PrintAndLog(" Data Rate: %02u | RF/%u", wordData & 0x3F, datarate);
872 PrintAndLog(" Encoder: %u | %s", encoder, enc);
873 PrintAndLog(" PSK CF: %u | %s", PSKcf, cf);
874 PrintAndLog(" Delay: %u | %s", delay, cdelay);
875 PrintAndLog(" LastWordR: %02u | Address of last word for default read", LWR);
876 PrintAndLog(" ReadLogin: %u | Read Login is %s", (wordData & 0x40000)>>18, (wordData & 0x40000) ? "Required" : "Not Required");
877 PrintAndLog(" ReadHKL: %u | Read Housekeeping Words Login is %s", (wordData & 0x80000)>>19, (wordData & 0x80000) ? "Required" : "Not Required");
878 PrintAndLog("WriteLogin: %u | Write Login is %s", (wordData & 0x100000)>>20, (wordData & 0x100000) ? "Required" : "Not Required");
879 PrintAndLog(" WriteHKL: %u | Write Housekeeping Words Login is %s", (wordData & 0x200000)>>21, (wordData & 0x200000) ? "Required" : "Not Required");
880 PrintAndLog(" R.A.W.: %u | Read After Write is %s", (wordData & 0x400000)>>22, (wordData & 0x400000) ? "On" : "Off");
881 PrintAndLog(" Disable: %u | Disable Command is %s", (wordData & 0x800000)>>23, (wordData & 0x800000) ? "Accepted" : "Not Accepted");
882 PrintAndLog(" R.T.F.: %u | Reader Talk First is %s", (wordData & 0x1000000)>>24, (wordData & 0x1000000) ? "Enabled" : "Disabled");
883 PrintAndLog(" Pigeon: %u | Pigeon Mode is %s\n", (wordData & 0x4000000)>>26, (wordData & 0x4000000) ? "Enabled" : "Disabled");
884 }
885
886 void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t serial) {
887 switch (chipType) {
888 case 9: PrintAndLog("\n Chip Type: %u | EM4305", chipType); break;
889 case 4: PrintAndLog(" Chip Type: %u | Unknown", chipType); break;
890 case 2: PrintAndLog(" Chip Type: %u | EM4469", chipType); break;
891 //add more here when known
892 default: PrintAndLog(" Chip Type: %u Unknown", chipType); break;
893 }
894
895 switch (cap) {
896 case 3: PrintAndLog(" Cap Type: %u | 330pF",cap); break;
897 case 2: PrintAndLog(" Cap Type: %u | %spF",cap, (chipType==2)? "75":"210"); break;
898 case 1: PrintAndLog(" Cap Type: %u | 250pF",cap); break;
899 case 0: PrintAndLog(" Cap Type: %u | no resonant capacitor",cap); break;
900 default: PrintAndLog(" Cap Type: %u | unknown",cap); break;
901 }
902
903 PrintAndLog(" Cust Code: %03u | %s", custCode, (custCode == 0x200) ? "Default": "Unknown");
904 if (serial != 0) {
905 PrintAndLog("\n Serial #: %08X\n", serial);
906 }
907 }
908
909 void printEM4x05ProtectionBits(uint32_t wordData) {
910 for (uint8_t i = 0; i < 15; i++) {
911 PrintAndLog(" Word: %02u | %s", i, (((1 << i) & wordData ) || i < 2) ? "Is Write Locked" : "Is Not Write Locked");
912 if (i==14) {
913 PrintAndLog(" Word: %02u | %s", i+1, (((1 << i) & wordData ) || i < 2) ? "Is Write Locked" : "Is Not Write Locked");
914 }
915 }
916 }
917
918 //quick test for EM4x05/EM4x69 tag
919 bool EM4x05Block0Test(uint32_t *wordData) {
920 if (EM4x05ReadWord_ext(0,0,false,wordData) == 1) {
921 return true;
922 }
923 return false;
924 }
925
926 int CmdEM4x05info(const char *Cmd) {
927 //uint8_t addr = 0;
928 uint32_t pwd;
929 uint32_t wordData = 0;
930 bool usePwd = false;
931 uint8_t ctmp = param_getchar(Cmd, 0);
932 if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_dump();
933
934 // for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
935 pwd = param_get32ex(Cmd, 0, 1, 16);
936
937 if ( pwd != 1 ) {
938 usePwd = true;
939 }
940
941 // read word 0 (chip info)
942 // block 0 can be read even without a password.
943 if ( !EM4x05Block0Test(&wordData) )
944 return -1;
945
946 uint8_t chipType = (wordData >> 1) & 0xF;
947 uint8_t cap = (wordData >> 5) & 3;
948 uint16_t custCode = (wordData >> 9) & 0x3FF;
949
950 // read word 1 (serial #) doesn't need pwd
951 wordData = 0;
952 if (EM4x05ReadWord_ext(1, 0, false, &wordData) != 1) {
953 //failed, but continue anyway...
954 }
955 printEM4x05info(chipType, cap, custCode, wordData);
956
957 // read word 4 (config block)
958 // needs password if one is set
959 wordData = 0;
960 if ( EM4x05ReadWord_ext(4, pwd, usePwd, &wordData) != 1 ) {
961 //failed
962 return 0;
963 }
964 printEM4x05config(wordData);
965
966 // read word 14 and 15 to see which is being used for the protection bits
967 wordData = 0;
968 if ( EM4x05ReadWord_ext(14, pwd, usePwd, &wordData) != 1 ) {
969 //failed
970 return 0;
971 }
972 // if status bit says this is not the used protection word
973 if (!(wordData & 0x8000)) {
974 if ( EM4x05ReadWord_ext(15, pwd, usePwd, &wordData) != 1 ) {
975 //failed
976 return 0;
977 }
978 }
979 if (!(wordData & 0x8000)) {
980 //something went wrong
981 return 0;
982 }
983 printEM4x05ProtectionBits(wordData);
984
985 return 1;
986 }
987
988
989 static command_t CommandTable[] =
990 {
991 {"help", CmdHelp, 1, "This help"},
992 {"410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
993 {"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
994 {"410xsim", CmdEM410xSim, 0, "<UID> [clock rate] -- Simulate EM410x tag"},
995 {"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
996 {"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
997 {"410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
998 {"4x05dump", CmdEM4x05dump, 0, "(pwd) -- Read EM4x05/EM4x69 all word data"},
999 {"4x05info", CmdEM4x05info, 0, "(pwd) -- Get info from EM4x05/EM4x69 tag"},
1000 {"4x05readword", CmdEM4x05ReadWord, 0, "<Word> (pwd) -- Read EM4x05/EM4x69 word data"},
1001 {"4x05writeword", CmdEM4x05WriteWord, 0, "<Word> <data> (pwd) -- Write EM4x05/EM4x69 word data"},
1002 {"4x50read", CmdEM4x50Read, 1, "demod data from EM4x50 tag from the graph buffer"},
1003 {NULL, NULL, 0, NULL}
1004 };
1005
1006 int CmdLFEM4X(const char *Cmd)
1007 {
1008 CmdsParse(CommandTable, Cmd);
1009 return 0;
1010 }
1011
1012 int CmdHelp(const char *Cmd)
1013 {
1014 CmdsHelp(CommandTable);
1015 return 0;
1016 }
Impressum, Datenschutz