1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
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
7 //-----------------------------------------------------------------------------
8 // Low frequency EM4x commands
9 //-----------------------------------------------------------------------------
11 #include "cmdlfem4x05.h"
19 #include "util_posix.h" // msclock
20 #include "fileutils.h"
21 #include "cmdparser.h" // command_t
23 #include "commonutil.h"
25 #include "util_posix.h"
26 #include "protocols.h"
33 #include "generator.h"
34 #include "cliparser.h"
37 //////////////// 4205 / 4305 commands
39 #define EM_PREAMBLE_LEN 8
41 static int CmdHelp(const char *Cmd
);
45 static em_tech_type_t
em_get_card_type(uint32_t config
) {
46 uint8_t t
= (config
>> 1) & 0xF;
60 static const char *em_get_card_str(uint32_t config
) {
61 switch (em_get_card_type(config
)) {
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;
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;
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)
96 if (!GetFromDevice(BIG_BUF
, got
, sizeof(got
), 0, NULL
, 0, NULL
, 2500, false)) {
97 PrintAndLogEx(WARNING
, "(em_download_samples) command execution time out");
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");
113 static int doPreambleSearch(size_t *startIdx
) {
116 if (DemodBufferLen
< EM_PREAMBLE_LEN
) {
117 PrintAndLogEx(DEBUG
, "DEBUG: Error - EM4305 demodbuffer too small");
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;
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
);
135 return PM3_EFAILED
; // Error preamble found
141 static bool detectFSK(void) {
143 if (GetFskClock("", false) == 0) {
144 PrintAndLogEx(DEBUG
, "DEBUG: Error - EM: FSK clock failed");
148 int ans
= FSKrawDemod(0, 0, 0, 0, false);
149 if (ans
!= PM3_SUCCESS
) {
150 PrintAndLogEx(DEBUG
, "DEBUG: Error - EM: FSK Demod failed");
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);
159 PrintAndLogEx(DEBUG
, "DEBUG: Error - EM: PSK clock failed");
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");
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;
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)) {
181 ans
= PSKDemod(0, 1, 6, false);
182 if (ans
!= PM3_SUCCESS
) {
183 PrintAndLogEx(DEBUG
, "DEBUG: Error - EM: PSK1 inverted Demod failed");
187 if (!preambleSearchEx(DemodBuffer
, preamble
, EM_PREAMBLE_LEN
, &size
, &startIdx
, true)) {
188 PrintAndLogEx(DEBUG
, "DEBUG: Error - EM: PSK1 inverted Demod failed 2");
193 // either PSK1 or PSK1 inverted is ok from here.
194 // lets check PSK2 later.
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");
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");
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");
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");
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");
251 setDemodBuff(DemodBuffer
, 32, 0);
252 *word
= bytebits_to_byteLSBF(DemodBuffer
, 32);
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
) {
263 bool found_err
= false;
265 if (detectASK_MAN()) {
266 res
= doPreambleSearch(&idx
);
267 if (res
== PM3_SUCCESS
)
269 if (res
== PM3_EFAILED
)
270 // go on, maybe it's false positive and another modulation will work
273 if (detectASK_BI()) {
274 res
= doPreambleSearch(&idx
);
275 if (res
== PM3_SUCCESS
)
277 if (res
== PM3_EFAILED
)
281 res
= doPreambleSearch(&idx
);
282 if (res
== PM3_SUCCESS
)
284 if (res
== PM3_EFAILED
)
288 res
= doPreambleSearch(&idx
);
289 if (res
== PM3_SUCCESS
)
291 if (res
== PM3_EFAILED
)
295 res
= doPreambleSearch(&idx
);
296 if (res
== PM3_SUCCESS
)
299 if (res
== PM3_EFAILED
)
302 psk1TOpsk2(DemodBuffer
, DemodBufferLen
);
303 res
= doPreambleSearch(&idx
);
304 if (res
== PM3_SUCCESS
)
307 if (res
== PM3_EFAILED
)
320 res
= em4x05_setdemod_buffer(word
, idx
);
321 if (res
== PM3_SUCCESS
)
330 //////////////// 4205 / 4305 commands
332 static bool em4x05_verify_write(uint8_t addr
, uint32_t pwd
, bool use_pwd
, uint32_t data
) {
334 int res
= em4x05_read_word_ext(addr
, pwd
, use_pwd
, &r
);
335 if (res
== PM3_SUCCESS
) {
336 PrintAndLogEx(INFO
, "%08x == %08x", r
, data
);
342 int em4x05_clone_tag(uint32_t *blockdata
, uint8_t numblocks
, uint32_t pwd
, bool use_pwd
) {
344 if (blockdata
== NULL
)
347 if (numblocks
< 1 || numblocks
> 8)
351 conn
.block_after_ACK
= true;
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;
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");
372 for (int8_t i
= 0; i
< numblocks
; i
++) {
373 if (em4x05_verify_write(4 + i
, use_pwd
, pwd
, blockdata
[i
]) == false) {
379 PrintAndLogEx(SUCCESS
, "Data written and verified");
384 static int em4x05_login_ext(uint32_t pwd
) {
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.");
400 if (em4x05_download_samples() == false) {
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
) {
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.");
427 if (em4x05_download_samples() == false) {
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
) {
441 payload
.password
= pwd
;
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.");
456 static int em4x05_protect(uint32_t pwd
, bool use_pwd
, uint32_t data
) {
463 payload
.password
= pwd
;
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.");
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",
488 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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.",
500 "lf em 4x05 dump -p 11223344\n"
501 "lf em 4x05 dump -f myfile -p 11223344"
506 arg_str0("p", "pwd", "<hex>", "password (00000000)"),
507 arg_str0("f", "file", "<fn>", "override filename prefix (optional). Default is based on UID"),
510 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
512 uint64_t inputpwd
= arg_get_u64_hexstr_def(ctx
, 1, 0xFFFFFFFFFFFFFFFF);
514 char filename
[FILE_PATH_SIZE
] = {0};
515 CLIParamStrToBuf(arg_get_str(ctx
, 2), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
521 if (inputpwd
!= 0xFFFFFFFFFFFFFFFF) {
523 if (inputpwd
& 0xFFFFFFFF00000000) {
524 PrintAndLogEx(FAILED
, "Pwd too large");
529 pwd
= (inputpwd
& 0xFFFFFFFF);
533 // read word 0 (chip info)
534 // block 0 can be read even without a password.
535 if (em4x05_isblock0(&block0
) == false)
538 uint8_t bytes
[4] = {0};
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;
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"};
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
));
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");
564 } else if (status
!= PM3_EFAILED
) {
565 PrintAndLogEx(WARNING
, "Login attempt: no answer from tag");
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) {
585 data
[EM4305_PROT1_BLOCK
] = word
;
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
596 data
[EM4305_PROT2_BLOCK
] = word
;
598 success
= PM3_ESOFT
; // If any error ensure fail is set so not to save invalid data
601 // Now read blocks 0 - 13 as we have 14 and 15
602 for (; addr
< 14; addr
++) {
603 lockbit
= (lock_bits
>> addr
) & 1;
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
]);
610 data
[addr
] = 0x00; // Unknown password, but not used to set to zeros
611 PrintAndLogEx(INFO
, " %02u | | | | %-10s " _YELLOW_("write only"), addr
, info
[addr
]);
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
]);
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)
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"));
633 PrintAndLogEx(INFO
, " %02u | | | | %-10s %s", addr
, info
[addr
], status14
== PM3_EFAILED
? _RED_("read denied") : _RED_("read failed"));
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") : "");
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
) {
654 data
[EM4469_PROT_BLOCK
] = word
;
656 success
= PM3_ESOFT
; // If any error ensure fail is set so not to save invalid data
661 for (; addr
< 16; addr
++) {
662 lockbit
= (lock_bits
>> (addr
* 2)) & 3;
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
]);
669 data
[addr
] = 0x00; // Unknown password, but not used to set to zeros
670 PrintAndLogEx(INFO
, " %02u | | | | %-10s " _YELLOW_("write only"), addr
, info4x69
[addr
]);
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
]);
684 PrintAndLogEx(INFO
, " %02u | | | | %-10s %s", addr
, info4x69
[addr
], status
== PM3_EFAILED
? _RED_("read denied") : _RED_("read failed"));
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]));
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
, "");
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"
726 arg_int1("a", "addr", "<dec>", "memory address to read. (0-15)"),
727 arg_str0("p", "pwd", "<hex>", "optional - password, 4 bytes hex"),
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);
736 bool use_pwd
= false;
739 PrintAndLogEx(ERR
, "Address must be between 0 and 15");
743 if (inputpwd
== 0xFFFFFFFFFFFFFFFF) {
744 PrintAndLogEx(INFO
, "Reading address %02u", addr
);
746 pwd
= (inputpwd
& 0xFFFFFFFF);
748 PrintAndLogEx(INFO
, "Reading address %02u using password %08X", addr
, pwd
);
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");
758 PrintAndLogEx(WARNING
, "No answer from tag");
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"
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"),
779 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
780 uint8_t addr
= (uint8_t)arg_get_int_def(ctx
, 1, 50);
782 int res
= arg_get_u32_hexstr_def(ctx
, 2, 0, &data
);
785 PrintAndLogEx(WARNING
, "Data must be 4 hex bytes");
787 } else if (res
== 0) {
789 PrintAndLogEx(WARNING
, "Data must be 4 hex bytes");
793 bool use_pwd
= false;
795 res
= arg_get_u32_hexstr_def_nlen(ctx
, 3, 0, &pwd
, 4, true);
798 PrintAndLogEx(WARNING
, "Password must be 4 hex bytes");
800 } else if (res
== 3) {
802 } else if (res
== 1) {
806 bool protect_operation
= arg_get_lit(ctx
, 4);
809 if ((addr
> 13) && (protect_operation
== false)) {
810 PrintAndLogEx(WARNING
, "Address must be between 0 and 13");
815 if (protect_operation
)
816 PrintAndLogEx(INFO
, "Writing protection words data %08X using password %08X", data
, pwd
);
818 PrintAndLogEx(INFO
, "Writing address %d data %08X using password %08X", addr
, data
, pwd
);
820 if (protect_operation
)
821 PrintAndLogEx(INFO
, "Writing protection words data %08X", data
);
823 PrintAndLogEx(INFO
, "Writing address %d data %08X", addr
, data
);
828 if (protect_operation
) {
829 res
= em4x05_protect(pwd
, use_pwd
, data
);
830 if (res
!= PM3_SUCCESS
) {
834 res
= em4x05_write_word_ext(addr
, pwd
, use_pwd
, data
);
835 if (res
!= PM3_SUCCESS
) {
840 if (em4x05_download_samples() == false)
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");
850 PrintAndLogEx(DEBUG
, "No answer from tag");
852 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf em 4x05 read`") " to verify");
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"
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"),
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);
884 uint8_t foo
= target_4205
+ target_4305
+ target_4369
+ target_4469
;
887 PrintAndLogEx(ERR
, "Can't target multiple chip types at the same time");
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)
898 chip_info
= 0x00040070;
901 chip_info
= 0x00020078; // found on HID Prox
904 // chip_info = 0x00020078; // need to get a normal 4469 chip info block
907 bool use_pwd
= false;
909 if (inputpwd
!= 0xFFFFFFFFFFFFFFFF) {
910 pwd
= (inputpwd
& 0xFFFFFFFF);
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
) {
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
) {
931 // Password should now have changed, so use new password
933 // block 3 : user data
934 res
= em4x05_write_word_ext(3, pwd
, use_pwd
, block_data
);
935 if (res
!= PM3_SUCCESS
) {
940 res
= em4x05_write_word_ext(4, pwd
, use_pwd
, config
);
941 if (res
!= PM3_SUCCESS
) {
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
) {
955 static const char *printEM4x05_known(uint32_t 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
: {
969 case EM4305_VIKING_CONFIG_BLOCK
: {
972 case EM4305_NORALSY_CONFIG_BLOCK
: {
975 case EM4305_SECURAKEY_CONFIG_BLOCK
: {
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
: {
986 case EM4305_IOPROX_CONFIG_BLOCK
: {
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
: {
996 case EM4305_MOTOROLA_CONFIG_BLOCK
: {
999 case EM4305_NEXWATCH_CONFIG_BLOCK
: {
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
: {
1012 case EM4305_PAC_CONFIG_BLOCK
: {
1013 return "PAC/Stanley";
1015 case EM4305_VERICHIP_CONFIG_BLOCK
: {
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);
1026 memset(enc
, 0, sizeof(enc
));
1028 uint8_t PSKcf
= (wordData
>> 10) & 0x3;
1030 memset(cf
, 0, sizeof(cf
));
1031 uint8_t delay
= (wordData
>> 12) & 0x3;
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
1038 snprintf(enc
, sizeof(enc
), "NRZ");
1041 snprintf(enc
, sizeof(enc
), "Manchester");
1044 snprintf(enc
, sizeof(enc
), "Biphase");
1047 snprintf(enc
, sizeof(enc
), "Miller");
1050 snprintf(enc
, sizeof(enc
), "PSK1");
1053 snprintf(enc
, sizeof(enc
), "PSK2");
1056 snprintf(enc
, sizeof(enc
), "PSK3");
1059 snprintf(enc
, sizeof(enc
), "Unknown");
1062 snprintf(enc
, sizeof(enc
), "FSK1");
1065 snprintf(enc
, sizeof(enc
), "FSK2");
1068 snprintf(enc
, sizeof(enc
), "Unknown");
1074 snprintf(cf
, sizeof(cf
), "RF/2");
1077 snprintf(cf
, sizeof(cf
), "RF/8");
1080 snprintf(cf
, sizeof(cf
), "RF/4");
1083 snprintf(cf
, sizeof(cf
), "unknown");
1089 snprintf(cdelay
, sizeof(cdelay
), "no delay");
1092 snprintf(cdelay
, sizeof(cdelay
), "BP/8 or 1/8th bit period delay");
1095 snprintf(cdelay
, sizeof(cdelay
), "BP/4 or 1/4th bit period delay");
1098 snprintf(cdelay
, sizeof(cdelay
), "no delay");
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;
1167 // 1,2,3,4 chip type
1170 // 9 - 18 customer code
1173 98765432109876543210
1175 // 00100000000001111000
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
));
1189 PrintAndLogEx(SUCCESS
, " Cap Type: %3u | 330pF", cap
);
1192 PrintAndLogEx(SUCCESS
, " Cap Type: %3u | %spF", cap
, (chipType
== 4) ? "75" : "210");
1195 PrintAndLogEx(SUCCESS
, " Cap Type: %3u | 250pF", cap
);
1198 PrintAndLogEx(SUCCESS
, " Cap Type: %3u | no resonant capacitor", cap
);
1201 PrintAndLogEx(SUCCESS
, " Cap Type: %3u | unknown", cap
);
1205 PrintAndLogEx(SUCCESS
, " Cust Code: 0x%x | %s", custCode
, (custCode
== 0x200) ? "Default" : "Unknown");
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");
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.",
1232 "lf em 4x05 info -p 11223344"
1235 void *argtable
[] = {
1237 arg_str0("p", "pwd", "<hex>", "optional - password, 4 hex bytes"),
1240 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1241 uint64_t inputpwd
= arg_get_u64_hexstr_def(ctx
, 1, 0xFFFFFFFFFFFFFFFF);
1244 bool use_pwd
= false;
1246 if (inputpwd
!= 0xFFFFFFFFFFFFFFFF) {
1247 pwd
= inputpwd
& 0xFFFFFFFF;
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)
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");
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
) {
1285 if (word
& 0x8000) {
1286 printEM4x05ProtectionBits(word
, EM4305_PROT1_BLOCK
);
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
)
1291 if (word
& 0x8000) {
1292 printEM4x05ProtectionBits(word
, EM4305_PROT2_BLOCK
);
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
) {
1301 printEM4x05ProtectionBits(word
, EM4469_PROT_BLOCK
);
1304 //something went wrong
1308 static bool is_cancelled(void) {
1309 if (kbd_enter_pressed()) {
1310 PrintAndLogEx(WARNING
, "\naborted via keyboard!\n");
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",
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
[] = {
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"),
1332 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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);
1340 if (strlen(filename
) == 0) {
1341 snprintf(filename
, sizeof(filename
), "t55xx_default_pwds");
1343 PrintAndLogEx(NORMAL
, "");
1346 uint64_t t1
= msclock();
1348 // White cloner password based on EM4100 ID
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
);
1358 } else if (status
!= PM3_EFAILED
) {
1359 PrintAndLogEx(WARNING
, "no answer from tag");
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
)
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");
1388 if (is_cancelled()) {
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
);
1402 } else if (status
!= PM3_EFAILED
) {
1403 PrintAndLogEx(WARNING
, "no answer from tag");
1409 PrintAndLogEx(WARNING
, "check pwd failed");
1413 t1
= msclock() - t1
;
1414 PrintAndLogEx(SUCCESS
, "\ntime in check pwd " _YELLOW_("%.0f") " seconds\n", (float)t1
/ 1000.0);
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
[] = {
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"),
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);
1439 PrintAndLogEx(NORMAL
, "");
1446 payload
.start_pwd
= start_pwd
;
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");
1463 } em4x05_unlock_item_t
;
1465 static int unlock_write_protect(bool use_pwd
, uint32_t pwd
, uint32_t data
, bool verbose
) {
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)
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");
1495 PrintAndLogEx(DEBUG
, "No answer from tag");
1499 static int unlock_reset(bool use_pwd
, uint32_t pwd
, uint32_t data
, bool 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
) {
1508 for (; i
< len
; i
++) {
1509 if (array
[i
].value
== value
) {
1513 if (array
[i
].cnt
== 0) {
1515 array
[i
].value
= value
;
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
[] = {
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"),
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);
1549 PrintAndLogEx(FAILED
, "start delay can\'t be larger than end delay %.0lf vs %.0lf", start
, end
);
1553 if (session
.pm3_present
== false) {
1554 PrintAndLogEx(WARNING
, "device offline\n");
1558 bool use_pwd
= false;
1560 if (inputpwd
!= 0xFFFFFFFFFFFFFFFF) {
1562 pwd
= inputpwd
& 0xFFFFFFFF;
1565 uint32_t search_value
= 0;
1566 uint32_t write_value
= 0;
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");
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");
1587 #define ACTIVE_MASK 0x00008000
1588 if ((init_15
& ACTIVE_MASK
) == ACTIVE_MASK
) {
1589 search_value
= init_15
;
1591 search_value
= init_14
;
1594 if (search_value
== ACTIVE_MASK
) {
1595 PrintAndLogEx(SUCCESS
, "Tag already fully unlocked, nothing to do");
1599 bool my_auto
= false;
1602 n
= (end
- start
) / 2;
1605 // fix at one specific delay
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
);
1615 PrintAndLogEx(INFO
, " target password [ " _GREEN_("%08X") " ]", pwd
);
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;
1639 em4x05_unlock_item_t flipped
[64] = {{0, 0}};
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"));
1655 if (my_auto
== false) {
1659 if (tries
>= 5 && n
== 0 && soon
!= late
) {
1662 PrintAndLogEx(INFO
, "Tried %d times, soon:%i late:%i => " _CYAN_("adjust +1 us >> %.0lf us"), tries
, soon
, late
, start
);
1666 PrintAndLogEx(INFO
, "Tried %d times, soon:%i late:%i => " _CYAN_("adjust -1 us >> %.0lf us"), tries
, soon
, late
, start
);
1675 if (is_cancelled()) {
1676 exit_code
= PM3_EOPABORTED
;
1680 // set tear off trigger
1681 clearCommandBuffer();
1682 tearoff_params_t params
= {
1687 res
= handle_tearoff(¶ms
, verbose
);
1688 if (res
!= PM3_SUCCESS
) {
1689 PrintAndLogEx(WARNING
, "failed to configure tear off");
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");
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");
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"));
1719 PrintAndLogEx(INFO
, " => " _CYAN_("adjust +%.0lf us >> %.0lf us"), n
, start
);
1726 if (word15
== search_value
) {
1729 PrintAndLogEx(INFO
, "Status: Protect succeeded => " _GREEN_("tearing too late"));
1731 if (word14
== search_value
) {
1732 PrintAndLogEx(INFO
, "Status: 15 ok, 14 not yet erased => " _GREEN_("tearing too late"));
1734 PrintAndLogEx(INFO
, "Status: 15 ok, 14 partially erased => " _GREEN_("tearing too late"));
1738 unlock_reset(use_pwd
, pwd
, write_value
, verbose
);
1741 res
= em4x05_read_word_ext(14, pwd
, use_pwd
, &word14b
);
1742 if (res
!= PM3_SUCCESS
) {
1743 PrintAndLogEx(WARNING
, "failed to read 14");
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");
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
);
1766 PrintAndLogEx(WARNING
, "failed to read 15");
1773 PrintAndLogEx(INFO
, " => " _CYAN_("adjust -%.0lf us >> %.0lf us"), n
, start
);
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
);
1789 res
= em4x05_read_word_ext(14, pwd
, use_pwd
, &word14b
);
1790 if (res
!= PM3_SUCCESS
) {
1791 PrintAndLogEx(WARNING
, "failed to read 14");
1795 res
= em4x05_read_word_ext(15, pwd
, use_pwd
, &word15b
);
1796 if (res
!= PM3_SUCCESS
) {
1797 PrintAndLogEx(WARNING
, "failed to read 15");
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
);
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
);
1822 PrintAndLogEx(INFO
, "Status: failed to commit bitflip => " _RED_("FAIL: ") "14: %08X 15: %08X", word14b
, word15b
);
1833 PrintAndLogEx(INFO
, "Status: 15 bitflipped but inactive => " _YELLOW_("PROMISING: ") "14: %08X 15: " _CYAN_("%08X"), word14
, word15
);
1835 unlock_add_item(flipped
, 64, word15
);
1842 if (my_auto
== false) {
1847 PrintAndLogEx(INFO
, "----------------------------- " _CYAN_("exit") " ----------------------------------\n");
1848 t1
= msclock() - t1
;
1849 PrintAndLogEx(SUCCESS
, "\ntime in unlock " _YELLOW_("%.0f") " seconds\n", (float)t1
/ 1000.0);
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`"));
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)
1871 PrintAndLogEx(INFO
, " %3u | %08X | %3u | %u", i
, flipped
[i
].value
, flipped
[i
].cnt
, bitcount32(search_value
^ flipped
[i
].value
));
1874 PrintAndLogEx(NORMAL
, "");
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
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.
1885 (*pulsesamples
) = 0;
1886 while ((idx
< sc
) && ((data
[idx
+ 1] - data
[idx
]) < 10)) { // find "sharp rise"
1894 uint32_t static em4x05_Sniff_GetBlock(char *bits
, bool fwd
) {
1897 bool parityerror
= false;
1901 for (idx
= 0; idx
< 8; idx
++) {
1903 value
+= (bits
[idx
] - '0');
1904 parity
+= (bits
[idx
] - '0');
1906 parity
= parity
% 2;
1907 if (parity
!= (bits
[8] - '0'))
1911 for (idx
= 9; idx
< 17; idx
++) {
1913 value
+= (bits
[idx
] - '0');
1914 parity
+= (bits
[idx
] - '0');
1916 parity
= parity
% 2;
1917 if (parity
!= (bits
[17] - '0'))
1921 for (idx
= 18; idx
< 26; idx
++) {
1923 value
+= (bits
[idx
] - '0');
1924 parity
+= (bits
[idx
] - '0');
1926 parity
= parity
% 2;
1927 if (parity
!= (bits
[26] - '0'))
1931 for (idx
= 27; idx
< 35; idx
++) {
1933 value
+= (bits
[idx
] - '0');
1934 parity
+= (bits
[idx
] - '0');
1936 parity
= parity
% 2;
1937 if (parity
!= (bits
[35] - '0'))
1941 PrintAndLogEx(ERR
, "parity error : ");
1944 uint32_t t1
= value
;
1946 for (idx
= 0; idx
< 32; idx
++)
1947 value
|= (((t1
>> idx
) & 1) << (31 - idx
));
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
[] = {
1967 arg_lit0("1", "buf", "Use the data in the buffer"),
1968 arg_lit0("r", "rev", "Reverse the bit order for data blocks"),
1971 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1972 sampleData
= (arg_get_lit(ctx
, 1) == false);
1973 fwd
= arg_get_lit(ctx
, 2);
1981 int ZeroWidth
; // 32-42 "1" is 32
1983 size_t idx
= 0, pulseSamples
, pktOffset
;
1987 // setup and sample data from Proxmark
1988 // if not directed to existing sample/graphbuffer
1990 if (IfPm3Lf() == false) {
1991 PrintAndLogEx(WARNING
, "Only offline mode is available");
1998 PrintAndLogEx(NORMAL
, "");
1999 PrintAndLogEx(INFO
, _CYAN_("EM4x05 command detection"));
2000 PrintAndLogEx(SUCCESS
, "offset | Command | Data | blk | raw");
2001 PrintAndLogEx(SUCCESS
, "-------+-------------+----------+-----+------------------------------------------------------------");
2004 // loop though sample buffer
2005 while (idx
< GraphTraceLen
) {
2010 idx
= em4x05_Sniff_GetNextBitStart(idx
, GraphTraceLen
, GraphBuffer
, &pulseSamples
);
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
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
));
2024 while ((idx
< GraphTraceLen
) && !eop
) {
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
2031 bits
[bitidx
++] = '0'; // Append last zero from the last bit find
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);
2050 PrintAndLogEx(INFO
, "Trim leading 0");
2055 if ((strncmp(bits
, "0011", 4) == 0) && (bitidx
== 49)) {
2058 sprintf(cmdText
, "Logon");
2059 sprintf(blkAddr
, " ");
2060 tmpValue
= em4x05_Sniff_GetBlock(&bits
[4], fwd
);
2061 sprintf(dataText
, "%08X", tmpValue
);
2065 if ((strncmp(bits
, "0101", 4) == 0) && (bitidx
== 56)) {
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) {
2073 tmpValue
= em4x05_Sniff_GetBlock(&bits
[11], fwd
);
2074 sprintf(dataText
, "%08X", tmpValue
);
2078 if ((strncmp(bits
, "1001", 4) == 0) && (bitidx
== 11)) {
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
, " ");
2088 if ((strncmp(bits
, "1100", 4) == 0) && (bitidx
== 49)) {
2091 sprintf(cmdText
, "Protect");
2092 sprintf(blkAddr
, " ");
2093 tmpValue
= em4x05_Sniff_GetBlock(&bits
[11], fwd
);
2094 sprintf(dataText
, "%08X", tmpValue
);
2098 if ((strncmp(bits
, "1010", 4) == 0) && (bitidx
== 49)) {
2101 sprintf(cmdText
, "Disable");
2102 sprintf(blkAddr
, " ");
2103 tmpValue
= em4x05_Sniff_GetBlock(&bits
[11], fwd
);
2104 sprintf(dataText
, "%08X", tmpValue
);
2107 // bits[bitidx] = 0;
2109 i
= (CycleWidth
- ZeroWidth
) / 28;
2110 bits
[bitidx
++] = '0';
2111 for (int ii
= 0; ii
< i
; ii
++) {
2112 bits
[bitidx
++] = '1';
2121 if (haveData
) { //&& (minWidth > 1) && (maxWidth > minWidth)){
2123 PrintAndLogEx(SUCCESS
, "%6zu | %-10s | " _YELLOW_("%8s")" | " _YELLOW_("%3s")" | %s", pktOffset
, cmdText
, dataText
, blkAddr
, bits
);
2125 PrintAndLogEx(SUCCESS
, "%6zu | %-10s | " _GREEN_("%8s")" | " _GREEN_("%3s")" | %s", pktOffset
, cmdText
, dataText
, blkAddr
, bits
);
2130 PrintAndLogEx(SUCCESS
, "---------------------------------------------------------------------------------------------------");
2131 PrintAndLogEx(NORMAL
, "");
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
);
2156 int CmdLFEM4X05(const char *Cmd
) {
2157 clearCommandBuffer();
2158 return CmdsParse(CommandTable
, Cmd
);