renamed 'hf mfdes readdata, writedata' to 'read/write'
[RRG-proxmark3.git] / client / src / cmdlfem4x05.c
blob1a2fc82551cee47374f8ffdb7d1c17b4480deb8c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Low frequency EM4x commands
9 //-----------------------------------------------------------------------------
11 #include "cmdlfem4x05.h"
13 #include <stdio.h>
14 #include <string.h>
15 #include <inttypes.h>
16 #include <ctype.h>
17 #include <stdlib.h>
19 #include "util_posix.h" // msclock
20 #include "fileutils.h"
21 #include "cmdparser.h" // command_t
22 #include "comms.h"
23 #include "commonutil.h"
24 #include "common.h"
25 #include "util_posix.h"
26 #include "protocols.h"
27 #include "ui.h"
28 #include "proxgui.h"
29 #include "graph.h"
30 #include "cmddata.h"
31 #include "cmdlf.h"
32 #include "lfdemod.h"
33 #include "generator.h"
34 #include "cliparser.h"
35 #include "cmdhw.h"
37 //////////////// 4205 / 4305 commands
39 #define EM_PREAMBLE_LEN 8
41 static int CmdHelp(const char *Cmd);
43 // 1 = EM4x69
44 // 2 = EM4x05
45 static em_tech_type_t em_get_card_type(uint32_t config) {
46 uint8_t t = (config >> 1) & 0xF;
47 switch (t) {
48 case 4:
49 return EM_4469;
50 case 8:
51 return EM_4205;
52 case 9:
53 return EM_4305;
54 case 12:
55 return EM_4369;
57 return EM_UNKNOWN;
60 static const char *em_get_card_str(uint32_t config) {
61 switch (em_get_card_type(config)) {
62 case EM_4305:
63 return "EM4305";
64 case EM_4469:
65 return "EM4469";
66 case EM_4205:
67 return "EM4205";
68 case EM_4369:
69 return "EM4369";
70 case EM_UNKNOWN:
71 break;
73 return "Unknown";
76 // even parity COLUMN
77 static bool em4x05_col_parity_test(uint8_t *bs, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) {
78 if (rows * cols > size) return false;
79 uint8_t colP = 0;
81 for (uint8_t c = 0; c < cols - 1; c++) {
82 for (uint8_t r = 0; r < rows; r++) {
83 colP ^= bs[(r * cols) + c];
85 if (colP != pType) return false;
86 colP = 0;
88 return true;
91 // download samples from device and copy to Graphbuffer
92 static bool em4x05_download_samples(void) {
94 // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
95 uint8_t got[6000];
96 if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 0, NULL, 2500, false)) {
97 PrintAndLogEx(WARNING, "(em_download_samples) command execution time out");
98 return false;
101 setGraphBuf(got, sizeof(got));
102 // set signal properties low/high/mean/amplitude and is_noise detection
103 computeSignalProperties(got, sizeof(got));
104 RepaintGraphWindow();
105 if (getSignalProperties()->isnoise) {
106 PrintAndLogEx(DEBUG, "No tag found - signal looks like noise");
107 return false;
109 return true;
112 // em_demod
113 static int doPreambleSearch(size_t *startIdx) {
115 // sanity check
116 if (DemodBufferLen < EM_PREAMBLE_LEN) {
117 PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 demodbuffer too small");
118 return PM3_ESOFT;
121 // set size to 11 to only test first 3 positions for the preamble
122 // do not set it too long else an error preamble followed by 010 could be seen as success.
123 size_t size = (11 > DemodBufferLen) ? DemodBufferLen : 11;
124 *startIdx = 0;
126 // skip first two 0 bits as they might have been missed in the demod
127 uint8_t preamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 1, 0, 1, 0};
128 if (!preambleSearchEx(DemodBuffer, preamble, EM_PREAMBLE_LEN, &size, startIdx, true)) {
130 uint8_t errpreamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 0, 0, 0, 1};
131 if (!preambleSearchEx(DemodBuffer, errpreamble, EM_PREAMBLE_LEN, &size, startIdx, true)) {
132 PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 preamble not found :: %zu", *startIdx);
133 return PM3_ESOFT;
135 return PM3_EFAILED; // Error preamble found
138 return PM3_SUCCESS;
141 static bool detectFSK(void) {
142 // detect fsk clock
143 if (GetFskClock("", false) == 0) {
144 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: FSK clock failed");
145 return false;
147 // demod
148 int ans = FSKrawDemod(0, 0, 0, 0, false);
149 if (ans != PM3_SUCCESS) {
150 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: FSK Demod failed");
151 return false;
153 return true;
155 // PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... )
156 static bool detectPSK(void) {
157 int ans = GetPskClock("", false);
158 if (ans <= 0) {
159 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: PSK clock failed");
160 return false;
162 //demod
163 //try psk1 -- 0 0 6 (six errors?!?)
164 ans = PSKDemod(0, 0, 6, false);
165 if (ans != PM3_SUCCESS) {
166 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: PSK1 Demod failed");
167 return false;
170 // In order to hit the INVERT, we need to demod here
171 if (DemodBufferLen < 11) {
172 PrintAndLogEx(INFO, " demod buff len less than PREAMBLE lEN");
175 size_t size = (11 > DemodBufferLen) ? DemodBufferLen : 11;
176 size_t startIdx = 0;
177 uint8_t preamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 1, 0, 1, 0};
178 if (!preambleSearchEx(DemodBuffer, preamble, EM_PREAMBLE_LEN, &size, &startIdx, true)) {
180 //try psk1 inverted
181 ans = PSKDemod(0, 1, 6, false);
182 if (ans != PM3_SUCCESS) {
183 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: PSK1 inverted Demod failed");
184 return false;
187 if (!preambleSearchEx(DemodBuffer, preamble, EM_PREAMBLE_LEN, &size, &startIdx, true)) {
188 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: PSK1 inverted Demod failed 2");
189 return false;
193 // either PSK1 or PSK1 inverted is ok from here.
194 // lets check PSK2 later.
195 return true;
197 // try manchester - NOTE: ST only applies to T55x7 tags.
198 static bool detectASK_MAN(void) {
199 bool stcheck = false;
200 if (ASKDemod_ext(0, 0, 50, 0, false, false, false, 1, &stcheck) != PM3_SUCCESS) {
201 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/Manchester Demod failed");
202 return false;
204 return true;
207 static bool detectASK_BI(void) {
208 int ans = ASKbiphaseDemod(0, 0, 1, 50, false);
209 if (ans != PM3_SUCCESS) {
210 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/biphase normal demod failed");
212 ans = ASKbiphaseDemod(0, 1, 1, 50, false);
213 if (ans != PM3_SUCCESS) {
214 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/biphase inverted demod failed");
215 return false;
218 return true;
220 static bool detectNRZ(void) {
221 int ans = NRZrawDemod(0, 0, 1, false);
222 if (ans != PM3_SUCCESS) {
223 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: NRZ normal demod failed");
225 ans = NRZrawDemod(0, 1, 1, false);
226 if (ans != PM3_SUCCESS) {
227 PrintAndLogEx(DEBUG, "DEBUG: Error - EM: NRZ inverted demod failed");
228 return false;
232 return true;
235 // param: idx - start index in demoded data.
236 static int em4x05_setdemod_buffer(uint32_t *word, size_t idx) {
238 //test for even parity bits.
239 uint8_t parity[45] = {0};
240 memcpy(parity, DemodBuffer, 45);
241 if (!em4x05_col_parity_test(DemodBuffer + idx + EM_PREAMBLE_LEN, 45, 5, 9, 0)) {
242 PrintAndLogEx(DEBUG, "DEBUG: Error - End Parity check failed");
243 return PM3_ESOFT;
246 // test for even parity bits and remove them. (leave out the end row of parities so 36 bits)
247 if (!removeParity(DemodBuffer, idx + EM_PREAMBLE_LEN, 9, 0, 36)) {
248 PrintAndLogEx(DEBUG, "DEBUG: Error - EM, failed removing parity");
249 return PM3_ESOFT;
251 setDemodBuff(DemodBuffer, 32, 0);
252 *word = bytebits_to_byteLSBF(DemodBuffer, 32);
253 return PM3_SUCCESS;
256 // FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE, NRZ
257 // should cover 90% of known used configs
258 // the rest will need to be manually demoded for now...
259 static int em4x05_demod_resp(uint32_t *word, bool onlyPreamble) {
260 *word = 0;
261 int res;
262 size_t idx = 0;
263 bool found_err = false;
264 do {
265 if (detectASK_MAN()) {
266 res = doPreambleSearch(&idx);
267 if (res == PM3_SUCCESS)
268 break;
269 if (res == PM3_EFAILED)
270 // go on, maybe it's false positive and another modulation will work
271 found_err = true;
273 if (detectASK_BI()) {
274 res = doPreambleSearch(&idx);
275 if (res == PM3_SUCCESS)
276 break;
277 if (res == PM3_EFAILED)
278 found_err = true;
280 if (detectNRZ()) {
281 res = doPreambleSearch(&idx);
282 if (res == PM3_SUCCESS)
283 break;
284 if (res == PM3_EFAILED)
285 found_err = true;
287 if (detectFSK()) {
288 res = doPreambleSearch(&idx);
289 if (res == PM3_SUCCESS)
290 break;
291 if (res == PM3_EFAILED)
292 found_err = true;
294 if (detectPSK()) {
295 res = doPreambleSearch(&idx);
296 if (res == PM3_SUCCESS)
297 break;
299 if (res == PM3_EFAILED)
300 found_err = true;
302 psk1TOpsk2(DemodBuffer, DemodBufferLen);
303 res = doPreambleSearch(&idx);
304 if (res == PM3_SUCCESS)
305 break;
307 if (res == PM3_EFAILED)
308 found_err = true;
311 if (found_err)
312 return PM3_EFAILED;
314 return PM3_ESOFT;
315 } while (0);
317 if (onlyPreamble)
318 return PM3_SUCCESS;
320 res = em4x05_setdemod_buffer(word, idx);
321 if (res == PM3_SUCCESS)
322 return res;
324 if (found_err)
325 return PM3_EFAILED;
326 return res;
330 //////////////// 4205 / 4305 commands
332 static bool em4x05_verify_write(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t data) {
333 uint32_t r = 0;
334 int res = em4x05_read_word_ext(addr, pwd, use_pwd, &r);
335 if (res == PM3_SUCCESS) {
336 PrintAndLogEx(INFO, "%08x == %08x", r, data);
337 return (r == data);
339 return false;
342 int em4x05_clone_tag(uint32_t *blockdata, uint8_t numblocks, uint32_t pwd, bool use_pwd) {
344 if (blockdata == NULL)
345 return PM3_EINVARG;
347 if (numblocks < 1 || numblocks > 8)
348 return PM3_EINVARG;
350 // fast push mode
351 conn.block_after_ACK = true;
352 int res = 0;
353 for (int8_t i = 0; i < numblocks; i++) {
355 // Disable fast mode on last packet
356 if (i == numblocks - 1) {
357 conn.block_after_ACK = false;
360 if (i != 0) {
361 blockdata[i] = reflect(blockdata[i], 32);
364 res = em4x05_write_word_ext(4 + i, pwd, use_pwd, blockdata[i]);
365 if (res != PM3_SUCCESS) {
366 PrintAndLogEx(FAILED, "(em4x05_clone_tag) Time out writing to tag");
367 return res;
371 res = 0;
372 for (int8_t i = 0; i < numblocks; i++) {
373 if (em4x05_verify_write(4 + i, use_pwd, pwd, blockdata[i]) == false) {
374 res++;
378 if (res == 0)
379 PrintAndLogEx(SUCCESS, "Data written and verified");
381 return PM3_SUCCESS;
384 static int em4x05_login_ext(uint32_t pwd) {
386 struct {
387 uint32_t password;
388 } PACKED payload;
390 payload.password = pwd;
392 clearCommandBuffer();
393 SendCommandNG(CMD_LF_EM4X_LOGIN, (uint8_t *)&payload, sizeof(payload));
394 PacketResponseNG resp;
395 if (!WaitForResponseTimeout(CMD_LF_EM4X_LOGIN, &resp, 10000)) {
396 PrintAndLogEx(WARNING, "(em4x05_login_ext) timeout while waiting for reply.");
397 return PM3_ETIMEOUT;
400 if (em4x05_download_samples() == false) {
401 return PM3_ESOFT;
403 uint32_t word;
404 return em4x05_demod_resp(&word, true);
407 int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t *word) {
409 struct {
410 uint32_t password;
411 uint8_t address;
412 uint8_t usepwd;
413 } PACKED payload;
415 payload.password = pwd;
416 payload.address = addr;
417 payload.usepwd = use_pwd;
419 clearCommandBuffer();
420 SendCommandNG(CMD_LF_EM4X_READWORD, (uint8_t *)&payload, sizeof(payload));
421 PacketResponseNG resp;
422 if (!WaitForResponseTimeout(CMD_LF_EM4X_READWORD, &resp, 10000)) {
423 PrintAndLogEx(WARNING, "(em4x05_read_word_ext) timeout while waiting for reply.");
424 return PM3_ETIMEOUT;
427 if (em4x05_download_samples() == false) {
428 return PM3_ESOFT;
430 return em4x05_demod_resp(word, false);
433 int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t data) {
434 struct {
435 uint32_t password;
436 uint32_t data;
437 uint8_t address;
438 uint8_t usepwd;
439 } PACKED payload;
441 payload.password = pwd;
442 payload.data = data;
443 payload.address = addr;
444 payload.usepwd = use_pwd;
446 clearCommandBuffer();
447 SendCommandNG(CMD_LF_EM4X_WRITEWORD, (uint8_t *)&payload, sizeof(payload));
448 PacketResponseNG resp;
449 if (!WaitForResponseTimeout(CMD_LF_EM4X_WRITEWORD, &resp, 2000)) {
450 PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
451 return PM3_ETIMEOUT;
453 return PM3_SUCCESS;
456 static int em4x05_protect(uint32_t pwd, bool use_pwd, uint32_t data) {
457 struct {
458 uint32_t password;
459 uint32_t data;
460 uint8_t usepwd;
461 } PACKED payload;
463 payload.password = pwd;
464 payload.data = data;
465 payload.usepwd = use_pwd;
467 clearCommandBuffer();
468 SendCommandNG(CMD_LF_EM4X_PROTECTWORD, (uint8_t *)&payload, sizeof(payload));
469 PacketResponseNG resp;
470 if (!WaitForResponseTimeout(CMD_LF_EM4X_PROTECTWORD, &resp, 2000)) {
471 PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
472 return PM3_ETIMEOUT;
474 return PM3_SUCCESS;
477 int CmdEM4x05Demod(const char *Cmd) {
478 CLIParserContext *ctx;
479 CLIParserInit(&ctx, "lf em 4x05 demod",
480 "Try to find EM 4x05 preamble, if found decode / descramble data",
481 "lf em 4x05 demod"
484 void *argtable[] = {
485 arg_param_begin,
486 arg_param_end
488 CLIExecWithReturn(ctx, Cmd, argtable, true);
489 CLIParserFree(ctx);
490 uint32_t dummy = 0;
491 return em4x05_demod_resp(&dummy, false);
494 int CmdEM4x05Dump(const char *Cmd) {
496 CLIParserContext *ctx;
497 CLIParserInit(&ctx, "lf em 4x05 dump",
498 "Dump EM4x05/EM4x69. Tag must be on antenna.",
499 "lf em 4x05 dump\n"
500 "lf em 4x05 dump -p 11223344\n"
501 "lf em 4x05 dump -f myfile -p 11223344"
504 void *argtable[] = {
505 arg_param_begin,
506 arg_str0("p", "pwd", "<hex>", "password (00000000)"),
507 arg_str0("f", "file", "<fn>", "override filename prefix (optional). Default is based on UID"),
508 arg_param_end
510 CLIExecWithReturn(ctx, Cmd, argtable, true);
512 uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 1, 0xFFFFFFFFFFFFFFFF);
513 int fnlen = 0;
514 char filename[FILE_PATH_SIZE] = {0};
515 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
516 CLIParserFree(ctx);
518 uint8_t addr = 0;
519 uint32_t pwd = 0;
520 bool usePwd = false;
521 if (inputpwd != 0xFFFFFFFFFFFFFFFF) {
523 if (inputpwd & 0xFFFFFFFF00000000) {
524 PrintAndLogEx(FAILED, "Pwd too large");
525 return PM3_EINVARG;
528 usePwd = true;
529 pwd = (inputpwd & 0xFFFFFFFF);
532 uint32_t block0 = 0;
533 // read word 0 (chip info)
534 // block 0 can be read even without a password.
535 if (em4x05_isblock0(&block0) == false)
536 return PM3_ESOFT;
538 uint8_t bytes[4] = {0};
539 uint32_t data[16];
541 int success = PM3_SUCCESS;
542 int status, status14, status15;
543 uint32_t lock_bits = 0x00; // no blocks locked
544 bool gotLockBits = false;
545 bool lockInPW2 = false;
546 uint32_t word = 0;
548 const char *info[] = {"Info/User", "UID", "Password", "User", "Config", "User", "User", "User", "User", "User", "User", "User", "User", "User", "Lock", "Lock"};
549 const char *info4x69 [] = {"Info", "UID", "Password", "Lock", "Config", "User", "User", "User", "User", "User", "User", "User", "User", "User", "User", "User"};
551 // EM4305 vs EM4469
552 em_tech_type_t card_type = em_get_card_type(block0);
554 PrintAndLogEx(INFO, "Found a " _GREEN_("%s") " tag", em_get_card_str(block0));
556 if (usePwd) {
557 // Test first if the password is correct
558 status = em4x05_login_ext(pwd);
559 if (status == PM3_SUCCESS) {
560 PrintAndLogEx(INFO, "password is " _GREEN_("correct"));
561 } else if (status == PM3_EFAILED) {
562 PrintAndLogEx(WARNING, "password is " _RED_("incorrect") ", will try without password");
563 usePwd = false;
564 } else if (status != PM3_EFAILED) {
565 PrintAndLogEx(WARNING, "Login attempt: no answer from tag");
566 return status;
570 PrintAndLogEx(NORMAL, "");
571 PrintAndLogEx(INFO, "Addr | data | ascii |lck| info");
572 PrintAndLogEx(INFO, "-----+----------+-------+---+-----");
574 if (card_type == EM_4205 || card_type == EM_4305 || card_type == EM_UNKNOWN) {
577 // To flag any blocks locked we need to read blocks 14 and 15 first
578 // dont swap endian until we get block lock flags.
579 status14 = em4x05_read_word_ext(EM4305_PROT1_BLOCK, pwd, usePwd, &word);
580 if (status14 == PM3_SUCCESS) {
581 if ((word & 0x00008000) != 0x00) {
582 lock_bits = word;
583 gotLockBits = true;
585 data[EM4305_PROT1_BLOCK] = word;
586 } else {
587 success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
589 status15 = em4x05_read_word_ext(EM4305_PROT2_BLOCK, pwd, usePwd, &word);
590 if (status15 == PM3_SUCCESS) {
591 if ((word & 0x00008000) != 0x00) { // assume block 15 is the current lock block
592 lock_bits = word;
593 gotLockBits = true;
594 lockInPW2 = true;
596 data[EM4305_PROT2_BLOCK] = word;
597 } else {
598 success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
600 uint32_t lockbit;
601 // Now read blocks 0 - 13 as we have 14 and 15
602 for (; addr < 14; addr++) {
603 lockbit = (lock_bits >> addr) & 1;
604 if (addr == 2) {
605 if (usePwd) {
606 data[addr] = BSWAP_32(pwd);
607 num_to_bytes(pwd, 4, bytes);
608 PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]);
609 } else {
610 data[addr] = 0x00; // Unknown password, but not used to set to zeros
611 PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]);
613 } else {
614 // success &= em4x05_read_word_ext(addr, pwd, usePwd, &word);
615 status = em4x05_read_word_ext(addr, pwd, usePwd, &word); // Get status for single read
616 if (status != PM3_SUCCESS)
617 success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
618 data[addr] = BSWAP_32(word);
619 if (status == PM3_SUCCESS) {
620 num_to_bytes(word, 4, bytes);
621 PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, word, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]);
622 } else
623 PrintAndLogEx(INFO, " %02u | | | | %-10s %s", addr, info[addr], status == PM3_EFAILED ? _RED_("read denied") : _RED_("read failed"));
626 // Print blocks 14 and 15
627 // Both lock bits are protected with bit idx 14 (special case)
628 addr = 14;
629 if (status14 == PM3_SUCCESS) {
630 lockbit = (lock_bits >> addr) & 1;
631 PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %-10s %s", addr, data[addr], sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr], lockInPW2 ? "" : _GREEN_("active"));
632 } else {
633 PrintAndLogEx(INFO, " %02u | | | | %-10s %s", addr, info[addr], status14 == PM3_EFAILED ? _RED_("read denied") : _RED_("read failed"));
635 addr = 15;
636 if (status15 == PM3_SUCCESS) {
637 lockbit = (lock_bits >> 14) & 1; // beware lock bit of word15 is pr14
638 PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %-10s %s", addr, data[addr], sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr], lockInPW2 ? _GREEN_("active") : "");
639 } else {
640 PrintAndLogEx(INFO, " %02u | | | | %-10s %s", addr, info[addr], status15 == PM3_EFAILED ? _RED_("read denied") : _RED_("read failed"));
642 // Update endian for files
643 data[14] = BSWAP_32(data[14]);
644 data[15] = BSWAP_32(data[15]);
646 } else if (card_type == EM_4369 || card_type == EM_4469) {
648 // To flag any blocks locked we need to read block 3 first
649 // dont swap endian until we get block lock flags.
650 status14 = em4x05_read_word_ext(EM4469_PROT_BLOCK, pwd, usePwd, &word);
651 if (status14 == PM3_SUCCESS) {
652 lock_bits = word;
653 gotLockBits = true;
654 data[EM4469_PROT_BLOCK] = word;
655 } else {
656 success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
659 uint32_t lockbit;
661 for (; addr < 16; addr++) {
662 lockbit = (lock_bits >> (addr * 2)) & 3;
663 if (addr == 2) {
664 if (usePwd) {
665 data[addr] = BSWAP_32(pwd);
666 num_to_bytes(pwd, 4, bytes);
667 PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]);
668 } else {
669 data[addr] = 0x00; // Unknown password, but not used to set to zeros
670 PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]);
672 } else {
674 status = em4x05_read_word_ext(addr, pwd, usePwd, &word);
675 if (status != PM3_SUCCESS) {
676 success = PM3_ESOFT; // If any error ensure fail is set so not to save invalid data
679 data[addr] = BSWAP_32(word);
680 if (status == PM3_SUCCESS) {
681 num_to_bytes(word, 4, bytes);
682 PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, word, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]);
683 } else {
684 PrintAndLogEx(INFO, " %02u | | | | %-10s %s", addr, info4x69[addr], status == PM3_EFAILED ? _RED_("read denied") : _RED_("read failed"));
689 } else {
692 if (success == PM3_SUCCESS) { // all ok save dump to file
693 // saveFileEML will add .eml extension to filename
694 // saveFile (binary) passes in the .bin extension.
695 if (strcmp(filename, "") == 0) {
697 if (card_type == EM_4369) {
698 sprintf(filename, "lf-4369-%08X-dump", BSWAP_32(data[1]));
699 } else if (card_type == EM_4469) {
700 sprintf(filename, "lf-4469-%08X-dump", BSWAP_32(data[1]));
701 } else {
702 sprintf(filename, "lf-4x05-%08X-dump", BSWAP_32(data[1]));
706 PrintAndLogEx(NORMAL, "");
707 saveFileJSON(filename, (card_type == EM_4369 || card_type == EM_4469) ? jsfEM4x69 : jsfEM4x05, (uint8_t *)data, 16 * sizeof(uint32_t), NULL);
708 saveFileEML(filename, (uint8_t *)data, 16 * sizeof(uint32_t), sizeof(uint32_t));
709 saveFile(filename, ".bin", data, sizeof(data));
711 PrintAndLogEx(NORMAL, "");
712 return success;
715 int CmdEM4x05Read(const char *Cmd) {
717 CLIParserContext *ctx;
718 CLIParserInit(&ctx, "lf em 4x05 read",
719 "Read EM4x05/EM4x69. Tag must be on antenna.",
720 "lf em 4x05 read -a 1\n"
721 "lf em 4x05 read --addr 1 --pwd 11223344"
724 void *argtable[] = {
725 arg_param_begin,
726 arg_int1("a", "addr", "<dec>", "memory address to read. (0-15)"),
727 arg_str0("p", "pwd", "<hex>", "optional - password, 4 bytes hex"),
728 arg_param_end
730 CLIExecWithReturn(ctx, Cmd, argtable, true);
731 uint8_t addr = (uint8_t)arg_get_int_def(ctx, 1, 50);
732 uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 2, 0xFFFFFFFFFFFFFFFF);
733 CLIParserFree(ctx);
735 uint32_t pwd = 0;
736 bool use_pwd = false;
738 if (addr > 15) {
739 PrintAndLogEx(ERR, "Address must be between 0 and 15");
740 return PM3_EINVARG;
743 if (inputpwd == 0xFFFFFFFFFFFFFFFF) {
744 PrintAndLogEx(INFO, "Reading address %02u", addr);
745 } else {
746 pwd = (inputpwd & 0xFFFFFFFF);
747 use_pwd = true;
748 PrintAndLogEx(INFO, "Reading address %02u using password %08X", addr, pwd);
751 uint32_t word = 0;
752 int status = em4x05_read_word_ext(addr, pwd, use_pwd, &word);
753 if (status == PM3_SUCCESS)
754 PrintAndLogEx(SUCCESS, "Address %02d | %08X - %s", addr, word, (addr > 13) ? "Lock" : "");
755 else if (status == PM3_EFAILED)
756 PrintAndLogEx(ERR, "Tag denied Read operation");
757 else
758 PrintAndLogEx(WARNING, "No answer from tag");
759 return status;
762 int CmdEM4x05Write(const char *Cmd) {
763 CLIParserContext *ctx;
764 CLIParserInit(&ctx, "lf em 4x05 write",
765 "Write EM4x05/EM4x69. Tag must be on antenna.",
766 "lf em 4x05 write -a 1 -d deadc0de\n"
767 "lf em 4x05 write --addr 1 --pwd 11223344 --data deadc0de\n"
768 "lf em 4x05 write --po --pwd 11223344 --data deadc0de\n"
771 void *argtable[] = {
772 arg_param_begin,
773 arg_int0("a", "addr", "<dec>", "memory address to write to. (0-13)"),
774 arg_str1("d", "data", "<hex>", "data to write (4 hex bytes)"),
775 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
776 arg_lit0(NULL, "po", "protect operation"),
777 arg_param_end
779 CLIExecWithReturn(ctx, Cmd, argtable, true);
780 uint8_t addr = (uint8_t)arg_get_int_def(ctx, 1, 50);
781 uint32_t data = 0;
782 int res = arg_get_u32_hexstr_def(ctx, 2, 0, &data);
783 if (res == 2) {
784 CLIParserFree(ctx);
785 PrintAndLogEx(WARNING, "Data must be 4 hex bytes");
786 return PM3_EINVARG;
787 } else if (res == 0) {
788 CLIParserFree(ctx);
789 PrintAndLogEx(WARNING, "Data must be 4 hex bytes");
790 return PM3_EINVARG;
793 bool use_pwd = false;
794 uint32_t pwd = 0;
795 res = arg_get_u32_hexstr_def_nlen(ctx, 3, 0, &pwd, 4, true);
796 if (res == 2) {
797 CLIParserFree(ctx);
798 PrintAndLogEx(WARNING, "Password must be 4 hex bytes");
799 return PM3_EINVARG;
800 } else if (res == 3) {
801 use_pwd = false;
802 } else if (res == 1) {
803 use_pwd = true;
806 bool protect_operation = arg_get_lit(ctx, 4);
807 CLIParserFree(ctx);
809 if ((addr > 13) && (protect_operation == false)) {
810 PrintAndLogEx(WARNING, "Address must be between 0 and 13");
811 return PM3_EINVARG;
814 if (use_pwd) {
815 if (protect_operation)
816 PrintAndLogEx(INFO, "Writing protection words data %08X using password %08X", data, pwd);
817 else
818 PrintAndLogEx(INFO, "Writing address %d data %08X using password %08X", addr, data, pwd);
819 } else {
820 if (protect_operation)
821 PrintAndLogEx(INFO, "Writing protection words data %08X", data);
822 else
823 PrintAndLogEx(INFO, "Writing address %d data %08X", addr, data);
826 res = PM3_SUCCESS;
827 // set Protect Words
828 if (protect_operation) {
829 res = em4x05_protect(pwd, use_pwd, data);
830 if (res != PM3_SUCCESS) {
831 return res;
833 } else {
834 res = em4x05_write_word_ext(addr, pwd, use_pwd, data);
835 if (res != PM3_SUCCESS) {
836 return res;
840 if (em4x05_download_samples() == false)
841 return PM3_ENODATA;
843 uint32_t dummy = 0;
844 int status = em4x05_demod_resp(&dummy, true);
845 if (status == PM3_SUCCESS)
846 PrintAndLogEx(SUCCESS, "Data written and verified");
847 else if (status == PM3_EFAILED)
848 PrintAndLogEx(ERR, "Tag denied %s operation", protect_operation ? "Protect" : "Write");
849 else
850 PrintAndLogEx(DEBUG, "No answer from tag");
852 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05 read`") " to verify");
853 return status;
856 int CmdEM4x05Wipe(const char *Cmd) {
858 CLIParserContext *ctx;
859 CLIParserInit(&ctx, "lf em 4x05 wipe",
860 "Wipe EM4x05/EM4x69. Tag must be on antenna.",
861 "lf em 4x05 wipe --4305 -p 11223344 -> wipe EM 4305 w pwd\n"
862 "lf em 4x05 wipe --4205 -> wipe EM 4205\n"
863 "lf em 4x05 wipe --4369 -> wipe EM 4369"
866 void *argtable[] = {
867 arg_param_begin,
868 arg_lit0(NULL, "4205", "target chip type EM 4205"),
869 arg_lit0(NULL, "4305", "target chip type EM 4305 (default)"),
870 arg_lit0(NULL, "4369", "target chip type EM 4369"),
871 arg_lit0(NULL, "4369", "target chip type EM 4469"),
872 arg_str0("p", "pwd", "<hex>", "optional - password, 4 bytes hex"),
873 arg_param_end
875 CLIExecWithReturn(ctx, Cmd, argtable, false);
877 bool target_4205 = arg_get_lit(ctx, 1);
878 bool target_4305 = arg_get_lit(ctx, 2);
879 bool target_4369 = arg_get_lit(ctx, 3);
880 bool target_4469 = arg_get_lit(ctx, 4);
881 uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 5, 0xFFFFFFFFFFFFFFFF);
882 CLIParserFree(ctx);
884 uint8_t foo = target_4205 + target_4305 + target_4369 + target_4469;
886 if (foo > 1) {
887 PrintAndLogEx(ERR, "Can't target multiple chip types at the same time");
888 return PM3_EINVARG;
891 uint8_t addr = 0;
892 uint32_t chip_info = 0x00040072; // Chip info/User Block normal 4305 Chip Type
893 uint32_t chip_UID = 0x614739AE; // UID normally readonly, but just in case
894 uint32_t block_data = 0x00000000; // UserBlock/Password (set to 0x00000000 for a wiped card1
895 uint32_t config = 0x0001805F; // Default config (no password)
897 if (target_4205) {
898 chip_info = 0x00040070;
900 if (target_4369) {
901 chip_info = 0x00020078; // found on HID Prox
903 if (target_4469) {
904 // chip_info = 0x00020078; // need to get a normal 4469 chip info block
907 bool use_pwd = false;
908 uint32_t pwd = 0;
909 if (inputpwd != 0xFFFFFFFFFFFFFFFF) {
910 pwd = (inputpwd & 0xFFFFFFFF);
911 use_pwd = true;
913 // block 0 : User Data or Chip Info
914 int res = em4x05_write_word_ext(0, pwd, use_pwd, chip_info);
915 if (res != PM3_SUCCESS) {
916 return res;
919 // block 1 : UID - this should be read only for EM4205 and EM4305 not sure about others
920 res = em4x05_write_word_ext(1, pwd, use_pwd, chip_UID);
921 if (res != PM3_SUCCESS) {
922 PrintAndLogEx(INFO, "UID block write failed");
925 // block 2 : password
926 res = em4x05_write_word_ext(2, pwd, use_pwd, block_data);
927 if (res != PM3_SUCCESS) {
928 return res;
931 // Password should now have changed, so use new password
932 pwd = block_data;
933 // block 3 : user data
934 res = em4x05_write_word_ext(3, pwd, use_pwd, block_data);
935 if (res != PM3_SUCCESS) {
936 return res;
939 // block 4 : config
940 res = em4x05_write_word_ext(4, pwd, use_pwd, config);
941 if (res != PM3_SUCCESS) {
942 return res;
945 // Remainder of user/data blocks
946 for (addr = 5; addr < 14; addr++) {// Clear user data blocks
947 res = em4x05_write_word_ext(addr, pwd, use_pwd, block_data);
948 if (res != PM3_SUCCESS) {
949 return res;
952 return PM3_SUCCESS;
955 static const char *printEM4x05_known(uint32_t word) {
957 switch (word) {
958 // case EM4305_DEFAULT_CONFIG_BLOCK:
959 case EM4305_PRESCO_CONFIG_BLOCK: {
960 return "EM4305 DEFAULT / PRESCO";
962 // case EM4305_PAXTON_CONFIG_BLOCK:
963 case EM4305_EM_UNIQUE_CONFIG_BLOCK: {
964 return "EM UNIQUE / PAXTON";
966 case EM4305_VISA2000_CONFIG_BLOCK: {
967 return "VISA2000";
969 case EM4305_VIKING_CONFIG_BLOCK: {
970 return "VIKING";
972 case EM4305_NORALSY_CONFIG_BLOCK: {
973 return "NORALSY";
975 case EM4305_SECURAKEY_CONFIG_BLOCK: {
976 return "SECURAKEY";
978 // case EM4305_HID_26_CONFIG_BLOCK:
979 // case EM4305_PARADOX_CONFIG_BLOCK:
980 case EM4305_AWID_CONFIG_BLOCK: {
981 return "HID26 / PARADOX / AWID";
983 case EM4305_PYRAMID_CONFIG_BLOCK: {
984 return "PYRAMID";
986 case EM4305_IOPROX_CONFIG_BLOCK: {
987 return "IOPROX";
989 // case EM4305_KERI_CONFIG_BLOCK:
990 case EM4305_INDALA_64_CONFIG_BLOCK: {
991 return "INDALA 64 / KERI";
993 case EM4305_INDALA_224_CONFIG_BLOCK: {
994 return "INDALA 224";
996 case EM4305_MOTOROLA_CONFIG_BLOCK: {
997 return "MOTOROLA";
999 case EM4305_NEXWATCH_CONFIG_BLOCK: {
1000 return "NEXWATCH";
1002 // case EM4305_NEDAP_64_CONFIG_BLOCK:
1003 case EM4305_JABLOTRON_CONFIG_BLOCK: {
1004 return "JABLOTRON / NEDAP 64";
1006 case EM4305_GUARDPROXII_CONFIG_BLOCK: {
1007 return "GUARD PROXII";
1009 case EM4305_NEDAP_128_CONFIG_BLOCK: {
1010 return "NEDAP 128";
1012 case EM4305_PAC_CONFIG_BLOCK: {
1013 return "PAC/Stanley";
1015 case EM4305_VERICHIP_CONFIG_BLOCK: {
1016 return "VERICHIP";
1019 return "";
1022 static void printEM4x05config(em_tech_type_t card_type, uint32_t wordData) {
1023 uint16_t datarate = (((wordData & 0x3F) + 1) * 2);
1024 uint8_t encoder = ((wordData >> 6) & 0xF);
1025 char enc[14];
1026 memset(enc, 0, sizeof(enc));
1028 uint8_t PSKcf = (wordData >> 10) & 0x3;
1029 char cf[10];
1030 memset(cf, 0, sizeof(cf));
1031 uint8_t delay = (wordData >> 12) & 0x3;
1032 char cdelay[33];
1033 memset(cdelay, 0, sizeof(cdelay));
1034 uint8_t numblks = EM4x05_GET_NUM_BLOCKS(wordData);
1035 uint8_t LWR = numblks + 5 - 1; //last word read
1036 switch (encoder) {
1037 case 0:
1038 snprintf(enc, sizeof(enc), "NRZ");
1039 break;
1040 case 1:
1041 snprintf(enc, sizeof(enc), "Manchester");
1042 break;
1043 case 2:
1044 snprintf(enc, sizeof(enc), "Biphase");
1045 break;
1046 case 3:
1047 snprintf(enc, sizeof(enc), "Miller");
1048 break;
1049 case 4:
1050 snprintf(enc, sizeof(enc), "PSK1");
1051 break;
1052 case 5:
1053 snprintf(enc, sizeof(enc), "PSK2");
1054 break;
1055 case 6:
1056 snprintf(enc, sizeof(enc), "PSK3");
1057 break;
1058 case 7:
1059 snprintf(enc, sizeof(enc), "Unknown");
1060 break;
1061 case 8:
1062 snprintf(enc, sizeof(enc), "FSK1");
1063 break;
1064 case 9:
1065 snprintf(enc, sizeof(enc), "FSK2");
1066 break;
1067 default:
1068 snprintf(enc, sizeof(enc), "Unknown");
1069 break;
1072 switch (PSKcf) {
1073 case 0:
1074 snprintf(cf, sizeof(cf), "RF/2");
1075 break;
1076 case 1:
1077 snprintf(cf, sizeof(cf), "RF/8");
1078 break;
1079 case 2:
1080 snprintf(cf, sizeof(cf), "RF/4");
1081 break;
1082 case 3:
1083 snprintf(cf, sizeof(cf), "unknown");
1084 break;
1087 switch (delay) {
1088 case 0:
1089 snprintf(cdelay, sizeof(cdelay), "no delay");
1090 break;
1091 case 1:
1092 snprintf(cdelay, sizeof(cdelay), "BP/8 or 1/8th bit period delay");
1093 break;
1094 case 2:
1095 snprintf(cdelay, sizeof(cdelay), "BP/4 or 1/4th bit period delay");
1096 break;
1097 case 3:
1098 snprintf(cdelay, sizeof(cdelay), "no delay");
1099 break;
1101 uint8_t readLogin = (wordData & EM4x05_READ_LOGIN_REQ) >> 18;
1102 uint8_t readHKL = (wordData & EM4x05_READ_HK_LOGIN_REQ) >> 19;
1103 uint8_t writeLogin = (wordData & EM4x05_WRITE_LOGIN_REQ) >> 20;
1104 uint8_t writeHKL = (wordData & EM4x05_WRITE_HK_LOGIN_REQ) >> 21;
1105 uint8_t raw = (wordData & EM4x05_READ_AFTER_WRITE) >> 22;
1106 uint8_t disable = (wordData & EM4x05_DISABLE_ALLOWED) >> 23;
1107 uint8_t rtf = (wordData & EM4x05_READER_TALK_FIRST) >> 24;
1108 uint8_t invert = (wordData & EM4x05_INVERT) >> 25;
1109 uint8_t pigeon = (wordData & EM4x05_PIGEON) >> 26;
1111 PrintAndLogEx(NORMAL, "");
1112 PrintAndLogEx(INFO, "--- " _CYAN_("Config Information") " ------------------------");
1113 PrintAndLogEx(INFO, "ConfigWord: %08X ( " _YELLOW_("%s") " )", wordData, printEM4x05_known(wordData));
1115 PrintAndLogEx(INFO, " Data Rate: %02u | "_YELLOW_("RF/%u"), wordData & 0x3F, datarate);
1116 PrintAndLogEx(INFO, " Encoder: %u | " _YELLOW_("%s"), encoder, enc);
1117 if (card_type == EM_4369 || card_type == EM_4469) {
1118 PrintAndLogEx(INFO, " PSK CF: %u | %s", PSKcf, cf);
1119 } else if (PSKcf != 0) {
1120 PrintAndLogEx(INFO, "co10..c011: %u | %s", PSKcf, _RED_("Not used, must be set to logic 0"));
1122 if (card_type == EM_4305) {
1123 PrintAndLogEx(INFO, " Delay: %u | %s", delay, cdelay);
1124 } else if (delay != 0) {
1125 PrintAndLogEx(INFO, "co12..c013: %u | %s", delay, _RED_("Not used, must be set to logic 0"));
1127 PrintAndLogEx(INFO, " LastWordR: %02u | Address of last word for default read - meaning %u blocks are output", LWR, numblks);
1128 PrintAndLogEx(INFO, " ReadLogin: %u | Read login is %s", readLogin, readLogin ? _YELLOW_("required") : _GREEN_("not required"));
1129 if (card_type == EM_4369 || card_type == EM_4469) {
1130 PrintAndLogEx(INFO, " ReadHKL: %u | Read housekeeping words (3,4) login is %s", readHKL, readHKL ? _YELLOW_("required") : _GREEN_("not required"));
1131 } else if (readHKL != 0) {
1132 PrintAndLogEx(INFO, " c019: %u | %s", readHKL, _RED_("Not used, must be set to logic 0"));
1134 PrintAndLogEx(INFO, "WriteLogin: %u | Write login is %s", writeLogin, writeLogin ? _YELLOW_("required") : _GREEN_("not required"));
1135 if (card_type == EM_4369 || card_type == EM_4469) {
1136 PrintAndLogEx(INFO, " WriteHKL: %u | Write housekeeping words (2,3,4) login is %s", writeHKL, writeHKL ? _YELLOW_("required") : _GREEN_("not Required"));
1137 } else if (writeHKL != 0) {
1138 PrintAndLogEx(INFO, " c021: %u | %s", writeHKL, _RED_("Not used, must be set to logic 0"));
1140 if (card_type == EM_4369 || card_type == EM_4469) {
1141 PrintAndLogEx(INFO, " R.A.W.: %u | Read after write is %s", raw, raw ? "on" : "off");
1142 } else if (raw != 0) {
1143 PrintAndLogEx(INFO, " c022: %u | %s", raw, _RED_("Not used, must be set to logic 0"));
1145 PrintAndLogEx(INFO, " Disable: %u | Disable command is %s", disable, disable ? "accepted" : "not accepted");
1146 PrintAndLogEx(INFO, " R.T.F.: %u | Reader talk first is %s", rtf, rtf ? _YELLOW_("enabled") : "disabled");
1147 if (card_type == EM_4369) {
1148 PrintAndLogEx(INFO, " Invert: %u | Invert data? %s", invert, invert ? _YELLOW_("yes") : "no");
1149 } else if (invert != 0) {
1150 PrintAndLogEx(INFO, " c025: %u | %s", invert, _RED_("Not used, must be set to logic 0"));
1152 if (card_type == EM_4305) {
1153 PrintAndLogEx(INFO, " Pigeon: %u | Pigeon mode is %s", pigeon, pigeon ? _YELLOW_("enabled") : "disabled");
1154 } else if (pigeon != 0) {
1155 PrintAndLogEx(INFO, " c026: %u | %s", pigeon, _RED_("Not used, must be set to logic 0"));
1159 static void printEM4x05info(uint32_t block0, uint32_t serial) {
1161 uint8_t chipType = (block0 >> 1) & 0xF;
1162 uint8_t cap = (block0 >> 5) & 3;
1163 uint16_t custCode = (block0 >> 9) & 0x2FF;
1165 /* bits
1166 // 0, rfu
1167 // 1,2,3,4 chip type
1168 // 5,6 resonant cap
1169 // 7,8, rfu
1170 // 9 - 18 customer code
1171 // 19, rfu
1173 98765432109876543210
1174 001000000000
1175 // 00100000000001111000
1176 xxx----
1177 // 1100
1178 // 011
1179 // 00100000000
1182 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
1184 PrintAndLogEx(SUCCESS, " Block0: " _GREEN_("%08x"), block0);
1185 PrintAndLogEx(SUCCESS, " Chip Type: %3u | " _YELLOW_("%s"), chipType, em_get_card_str(block0));
1187 switch (cap) {
1188 case 3:
1189 PrintAndLogEx(SUCCESS, " Cap Type: %3u | 330pF", cap);
1190 break;
1191 case 2:
1192 PrintAndLogEx(SUCCESS, " Cap Type: %3u | %spF", cap, (chipType == 4) ? "75" : "210");
1193 break;
1194 case 1:
1195 PrintAndLogEx(SUCCESS, " Cap Type: %3u | 250pF", cap);
1196 break;
1197 case 0:
1198 PrintAndLogEx(SUCCESS, " Cap Type: %3u | no resonant capacitor", cap);
1199 break;
1200 default:
1201 PrintAndLogEx(SUCCESS, " Cap Type: %3u | unknown", cap);
1202 break;
1205 PrintAndLogEx(SUCCESS, " Cust Code: 0x%x | %s", custCode, (custCode == 0x200) ? "Default" : "Unknown");
1206 if (serial != 0)
1207 PrintAndLogEx(SUCCESS, " Serial #: " _YELLOW_("%08X"), serial);
1210 static void printEM4x05ProtectionBits(uint32_t word, uint8_t addr) {
1211 PrintAndLogEx(NORMAL, "");
1212 PrintAndLogEx(INFO, "--- " _CYAN_("Protection") " --------------------------------");
1213 PrintAndLogEx(INFO, "ProtectionWord: %08X (Word %i)", word, addr);
1214 for (uint8_t i = 0; i < 15; i++) {
1215 PrintAndLogEx(INFO, " Word: %02u | %s", i, ((1 << i) & word) ? _RED_("write Locked") : "unlocked");
1216 if (i == 14)
1217 PrintAndLogEx(INFO, " Word: %02u | %s", i + 1, ((1 << i) & word) ? _RED_("write locked") : "unlocked");
1221 //quick test for EM4x05/EM4x69 tag
1222 bool em4x05_isblock0(uint32_t *word) {
1223 return (em4x05_read_word_ext(0, 0, false, word) == PM3_SUCCESS);
1226 int CmdEM4x05Info(const char *Cmd) {
1228 CLIParserContext *ctx;
1229 CLIParserInit(&ctx, "lf em 4x05 info",
1230 "Tag information EM4205/4305/4469//4569 tags. Tag must be on antenna.",
1231 "lf em 4x05 info\n"
1232 "lf em 4x05 info -p 11223344"
1235 void *argtable[] = {
1236 arg_param_begin,
1237 arg_str0("p", "pwd", "<hex>", "optional - password, 4 hex bytes"),
1238 arg_param_end
1240 CLIExecWithReturn(ctx, Cmd, argtable, true);
1241 uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 1, 0xFFFFFFFFFFFFFFFF);
1242 CLIParserFree(ctx);
1244 bool use_pwd = false;
1245 uint32_t pwd = 0;
1246 if (inputpwd != 0xFFFFFFFFFFFFFFFF) {
1247 pwd = inputpwd & 0xFFFFFFFF;
1248 use_pwd = true;
1251 uint32_t word = 0, block0 = 0, serial = 0;
1253 // read word 0 (chip info)
1254 // block 0 can be read even without a password.
1255 if (em4x05_isblock0(&block0) == false)
1256 return PM3_ESOFT;
1258 // based on Block0 , decide type.
1259 em_tech_type_t card_type = em_get_card_type(block0);
1261 // read word 1 (serial #) doesn't need pwd
1262 // continue if failed, .. non blocking fail.
1263 em4x05_read_word_ext(EM_SERIAL_BLOCK, 0, false, &serial);
1265 printEM4x05info(block0, serial);
1267 // read word 4 (config block)
1268 // needs password if one is set
1269 if (em4x05_read_word_ext(EM_CONFIG_BLOCK, pwd, use_pwd, &word) != PM3_SUCCESS) {
1270 PrintAndLogEx(DEBUG, "(CmdEM4x05Info) failed to read CONFIG BLOCK");
1271 return PM3_ESOFT;
1274 printEM4x05config(card_type, word);
1276 // if 4469 read EM4469_PROT_BLOCK
1277 // if 4305 read 14,15
1278 if (card_type == EM_4205 || card_type == EM_4305) {
1280 // read word 14 and 15 to see which is being used for the protection bits
1281 if (em4x05_read_word_ext(EM4305_PROT1_BLOCK, pwd, use_pwd, &word) != PM3_SUCCESS) {
1282 return PM3_ESOFT;
1285 if (word & 0x8000) {
1286 printEM4x05ProtectionBits(word, EM4305_PROT1_BLOCK);
1287 return PM3_SUCCESS;
1288 } else { // if status bit says this is not the used protection word
1289 if (em4x05_read_word_ext(EM4305_PROT2_BLOCK, pwd, use_pwd, &word) != PM3_SUCCESS)
1290 return PM3_ESOFT;
1291 if (word & 0x8000) {
1292 printEM4x05ProtectionBits(word, EM4305_PROT2_BLOCK);
1293 return PM3_SUCCESS;
1296 } else if (card_type == EM_4369 || card_type == EM_4469) {
1297 // read word 3 to see which is being used for the protection bits
1298 if (em4x05_read_word_ext(EM4469_PROT_BLOCK, pwd, use_pwd, &word) != PM3_SUCCESS) {
1299 return PM3_ESOFT;
1301 printEM4x05ProtectionBits(word, EM4469_PROT_BLOCK);
1304 //something went wrong
1305 return PM3_ESOFT;
1308 static bool is_cancelled(void) {
1309 if (kbd_enter_pressed()) {
1310 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
1311 return true;
1313 return false;
1315 // load a default pwd file.
1316 int CmdEM4x05Chk(const char *Cmd) {
1318 CLIParserContext *ctx;
1319 CLIParserInit(&ctx, "lf em 4x05 chk",
1320 "This command uses a dictionary attack against EM4205/4305/4469/4569",
1321 "lf em 4x05 chk\n"
1322 "lf em 4x05 chk -e 000022B8 -> remember to use 0x for hex\n"
1323 "lf em 4x05 chk -f t55xx_default_pwds -> use T55xx default dictionary"
1326 void *argtable[] = {
1327 arg_param_begin,
1328 arg_strx0("f", "file", "<*.dic>", "loads a default keys dictionary file <*.dic>"),
1329 arg_str0("e", "em", "<EM4100>", "try the calculated password from some cloners based on EM4100 ID"),
1330 arg_param_end
1332 CLIExecWithReturn(ctx, Cmd, argtable, true);
1333 int fnlen = 0;
1334 char filename[FILE_PATH_SIZE] = {0};
1335 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
1337 uint64_t card_id = arg_get_u64_hexstr_def(ctx, 2, 0);
1338 CLIParserFree(ctx);
1340 if (strlen(filename) == 0) {
1341 snprintf(filename, sizeof(filename), "t55xx_default_pwds");
1343 PrintAndLogEx(NORMAL, "");
1345 bool found = false;
1346 uint64_t t1 = msclock();
1348 // White cloner password based on EM4100 ID
1349 if (card_id > 0) {
1351 uint32_t pwd = lf_t55xx_white_pwdgen(card_id & 0xFFFFFFFF);
1352 PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd);
1354 int status = em4x05_login_ext(pwd);
1355 if (status == PM3_SUCCESS) {
1356 PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd);
1357 found = true;
1358 } else if (status != PM3_EFAILED) {
1359 PrintAndLogEx(WARNING, "no answer from tag");
1363 // Loop dictionary
1364 uint8_t *keyBlock = NULL;
1365 if (found == false) {
1367 uint32_t keycount = 0;
1369 int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount);
1370 if (res != PM3_SUCCESS || keycount == 0 || keyBlock == NULL) {
1371 PrintAndLogEx(WARNING, "no keys found in file");
1372 if (keyBlock != NULL)
1373 free(keyBlock);
1375 return PM3_ESOFT;
1378 PrintAndLogEx(INFO, "press " _GREEN_("<Enter>") " to exit");
1380 for (uint32_t c = 0; c < keycount; ++c) {
1382 if (!session.pm3_present) {
1383 PrintAndLogEx(WARNING, "device offline\n");
1384 free(keyBlock);
1385 return PM3_ENODATA;
1388 if (is_cancelled()) {
1389 free(keyBlock);
1390 return PM3_EOPABORTED;
1393 uint32_t curr_password = bytes_to_num(keyBlock + 4 * c, 4);
1395 PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password);
1397 int status = em4x05_login_ext(curr_password);
1398 if (status == PM3_SUCCESS) {
1399 PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password);
1400 found = true;
1401 break;
1402 } else if (status != PM3_EFAILED) {
1403 PrintAndLogEx(WARNING, "no answer from tag");
1408 if (found == false)
1409 PrintAndLogEx(WARNING, "check pwd failed");
1411 free(keyBlock);
1413 t1 = msclock() - t1;
1414 PrintAndLogEx(SUCCESS, "\ntime in check pwd " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
1415 return PM3_SUCCESS;
1418 int CmdEM4x05Brute(const char *Cmd) {
1419 CLIParserContext *ctx;
1420 CLIParserInit(&ctx, "lf em 4x05 brute",
1421 "This command tries to bruteforce the password of a EM4205/4305/4469/4569\n",
1422 "Note: if you get many false positives, change position on the antenna"
1423 "lf em 4x05 brute\n"
1424 "lf em 4x05 brute -n 1 -> stop after first candidate found\n"
1425 "lf em 4x05 brute -s 000022B8 -> remember to use 0x for hex"
1428 void *argtable[] = {
1429 arg_param_begin,
1430 arg_u64_0("s", "start", "<pwd>", "Start bruteforce enumeration from this password value"),
1431 arg_int0("n", NULL, "<digits>", "Stop after having found n candidates. Default: 0 => infinite"),
1432 arg_param_end
1434 CLIExecWithReturn(ctx, Cmd, argtable, true);
1435 uint32_t start_pwd = arg_get_u64_hexstr_def(ctx, 1, 0);
1436 uint32_t n = arg_get_int_def(ctx, 2, 0);
1437 CLIParserFree(ctx);
1439 PrintAndLogEx(NORMAL, "");
1441 struct {
1442 uint32_t start_pwd;
1443 uint32_t n;
1444 } PACKED payload;
1446 payload.start_pwd = start_pwd;
1447 payload.n = n;
1449 clearCommandBuffer();
1450 SendCommandNG(CMD_LF_EM4X_BF, (uint8_t *)&payload, sizeof(payload));
1451 PacketResponseNG resp;
1452 if (!WaitForResponseTimeout(CMD_LF_EM4X_BF, &resp, 1000)) {
1453 PrintAndLogEx(WARNING, "(EM4x05 Bruteforce) timeout while waiting for reply.");
1454 return PM3_ETIMEOUT;
1456 PrintAndLogEx(INFO, "Bruteforce is running on device side, press button to interrupt");
1457 return PM3_SUCCESS;
1460 typedef struct {
1461 uint16_t cnt;
1462 uint32_t value;
1463 } em4x05_unlock_item_t;
1465 static int unlock_write_protect(bool use_pwd, uint32_t pwd, uint32_t data, bool verbose) {
1467 struct {
1468 uint32_t password;
1469 uint32_t data;
1470 uint8_t usepwd;
1471 } PACKED payload;
1473 payload.password = pwd;
1474 payload.data = data;
1475 payload.usepwd = use_pwd;
1477 clearCommandBuffer();
1478 SendCommandNG(CMD_LF_EM4X_PROTECTWORD, (uint8_t *)&payload, sizeof(payload));
1479 PacketResponseNG resp;
1480 if (WaitForResponseTimeout(CMD_LF_EM4X_PROTECTWORD, &resp, 2000) == false) {
1481 PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
1482 return PM3_ETIMEOUT;
1485 if (em4x05_download_samples() == false)
1486 return PM3_ENODATA;
1488 uint32_t dummy = 0;
1489 int status = em4x05_demod_resp(&dummy, true);
1490 if (status == PM3_SUCCESS && verbose)
1491 PrintAndLogEx(SUCCESS, "Data written and verified");
1492 else if (status == PM3_EFAILED)
1493 PrintAndLogEx(ERR, "Tag denied PROTECT operation");
1494 else
1495 PrintAndLogEx(DEBUG, "No answer from tag");
1497 return status;
1499 static int unlock_reset(bool use_pwd, uint32_t pwd, uint32_t data, bool verbose) {
1500 if (verbose)
1501 PrintAndLogEx(INFO, "resetting the " _RED_("active") " lock block");
1503 return unlock_write_protect(use_pwd, pwd, data, false);
1505 static void unlock_add_item(em4x05_unlock_item_t *array, uint8_t len, uint32_t value) {
1507 uint8_t i = 0;
1508 for (; i < len; i++) {
1509 if (array[i].value == value) {
1510 array[i].cnt++;
1511 break;
1513 if (array[i].cnt == 0) {
1514 array[i].cnt++;
1515 array[i].value = value;
1516 break;
1521 int CmdEM4x05Unlock(const char *Cmd) {
1523 CLIParserContext *ctx;
1524 CLIParserInit(&ctx, "lf em 4x05 unlock",
1525 "execute tear off against EM4205/4305/4469/4569",
1526 "lf em 4x05 unlock\n"
1527 "lf em 4x05 unlock -s 4100 -e 4100 -> lock on and autotune at 4100us\n"
1528 "lf em 4x05 unlock -n 10 -s 3000 -e 4400 -> scan delays 3000us -> 4400us"
1531 void *argtable[] = {
1532 arg_param_begin,
1533 arg_int0("n", NULL, NULL, "steps to skip"),
1534 arg_int0("s", "start", "<us>", "start scan from delay (us)"),
1535 arg_int0("e", "end", "<us>", "end scan at delay (us)"),
1536 arg_str0("p", "pwd", "<hex>", "password (def 00000000)"),
1537 arg_lit0("v", "verbose", "verbose output"),
1538 arg_param_end
1540 CLIExecWithReturn(ctx, Cmd, argtable, true);
1541 double n = (double)arg_get_int_def(ctx, 1, 0);
1542 double start = (double)arg_get_int_def(ctx, 2, 2000);
1543 double end = (double)arg_get_int_def(ctx, 3, 6000);
1544 uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 4, 0xFFFFFFFFFFFFFFFF);
1545 bool verbose = arg_get_lit(ctx, 5);
1546 CLIParserFree(ctx);
1548 if (start > end) {
1549 PrintAndLogEx(FAILED, "start delay can\'t be larger than end delay %.0lf vs %.0lf", start, end);
1550 return PM3_EINVARG;
1553 if (session.pm3_present == false) {
1554 PrintAndLogEx(WARNING, "device offline\n");
1555 return PM3_ENODATA;
1558 bool use_pwd = false;
1559 uint32_t pwd = 0;
1560 if (inputpwd != 0xFFFFFFFFFFFFFFFF) {
1561 use_pwd = true;
1562 pwd = inputpwd & 0xFFFFFFFF;
1565 uint32_t search_value = 0;
1566 uint32_t write_value = 0;
1568 // inital phase
1570 // read word 14
1571 uint32_t init_14 = 0;
1572 int res = em4x05_read_word_ext(14, pwd, use_pwd, &init_14);
1573 if (res != PM3_SUCCESS) {
1574 PrintAndLogEx(FAILED, "failed to read word 14\n");
1575 return PM3_ENODATA;
1579 // read 15
1580 uint32_t init_15 = 0;
1581 res = em4x05_read_word_ext(15, pwd, use_pwd, &init_15);
1582 if (res != PM3_SUCCESS) {
1583 PrintAndLogEx(FAILED, "failed to read word 15\n");
1584 return PM3_ENODATA;
1587 #define ACTIVE_MASK 0x00008000
1588 if ((init_15 & ACTIVE_MASK) == ACTIVE_MASK) {
1589 search_value = init_15;
1590 } else {
1591 search_value = init_14;
1594 if (search_value == ACTIVE_MASK) {
1595 PrintAndLogEx(SUCCESS, "Tag already fully unlocked, nothing to do");
1596 return PM3_SUCCESS;
1599 bool my_auto = false;
1600 if (n == 0) {
1601 my_auto = true;
1602 n = (end - start) / 2;
1605 // fix at one specific delay
1606 if (start == end) {
1607 n = 0;
1610 PrintAndLogEx(INFO, "--------------- " _CYAN_("EM4x05 tear-off : target PROTECT") " -----------------------\n");
1612 PrintAndLogEx(INFO, "initial prot 14&15 [ " _GREEN_("%08X") ", " _GREEN_("%08X") " ]", init_14, init_15);
1614 if (use_pwd) {
1615 PrintAndLogEx(INFO, " target password [ " _GREEN_("%08X") " ]", pwd);
1617 if (my_auto) {
1618 PrintAndLogEx(INFO, " automatic mode [ " _GREEN_("enabled") " ]");
1621 PrintAndLogEx(INFO, " target stepping [ " _GREEN_("%.0lf") " ]", n);
1622 PrintAndLogEx(INFO, "target delay range [ " _GREEN_("%.0lf") " ... " _GREEN_("%.0lf") " ]", start, end);
1623 PrintAndLogEx(INFO, " search value [ " _GREEN_("%08X") " ]", search_value);
1624 PrintAndLogEx(INFO, " write value [ " _GREEN_("%08X") " ]", write_value);
1626 PrintAndLogEx(INFO, "----------------------------------------------------------------------------\n");
1627 PrintAndLogEx(NORMAL, "");
1628 PrintAndLogEx(INFO, "press " _GREEN_("<Enter>'") " to exit");
1629 PrintAndLogEx(NORMAL, "");
1630 PrintAndLogEx(INFO, "--------------- " _CYAN_("start") " -----------------------\n");
1632 int exit_code = PM3_SUCCESS;
1633 uint32_t word14 = 0, word15 = 0;
1634 uint32_t word14b = 0, word15b = 0;
1635 uint32_t tries = 0;
1636 uint32_t soon = 0;
1637 uint32_t late = 0;
1639 em4x05_unlock_item_t flipped[64] = {{0, 0}};
1642 // main loop
1644 bool success = false;
1645 uint64_t t1 = msclock();
1646 while (start <= end) {
1648 if (my_auto && n < 1) {
1649 PrintAndLogEx(INFO, "Reached n < 1 => " _YELLOW_("disabling automatic mode"));
1650 end = start;
1651 my_auto = false;
1652 n = 0;
1655 if (my_auto == false) {
1656 start += n;
1659 if (tries >= 5 && n == 0 && soon != late) {
1661 if (soon > late) {
1662 PrintAndLogEx(INFO, "Tried %d times, soon:%i late:%i => " _CYAN_("adjust +1 us >> %.0lf us"), tries, soon, late, start);
1663 start++;
1664 end++;
1665 } else {
1666 PrintAndLogEx(INFO, "Tried %d times, soon:%i late:%i => " _CYAN_("adjust -1 us >> %.0lf us"), tries, soon, late, start);
1667 start--;
1668 end--;
1670 tries = 0;
1671 soon = 0;
1672 late = 0;
1675 if (is_cancelled()) {
1676 exit_code = PM3_EOPABORTED;
1677 break;
1680 // set tear off trigger
1681 clearCommandBuffer();
1682 tearoff_params_t params = {
1683 .delay_us = start,
1684 .on = true,
1685 .off = false
1687 res = handle_tearoff(&params, verbose);
1688 if (res != PM3_SUCCESS) {
1689 PrintAndLogEx(WARNING, "failed to configure tear off");
1690 return PM3_ESOFT;
1693 // write
1694 // don't check the return value. As a tear-off occurred, the write failed.
1695 unlock_write_protect(use_pwd, pwd, write_value, verbose);
1697 // read after trigger
1698 res = em4x05_read_word_ext(14, pwd, use_pwd, &word14);
1699 if (res != PM3_SUCCESS) {
1700 PrintAndLogEx(WARNING, "failed to read 14");
1701 return PM3_ESOFT;
1704 // read after trigger
1705 res = em4x05_read_word_ext(15, pwd, use_pwd, &word15);
1706 if (res != PM3_SUCCESS) {
1707 PrintAndLogEx(WARNING, "failed to read 15");
1708 return PM3_ESOFT;
1711 if (verbose)
1712 PrintAndLogEx(INFO, "ref:%08X 14:%08X 15:%08X ", search_value, word14, word15);
1714 if (word14 == search_value && word15 == 0) {
1715 PrintAndLogEx(INFO, "Status: Nothing happened => " _GREEN_("tearing too soon"));
1717 if (my_auto) {
1718 start += n;
1719 PrintAndLogEx(INFO, " => " _CYAN_("adjust +%.0lf us >> %.0lf us"), n, start);
1720 n /= 2;
1721 } else {
1722 soon++;
1724 } else {
1726 if (word15 == search_value) {
1728 if (word14 == 0) {
1729 PrintAndLogEx(INFO, "Status: Protect succeeded => " _GREEN_("tearing too late"));
1730 } else {
1731 if (word14 == search_value) {
1732 PrintAndLogEx(INFO, "Status: 15 ok, 14 not yet erased => " _GREEN_("tearing too late"));
1733 } else {
1734 PrintAndLogEx(INFO, "Status: 15 ok, 14 partially erased => " _GREEN_("tearing too late"));
1738 unlock_reset(use_pwd, pwd, write_value, verbose);
1740 // read after reset
1741 res = em4x05_read_word_ext(14, pwd, use_pwd, &word14b);
1742 if (res != PM3_SUCCESS) {
1743 PrintAndLogEx(WARNING, "failed to read 14");
1744 return PM3_ESOFT;
1747 if (word14b == 0) {
1749 unlock_reset(use_pwd, pwd, write_value, verbose);
1751 res = em4x05_read_word_ext(14, pwd, use_pwd, &word14b);
1752 if (res != PM3_SUCCESS) {
1753 PrintAndLogEx(WARNING, "failed to read 14");
1754 return PM3_ESOFT;
1758 if (word14b != search_value) {
1760 res = em4x05_read_word_ext(15, pwd, use_pwd, &word15b);
1761 if (res == PM3_SUCCESS) {
1762 PrintAndLogEx(INFO, "Status: new definitive value! => " _RED_("SUCCESS:") " 14: " _CYAN_("%08X") " 15: %08X", word14b, word15b);
1763 success = true;
1764 break;
1765 } else {
1766 PrintAndLogEx(WARNING, "failed to read 15");
1767 return PM3_ESOFT;
1770 if (my_auto) {
1771 end = start;
1772 start -= n;
1773 PrintAndLogEx(INFO, " => " _CYAN_("adjust -%.0lf us >> %.0lf us"), n, start);
1774 n /= 2;
1775 } else {
1776 late++;
1779 } else {
1781 if ((word15 & ACTIVE_MASK) == ACTIVE_MASK) {
1783 PrintAndLogEx(INFO, "Status: 15 bitflipped and active => " _RED_("SUCCESS?: ") "14: %08X 15: " _CYAN_("%08X"), word14, word15);
1784 PrintAndLogEx(INFO, "Committing results...");
1786 unlock_reset(use_pwd, pwd, write_value, verbose);
1788 // read after reset
1789 res = em4x05_read_word_ext(14, pwd, use_pwd, &word14b);
1790 if (res != PM3_SUCCESS) {
1791 PrintAndLogEx(WARNING, "failed to read 14");
1792 return PM3_ESOFT;
1795 res = em4x05_read_word_ext(15, pwd, use_pwd, &word15b);
1796 if (res != PM3_SUCCESS) {
1797 PrintAndLogEx(WARNING, "failed to read 15");
1798 return PM3_ESOFT;
1801 if (verbose)
1802 PrintAndLogEx(INFO, "ref:%08x 14:%08X 15:%08X", search_value, word14b, word15b);
1804 if ((word14b & ACTIVE_MASK) == ACTIVE_MASK) {
1806 if (word14b == word15) {
1807 PrintAndLogEx(INFO, "Status: confirmed => " _GREEN_("SUCCESS: ") "14: " _GREEN_("%08X") " 15: %08X", word14b, word15b);
1809 unlock_add_item(flipped, 64, word14b);
1810 success = true;
1811 break;
1814 if (word14b != search_value) {
1815 PrintAndLogEx(INFO, "Status: new definitive value! => " _RED_("SUCCESS: ") "14: " _CYAN_("%08X") " 15: %08X", word14b, word15b);
1817 unlock_add_item(flipped, 64, word14b);
1818 success = true;
1819 break;
1822 PrintAndLogEx(INFO, "Status: failed to commit bitflip => " _RED_("FAIL: ") "14: %08X 15: %08X", word14b, word15b);
1824 if (my_auto) {
1825 n = 0;
1826 end = start;
1827 } else {
1828 tries = 0;
1829 soon = 0;
1830 late = 0;
1832 } else {
1833 PrintAndLogEx(INFO, "Status: 15 bitflipped but inactive => " _YELLOW_("PROMISING: ") "14: %08X 15: " _CYAN_("%08X"), word14, word15);
1835 unlock_add_item(flipped, 64, word15);
1837 soon ++;
1842 if (my_auto == false) {
1843 tries++;
1847 PrintAndLogEx(INFO, "----------------------------- " _CYAN_("exit") " ----------------------------------\n");
1848 t1 = msclock() - t1;
1849 PrintAndLogEx(SUCCESS, "\ntime in unlock " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
1850 if (success) {
1851 uint32_t bitflips = search_value ^ word14b;
1852 PrintAndLogEx(INFO, "Old protection word => " _YELLOW_("%08X"), search_value);
1853 char bitstring[9] = {0};
1854 for (int i = 0; i < 8; i++) {
1855 bitstring[i] = (bitflips & (0xFU << ((7 - i) * 4))) ? 'x' : '.';
1857 // compute number of bits flipped
1858 PrintAndLogEx(INFO, "Bitflips: %2u events => %s", bitcount32(bitflips), bitstring);
1859 PrintAndLogEx(INFO, "New protection word => " _CYAN_("%08X") "\n", word14b);
1860 PrintAndLogEx(INFO, "Try " _YELLOW_("`lf em 4x05_dump`"));
1863 if (verbose) {
1864 PrintAndLogEx(NORMAL, "Stats:");
1865 PrintAndLogEx(INFO, " idx | value | cnt | flipped bits");
1866 PrintAndLogEx(INFO, "-----+----------+-----+------");
1867 for (uint8_t i = 0; i < 64; i++) {
1868 if (flipped[i].cnt == 0)
1869 break;
1871 PrintAndLogEx(INFO, " %3u | %08X | %3u | %u", i, flipped[i].value, flipped[i].cnt, bitcount32(search_value ^ flipped[i].value));
1874 PrintAndLogEx(NORMAL, "");
1875 return exit_code;
1878 static size_t em4x05_Sniff_GetNextBitStart(size_t idx, size_t sc, int *data, size_t *pulsesamples) {
1879 while ((idx < sc) && (data[idx] <= 10)) // find a going high
1880 idx++;
1882 while ((idx < sc) && (data[idx] > -10)) // find going low may need to add something here it SHOULD be a small clk around 0, but white seems to extend a bit.
1883 idx++;
1885 (*pulsesamples) = 0;
1886 while ((idx < sc) && ((data[idx + 1] - data[idx]) < 10)) { // find "sharp rise"
1887 (*pulsesamples)++;
1888 idx++;
1891 return idx;
1894 uint32_t static em4x05_Sniff_GetBlock(char *bits, bool fwd) {
1895 uint32_t value = 0;
1896 uint8_t idx;
1897 bool parityerror = false;
1898 uint8_t parity;
1900 parity = 0;
1901 for (idx = 0; idx < 8; idx++) {
1902 value <<= 1;
1903 value += (bits[idx] - '0');
1904 parity += (bits[idx] - '0');
1906 parity = parity % 2;
1907 if (parity != (bits[8] - '0'))
1908 parityerror = true;
1910 parity = 0;
1911 for (idx = 9; idx < 17; idx++) {
1912 value <<= 1;
1913 value += (bits[idx] - '0');
1914 parity += (bits[idx] - '0');
1916 parity = parity % 2;
1917 if (parity != (bits[17] - '0'))
1918 parityerror = true;
1920 parity = 0;
1921 for (idx = 18; idx < 26; idx++) {
1922 value <<= 1;
1923 value += (bits[idx] - '0');
1924 parity += (bits[idx] - '0');
1926 parity = parity % 2;
1927 if (parity != (bits[26] - '0'))
1928 parityerror = true;
1930 parity = 0;
1931 for (idx = 27; idx < 35; idx++) {
1932 value <<= 1;
1933 value += (bits[idx] - '0');
1934 parity += (bits[idx] - '0');
1936 parity = parity % 2;
1937 if (parity != (bits[35] - '0'))
1938 parityerror = true;
1940 if (parityerror)
1941 PrintAndLogEx(ERR, "parity error : ");
1943 if (!fwd) {
1944 uint32_t t1 = value;
1945 value = 0;
1946 for (idx = 0; idx < 32; idx++)
1947 value |= (((t1 >> idx) & 1) << (31 - idx));
1949 return value;
1952 int CmdEM4x05Sniff(const char *Cmd) {
1954 bool pwd = false, fwd = false;
1955 bool haveData, sampleData = true;
1957 CLIParserContext *ctx;
1958 CLIParserInit(&ctx, "lf em 4x05 sniff",
1959 "Sniff EM4x05 commands sent from a programmer",
1960 "lf em 4x05 sniff --> sniff via lf sniff\n"
1961 "lf em 4x05 sniff -1 --> sniff from data loaded into the buffer\n"
1962 "lf em 4x05 sniff -r --> reverse the bit order when showing block data"
1965 void *argtable[] = {
1966 arg_param_begin,
1967 arg_lit0("1", "buf", "Use the data in the buffer"),
1968 arg_lit0("r", "rev", "Reverse the bit order for data blocks"),
1969 arg_param_end
1971 CLIExecWithReturn(ctx, Cmd, argtable, true);
1972 sampleData = (arg_get_lit(ctx, 1) == false);
1973 fwd = arg_get_lit(ctx, 2);
1974 CLIParserFree(ctx);
1976 char cmdText[100];
1977 char dataText[100];
1978 char blkAddr[4];
1979 char bits[80];
1980 int i, bitidx;
1981 int ZeroWidth; // 32-42 "1" is 32
1982 int CycleWidth;
1983 size_t idx = 0, pulseSamples, pktOffset;
1984 uint32_t tmpValue;
1985 bool eop = false;
1987 // setup and sample data from Proxmark
1988 // if not directed to existing sample/graphbuffer
1989 if (sampleData) {
1990 if (IfPm3Lf() == false) {
1991 PrintAndLogEx(WARNING, "Only offline mode is available");
1992 return PM3_EINVARG;
1994 CmdLFSniff("");
1997 // Headings
1998 PrintAndLogEx(NORMAL, "");
1999 PrintAndLogEx(INFO, _CYAN_("EM4x05 command detection"));
2000 PrintAndLogEx(SUCCESS, "offset | Command | Data | blk | raw");
2001 PrintAndLogEx(SUCCESS, "-------+-------------+----------+-----+------------------------------------------------------------");
2003 idx = 0;
2004 // loop though sample buffer
2005 while (idx < GraphTraceLen) {
2006 eop = false;
2007 haveData = false;
2008 pwd = false;
2010 idx = em4x05_Sniff_GetNextBitStart(idx, GraphTraceLen, GraphBuffer, &pulseSamples);
2011 pktOffset = idx;
2012 if (pulseSamples >= 10) { // Should be 18 so a bit less to allow for processing
2014 // Use first bit to get "0" bit samples as a reference
2015 ZeroWidth = idx;
2016 idx = em4x05_Sniff_GetNextBitStart(idx, GraphTraceLen, GraphBuffer, &pulseSamples);
2017 ZeroWidth = idx - ZeroWidth;
2019 if (ZeroWidth <= 50) {
2020 pktOffset -= ZeroWidth;
2021 memset(bits, 0x00, sizeof(bits));
2022 bitidx = 0;
2024 while ((idx < GraphTraceLen) && !eop) {
2025 CycleWidth = idx;
2026 idx = em4x05_Sniff_GetNextBitStart(idx, GraphTraceLen, GraphBuffer, &pulseSamples);
2028 CycleWidth = idx - CycleWidth;
2029 if ((CycleWidth > 300) || (CycleWidth < (ZeroWidth - 5))) { // to long or too short
2030 eop = true;
2031 bits[bitidx++] = '0'; // Append last zero from the last bit find
2032 cmdText[0] = 0;
2034 // EM4305 command lengths
2035 // Login 0011 <pwd> => 4 + 45 => 49
2036 // Write Word 0101 <adr> <data> => 4 + 7 + 45 => 56
2037 // Read Word 1001 <adr> => 4 + 7 => 11
2038 // Protect 1100 <data> => 4 + 45 => 49
2039 // Disable 1010 <data> => 4 + 45 => 49
2040 // -> disable 1010 11111111 0 11111111 0 11111111 0 11111111 0 00000000 0
2042 // Check to see if we got the leading 0
2043 if (((strncmp(bits, "00011", 5) == 0) && (bitidx == 50)) ||
2044 ((strncmp(bits, "00101", 5) == 0) && (bitidx == 57)) ||
2045 ((strncmp(bits, "01001", 5) == 0) && (bitidx == 12)) ||
2046 ((strncmp(bits, "01100", 5) == 0) && (bitidx == 50)) ||
2047 ((strncmp(bits, "01010", 5) == 0) && (bitidx == 50))) {
2048 memmove(bits, &bits[1], bitidx - 1);
2049 bitidx--;
2050 PrintAndLogEx(INFO, "Trim leading 0");
2052 bits[bitidx] = 0;
2054 // logon
2055 if ((strncmp(bits, "0011", 4) == 0) && (bitidx == 49)) {
2056 haveData = true;
2057 pwd = true;
2058 sprintf(cmdText, "Logon");
2059 sprintf(blkAddr, " ");
2060 tmpValue = em4x05_Sniff_GetBlock(&bits[4], fwd);
2061 sprintf(dataText, "%08X", tmpValue);
2064 // write
2065 if ((strncmp(bits, "0101", 4) == 0) && (bitidx == 56)) {
2066 haveData = true;
2067 sprintf(cmdText, "Write");
2068 tmpValue = (bits[4] - '0') + ((bits[5] - '0') << 1) + ((bits[6] - '0') << 2) + ((bits[7] - '0') << 3);
2069 sprintf(blkAddr, "%u", tmpValue);
2070 if (tmpValue == 2) {
2071 pwd = true;
2073 tmpValue = em4x05_Sniff_GetBlock(&bits[11], fwd);
2074 sprintf(dataText, "%08X", tmpValue);
2077 // read
2078 if ((strncmp(bits, "1001", 4) == 0) && (bitidx == 11)) {
2079 haveData = true;
2080 pwd = false;
2081 sprintf(cmdText, "Read");
2082 tmpValue = (bits[4] - '0') + ((bits[5] - '0') << 1) + ((bits[6] - '0') << 2) + ((bits[7] - '0') << 3);
2083 sprintf(blkAddr, "%u", tmpValue);
2084 sprintf(dataText, " ");
2087 // protect
2088 if ((strncmp(bits, "1100", 4) == 0) && (bitidx == 49)) {
2089 haveData = true;
2090 pwd = false;
2091 sprintf(cmdText, "Protect");
2092 sprintf(blkAddr, " ");
2093 tmpValue = em4x05_Sniff_GetBlock(&bits[11], fwd);
2094 sprintf(dataText, "%08X", tmpValue);
2097 // disable
2098 if ((strncmp(bits, "1010", 4) == 0) && (bitidx == 49)) {
2099 haveData = true;
2100 pwd = false;
2101 sprintf(cmdText, "Disable");
2102 sprintf(blkAddr, " ");
2103 tmpValue = em4x05_Sniff_GetBlock(&bits[11], fwd);
2104 sprintf(dataText, "%08X", tmpValue);
2107 // bits[bitidx] = 0;
2108 } else {
2109 i = (CycleWidth - ZeroWidth) / 28;
2110 bits[bitidx++] = '0';
2111 for (int ii = 0; ii < i; ii++) {
2112 bits[bitidx++] = '1';
2118 idx++;
2120 // Print results
2121 if (haveData) { //&& (minWidth > 1) && (maxWidth > minWidth)){
2122 if (pwd)
2123 PrintAndLogEx(SUCCESS, "%6zu | %-10s | " _YELLOW_("%8s")" | " _YELLOW_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits);
2124 else
2125 PrintAndLogEx(SUCCESS, "%6zu | %-10s | " _GREEN_("%8s")" | " _GREEN_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits);
2129 // footer
2130 PrintAndLogEx(SUCCESS, "---------------------------------------------------------------------------------------------------");
2131 PrintAndLogEx(NORMAL, "");
2132 return PM3_SUCCESS;
2135 static command_t CommandTable[] = {
2136 {"help", CmdHelp, AlwaysAvailable, "This help"},
2137 {"brute", CmdEM4x05Brute, IfPm3Lf, "Bruteforce password"},
2138 {"chk", CmdEM4x05Chk, IfPm3Lf, "Check passwords from dictionary"},
2139 {"demod", CmdEM4x05Demod, AlwaysAvailable, "demodulate a EM4x05/EM4x69 tag from the GraphBuffer"},
2140 {"dump", CmdEM4x05Dump, IfPm3Lf, "dump EM4x05/EM4x69 tag"},
2141 {"info", CmdEM4x05Info, IfPm3Lf, "tag information EM4x05/EM4x69"},
2142 {"read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"},
2143 {"sniff", CmdEM4x05Sniff, AlwaysAvailable, "Attempt to recover em4x05 commands from sample buffer"},
2144 {"unlock", CmdEM4x05Unlock, IfPm3Lf, "execute tear off against EM4x05/EM4x69"},
2145 {"wipe", CmdEM4x05Wipe, IfPm3Lf, "wipe EM4x05/EM4x69 tag"},
2146 {"write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"},
2147 {NULL, NULL, NULL, NULL}
2150 static int CmdHelp(const char *Cmd) {
2151 (void)Cmd; // Cmd is not used so far
2152 CmdsHelp(CommandTable);
2153 return PM3_SUCCESS;
2156 int CmdLFEM4X05(const char *Cmd) {
2157 clearCommandBuffer();
2158 return CmdsParse(CommandTable, Cmd);