1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
4 // modified marshmellow
5 // modified Iceman, 2020
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
10 //-----------------------------------------------------------------------------
11 // Low frequency EM4x commands
12 //-----------------------------------------------------------------------------
14 #include "cmdlfem410x.h"
15 #include "cmdlfem4x50.h"
21 #include "fileutils.h"
22 #include "cmdparser.h" // command_t
24 #include "commonutil.h"
26 #include "util_posix.h"
27 #include "protocols.h"
34 #include "generator.h"
35 #include "cliparser.h"
38 static uint64_t g_em410xid
= 0;
40 static int CmdHelp(const char *Cmd
);
41 /* Read the ID of an EM410x tag.
43 * 1111 1111 1 <-- standard non-repeatable header
44 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
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
) {
56 // write 16 zero bit sledge
57 for (uint8_t i
= 0; i
< gap
; i
++)
58 AppendGraph(false, clock
, 0);
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
++) {
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
)]);
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
)];
93 AppendGraph(false, clock
, parity
[0]);
94 AppendGraph(false, clock
, parity
[1]);
95 AppendGraph(false, clock
, parity
[2]);
96 AppendGraph(false, clock
, parity
[3]);
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;
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) {
119 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%06X%016" PRIX64
), hi
, id
);
121 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
), id
);
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
);
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};
166 for (int k
= 0 ; k
< 24; ++k
, --j
) {
167 arr
[k
] = (p1id
>> k
) & 1;
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.
212 * 1111 1111 1 <-- standard non-repeatable header
213 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
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
) {
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");
227 int ans
= Em410xDecode(bits
, &size
, &idx
, hi
, lo
);
231 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x not enough samples after demod");
233 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x preamble not found");
235 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x Size not correct: %zu", size
);
237 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x parity failed");
242 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x decoded to all zeros");
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
);
252 printDemodBuff(0, false, false, true);
255 printEM410x(*hi
, *lo
, verbose
);
260 int AskEm410xDemod(int clk
, int invert
, int maxErr
, size_t maxLen
, bool amplify
, uint32_t *hi
, uint64_t *lo
, bool verbose
) {
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
)
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.",
286 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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
);
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
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"
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"),
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);
337 if (AskEm410xDemod(clk
, invert
, max_err
, max_len
, amplify
, &hi
, &lo
, true) != 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",
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"
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"),
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);
381 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
387 lf_read(false, 12288);
388 AskEm410xDemod(clk
, invert
, max_err
, max_len
, amplify
, &hi
, &lo
, verbose
);
390 if (break_first
&& g_em410xid
!= 0) {
393 } while (cm
&& !kbd_enter_pressed());
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"
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)"),
417 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
419 // clock is 64 in EM410x tags
420 int clk
= arg_get_u32_def(ctx
, 1, 64);
422 int gap
= arg_get_u32_def(ctx
, 3, 20);
423 uint8_t uid
[5] = {0};
424 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
428 PrintAndLogEx(FAILED
, "UID must include 5 hex bytes (%u)", uid_len
);
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
);
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"
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)"),
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);
465 char filename
[FILE_PATH_SIZE
] = {0};
466 CLIParamStrToBuf(arg_get_str(ctx
, 3), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
470 PrintAndLogEx(ERR
, "Error: Please specify a filename");
475 uint8_t stUidBlock
= 20;
477 uint8_t uid
[5] = {0x00};
481 if ((f
= fopen(filename
, "r")) == NULL
) {
482 PrintAndLogEx(ERR
, "Error: Could not open UIDs file ["_YELLOW_("%s")"]", filename
);
486 // allocate mem for file contents
487 uint8_t *uidblock
= calloc(stUidBlock
, 5);
488 if (uidblock
== NULL
) {
490 PrintAndLogEx(ERR
, "Error: can't allocate memory");
494 // read file into memory
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");
513 if (stUidBlock
- uidcnt
< 2) {
514 p
= realloc(uidblock
, 5 * (stUidBlock
+= 10));
516 PrintAndLogEx(WARNING
, "Cannot allocate memory for UIDs");
523 memset(uidblock
+ 5 * uidcnt
, 0, 5);
524 num_to_bytes(strtoll(buf
, NULL
, 16), 5, uidblock
+ 5 * uidcnt
);
526 memset(buf
, 0, sizeof(buf
));
531 PrintAndLogEx(FAILED
, "No UIDs found in file");
536 PrintAndLogEx(SUCCESS
, "Loaded "_YELLOW_("%d")" UIDs from "_YELLOW_("%s")", pause delay:"_YELLOW_("%d")" ms", uidcnt
, filename
, delay
);
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");
545 return PM3_EOPABORTED
;
548 memcpy(testuid
, uidblock
+ 5 * c
, 5);
549 PrintAndLogEx(INFO
, "Bruteforce %d / %u: simulating UID " _YELLOW_("%s")
552 , sprint_hex_inrow(testuid
, sizeof(testuid
))
555 em410x_construct_emul_graph(testuid
, clk
, gap
);
563 payload
.len
= GraphTraceLen
;
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");
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",
594 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
597 // loops if the captured ID was in XL-format.
599 CmdEM410xReader("-b@");
600 PrintAndLogEx(SUCCESS
, "Replaying captured ID "_YELLOW_("%010" PRIx64
), g_em410xid
);
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"
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"),
620 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
622 // clock default 64 in EM410x
623 uint32_t clk
= arg_get_u32_def(ctx
, 1, 64);
625 uint8_t uid
[5] = {0};
626 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
627 bool q5
= arg_get_lit(ctx
, 3);
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
);
638 char cardtype
[16] = {"T55x7"};
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
656 params
.card
= (q5
) ? 0 : 1;
658 params
.high
= (uint32_t)(id
>> 32);
659 params
.low
= (uint32_t)id
;
661 clearCommandBuffer();
662 SendCommandNG(CMD_LF_EM410X_WRITE
, (uint8_t *)¶ms
, sizeof(params
));
664 PacketResponseNG resp
;
665 WaitForResponse(CMD_LF_EM410X_WRITE
, &resp
);
666 switch (resp
.status
) {
668 PrintAndLogEx(SUCCESS
, "Done");
669 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf em 410x reader`") " to verify");
673 PrintAndLogEx(WARNING
, "Something went wrong");
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
);
699 int CmdLFEM410X(const char *Cmd
) {
700 clearCommandBuffer();
701 return CmdsParse(CommandTable
, Cmd
);