textual
[RRG-proxmark3.git] / client / src / cmdlfem410x.c
blob5619b9a151e6d2f967170c29691d419361ac7a74
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
4 // modified marshmellow
5 // modified Iceman, 2020
6 //
7 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
8 // at your option, any later version. See the LICENSE.txt file for the text of
9 // the license.
10 //-----------------------------------------------------------------------------
11 // Low frequency EM4x commands
12 //-----------------------------------------------------------------------------
14 #include "cmdlfem410x.h"
15 #include "cmdlfem4x50.h"
16 #include <stdio.h>
17 #include <string.h>
18 #include <inttypes.h>
19 #include <ctype.h>
20 #include <stdlib.h>
21 #include "fileutils.h"
22 #include "cmdparser.h" // command_t
23 #include "comms.h"
24 #include "commonutil.h"
25 #include "common.h"
26 #include "util_posix.h"
27 #include "protocols.h"
28 #include "ui.h"
29 #include "proxgui.h"
30 #include "graph.h"
31 #include "cmddata.h"
32 #include "cmdlf.h"
33 #include "lfdemod.h"
34 #include "generator.h"
35 #include "cliparser.h"
36 #include "cmdhw.h"
38 static uint64_t g_em410xid = 0;
40 static int CmdHelp(const char *Cmd);
41 /* Read the ID of an EM410x tag.
42 * Format:
43 * 1111 1111 1 <-- standard non-repeatable header
44 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
45 * ....
46 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
47 * 0 <-- stop bit, end of tag
50 // Construct the graph for emulating an EM410X tag
51 static void em410x_construct_emul_graph(uint8_t *uid, uint8_t clock, uint8_t gap) {
53 // clear our graph
54 ClearGraph(true);
56 // write 16 zero bit sledge
57 for (uint8_t i = 0; i < gap; i++)
58 AppendGraph(false, clock, 0);
60 // write 9 start bits
61 for (uint8_t i = 0; i < 9; i++)
62 AppendGraph(false, clock, 1);
64 uint8_t bs[8], parity[8];
65 memset(parity, 0, sizeof(parity));
67 for (uint8_t i = 0; i < 5; i++) {
69 for (uint8_t j = 0; j < 8; j++) {
70 bs[j] = (uid[i] >> (7 - j) & 1);
72 PrintAndLogEx(DEBUG, "uid[%d] 0x%02x (%s)", i, uid[i], sprint_bin(bs, 4));
74 for (uint8_t j = 0; j < 2; j++) {
75 // append each bit
76 AppendGraph(false, clock, bs[0 + (4 * j)]);
77 AppendGraph(false, clock, bs[1 + (4 * j)]);
78 AppendGraph(false, clock, bs[2 + (4 * j)]);
79 AppendGraph(false, clock, bs[3 + (4 * j)]);
81 // append parity bit
82 AppendGraph(false, clock, bs[0 + (4 * j)] ^ bs[1 + (4 * j)] ^ bs[2 + (4 * j)] ^ bs[3 + (4 * j)]);
84 // keep track of column parity
85 parity[0] ^= bs[0 + (4 * j)];
86 parity[1] ^= bs[1 + (4 * j)];
87 parity[2] ^= bs[2 + (4 * j)];
88 parity[3] ^= bs[3 + (4 * j)];
92 // parity columns
93 AppendGraph(false, clock, parity[0]);
94 AppendGraph(false, clock, parity[1]);
95 AppendGraph(false, clock, parity[2]);
96 AppendGraph(false, clock, parity[3]);
98 // stop bit
99 AppendGraph(true, clock, 0);
102 //print 64 bit EM410x ID in multiple formats
103 void printEM410x(uint32_t hi, uint64_t id, bool verbose) {
105 if (!id && !hi) return;
107 uint64_t n = 1;
108 uint64_t id2lo = 0;
109 uint8_t m, i;
110 for (m = 5; m > 0; m--) {
111 for (i = 0; i < 8; i++) {
112 id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8)));
116 if (verbose == false) {
118 if (hi) {
119 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%06X%016" PRIX64), hi, id);
120 } else {
121 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
123 return;
126 if (hi) {
127 //output 88 bit em id
128 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%06X%016" PRIX64), hi, id);
129 PrintAndLogEx(SUCCESS, "EM410x XL ( RF/%d )", g_DemodClock);
130 } else {
131 //output 40 bit em id
132 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
133 PrintAndLogEx(SUCCESS, "EM410x ( RF/%d )", g_DemodClock);
134 PrintAndLogEx(INFO, "-------- " _CYAN_("Possible de-scramble patterns") " ---------");
135 PrintAndLogEx(SUCCESS, "Unique TAG ID : %010" PRIX64, id2lo);
136 PrintAndLogEx(INFO, "HoneyWell IdentKey");
137 PrintAndLogEx(SUCCESS, " DEZ 8 : %08" PRIu64, id & 0xFFFFFF);
138 PrintAndLogEx(SUCCESS, " DEZ 10 : %010" PRIu64, id & 0xFFFFFFFF);
139 PrintAndLogEx(SUCCESS, " DEZ 5.5 : %05" PRIu64 ".%05" PRIu64, (id >> 16LL) & 0xFFFF, (id & 0xFFFF));
140 PrintAndLogEx(SUCCESS, " DEZ 3.5A : %03" PRIu64 ".%05" PRIu64, (id >> 32ll), (id & 0xFFFF));
141 PrintAndLogEx(SUCCESS, " DEZ 3.5B : %03" PRIu64 ".%05" PRIu64, (id & 0xFF000000) >> 24, (id & 0xFFFF));
142 PrintAndLogEx(SUCCESS, " DEZ 3.5C : %03" PRIu64 ".%05" PRIu64, (id & 0xFF0000) >> 16, (id & 0xFFFF));
143 PrintAndLogEx(SUCCESS, " DEZ 14/IK2 : %014" PRIu64, id);
144 PrintAndLogEx(SUCCESS, " DEZ 15/IK3 : %015" PRIu64, id2lo);
145 PrintAndLogEx(SUCCESS, " DEZ 20/ZK : %02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64,
146 (id2lo & 0xf000000000) >> 36,
147 (id2lo & 0x0f00000000) >> 32,
148 (id2lo & 0x00f0000000) >> 28,
149 (id2lo & 0x000f000000) >> 24,
150 (id2lo & 0x0000f00000) >> 20,
151 (id2lo & 0x00000f0000) >> 16,
152 (id2lo & 0x000000f000) >> 12,
153 (id2lo & 0x0000000f00) >> 8,
154 (id2lo & 0x00000000f0) >> 4,
155 (id2lo & 0x000000000f)
157 PrintAndLogEx(INFO, "");
159 uint64_t paxton = (((id >> 32) << 24) | (id & 0xffffff)) + 0x143e00;
160 PrintAndLogEx(SUCCESS, "Other : %05" PRIu64 "_%03" PRIu64 "_%08" PRIu64, (id & 0xFFFF), ((id >> 16LL) & 0xFF), (id & 0xFFFFFF));
161 PrintAndLogEx(SUCCESS, "Pattern Paxton : %" PRIu64 " [0x%" PRIX64 "]", paxton, paxton);
163 uint32_t p1id = (id & 0xFFFFFF);
164 uint8_t arr[32] = {0x00};
165 int j = 23;
166 for (int k = 0 ; k < 24; ++k, --j) {
167 arr[k] = (p1id >> k) & 1;
170 uint32_t p1 = 0;
172 p1 |= arr[23] << 21;
173 p1 |= arr[22] << 23;
174 p1 |= arr[21] << 20;
175 p1 |= arr[20] << 22;
177 p1 |= arr[19] << 18;
178 p1 |= arr[18] << 16;
179 p1 |= arr[17] << 19;
180 p1 |= arr[16] << 17;
182 p1 |= arr[15] << 13;
183 p1 |= arr[14] << 15;
184 p1 |= arr[13] << 12;
185 p1 |= arr[12] << 14;
187 p1 |= arr[11] << 6;
188 p1 |= arr[10] << 2;
189 p1 |= arr[9] << 7;
190 p1 |= arr[8] << 1;
192 p1 |= arr[7] << 0;
193 p1 |= arr[6] << 8;
194 p1 |= arr[5] << 11;
195 p1 |= arr[4] << 3;
197 p1 |= arr[3] << 10;
198 p1 |= arr[2] << 4;
199 p1 |= arr[1] << 5;
200 p1 |= arr[0] << 9;
201 PrintAndLogEx(SUCCESS, "Pattern 1 : %d [0x%X]", p1, p1);
203 uint16_t sebury1 = id & 0xFFFF;
204 uint8_t sebury2 = (id >> 16) & 0x7F;
205 uint32_t sebury3 = id & 0x7FFFFF;
206 PrintAndLogEx(SUCCESS, "Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3);
207 PrintAndLogEx(INFO, "------------------------------------------------");
210 /* Read the ID of an EM410x tag.
211 * Format:
212 * 1111 1111 1 <-- standard non-repeatable header
213 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
214 * ....
215 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
216 * 0 <-- stop bit, end of tag
218 int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) {
219 size_t idx = 0;
220 uint8_t bits[512] = {0};
221 size_t size = sizeof(bits);
222 if (!getDemodBuff(bits, &size)) {
223 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x problem during copy from ASK demod");
224 return PM3_ESOFT;
227 int ans = Em410xDecode(bits, &size, &idx, hi, lo);
228 if (ans < 0) {
230 if (ans == -2)
231 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x not enough samples after demod");
232 else if (ans == -4)
233 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x preamble not found");
234 else if (ans == -5)
235 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x Size not correct: %zu", size);
236 else if (ans == -6)
237 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x parity failed");
239 return PM3_ESOFT;
241 if (!lo && !hi) {
242 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x decoded to all zeros");
243 return PM3_ESOFT;
246 //set GraphBuffer for clone or sim command
247 setDemodBuff(DemodBuffer, (size == 40) ? 64 : 128, idx + 1);
248 setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 1)*g_DemodClock));
250 PrintAndLogEx(DEBUG, "DEBUG: Em410x idx: %zu, Len: %zu, Printing Demod Buffer:", idx, size);
251 if (g_debugMode) {
252 printDemodBuff(0, false, false, true);
255 printEM410x(*hi, *lo, verbose);
256 g_em410xid = *lo;
257 return PM3_SUCCESS;
260 int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose) {
261 bool st = true;
263 // em410x simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
264 if (isGraphBitstream()) {
265 convertGraphFromBitstream();
267 if (ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, false, false, 1, &st) != PM3_SUCCESS)
268 return PM3_ESOFT;
269 return AskEm410xDecode(verbose, hi, lo);
272 // this read loops on device side.
273 // uses the demod in lfops.c
274 static int CmdEM410xWatch(const char *Cmd) {
275 CLIParserContext *ctx;
276 CLIParserInit(&ctx, "lf em 410x watch",
277 "Enables Electro Marine (EM) compatible reader mode printing details of scanned tags.\n"
278 "Run until the button is pressed or another USB command is issued.",
279 "lf em 410x watch"
282 void *argtable[] = {
283 arg_param_begin,
284 arg_param_end
286 CLIExecWithReturn(ctx, Cmd, argtable, true);
287 CLIParserFree(ctx);
289 PrintAndLogEx(SUCCESS, "Watching for EM410x cards - place tag on Proxmark3 antenna");
290 clearCommandBuffer();
291 SendCommandNG(CMD_LF_EM410X_WATCH, NULL, 0);
292 return lfsim_wait_check(CMD_LF_EM410X_WATCH);
295 //by marshmellow
296 //takes 3 arguments - clock, invert and maxErr as integers
297 //attempts to demodulate ask while decoding manchester
298 //prints binary found and saves in graphbuffer for further commands
299 int demodEM410x(bool verbose) {
300 (void) verbose; // unused so far
301 uint32_t hi = 0;
302 uint64_t lo = 0;
303 return AskEm410xDemod(0, 0, 100, 0, false, &hi, &lo, true);
306 static int CmdEM410xDemod(const char *Cmd) {
307 CLIParserContext *ctx;
308 CLIParserInit(&ctx, "lf em 410x demod",
309 "Try to find EM 410x preamble, if found decode / descramble data",
310 "lf em 410x demod -> demod an EM410x Tag ID from GraphBuffer\n"
311 "lf em 410x demod --clk 32 -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/32\n"
312 "lf em 410x demod --clk 32 -i -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data\n"
313 "lf em 410x demod -i -> demod an EM410x Tag ID from GraphBuffer while inverting data\n"
314 "lf em 410x demod --clk 64 -i --err 0 -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors"
317 void *argtable[] = {
318 arg_param_begin,
319 arg_u64_0(NULL, "clk", "<dec>", "clock (default autodetect)"),
320 arg_u64_0(NULL, "err", "<dec>", "maximum allowed errors (default 100)"),
321 arg_u64_0(NULL, "len", "<dec>", "maximum length"),
322 arg_lit0("i", "invert", "invert output"),
323 arg_lit0("a", "amp", "amplify signal"),
324 arg_param_end
326 CLIExecWithReturn(ctx, Cmd, argtable, true);
328 int clk = arg_get_u32_def(ctx, 1, 0);
329 int max_err = arg_get_u32_def(ctx, 2, 100);
330 size_t max_len = arg_get_u32_def(ctx, 3, 0);
331 bool invert = arg_get_lit(ctx, 4);
332 bool amplify = arg_get_lit(ctx, 5);
333 CLIParserFree(ctx);
335 uint32_t hi = 0;
336 uint64_t lo = 0;
337 if (AskEm410xDemod(clk, invert, max_err, max_len, amplify, &hi, &lo, true) != PM3_SUCCESS)
338 return PM3_ESOFT;
340 return PM3_SUCCESS;
343 // this read is the "normal" read, which download lf signal and tries to demod here.
344 static int CmdEM410xReader(const char *Cmd) {
345 CLIParserContext *ctx;
346 CLIParserInit(&ctx, "lf em 410x reader",
347 "read EM 410x tag",
348 "lf em 410x reader -> reader\n"
349 "lf em 410x reader -@ -> continuous reader mode\n"
350 "lf em 410x reader --clk 32 -> reader using a clock of RF/32\n"
351 "lf em 410x reader --clk 32 -i -> reader using a clock of RF/32 and inverting data\n"
352 "lf em 410x reader -i -> reader while inverting data\n"
353 "lf em 410x reader --clk 64 -i --err 0 -> reader using a clock of RF/64 and inverting data and allowing 0 demod errors"
356 void *argtable[] = {
357 arg_param_begin,
358 arg_u64_0(NULL, "clk", "<dec>", "clock (default autodetect)"),
359 arg_u64_0(NULL, "err", "<dec>", "maximum allowed errors (default 100)"),
360 arg_u64_0(NULL, "len", "<dec>", "maximum length"),
361 arg_lit0("i", "invert", "invert output"),
362 arg_lit0("a", "amp", "amplify signal"),
363 arg_lit0("b", NULL, "break on first found"),
364 arg_lit0("@", NULL, "continuous reader mode"),
365 arg_lit0("v", "verbose", "verbose output"),
366 arg_param_end
368 CLIExecWithReturn(ctx, Cmd, argtable, true);
370 int clk = arg_get_u32_def(ctx, 1, 0);
371 int max_err = arg_get_u32_def(ctx, 2, 100);
372 size_t max_len = arg_get_u32_def(ctx, 3, 0);
373 bool invert = arg_get_lit(ctx, 4);
374 bool amplify = arg_get_lit(ctx, 5);
375 bool break_first = arg_get_lit(ctx, 6);
376 bool cm = arg_get_lit(ctx, 7);
377 bool verbose = arg_get_lit(ctx, 8);
378 CLIParserFree(ctx);
380 if (cm) {
381 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
384 do {
385 uint32_t hi = 0;
386 uint64_t lo = 0;
387 lf_read(false, 12288);
388 AskEm410xDemod(clk, invert, max_err, max_len, amplify, &hi, &lo, verbose);
390 if (break_first && g_em410xid != 0) {
391 break;
393 } while (cm && !kbd_enter_pressed());
395 return PM3_SUCCESS;
398 // emulate an EM410X tag
399 static int CmdEM410xSim(const char *Cmd) {
401 CLIParserContext *ctx;
402 CLIParserInit(&ctx, "lf em 410x sim",
403 "Enables simulation of EM 410x card.\n"
404 "Simulation runs until the button is pressed or another USB command is issued.",
405 "lf em 410x sim --id 0F0368568B\n"
406 "lf em 410x sim --id 0F0368568B --clk 32\n"
407 "lf em 410x sim --id 0F0368568B --gap 0"
410 void *argtable[] = {
411 arg_param_begin,
412 arg_u64_0(NULL, "clk", "<dec>", "<32|64> clock (default 64)"),
413 arg_str1(NULL, "id", "<hex>", "ID number (5 hex bytes)"),
414 arg_u64_0(NULL, "gap", "<dec>", "gap (0's) between ID repeats (default 20)"),
415 arg_param_end
417 CLIExecWithReturn(ctx, Cmd, argtable, false);
419 // clock is 64 in EM410x tags
420 int clk = arg_get_u32_def(ctx, 1, 64);
421 int uid_len = 0;
422 int gap = arg_get_u32_def(ctx, 3, 20);
423 uint8_t uid[5] = {0};
424 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
425 CLIParserFree(ctx);
427 if (uid_len != 5) {
428 PrintAndLogEx(FAILED, "UID must include 5 hex bytes (%u)", uid_len);
429 return PM3_EINVARG;
432 PrintAndLogEx(SUCCESS, "Starting simulating UID "_YELLOW_("%s")" clock: "_YELLOW_("%d"), sprint_hex_inrow(uid, sizeof(uid)), clk);
433 em410x_construct_emul_graph(uid, clk, gap);
434 CmdLFSim("");
435 return PM3_SUCCESS;
438 static int CmdEM410xBrute(const char *Cmd) {
439 CLIParserContext *ctx;
440 CLIParserInit(&ctx, "lf em 410x brute",
441 "bruteforcing by emulating EM 410x tag",
442 "lf em 410x brute -f ids.txt\n"
443 "lf em 410x brute -f ids.txt --clk 32\n"
444 "lf em 410x brute -f ids.txt --delay 3000\n"
445 "lf em 410x brute -f ids.txt --delay 3000 --clk 32\n"
448 void *argtable[] = {
449 arg_param_begin,
450 arg_u64_0(NULL, "clk", "<dec>", "<32|64> clock (default 64)"),
451 arg_u64_0(NULL, "delay", "<dec>", "pause delay in milliseconds between UIDs simulation (default 1000ms)"),
452 arg_str1("f", "file", "<hex>", "file with UIDs in HEX format, one per line"),
453 arg_u64_0(NULL, "gap", "<dec>", "gap (0's) between ID repeats (default 20)"),
454 arg_param_end
456 CLIExecWithReturn(ctx, Cmd, argtable, false);
458 // clock default 64 in EM410x
459 uint32_t clk = arg_get_u32_def(ctx, 1, 64);
460 int gap = arg_get_u32_def(ctx, 4, 20);
461 // default pause time: 1 second
462 uint32_t delay = arg_get_u32_def(ctx, 2, 1000);
464 int fnlen = 0;
465 char filename[FILE_PATH_SIZE] = {0};
466 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
467 CLIParserFree(ctx);
469 if (fnlen == 0) {
470 PrintAndLogEx(ERR, "Error: Please specify a filename");
471 return PM3_EINVARG;
474 uint32_t uidcnt = 0;
475 uint8_t stUidBlock = 20;
476 uint8_t *p = NULL;
477 uint8_t uid[5] = {0x00};
479 // open file
480 FILE *f = NULL;
481 if ((f = fopen(filename, "r")) == NULL) {
482 PrintAndLogEx(ERR, "Error: Could not open UIDs file ["_YELLOW_("%s")"]", filename);
483 return PM3_EFILE;
486 // allocate mem for file contents
487 uint8_t *uidblock = calloc(stUidBlock, 5);
488 if (uidblock == NULL) {
489 fclose(f);
490 PrintAndLogEx(ERR, "Error: can't allocate memory");
491 return PM3_EMALLOC;
494 // read file into memory
495 char buf[11];
497 while (fgets(buf, sizeof(buf), f)) {
498 if (strlen(buf) < 10 || buf[9] == '\n') continue;
499 while (fgetc(f) != '\n' && !feof(f)); //goto next line
501 //The line start with # is comment, skip
502 if (buf[0] == '#') continue;
504 if (param_gethex(buf, 0, uid, 10)) {
505 PrintAndLogEx(FAILED, "UIDs must include 10 HEX symbols");
506 free(uidblock);
507 fclose(f);
508 return PM3_ESOFT;
511 buf[10] = 0;
513 if (stUidBlock - uidcnt < 2) {
514 p = realloc(uidblock, 5 * (stUidBlock += 10));
515 if (!p) {
516 PrintAndLogEx(WARNING, "Cannot allocate memory for UIDs");
517 free(uidblock);
518 fclose(f);
519 return PM3_ESOFT;
521 uidblock = p;
523 memset(uidblock + 5 * uidcnt, 0, 5);
524 num_to_bytes(strtoll(buf, NULL, 16), 5, uidblock + 5 * uidcnt);
525 uidcnt++;
526 memset(buf, 0, sizeof(buf));
528 fclose(f);
530 if (uidcnt == 0) {
531 PrintAndLogEx(FAILED, "No UIDs found in file");
532 free(uidblock);
533 return PM3_ESOFT;
536 PrintAndLogEx(SUCCESS, "Loaded "_YELLOW_("%d")" UIDs from "_YELLOW_("%s")", pause delay:"_YELLOW_("%d")" ms", uidcnt, filename, delay);
538 // loop
539 uint8_t testuid[5];
540 for (uint32_t c = 0; c < uidcnt; ++c) {
541 if (kbd_enter_pressed()) {
542 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
543 PrintAndLogEx(WARNING, "aborted via keyboard!\n");
544 free(uidblock);
545 return PM3_EOPABORTED;
548 memcpy(testuid, uidblock + 5 * c, 5);
549 PrintAndLogEx(INFO, "Bruteforce %d / %u: simulating UID " _YELLOW_("%s")
550 , c + 1
551 , uidcnt
552 , sprint_hex_inrow(testuid, sizeof(testuid))
555 em410x_construct_emul_graph(testuid, clk, gap);
557 lfsim_upload_gb();
559 struct p {
560 uint16_t len;
561 uint16_t gap;
562 } PACKED payload;
563 payload.len = GraphTraceLen;
564 payload.gap = 0;
566 clearCommandBuffer();
567 SendCommandNG(CMD_LF_SIMULATE, (uint8_t *)&payload, sizeof(payload));
569 PacketResponseNG resp;
570 if (WaitForResponseTimeout(CMD_LF_SIMULATE, &resp, delay)) {
571 if (resp.status == PM3_EOPABORTED) {
572 PrintAndLogEx(INFO, "Button pressed, user aborted");
573 break;
577 free(uidblock);
578 return PM3_SUCCESS;
581 //currently only supports manchester modulations
582 static int CmdEM410xSpoof(const char *Cmd) {
583 CLIParserContext *ctx;
584 CLIParserInit(&ctx, "lf em 410x spoof",
585 "Watch 'nd Spoof, activates reader\n"
586 "Waits until a EM 410x tag gets presented then Proxmark3 starts simulating the found UID",
587 "lf em 410x spoof"
590 void *argtable[] = {
591 arg_param_begin,
592 arg_param_end
594 CLIExecWithReturn(ctx, Cmd, argtable, true);
595 CLIParserFree(ctx);
597 // loops if the captured ID was in XL-format.
598 g_em410xid = 0;
599 CmdEM410xReader("-b@");
600 PrintAndLogEx(SUCCESS, "Replaying captured ID "_YELLOW_("%010" PRIx64), g_em410xid);
601 CmdLFSim("");
602 return PM3_SUCCESS;
605 static int CmdEM410xClone(const char *Cmd) {
606 CLIParserContext *ctx;
607 CLIParserInit(&ctx, "lf em 410x clone",
608 "Writes EM410x ID to a T55x7 or Q5/T5555 tag",
609 "lf em 410x clone --id 0F0368568B -> write id to T55x7 tag\n"
610 "lf em 410x clone --id 0F0368568B --q5 -> write id to Q5/T5555 tag"
613 void *argtable[] = {
614 arg_param_begin,
615 arg_u64_0(NULL, "clk", "<dec>", "<16|32|40|64> clock (default 64)"),
616 arg_str1(NULL, "id", "<hex>", "ID number (5 hex bytes)"),
617 arg_lit0(NULL, "q5", "specify writing to Q5/T5555 tag"),
618 arg_param_end
620 CLIExecWithReturn(ctx, Cmd, argtable, false);
622 // clock default 64 in EM410x
623 uint32_t clk = arg_get_u32_def(ctx, 1, 64);
624 int uid_len = 0;
625 uint8_t uid[5] = {0};
626 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
627 bool q5 = arg_get_lit(ctx, 3);
628 CLIParserFree(ctx);
630 uint64_t id = bytes_to_num(uid, uid_len);
632 // Allowed clock rates: 16, 32, 40 and 64
633 if ((clk != 16) && (clk != 32) && (clk != 64) && (clk != 40)) {
634 PrintAndLogEx(FAILED, "supported clock rates are " _YELLOW_("16, 32, 40, 64") " got " _RED_("%d") "\n", clk);
635 return PM3_EINVARG;
638 char cardtype[16] = {"T55x7"};
639 if (q5) {
640 snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
643 PrintAndLogEx(SUCCESS, "Preparing to clone EM4102 to " _YELLOW_("%s") " tag with ID " _GREEN_("%010" PRIX64) " (RF/%d)", cardtype, id, clk);
644 // NOTE: We really should pass the clock in as a separate argument, but to
645 // provide for backwards-compatibility for older firmware, and to avoid
646 // having to add another argument to CMD_LF_EM410X_WRITE, we just store
647 // the clock rate in bits 8-15 of the card value
649 struct {
650 uint8_t card;
651 uint8_t clock;
652 uint32_t high;
653 uint32_t low;
654 } PACKED params;
656 params.card = (q5) ? 0 : 1;
657 params.clock = clk;
658 params.high = (uint32_t)(id >> 32);
659 params.low = (uint32_t)id;
661 clearCommandBuffer();
662 SendCommandNG(CMD_LF_EM410X_WRITE, (uint8_t *)&params, sizeof(params));
664 PacketResponseNG resp;
665 WaitForResponse(CMD_LF_EM410X_WRITE, &resp);
666 switch (resp.status) {
667 case PM3_SUCCESS: {
668 PrintAndLogEx(SUCCESS, "Done");
669 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 410x reader`") " to verify");
670 break;
672 default: {
673 PrintAndLogEx(WARNING, "Something went wrong");
674 break;
677 return resp.status;
680 static command_t CommandTable[] = {
681 {"help", CmdHelp, AlwaysAvailable, "This help"},
682 //{"demod", CmdEMdemodASK, IfPm3Lf, "Extract ID from EM410x tag on antenna)"},
683 {"demod", CmdEM410xDemod, AlwaysAvailable, "demodulate a EM410x tag from the GraphBuffer"},
684 {"reader", CmdEM410xReader, IfPm3Lf, "attempt to read and extract tag data"},
685 {"sim", CmdEM410xSim, IfPm3Lf, "simulate EM410x tag"},
686 {"brute", CmdEM410xBrute, IfPm3Lf, "reader bruteforce attack by simulating EM410x tags"},
687 {"watch", CmdEM410xWatch, IfPm3Lf, "watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
688 {"spoof", CmdEM410xSpoof, IfPm3Lf, "watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
689 {"clone", CmdEM410xClone, IfPm3Lf, "write EM410x UID to T55x7 or Q5/T5555 tag"},
690 {NULL, NULL, NULL, NULL}
693 static int CmdHelp(const char *Cmd) {
694 (void)Cmd; // Cmd is not used so far
695 CmdsHelp(CommandTable);
696 return PM3_SUCCESS;
699 int CmdLFEM410X(const char *Cmd) {
700 clearCommandBuffer();
701 return CmdsParse(CommandTable, Cmd);