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 (!id
&& !hi
) return;
113 if (verbose
== false) {
114 if (type
& 0x1) { // Short ID
115 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
), id
);
117 if (type
& 0x2) { // Long ID
118 PrintAndLogEx(SUCCESS
, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64
), hi
, id
);
120 if (type
& 0x4) { // Short Extended ID
121 uint64_t data
= (id
<< 20) >> 20;
122 // Convert back to Short ID
123 id
= ((uint64_t)hi
<< 16) | (id
>> 48);
124 if ((data
& 0xFFFFFFFF) == 0) {
125 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
)" Electra "_GREEN_("%03" PRIu64
), id
, data
>> 32);
127 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
)" on 128b frame with data "_GREEN_("%011" PRIX64
), id
, data
);
133 if (type
& 0x2) { // Long ID
134 //output 88 bit em id
135 PrintAndLogEx(SUCCESS
, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64
)" ( RF/%d )", hi
, id
, g_DemodClock
);
137 if (type
& 0x4) { // Short Extended ID
138 PrintAndLogEx(SUCCESS
, "EM 410x Short ID found on a 128b frame");
139 uint64_t data
= (id
<< 20) >> 20;
140 PrintAndLogEx(SUCCESS
, " Data after ID: "_GREEN_("%011" PRIX64
), data
);
141 if ((data
& 0xFFFFFFFF) == 0) {
142 PrintAndLogEx(SUCCESS
, " Possibly an Electra (RO), 0x"_GREEN_("%03" PRIX64
)" = "_GREEN_("%03" PRIu64
), data
>> 32, data
>> 32);
144 PrintAndLogEx(SUCCESS
, " Short ID details:");
145 // Convert back to Short ID
146 id
= ((uint64_t)hi
<< 16) | (id
>> 48);
148 if (type
& (0x4 | 0x1)) { // Short Extended or Short ID
149 //output 40 bit em id
153 for (m
= 5; m
> 0; m
--) {
154 for (i
= 0; i
< 8; i
++) {
155 id2lo
= (id2lo
<< 1LL) | ((id
& (n
<< (i
+ ((m
- 1) * 8)))) >> (i
+ ((m
- 1) * 8)));
158 PrintAndLogEx(SUCCESS
, "EM 410x ID "_GREEN_("%010" PRIX64
), id
);
159 PrintAndLogEx(SUCCESS
, "EM410x ( RF/%d )", g_DemodClock
);
160 PrintAndLogEx(INFO
, "-------- " _CYAN_("Possible de-scramble patterns") " ---------");
161 PrintAndLogEx(SUCCESS
, "Unique TAG ID : %010" PRIX64
, id2lo
);
162 PrintAndLogEx(INFO
, "HoneyWell IdentKey");
163 PrintAndLogEx(SUCCESS
, " DEZ 8 : %08" PRIu64
, id
& 0xFFFFFF);
164 PrintAndLogEx(SUCCESS
, " DEZ 10 : %010" PRIu64
, id
& 0xFFFFFFFF);
165 PrintAndLogEx(SUCCESS
, " DEZ 5.5 : %05" PRIu64
".%05" PRIu64
, (id
>> 16LL) & 0xFFFF, (id
& 0xFFFF));
166 PrintAndLogEx(SUCCESS
, " DEZ 3.5A : %03" PRIu64
".%05" PRIu64
, (id
>> 32ll), (id
& 0xFFFF));
167 PrintAndLogEx(SUCCESS
, " DEZ 3.5B : %03" PRIu64
".%05" PRIu64
, (id
& 0xFF000000) >> 24, (id
& 0xFFFF));
168 PrintAndLogEx(SUCCESS
, " DEZ 3.5C : %03" PRIu64
".%05" PRIu64
, (id
& 0xFF0000) >> 16, (id
& 0xFFFF));
169 PrintAndLogEx(SUCCESS
, " DEZ 14/IK2 : %014" PRIu64
, id
);
170 PrintAndLogEx(SUCCESS
, " DEZ 15/IK3 : %015" PRIu64
, id2lo
);
171 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
,
172 (id2lo
& 0xf000000000) >> 36,
173 (id2lo
& 0x0f00000000) >> 32,
174 (id2lo
& 0x00f0000000) >> 28,
175 (id2lo
& 0x000f000000) >> 24,
176 (id2lo
& 0x0000f00000) >> 20,
177 (id2lo
& 0x00000f0000) >> 16,
178 (id2lo
& 0x000000f000) >> 12,
179 (id2lo
& 0x0000000f00) >> 8,
180 (id2lo
& 0x00000000f0) >> 4,
181 (id2lo
& 0x000000000f)
183 PrintAndLogEx(INFO
, "");
185 uint64_t paxton
= (((id
>> 32) << 24) | (id
& 0xffffff)) + 0x143e00;
186 PrintAndLogEx(SUCCESS
, "Other : %05" PRIu64
"_%03" PRIu64
"_%08" PRIu64
, (id
& 0xFFFF), ((id
>> 16LL) & 0xFF), (id
& 0xFFFFFF));
187 PrintAndLogEx(SUCCESS
, "Pattern Paxton : %" PRIu64
" [0x%" PRIX64
"]", paxton
, paxton
);
189 uint32_t p1id
= (id
& 0xFFFFFF);
190 uint8_t arr
[32] = {0x00};
192 for (int k
= 0 ; k
< 24; ++k
, --j
) {
193 arr
[k
] = (p1id
>> k
) & 1;
227 PrintAndLogEx(SUCCESS
, "Pattern 1 : %d [0x%X]", p1
, p1
);
229 uint16_t sebury1
= id
& 0xFFFF;
230 uint8_t sebury2
= (id
>> 16) & 0x7F;
231 uint32_t sebury3
= id
& 0x7FFFFF;
232 PrintAndLogEx(SUCCESS
, "Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1
, sebury2
, sebury3
, sebury1
, sebury2
, sebury3
);
233 PrintAndLogEx(SUCCESS
, "VD / ID : %03" PRIu64
" / %010" PRIu64
, (id
>> 32LL) & 0xFFFF, (id
& 0xFFFFFFFF));
234 PrintAndLogEx(SUCCESS
, "Pattern ELECTRA : %" PRIu64
" %" PRIu64
, (id
>> 24) & 0xFFFF, id
& 0xFFFFFF);
236 PrintAndLogEx(INFO
, "------------------------------------------------");
240 // takes 1s and 0s and searches for EM410x format - output EM ID
241 static int ask_em410x_binary_decode(bool verbose
, uint32_t *hi
, uint64_t *lo
, uint8_t *bits
, size_t *size
, size_t *idx
) {
243 int ans
= Em410xDecode(bits
, size
, idx
, hi
, lo
);
246 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x not enough samples after demod");
248 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x preamble not found");
250 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x Size not correct: %zu", size
);
252 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x parity failed");
258 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x decoded to all zeros");
262 PrintAndLogEx(DEBUG
, "DEBUG: Em410x idx: %zu, Len: %zu, Printing DemodBuffer:", *idx
, *size
);
264 printDemodBuff(0, false, false, true);
267 printEM410x(*hi
, *lo
, verbose
, ans
);
272 /* Read the ID of an EM410x tag.
274 * 1111 1111 1 <-- standard non-repeatable header
275 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
277 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
278 * 0 <-- stop bit, end of tag
280 int AskEm410xDecode(bool verbose
, uint32_t *hi
, uint64_t *lo
) {
282 uint8_t bits
[512] = {0};
283 size_t size
= sizeof(bits
);
284 if (getDemodBuff(bits
, &size
) == false) {
285 PrintAndLogEx(DEBUG
, "DEBUG: Error - Em410x problem during copy from ASK demod");
289 int ret
= ask_em410x_binary_decode(verbose
, hi
, lo
, bits
, &size
, &idx
);
291 if (ret
== PM3_SUCCESS
) {
292 // set g_GraphBuffer for clone or sim command
293 setDemodBuff(g_DemodBuffer
, (size
== 40) ? 64 : 128, idx
+ 1);
294 setClockGrid(g_DemodClock
, g_DemodStartIdx
+ ((idx
+ 1)*g_DemodClock
));
299 int AskEm410xDemod(int clk
, int invert
, int maxErr
, size_t maxLen
, bool amplify
, uint32_t *hi
, uint64_t *lo
, bool verbose
) {
302 // em410x simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
303 if (isGraphBitstream()) {
304 convertGraphFromBitstream();
306 if (ASKDemod_ext(clk
, invert
, maxErr
, maxLen
, amplify
, false, false, 1, &st
) != PM3_SUCCESS
) {
309 return AskEm410xDecode(verbose
, hi
, lo
);
312 // this read loops on device side.
313 // uses the demod in lfops.c
314 static int CmdEM410xWatch(const char *Cmd
) {
315 CLIParserContext
*ctx
;
316 CLIParserInit(&ctx
, "lf em 410x watch",
317 "Enables Electro Marine (EM) compatible reader mode printing details of scanned tags.\n"
318 "Run until the button is pressed or another USB command is issued.",
326 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
329 PrintAndLogEx(SUCCESS
, "Watching for EM410x cards - place tag on Proxmark3 antenna");
330 clearCommandBuffer();
331 SendCommandNG(CMD_LF_EM410X_WATCH
, NULL
, 0);
332 return lfsim_wait_check(CMD_LF_EM410X_WATCH
);
336 //takes 3 arguments - clock, invert and maxErr as integers
337 //attempts to demodulate ask while decoding manchester
338 //prints binary found and saves in graphbuffer for further commands
339 int demodEM410x(bool verbose
) {
340 (void) verbose
; // unused so far
343 return AskEm410xDemod(0, 0, 100, 0, false, &hi
, &lo
, true);
346 static int CmdEM410xDemod(const char *Cmd
) {
347 CLIParserContext
*ctx
;
348 CLIParserInit(&ctx
, "lf em 410x demod",
349 "Try to find EM 410x preamble, if found decode / descramble data",
350 "lf em 410x demod -> demod an EM410x Tag ID from GraphBuffer\n"
351 "lf em 410x demod --clk 32 -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/32\n"
352 "lf em 410x demod --clk 32 -i -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data\n"
353 "lf em 410x demod -i -> demod an EM410x Tag ID from GraphBuffer while inverting data\n"
354 "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"
359 arg_u64_0(NULL
, "clk", "<dec>", "clock (default autodetect)"),
360 arg_u64_0(NULL
, "err", "<dec>", "maximum allowed errors (default 100)"),
361 arg_u64_0(NULL
, "len", "<dec>", "maximum length"),
362 arg_lit0("i", "invert", "invert output"),
363 arg_lit0("a", "amp", "amplify signal"),
364 arg_str0(NULL
, "bin", "<bin>", "Binary string i.e 0001001001"),
367 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
369 int clk
= arg_get_u32_def(ctx
, 1, 0);
370 int max_err
= arg_get_u32_def(ctx
, 2, 100);
371 size_t max_len
= arg_get_u32_def(ctx
, 3, 0);
372 bool invert
= arg_get_lit(ctx
, 4);
373 bool amplify
= arg_get_lit(ctx
, 5);
375 uint8_t bin
[512] = {0};
376 CLIGetStrWithReturn(ctx
, 6, bin
, &bin_len
);
383 // 111111111011110010010100001110010101001101110001100100000010010011111100001111
384 size_t demodlen
= bin_len
;
385 size_t start_idx
= 0;
387 binstr_2_binarray(arr
, (char *)bin
, bin_len
);
388 return ask_em410x_binary_decode(true, &hi
, &lo
, arr
, &demodlen
, &start_idx
);
391 if (AskEm410xDemod(clk
, invert
, max_err
, max_len
, amplify
, &hi
, &lo
, true) != PM3_SUCCESS
) {
398 // this read is the "normal" read, which download lf signal and tries to demod here.
399 static int CmdEM410xReader(const char *Cmd
) {
400 CLIParserContext
*ctx
;
401 CLIParserInit(&ctx
, "lf em 410x reader",
403 "lf em 410x reader\n"
404 "lf em 410x reader -@ -> continuous reader mode\n"
405 "lf em 410x reader --clk 32 -> using a clock of RF/32\n"
406 "lf em 410x reader --clk 32 -i -> using a clock of RF/32 and inverting data\n"
407 "lf em 410x reader -i -> inverting data\n"
408 "lf em 410x reader --clk 64 -i --err 0 -> using a clock of RF/64 and inverting data and allowing 0 demod errors"
413 arg_u64_0(NULL
, "clk", "<dec>", "clock (default autodetect)"),
414 arg_u64_0(NULL
, "err", "<dec>", "maximum allowed errors (default 100)"),
415 arg_u64_0(NULL
, "len", "<dec>", "maximum length"),
416 arg_lit0("i", "invert", "invert output"),
417 arg_lit0("a", "amp", "amplify signal"),
418 arg_lit0("b", NULL
, "break on first found"),
419 arg_lit0("@", NULL
, "continuous reader mode"),
420 arg_lit0("v", "verbose", "verbose output"),
423 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
425 int clk
= arg_get_u32_def(ctx
, 1, 0);
426 int max_err
= arg_get_u32_def(ctx
, 2, 100);
427 size_t max_len
= arg_get_u32_def(ctx
, 3, 0);
428 bool invert
= arg_get_lit(ctx
, 4);
429 bool amplify
= arg_get_lit(ctx
, 5);
430 bool break_first
= arg_get_lit(ctx
, 6);
431 bool cm
= arg_get_lit(ctx
, 7);
432 bool verbose
= arg_get_lit(ctx
, 8);
436 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
442 lf_read(false, 12288);
443 AskEm410xDemod(clk
, invert
, max_err
, max_len
, amplify
, &hi
, &lo
, verbose
);
445 if (break_first
&& gs_em410xid
!= 0) {
448 } while (cm
&& !kbd_enter_pressed());
453 // emulate an EM410X tag
454 static int CmdEM410xSim(const char *Cmd
) {
456 CLIParserContext
*ctx
;
457 CLIParserInit(&ctx
, "lf em 410x sim",
458 "Enables simulation of EM 410x card.\n"
459 "Simulation runs until the button is pressed or another USB command is issued.",
460 "lf em 410x sim --id 0F0368568B\n"
461 "lf em 410x sim --id 0F0368568B --clk 32\n"
462 "lf em 410x sim --id 0F0368568B --gap 0"
467 arg_u64_0(NULL
, "clk", "<dec>", "<32|64> clock (default 64)"),
468 arg_str1(NULL
, "id", "<hex>", "EM Tag ID number (5 hex bytes)"),
469 arg_u64_0(NULL
, "gap", "<dec>", "gap (0's) between ID repeats (default 20)"),
472 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
474 // clock is 64 in EM410x tags
475 int clk
= arg_get_u32_def(ctx
, 1, 64);
477 int gap
= arg_get_u32_def(ctx
, 3, 20);
478 uint8_t uid
[5] = {0};
479 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
483 PrintAndLogEx(FAILED
, "EM ID must include 5 hex bytes (10 hex symbols), got " _YELLOW_("%u"), uid_len
);
487 PrintAndLogEx(SUCCESS
, "Starting simulating EM Tag ID "_YELLOW_("%s")" clock: "_YELLOW_("%d"), sprint_hex_inrow(uid
, sizeof(uid
)), clk
);
488 em410x_construct_emul_graph(uid
, clk
, gap
);
493 static int CmdEM410xBrute(const char *Cmd
) {
494 CLIParserContext
*ctx
;
495 CLIParserInit(&ctx
, "lf em 410x brute",
496 "bruteforcing by emulating EM 410x tag",
497 "lf em 410x brute -f ids.txt\n"
498 "lf em 410x brute -f ids.txt --clk 32\n"
499 "lf em 410x brute -f ids.txt --delay 3000\n"
500 "lf em 410x brute -f ids.txt --delay 3000 --clk 32\n"
505 arg_u64_0(NULL
, "clk", "<dec>", "<32|64> clock (default 64)"),
506 arg_u64_0(NULL
, "delay", "<dec>", "pause delay in milliseconds between UIDs simulation (default 1000ms)"),
507 arg_str1("f", "file", "<hex>", "file with EM Tag IDs, one id per line"),
508 arg_u64_0(NULL
, "gap", "<dec>", "gap (0's) between ID repeats (default 20)"),
511 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
513 // clock default 64 in EM410x
514 uint32_t clk
= arg_get_u32_def(ctx
, 1, 64);
515 int gap
= arg_get_u32_def(ctx
, 4, 20);
516 // default pause time: 1 second
517 uint32_t delay
= arg_get_u32_def(ctx
, 2, 1000);
520 char filename
[FILE_PATH_SIZE
] = {0};
521 CLIParamStrToBuf(arg_get_str(ctx
, 3), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
525 PrintAndLogEx(ERR
, "Error: Please specify a filename");
530 uint8_t stUidBlock
= 20;
532 uint8_t uid
[5] = {0x00};
536 if ((f
= fopen(filename
, "r")) == NULL
) {
537 PrintAndLogEx(ERR
, "Error: Could not open EM Tag IDs file ["_YELLOW_("%s")"]", filename
);
541 // allocate mem for file contents
542 uint8_t *uidblock
= calloc(stUidBlock
, 5);
543 if (uidblock
== NULL
) {
545 PrintAndLogEx(ERR
, "Error: can't allocate memory");
549 // read file into memory
552 while (fgets(buf
, sizeof(buf
), f
)) {
553 if (strlen(buf
) < 10 || buf
[9] == '\n') continue;
554 while (fgetc(f
) != '\n' && !feof(f
)); //goto next line
556 //The line start with # is comment, skip
557 if (buf
[0] == '#') continue;
560 if (param_gethex_ex(buf
, 0, uid
, &uidlen
) && (uidlen
!= 10)) {
561 PrintAndLogEx(FAILED
, "EM Tag IDs must include 5 hex bytes (10 hex symbols), got ( " _RED_("%d") " )", uidlen
);
569 if (stUidBlock
- uidcnt
< 2) {
570 p
= realloc(uidblock
, 5 * (stUidBlock
+= 10));
572 PrintAndLogEx(WARNING
, "Cannot allocate memory for EM Tag IDs");
579 memset(uidblock
+ 5 * uidcnt
, 0, 5);
580 num_to_bytes(strtoll(buf
, NULL
, 16), 5, uidblock
+ 5 * uidcnt
);
582 memset(buf
, 0, sizeof(buf
));
587 PrintAndLogEx(FAILED
, "No EM Tag IDs found in file");
592 PrintAndLogEx(SUCCESS
, "Loaded "_YELLOW_("%d")" EM Tag IDs from "_YELLOW_("%s")", pause delay:"_YELLOW_("%d")" ms", uidcnt
, filename
, delay
);
596 for (uint32_t c
= 0; c
< uidcnt
; ++c
) {
597 if (kbd_enter_pressed()) {
598 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
599 PrintAndLogEx(WARNING
, "aborted via keyboard!\n");
601 return PM3_EOPABORTED
;
604 memcpy(testuid
, uidblock
+ 5 * c
, 5);
605 PrintAndLogEx(INFO
, "Bruteforce %d / %u: simulating EM Tag ID " _YELLOW_("%s")
608 , sprint_hex_inrow(testuid
, sizeof(testuid
))
611 em410x_construct_emul_graph(testuid
, clk
, gap
);
619 payload
.len
= g_GraphTraceLen
;
622 clearCommandBuffer();
623 SendCommandNG(CMD_LF_SIMULATE
, (uint8_t *)&payload
, sizeof(payload
));
625 PacketResponseNG resp
;
626 if (WaitForResponseTimeout(CMD_LF_SIMULATE
, &resp
, delay
)) {
627 if (resp
.status
== PM3_EOPABORTED
) {
628 PrintAndLogEx(INFO
, "Button pressed, user aborted");
637 //currently only supports manchester modulations
638 static int CmdEM410xSpoof(const char *Cmd
) {
639 CLIParserContext
*ctx
;
640 CLIParserInit(&ctx
, "lf em 410x spoof",
641 "Watch 'nd Spoof, activates reader\n"
642 "Waits until a EM 410x tag gets presented then Proxmark3 starts simulating the found EM Tag ID",
650 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
653 // loops if the captured ID was in XL-format.
655 CmdEM410xReader("-b@");
656 PrintAndLogEx(SUCCESS
, "Replaying captured EM Tag ID "_YELLOW_("%010" PRIx64
), gs_em410xid
);
661 static size_t concatbits(uint8_t *dst
, size_t dstskip
, const uint8_t *src
, size_t srcstart
, size_t srclen
) {
662 // erase dstbuf bits that will be overriden
663 dst
[dstskip
/ 8] &= 0xFF - ((1 << (7 - (dstskip
% 8) + 1)) - 1);
664 for (size_t i
= (dstskip
/ 8) + 1; i
<= (dstskip
+ srclen
) / 8; i
++) {
668 for (size_t i
= 0; i
< srclen
; i
++) {
669 // equiv of dstbufbits[dstbufskip + i] = srcbufbits[srcbufstart + i]
670 dst
[(dstskip
+ i
) / 8] |= ((src
[(srcstart
+ i
) / 8] >> (7 - ((srcstart
+ i
) % 8))) & 1) << (7 - ((dstskip
+ i
) % 8));
673 return dstskip
+ srclen
;
676 static int CmdEM410xClone(const char *Cmd
) {
677 CLIParserContext
*ctx
;
678 CLIParserInit(&ctx
, "lf em 410x clone",
679 "clone a EM410x ID to a T55x7, Q5/T5555, EM4305/4469 or Hitag S/8211 tag.",
680 "lf em 410x clone --id 0F0368568B -> encode for T55x7 tag\n"
681 "lf em 410x clone --id 0F0368568B --q5 -> encode for Q5/T5555 tag\n"
682 "lf em 410x clone --id 0F0368568B --em -> encode for EM4305/4469\n"
683 "lf em 410x clone --id 0F0368568B --hs -> encode for Hitag S/8211"
688 arg_u64_0(NULL
, "clk", "<dec>", "<16|32|40|64> clock (default 64)"),
689 arg_str1(NULL
, "id", "<hex>", "EM Tag ID number (5 hex bytes)"),
690 arg_lit0(NULL
, "q5", "optional - specify writing to Q5/T5555 tag"),
691 arg_lit0(NULL
, "em", "optional - specify writing to EM4305/4469 tag"),
692 arg_lit0(NULL
, "hs", "optional - specify writing to Hitag S/8211 tag"),
693 arg_lit0(NULL
, "electra", "optional - add Electra blocks to tag"),
696 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
698 // clock default 64 in EM410x
699 uint32_t clk
= arg_get_u32_def(ctx
, 1, 64);
701 uint8_t uid
[5] = {0};
702 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
703 bool q5
= arg_get_lit(ctx
, 3);
704 bool em
= arg_get_lit(ctx
, 4);
705 bool hs
= arg_get_lit(ctx
, 5);
706 bool add_electra
= arg_get_lit(ctx
, 6);
709 if (q5
+ em
+ hs
> 1) {
710 PrintAndLogEx(FAILED
, "Only specify one tag Type");
715 if (IfPm3Hitag() == false) {
716 PrintAndLogEx(FAILED
, "Device not compiled to support Hitag");
720 PrintAndLogEx(FAILED
, "supported clock rates for Hitag are " _YELLOW_("16, 32, 64"));
725 // Allowed clock rates: 16, 32, 40 and 64
726 if ((clk
!= 16) && (clk
!= 32) && (clk
!= 64) && (clk
!= 40)) {
727 PrintAndLogEx(FAILED
, "supported clock rates are " _YELLOW_("16, 32, 40, 64") " got " _RED_("%d") "\n", clk
);
731 uint64_t id
= bytes_to_num(uid
, uid_len
);
732 PrintAndLogEx(SUCCESS
, "Preparing to clone EM4102 to " _YELLOW_("%s") " tag with EM Tag ID " _GREEN_("%010" PRIX64
) " (RF/%d)",
733 q5
? "Q5/T5555" : (em
? "EM4305/4469" : (hs
? "Hitag S/8211" : "T55x7")), id
, clk
);
735 uint8_t data
[HITAG_BLOCK_SIZE
* 2] = {0xFF, 0x80}; // EM410X_HEADER 9 bits of one
736 uint32_t databits
= 9;
737 uint8_t c_parity
= 0;
739 for (int i
= 36; i
>= 0; i
-= 4) {
740 uint8_t r_parity
= 0;
741 uint8_t nibble
= id
>> i
& 0xF;
743 databits
= concatbits(data
, databits
, &nibble
, 4, 4);
744 for (size_t j
= 0; j
< 4; j
++) {
745 r_parity
^= nibble
>> j
& 1;
747 databits
= concatbits(data
, databits
, &r_parity
, 7, 1);
750 data
[7] |= c_parity
<< 1;
752 PrintAndLogEx(INFO
, "Encoded to %s", sprint_hex(data
, sizeof(data
)));
754 clearCommandBuffer();
755 PacketResponseNG resp
;
758 lf_hitag_data_t packet
;
759 memset(&packet
, 0, sizeof(packet
));
761 for (size_t steps
= 0; steps
< 3; steps
++) {
764 packet
.data
[0] = 0xCA; //compatiable for 82xx, no impact on Hitag S
765 // clk -> TTFDR1 TTFDR0
766 // 32 -> 0x00 4 kBit/s
767 // 16 -> 0x10 8 kBit/s
768 // 64 -> 0x20 2 kBit/s
769 packet
.data
[1] = 0x04;
774 packet
.data
[1] |= 0x10;
777 packet
.data
[1] |= 0x20;
781 packet
.data
[3] = 0; //TODO: keep PWDH0?
785 memcpy(packet
.data
, &data
[HITAG_BLOCK_SIZE
* 0], HITAG_BLOCK_SIZE
);
789 memcpy(packet
.data
, &data
[HITAG_BLOCK_SIZE
* 1], HITAG_BLOCK_SIZE
);
794 packet
.cmd
= WHTSF_PLAIN
;
795 SendCommandNG(CMD_LF_HITAGS_WRITE
, (uint8_t *)&packet
, sizeof(packet
));
796 if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE
, &resp
, 4000) == false) {
797 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
800 if (resp
.status
!= PM3_SUCCESS
) {
801 PrintAndLogEx(WARNING
, "Something went wrong");
817 payload
.add_electra
= add_electra
;
819 payload
.high
= (uint32_t)(id
>> 32);
820 payload
.low
= (uint32_t)id
;
822 SendCommandNG(CMD_LF_EM410X_CLONE
, (uint8_t *)&payload
, sizeof(payload
));
823 WaitForResponse(CMD_LF_EM410X_CLONE
, &resp
);
826 switch (resp
.status
) {
828 PrintAndLogEx(SUCCESS
, "Done");
829 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf em 410x reader`") " to verify");
833 PrintAndLogEx(WARNING
, "Something went wrong");
840 static command_t CommandTable
[] = {
841 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
842 //{"demod", CmdEMdemodASK, IfPm3Lf, "Extract ID from EM410x tag on antenna)"},
843 {"demod", CmdEM410xDemod
, AlwaysAvailable
, "demodulate a EM410x tag from the GraphBuffer"},
844 {"reader", CmdEM410xReader
, IfPm3Lf
, "attempt to read and extract tag data"},
845 {"sim", CmdEM410xSim
, IfPm3Lf
, "simulate EM410x tag"},
846 {"brute", CmdEM410xBrute
, IfPm3Lf
, "reader bruteforce attack by simulating EM410x tags"},
847 {"watch", CmdEM410xWatch
, IfPm3Lf
, "watches for EM410x 125/134 kHz tags"},
848 {"spoof", CmdEM410xSpoof
, IfPm3Lf
, "watches for EM410x 125/134 kHz tags, and replays them" },
849 {"clone", CmdEM410xClone
, IfPm3Lf
, "clone EM410x Tag ID to T55x7, Q5/T5555 or EM4305/4469"},
850 {NULL
, NULL
, NULL
, NULL
}
853 static int CmdHelp(const char *Cmd
) {
854 (void)Cmd
; // Cmd is not used so far
855 CmdsHelp(CommandTable
);
859 int CmdLFEM410X(const char *Cmd
) {
860 clearCommandBuffer();
861 return CmdsParse(CommandTable
, Cmd
);