1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Low frequency EM410x commands
17 //-----------------------------------------------------------------------------
19 #include "cmdlfem410x.h"
20 #include "cmdlfem4x50.h"
26 #include "fileutils.h"
27 #include "cmdparser.h" // command_t
29 #include "commonutil.h"
31 #include "util_posix.h"
32 #include "protocols.h"
39 #include "generator.h"
40 #include "cliparser.h"
44 static uint64_t gs_em410xid
= 0;
46 static int CmdHelp(const char *Cmd
);
47 /* Read the ID of an EM410x tag.
49 * 1111 1111 1 <-- standard non-repeatable header
50 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
52 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
53 * 0 <-- stop bit, end of tag
56 // Construct the graph for emulating an EM410X tag
57 static void em410x_construct_emul_graph(uint8_t *uid
, uint8_t clock
, uint8_t gap
) {
62 // write 16 zero bit sledge
63 for (uint8_t i
= 0; i
< gap
; i
++)
64 AppendGraph(false, clock
, 0);
67 for (uint8_t i
= 0; i
< 9; i
++)
68 AppendGraph(false, clock
, 1);
70 uint8_t bs
[8], parity
[8];
71 memset(parity
, 0, sizeof(parity
));
73 for (uint8_t i
= 0; i
< 5; i
++) {
75 for (uint8_t j
= 0; j
< 8; j
++) {
76 bs
[j
] = (uid
[i
] >> (7 - j
) & 1);
78 PrintAndLogEx(DEBUG
, "EM ID[%d] 0x%02x (%s)", i
, uid
[i
], sprint_bytebits_bin(bs
, 4));
80 for (uint8_t j
= 0; j
< 2; j
++) {
82 AppendGraph(false, clock
, bs
[0 + (4 * j
)]);
83 AppendGraph(false, clock
, bs
[1 + (4 * j
)]);
84 AppendGraph(false, clock
, bs
[2 + (4 * j
)]);
85 AppendGraph(false, clock
, bs
[3 + (4 * j
)]);
88 AppendGraph(false, clock
, bs
[0 + (4 * j
)] ^ bs
[1 + (4 * j
)] ^ bs
[2 + (4 * j
)] ^ bs
[3 + (4 * j
)]);
90 // keep track of column parity
91 parity
[0] ^= bs
[0 + (4 * j
)];
92 parity
[1] ^= bs
[1 + (4 * j
)];
93 parity
[2] ^= bs
[2 + (4 * j
)];
94 parity
[3] ^= bs
[3 + (4 * j
)];
99 AppendGraph(false, clock
, parity
[0]);
100 AppendGraph(false, clock
, parity
[1]);
101 AppendGraph(false, clock
, parity
[2]);
102 AppendGraph(false, clock
, parity
[3]);
105 AppendGraph(true, clock
, 0);
108 // print 64 bit EM410x ID in multiple formats
109 void printEM410x(uint32_t hi
, uint64_t id
, bool verbose
, int type
) {
111 if (verbose
== false) {
112 if (type
& 0x1) { // Short ID
113 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
), id
);
115 if (type
& 0x2) { // Long ID
116 PrintAndLogEx(SUCCESS
, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64
), hi
, id
);
118 if (type
& 0x4) { // Short Extended ID
119 uint64_t data
= (id
<< 20) >> 20;
120 // Convert back to Short ID
121 id
= ((uint64_t)hi
<< 16) | (id
>> 48);
122 if ((data
& 0xFFFFFFFF) == 0) {
123 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
)" Electra "_GREEN_("%03" PRIu64
), id
, data
>> 32);
125 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
)" on 128b frame with data "_GREEN_("%011" PRIX64
), id
, data
);
131 if (type
& 0x2) { // Long ID
132 //output 88 bit em id
133 PrintAndLogEx(SUCCESS
, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64
)" ( RF/%d )", hi
, id
, g_DemodClock
);
135 if (type
& 0x4) { // Short Extended ID
136 PrintAndLogEx(SUCCESS
, "EM 410x Short ID found on a 128b frame");
137 uint64_t data
= (id
<< 20) >> 20;
138 PrintAndLogEx(SUCCESS
, " Data after ID: "_GREEN_("%011" PRIX64
), data
);
139 if ((data
& 0xFFFFFFFF) == 0) {
140 PrintAndLogEx(SUCCESS
, " Possibly an Electra (RO), 0x"_GREEN_("%03" PRIX64
)" = "_GREEN_("%03" PRIu64
), data
>> 32, data
>> 32);
142 PrintAndLogEx(SUCCESS
, " Short ID details:");
143 // Convert back to Short ID
144 id
= ((uint64_t)hi
<< 16) | (id
>> 48);
146 if (type
& (0x4 | 0x1)) { // Short Extended or Short ID
147 //output 40 bit em id
151 for (m
= 5; m
> 0; m
--) {
152 for (i
= 0; i
< 8; i
++) {
153 id2lo
= (id2lo
<< 1LL) | ((id
& (n
<< (i
+ ((m
- 1) * 8)))) >> (i
+ ((m
- 1) * 8)));
156 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
), id
);
157 PrintAndLogEx(SUCCESS
, "EM410x ( RF/%d )", g_DemodClock
);
158 PrintAndLogEx(INFO
, "-------- " _CYAN_("Possible de-scramble patterns") " ---------");
159 PrintAndLogEx(SUCCESS
, "Unique TAG ID : %010" PRIX64
, id2lo
);
160 PrintAndLogEx(INFO
, "HoneyWell IdentKey");
161 PrintAndLogEx(SUCCESS
, " DEZ 8 : %08" PRIu64
, id
& 0xFFFFFF);
162 PrintAndLogEx(SUCCESS
, " DEZ 10 : %010" PRIu64
, id
& 0xFFFFFFFF);
163 PrintAndLogEx(SUCCESS
, " DEZ 5.5 : %05" PRIu64
".%05" PRIu64
, (id
>> 16LL) & 0xFFFF, (id
& 0xFFFF));
164 PrintAndLogEx(SUCCESS
, " DEZ 3.5A : %03" PRIu64
".%05" PRIu64
, (id
>> 32ll), (id
& 0xFFFF));
165 PrintAndLogEx(SUCCESS
, " DEZ 3.5B : %03" PRIu64
".%05" PRIu64
, (id
& 0xFF000000) >> 24, (id
& 0xFFFF));
166 PrintAndLogEx(SUCCESS
, " DEZ 3.5C : %03" PRIu64
".%05" PRIu64
, (id
& 0xFF0000) >> 16, (id
& 0xFFFF));
167 PrintAndLogEx(SUCCESS
, " DEZ 14/IK2 : %014" PRIu64
, id
);
168 PrintAndLogEx(SUCCESS
, " DEZ 15/IK3 : %015" PRIu64
, id2lo
);
169 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
,
170 (id2lo
& 0xf000000000) >> 36,
171 (id2lo
& 0x0f00000000) >> 32,
172 (id2lo
& 0x00f0000000) >> 28,
173 (id2lo
& 0x000f000000) >> 24,
174 (id2lo
& 0x0000f00000) >> 20,
175 (id2lo
& 0x00000f0000) >> 16,
176 (id2lo
& 0x000000f000) >> 12,
177 (id2lo
& 0x0000000f00) >> 8,
178 (id2lo
& 0x00000000f0) >> 4,
179 (id2lo
& 0x000000000f)
181 PrintAndLogEx(INFO
, "");
183 uint64_t paxton
= (((id
>> 32) << 24) | (id
& 0xffffff)) + 0x143e00;
184 PrintAndLogEx(SUCCESS
, "Other : %05" PRIu64
"_%03" PRIu64
"_%08" PRIu64
, (id
& 0xFFFF), ((id
>> 16LL) & 0xFF), (id
& 0xFFFFFF));
185 PrintAndLogEx(SUCCESS
, "Pattern Paxton : %" PRIu64
" [0x%" PRIX64
"]", paxton
, paxton
);
187 uint32_t p1id
= (id
& 0xFFFFFF);
188 uint8_t arr
[32] = {0x00};
190 for (int k
= 0 ; k
< 24; ++k
, --j
) {
191 arr
[k
] = (p1id
>> k
) & 1;
225 PrintAndLogEx(SUCCESS
, "Pattern 1 : %d [0x%X]", p1
, p1
);
227 uint16_t sebury1
= id
& 0xFFFF;
228 uint8_t sebury2
= (id
>> 16) & 0x7F;
229 uint32_t sebury3
= id
& 0x7FFFFF;
230 PrintAndLogEx(SUCCESS
, "Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1
, sebury2
, sebury3
, sebury1
, sebury2
, sebury3
);
231 PrintAndLogEx(SUCCESS
, "VD / ID : %03" PRIu64
" / %010" PRIu64
, (id
>> 32LL) & 0xFFFF, (id
& 0xFFFFFFFF));
232 PrintAndLogEx(SUCCESS
, "Pattern ELECTRA : %" PRIu64
" %" PRIu64
, (id
>> 24) & 0xFFFF, id
& 0xFFFFFF);
234 PrintAndLogEx(INFO
, "------------------------------------------------");
238 // takes 1s and 0s and searches for EM410x format - output EM ID
239 static int ask_em410x_binary_decode(bool verbose
, uint32_t *hi
, uint64_t *lo
, uint8_t *bits
, size_t *size
, size_t *idx
) {
241 int ans
= Em410xDecode(bits
, size
, idx
, hi
, lo
);
244 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x not enough samples after demod");
246 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x preamble not found");
248 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x Size not correct: %zu", size
);
250 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x parity failed");
255 PrintAndLogEx(DEBUG
, "DEBUG: Em410x idx: %zu, Len: %zu, Printing DemodBuffer:", *idx
, *size
);
257 printDemodBuff(0, false, false, true);
260 printEM410x(*hi
, *lo
, verbose
, ans
);
265 /* Read the ID of an EM410x tag.
267 * 1111 1111 1 <-- standard non-repeatable header
268 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
270 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
271 * 0 <-- stop bit, end of tag
273 int AskEm410xDecode(bool verbose
, uint32_t *hi
, uint64_t *lo
) {
275 uint8_t bits
[512] = {0};
276 size_t size
= sizeof(bits
);
277 if (getDemodBuff(bits
, &size
) == false) {
278 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x problem during copy from ASK demod");
282 int ret
= ask_em410x_binary_decode(verbose
, hi
, lo
, bits
, &size
, &idx
);
284 if (ret
== PM3_SUCCESS
) {
285 // set g_GraphBuffer for clone or sim command
286 setDemodBuff(g_DemodBuffer
, (size
== 40) ? 64 : 128, idx
+ 1);
287 setClockGrid(g_DemodClock
, g_DemodStartIdx
+ ((idx
+ 1)*g_DemodClock
));
292 int AskEm410xDemod(int clk
, int invert
, int maxErr
, size_t maxLen
, bool amplify
, uint32_t *hi
, uint64_t *lo
, bool verbose
) {
295 // em410x simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
296 if (isGraphBitstream()) {
297 convertGraphFromBitstream();
299 if (ASKDemod_ext(clk
, invert
, maxErr
, maxLen
, amplify
, false, false, 1, &st
) != PM3_SUCCESS
) {
302 return AskEm410xDecode(verbose
, hi
, lo
);
305 // this read loops on device side.
306 // uses the demod in lfops.c
307 static int CmdEM410xWatch(const char *Cmd
) {
308 CLIParserContext
*ctx
;
309 CLIParserInit(&ctx
, "lf em 410x watch",
310 "Enables Electro Marine (EM) compatible reader mode printing details of scanned tags.\n"
311 "Run until the button is pressed or another USB command is issued.",
319 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
322 PrintAndLogEx(SUCCESS
, "Watching for EM410x cards - place tag on Proxmark3 antenna");
323 clearCommandBuffer();
324 SendCommandNG(CMD_LF_EM410X_WATCH
, NULL
, 0);
325 return lfsim_wait_check(CMD_LF_EM410X_WATCH
);
329 //takes 3 arguments - clock, invert and maxErr as integers
330 //attempts to demodulate ask while decoding manchester
331 //prints binary found and saves in graphbuffer for further commands
332 int demodEM410x(bool verbose
) {
333 (void) verbose
; // unused so far
336 return AskEm410xDemod(0, 0, 100, 0, false, &hi
, &lo
, true);
339 static int CmdEM410xDemod(const char *Cmd
) {
340 CLIParserContext
*ctx
;
341 CLIParserInit(&ctx
, "lf em 410x demod",
342 "Try to find EM 410x preamble, if found decode / descramble data",
343 "lf em 410x demod -> demod an EM410x Tag ID from GraphBuffer\n"
344 "lf em 410x demod --clk 32 -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/32\n"
345 "lf em 410x demod --clk 32 -i -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data\n"
346 "lf em 410x demod -i -> demod an EM410x Tag ID from GraphBuffer while inverting data\n"
347 "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"
352 arg_u64_0(NULL
, "clk", "<dec>", "clock (default autodetect)"),
353 arg_u64_0(NULL
, "err", "<dec>", "maximum allowed errors (default 100)"),
354 arg_u64_0(NULL
, "len", "<dec>", "maximum length"),
355 arg_lit0("i", "invert", "invert output"),
356 arg_lit0("a", "amp", "amplify signal"),
357 arg_str0(NULL
, "bin", "<bin>", "Binary string i.e 0001001001"),
360 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
362 int clk
= arg_get_u32_def(ctx
, 1, 0);
363 int max_err
= arg_get_u32_def(ctx
, 2, 100);
364 size_t max_len
= arg_get_u32_def(ctx
, 3, 0);
365 bool invert
= arg_get_lit(ctx
, 4);
366 bool amplify
= arg_get_lit(ctx
, 5);
368 uint8_t bin
[512] = {0};
369 CLIGetStrWithReturn(ctx
, 6, bin
, &bin_len
);
376 // 111111111011110010010100001110010101001101110001100100000010010011111100001111
377 size_t demodlen
= bin_len
;
378 size_t start_idx
= 0;
380 binstr_2_binarray(arr
, (char *)bin
, bin_len
);
381 return ask_em410x_binary_decode(true, &hi
, &lo
, arr
, &demodlen
, &start_idx
);
384 if (AskEm410xDemod(clk
, invert
, max_err
, max_len
, amplify
, &hi
, &lo
, true) != PM3_SUCCESS
) {
391 // this read is the "normal" read, which download lf signal and tries to demod here.
392 static int CmdEM410xReader(const char *Cmd
) {
393 CLIParserContext
*ctx
;
394 CLIParserInit(&ctx
, "lf em 410x reader",
396 "lf em 410x reader\n"
397 "lf em 410x reader -@ -> continuous reader mode\n"
398 "lf em 410x reader --clk 32 -> using a clock of RF/32\n"
399 "lf em 410x reader --clk 32 -i -> using a clock of RF/32 and inverting data\n"
400 "lf em 410x reader -i -> inverting data\n"
401 "lf em 410x reader --clk 64 -i --err 0 -> using a clock of RF/64 and inverting data and allowing 0 demod errors"
406 arg_u64_0(NULL
, "clk", "<dec>", "clock (default autodetect)"),
407 arg_u64_0(NULL
, "err", "<dec>", "maximum allowed errors (default 100)"),
408 arg_u64_0(NULL
, "len", "<dec>", "maximum length"),
409 arg_lit0("i", "invert", "invert output"),
410 arg_lit0("a", "amp", "amplify signal"),
411 arg_lit0("b", NULL
, "break on first found"),
412 arg_lit0("@", NULL
, "continuous reader mode"),
413 arg_lit0("v", "verbose", "verbose output"),
416 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
418 int clk
= arg_get_u32_def(ctx
, 1, 0);
419 int max_err
= arg_get_u32_def(ctx
, 2, 100);
420 size_t max_len
= arg_get_u32_def(ctx
, 3, 0);
421 bool invert
= arg_get_lit(ctx
, 4);
422 bool amplify
= arg_get_lit(ctx
, 5);
423 bool break_first
= arg_get_lit(ctx
, 6);
424 bool cm
= arg_get_lit(ctx
, 7);
425 bool verbose
= arg_get_lit(ctx
, 8);
429 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
435 lf_read(false, 12288);
436 AskEm410xDemod(clk
, invert
, max_err
, max_len
, amplify
, &hi
, &lo
, verbose
);
438 if (break_first
&& gs_em410xid
!= 0) {
441 } while (cm
&& !kbd_enter_pressed());
446 // emulate an EM410X tag
447 static int CmdEM410xSim(const char *Cmd
) {
449 CLIParserContext
*ctx
;
450 CLIParserInit(&ctx
, "lf em 410x sim",
451 "Enables simulation of EM 410x card.\n"
452 "Simulation runs until the button is pressed or another USB command is issued.",
453 "lf em 410x sim --id 0F0368568B\n"
454 "lf em 410x sim --id 0F0368568B --clk 32\n"
455 "lf em 410x sim --id 0F0368568B --gap 0"
460 arg_u64_0(NULL
, "clk", "<dec>", "<32|64> clock (default 64)"),
461 arg_str1(NULL
, "id", "<hex>", "EM Tag ID number (5 hex bytes)"),
462 arg_u64_0(NULL
, "gap", "<dec>", "gap (0's) between ID repeats (default 20)"),
465 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
467 // clock is 64 in EM410x tags
468 int clk
= arg_get_u32_def(ctx
, 1, 64);
470 int gap
= arg_get_u32_def(ctx
, 3, 20);
471 uint8_t uid
[5] = {0};
472 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
476 PrintAndLogEx(FAILED
, "EM ID must include 5 hex bytes (10 hex symbols), got " _YELLOW_("%u"), uid_len
);
480 PrintAndLogEx(SUCCESS
, "Starting simulating EM Tag ID "_YELLOW_("%s")" clock: "_YELLOW_("%d"), sprint_hex_inrow(uid
, sizeof(uid
)), clk
);
481 em410x_construct_emul_graph(uid
, clk
, gap
);
486 static int CmdEM410xBrute(const char *Cmd
) {
487 CLIParserContext
*ctx
;
488 CLIParserInit(&ctx
, "lf em 410x brute",
489 "bruteforcing by emulating EM 410x tag",
490 "lf em 410x brute -f ids.txt\n"
491 "lf em 410x brute -f ids.txt --clk 32\n"
492 "lf em 410x brute -f ids.txt --delay 3000\n"
493 "lf em 410x brute -f ids.txt --delay 3000 --clk 32\n"
498 arg_u64_0(NULL
, "clk", "<dec>", "<32|64> clock (default 64)"),
499 arg_u64_0(NULL
, "delay", "<dec>", "pause delay in milliseconds between UIDs simulation (default 1000ms)"),
500 arg_str1("f", "file", "<hex>", "file with EM Tag IDs, one id per line"),
501 arg_u64_0(NULL
, "gap", "<dec>", "gap (0's) between ID repeats (default 20)"),
504 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
506 // clock default 64 in EM410x
507 uint32_t clk
= arg_get_u32_def(ctx
, 1, 64);
508 int gap
= arg_get_u32_def(ctx
, 4, 20);
509 // default pause time: 1 second
510 uint32_t delay
= arg_get_u32_def(ctx
, 2, 1000);
513 char filename
[FILE_PATH_SIZE
] = {0};
514 CLIParamStrToBuf(arg_get_str(ctx
, 3), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
518 PrintAndLogEx(ERR
, "Error: Please specify a filename");
523 char suffix
[10] = {0};
524 char *ext
= strrchr(filename
, '.');
526 strncpy(suffix
, ext
, sizeof(suffix
) - 1);
530 uint8_t *uidblock
= NULL
;
531 uint32_t uidcount
= 0;
532 int res
= loadFileDICTIONARY_safe_ex(filename
, suffix
, (void **)&uidblock
, 5, &uidcount
, false);
533 if (res
!= PM3_SUCCESS
) {
539 PrintAndLogEx(FAILED
, "No EM Tag IDs found in file");
544 PrintAndLogEx(SUCCESS
, "Loaded "_GREEN_("%d")" EM Tag IDs from `"_YELLOW_("%s")"` pause delay:"_YELLOW_("%d")" ms", uidcount
, filename
, delay
);
548 for (uint32_t i
= 0; i
< uidcount
; ++i
) {
550 if (kbd_enter_pressed()) {
551 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
552 PrintAndLogEx(WARNING
, "aborted via keyboard!\n");
554 return PM3_EOPABORTED
;
557 memset(testuid
, 0, sizeof(testuid
));
558 memcpy(testuid
, uidblock
+ (5 * i
), sizeof(testuid
));
560 PrintAndLogEx(INFO
, "Bruteforce %d / %u: simulating EM Tag ID " _YELLOW_("%s")
563 , sprint_hex_inrow(testuid
, sizeof(testuid
))
566 em410x_construct_emul_graph(testuid
, clk
, gap
);
574 payload
.len
= g_GraphTraceLen
;
577 clearCommandBuffer();
578 SendCommandNG(CMD_LF_SIMULATE
, (uint8_t *)&payload
, sizeof(payload
));
579 PacketResponseNG resp
;
580 if (WaitForResponseTimeout(CMD_LF_SIMULATE
, &resp
, delay
)) {
581 if (resp
.status
== PM3_EOPABORTED
) {
582 PrintAndLogEx(INFO
, "Button pressed, user aborted");
591 //currently only supports manchester modulations
592 static int CmdEM410xSpoof(const char *Cmd
) {
593 CLIParserContext
*ctx
;
594 CLIParserInit(&ctx
, "lf em 410x spoof",
595 "Watch 'nd Spoof, activates reader\n"
596 "Waits until a EM 410x tag gets presented then Proxmark3 starts simulating the found EM Tag ID",
604 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
607 // loops if the captured ID was in XL-format.
609 CmdEM410xReader("-b@");
610 PrintAndLogEx(SUCCESS
, "Replaying captured EM Tag ID "_YELLOW_("%010" PRIx64
), gs_em410xid
);
615 static int CmdEM410xClone(const char *Cmd
) {
616 CLIParserContext
*ctx
;
617 CLIParserInit(&ctx
, "lf em 410x clone",
618 "clone a EM410x ID to a T55x7, Q5/T5555, EM4305/4469 or Hitag S/8211/8268/8310 tag.",
619 "lf em 410x clone --id 0F0368568B -> encode for T55x7 tag\n"
620 "lf em 410x clone --id 0F0368568B --q5 -> encode for Q5/T5555 tag\n"
621 "lf em 410x clone --id 0F0368568B --em -> encode for EM4305/4469\n"
622 "lf em 410x clone --id 0F0368568B --hts -> encode for Hitag S/8211/8268/8310"
627 arg_u64_0(NULL
, "clk", "<dec>", "<16|32|40|64> clock (default 64)"),
628 arg_str1(NULL
, "id", "<hex>", "EM Tag ID number (5 hex bytes)"),
629 arg_lit0(NULL
, "q5", "optional - specify writing to Q5/T5555 tag"),
630 arg_lit0(NULL
, "em", "optional - specify writing to EM4305/4469 tag"),
631 arg_lit0(NULL
, "hts", "optional - specify writing to Hitag S/8211/8268/8310 tag"),
632 arg_lit0(NULL
, "electra", "optional - add Electra blocks to tag"),
635 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
637 // clock default 64 in EM410x
638 uint32_t clk
= arg_get_u32_def(ctx
, 1, 64);
640 uint8_t uid
[5] = {0};
641 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
642 bool q5
= arg_get_lit(ctx
, 3);
643 bool em
= arg_get_lit(ctx
, 4);
644 bool hts
= arg_get_lit(ctx
, 5);
645 bool add_electra
= arg_get_lit(ctx
, 6);
648 if (q5
+ em
+ hts
> 1) {
649 PrintAndLogEx(FAILED
, "Only specify one tag Type");
654 if (IfPm3Hitag() == false) {
655 PrintAndLogEx(FAILED
, "Device not compiled to support Hitag");
659 PrintAndLogEx(FAILED
, "supported clock rates for Hitag are " _YELLOW_("16, 32, 64"));
664 // Allowed clock rates: 16, 32, 40 and 64
665 if ((clk
!= 16) && (clk
!= 32) && (clk
!= 64) && (clk
!= 40)) {
666 PrintAndLogEx(FAILED
, "supported clock rates are " _YELLOW_("16, 32, 40, 64") " got " _RED_("%d") "\n", clk
);
670 uint64_t id
= bytes_to_num(uid
, uid_len
);
671 PrintAndLogEx(SUCCESS
, "Preparing to clone EM4102 to " _YELLOW_("%s") " tag with EM Tag ID " _GREEN_("%010" PRIX64
) " (RF/%d)",
672 q5
? "Q5/T5555" : (em
? "EM4305/4469" : (hts
? "Hitag S/82xx" : "T55x7")), id
, clk
);
674 uint8_t data
[HITAG_BLOCK_SIZE
* 2] = {0xFF, 0x80}; // EM410X_HEADER 9 bits of one
675 uint32_t databits
= 9;
676 uint8_t c_parity
= 0;
678 for (int i
= 36; i
>= 0; i
-= 4) {
679 uint8_t r_parity
= 0;
680 uint8_t nibble
= id
>> i
& 0xF;
682 databits
= concatbits(data
, databits
, &nibble
, 4, 4);
683 for (size_t j
= 0; j
< 4; j
++) {
684 r_parity
^= nibble
>> j
& 1;
686 databits
= concatbits(data
, databits
, &r_parity
, 7, 1);
689 data
[7] |= c_parity
<< 1;
691 PrintAndLogEx(INFO
, "Encoded to %s", sprint_hex(data
, sizeof(data
)));
693 clearCommandBuffer();
694 PacketResponseNG resp
;
697 lf_hitag_data_t packet
;
698 memset(&packet
, 0, sizeof(packet
));
700 for (size_t steps
= 0; steps
< 3; steps
++) {
703 packet
.data
[0] = 0xCA; //compatiable for 82xx, no impact on Hitag S
704 // clk -> TTFDR1 TTFDR0
705 // 32 -> 0x00 4 kBit/s
706 // 16 -> 0x10 8 kBit/s
707 // 64 -> 0x20 2 kBit/s
708 packet
.data
[1] = 0x04;
713 packet
.data
[1] |= 0x10;
716 packet
.data
[1] |= 0x20;
720 packet
.data
[3] = 0; //TODO: keep PWDH0?
724 memcpy(packet
.data
, &data
[HITAG_BLOCK_SIZE
* 0], HITAG_BLOCK_SIZE
);
728 memcpy(packet
.data
, &data
[HITAG_BLOCK_SIZE
* 1], HITAG_BLOCK_SIZE
);
733 packet
.cmd
= HTSF_82xx
;
734 memcpy(packet
.pwd
, "\xBB\xDD\x33\x99", HITAGS_PAGE_SIZE
);
735 SendCommandNG(CMD_LF_HITAGS_WRITE
, (uint8_t *)&packet
, sizeof(packet
));
736 if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE
, &resp
, 4000) == false) {
737 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
740 if (resp
.status
!= PM3_SUCCESS
) {
741 PrintAndLogEx(WARNING
, "Something went wrong");
757 payload
.add_electra
= add_electra
;
759 payload
.high
= (uint32_t)(id
>> 32);
760 payload
.low
= (uint32_t)id
;
762 SendCommandNG(CMD_LF_EM410X_CLONE
, (uint8_t *)&payload
, sizeof(payload
));
763 if (WaitForResponseTimeout(CMD_LF_EM410X_CLONE
, &resp
, 2000) == false) {
764 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
769 switch (resp
.status
) {
771 PrintAndLogEx(SUCCESS
, "Done!");
772 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf em 410x reader`") " to verify");
776 PrintAndLogEx(WARNING
, "Something went wrong");
783 static command_t CommandTable
[] = {
784 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
785 //{"demod", CmdEMdemodASK, IfPm3Lf, "Extract ID from EM410x tag on antenna)"},
786 {"demod", CmdEM410xDemod
, AlwaysAvailable
, "demodulate a EM410x tag from the GraphBuffer"},
787 {"reader", CmdEM410xReader
, IfPm3Lf
, "attempt to read and extract tag data"},
788 {"sim", CmdEM410xSim
, IfPm3Lf
, "simulate EM410x tag"},
789 {"brute", CmdEM410xBrute
, IfPm3Lf
, "reader bruteforce attack by simulating EM410x tags"},
790 {"watch", CmdEM410xWatch
, IfPm3Lf
, "watches for EM410x 125/134 kHz tags"},
791 {"spoof", CmdEM410xSpoof
, IfPm3Lf
, "watches for EM410x 125/134 kHz tags, and replays them" },
792 {"clone", CmdEM410xClone
, IfPm3Lf
, "clone EM410x Tag ID to T55x7, Q5/T5555 or EM4305/4469"},
793 {NULL
, NULL
, NULL
, NULL
}
796 static int CmdHelp(const char *Cmd
) {
797 (void)Cmd
; // Cmd is not used so far
798 CmdsHelp(CommandTable
);
802 int CmdLFEM410X(const char *Cmd
) {
803 clearCommandBuffer();
804 return CmdsParse(CommandTable
, Cmd
);