style
[RRG-proxmark3.git] / client / src / cmdlfem410x.c
blob1acebd6ab1cfb41d595480b101a21a55cd8bac8b
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
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.
8 //
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"
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include "fileutils.h"
27 #include "cmdparser.h" // command_t
28 #include "comms.h"
29 #include "commonutil.h"
30 #include "common.h"
31 #include "util_posix.h"
32 #include "protocols.h"
33 #include "ui.h"
34 #include "proxgui.h"
35 #include "graph.h"
36 #include "cmddata.h"
37 #include "cmdlf.h"
38 #include "lfdemod.h"
39 #include "generator.h"
40 #include "cliparser.h"
41 #include "cmdhw.h"
42 #include "hitag.h"
44 static uint64_t gs_em410xid = 0;
46 static int CmdHelp(const char *Cmd);
47 /* Read the ID of an EM410x tag.
48 * Format:
49 * 1111 1111 1 <-- standard non-repeatable header
50 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
51 * ....
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) {
59 // clear our graph
60 ClearGraph(true);
62 // write 16 zero bit sledge
63 for (uint8_t i = 0; i < gap; i++)
64 AppendGraph(false, clock, 0);
66 // write 9 start bits
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++) {
81 // append each bit
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)]);
87 // append parity bit
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)];
98 // parity columns
99 AppendGraph(false, clock, parity[0]);
100 AppendGraph(false, clock, parity[1]);
101 AppendGraph(false, clock, parity[2]);
102 AppendGraph(false, clock, parity[3]);
104 // stop bit
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);
124 } else {
125 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64)" on 128b frame with data "_GREEN_("%011" PRIX64), id, data);
128 return;
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
148 uint64_t n = 1;
149 uint64_t id2lo = 0;
150 uint8_t m, i;
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};
189 int j = 23;
190 for (int k = 0 ; k < 24; ++k, --j) {
191 arr[k] = (p1id >> k) & 1;
194 uint32_t p1 = 0;
196 p1 |= arr[23] << 21;
197 p1 |= arr[22] << 23;
198 p1 |= arr[21] << 20;
199 p1 |= arr[20] << 22;
201 p1 |= arr[19] << 18;
202 p1 |= arr[18] << 16;
203 p1 |= arr[17] << 19;
204 p1 |= arr[16] << 17;
206 p1 |= arr[15] << 13;
207 p1 |= arr[14] << 15;
208 p1 |= arr[13] << 12;
209 p1 |= arr[12] << 14;
211 p1 |= arr[11] << 6;
212 p1 |= arr[10] << 2;
213 p1 |= arr[9] << 7;
214 p1 |= arr[8] << 1;
216 p1 |= arr[7] << 0;
217 p1 |= arr[6] << 8;
218 p1 |= arr[5] << 11;
219 p1 |= arr[4] << 3;
221 p1 |= arr[3] << 10;
222 p1 |= arr[2] << 4;
223 p1 |= arr[1] << 5;
224 p1 |= arr[0] << 9;
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);
242 if (ans < 0) {
243 if (ans == -2)
244 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x not enough samples after demod");
245 else if (ans == -4)
246 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x preamble not found");
247 else if (ans == -5)
248 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x Size not correct: %zu", size);
249 else if (ans == -6)
250 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x parity failed");
252 return PM3_ESOFT;
255 PrintAndLogEx(DEBUG, "DEBUG: Em410x idx: %zu, Len: %zu, Printing DemodBuffer:", *idx, *size);
256 if (g_debugMode) {
257 printDemodBuff(0, false, false, true);
260 printEM410x(*hi, *lo, verbose, ans);
261 gs_em410xid = *lo;
262 return PM3_SUCCESS;
265 /* Read the ID of an EM410x tag.
266 * Format:
267 * 1111 1111 1 <-- standard non-repeatable header
268 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
269 * ....
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) {
274 size_t idx = 0;
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");
279 return PM3_ESOFT;
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));
289 return ret;
292 int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose) {
293 bool st = true;
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) {
300 return PM3_ESOFT;
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.",
312 "lf em 410x watch"
315 void *argtable[] = {
316 arg_param_begin,
317 arg_param_end
319 CLIExecWithReturn(ctx, Cmd, argtable, true);
320 CLIParserFree(ctx);
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);
328 // by marshmellow
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
334 uint32_t hi = 0;
335 uint64_t lo = 0;
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"
350 void *argtable[] = {
351 arg_param_begin,
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"),
358 arg_param_end
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);
367 int bin_len = 512;
368 uint8_t bin[512] = {0};
369 CLIGetStrWithReturn(ctx, 6, bin, &bin_len);
370 CLIParserFree(ctx);
372 uint32_t hi = 0;
373 uint64_t lo = 0;
375 if (bin_len) {
376 // 111111111011110010010100001110010101001101110001100100000010010011111100001111
377 size_t demodlen = bin_len;
378 size_t start_idx = 0;
379 uint8_t arr[258];
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) {
385 return PM3_ESOFT;
388 return 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",
395 "read EM 410x tag",
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"
404 void *argtable[] = {
405 arg_param_begin,
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"),
414 arg_param_end
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);
426 CLIParserFree(ctx);
428 if (cm) {
429 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
432 do {
433 uint32_t hi = 0;
434 uint64_t lo = 0;
435 lf_read(false, 12288);
436 AskEm410xDemod(clk, invert, max_err, max_len, amplify, &hi, &lo, verbose);
438 if (break_first && gs_em410xid != 0) {
439 break;
441 } while (cm && !kbd_enter_pressed());
443 return PM3_SUCCESS;
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"
458 void *argtable[] = {
459 arg_param_begin,
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)"),
463 arg_param_end
465 CLIExecWithReturn(ctx, Cmd, argtable, false);
467 // clock is 64 in EM410x tags
468 int clk = arg_get_u32_def(ctx, 1, 64);
469 int uid_len = 0;
470 int gap = arg_get_u32_def(ctx, 3, 20);
471 uint8_t uid[5] = {0};
472 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
473 CLIParserFree(ctx);
475 if (uid_len != 5) {
476 PrintAndLogEx(FAILED, "EM ID must include 5 hex bytes (10 hex symbols), got " _YELLOW_("%u"), uid_len);
477 return PM3_EINVARG;
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);
482 CmdLFSim("");
483 return PM3_SUCCESS;
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"
496 void *argtable[] = {
497 arg_param_begin,
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)"),
502 arg_param_end
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);
512 int fnlen = 0;
513 char filename[FILE_PATH_SIZE] = {0};
514 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
515 CLIParserFree(ctx);
517 if (fnlen == 0) {
518 PrintAndLogEx(ERR, "Error: Please specify a filename");
519 return PM3_EINVARG;
522 // get suffix.
523 char suffix[10] = {0};
524 char *ext = strrchr(filename, '.');
525 if (ext != NULL) {
526 strncpy(suffix, ext, sizeof(suffix) - 1);
529 // load keys
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) {
534 free(uidblock);
535 return res;
538 if (uidcount == 0) {
539 PrintAndLogEx(FAILED, "No EM Tag IDs found in file");
540 free(uidblock);
541 return PM3_EINVARG;
544 PrintAndLogEx(SUCCESS, "Loaded "_GREEN_("%d")" EM Tag IDs from `"_YELLOW_("%s")"` pause delay:"_YELLOW_("%d")" ms", uidcount, filename, delay);
546 // loop
547 uint8_t testuid[5];
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");
553 free(uidblock);
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")
561 , i + 1
562 , uidcount
563 , sprint_hex_inrow(testuid, sizeof(testuid))
566 em410x_construct_emul_graph(testuid, clk, gap);
568 lfsim_upload_gb();
570 struct p {
571 uint16_t len;
572 uint16_t gap;
573 } PACKED payload;
574 payload.len = g_GraphTraceLen;
575 payload.gap = 0;
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");
583 break;
587 free(uidblock);
588 return PM3_SUCCESS;
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",
597 "lf em 410x spoof"
600 void *argtable[] = {
601 arg_param_begin,
602 arg_param_end
604 CLIExecWithReturn(ctx, Cmd, argtable, true);
605 CLIParserFree(ctx);
607 // loops if the captured ID was in XL-format.
608 gs_em410xid = 0;
609 CmdEM410xReader("-b@");
610 PrintAndLogEx(SUCCESS, "Replaying captured EM Tag ID "_YELLOW_("%010" PRIx64), gs_em410xid);
611 CmdLFSim("");
612 return PM3_SUCCESS;
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"
625 void *argtable[] = {
626 arg_param_begin,
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"),
633 arg_param_end
635 CLIExecWithReturn(ctx, Cmd, argtable, false);
637 // clock default 64 in EM410x
638 uint32_t clk = arg_get_u32_def(ctx, 1, 64);
639 int uid_len = 0;
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);
646 CLIParserFree(ctx);
648 if (q5 + em + hts > 1) {
649 PrintAndLogEx(FAILED, "Only specify one tag Type");
650 return PM3_EINVARG;
653 if (hts) {
654 if (IfPm3Hitag() == false) {
655 PrintAndLogEx(FAILED, "Device not compiled to support Hitag");
656 return PM3_EINVARG;
658 if (clk == 40) {
659 PrintAndLogEx(FAILED, "supported clock rates for Hitag are " _YELLOW_("16, 32, 64"));
660 return PM3_EINVARG;
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);
667 return PM3_EINVARG;
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);
687 c_parity ^= nibble;
689 data[7] |= c_parity << 1;
691 PrintAndLogEx(INFO, "Encoded to %s", sprint_hex(data, sizeof(data)));
693 clearCommandBuffer();
694 PacketResponseNG resp;
696 if (hts) {
697 lf_hitag_data_t packet;
698 memset(&packet, 0, sizeof(packet));
700 for (size_t steps = 0; steps < 3; steps++) {
701 switch (steps) {
702 case 0:
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;
709 switch (clk) {
710 case 32:
711 break;
712 case 16:
713 packet.data[1] |= 0x10;
714 break;
715 case 64:
716 packet.data[1] |= 0x20;
717 break;
719 packet.data[2] = 0;
720 packet.data[3] = 0; //TODO: keep PWDH0?
721 packet.page = 1;
722 break;
723 case 1:
724 memcpy(packet.data, &data[HITAG_BLOCK_SIZE * 0], HITAG_BLOCK_SIZE);
725 packet.page = 4;
726 break;
727 case 2:
728 memcpy(packet.data, &data[HITAG_BLOCK_SIZE * 1], HITAG_BLOCK_SIZE);
729 packet.page = 5;
730 break;
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.");
738 return PM3_ETIMEOUT;
740 if (resp.status != PM3_SUCCESS) {
741 PrintAndLogEx(WARNING, "Something went wrong");
742 return resp.status;
745 } else {
746 struct {
747 bool Q5;
748 bool EM;
749 bool add_electra;
750 uint8_t clock;
751 uint32_t high;
752 uint32_t low;
753 } PACKED payload;
755 payload.Q5 = q5;
756 payload.EM = em;
757 payload.add_electra = add_electra;
758 payload.clock = clk;
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.");
765 return PM3_ETIMEOUT;
769 switch (resp.status) {
770 case PM3_SUCCESS: {
771 PrintAndLogEx(SUCCESS, "Done!");
772 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 410x reader`") " to verify");
773 break;
775 default: {
776 PrintAndLogEx(WARNING, "Something went wrong");
777 break;
780 return resp.status;
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);
799 return PM3_SUCCESS;
802 int CmdLFEM410X(const char *Cmd) {
803 clearCommandBuffer();
804 return CmdsParse(CommandTable, Cmd);