1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Low frequency T55xx commands
17 //-----------------------------------------------------------------------------
19 // ensure localtime_r is available even with -std=c99; must be included before
21 #define _POSIX_C_SOURCE 200112L
24 #include "cmdlft55xx.h"
26 #include <time.h> // MingW
27 #include "cmdparser.h" // command_t
29 #include "commonutil.h"
30 #include "protocols.h"
35 #include "cmdhf14a.h" // for getTagInfo
36 #include "fileutils.h" // loadDictionary
37 #include "util_posix.h"
38 #include "cmdlf.h" // for lf sniff
39 #include "generator.h"
40 #include "cliparser.h" // cliparsing
42 // Some defines for readability
43 #define T55XX_DLMODE_FIXED 0 // Default Mode
44 #define T55XX_DLMODE_LLR 1 // Long Leading Reference
45 #define T55XX_DLMODE_LEADING_ZERO 2 // Leading Zero
46 #define T55XX_DLMODE_1OF4 3 // 1 of 4
47 // #define T55XX_LONGLEADINGREFERENCE 4 // Value to tell Write Bit to send long reference
48 #define T55XX_DLMODE_ALL 4 // Tell help to show 'r 4' for all dl modes
49 #define T55XX_DLMODE_SINGLE 5 // Tell help file NOT to show 'r 4' (not available)
51 #define T55XX_PrintConfig true
52 #define T55XX_DontPrintConfig false
54 //static uint8_t bit_rates[9] = {8, 16, 32, 40, 50, 64, 100, 128, 0};
56 // Default configuration
57 static t55xx_conf_block_t config
= {
58 .modulation
= DEMOD_ASK
,
62 .block0Status
= NOTSET
,
65 .downlink_mode
= refFixedBit
68 static t55xx_memory_item_t cardmem
[T55x7_BLOCK_COUNT
] = {{0}};
70 #define DC(x) ((x) + 128)
72 static bool t55xx_is_valid_block0(uint32_t block, uint8_t rfclk, uint8_t pskcf) {
78 // Master key = 6 or 9
79 if ((((block >> 28)& 0xF) != 0x0) &&
80 (((block >> 28)& 0xF) != 0x6) &&
81 (((block >> 28)& 0xF) != 0x9)) {
86 if ( ((block >> 17) & 1) && ((((block >> 28) & 0xf) == 0x6) || (((block >> 28) & 0xf) == 0x9)) ) {
87 // X mode fixed 0 bits
88 if ((block & 0x0F000000) != 0x00) {
92 // / Basic Mode fixed 0 bits
93 if ((block & 0x0FE00106) != 0x00) {
99 if ( (((block >> 12) & 0x1F) != 0x00) && // Direct
100 (((block >> 12) & 0x1F) != 0x01) && // PSK1
101 (((block >> 12) & 0x1F) != 0x02) && // PSK2
102 (((block >> 12) & 0x1F) != 0x03) && // PSK3
103 (((block >> 12) & 0x1F) != 0x04) && // FSK1
104 (((block >> 12) & 0x1F) != 0x05) && // FSK2
105 (((block >> 12) & 0x1F) != 0x06) && // FSK1a
106 (((block >> 12) & 0x1F) != 0x07) && // FSK2a
107 (((block >> 12) & 0x1F) != 0x08) && // Manchester
108 (((block >> 12) & 0x1F) != 0x10) && // Bi-phase
109 (((block >> 12) & 0x1F) != 0x18) ) { // Reserved
113 PrintAndLogEx(DEBUG, "suggested block... %08x", block);
116 if ((pskcf <= 3) && (((block >> 10) & 0x3) != pskcf)) {
117 PrintAndLogEx(DEBUG, "fail 6 - %u %u", pskcf, (block >> 10) & 0x3);
124 if ((((block >> 17) & 1) == 1) && ((((block >> 28) & 0xf) == 0x6) || (((block >> 28) & 0xf) == 0x9)) ){ // X mode speedBits
125 testSpeed = (((block >> 18) & 0x3F) * 2) + 2;
127 uint8_t basicSpeeds[] = {8,16,32,40,50,64,100,128};
128 testSpeed = basicSpeeds[(block >> 18) & 0x7];
131 if (testSpeed != rfclk) {
132 PrintAndLogEx(DEBUG, "fail 7 - %u %u ", testSpeed , rfclk);
138 static void t55xx_psk1_demod (int *data, uint8_t rfclk, uint8_t pskcf, uint32_t *block) {
140 if ((rfclk < 8) || (rfclk > 128)) {
162 int startOffset = 1; // where to start reading data samples
163 int sampleCount = 0; // Counter for 1 bit of samples
164 int samples0, samples1; // Number of High even and odd bits in a sample.
165 int startBitOffset = 1; // which bit to start at e.g. for rf/32 1 33 65 ...
167 uint32_t myblock = 0;
170 uint8_t tuneOffset = 0;
172 drift = (rfclk % pskcf); // 50 2 = 1 50 4 = 2
174 // locate first "0" - high transisiton for correct start offset
175 while (DC(data[startOffset]) <= (DC(data[startOffset - 1]) + 5)) {
176 // sampleToggle ^= 1;
180 // Start sample may be 1 off due to sample alignment with chip modulation
181 // so seach for the first lower value, and adjust as needed
184 tuneOffset = startOffset + 1;
186 while (DC(data[tuneOffset]) >= (DC(data[tuneOffset - 1]) + 5)) {
190 if ((tuneOffset - startOffset - 1) % 2) {
195 uint8_t pskcfidx = 0;
197 // Get the offset to the first sample of the data block
198 offset = (rfclk * startBitOffset) + startOffset;
200 pskcfidx = (drift / 2);
201 pskcfidx = pskcfidx % pskcf;
203 // while data my be in the settle period of sampling
204 // First 18 - 24 bits not usable for reference only
205 while (offset < 20) {
206 offset += (32 * rfclk);
209 // Read 1 block of data
210 for (bitCount = 0; bitCount < 32; bitCount++) {
216 for (sampleCount = 0; sampleCount < rfclk; sampleCount++){
217 // Count number of even and odd high bits at center to edge
221 // if current sample is high
222 if (DC(data[offset]) > DC(data[offset + 1])) {
233 // only check pskcf 2nd bit x 1 x x
236 // if current sample is high
237 if (DC(data[offset]) > DC(data[offset + 2])) {
247 if (pskcfidx == 3) { // x x x 1 x x x x // 00041840 : FFFBE7BF
249 // if current sample is high
250 if (DC(data[offset]) > DC(data[offset + 4])) {
263 // If at bit boundary (after first bit) then adjust phase check for drift
264 if ((sampleCount > 0) && (sampleCount % rfclk) == 0) {
270 pskcfidx = pskcfidx % pskcf;
274 if (samples1 > samples0) {
282 static void t55xx_psk2_demod (int *data, uint8_t rfclk, uint8_t pskcf, uint32_t *block) {
284 t55xx_psk1_demod (data, rfclk, pskcf, block);
286 uint32_t new_block = 0;
287 uint8_t prev_phase = 1;
290 for (int8_t bit = 31; bit >= 0; bit--) {
294 if (((*block >> bit) & 1) != prev_phase) {
298 prev_phase = ((*block >> bit) & 1);
304 static void t55xx_search_config_psk(int *d, int pskV) {
306 for (uint8_t pskcf = 0; pskcf < 3; pskcf++) {
308 for (uint8_t speedBits = 0; speedBits < 64; speedBits++) {
310 uint8_t rfclk = rfclk = (2 * speedBits) + 2;
314 t55xx_psk1_demod (d, rfclk, pskcf, &block);
318 t55xx_psk2_demod (d, rfclk, pskcf, &block);
321 if (t55xx_is_valid_block0(block, rfclk, pskcf)) {
322 PrintAndLogEx(SUCCESS, "Valid config block [%08X] - rfclk [%d] - pskcf [%d]", block, rfclk, pskcf);
329 t55xx_conf_block_t
Get_t55xx_Config(void) {
333 void Set_t55xx_Config(t55xx_conf_block_t conf
) {
337 static int CmdHelp(const char *Cmd
);
339 static void arg_add_t55xx_downloadlink(void *at
[], uint8_t *idx
, uint8_t show
, uint8_t dl_mode_def
) {
340 const size_t r_count
= 56;
341 const size_t r_len
= r_count
* sizeof(uint8_t);
343 char *r0
= (char *)calloc(r_count
, sizeof(uint8_t));
344 char *r1
= (char *)calloc(r_count
, sizeof(uint8_t));
345 char *r2
= (char *)calloc(r_count
, sizeof(uint8_t));
346 char *r3
= (char *)calloc(r_count
, sizeof(uint8_t));
348 snprintf(r0
, r_len
, "downlink - fixed bit length %s", (dl_mode_def
== 0) ? "(detected def)" : "");
349 snprintf(r1
, r_len
, "downlink - long leading reference %s", (dl_mode_def
== 1) ? "(detected def)" : "");
350 snprintf(r2
, r_len
, "downlink - leading zero %s", (dl_mode_def
== 2) ? "(detected def)" : "");
351 snprintf(r3
, r_len
, "downlink - 1 of 4 coding reference %s", (dl_mode_def
== 3) ? "(detected def)" : "");
354 at
[n
++] = arg_lit0(NULL
, "r0", r0
);
355 at
[n
++] = arg_lit0(NULL
, "r1", r1
);
356 at
[n
++] = arg_lit0(NULL
, "r2", r2
);
357 at
[n
++] = arg_lit0(NULL
, "r3", r3
);
359 if (show
== T55XX_DLMODE_ALL
) {
360 char *r4
= (char *)calloc(r_count
, sizeof(uint8_t));
361 snprintf(r4
, r_len
, "try all downlink modes %s", (dl_mode_def
== 4) ? "(def)" : "");
362 at
[n
++] = arg_lit0(NULL
, "all", r4
);
364 at
[n
++] = arg_param_end
;
368 static int CmdT55xxCloneHelp(const char *Cmd
) {
369 CLIParserContext
*ctx
;
370 CLIParserInit(&ctx
, "lf t55xx clonehelp",
371 "Display a list of available commands for cloning specific techs on T5xx tags",
378 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
380 PrintAndLogEx(NORMAL
, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:");
381 PrintAndLogEx(NORMAL
, _GREEN_("lf awid clone"));
382 PrintAndLogEx(NORMAL
, _GREEN_("lf destron clone"));
383 PrintAndLogEx(NORMAL
, _GREEN_("lf em 410x clone"));
384 // todo: implement restore
385 // PrintAndLogEx(NORMAL, _GREEN_("lf em 4x05 write"));
386 // PrintAndLogEx(NORMAL, _GREEN_("lf em 4x50 restore"));
387 PrintAndLogEx(NORMAL
, _GREEN_("lf fdxb clone"));
388 PrintAndLogEx(NORMAL
, _GREEN_("lf gallagher clone"));
389 PrintAndLogEx(NORMAL
, _GREEN_("lf gproxii clone"));
390 PrintAndLogEx(NORMAL
, _GREEN_("lf hid clone"));
391 // todo: implement restore
392 // PrintAndLogEx(NORMAL, _GREEN_("lf hitag clone"));
393 PrintAndLogEx(NORMAL
, _GREEN_("lf idteck clone"));
394 PrintAndLogEx(NORMAL
, _GREEN_("lf indala clone"));
395 PrintAndLogEx(NORMAL
, _GREEN_("lf io clone"));
396 PrintAndLogEx(NORMAL
, _GREEN_("lf jablotron clone"));
397 PrintAndLogEx(NORMAL
, _GREEN_("lf keri clone"));
398 PrintAndLogEx(NORMAL
, _GREEN_("lf motorola clone"));
399 PrintAndLogEx(NORMAL
, _GREEN_("lf nedap clone"));
400 PrintAndLogEx(NORMAL
, _GREEN_("lf nexwatch clone"));
401 PrintAndLogEx(NORMAL
, _GREEN_("lf noralsy clone"));
402 PrintAndLogEx(NORMAL
, _GREEN_("lf pac clone"));
403 PrintAndLogEx(NORMAL
, _GREEN_("lf paradox clone"));
404 PrintAndLogEx(NORMAL
, _GREEN_("lf presco clone"));
405 PrintAndLogEx(NORMAL
, _GREEN_("lf pyramid clone"));
406 PrintAndLogEx(NORMAL
, _GREEN_("lf securakey clone"));
407 PrintAndLogEx(NORMAL
, _GREEN_("lf viking clone"));
408 PrintAndLogEx(NORMAL
, _GREEN_("lf visa2000 clone"));
412 static void T55x7_SaveBlockData(uint8_t idx
, uint32_t data
) {
413 if (idx
< T55x7_BLOCK_COUNT
) {
414 cardmem
[idx
].valid
= true;
415 cardmem
[idx
].blockdata
= data
;
418 static void T55x7_ClearAllBlockData(void) {
419 for (uint8_t idx
= 0; idx
< T55x7_BLOCK_COUNT
; idx
++) {
420 cardmem
[idx
].valid
= false;
421 cardmem
[idx
].blockdata
= 0x00;
425 int clone_t55xx_tag(uint32_t *blockdata
, uint8_t numblocks
) {
427 if (blockdata
== NULL
)
429 if (numblocks
< 1 || numblocks
> 8)
432 PacketResponseNG resp
;
435 g_conn
.block_after_ACK
= true;
437 for (int8_t i
= 0; i
< numblocks
; i
++) {
439 // Disable fast mode on last packet
440 if (i
== numblocks
- 1) {
441 g_conn
.block_after_ACK
= false;
444 clearCommandBuffer();
446 t55xx_write_block_t ng
;
447 ng
.data
= blockdata
[i
];
452 SendCommandNG(CMD_LF_T55XX_WRITEBL
, (uint8_t *)&ng
, sizeof(ng
));
453 if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL
, &resp
, T55XX_WRITE_TIMEOUT
)) {
454 PrintAndLogEx(ERR
, "Error occurred, device did not respond during write operation.");
460 for (int8_t i
= 0; i
< numblocks
; i
++) {
463 SetConfigWithBlock0(blockdata
[0]);
464 if (t55xxAcquireAndCompareBlock0(false, 0, blockdata
[0], false))
468 if (t55xxVerifyWrite(i
, 0, false, false, 0, 0xFF, blockdata
[i
]) == false)
473 PrintAndLogEx(SUCCESS
, "Data written and verified");
478 static bool t55xxProtect(bool lock
, bool usepwd
, uint8_t override
, uint32_t password
, uint8_t downlink_mode
, uint32_t new_password
) {
480 PrintAndLogEx(INFO
, "Checking current configuration");
482 bool testmode
= false;
485 int res
= T55xxReadBlockEx(T55x7_CONFIGURATION_BLOCK
, T55x7_PAGE0
, usepwd
, override
, password
, downlink_mode
, false);
486 if (res
!= PM3_SUCCESS
) {
487 PrintAndLogEx(WARNING
, "Failed to read block0, use " _YELLOW_("`p`") " password parameter?");
491 if (GetT55xxBlockData(&block0
) == false) {
492 PrintAndLogEx(DEBUG
, "ERROR decoded block0 == %08x", block0
);
495 PrintAndLogEx(DEBUG
, "OK read block0 == %08x", block0
);
498 bool isPwdBitAlreadySet
= (block0
>> (32 - 28) & 1);
499 if (isPwdBitAlreadySet
) {
500 PrintAndLogEx(INFO
, "PWD bit is already set");
504 // set / clear pwd bit
511 // write new password
512 if (t55xxWrite(T55x7_PWD_BLOCK
, T55x7_PAGE0
, usepwd
, testmode
, password
, downlink_mode
, new_password
) != PM3_SUCCESS
) {
513 PrintAndLogEx(ERR
, "Failed to write new password");
516 PrintAndLogEx(SUCCESS
, "Wrote new password");
519 // validate new password
520 uint32_t curr_password
= (isPwdBitAlreadySet
) ? new_password
: password
;
522 if (t55xxVerifyWrite(T55x7_PWD_BLOCK
, T55x7_PAGE0
, usepwd
, override
, curr_password
, downlink_mode
, new_password
) == false) {
523 PrintAndLogEx(WARNING
, "Failed to validate the password write. aborting.");
526 PrintAndLogEx(SUCCESS
, "Validated new password");
530 if (t55xxWrite(T55x7_CONFIGURATION_BLOCK
, T55x7_PAGE0
, usepwd
, testmode
, curr_password
, downlink_mode
, block0
) != PM3_SUCCESS
) {
531 PrintAndLogEx(ERR
, "Failed to write modified configuration block %08X", block0
);
534 PrintAndLogEx(SUCCESS
, "Wrote modified configuration block");
537 // validate new config. If all went well, card should now demand pwd, hence override = 0.
539 if (t55xxVerifyWrite(T55x7_CONFIGURATION_BLOCK
, T55x7_PAGE0
, true, override
, new_password
, downlink_mode
, block0
) == false) {
540 PrintAndLogEx(WARNING
, "Failed to validate pwd bit set on configuration block. aborting.");
543 PrintAndLogEx(SUCCESS
, "New configuration block " _YELLOW_("%08X")" password " _YELLOW_("%08X"), block0
, new_password
);
544 PrintAndLogEx(SUCCESS
, "Success, tag is locked");
549 bool t55xxAcquireAndCompareBlock0(bool usepwd
, uint32_t password
, uint32_t known_block0
, bool verbose
) {
552 PrintAndLogEx(INFO
, "Block0 write detected, running `detect` to see if validation is possible");
554 for (uint8_t m
= 0; m
< 4; m
++) {
555 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, usepwd
, password
, m
) == false) {
559 if (DecodeT55xxBlock() == false) {
563 for (size_t i
= 0; i
< g_DemodBufferLen
- 32; i
++) {
564 uint32_t tmp
= PackBits(i
, 32, g_DemodBuffer
);
565 if (tmp
== known_block0
) {
567 config
.downlink_mode
= m
;
575 bool t55xxAcquireAndDetect(bool usepwd
, uint32_t password
, uint32_t known_block0
, bool verbose
) {
578 PrintAndLogEx(INFO
, "Block0 write detected, running `detect` to see if validation is possible");
580 for (uint8_t m
= 0; m
< 4; m
++) {
581 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, usepwd
, password
, m
) == false)
584 if (t55xxTryDetectModulationEx(m
, verbose
, known_block0
, (usepwd
) ? password
: -1) == false)
587 config
.downlink_mode
= m
;
590 config
.usepwd
= false; // unknown so assume no password
595 bool t55xxVerifyWrite(uint8_t block
, bool page1
, bool usepwd
, uint8_t override
, uint32_t password
, uint8_t downlink_mode
, uint32_t data
) {
597 uint32_t read_data
= 0;
599 if (downlink_mode
== 0xFF)
600 downlink_mode
= config
.downlink_mode
;
602 int res
= T55xxReadBlockEx(block
, page1
, usepwd
, override
, password
, downlink_mode
, false);
603 if (res
== PM3_SUCCESS
) {
605 if (GetT55xxBlockData(&read_data
) == false)
608 } else if (res
== PM3_EWRONGANSWER
) {
610 // couldn't decode. Lets see if this was a block 0 write and try read/detect it auto.
611 // this messes up with ppl config..
612 if (block
== 0 && page1
== false) {
614 if (t55xxAcquireAndDetect(usepwd
, password
, data
, true) == false)
617 return t55xxVerifyWrite(block
, page1
, usepwd
, 2, password
, config
.downlink_mode
, data
);
621 return (read_data
== data
);
624 int t55xxWrite(uint8_t block
, bool page1
, bool usepwd
, bool testMode
, uint32_t password
, uint8_t downlink_mode
, uint32_t data
) {
627 flags
= (usepwd
) ? 0x1 : 0;
628 flags
|= (page1
) ? 0x2 : 0;
629 flags
|= (testMode
) ? 0x4 : 0;
630 flags
|= (downlink_mode
<< 3);
634 arg0 = data, (4 bytes)
635 arg1 = block (1 byte)
636 arg2 = password (4 bytes)
637 flags = data[0] (1 byte)
640 uses struct in pm3_cmd.h
642 t55xx_write_block_t ng
;
648 PacketResponseNG resp
;
649 clearCommandBuffer();
650 SendCommandNG(CMD_LF_T55XX_WRITEBL
, (uint8_t *)&ng
, sizeof(ng
));
651 if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL
, &resp
, 2000)) {
652 PrintAndLogEx(ERR
, "Error occurred, device did not ACK write operation.");
658 void printT5xxHeader(uint8_t page
) {
659 PrintAndLogEx(NORMAL
, "");
660 PrintAndLogEx(SUCCESS
, _YELLOW_("Page %d"), page
);
661 PrintAndLogEx(SUCCESS
, "blk | hex data | binary | ascii");
662 PrintAndLogEx(SUCCESS
, "----+----------+----------------------------------+-------");
665 void SetConfigWithBlock0(uint32_t block0
) {
666 SetConfigWithBlock0Ex(block0
, 0, false);
668 void SetConfigWithBlock0Ex(uint32_t block0
, uint8_t offset
, bool Q5
) {
670 uint32_t extend
= (block0
>> (32 - 15)) & 0x01;
673 dbr
= (block0
>> (32 - 14)) & 0x3F;
675 dbr
= (block0
>> (32 - 14)) & 0x07;
677 uint32_t datamod
= (block0
>> (32 - 20)) & 0x1F;
678 bool pwd
= (bool)((block0
>> (32 - 28)) & 0x01);
679 bool sst
= (bool)((block0
>> (32 - 29)) & 0x01);
680 bool inv
= (bool)((block0
>> (32 - 31)) & 0x01);
682 config
.modulation
= datamod
;
683 config
.bitrate
= dbr
;
686 if (datamod
== DEMOD_FSK1a
|| datamod
== DEMOD_FSK2a
|| datamod
== DEMOD_BIa
)
689 config
.inverted
= inv
;
694 config
.offset
= offset
;
695 config
.block0
= block0
;
698 static int CmdT55xxSetConfig(const char *Cmd
) {
700 if (strlen(Cmd
) == 0) {
701 PrintAndLogEx(INFO
, "--- " _CYAN_("current t55xx config") " --------------------------");
702 return printConfiguration(config
);
705 CLIParserContext
*ctx
;
706 CLIParserInit(&ctx
, "lf t55xx config",
707 "Set/Get T55XX configuration of the pm3 client. Like modulation, inverted, offset, rate etc.\n"
708 "Offset is start position to decode data.",
709 "lf t55xx config --FSK --> FSK demodulation\n"
710 "lf t55xx config --FSK -i --> FSK demodulation, inverse data\n"
711 "lf t55xx config --FSK -i -o 3 --> FSK demodulation, inverse data, offset 3\n"
714 // 1 (help) + 19 (user specified params) + (5 T55XX_DLMODE_SINGLE)
715 void *argtable
[1 + 12 + 6 + 5] = {
717 arg_lit0(NULL
, "FSK", "set demodulation FSK"),
718 arg_lit0(NULL
, "FSK1", "set demodulation FSK 1"),
719 arg_lit0(NULL
, "FSK1A", "set demodulation FSK 1a (inv)"),
720 arg_lit0(NULL
, "FSK2", "set demodulation FSK 2"),
721 arg_lit0(NULL
, "FSK2A", "set demodulation FSK 2a (inv)"),
722 arg_lit0(NULL
, "ASK", "set demodulation ASK"),
723 arg_lit0(NULL
, "PSK1", "set demodulation PSK 1"),
724 arg_lit0(NULL
, "PSK2", "set demodulation PSK 2"),
725 arg_lit0(NULL
, "PSK3", "set demodulation PSK 3"),
726 arg_lit0(NULL
, "NRZ", "set demodulation NRZ"),
727 arg_lit0(NULL
, "BI", "set demodulation Biphase"),
728 arg_lit0(NULL
, "BIA", "set demodulation Diphase (inverted biphase)"),
729 arg_lit0("i", "inv", "set/reset data signal inversion"),
730 arg_lit0(NULL
, "q5", "set/reset as Q5/T5555 chip instead of T55x7"),
731 arg_lit0(NULL
, "st", "set/reset Sequence Terminator on"),
732 arg_int0(NULL
, "rate", "<dec>", "set bitrate <8|16|32|40|50|64|100|128>"),
733 arg_str0("c", "blk0", "<hex>", "set configuration from a block0 (4 hex bytes)"),
734 arg_int0("o", "offset", "<0-255>", "set offset, where data should start decode in bitstream "),
738 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
739 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
744 while (idx
- 1 < sizeof(mods
)) {
745 mods
[idx
- 1] = arg_get_lit(ctx
, idx
);
746 verify_mods
+= mods
[idx
- 1];
750 // Not these flags are used to Toggle the values.
751 // If not flag then don't set or reset, leave as is since the call may just be be setting a different value.
752 bool invert
= arg_get_lit(ctx
, idx
++);
753 bool use_q5
= arg_get_lit(ctx
, idx
++);
754 bool use_st
= arg_get_lit(ctx
, idx
++);
756 int bitrate
= arg_get_int_def(ctx
, idx
, -1);
759 bool gotconf
= false;
761 int res
= arg_get_u32_hexstr_def_nlen(ctx
, idx
++, 0, &block0
, 4, true);
762 if (res
== 0 || res
== 2) {
763 PrintAndLogEx(ERR
, "block0 data must be 4 hex bytes");
771 int offset
= arg_get_int_def(ctx
, idx
, -1);
774 bool r0
= arg_get_lit(ctx
, idx
++);
775 bool r1
= arg_get_lit(ctx
, idx
++);
776 bool r2
= arg_get_lit(ctx
, idx
++);
777 bool r3
= arg_get_lit(ctx
, idx
++);
780 // validate user specified downlink mode
781 if ((r0
+ r1
+ r2
+ r3
) > 1) {
782 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
786 // validate user specified modulation FSK,FSK1,...BIA
787 if (verify_mods
> 1) {
788 PrintAndLogEx(FAILED
, "Error multiple demodulations, select one");
792 // validate user specified bitrate
795 uint8_t rates
[9] = {8, 16, 32, 40, 50, 64, 100, 128, 0};
797 for (; i
< ARRAYLEN(rates
); i
++) {
798 if (rates
[i
] == bitrate
) {
800 config
.block0
= ((config
.block0
& ~(0x1c0000)) | (i
<< 18));
805 PrintAndLogEx(FAILED
, "Error select a valid bitrate");
810 // validate user specified offset
811 if (offset
> -1 && offset
< 0x100) {
812 config
.offset
= offset
;
815 // validate user specific T5555 / Q5 - use the flag to toggle between T5577 and Q5
818 // validate user specific sequence terminator
819 // if use_st flag was supplied, then toggle and update the config block0; if not supplied skip the config block0 update.
822 config
.block0
= ((config
.block0
& ~(0x8)) | (config
.ST
<< 3));
825 // validate user specific invert
826 // In theory this should also be set in the config block 0; butit requries the extend mode config, which will change other things.
827 // as such, leave in user config for decoding the data until a full fix can be added.
828 // use the flag to toggle if invert is on or off.
829 config
.inverted
^= invert
;
831 // validate user specific downlink mode
832 uint8_t downlink_mode
= config
.downlink_mode
;
834 downlink_mode
= refFixedBit
;
836 downlink_mode
= refLongLeading
;
838 downlink_mode
= refLeading0
;
840 downlink_mode
= ref1of4
;
842 config
.downlink_mode
= downlink_mode
;
844 // validate user specific modulation
846 config
.modulation
= DEMOD_FSK
;
847 } else if (mods
[1]) {
848 config
.modulation
= DEMOD_FSK1
;
850 } else if (mods
[2]) {
851 config
.modulation
= DEMOD_FSK1a
;
853 } else if (mods
[3]) {
854 config
.modulation
= DEMOD_FSK2
;
856 } else if (mods
[4]) {
857 config
.modulation
= DEMOD_FSK2a
;
859 } else if (mods
[5]) {
860 config
.modulation
= DEMOD_ASK
;
861 } else if (mods
[6]) {
862 config
.modulation
= DEMOD_PSK1
;
863 } else if (mods
[7]) {
864 config
.modulation
= DEMOD_PSK2
;
865 } else if (mods
[8]) {
866 config
.modulation
= DEMOD_PSK3
;
867 } else if (mods
[9]) {
868 config
.modulation
= DEMOD_NRZ
;
869 } else if (mods
[10]) {
870 config
.modulation
= DEMOD_BI
;
872 } else if (mods
[11]) {
873 config
.modulation
= DEMOD_BIa
;
877 config
.block0
= ((config
.block0
& ~(0x1f000)) | (config
.modulation
<< 12));
879 config
.block0Status
= USERSET
;
881 SetConfigWithBlock0Ex(block0
, config
.offset
, config
.Q5
);
884 PrintAndLogEx(INFO
, "--- " _CYAN_("current t55xx config") " --------------------------");
885 return printConfiguration(config
);
887 int T55xxReadBlock(uint8_t block
, bool page1
, bool usepwd
, uint8_t override
, uint32_t password
, uint8_t downlink_mode
) {
888 return T55xxReadBlockEx(block
, page1
, usepwd
, override
, password
, downlink_mode
, true);
891 int T55xxReadBlockEx(uint8_t block
, bool page1
, bool usepwd
, uint8_t override
, uint32_t password
, uint8_t downlink_mode
, bool verbose
) {
894 // try reading the config block and verify that PWD bit is set before doing this!
895 // override = 1 (override and display)
896 // override = 2 (override and no display)
898 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, false, 0, downlink_mode
) == false)
901 if (t55xxTryDetectModulationEx(downlink_mode
, false, 0, password
) == false) {
902 PrintAndLogEx(WARNING
, "Safety check: Could not detect if PWD bit is set in config block. Exits.");
903 PrintAndLogEx(HINT
, "Consider using the override parameter to force read.");
904 return PM3_EWRONGANSWER
;
906 PrintAndLogEx(WARNING
, "Safety check: PWD bit is NOT set in config block. Reading without password...");
910 } else if (override
== 1) {
911 PrintAndLogEx(INFO
, "Safety check overridden - proceeding despite risk");
915 if (AcquireData(page1
, block
, usepwd
, password
, downlink_mode
) == false)
918 if (DecodeT55xxBlock() == false)
919 return PM3_EWRONGANSWER
;
922 printT55xxBlock(block
, page1
);
927 static int CmdT55xxReadBlock(const char *Cmd
) {
928 CLIParserContext
*ctx
;
929 CLIParserInit(&ctx
, "lf t55xx read",
930 "Read T55xx block data. This commands defaults to page 0.\n\n"
931 _RED_(" * * * WARNING * * *") "\n"
932 _CYAN_("Use of read with password on a tag not configured") "\n"
933 _CYAN_("for a password can damage the tag") "\n"
934 _RED_(" * * * * * * * * * *"),
935 "lf t55xx read -b 0 --> read data from block 0\n"
936 "lf t55xx read -b 0 --pwd 01020304 --> read data from block 0, pwd 01020304\n"
937 "lf t55xx read -b 0 --pwd 01020304 -o --> read data from block 0, pwd 01020304, override\n"
940 // 1 (help) + 4(four user specified params) + (5 T55XX_DLMODE_SINGLE)
941 void *argtable
[5 + 5] = {
943 arg_int1("b", "blk", "<0-7>", "block number to read"),
944 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
945 arg_lit0("o", "override", "override safety check"),
946 arg_lit0(NULL
, "pg1", "read page 1"),
949 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
950 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
952 int block
= arg_get_int_def(ctx
, 1, REGULAR_READ_MODE_BLOCK
);
955 uint32_t password
= 0;
956 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &password
, 4, true);
957 if (res
== 0 || res
== 2) {
958 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
966 uint8_t override
= arg_get_lit(ctx
, 3);
967 bool page1
= arg_get_lit(ctx
, 4);
969 bool r0
= arg_get_lit(ctx
, 5);
970 bool r1
= arg_get_lit(ctx
, 6);
971 bool r2
= arg_get_lit(ctx
, 7);
972 bool r3
= arg_get_lit(ctx
, 8);
975 if ((r0
+ r1
+ r2
+ r3
) > 1) {
976 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
980 uint8_t downlink_mode
= config
.downlink_mode
;
982 downlink_mode
= refFixedBit
;
984 downlink_mode
= refLongLeading
;
986 downlink_mode
= refLeading0
;
988 downlink_mode
= ref1of4
;
990 if (block
> 7 && block
!= REGULAR_READ_MODE_BLOCK
) {
991 PrintAndLogEx(NORMAL
, "Block must be between 0 and 7");
995 printT5xxHeader(page1
);
996 return T55xxReadBlock(block
, page1
, usepwd
, override
, password
, downlink_mode
);
999 bool DecodeT55xxBlock(void) {
1002 bool ST
= config
.ST
;
1003 uint8_t bitRate
[8] = {8, 16, 32, 40, 50, 64, 100, 128};
1004 g_DemodBufferLen
= 0x00;
1006 switch (config
.modulation
) {
1008 ans
= FSKrawDemod(bitRate
[config
.bitrate
], config
.inverted
, 0, 0, false);
1012 ans
= FSKrawDemod(bitRate
[config
.bitrate
], config
.inverted
, 8, 5, false);
1016 ans
= FSKrawDemod(bitRate
[config
.bitrate
], config
.inverted
, 10, 8, false);
1019 ans
= ASKDemod_ext(bitRate
[config
.bitrate
], config
.inverted
, 1, 0, false, false, false, 1, &ST
);
1022 ans
= PSKDemod(bitRate
[config
.bitrate
], config
.inverted
, 6, false);
1024 case DEMOD_PSK2
: //inverted won't affect this
1025 case DEMOD_PSK3
: //not fully implemented
1026 ans
= PSKDemod(bitRate
[config
.bitrate
], 0, 6, false);
1027 psk1TOpsk2(g_DemodBuffer
, g_DemodBufferLen
);
1030 ans
= NRZrawDemod(bitRate
[config
.bitrate
], config
.inverted
, 1, false);
1034 ans
= ASKbiphaseDemod(0, bitRate
[config
.bitrate
], config
.inverted
, 1, false);
1039 return (ans
== PM3_SUCCESS
);
1042 static bool DecodeT5555TraceBlock(void) {
1043 g_DemodBufferLen
= 0x00;
1045 // According to datasheet. Always: RF/64, not inverted, Manchester
1047 return (ASKDemod_ext(64, 0, 1, 0, false, false, false, 1, &st
) == PM3_SUCCESS
);
1050 // sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf
1051 static int SanityOfflineCheck(bool useGraphBuffer
) {
1052 if (!useGraphBuffer
&& !g_session
.pm3_present
) {
1053 PrintAndLogEx(WARNING
, "Your proxmark3 device is offline. Specify [1] to use graphbuffer data instead");
1059 static void T55xx_Print_DownlinkMode(uint8_t downlink_mode
) {
1061 snprintf(msg
, sizeof(msg
), "Downlink Mode used : ");
1063 switch (downlink_mode
) {
1065 strcat(msg
, _YELLOW_("long leading reference"));
1068 strcat(msg
, _YELLOW_("leading zero reference"));
1071 strcat(msg
, _YELLOW_("1 of 4 coding reference"));
1074 strcat(msg
, _YELLOW_("default/fixed bit length"));
1078 PrintAndLogEx(SUCCESS
, msg
);
1081 static int CmdT55xxWakeUp(const char *Cmd
) {
1082 CLIParserContext
*ctx
;
1083 CLIParserInit(&ctx
, "lf t55xx wakeup",
1084 "This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards",
1085 "lf t55xx wakeup -p 11223344 --> send wakeup with password\n"
1088 // 1 (help) + 2 (two user specified params) + (5 T55XX_DLMODE_SINGLE)
1089 void *argtable
[3 + 5] = {
1091 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
1092 arg_lit0("v", "verbose", "verbose output"),
1095 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
1096 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1098 uint32_t password
= 0;
1099 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &password
, 4, true);
1100 if (res
== 0 || res
== 2) {
1101 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
1106 bool verbose
= arg_get_lit(ctx
, 2);
1107 bool r0
= arg_get_lit(ctx
, 3);
1108 bool r1
= arg_get_lit(ctx
, 4);
1109 bool r2
= arg_get_lit(ctx
, 5);
1110 bool r3
= arg_get_lit(ctx
, 6);
1113 if ((r0
+ r1
+ r2
+ r3
) > 1) {
1114 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
1118 uint8_t downlink_mode
= config
.downlink_mode
;
1120 downlink_mode
= refFixedBit
;
1122 downlink_mode
= refLongLeading
;
1124 downlink_mode
= refLeading0
;
1126 downlink_mode
= ref1of4
;
1133 payload
.password
= password
;
1134 payload
.flags
= (downlink_mode
<< 3);
1136 clearCommandBuffer();
1137 SendCommandNG(CMD_LF_T55XX_WAKEUP
, (uint8_t *)&payload
, sizeof(payload
));
1138 if (WaitForResponseTimeout(CMD_LF_T55XX_WAKEUP
, NULL
, 1000) == false) {
1139 PrintAndLogEx(WARNING
, "command execution time out");
1140 return PM3_ETIMEOUT
;
1144 PrintAndLogEx(SUCCESS
, "Wake up command sent. Try read now");
1149 static int CmdT55xxDetect(const char *Cmd
) {
1150 CLIParserContext
*ctx
;
1151 CLIParserInit(&ctx
, "lf t55xx detect",
1152 "Try detecting the tag modulation from reading the configuration block",
1154 "lf t55xx detect -1\n"
1155 "lf t55xx detect -p 11223344\n"
1158 // 1 (help) + 2 (two user specified params) + (6 T55XX_DLMODE_ALL)
1159 void *argtable
[3 + 6] = {
1161 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
1162 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
1165 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_ALL
, config
.downlink_mode
);
1166 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1168 bool use_gb
= arg_get_lit(ctx
, 1);
1170 bool usepwd
= false;
1171 uint64_t password
= -1;
1172 uint32_t tmp_pwd
= 0;
1173 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &tmp_pwd
, 4, true);
1174 if (res
== 0 || res
== 2) {
1175 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
1184 bool r0
= arg_get_lit(ctx
, 3);
1185 bool r1
= arg_get_lit(ctx
, 4);
1186 bool r2
= arg_get_lit(ctx
, 5);
1187 bool r3
= arg_get_lit(ctx
, 6);
1188 bool ra
= arg_get_lit(ctx
, 7);
1191 if ((r0
+ r1
+ r2
+ r3
+ ra
) > 1) {
1192 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
1196 bool try_all_dl_modes
= false;
1197 uint8_t downlink_mode
= config
.downlink_mode
;
1199 downlink_mode
= refFixedBit
;
1201 downlink_mode
= refLongLeading
;
1203 downlink_mode
= refLeading0
;
1205 downlink_mode
= ref1of4
;
1206 else // This will set the default to user all d/l modes which will cover the ra flag as well.
1207 try_all_dl_modes
= true;
1211 // Setup the 90ms time value to sleep for after the wake, to allow delay init to complete (~70ms)
1212 struct timespec sleepperiod
;
1213 sleepperiod
.tv_sec
= 0;
1214 sleepperiod
.tv_nsec
= 90000000;
1216 // detect called so clear data blocks
1217 T55x7_ClearAllBlockData();
1220 if (SanityOfflineCheck(use_gb
) != PM3_SUCCESS
)
1223 if (use_gb
== false) {
1225 char wakecmd
[20] = { 0x00 };
1226 snprintf(wakecmd
, sizeof(wakecmd
), "-p %08" PRIx64
, password
);
1228 bool usewake
= false;
1229 bool try_with_pwd
= false;
1230 // do ... while not found and not yet tried with wake (for AOR or Init Delay)
1232 // do ... while to check without password then loop back if password supplied
1234 if (try_all_dl_modes
) {
1235 // Loop from 1st d/l mode refFixedBit to the last d/l mode ref1of4
1236 for (uint8_t m
= refFixedBit
; m
<= ref1of4
; m
++) {
1240 CmdT55xxWakeUp(wakecmd
);
1244 nanosleep(&sleepperiod
, &sleepperiod
);
1247 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, (try_with_pwd
&& usepwd
), password
, m
) == false)
1250 if (t55xxTryDetectModulationEx(m
, T55XX_PrintConfig
, 0, (try_with_pwd
&& usepwd
) ? password
: -1) == false)
1260 CmdT55xxWakeUp(wakecmd
);
1264 nanosleep(&sleepperiod
, &sleepperiod
);
1267 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, usepwd
, password
, downlink_mode
)) {
1268 found
= t55xxTryDetectModulationEx(downlink_mode
, T55XX_PrintConfig
, 0, (usepwd
) ? password
: -1);
1272 // toggle so we loop back if not found and try with pwd
1273 if (found
== false && usepwd
)
1274 try_with_pwd
= !try_with_pwd
;
1276 // force exit as detect block has been found
1278 try_with_pwd
= false;
1280 } while (try_with_pwd
);
1281 // Toggle so we loop back and try with wakeup.
1283 } while (found
== false && usewake
);
1285 found
= t55xxTryDetectModulation(downlink_mode
, T55XX_PrintConfig
);
1288 if (found
== false) {
1289 config
.usepwd
= false;
1291 PrintAndLogEx(WARNING
, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'"));
1297 // detect configuration?
1298 bool t55xxTryDetectModulation(uint8_t downlink_mode
, bool print_config
) {
1299 return t55xxTryDetectModulationEx(downlink_mode
, print_config
, 0, -1);
1302 bool t55xxTryDetectModulationEx(uint8_t downlink_mode
, bool print_config
, uint32_t wanted_conf
, uint64_t pwd
) {
1304 t55xx_conf_block_t tests
[15];
1305 int bitRate
= 0, clk
= 0, firstClockEdge
= 0;
1306 uint8_t hits
= 0, fc1
= 0, fc2
= 0, ans
= 0;
1308 ans
= fskClocks(&fc1
, &fc2
, (uint8_t *)&clk
, &firstClockEdge
);
1310 if (ans
&& ((fc1
== 10 && fc2
== 8) || (fc1
== 8 && fc2
== 5))) {
1311 if ((FSKrawDemod(0, 0, 0, 0, false) == PM3_SUCCESS
) && test(DEMOD_FSK
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1312 tests
[hits
].modulation
= DEMOD_FSK
;
1313 if (fc1
== 8 && fc2
== 5)
1314 tests
[hits
].modulation
= DEMOD_FSK1a
;
1315 else if (fc1
== 10 && fc2
== 8)
1316 tests
[hits
].modulation
= DEMOD_FSK2
;
1317 tests
[hits
].bitrate
= bitRate
;
1318 tests
[hits
].inverted
= false;
1319 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1320 tests
[hits
].ST
= false;
1321 tests
[hits
].downlink_mode
= downlink_mode
;
1324 if ((FSKrawDemod(0, 1, 0, 0, false) == PM3_SUCCESS
) && test(DEMOD_FSK
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1325 tests
[hits
].modulation
= DEMOD_FSK
;
1326 if (fc1
== 8 && fc2
== 5)
1327 tests
[hits
].modulation
= DEMOD_FSK1
;
1328 else if (fc1
== 10 && fc2
== 8)
1329 tests
[hits
].modulation
= DEMOD_FSK2a
;
1330 tests
[hits
].bitrate
= bitRate
;
1331 tests
[hits
].inverted
= true;
1332 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1333 tests
[hits
].ST
= false;
1334 tests
[hits
].downlink_mode
= downlink_mode
;
1338 clk
= GetAskClock("", false);
1340 tests
[hits
].ST
= true;
1341 // "0 0 1 " == clock auto, invert false, maxError 1.
1342 // false = no verbose
1343 // false = no emSearch
1346 if ((ASKDemod_ext(0, 0, 1, 0, false, false, false, 1, &tests
[hits
].ST
) == PM3_SUCCESS
) && test(DEMOD_ASK
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1347 tests
[hits
].modulation
= DEMOD_ASK
;
1348 tests
[hits
].bitrate
= bitRate
;
1349 tests
[hits
].inverted
= false;
1350 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1351 tests
[hits
].downlink_mode
= downlink_mode
;
1354 tests
[hits
].ST
= true;
1355 // "0 0 1 " == clock auto, invert true, maxError 1.
1356 // false = no verbose
1357 // false = no emSearch
1360 if ((ASKDemod_ext(0, 1, 1, 0, false, false, false, 1, &tests
[hits
].ST
) == PM3_SUCCESS
) && test(DEMOD_ASK
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1361 tests
[hits
].modulation
= DEMOD_ASK
;
1362 tests
[hits
].bitrate
= bitRate
;
1363 tests
[hits
].inverted
= true;
1364 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1365 tests
[hits
].downlink_mode
= downlink_mode
;
1368 if ((ASKbiphaseDemod(0, 0, 0, 2, false) == PM3_SUCCESS
) && test(DEMOD_BI
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1369 tests
[hits
].modulation
= DEMOD_BI
;
1370 tests
[hits
].bitrate
= bitRate
;
1371 tests
[hits
].inverted
= false;
1372 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1373 tests
[hits
].ST
= false;
1374 tests
[hits
].downlink_mode
= downlink_mode
;
1377 if ((ASKbiphaseDemod(0, 0, 1, 2, false) == PM3_SUCCESS
) && test(DEMOD_BIa
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1378 tests
[hits
].modulation
= DEMOD_BIa
;
1379 tests
[hits
].bitrate
= bitRate
;
1380 tests
[hits
].inverted
= true;
1381 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1382 tests
[hits
].ST
= false;
1383 tests
[hits
].downlink_mode
= downlink_mode
;
1387 clk
= GetNrzClock("", false);
1388 if (clk
> 8) { //clock of rf/8 is likely a false positive, so don't use it.
1389 if ((NRZrawDemod(0, 0, 1, false) == PM3_SUCCESS
) && test(DEMOD_NRZ
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1390 tests
[hits
].modulation
= DEMOD_NRZ
;
1391 tests
[hits
].bitrate
= bitRate
;
1392 tests
[hits
].inverted
= false;
1393 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1394 tests
[hits
].ST
= false;
1395 tests
[hits
].downlink_mode
= downlink_mode
;
1399 if ((NRZrawDemod(0, 1, 1, false) == PM3_SUCCESS
) && test(DEMOD_NRZ
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1400 tests
[hits
].modulation
= DEMOD_NRZ
;
1401 tests
[hits
].bitrate
= bitRate
;
1402 tests
[hits
].inverted
= true;
1403 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1404 tests
[hits
].ST
= false;
1405 tests
[hits
].downlink_mode
= downlink_mode
;
1410 clk
= GetPskClock("", false);
1413 buffer_savestate_t saveState
= save_bufferS32(g_GraphBuffer
, g_GraphTraceLen
);
1414 saveState
.offset
= g_GridOffset
;
1415 // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
1417 if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) && test(DEMOD_PSK1
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1418 tests
[hits
].modulation
= DEMOD_PSK1
;
1419 tests
[hits
].bitrate
= bitRate
;
1420 tests
[hits
].inverted
= false;
1421 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1422 tests
[hits
].ST
= false;
1423 tests
[hits
].downlink_mode
= downlink_mode
;
1426 if ((PSKDemod(0, 1, 6, false) == PM3_SUCCESS
) && test(DEMOD_PSK1
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1427 tests
[hits
].modulation
= DEMOD_PSK1
;
1428 tests
[hits
].bitrate
= bitRate
;
1429 tests
[hits
].inverted
= true;
1430 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1431 tests
[hits
].ST
= false;
1432 tests
[hits
].downlink_mode
= downlink_mode
;
1435 //ICEMAN: are these PSKDemod calls needed?
1436 // PSK2 - needs a call to psk1TOpsk2.
1437 if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) {
1438 psk1TOpsk2(g_DemodBuffer
, g_DemodBufferLen
);
1439 if (test(DEMOD_PSK2
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1440 tests
[hits
].modulation
= DEMOD_PSK2
;
1441 tests
[hits
].bitrate
= bitRate
;
1442 tests
[hits
].inverted
= false;
1443 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1444 tests
[hits
].ST
= false;
1445 tests
[hits
].downlink_mode
= downlink_mode
;
1448 } // inverse waves does not affect this demod
1449 // PSK3 - needs a call to psk1TOpsk2.
1450 if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) {
1451 psk1TOpsk2(g_DemodBuffer
, g_DemodBufferLen
);
1452 if (test(DEMOD_PSK3
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1453 tests
[hits
].modulation
= DEMOD_PSK3
;
1454 tests
[hits
].bitrate
= bitRate
;
1455 tests
[hits
].inverted
= false;
1456 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, g_DemodBuffer
);
1457 tests
[hits
].ST
= false;
1458 tests
[hits
].downlink_mode
= downlink_mode
;
1461 } // inverse waves does not affect this demod
1463 restore_bufferS32(saveState
, g_GraphBuffer
);
1464 g_GridOffset
= saveState
.offset
;
1465 // t55xx_search_config_psk(g_GraphBuffer, 1);
1466 // t55xx_search_config_psk(g_GraphBuffer, 2);
1470 config
.modulation
= tests
[0].modulation
;
1471 config
.bitrate
= tests
[0].bitrate
;
1472 config
.inverted
= tests
[0].inverted
;
1473 config
.offset
= tests
[0].offset
;
1474 config
.block0
= tests
[0].block0
;
1475 config
.Q5
= tests
[0].Q5
;
1476 config
.ST
= tests
[0].ST
;
1477 config
.downlink_mode
= downlink_mode
;
1479 config
.usepwd
= true;
1480 config
.pwd
= pwd
& 0xffffffff;
1483 config
.block0Status
= AUTODETECT
;
1485 printConfiguration(config
);
1490 bool retval
= false;
1492 PrintAndLogEx(SUCCESS
, "Found [%d] possible matches for modulation.", hits
);
1493 for (int i
= 0; i
< hits
; ++i
) {
1495 bool wanted
= false;
1496 if (wanted_conf
> 0)
1497 wanted
= (wanted_conf
== tests
[i
].block0
);
1499 retval
= testKnownConfigBlock(tests
[i
].block0
);
1500 if (retval
|| wanted
) {
1501 PrintAndLogEx(NORMAL
, "--[%d]--------------- << selected this", i
+ 1);
1502 config
.modulation
= tests
[i
].modulation
;
1503 config
.bitrate
= tests
[i
].bitrate
;
1504 config
.inverted
= tests
[i
].inverted
;
1505 config
.offset
= tests
[i
].offset
;
1506 config
.block0
= tests
[i
].block0
;
1507 config
.Q5
= tests
[i
].Q5
;
1508 config
.ST
= tests
[i
].ST
;
1509 config
.downlink_mode
= tests
[i
].downlink_mode
;
1512 config
.usepwd
= true;
1513 config
.pwd
= pwd
& 0xffffffff;
1516 PrintAndLogEx(NORMAL
, "--[%d]---------------", i
+ 1);
1519 config
.block0Status
= AUTODETECT
;
1521 printConfiguration(tests
[i
]);
1527 bool testKnownConfigBlock(uint32_t block0
) {
1529 case T55X7_DEFAULT_CONFIG_BLOCK
:
1530 case T55X7_RAW_CONFIG_BLOCK
:
1531 case T55X7_EM_UNIQUE_CONFIG_BLOCK
:
1532 case T55X7_FDXB_CONFIG_BLOCK
:
1533 case T55X7_FDXB_2_CONFIG_BLOCK
:
1534 case T55X7_HID_26_CONFIG_BLOCK
:
1535 case T55X7_PYRAMID_CONFIG_BLOCK
:
1536 case T55X7_INDALA_64_CONFIG_BLOCK
:
1537 case T55X7_INDALA_224_CONFIG_BLOCK
:
1538 case T55X7_GUARDPROXII_CONFIG_BLOCK
:
1539 case T55X7_VIKING_CONFIG_BLOCK
:
1540 case T55X7_NORALSY_CONFIG_BLOCK
:
1541 case T55X7_IOPROX_CONFIG_BLOCK
:
1542 case T55X7_PRESCO_CONFIG_BLOCK
:
1543 case T55X7_NEDAP_64_CONFIG_BLOCK
:
1544 case T55X7_NEDAP_128_CONFIG_BLOCK
:
1545 case T55X7_VISA2000_CONFIG_BLOCK
:
1546 case T55X7_SECURAKEY_CONFIG_BLOCK
:
1547 case T55X7_PAC_CONFIG_BLOCK
:
1548 case T55X7_VERICHIP_CONFIG_BLOCK
:
1549 case T55X7_KERI_CONFIG_BLOCK
:
1550 case T55X7_NEXWATCH_CONFIG_BLOCK
:
1551 case T55X7_JABLOTRON_CONFIG_BLOCK
:
1552 case T55X7_PYRONIX_CONFIG_BLOCK
:
1558 bool GetT55xxBlockData(uint32_t *blockdata
) {
1560 if (g_DemodBufferLen
== 0)
1563 uint8_t idx
= config
.offset
;
1565 if (idx
+ 32 > g_DemodBufferLen
) {
1566 PrintAndLogEx(WARNING
, "The configured offset %d is too big. Possible offset: %zu)", idx
, g_DemodBufferLen
- 32);
1570 *blockdata
= PackBits(0, 32, g_DemodBuffer
+ idx
);
1574 void printT55xxBlock(uint8_t blockNum
, bool page1
) {
1577 if (GetT55xxBlockData(&val
) == false)
1580 uint8_t bytes
[4] = {0};
1581 num_to_bytes(val
, 4, bytes
);
1583 T55x7_SaveBlockData((page1
) ? blockNum
+ 8 : blockNum
, val
);
1585 PrintAndLogEx(SUCCESS
, " %02d | %08X | %s | %s", blockNum
, val
, sprint_bytebits_bin(g_DemodBuffer
+ config
.offset
, 32), sprint_ascii(bytes
, 4));
1588 static bool testModulation(uint8_t mode
, uint8_t modread
) {
1591 if (modread
>= DEMOD_FSK1
&& modread
<= DEMOD_FSK2a
) return true;
1594 if (modread
== DEMOD_ASK
) return true;
1597 if (modread
== DEMOD_PSK1
) return true;
1600 if (modread
== DEMOD_PSK2
) return true;
1603 if (modread
== DEMOD_PSK3
) return true;
1606 if (modread
== DEMOD_NRZ
) return true;
1609 if (modread
== DEMOD_BI
) return true;
1612 if (modread
== DEMOD_BIa
) return true;
1620 static bool testQ5Modulation(uint8_t mode
, uint8_t modread
) {
1623 if (modread
>= 4 && modread
<= 5) return true;
1626 if (modread
== 0) return true;
1629 if (modread
== 1) return true;
1632 if (modread
== 2) return true;
1635 if (modread
== 3) return true;
1638 if (modread
== 7) return true;
1641 if (modread
== 6) return true;
1649 static int convertQ5bitRate(uint8_t bitRateRead
) {
1650 const uint8_t expected
[] = {8, 16, 32, 40, 50, 64, 100, 128};
1651 for (int i
= 0; i
< 8; i
++)
1652 if (expected
[i
] == bitRateRead
)
1658 static bool testQ5(uint8_t mode
, uint8_t *offset
, int *fndBitRate
, uint8_t clk
) {
1660 if (g_DemodBufferLen
< 64) return false;
1662 for (uint8_t idx
= 28; idx
< 64; idx
++) {
1664 if (PackBits(si
, 28, g_DemodBuffer
) == 0x00) continue;
1666 uint8_t safer
= PackBits(si
, 4, g_DemodBuffer
);
1667 si
+= 4; //master key
1668 uint8_t resv
= PackBits(si
, 8, g_DemodBuffer
);
1670 // 2nibble must be zeroed.
1671 if (safer
!= 0x6 && safer
!= 0x9) continue;
1672 if (resv
> 0x00) continue;
1673 //uint8_t pageSel = PackBits(si, 1, g_DemodBuffer); si += 1;
1674 //uint8_t fastWrite = PackBits(si, 1, g_DemodBuffer); si += 1;
1676 int bitRate
= PackBits(si
, 6, g_DemodBuffer
) * 2 + 2;
1678 if (bitRate
> 128 || bitRate
< 8) continue;
1680 //uint8_t AOR = PackBits(si, 1, g_DemodBuffer); si += 1;
1681 //uint8_t PWD = PackBits(si, 1, g_DemodBuffer); si += 1;
1682 //uint8_t pskcr = PackBits(si, 2, g_DemodBuffer); si += 2; //could check psk cr
1683 //uint8_t inverse = PackBits(si, 1, g_DemodBuffer); si += 1;
1684 si
+= 1 + 1 + 2 + 1;
1685 uint8_t modread
= PackBits(si
, 3, g_DemodBuffer
);
1687 uint8_t maxBlk
= PackBits(si
, 3, g_DemodBuffer
);
1689 //uint8_t ST = PackBits(si, 1, g_DemodBuffer); si += 1;
1690 if (maxBlk
== 0) continue;
1693 if (!testQ5Modulation(mode
, modread
)) continue;
1694 if (bitRate
!= clk
) continue;
1696 *fndBitRate
= convertQ5bitRate(bitRate
);
1697 if (*fndBitRate
< 0) continue;
1706 static bool testBitRate(uint8_t readRate
, uint8_t clk
) {
1707 const uint8_t expected
[] = {8, 16, 32, 40, 50, 64, 100, 128};
1708 if (expected
[readRate
] == clk
)
1714 bool test(uint8_t mode
, uint8_t *offset
, int *fndBitRate
, uint8_t clk
, bool *Q5
) {
1716 if (g_DemodBufferLen
< 64) {
1720 for (uint8_t idx
= 28; idx
< 64; idx
++) {
1724 if (PackBits(si
, 28, g_DemodBuffer
) == 0x00) {
1728 uint8_t safer
= PackBits(si
, 4, g_DemodBuffer
);
1729 si
+= 4; //master key
1730 uint8_t resv
= PackBits(si
, 4, g_DemodBuffer
);
1731 si
+= 4; //was 7 & +=7+3 //should be only 4 bits if extended mode
1732 // 2nibble must be zeroed.
1733 // moved test to here, since this gets most faults first.
1739 int bitRate
= PackBits(si
, 6, g_DemodBuffer
);
1740 si
+= 6; //bit rate (includes extended mode part of rate)
1741 uint8_t extend
= PackBits(si
, 1, g_DemodBuffer
);
1742 si
+= 1; //bit 15 extended mode
1743 uint8_t modread
= PackBits(si
, 5, g_DemodBuffer
);
1745 //uint8_t pskcr = PackBits(si, 2, g_DemodBuffer); si += 2+1; //could check psk cr
1746 //uint8_t nml01 = PackBits(si, 1, g_DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode
1747 //uint8_t nml02 = PackBits(si, 2, g_DemodBuffer); si += 2;
1750 bool extMode
= ((safer
== 0x6 || safer
== 0x9) && extend
) ? true : false;
1752 if (extMode
== false) {
1758 if (testBitRate(bitRate
, clk
) == false) {
1762 } else { //extended mode bitrate = same function to calc bitrate as em4x05
1763 if (EM4x05_GET_BITRATE(bitRate
) != clk
) {
1769 if (testModulation(mode
, modread
) == false) {
1773 *fndBitRate
= bitRate
;
1779 if (testQ5(mode
, offset
, fndBitRate
, clk
)) {
1786 int CmdT55xxSpecial(const char *Cmd
) {
1788 CLIParserContext
*ctx
;
1789 CLIParserInit(&ctx
, "lf t55xx special",
1790 "Show block changes with 64 different offsets, data taken from DemodBuffer.",
1791 "lf t55xx special\n"
1794 void *argtable
[] = {
1798 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1801 uint8_t bits
[32] = {0x00};
1803 PrintAndLogEx(NORMAL
, "OFFSET | DATA | BINARY | ASCII");
1804 PrintAndLogEx(NORMAL
, "-------+-------+-------------------------------------+------");
1806 for (; j
< 64; ++j
) {
1808 for (i
= 0; i
< 32; ++i
)
1809 bits
[i
] = g_DemodBuffer
[j
+ i
];
1811 uint32_t blockData
= PackBits(0, 32, bits
);
1813 PrintAndLogEx(NORMAL
, "%02d | 0x%08X | %s", j
, blockData
, sprint_bytebits_bin(bits
, 32));
1818 int printConfiguration(t55xx_conf_block_t b
) {
1819 PrintAndLogEx(INFO
, " Chip type......... " _GREEN_("%s"), (b
.Q5
) ? "Q5/T5555" : "T55x7");
1820 PrintAndLogEx(INFO
, " Modulation........ " _GREEN_("%s"), GetSelectedModulationStr(b
.modulation
));
1821 PrintAndLogEx(INFO
, " Bit rate.......... %s", GetBitRateStr(b
.bitrate
, (b
.block0
& T55x7_X_MODE
&& (b
.block0
>> 28 == 6 || b
.block0
>> 28 == 9))));
1822 PrintAndLogEx(INFO
, " Inverted.......... %s", (b
.inverted
) ? _GREEN_("Yes") : "No");
1823 PrintAndLogEx(INFO
, " Offset............ %d", b
.offset
);
1824 PrintAndLogEx(INFO
, " Seq. terminator... %s", (b
.ST
) ? _GREEN_("Yes") : "No");
1825 PrintAndLogEx(INFO
, " Block0............ %08X %s", b
.block0
, GetConfigBlock0Source(b
.block0Status
));
1826 PrintAndLogEx(INFO
, " Downlink mode..... %s", GetDownlinkModeStr(b
.downlink_mode
));
1827 PrintAndLogEx(INFO
, " Password set...... %s", (b
.usepwd
) ? _RED_("Yes") : _GREEN_("No"));
1829 PrintAndLogEx(INFO
, " Password.......... %08X", b
.pwd
);
1831 PrintAndLogEx(NORMAL
, "");
1835 static int CmdT55xxWriteBlock(const char *Cmd
) {
1836 CLIParserContext
*ctx
;
1837 CLIParserInit(&ctx
, "lf t55xx write",
1838 "Write T55xx block data",
1839 "lf t55xx write -b 3 -d 11223344 --> write 11223344 to block 3\n"
1840 "lf t55xx write -b 3 -d 11223344 --pwd 01020304 --> write 11223344 to block 3, pwd 01020304\n"
1841 "lf t55xx write -b 3 -d 11223344 --pwd 01020304 --verify --> write 11223344 to block 3 and try validating write"
1844 // 1 (help) + 6 (six user specified params) + (5 T55XX_DLMODE_SINGLE)
1845 void *argtable
[7 + 5] = {
1847 arg_int1("b", "blk", "<0-7>", "block number to write"),
1848 arg_str0("d", "data", "<hex>", "data to write (4 hex bytes)"),
1849 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
1850 arg_lit0("t", "tm", "test mode write ( " _RED_("danger") " )"),
1851 arg_lit0(NULL
, "pg1", "write page 1"),
1852 arg_lit0(NULL
, "verify", "try validate data afterward"),
1855 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
1856 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1858 int block
= arg_get_int_def(ctx
, 1, REGULAR_READ_MODE_BLOCK
);
1860 uint32_t data
= 0; // default to blank Block
1861 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &data
, 4, true);
1862 if (res
== 0 || res
== 2) {
1863 PrintAndLogEx(ERR
, "data must be 4 hex bytes");
1868 bool usepwd
= false;
1869 uint32_t password
= 0; // default to blank Block 7
1870 res
= arg_get_u32_hexstr_def_nlen(ctx
, 3, 0, &password
, 4, true);
1871 if (res
== 0 || res
== 2) {
1872 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
1880 bool testmode
= arg_get_lit(ctx
, 4);
1881 bool page1
= arg_get_lit(ctx
, 5);
1882 bool validate
= arg_get_lit(ctx
, 6);
1884 bool r0
= arg_get_lit(ctx
, 7);
1885 bool r1
= arg_get_lit(ctx
, 8);
1886 bool r2
= arg_get_lit(ctx
, 9);
1887 bool r3
= arg_get_lit(ctx
, 10);
1890 if ((r0
+ r1
+ r2
+ r3
) > 1) {
1891 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
1895 uint8_t downlink_mode
= config
.downlink_mode
;
1897 downlink_mode
= refFixedBit
;
1899 downlink_mode
= refLongLeading
;
1901 downlink_mode
= refLeading0
;
1903 downlink_mode
= ref1of4
;
1905 if (block
> 7 && block
!= REGULAR_READ_MODE_BLOCK
) {
1906 PrintAndLogEx(NORMAL
, "Block must be between 0 and 7");
1910 char pwdstr
[16] = {0};
1911 snprintf(pwdstr
, sizeof(pwdstr
), "pwd: 0x%08X", password
);
1913 PrintAndLogEx(INFO
, "Writing page %d block: %02d data: 0x%08X %s", page1
, block
, data
, (usepwd
) ? pwdstr
: "");
1915 if (t55xxWrite(block
, page1
, usepwd
, testmode
, password
, downlink_mode
, data
) != PM3_SUCCESS
) {
1916 PrintAndLogEx(ERR
, "Write failed");
1921 bool isOK
= t55xxVerifyWrite(block
, page1
, usepwd
, 1, password
, downlink_mode
, data
);
1923 PrintAndLogEx(SUCCESS
, "Write OK, validation successful");
1925 PrintAndLogEx(WARNING
, "Write could not validate the written data");
1931 static int CmdT55xxDangerousRaw(const char *Cmd
) {
1932 CLIParserContext
*ctx
;
1933 CLIParserInit(&ctx
, "lf t55xx dangerraw",
1934 "This command allows to emit arbitrary raw commands on T5577 and cut the field after arbitrary duration.\n"
1935 "Uncontrolled usage can easily write an invalid configuration, activate lock bits,\n"
1936 "OTP bit, password protection bit, deactivate test-mode, lock your card forever.\n"
1937 _RED_("WARNING:") _CYAN_(" this may lock definitively the tag in an unusable state!"),
1938 "lf t55xx dangerraw -d 01000000000000010000100000000100000000 -t 3200\n"
1941 void *argtable
[] = {
1943 arg_str1("d", "data", NULL
, "raw bit string"),
1944 arg_int1("t", "time", "<us>", "<0 - 200000> time in microseconds before dropping the field"),
1947 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1949 // supports only default downlink mode
1950 t55xx_test_block_t ng
;
1953 memset(ng
.data
, 0x00, sizeof(ng
.data
));
1955 uint8_t bin
[129] = {0};
1956 int bin_len
= sizeof(bin
) - 1; // CLIGetStrWithReturn does not guarantee string to be null-terminated
1957 CLIGetStrWithReturn(ctx
, 1, bin
, &bin_len
);
1959 ng
.time
= arg_get_int_def(ctx
, 2, 0);
1962 if (ng
.time
== 0 || ng
.time
> 200000) {
1963 PrintAndLogEx(ERR
, "Timing off 1..200000 limits, got %i", ng
.time
);
1967 int bs_len
= binstr_2_binarray(ng
.data
, (char *)bin
, bin_len
);
1974 PacketResponseNG resp
;
1975 clearCommandBuffer();
1976 SendCommandNG(CMD_LF_T55XX_DANGERRAW
, (uint8_t *)&ng
, sizeof(ng
));
1977 if (!WaitForResponseTimeout(CMD_LF_T55XX_DANGERRAW
, &resp
, 2000)) {
1978 PrintAndLogEx(ERR
, "Error occurred, device did not ACK write operation.");
1979 return PM3_ETIMEOUT
;
1984 static int CmdT55xxReadTrace(const char *Cmd
) {
1986 CLIParserContext
*ctx
;
1987 CLIParserInit(&ctx
, "lf t55xx trace",
1988 "Show T55x7 configuration data (page 0/ blk 0) from reading the configuration block",
1993 // 1 (help) + 1 (one user specified params) + (5 T55XX_DLMODE_SINGLE)
1994 void *argtable
[2 + 5] = {
1996 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
1999 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
2000 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2002 bool use_gb
= arg_get_lit(ctx
, 1);
2004 bool r0
= arg_get_lit(ctx
, 2);
2005 bool r1
= arg_get_lit(ctx
, 3);
2006 bool r2
= arg_get_lit(ctx
, 4);
2007 bool r3
= arg_get_lit(ctx
, 5);
2010 if ((r0
+ r1
+ r2
+ r3
) > 1) {
2011 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
2015 uint8_t downlink_mode
= config
.downlink_mode
;
2017 downlink_mode
= refFixedBit
;
2019 downlink_mode
= refLongLeading
;
2021 downlink_mode
= refLeading0
;
2023 downlink_mode
= ref1of4
;
2025 if (use_gb
== false) {
2027 if (SanityOfflineCheck(false) != PM3_SUCCESS
) return PM3_ENODATA
;
2029 bool pwdmode
= false;
2030 uint32_t password
= 0;
2032 // REGULAR_READ_MODE_BLOCK - yields correct Page 1 Block 2 data i.e. + 32 bit offset.
2033 if (!AcquireData(T55x7_PAGE1
, REGULAR_READ_MODE_BLOCK
, pwdmode
, password
, downlink_mode
))
2038 if (DecodeT5555TraceBlock() == false) {
2042 if (DecodeT55xxBlock() == false) {
2047 if (g_DemodBufferLen
== 0) {
2051 RepaintGraphWindow();
2052 uint8_t repeat
= (config
.offset
> 5) ? 32 : 0;
2054 uint8_t si
= config
.offset
+ repeat
;
2055 uint32_t bl1
= PackBits(si
, 32, g_DemodBuffer
);
2056 uint32_t bl2
= PackBits(si
+ 32, 32, g_DemodBuffer
);
2059 uint32_t hdr
= PackBits(si
, 9, g_DemodBuffer
);
2063 PrintAndLogEx(FAILED
, "Invalid Q5/T5555 Trace data header (expected 0x1FF, found %X)", hdr
);
2067 t5555_tracedata_t data
= {.bl1
= bl1
, .bl2
= bl2
, .icr
= 0, .lotidc
= '?', .lotid
= 0, .wafer
= 0, .dw
= 0};
2069 data
.icr
= PackBits(si
, 2, g_DemodBuffer
);
2071 data
.lotidc
= 'Z' - PackBits(si
, 2, g_DemodBuffer
);
2074 data
.lotid
= PackBits(si
, 4, g_DemodBuffer
);
2077 data
.lotid
|= PackBits(si
, 4, g_DemodBuffer
);
2080 data
.lotid
|= PackBits(si
, 4, g_DemodBuffer
);
2083 data
.lotid
|= PackBits(si
, 4, g_DemodBuffer
);
2086 data
.lotid
|= PackBits(si
, 1, g_DemodBuffer
);
2089 data
.wafer
= PackBits(si
, 3, g_DemodBuffer
);
2092 data
.wafer
|= PackBits(si
, 2, g_DemodBuffer
);
2095 data
.dw
= PackBits(si
, 2, g_DemodBuffer
);
2098 data
.dw
|= PackBits(si
, 4, g_DemodBuffer
);
2101 data
.dw
|= PackBits(si
, 4, g_DemodBuffer
);
2104 data
.dw
|= PackBits(si
, 4, g_DemodBuffer
);
2106 printT5555Trace(data
, repeat
);
2110 t55x7_tracedata_t data
= {.bl1
= bl1
, .bl2
= bl2
, .acl
= 0, .mfc
= 0, .cid
= 0, .year
= 0, .quarter
= 0, .icr
= 0, .lotid
= 0, .wafer
= 0, .dw
= 0};
2112 data
.acl
= PackBits(si
, 8, g_DemodBuffer
);
2114 if (data
.acl
!= 0xE0) {
2115 PrintAndLogEx(FAILED
, "The modulation is most likely wrong since the ACL is not 0xE0. ");
2119 data
.mfc
= PackBits(si
, 8, g_DemodBuffer
);
2121 data
.cid
= PackBits(si
, 5, g_DemodBuffer
);
2123 data
.icr
= PackBits(si
, 3, g_DemodBuffer
);
2125 data
.year
= PackBits(si
, 4, g_DemodBuffer
);
2127 data
.quarter
= PackBits(si
, 2, g_DemodBuffer
);
2129 data
.lotid
= PackBits(si
, 14, g_DemodBuffer
);
2131 data
.wafer
= PackBits(si
, 5, g_DemodBuffer
);
2133 data
.dw
= PackBits(si
, 15, g_DemodBuffer
);
2135 struct tm
*ct
, tm_buf
;
2136 time_t now
= time(NULL
);
2138 ct
= localtime_s(&tm_buf
, &now
) == 0 ? &tm_buf
: NULL
;
2140 ct
= localtime_r(&now
, &tm_buf
);
2143 if (ct
!= NULL
&& (data
.year
> ct
->tm_year
- 110))
2148 printT55x7Trace(data
, repeat
);
2153 void printT55x7Trace(t55x7_tracedata_t data
, uint8_t repeat
) {
2154 PrintAndLogEx(INFO
, "--- " _CYAN_("T55x7 Trace Information") " ----------------------------------");
2155 PrintAndLogEx(INFO
, " ACL Allocation class (ISO/IEC 15963-1) : 0x%02X ( %d )", data
.acl
, data
.acl
);
2156 PrintAndLogEx(INFO
, " MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X ( %d ) - %s", data
.mfc
, data
.mfc
, getTagInfo(data
.mfc
));
2157 PrintAndLogEx(INFO
, " CID : 0x%02X ( %d ) - %s", data
.cid
, data
.cid
, GetModelStrFromCID(data
.cid
));
2158 PrintAndLogEx(INFO
, " ICR IC Revision : %d", data
.icr
);
2159 PrintAndLogEx(INFO
, " Manufactured");
2160 PrintAndLogEx(INFO
, " Year/Quarter... %d/%d", data
.year
, data
.quarter
);
2161 PrintAndLogEx(INFO
, " Lot ID......... %d", data
.lotid
);
2162 PrintAndLogEx(INFO
, " Wafer number... %d", data
.wafer
);
2163 PrintAndLogEx(INFO
, " Die Number..... %d", data
.dw
);
2164 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
2165 PrintAndLogEx(INFO
, " Raw Data - Page 1");
2166 PrintAndLogEx(INFO
, " Block 1... %08X - %s", data
.bl1
, sprint_bytebits_bin(g_DemodBuffer
+ config
.offset
+ repeat
, 32));
2167 PrintAndLogEx(INFO
, " Block 2... %08X - %s", data
.bl2
, sprint_bytebits_bin(g_DemodBuffer
+ config
.offset
+ repeat
+ 32, 32));
2168 PrintAndLogEx(NORMAL
, "");
2172 M1, M2 has the about ATMEL definition of trace data.
2173 M3 has unique format following industry defacto standard with row/col parity
2177 1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0
2178 9-16 MFC Manufacturer ID (ISO/IEC 7816-6) 0x15 Atmel Corporation
2179 17-21 CID 0x1 = Atmel ATA5577M1
2180 0x2 = Atmel ATA5577M2
2181 0x3 = Atmel ATA5577M3
2182 22-24 ICR IC revision
2183 25-28 YEAR (BCD encoded) 9 (= 2009)
2184 29-30 QUARTER 1,2,3,4
2190 18-32 DW, die number sequential
2199 void printT5555Trace(t5555_tracedata_t data
, uint8_t repeat
) {
2200 PrintAndLogEx(INFO
, "--- " _CYAN_("Q5/T5555 Trace Information") " ---------------------------");
2201 PrintAndLogEx(INFO
, " ICR IC Revision.... %d", data
.icr
);
2202 PrintAndLogEx(INFO
, " Lot ID......... %c%d", data
.lotidc
, data
.lotid
);
2203 PrintAndLogEx(INFO
, " Wafer number... %d", data
.wafer
);
2204 PrintAndLogEx(INFO
, " Die Number..... %d", data
.dw
);
2205 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
2206 PrintAndLogEx(INFO
, " Raw Data - Page 1");
2207 PrintAndLogEx(INFO
, " Block 1... %08X - %s", data
.bl1
, sprint_bytebits_bin(g_DemodBuffer
+ config
.offset
+ repeat
, 32));
2208 PrintAndLogEx(INFO
, " Block 2... %08X - %s", data
.bl2
, sprint_bytebits_bin(g_DemodBuffer
+ config
.offset
+ repeat
+ 32, 32));
2212 TRACE - BLOCK O and BLOCK1
2217 15-35 Lot ID (NB parity)
2218 36-41 Wafer number (NB parity)
2219 42-58 DW, die number sequential (NB parity)
2225 static void printT5x7KnownBlock0(uint32_t b0
) {
2228 memset(s
, 0, sizeof(s
));
2231 case T55X7_DEFAULT_CONFIG_BLOCK
:
2232 snprintf(s
, sizeof(s
) - strlen(s
), "T55x7 Default ");
2234 case T55X7_RAW_CONFIG_BLOCK
:
2235 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "T55x7 Raw ");
2237 case T55X7_EM_UNIQUE_CONFIG_BLOCK
:
2238 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "EM unique, Paxton ");
2240 case T55X7_FDXB_2_CONFIG_BLOCK
:
2241 case T55X7_FDXB_CONFIG_BLOCK
:
2242 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "FDXB ");
2244 case T55X7_HID_26_CONFIG_BLOCK
:
2245 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "HID 26b (ProxCard), Paradox, AWID ");
2247 case T55X7_PYRAMID_CONFIG_BLOCK
:
2248 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Pyramid ");
2250 case T55X7_INDALA_64_CONFIG_BLOCK
:
2251 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Indala 64, Motorola, Idteck");
2253 case T55X7_INDALA_224_CONFIG_BLOCK
:
2254 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Indala 224 ");
2256 case T55X7_GUARDPROXII_CONFIG_BLOCK
:
2257 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Guard Prox II ");
2259 case T55X7_VIKING_CONFIG_BLOCK
:
2260 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Viking ");
2262 case T55X7_NORALSY_CONFIG_BLOCK
:
2263 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Noralys ");
2265 case T55X7_IOPROX_CONFIG_BLOCK
:
2266 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "IO Prox ");
2268 case T55X7_PRESCO_CONFIG_BLOCK
:
2269 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Presco ");
2271 case T55X7_NEDAP_64_CONFIG_BLOCK
:
2272 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Nedap 64 ");
2274 case T55X7_NEDAP_128_CONFIG_BLOCK
:
2275 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Nedap 128 ");
2277 case T55X7_PAC_CONFIG_BLOCK
:
2278 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "PAC/Stanley ");
2280 case T55X7_VERICHIP_CONFIG_BLOCK
:
2281 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Verichip ");
2283 case T55X7_VISA2000_CONFIG_BLOCK
:
2284 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "VISA2000 ");
2286 case T55X7_JABLOTRON_CONFIG_BLOCK
:
2287 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Jablotron ");
2289 case T55X7_KERI_CONFIG_BLOCK
:
2290 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "KERI ");
2292 case T55X7_SECURAKEY_CONFIG_BLOCK
:
2293 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "SecuraKey ");
2295 case T55X7_NEXWATCH_CONFIG_BLOCK
:
2296 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "NexWatch, Quadrakey ");
2298 case T55X7_PYRONIX_CONFIG_BLOCK
:
2299 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Pyronix ");
2305 if (strlen(s
) > 0) {
2306 PrintAndLogEx(SUCCESS
, "Config block match : " _YELLOW_("%s"), s
);
2310 static int CmdT55xxInfo(const char *Cmd
) {
2311 CLIParserContext
*ctx
;
2312 CLIParserInit(&ctx
, "lf t55xx info",
2313 "Show T55x7 configuration data (page 0/ blk 0) from reading the configuration block\n"
2314 "from tag. Use `-c` to specify a config block data to be used instead of reading tag.",
2316 "lf t55xx info -1\n"
2317 "lf t55xx info -p 11223344\n"
2318 "lf t55xx info -c 00083040\n"
2319 "lf t55xx info -c 6001805A --q5"
2322 // 1 (help) + 4 (four user specified params) + (5 T55XX_DLMODE_SINGLE)
2323 void *argtable
[5 + 5] = {
2325 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
2326 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
2327 arg_str0("c", "blk0", "<hex>", "use these data instead (4 hex bytes)"),
2328 arg_lit0(NULL
, "q5", "interprete provided data as T5555/Q5 config"),
2331 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
2332 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2334 bool use_gb
= arg_get_lit(ctx
, 1);
2336 bool usepwd
= false;
2337 uint32_t password
= 0;
2338 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &password
, 4, true);
2339 if (res
== 0 || res
== 2) {
2340 PrintAndLogEx(ERR
, "Password must be 4 hex bytes");
2348 bool gotdata
= false;
2349 uint32_t block0
= 0;
2350 res
= arg_get_u32_hexstr_def_nlen(ctx
, 3, 0, &block0
, 4, true);
2351 if (res
== 0 || res
== 2) {
2352 PrintAndLogEx(ERR
, "block0 data must be 4 hex bytes");
2360 bool dataasq5
= arg_get_lit(ctx
, 4);
2362 bool r0
= arg_get_lit(ctx
, 5);
2363 bool r1
= arg_get_lit(ctx
, 6);
2364 bool r2
= arg_get_lit(ctx
, 7);
2365 bool r3
= arg_get_lit(ctx
, 8);
2368 if (gotdata
&& use_gb
) {
2369 PrintAndLogEx(FAILED
, "Must select one of user supplied data and use graphbuffer");
2373 if (dataasq5
&& gotdata
== false) {
2374 PrintAndLogEx(FAILED
, "Must specify user supplied Q5 data");
2378 if ((r0
+ r1
+ r2
+ r3
) > 1) {
2379 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
2383 uint8_t downlink_mode
= config
.downlink_mode
;
2385 downlink_mode
= refFixedBit
;
2387 downlink_mode
= refLongLeading
;
2389 downlink_mode
= refLeading0
;
2391 downlink_mode
= ref1of4
;
2395 Page 0 Block 0 Configuration data.
2400 if (use_gb
== false && gotdata
== false) {
2402 if (SanityOfflineCheck(false) != PM3_SUCCESS
) {
2406 if (!AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, usepwd
, password
, downlink_mode
)) {
2411 if (gotdata
== false) {
2412 if (DecodeT55xxBlock() == false) {
2416 // too little space to start with
2417 if (g_DemodBufferLen
< 32 + config
.offset
) {
2421 //PrintAndLogEx(NORMAL, "Offset+32 ==%d\n DemodLen == %d", config.offset + 32, g_DemodBufferLen);
2422 block0
= PackBits(config
.offset
, 32, g_DemodBuffer
);
2425 PrintAndLogEx(NORMAL
, "");
2426 if (((!gotdata
) && config
.Q5
) || (gotdata
&& dataasq5
)) {
2427 uint32_t header
= (block0
>> (32 - 12)) & 0xFFF;
2428 uint32_t ps
= (block0
>> (32 - 13)) & 0x01;
2429 uint32_t fw
= (block0
>> (32 - 14)) & 0x01;
2430 uint32_t dbr
= (block0
>> (32 - 20)) & 0x3F;
2431 uint32_t aor
= (block0
>> (32 - 21)) & 0x01;
2432 uint32_t pwd
= (block0
>> (32 - 22)) & 0x01;
2433 uint32_t pskcf
= (block0
>> (32 - 24)) & 0x03;
2434 uint32_t inv
= (block0
>> (32 - 25)) & 0x01;
2435 uint32_t datamod
= (block0
>> (32 - 28)) & 0x07;
2436 uint32_t maxblk
= (block0
>> (32 - 31)) & 0x07;
2437 uint32_t st
= block0
& 0x01;
2438 PrintAndLogEx(INFO
, "--- " _CYAN_("Q5 Configuration & Information") " ------------");
2439 PrintAndLogEx(INFO
, " Header : 0x%03X%s", header
, (header
!= 0x600) ? _RED_(" - Warning") : "");
2440 PrintAndLogEx(INFO
, " Page select : %d", ps
);
2441 PrintAndLogEx(INFO
, " Fast Write : %s", (fw
) ? _GREEN_("Yes") : "No");
2442 PrintAndLogEx(INFO
, " Data bit rate : %s", GetBitRateStr(dbr
, 1));
2443 PrintAndLogEx(INFO
, " AOR - Answer on Request : %s", (aor
) ? _GREEN_("Yes") : "No");
2444 PrintAndLogEx(INFO
, " Password mode : %s", (pwd
) ? _GREEN_("Yes") : "No");
2445 PrintAndLogEx(INFO
, " PSK clock frequency : %s", GetPskCfStr(pskcf
, 1));
2446 PrintAndLogEx(INFO
, " Inverse data : %s", (inv
) ? _GREEN_("Yes") : "No");
2447 PrintAndLogEx(INFO
, " Modulation : %s", GetQ5ModulationStr(datamod
));
2448 PrintAndLogEx(INFO
, " Max block : %d", maxblk
);
2449 PrintAndLogEx(INFO
, " Sequence Terminator : %s", (st
) ? _GREEN_("Yes") : "No");
2451 uint32_t safer
= (block0
>> (32 - 4)) & 0x0F;
2452 uint32_t extend
= (block0
>> (32 - 15)) & 0x01;
2455 resv
= (block0
>> (32 - 8)) & 0x0F;
2456 dbr
= (block0
>> (32 - 14)) & 0x3F;
2458 resv
= (block0
>> (32 - 11)) & 0x7F;
2459 dbr
= (block0
>> (32 - 14)) & 0x07;
2461 uint32_t datamod
= (block0
>> (32 - 20)) & 0x1F;
2462 uint32_t pskcf
= (block0
>> (32 - 22)) & 0x03;
2463 uint32_t aor
= (block0
>> (32 - 23)) & 0x01;
2464 uint32_t otp
= (block0
>> (32 - 24)) & 0x01;
2465 uint32_t maxblk
= (block0
>> (32 - 27)) & 0x07;
2466 uint32_t pwd
= (block0
>> (32 - 28)) & 0x01;
2467 uint32_t sst
= (block0
>> (32 - 29)) & 0x01;
2468 uint32_t fw
= (block0
>> (32 - 30)) & 0x01;
2469 uint32_t inv
= (block0
>> (32 - 31)) & 0x01;
2470 uint32_t por
= (block0
>> (32 - 32)) & 0x01;
2472 PrintAndLogEx(INFO
, "--- " _CYAN_("T55x7 Configuration & Information") " ---------");
2473 PrintAndLogEx(INFO
, " Safer key : %s", GetSaferStr(safer
));
2474 PrintAndLogEx(INFO
, " reserved : %d", resv
);
2475 PrintAndLogEx(INFO
, " Data bit rate : %s", GetBitRateStr(dbr
, extend
));
2476 PrintAndLogEx(INFO
, " eXtended mode : %s", (extend
) ? _YELLOW_("Yes - Warning") : "No");
2477 PrintAndLogEx(INFO
, " Modulation : %s", GetModulationStr(datamod
, extend
));
2478 PrintAndLogEx(INFO
, " PSK clock frequency : %s", GetPskCfStr(pskcf
, 0));
2479 PrintAndLogEx(INFO
, " AOR - Answer on Request : %s", (aor
) ? _GREEN_("Yes") : "No");
2480 PrintAndLogEx(INFO
, " OTP - One Time Pad : %s", (otp
) ? ((extend
) ? _YELLOW_("Yes - Warning") : _RED_("Yes - Warning")) : "No");
2481 PrintAndLogEx(INFO
, " Max block : %d", maxblk
);
2482 PrintAndLogEx(INFO
, " Password mode : %s", (pwd
) ? _GREEN_("Yes") : "No");
2483 PrintAndLogEx(INFO
, " Sequence %-12s : %s", (extend
) ? "Start Marker" : "Terminator", (sst
) ? _GREEN_("Yes") : "No");
2484 PrintAndLogEx(INFO
, " Fast Write : %s", (fw
) ? ((extend
) ? _GREEN_("Yes") : _RED_("Yes - Warning")) : "No");
2485 PrintAndLogEx(INFO
, " Inverse data : %s", (inv
) ? ((extend
) ? _GREEN_("Yes") : _RED_("Yes - Warning")) : "No");
2486 PrintAndLogEx(INFO
, " POR-Delay : %s", (por
) ? _GREEN_("Yes") : "No");
2488 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
2489 PrintAndLogEx(INFO
, " Raw Data - Page 0, block 0");
2491 PrintAndLogEx(INFO
, " " _GREEN_("%08X"), block0
);
2493 PrintAndLogEx(INFO
, " " _GREEN_("%08X") " - %s", block0
, sprint_bytebits_bin(g_DemodBuffer
+ config
.offset
, 32));
2495 if (((!gotdata
) && (!config
.Q5
)) || (gotdata
&& (!dataasq5
))) {
2496 PrintAndLogEx(INFO
, "--- " _CYAN_("Fingerprint") " ------------");
2497 printT5x7KnownBlock0(block0
);
2500 PrintAndLogEx(NORMAL
, "");
2501 //PrintAndLogEx(INFO, "-------------------------------------------------------------");
2505 static int CmdT55xxDump(const char *Cmd
) {
2507 CLIParserContext
*ctx
;
2508 CLIParserInit(&ctx
, "lf t55xx dump",
2509 "This command dumps a T55xx card Page 0 block 0-7.\n"
2510 "It will create two files (bin/json)",
2512 "lf t55xx dump -p aabbccdd --override\n"
2513 "lf t55xx dump -f my_lf_dump"
2516 // 1 (help) + 4 (two user specified params) + (5 T55XX_DLMODE_SINGLE)
2517 void *argtable
[5 + 5] = {
2519 arg_str0("f", "file", "<fn>", "filename (default is generated on blk 0)"),
2520 arg_lit0("o", "override", "override, force pwd read despite danger to card"),
2521 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
2522 arg_lit0(NULL
, "ns", "no save to file"),
2525 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, T55XX_DLMODE_SINGLE
);
2526 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2529 char filename
[FILE_PATH_SIZE
] = {0};
2530 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
2532 uint8_t override
= arg_get_lit(ctx
, 2) ? 1 : 0;
2534 bool usepwd
= false;
2535 uint32_t password
= 0;
2536 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 3, 0, &password
, 4, true);
2537 if (res
== 0 || res
== 2) {
2538 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
2546 bool nosave
= arg_get_lit(ctx
, 4);
2548 bool r0
= arg_get_lit(ctx
, 5);
2549 bool r1
= arg_get_lit(ctx
, 6);
2550 bool r2
= arg_get_lit(ctx
, 7);
2551 bool r3
= arg_get_lit(ctx
, 8);
2554 if ((r0
+ r1
+ r2
+ r3
) > 1) {
2555 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
2559 uint8_t downlink_mode
= config
.downlink_mode
;
2561 downlink_mode
= refFixedBit
;
2563 downlink_mode
= refLongLeading
;
2565 downlink_mode
= refLeading0
;
2567 downlink_mode
= ref1of4
;
2569 bool success
= true;
2571 PrintAndLogEx(NORMAL
, "");
2572 PrintAndLogEx(INFO
, "------------------------- " _CYAN_("T55xx tag memory") " -----------------------------");
2574 // Due to the few different T55xx cards and number of blocks supported
2575 // will save the dump file if ALL page 0 is OK
2577 for (uint8_t i
= 0; i
< 8; ++i
) {
2578 if (T55xxReadBlock(i
, 0, usepwd
, override
, password
, downlink_mode
) != PM3_SUCCESS
) {
2582 // only show override warning on the first block read
2583 if (override
== 1) {
2588 for (uint8_t i
= 0; i
< 4; i
++) {
2589 if (T55xxReadBlock(i
, 1, usepwd
, override
, password
, downlink_mode
) != PM3_SUCCESS
) {
2590 T55x7_SaveBlockData(8 + i
, 0x00);
2595 PrintAndLogEx(INFO
, "Called with no save option");
2596 PrintAndLogEx(NORMAL
, "");
2600 // all ok, save dump to file
2603 // set default filename, if not set by user
2604 if (strlen(filename
) == 0) {
2605 strcpy(filename
, "lf-t55xx");
2606 for (uint8_t i
= 1; i
<= 7; i
++) {
2607 if ((cardmem
[i
].blockdata
!= 0x00) && (cardmem
[i
].blockdata
!= 0xFFFFFFFF)) {
2608 snprintf(filename
+ strlen(filename
), sizeof(filename
) - strlen(filename
), "-%08X", cardmem
[i
].blockdata
);
2613 strcat(filename
, "-dump");
2616 // Swap endian so the files match the txt display
2617 uint32_t data
[T55x7_BLOCK_COUNT
] = {0};
2619 for (int i
= 0; i
< T55x7_BLOCK_COUNT
; i
++) {
2620 data
[i
] = BSWAP_32(cardmem
[i
].blockdata
);
2623 pm3_save_dump(filename
, (uint8_t *)data
, (T55x7_BLOCK_COUNT
* sizeof(uint32_t)), jsfT55x7
);
2629 static int CmdT55xxRestore(const char *Cmd
) {
2630 CLIParserContext
*ctx
;
2631 CLIParserInit(&ctx
, "lf t55xx restore",
2632 "Restore T55xx card page 0/1 n blocks from (bin/eml/json) dump file",
2633 "lf t55xx restore -f lf-t55xx-00148040-dump.bin"
2636 void *argtable
[] = {
2638 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
2639 arg_str0("p", "pwd", "<hex>", "password if target card has password set (4 hex bytes)"),
2642 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2645 char filename
[FILE_PATH_SIZE
] = {0};
2646 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
2648 bool usepwd
= false;
2649 uint32_t password
= 0;
2650 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &password
, 4, true);
2651 if (res
== 0 || res
== 2) {
2652 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
2662 PrintAndLogEx(ERR
, "Must specify a filename");
2667 uint32_t *dump
= NULL
;
2668 size_t bytes_read
= 0;
2669 res
= pm3_load_dump(filename
, (void **)&dump
, &bytes_read
, (T55x7_BLOCK_COUNT
* 4));
2670 if (res
!= PM3_SUCCESS
) {
2674 if (bytes_read
!= (T55x7_BLOCK_COUNT
* 4)) {
2676 PrintAndLogEx(FAILED
, "wrong length of dump file. Expected 48 bytes, got %zu", bytes_read
);
2680 // 12 blocks * 4 bytes per block
2681 // this part creates strings to call "lf t55 write" command.
2682 PrintAndLogEx(INFO
, "Starting to write...");
2684 uint8_t downlink_mode
;
2686 char pwdopt
[14] = {0}; // p XXXXXXXX
2689 snprintf(pwdopt
, sizeof(pwdopt
), "-p %08X", password
);
2693 // Restore endien for writing to card
2694 for (idx
= 0; idx
< 12; idx
++) {
2695 dump
[idx
] = BSWAP_32(dump
[idx
]);
2698 // Have data ready, lets write
2700 // write blocks 1..7 page 0
2701 // write blocks 1..3 page 1
2702 // update downlink mode (if needed) and write b 0
2704 if ((((dump
[11] >> 28) & 0xF) == 6) || (((dump
[11] >> 28) & 0xF) == 9))
2705 downlink_mode
= (dump
[11] >> 10) & 3;
2707 // write out blocks 1-7 page 0
2708 for (idx
= 1; idx
<= 7; idx
++) {
2709 snprintf(wcmd
, sizeof(wcmd
), "-b %d -d %08X %s", idx
, dump
[idx
], pwdopt
);
2711 if (CmdT55xxWriteBlock(wcmd
) != PM3_SUCCESS
) {
2712 PrintAndLogEx(WARNING
, "Warning: error writing blk %d", idx
);
2716 // if password was set on the "blank" update as we may have just changed it
2718 snprintf(pwdopt
, sizeof(pwdopt
), "-p %08X", dump
[7]);
2721 // write out blocks 1-3 page 1
2722 for (idx
= 9; idx
<= 11; idx
++) {
2723 snprintf(wcmd
, sizeof(wcmd
), "-b %d --pg1 -d %08X %s", idx
- 8, dump
[idx
], pwdopt
);
2725 if (CmdT55xxWriteBlock(wcmd
) != PM3_SUCCESS
) {
2726 PrintAndLogEx(WARNING
, "Warning: error writing blk %d", idx
);
2730 // Update downlink mode for the page 0 config write.
2731 config
.downlink_mode
= downlink_mode
;
2733 // Write the page 0 config
2734 snprintf(wcmd
, sizeof(wcmd
), "-b 0 -d %08X %s", dump
[0], pwdopt
);
2735 if (CmdT55xxWriteBlock(wcmd
) != PM3_SUCCESS
) {
2736 PrintAndLogEx(WARNING
, "Warning: error writing blk 0");
2739 PrintAndLogEx(INFO
, "Done!");
2743 static int CmdT55xxRestore(const char *Cmd) {
2745 uint32_t password = 0;
2746 uint8_t override = 0;
2747 uint8_t downlink_mode = config.downlink_mode;
2748 bool usepwd = false;
2749 bool errors = false;
2752 while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
2753 switch (tolower(param_getchar(Cmd, cmdp))) {
2755 return usage_t55xx_restore();
2757 downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
2758 if (downlink_mode > 3)
2764 password = param_get32ex(Cmd, cmdp + 1, 0, 16);
2773 PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
2778 if (errors) return usage_t55xx_restore();
2780 PrintAndLogEx(INFO, "Work in progress. To be implemented");
2781 if (usepwd || password || override ) {
2784 // load file name (json/eml/bin)
2788 uint32_t res = PM3_SUCCESS;
2791 // res = clone_t55xx_tag(blockdata, numblocks);
2796 bool AcquireData(uint8_t page
, uint8_t block
, bool pwdmode
, uint32_t password
, uint8_t downlink_mode
) {
2799 // b1 = page to read from
2800 // b2 = brute_mem (armside function)
2801 // arg1: which block to read
2808 uint8_t downlink_mode
;
2811 payload
.password
= password
;
2812 payload
.blockno
= block
;
2813 payload
.page
= page
& 0x1;
2814 payload
.pwdmode
= pwdmode
;
2815 payload
.downlink_mode
= downlink_mode
;
2817 clearCommandBuffer();
2818 SendCommandNG(CMD_LF_T55XX_READBL
, (uint8_t *)&payload
, sizeof(payload
));
2819 if (!WaitForResponseTimeout(CMD_LF_T55XX_READBL
, NULL
, 2500)) {
2820 PrintAndLogEx(WARNING
, "command execution time out");
2824 getSamples(12000, false);
2825 bool ok
= !getSignalProperties()->isnoise
;
2827 config
.usepwd
= pwdmode
;
2831 char *GetPskCfStr(uint32_t id
, bool q5
) {
2832 static char buf
[40];
2836 snprintf(retStr
, sizeof(buf
), "%u - RF/2", id
);
2839 snprintf(retStr
, sizeof(buf
), "%u - RF/4", id
);
2842 snprintf(retStr
, sizeof(buf
), "%u - RF/8", id
);
2846 snprintf(retStr
, sizeof(buf
), "%u - RF/8", id
);
2848 snprintf(retStr
, sizeof(buf
), "%u - " _RED_("(Unknown)"), id
);
2851 snprintf(retStr
, sizeof(buf
), "%u - " _RED_("(Unknown)"), id
);
2857 char *GetBitRateStr(uint32_t id
, bool xmode
) {
2858 static char buf
[35];
2861 if (xmode
) { //xmode bitrate calc is same as em4x05 calc
2862 snprintf(retStr
, sizeof(buf
), "%u - RF/%u", id
, EM4x05_GET_BITRATE(id
));
2866 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/8"), id
);
2869 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/16"), id
);
2872 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/32"), id
);
2875 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/40"), id
);
2878 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/50"), id
);
2881 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/64"), id
);
2884 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/100"), id
);
2887 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/128"), id
);
2890 snprintf(retStr
, sizeof(buf
), "%u - " _RED_("(Unknown)"), id
);
2897 char *GetSaferStr(uint32_t id
) {
2898 static char buf
[40];
2901 snprintf(retStr
, sizeof(buf
), "%u", id
);
2903 snprintf(retStr
, sizeof(buf
), "%u - " _YELLOW_("passwd"), id
);
2906 snprintf(retStr
, sizeof(buf
), "%u - " _YELLOW_("testmode"), id
);
2912 char *GetModulationStr(uint32_t id
, bool xmode
) {
2913 static char buf
[60];
2918 snprintf(retStr
, sizeof(buf
), "%u - DIRECT (ASK/NRZ)", id
);
2921 snprintf(retStr
, sizeof(buf
), "%u - PSK 1 phase change when input changes", id
);
2924 snprintf(retStr
, sizeof(buf
), "%u - PSK 2 phase change on bitclk if input high", id
);
2927 snprintf(retStr
, sizeof(buf
), "%u - PSK 3 phase change on rising edge of input", id
);
2930 snprintf(retStr
, sizeof(buf
), "%u - FSK 1 RF/8 RF/5", id
);
2933 snprintf(retStr
, sizeof(buf
), "%u - FSK 2 RF/8 RF/10", id
);
2936 snprintf(retStr
, sizeof(buf
), "%u - %s RF/5 RF/8", id
, (xmode
) ? "FSK 1a" : _YELLOW_("FSK 1a"));
2939 snprintf(retStr
, sizeof(buf
), "%u - %s RF/10 RF/8", id
, (xmode
) ? "FSK 2a" : _YELLOW_("FSK 2a"));
2942 snprintf(retStr
, sizeof(buf
), "%u - Manchester", id
);
2945 snprintf(retStr
, sizeof(buf
), "%u - Biphase", id
);
2948 snprintf(retStr
, sizeof(buf
), "%u - %s", id
, (xmode
) ? "Biphase a - AKA Conditional Dephase Encoding(CDP)" : _YELLOW_("Reserved"));
2951 snprintf(retStr
, sizeof(buf
), "0x%02X " _RED_("(Unknown)"), id
);
2957 char *GetDownlinkModeStr(uint8_t downlink_mode
) {
2958 static char buf
[30];
2961 switch (downlink_mode
) {
2962 case T55XX_DLMODE_FIXED
:
2963 snprintf(retStr
, sizeof(buf
), "default/fixed bit length");
2965 case T55XX_DLMODE_LLR
:
2966 snprintf(retStr
, sizeof(buf
), "long leading reference");
2968 case T55XX_DLMODE_LEADING_ZERO
:
2969 snprintf(retStr
, sizeof(buf
), "leading zero reference");
2971 case T55XX_DLMODE_1OF4
:
2972 snprintf(retStr
, sizeof(buf
), "1 of 4 coding reference");
2975 snprintf(retStr
, sizeof(buf
), _RED_("(Unknown)"));
2981 char *GetQ5ModulationStr(uint32_t id
) {
2982 static char buf
[60];
2987 snprintf(retStr
, sizeof(buf
), "%u - Manchester", id
);
2990 snprintf(retStr
, sizeof(buf
), "%u - PSK 1 phase change when input changes", id
);
2993 snprintf(retStr
, sizeof(buf
), "%u - PSK 2 phase change on bitclk if input high", id
);
2996 snprintf(retStr
, sizeof(buf
), "%u - PSK 3 phase change on rising edge of input", id
);
2999 snprintf(retStr
, sizeof(buf
), "%u - FSK 1a RF/5 RF/8", id
);
3002 snprintf(retStr
, sizeof(buf
), "%u - FSK 2a RF/10 RF/8", id
);
3005 snprintf(retStr
, sizeof(buf
), "%u - Biphase", id
);
3008 snprintf(retStr
, sizeof(buf
), "%u - NRZ / Direct", id
);
3014 char *GetModelStrFromCID(uint32_t cid
) {
3016 static char buf
[10];
3019 if (cid
== 1) snprintf(retStr
, sizeof(buf
), "ATA5577M1");
3020 if (cid
== 2) snprintf(retStr
, sizeof(buf
), "ATA5577M2");
3021 if (cid
== 3) snprintf(retStr
, sizeof(buf
), "ATA5577M3");
3025 char *GetConfigBlock0Source(uint8_t id
) {
3027 static char buf
[40];
3032 snprintf(retStr
, sizeof(buf
), _YELLOW_("(auto detect)"));
3035 snprintf(retStr
, sizeof(buf
), _YELLOW_("(user set)"));
3038 snprintf(retStr
, sizeof(buf
), _GREEN_("(tag read)"));
3041 snprintf(retStr
, sizeof(buf
), _RED_("(n/a)"));
3047 char *GetSelectedModulationStr(uint8_t id
) {
3049 static char buf
[20];
3054 snprintf(retStr
, sizeof(buf
), "FSK");
3057 snprintf(retStr
, sizeof(buf
), "FSK1");
3060 snprintf(retStr
, sizeof(buf
), "FSK1a");
3063 snprintf(retStr
, sizeof(buf
), "FSK2");
3066 snprintf(retStr
, sizeof(buf
), "FSK2a");
3069 snprintf(retStr
, sizeof(buf
), "ASK");
3072 snprintf(retStr
, sizeof(buf
), "DIRECT/NRZ");
3075 snprintf(retStr
, sizeof(buf
), "PSK1");
3078 snprintf(retStr
, sizeof(buf
), "PSK2");
3081 snprintf(retStr
, sizeof(buf
), "PSK3");
3084 snprintf(retStr
, sizeof(buf
), "BIPHASE");
3087 snprintf(retStr
, sizeof(buf
), "BIPHASEa - (CDP)");
3090 snprintf(retStr
, sizeof(buf
), _RED_("(Unknown)"));
3097 static void t55x7_create_config_block(int tagtype) {
3099 // T55X7_DEFAULT_CONFIG_BLOCK, T55X7_RAW_CONFIG_BLOCK
3100 // T55X7_EM_UNIQUE_CONFIG_BLOCK, T55X7_FDXB_CONFIG_BLOCK,
3101 // T55X7_FDXB_CONFIG_BLOCK, T55X7_HID_26_CONFIG_BLOCK, T55X7_INDALA_64_CONFIG_BLOCK, T55X7_INDALA_224_CONFIG_BLOCK
3102 // T55X7_GUARDPROXII_CONFIG_BLOCK, T55X7_VIKING_CONFIG_BLOCK, T55X7_NORALYS_CONFIG_BLOCK, T55X7_IOPROX_CONFIG_BLOCK
3103 static char buf[60];
3108 snprintf(retStr, sizeof(buf), "%08X - T55X7 Default", T55X7_DEFAULT_CONFIG_BLOCK);
3111 snprintf(retStr, sizeof(buf), "%08X - T55X7 Raw", T55X7_RAW_CONFIG_BLOCK);
3114 snprintf(retStr, sizeof(buf), "%08X - Q5/T5555 Default", T5555_DEFAULT_CONFIG_BLOCK);
3119 PrintAndLogEx(NORMAL, buf);
3123 static int CmdResetRead(const char *Cmd
) {
3125 CLIParserContext
*ctx
;
3126 CLIParserInit(&ctx
, "lf t55xx resetread",
3127 "Send Reset Cmd then `lf read` the stream to attempt\n"
3128 "to identify the start of it (needs a demod and/or plot after)",
3129 "lf t55xx resetread"
3132 // 1 (help) + 0(one user specified params) + (5 T55XX_DLMODE_SINGLE)
3133 void *argtable
[2 + 5] = {
3135 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
3138 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
3139 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3141 bool r0
= arg_get_lit(ctx
, 1);
3142 bool r1
= arg_get_lit(ctx
, 2);
3143 bool r2
= arg_get_lit(ctx
, 3);
3144 bool r3
= arg_get_lit(ctx
, 4);
3147 if ((r0
+ r1
+ r2
+ r3
) > 1) {
3148 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3152 uint8_t downlink_mode
= config
.downlink_mode
;
3154 downlink_mode
= refFixedBit
;
3156 downlink_mode
= refLongLeading
;
3158 downlink_mode
= refLeading0
;
3160 downlink_mode
= ref1of4
;
3162 uint8_t flags
= downlink_mode
<< 3;
3164 PrintAndLogEx(INFO
, "Sending reset command...");
3166 PacketResponseNG resp
;
3167 clearCommandBuffer();
3168 SendCommandNG(CMD_LF_T55XX_RESET_READ
, &flags
, sizeof(flags
));
3169 if (WaitForResponseTimeout(CMD_LF_T55XX_RESET_READ
, &resp
, 2500) == false) {
3170 PrintAndLogEx(WARNING
, "command execution time out");
3171 return PM3_ETIMEOUT
;
3174 if (resp
.status
== PM3_SUCCESS
) {
3176 uint16_t gotsize
= g_pm3_capabilities
.bigbuf_size
- 1;
3177 uint8_t *got
= calloc(gotsize
, sizeof(uint8_t));
3179 PrintAndLogEx(WARNING
, "failed to allocate memory");
3183 PrintAndLogEx(INFO
, "Downloading samples...");
3184 if (!GetFromDevice(BIG_BUF
, got
, gotsize
, 0, NULL
, 0, NULL
, 2500, false)) {
3185 PrintAndLogEx(WARNING
, "command execution time out");
3187 return PM3_ETIMEOUT
;
3189 setGraphBuffer(got
, gotsize
);
3193 PrintAndLogEx(INFO
, "Done!");
3197 static int CmdT55xxWipe(const char *Cmd
) {
3198 CLIParserContext
*ctx
;
3199 CLIParserInit(&ctx
, "lf t55xx wipe",
3200 "This commands wipes a tag, fills blocks 1-7 with zeros and a default configuration block",
3201 "lf t55xx wipe -> wipes a T55x7 tag, config block 0x000880E0\n"
3202 "lf t55xx wipe --q5 -> wipes a Q5/T5555 tag, config block 0x6001F004\n"
3203 "lf t55xx wipe -p 11223344 -> wipes a T55x7 tag, config block 0x000880E0, using pwd"
3206 // 1 (help) + 3 (three user specified params) + (5 T55XX_DLMODE_SINGLE)
3207 void *argtable
[4 + 5] = {
3209 arg_str0("c", "cfg", "<hex>", "configuration block0 (4 hex bytes)"),
3210 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
3211 arg_lit0(NULL
, "q5", "specify writing to Q5/T5555 tag using dedicated config block"),
3214 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
3215 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3217 bool usepwd
= false, gotconf
= false;
3218 uint32_t block0
= 0;
3219 int res
= arg_get_u32_hexstr_def(ctx
, 1, 0, &block0
);
3225 PrintAndLogEx(WARNING
, "config block needs to be 4 hex bytes");
3229 uint32_t password
= 0;
3230 res
= arg_get_u32_hexstr_def(ctx
, 2, 0x51243648, &password
);
3236 PrintAndLogEx(WARNING
, "Password should be 4 bytes, using default pwd");
3239 bool Q5
= arg_get_lit(ctx
, 3);
3242 PrintAndLogEx(INFO
, "Target " _YELLOW_("%s")" tag", (Q5
) ? "Q5/T5555" : "T55x7");
3244 // default config blocks.
3245 if (gotconf
== false) {
3246 block0
= (Q5
) ? 0x6001F004 : 0x000880E0;
3250 PrintAndLogEx(INFO
, "Using password " _GREEN_("%08X"), password
);
3254 snprintf(msg
, sizeof(msg
), "User provided configuration block " _GREEN_("%08X"), block0
);
3256 snprintf(msg
, sizeof(msg
), "Default configuration block " _GREEN_("%08X"), block0
);
3258 PrintAndLogEx(INFO
, "%s\n", msg
);
3260 PrintAndLogEx(INFO
, "Begin wiping...");
3262 // Creating cmd string for write block :)
3263 char wcmd
[36] = {0};
3266 snprintf(pwcmd
, sizeof(wcmd
), "-b 0 ");
3269 snprintf(pwcmd
+ strlen(wcmd
), sizeof(wcmd
) - strlen(wcmd
), "-p %08x ", password
);
3271 snprintf(pwcmd
+ strlen(wcmd
), sizeof(wcmd
) - strlen(wcmd
), "-d %08X", block0
);
3273 if (CmdT55xxWriteBlock(pwcmd
) != PM3_SUCCESS
)
3274 PrintAndLogEx(WARNING
, "Warning: error writing blk 0");
3276 for (uint8_t blk
= 1; blk
< 8; blk
++) {
3278 snprintf(pwcmd
, sizeof(wcmd
), "-b %d -d 00000000", blk
);
3280 if (CmdT55xxWriteBlock(pwcmd
) != PM3_SUCCESS
)
3281 PrintAndLogEx(WARNING
, "Warning: error writing blk %d", blk
);
3283 memset(wcmd
, 0x00, sizeof(wcmd
));
3286 // Check and rest t55xx downlink mode.
3287 if (config
.downlink_mode
!= T55XX_DLMODE_FIXED
) { // Detect found a different mode so card must support
3288 snprintf(pwcmd
, sizeof(wcmd
), "-b 3 --pg1 -d 00000000");
3289 if (CmdT55xxWriteBlock(pwcmd
) != PM3_SUCCESS
) {
3290 PrintAndLogEx(WARNING
, "Warning: failed writing block 3 page 1 (config)");
3292 memset(wcmd
, 0x00, sizeof(wcmd
));
3297 static bool IsCancelled(void) {
3298 if (kbd_enter_pressed()) {
3299 PrintAndLogEx(WARNING
, "\naborted via keyboard!\n");
3305 // load a default pwd file.
3306 static int CmdT55xxChkPwds(const char *Cmd
) {
3307 CLIParserContext
*ctx
;
3308 CLIParserInit(&ctx
, "lf t55xx chk",
3309 "This command uses a dictionary attack.\n"
3310 "For some cloners, try '--em' for known pwdgen algo.\n"
3311 "Try to reading Page 0 block 7 before.\n"
3312 _RED_("WARNING:") _CYAN_(" this may brick non-password protected chips!"),
3313 "lf t55xx chk -m -> use dictionary from flash memory (RDV4)\n"
3314 "lf t55xx chk -f my_dictionary_pwds -> loads a default keys dictionary file\n"
3315 "lf t55xx chk --em aa11223344 -> try known pwdgen algo from some cloners based on EM4100 ID"
3319 Calculate size of argtable accordingly:
3320 1 (help) + 3 (three user specified params) + ( 5 or 6 T55XX_DLMODE)
3321 start index to call arg_add_t55xx_downloadlink() is 4 (1 + 3) given the above sample
3324 // 1 (help) + 3 (three user specified params) + (6 T55XX_DLMODE_ALL)
3325 void *argtable
[4 + 6] = {
3327 arg_lit0("m", "fm", "use dictionary from flash memory (RDV4)"),
3328 arg_str0("f", "file", "<fn>", "file name"),
3329 arg_str0(NULL
, "em", "<hex>", "EM4100 ID (5 hex bytes)"),
3332 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_ALL
, T55XX_DLMODE_ALL
);
3333 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3335 bool from_flash
= arg_get_lit(ctx
, 1);
3338 char filename
[FILE_PATH_SIZE
] = {0};
3339 CLIParamStrToBuf(arg_get_str(ctx
, 2), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
3341 // White cloner password based on EM4100 ID
3342 bool use_calc_password
= false;
3343 uint32_t card_password
= 0x00;
3344 uint64_t cardid
= 0;
3345 int res
= arg_get_u64_hexstr_def_nlen(ctx
, 3, 0x00, &cardid
, 5, true);
3347 use_calc_password
= true;
3348 uint32_t calc
= cardid
& 0xFFFFFFFF;
3349 card_password
= lf_t55xx_white_pwdgen(calc
);
3353 PrintAndLogEx(WARNING
, "EM4100 ID must be 5 hex bytes");
3361 bool r0
= arg_get_lit(ctx
, 4);
3362 bool r1
= arg_get_lit(ctx
, 5);
3363 bool r2
= arg_get_lit(ctx
, 6);
3364 bool r3
= arg_get_lit(ctx
, 7);
3365 bool ra
= arg_get_lit(ctx
, 8);
3368 if ((r0
+ r1
+ r2
+ r3
+ ra
) > 1) {
3369 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3373 uint8_t downlink_mode
= refFixedBit
; // Password checks should always start with default/fixed bit unluess requested by user for specific mode
3374 // if (r0 || ra) // ra should start downlink mode ad fixed bit to loop through all modes correctly
3375 // downlink_mode = refFixedBit;
3378 downlink_mode
= refLongLeading
;
3380 downlink_mode
= refLeading0
;
3382 downlink_mode
= ref1of4
;
3384 bool use_pwd_file
= true; // Assume we are going to use a file, unless turned off later.
3386 if (strlen(filename
) == 0) {
3387 snprintf(filename
, sizeof(filename
), "t55xx_default_pwds");
3390 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
3391 PrintAndLogEx(NORMAL
, "");
3393 // block 7, page1 = false, usepwd = false, override = false, pwd = 00000000
3394 if ( T55xxReadBlock(7, false, false, false, 0x00000000) == PM3_SUCCESS) {
3396 // now try to validate it..
3397 PrintAndLogEx(WARNING, "\n Block 7 was readable");
3404 uint64_t t1
= msclock();
3405 uint8_t flags
= downlink_mode
<< 3;
3408 use_pwd_file
= false; // turn of local password file since we are checking from flash.
3409 clearCommandBuffer();
3410 SendCommandNG(CMD_LF_T55XX_CHK_PWDS
, &flags
, sizeof(flags
));
3411 PacketResponseNG resp
;
3413 uint8_t timeout
= 0;
3414 while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS
, &resp
, 2000)) {
3416 PrintAndLogEx(NORMAL
, "." NOLF
);
3417 if (timeout
> 180) {
3418 PrintAndLogEx(WARNING
, "\nno response from Proxmark3. Aborting...");
3422 PrintAndLogEx(NORMAL
, "");
3427 struct p
*packet
= (struct p
*)resp
.data
.asBytes
;
3429 if (packet
->found
) {
3430 PrintAndLogEx(SUCCESS
, "\nfound a candidate [ " _YELLOW_("%08"PRIX32
) " ]", packet
->candidate
);
3432 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, true, packet
->candidate
, downlink_mode
)) {
3433 found
= t55xxTryDetectModulationEx(downlink_mode
, T55XX_PrintConfig
, 0, packet
->candidate
);
3435 PrintAndLogEx(SUCCESS
, "found valid password [ " _GREEN_("%08"PRIX32
) " ]", packet
->candidate
);
3438 PrintAndLogEx(WARNING
, "check pwd failed");
3441 PrintAndLogEx(WARNING
, "check pwd failed");
3444 PrintAndLogEx(WARNING
, "check pwd failed");
3449 // to try each downlink mode for each password
3452 // try calculated password
3453 if (use_calc_password
) {
3455 PrintAndLogEx(INFO
, "testing %08"PRIX32
" generated ", card_password
);
3456 for (dl_mode
= downlink_mode
; dl_mode
<= 3; dl_mode
++) {
3458 if (!AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, true, card_password
, dl_mode
)) {
3462 found
= t55xxTryDetectModulationEx(dl_mode
, T55XX_PrintConfig
, 0, card_password
);
3464 PrintAndLogEx(SUCCESS
, "found valid password : [ " _GREEN_("%08"PRIX32
) " ]", card_password
);
3473 if ((found
== false) && use_pwd_file
) {
3474 uint32_t keycount
= 0;
3475 uint8_t *keyblock
= NULL
;
3477 res
= loadFileDICTIONARY_safe(filename
, (void **) &keyblock
, 4, &keycount
);
3478 if (res
!= PM3_SUCCESS
|| keycount
== 0 || keyblock
== NULL
) {
3479 PrintAndLogEx(WARNING
, "no keys found in file");
3480 if (keyblock
!= NULL
)
3486 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
3488 for (uint32_t c
= 0; c
< keycount
&& found
== false; ++c
) {
3490 if (!g_session
.pm3_present
) {
3491 PrintAndLogEx(WARNING
, "device offline\n");
3496 if (IsCancelled()) {
3498 return PM3_EOPABORTED
;
3501 uint32_t curr_password
= bytes_to_num(keyblock
+ 4 * c
, 4);
3503 PrintAndLogEx(INFO
, "testing %08"PRIX32
, curr_password
);
3504 for (dl_mode
= downlink_mode
; dl_mode
<= 3; dl_mode
++) {
3505 // If acquire fails, then we still need to check if we are only trying a single downlink mode.
3506 // If we continue on fail, it will skip that test and try the next downlink mode; thus slowing down the check
3507 // when on a single downlink mode is wanted.
3508 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, true, curr_password
, dl_mode
)) {
3509 found
= t55xxTryDetectModulationEx(dl_mode
, T55XX_PrintConfig
, 0, curr_password
);
3511 PrintAndLogEx(SUCCESS
, "found valid password: [ " _GREEN_("%08"PRIX32
) " ]", curr_password
);
3515 if (ra
== false) // Exit loop if not trying all downlink modes
3524 PrintAndLogEx(WARNING
, "failed to find password");
3527 t1
= msclock() - t1
;
3528 PrintAndLogEx(SUCCESS
, "\ntime in check pwd " _YELLOW_("%.0f") " seconds\n", (float)t1
/ 1000.0);
3532 // Bruteforce - incremental password range search
3533 static int CmdT55xxBruteForce(const char *Cmd
) {
3534 CLIParserContext
*ctx
;
3535 CLIParserInit(&ctx
, "lf t55xx bruteforce",
3536 "This command uses bruteforce to scan a number range.\n"
3537 "Try reading Page 0, block 7 before.\n\n"
3538 _RED_("WARNING") _CYAN_(" this may brick non-password protected chips!"),
3539 "lf t55xx bruteforce --r2 -s aaaaaa77 -e aaaaaa99\n"
3542 // 1 (help) + 2 (two user specified params) + (6 T55XX_DLMODE_ALL)
3543 void *argtable
[3 + 6] = {
3545 arg_str1("s", "start", "<hex>", "search start password (4 hex bytes)"),
3546 arg_str1("e", "end", "<hex>", "search end password (4 hex bytes)"),
3549 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_ALL
, T55XX_DLMODE_ALL
);
3550 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3552 uint32_t start_password
= 0;
3553 int res
= arg_get_u32_hexstr_def(ctx
, 1, 0, &start_password
);
3556 PrintAndLogEx(FAILED
, "start password should be 4 bytes");
3560 uint32_t end_password
= 0xFFFFFFFF;
3561 res
= arg_get_u32_hexstr_def(ctx
, 2, 0xFFFFFFFF, &end_password
);
3564 PrintAndLogEx(FAILED
, "end password should be 4 bytes");
3568 bool r0
= arg_get_lit(ctx
, 3);
3569 bool r1
= arg_get_lit(ctx
, 4);
3570 bool r2
= arg_get_lit(ctx
, 5);
3571 bool r3
= arg_get_lit(ctx
, 6);
3572 bool ra
= arg_get_lit(ctx
, 7);
3575 if ((r0
+ r1
+ r2
+ r3
+ ra
) > 1) {
3576 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3580 uint8_t downlink_mode
= refFixedBit
; // if no downlink mode suppliled use fixed bit/default as the is the most common
3581 // Since we don't know the password the config.downlink mode is of little value.
3582 // if (r0 || ra) // if try all (ra) then start at fixed bit for correct try all
3583 // downlink_mode = refFixedBit;
3586 downlink_mode
= refLongLeading
;
3588 downlink_mode
= refLeading0
;
3590 downlink_mode
= ref1of4
;
3593 uint8_t found
= 0; // > 0 if found xx1 xx downlink needed, 1 found
3595 if (start_password
> end_password
) {
3596 PrintAndLogEx(FAILED
, "Error, start larger then end password");
3600 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
3601 PrintAndLogEx(INFO
, "Search password range [%08X -> %08X]", start_password
, end_password
);
3603 uint64_t t1
= msclock();
3604 curr
= start_password
;
3606 while (found
== 0) {
3608 PrintAndLogEx(NORMAL
, "." NOLF
);
3610 if (IsCancelled()) {
3611 return PM3_EOPABORTED
;
3614 found
= t55xx_try_one_password(curr
, downlink_mode
, ra
);
3616 if (curr
== end_password
)
3622 PrintAndLogEx(NORMAL
, "");
3625 if (curr
!= end_password
) {
3626 PrintAndLogEx(SUCCESS
, "Found valid password: [ " _GREEN_("%08X") " ]", curr
- 1);
3628 PrintAndLogEx(SUCCESS
, "Found valid password: [ " _GREEN_("%08X") " ]", curr
);
3629 T55xx_Print_DownlinkMode((found
>> 1) & 3);
3631 PrintAndLogEx(WARNING
, "Bruteforce failed, last tried: [ " _YELLOW_("%08X") " ]", curr
);
3633 t1
= msclock() - t1
;
3634 PrintAndLogEx(SUCCESS
, "\ntime in bruteforce " _YELLOW_("%.0f") " seconds\n", (float)t1
/ 1000.0);
3638 uint8_t t55xx_try_one_password(uint32_t password
, uint8_t downlink_mode
, bool try_all_dl_modes
) {
3640 PrintAndLogEx(INFO
, "Trying password %08X", password
);
3643 downlink_mode
= (downlink_mode
& 3);
3645 // check if dl mode 4 and loop if needed
3646 for (uint8_t dl_mode
= downlink_mode
; dl_mode
< 4; dl_mode
++) {
3648 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, true, password
, dl_mode
)) {
3649 // if (getSignalProperties()->isnoise == false) {
3651 if (t55xxTryDetectModulationEx(dl_mode
, T55XX_PrintConfig
, 0, password
)) {
3652 return 1 + (dl_mode
<< 1);
3656 if (try_all_dl_modes
== false) {
3663 static int CmdT55xxRecoverPW(const char *Cmd
) {
3664 CLIParserContext
*ctx
;
3665 CLIParserInit(&ctx
, "lf t55xx recoverpw",
3666 "This command uses a few tricks to try to recover mangled password.\n"
3667 "Try reading Page 0, block 7 before.\n\n"
3668 _RED_("WARNING") _CYAN_(" this may brick non-password protected chips!"),
3669 "lf t55xx recoverpw\n"
3670 "lf t55xx recoverpw -p 11223344\n"
3671 "lf t55xx recoverpw -p 11223344 --r3\n"
3674 // 1 (help) + 1 (one user specified params) + (6 T55XX_DLMODE_ALL)
3675 void *argtable
[2 + 6] = {
3677 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
3680 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_ALL
, T55XX_DLMODE_ALL
);
3681 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3683 uint32_t orig_password
= 0;
3684 int res
= arg_get_u32_hexstr_def(ctx
, 1, 0x51243648, &orig_password
);
3686 PrintAndLogEx(INFO
, "Password should be 4 bytes, using default pwd instead");
3689 bool r0
= arg_get_lit(ctx
, 2);
3690 bool r1
= arg_get_lit(ctx
, 3);
3691 bool r2
= arg_get_lit(ctx
, 4);
3692 bool r3
= arg_get_lit(ctx
, 5);
3693 bool ra
= arg_get_lit(ctx
, 6);
3696 if ((r0
+ r1
+ r2
+ r3
+ ra
) > 1) {
3697 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3701 uint8_t downlink_mode
= config
.downlink_mode
;
3703 downlink_mode
= refFixedBit
;
3705 downlink_mode
= refLongLeading
;
3707 downlink_mode
= refLeading0
;
3709 downlink_mode
= ref1of4
;
3711 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
3714 uint32_t curr_password
= 0x0;
3715 uint32_t prev_password
= 0xffffffff;
3716 uint32_t mask
= 0x0;
3719 // first try fliping each bit in the expected password
3721 curr_password
= orig_password
^ (1u << bit
);
3722 found
= t55xx_try_one_password(curr_password
, downlink_mode
, ra
);
3723 if (found
> 0) // xx1 for found xx = dl mode used
3729 return PM3_EOPABORTED
;
3732 // now try to use partial original password, since block 7 should have been completely
3733 // erased during the write sequence and it is possible that only partial password has been
3735 // not sure from which end the bit bits are written, so try from both ends
3736 // from low bit to high bit
3739 mask
+= (1u << bit
);
3740 curr_password
= orig_password
& mask
;
3741 // if updated mask didn't change the password, don't try it again
3742 if (prev_password
== curr_password
) {
3747 found
= t55xx_try_one_password(curr_password
, downlink_mode
, ra
);
3752 prev_password
= curr_password
;
3755 return PM3_EOPABORTED
;
3758 // from high bit to low
3762 mask
-= (1u << bit
);
3763 curr_password
= orig_password
& mask
;
3764 // if updated mask didn't change the password, don't try it again
3765 if (prev_password
== curr_password
) {
3769 found
= t55xx_try_one_password(curr_password
, downlink_mode
, ra
);
3774 prev_password
= curr_password
;
3777 return PM3_EOPABORTED
;
3781 PrintAndLogEx(NORMAL
, "");
3784 PrintAndLogEx(SUCCESS
, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password
);
3785 T55xx_Print_DownlinkMode((found
>> 1) & 3);
3787 PrintAndLogEx(FAILED
, "Recover password failed");
3792 // note length of data returned is different for different chips.
3793 // some return all page 1 (64 bits) and others return just that block (32 bits)
3794 // unfortunately the 64 bits makes this more likely to get a false positive...
3795 bool tryDetectP1(bool getData
) {
3796 uint8_t preamble_atmel
[] = {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1};
3797 uint8_t preamble_silicon
[] = {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1};
3798 size_t startIdx
= 0;
3799 uint8_t fc1
= 0, fc2
= 0, ans
= 0;
3800 int clk
= 0, firstClockEdge
= 0;
3804 if (!AcquireData(T55x7_PAGE1
, T55x7_TRACE_BLOCK1
, false, 0, 0))
3808 // try fsk clock detect. if successful it cannot be any other type of modulation... (in theory...)
3809 ans
= fskClocks(&fc1
, &fc2
, (uint8_t *)&clk
, &firstClockEdge
);
3810 if (ans
&& ((fc1
== 10 && fc2
== 8) || (fc1
== 8 && fc2
== 5))) {
3812 if (FSKrawDemod(0, 0, 0, 0, false) == PM3_SUCCESS
) {
3813 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3814 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3818 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3819 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3824 if (FSKrawDemod(0, 1, 0, 0, false) == PM3_SUCCESS
) {
3825 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3826 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3830 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3831 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3838 // try ask clock detect. it could be another type even if successful.
3839 clk
= GetAskClock("", false);
3841 if (ASKDemod_ext(0, 0, 1, 0, false, false, false, 1, &st
) == PM3_SUCCESS
) {
3843 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3844 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3848 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3849 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3855 if (ASKDemod_ext(0, 1, 1, 0, false, false, false, 1, &st
) == PM3_SUCCESS
) {
3856 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3857 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3861 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3862 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3867 if (ASKbiphaseDemod(0, 0, 0, 2, false) == PM3_SUCCESS
) {
3868 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3869 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3873 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3874 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3879 if (ASKbiphaseDemod(0, 0, 1, 2, false) == PM3_SUCCESS
) {
3880 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3881 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3885 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3886 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3892 // try NRZ clock detect. it could be another type even if successful.
3893 clk
= GetNrzClock("", false); //has the most false positives :(
3895 if (NRZrawDemod(0, 0, 1, false) == PM3_SUCCESS
) {
3896 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3897 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3901 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3902 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3907 if (NRZrawDemod(0, 1, 1, false) == PM3_SUCCESS
) {
3908 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3909 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3913 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3914 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3920 // Fewer card uses PSK
3921 // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...)
3922 clk
= GetPskClock("", false);
3925 // save_restoreGB(GRAPH_SAVE);
3926 // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
3927 //CmdLtrim("-i 160");
3928 if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) {
3929 //save_restoreGB(GRAPH_RESTORE);
3930 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3931 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3935 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3936 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3941 if (PSKDemod(0, 1, 6, false) == PM3_SUCCESS
) {
3942 //save_restoreGB(GRAPH_RESTORE);
3943 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3944 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3948 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3949 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3954 // PSK2 - needs a call to psk1TOpsk2.
3955 if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) {
3956 psk1TOpsk2(g_DemodBuffer
, g_DemodBufferLen
);
3958 //save_restoreGB(GRAPH_RESTORE);
3959 if (preambleSearchEx(g_DemodBuffer
, preamble_atmel
, sizeof(preamble_atmel
), &g_DemodBufferLen
, &startIdx
, false) &&
3960 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3964 if (preambleSearchEx(g_DemodBuffer
, preamble_silicon
, sizeof(preamble_silicon
), &g_DemodBufferLen
, &startIdx
, false) &&
3965 (g_DemodBufferLen
== 32 || g_DemodBufferLen
== 64)) {
3968 } // inverse waves does not affect PSK2 demod
3970 //save_restoreGB(GRAPH_RESTORE);
3971 // no other modulation clocks = 2 or 4 so quit searching
3978 // does this need to be a callable command?
3979 static int CmdT55xxDetectPage1(const char *Cmd
) {
3980 CLIParserContext
*ctx
;
3981 CLIParserInit(&ctx
, "lf t55xx p1detect",
3982 "Detect Page 1 of a T55xx chip",
3983 "lf t55xx p1detect\n"
3984 "lf t55xx p1detect -1\n"
3985 "lf t55xx p1detect -p 11223344 --r3\n"
3988 // 1 (help) + 2 (two user specified params) + (5 T55XX_DLMODE_SINGLE)
3989 void *argtable
[3 + 5] = {
3991 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
3992 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
3995 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
3996 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3998 bool use_graphbuf
= arg_get_lit(ctx
, 1);
4000 bool usepwd
= false;
4001 uint32_t password
= 0;
4002 int res
= arg_get_u32_hexstr_def(ctx
, 2, 0, &password
);
4004 PrintAndLogEx(INFO
, "Password should be 4 hex bytes");
4007 } else if (res
== 1) {
4011 bool r0
= arg_get_lit(ctx
, 3);
4012 bool r1
= arg_get_lit(ctx
, 4);
4013 bool r2
= arg_get_lit(ctx
, 5);
4014 bool r3
= arg_get_lit(ctx
, 6);
4017 if ((r0
+ r1
+ r2
+ r3
) > 1) {
4018 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
4022 uint8_t downlink_mode
= config
.downlink_mode
;
4024 downlink_mode
= refFixedBit
;
4026 downlink_mode
= refLongLeading
;
4028 downlink_mode
= refLeading0
;
4030 downlink_mode
= ref1of4
;
4032 bool try_all_dl_modes
= true;
4035 if (downlink_mode
== 4)
4036 try_all_dl_modes
= true;
4037 if (downlink_mode
< 4)
4038 try_all_dl_modes
= false;
4040 if (downlink_mode
> 3)
4044 uint8_t found_mode
= 0;
4046 if (use_graphbuf
== false) {
4047 for (uint8_t dl_mode
= downlink_mode
; dl_mode
< 4; dl_mode
++) {
4049 if (AcquireData(T55x7_PAGE1
, T55x7_TRACE_BLOCK1
, usepwd
, password
, dl_mode
) == false)
4052 if (tryDetectP1(false)) {
4054 found_mode
= dl_mode
;
4060 if (try_all_dl_modes
== false) {
4065 found
= tryDetectP1(false);
4069 PrintAndLogEx(SUCCESS
, "T55xx chip found!");
4070 T55xx_Print_DownlinkMode(found_mode
);
4072 PrintAndLogEx(WARNING
, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'"));
4077 static int CmdT55xxSetDeviceConfig(const char *Cmd
) {
4078 CLIParserContext
*ctx
;
4079 CLIParserInit(&ctx
, "lf t55xx deviceconfig",
4080 "Sets t55x7 timings for direct commands.\n"
4081 "The timings are set here in Field Clocks (FC) which is converted to (US) on device.",
4082 "lf t55xx deviceconfig -a 29 -b 17 -c 15 -d 47 -e 15 -> default T55XX\n"
4083 "lf t55xx deviceconfig -a 55 -b 14 -c 21 -d 30 -> default EM4305"
4086 // 1 (help) + 9 (nine user specified params) + (5 T55XX_DLMODE_SINGLE)
4087 void *argtable
[10 + 5] = {
4089 arg_int0("a", NULL
, "<8..255>", "Set start gap"),
4090 arg_int0("b", NULL
, "<8..255>", "Set write gap"),
4091 arg_int0("c", NULL
, "<8..255>", "Set write ZERO gap"),
4092 arg_int0("d", NULL
, "<8..255>", "Set write ONE gap"),
4093 arg_int0("e", NULL
, "<8..255>", "Set read gap"),
4094 arg_int0("f", NULL
, "<8..255>", "Set write TWO gap (1 of 4 only)"),
4095 arg_int0("g", NULL
, "<8..255>", "Set write THREE gap (1 of 4 only)"),
4096 arg_lit0("p", "persist", "persist to flash memory (RDV4)"),
4097 arg_lit0("z", NULL
, "Set default t55x7 timings (use `-p` to save if required)"),
4100 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
4101 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
4103 uint8_t startgap
= arg_get_int(ctx
, 1);
4104 uint8_t writegap
= arg_get_int(ctx
, 2);
4105 uint8_t write0
= arg_get_int(ctx
, 3);
4106 uint8_t write1
= arg_get_int(ctx
, 4);
4107 uint8_t readgap
= arg_get_int(ctx
, 5);
4108 uint8_t write2
= arg_get_int(ctx
, 6);
4109 uint8_t write3
= arg_get_int(ctx
, 7);
4110 bool shall_persist
= arg_get_lit(ctx
, 8);
4111 bool set_defaults
= arg_get_lit(ctx
, 9);
4112 bool r0
= arg_get_lit(ctx
, 10);
4113 bool r1
= arg_get_lit(ctx
, 11);
4114 bool r2
= arg_get_lit(ctx
, 12);
4115 bool r3
= arg_get_lit(ctx
, 13);
4118 if ((r0
+ r1
+ r2
+ r3
) > 1) {
4119 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
4123 uint8_t downlink_mode
= 0;
4125 downlink_mode
= refFixedBit
;
4127 downlink_mode
= refLongLeading
;
4129 downlink_mode
= refLeading0
;
4131 downlink_mode
= ref1of4
;
4133 t55xx_configurations_t configurations
= {{{0}, {0}, {0}, {0}}};
4137 configurations
.m
[T55XX_DLMODE_FIXED
].start_gap
= 29 * 8;
4138 configurations
.m
[T55XX_DLMODE_FIXED
].write_gap
= 17 * 8;
4139 configurations
.m
[T55XX_DLMODE_FIXED
].write_0
= 15 * 8;
4140 configurations
.m
[T55XX_DLMODE_FIXED
].write_1
= 47 * 8;
4141 configurations
.m
[T55XX_DLMODE_FIXED
].read_gap
= 15 * 8;
4142 configurations
.m
[T55XX_DLMODE_FIXED
].write_2
= 0;
4143 configurations
.m
[T55XX_DLMODE_FIXED
].write_3
= 0;
4145 // long leading reference
4146 configurations
.m
[T55XX_DLMODE_LLR
].start_gap
= 29 * 8;
4147 configurations
.m
[T55XX_DLMODE_LLR
].write_gap
= 17 * 8;
4148 configurations
.m
[T55XX_DLMODE_LLR
].write_0
= 15 * 8;
4149 configurations
.m
[T55XX_DLMODE_LLR
].write_1
= 47 * 8;
4150 configurations
.m
[T55XX_DLMODE_LLR
].read_gap
= 15 * 8;
4151 configurations
.m
[T55XX_DLMODE_LLR
].write_2
= 0;
4152 configurations
.m
[T55XX_DLMODE_LLR
].write_3
= 0;
4155 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].start_gap
= 29 * 8;
4156 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_gap
= 17 * 8;
4157 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_0
= 15 * 8;
4158 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_1
= 40 * 8;
4159 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].read_gap
= 15 * 8;
4160 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_2
= 0;
4161 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_3
= 0;
4163 // 1 of 4 coding reference
4164 configurations
.m
[T55XX_DLMODE_1OF4
].start_gap
= 29 * 8;
4165 configurations
.m
[T55XX_DLMODE_1OF4
].write_gap
= 17 * 8;
4166 configurations
.m
[T55XX_DLMODE_1OF4
].write_0
= 15 * 8;
4167 configurations
.m
[T55XX_DLMODE_1OF4
].write_1
= 31 * 8;
4168 configurations
.m
[T55XX_DLMODE_1OF4
].read_gap
= 15 * 8;
4169 configurations
.m
[T55XX_DLMODE_1OF4
].write_2
= 47 * 8;
4170 configurations
.m
[T55XX_DLMODE_1OF4
].write_3
= 63 * 8;
4173 configurations
.m
[downlink_mode
].start_gap
= startgap
* 8;
4174 configurations
.m
[downlink_mode
].write_gap
= writegap
* 8;
4175 configurations
.m
[downlink_mode
].write_0
= write0
* 8;
4176 configurations
.m
[downlink_mode
].write_1
= write1
* 8;
4177 configurations
.m
[downlink_mode
].read_gap
= readgap
* 8;
4178 configurations
.m
[downlink_mode
].write_2
= write2
* 8;
4179 configurations
.m
[downlink_mode
].write_3
= write3
* 8;
4182 clearCommandBuffer();
4183 SendCommandMIX(CMD_LF_T55XX_SET_CONFIG
, shall_persist
, 0, 0, &configurations
, sizeof(t55xx_configurations_t
));
4187 static int CmdT55xxProtect(const char *Cmd
) {
4189 CLIParserContext
*ctx
;
4190 CLIParserInit(&ctx
, "lf t55xx protect",
4191 "This command sets the pwd bit on T5577.\n"
4192 _RED_("WARNING") _CYAN_(" this locks the tag!"),
4193 "lf t55xx protect -n 01020304 -> sets new pwd 01020304\n"
4194 "lf t55xx protect -p 11223344 -n 00000000 -> use pwd 11223344, sets new pwd 00000000"
4197 // 1 (help) + 3 (three user specified params) + (5 T55XX_DLMODE_SINGLE)
4198 void *argtable
[4 + 5] = {
4200 arg_lit0("o", "override", "override safety check"),
4201 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
4202 arg_str1("n", "new", "<hex>", "new password (4 hex bytes)"),
4205 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
4206 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
4208 uint8_t override
= 0;
4209 if (arg_get_lit(ctx
, 1))
4212 uint32_t password
= 0;
4213 bool usepwd
= false;
4214 int res
= arg_get_u32_hexstr_def(ctx
, 2, 0, &password
);
4217 PrintAndLogEx(FAILED
, "Error parsing password bytes");
4219 } else if (res
== 1) {
4224 uint32_t new_password
= 0;
4225 res
= arg_get_u32_hexstr_def(ctx
, 3, 0, &new_password
);
4228 PrintAndLogEx(FAILED
, "Error parsing new password bytes");
4230 } else if (res
== 0) {
4231 PrintAndLogEx(FAILED
, "Must specify new password param");
4236 bool r0
= arg_get_lit(ctx
, 4);
4237 bool r1
= arg_get_lit(ctx
, 5);
4238 bool r2
= arg_get_lit(ctx
, 6);
4239 bool r3
= arg_get_lit(ctx
, 7);
4242 if ((r0
+ r1
+ r2
+ r3
) > 1) {
4243 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
4247 uint8_t downlink_mode
= config
.downlink_mode
;
4249 downlink_mode
= refFixedBit
;
4251 downlink_mode
= refLongLeading
;
4253 downlink_mode
= refLeading0
;
4255 downlink_mode
= ref1of4
;
4258 if (SanityOfflineCheck(false) != PM3_SUCCESS
)
4262 if (t55xxProtect(true, usepwd
, override
, password
, downlink_mode
, new_password
) == false) {
4263 PrintAndLogEx(WARNING
, "Command failed. Did you run " _YELLOW_("`lf t55xx detect`") " before?");
4269 // if the difference between a and b is less then or eq to d i.e. does a = b +/- d
4270 #define APPROX_EQ(a, b, d) ((abs(a - b) <= d) ? true : false)
4272 static uint8_t t55sniff_get_packet(const int *pulseBuffer
, char *data
, uint8_t width0
, uint8_t width1
, uint8_t tolerance
) {
4277 while (ok
&& (i
< 73)) { // 70 bits max Fixed bit packet
4278 if (APPROX_EQ(width0
, pulseBuffer
[i
], tolerance
)) {
4283 if (APPROX_EQ(width1
, pulseBuffer
[i
], tolerance
)) {
4295 static uint8_t t55sniff_trim_samples(int *pulseBuffer
, int *pulseIdx
, uint8_t len
) {
4296 for (uint8_t i
= 0; i
< (80 - len
); i
++) {
4297 pulseBuffer
[i
] = pulseBuffer
[i
+ len
];
4304 static int CmdT55xxSniff(const char *Cmd
) {
4305 CLIParserContext
*ctx
;
4306 CLIParserInit(&ctx
, "lf t55xx sniff",
4307 "Sniff LF t55xx based trafic and decode possible cmd / blocks.\n"
4308 "Lower tolerance means tighter pulses. ",
4310 "lf t55xx sniff -1 -t 2 -> use buffer with tolerance of 2\n"
4311 "lf t55xx sniff -1 --zero 7 --one 14 -> use buffer, zero pulse width 7, one pulse width 15"
4314 void *argtable
[] = {
4316 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
4317 arg_int0("t", "tol", "<dec>", "set tolerance level (default 5)"),
4318 // arg_int0(NULL, "signal", "<dec>", "set minimum signal level (default 20)"),
4319 arg_int0("o", "one", "<dec>", "set samples width for ONE pulse (default auto)"),
4320 arg_int0("z", "zero", "<dec>", "set samples width for ZERO pulse (default auto)"),
4323 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
4324 bool use_graphbuf
= arg_get_lit(ctx
, 1);
4325 uint8_t tolerance
= arg_get_int_def(ctx
, 2, 5);
4326 int opt_width1
= arg_get_int_def(ctx
, 3, -1);
4327 int opt_width0
= arg_get_int_def(ctx
, 4, -1);
4330 if (opt_width0
== 0) {
4331 PrintAndLogEx(ERR
, "Must call with --zero larger than 0");
4334 if (opt_width1
== 0) {
4335 PrintAndLogEx(ERR
, "Must call with --one larger than 0");
4339 if (opt_width0
> 0 && opt_width1
== -1) {
4340 PrintAndLogEx(ERR
, _RED_("Missing sample width for ONE"));
4344 if (opt_width1
> 0 && opt_width0
== -1) {
4345 PrintAndLogEx(ERR
, _RED_("Missing sample width for ZERO"));
4352 if (opt_width0
> -1)
4353 width0
= (uint8_t)opt_width0
& 0xFF;
4355 if (opt_width1
> -1)
4356 width1
= (uint8_t)opt_width1
& 0xFF;
4362 T55xx packet lengths (1 of 4 needs to be checked)
4363 -----------------------------------------------
4364 | Default | LL 0 | Leading 0 | 1 of 4 |
4365 ----------------------------------------------------------------|
4366 | Standard Write | 38 | 39 | 39 | 40 |
4367 | Protect Write | 70 | 71 | 73 | 74 |
4368 | AOR | 34 | 35 | 37 | 38 |
4369 | Standard Read | 5 | 6 | 7 | 8 |
4370 | Protect Read | 38 | 39 | 41 | 42 |
4371 | Regular Read | 2 | 3 | 3 | 4 |
4372 | Reset | 2 | 3 | 3 | 4 |
4373 ----------------------------------------------------------------
4375 T55xx bit widths (decimation 1) - Expected, but may vary a little
4376 Reference 0 for LL0 and Leading 0 can be longer
4377 -----------------------------------------------
4378 | Default | LL 0 | Leading 0 | 1 of 4 |
4379 ----------------------------------------------------|
4380 | 0 | 16 - 32 | 9 - 33 | 5 - 80 | tbc |
4381 | 1 | 48 - 64 | 41 - 72 | 21 - 96 | tbc |
4382 ----------------------------------------------------
4386 uint8_t page
, blockAddr
;
4388 uint32_t usedPassword
, blockData
;
4389 int pulseSamples
= 0, pulseIdx
= 0;
4392 int pulseBuffer
[80] = { 0 }; // max should be 73 +/- - Holds Pulse widths
4393 char data
[80]; // linked to pulseBuffer. - Holds 0/1 from pulse widths
4395 // setup and sample data from Proxmark
4396 // if not directed to existing sample/graphbuffer
4397 if (use_graphbuf
== false) {
4399 // make loop to call sniff with skip samples..
4400 // then build it up by adding
4406 PrintAndLogEx(NORMAL
, "");
4407 PrintAndLogEx(INFO
, _CYAN_("T55xx command detection"));
4408 PrintAndLogEx(SUCCESS
, "Downlink mode | password | Data | blk | page | 0 | 1 | raw");
4409 PrintAndLogEx(SUCCESS
, "------------------------+------------+----------+-----+------+-----+-----+-------------------------------------------------------------------------------");
4412 // loop though sample buffer
4413 while (idx
< g_GraphTraceLen
) {
4415 int minWidth
= 1000;
4418 bool have_data
= false;
4419 const char *modeText
= "Default";
4420 strncpy(pwdText
, " ", sizeof(pwdText
));
4421 strncpy(dataText
, " ", sizeof(dataText
));
4423 if (pulseSamples
== 0) {
4428 while ((idx
< g_GraphTraceLen
) && (g_GraphBuffer
[idx
] < 0)) {
4432 // count high samples
4434 while ((idx
< g_GraphTraceLen
) && (g_GraphBuffer
[idx
] > 0)) { // last bit seems to be high to zero, but can vary in width..
4439 if (pulseSamples
> 0) {
4440 pulseBuffer
[pulseIdx
++] = pulseSamples
;
4441 if (pulseIdx
> 79) { // make room for next sample - if not used by now, it won't be.
4442 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 1);
4445 // Check Samples for valid packets;
4446 // We should find (outside of leading bits) we have a packet of "1" and "0" at same widths.
4447 if (pulseIdx
>= 6) {// min size for a read - ignoring 1of4 10 0 <adr>
4449 // We auto find widths
4450 if ((width0
== 0) && (width1
== 0)) {
4451 // We ignore bit 0 for the moment as it may be a ref. pulse, so check last
4453 minWidth
= pulseBuffer
[1];
4454 maxWidth
= pulseBuffer
[1];
4457 while ((!done
) && (ii
< pulseIdx
) && ((maxWidth
<= minWidth
) || (APPROX_EQ(minWidth
, maxWidth
, tolerance
)))) { // min should be 8, 16-32 more normal
4458 if (pulseBuffer
[ii
] + 3 < minWidth
) {
4459 minWidth
= pulseBuffer
[ii
];
4462 if (pulseBuffer
[ii
] - 1 > maxWidth
) {
4463 maxWidth
= pulseBuffer
[ii
];
4474 // out of bounds... min max far enough appart and minWidth is large enough
4475 if (((maxWidth
- minWidth
) < 6) || (minWidth
< 6)) // min 8 +/-
4478 // At this point we should have
4479 // - a min of 6 samples
4480 // - the 0 and 1 sample widths
4481 // - min 0 and min separations (worst case)
4482 // No max checks done (yet) as have seen samples > then specs in use.
4487 if (have_data
== false && (APPROX_EQ(pulseBuffer
[0], 136 + minWidth
, tolerance
) && APPROX_EQ(pulseBuffer
[1], maxWidth
, tolerance
))) {
4488 // printf ("Long Leading 0 - not yet handled | have 1 First bit | Min : %-3d - Max : %-3d : diff : %d\n",minWidth,maxWidth, maxWidth-minWidth);
4492 // Fixed bit - Default
4493 if (have_data
== false && (APPROX_EQ(pulseBuffer
[0], maxWidth
, tolerance
))) {
4494 uint16_t dataLen
= t55sniff_get_packet(pulseBuffer
, data
, minWidth
, maxWidth
, tolerance
);
4496 // if ((dataLen == 39) )
4497 // printf ("Fixed | Data end of 80 samples | offset : %llu - datalen %-2d - data : %s --- - Bit 0 width : %d\n",idx,dataLen,data,pulseBuffer[0]);
4499 if (data
[0] == '0') { // should never get here..
4505 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 4); // left 1 or 2 samples seemed to help
4507 page
= data
[1] - '0';
4509 for (uint8_t i
= 3; i
< 6; i
++) {
4511 if (data
[i
] == '1') {
4517 modeText
= "Default Read";
4521 if (dataLen
== 70) {
4522 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 70);
4524 page
= data
[1] - '0';
4526 for (uint8_t i
= 2; i
<= 33; i
++) {
4528 if (data
[i
] == '1') {
4535 for (uint8_t i
= 35; i
<= 66; i
++) {
4537 if (data
[i
] == '1') {
4543 for (uint8_t i
= 67; i
<= 69; i
++) {
4545 if (data
[i
] == '1') {
4550 modeText
= "Default pwd write";
4551 snprintf(pwdText
, sizeof(pwdText
), " %08X", usedPassword
);
4552 snprintf(dataText
, sizeof(dataText
), "%08X", blockData
);
4555 // Default Write or password read ???
4556 // the most confusing command.
4557 // if the token is with a password - all is OK,
4558 // if not - read command with a password will lead to write the shifted password to the memory and:
4559 // IF the most bit of the data is `1` ----> IT LEADS TO LOCK this block of the memory
4560 if (dataLen
== 38) {
4561 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 38);
4563 page
= data
[1] - '0';
4566 for (uint8_t i
= 3; i
<= 34; i
++) {
4568 if (data
[i
] == '1') {
4573 for (uint8_t i
= 2; i
<= 33; i
++) {
4575 if (data
[i
] == '1') {
4581 for (uint8_t i
= 35; i
<= 37; i
++) {
4583 if (data
[i
] == '1') {
4588 modeText
= "Default write/pwd read";
4589 snprintf(pwdText
, sizeof(pwdText
), "[%08X]", usedPassword
);
4590 snprintf(dataText
, sizeof(dataText
), "%08X", blockData
);
4596 if (have_data
== false && (APPROX_EQ(pulseBuffer
[0], minWidth
, tolerance
))) {
4597 // leading 0 (should = 0 width)
4598 // 1 of 4 (leads with 00)
4599 uint16_t dataLen
= t55sniff_get_packet(pulseBuffer
, data
, minWidth
, maxWidth
, tolerance
);
4600 // **** Should check to 0 to be actual 0 as well i.e. 01 .... data ....
4601 if ((data
[0] == '0') && (data
[1] == '1')) {
4602 if (dataLen
== 73) {
4603 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 73);
4605 page
= data
[2] - '0';
4607 for (uint8_t i
= 5; i
<= 36; i
++) {
4609 if (data
[i
] == '1') {
4615 for (uint8_t i
= 38; i
<= 69; i
++) {
4617 if (data
[i
] == '1') {
4623 for (uint8_t i
= 70; i
<= 72; i
++) {
4625 if (data
[i
] == '1') {
4631 modeText
= "Leading 0 pwd write";
4632 snprintf(pwdText
, sizeof(pwdText
), " %08X", usedPassword
);
4633 snprintf(dataText
, sizeof(dataText
), "%08X", blockData
);
4641 if (blockAddr
== 7) {
4642 PrintAndLogEx(SUCCESS
, "%-22s | "_GREEN_("%10s")" | "_YELLOW_("%8s")" | "_YELLOW_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s"
4653 PrintAndLogEx(SUCCESS
, "%-22s | "_GREEN_("%10s")" | "_GREEN_("%8s")" | "_GREEN_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s"
4668 PrintAndLogEx(SUCCESS
, "-----------------------------------------------------------------------------------------------------------------------------------------------------");
4669 PrintAndLogEx(NORMAL
, "");
4673 static command_t CommandTable
[] = {
4674 {"-----------", CmdHelp
, AlwaysAvailable
, "---------------------------- " _CYAN_("notice") " -----------------------------"},
4675 {"", CmdHelp
, AlwaysAvailable
, "Remember to run `" _YELLOW_("lf t55xx detect") "` first whenever a new card"},
4676 {"", CmdHelp
, AlwaysAvailable
, "is placed on the Proxmark3 or the config block changed."},
4677 {"", CmdHelp
, AlwaysAvailable
, ""},
4678 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
4679 {"-----------", CmdHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("operations") " ---------------------"},
4680 {"clonehelp", CmdT55xxCloneHelp
, IfPm3Lf
, "Shows the available clone commands"},
4681 {"config", CmdT55xxSetConfig
, AlwaysAvailable
, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
4682 {"dangerraw", CmdT55xxDangerousRaw
, IfPm3Lf
, "Sends raw bitstream. Dangerous, do not use!!"},
4683 {"detect", CmdT55xxDetect
, AlwaysAvailable
, "Try detecting the tag modulation from reading the configuration block"},
4684 {"deviceconfig", CmdT55xxSetDeviceConfig
, IfPm3Lf
, "Set/Get T55XX device configuration"},
4685 {"dump", CmdT55xxDump
, IfPm3Lf
, "Dump T55xx card Page 0 block 0-7"},
4686 {"info", CmdT55xxInfo
, AlwaysAvailable
, "Show T55x7 configuration data (page 0/ blk 0)"},
4687 {"p1detect", CmdT55xxDetectPage1
, IfPm3Lf
, "Try detecting if this is a t55xx tag by reading page 1"},
4688 {"read", CmdT55xxReadBlock
, IfPm3Lf
, "Read T55xx block data"},
4689 {"resetread", CmdResetRead
, IfPm3Lf
, "Send Reset Cmd then lf read the stream to attempt to identify the start of it"},
4690 {"restore", CmdT55xxRestore
, IfPm3Lf
, "Restore T55xx card Page 0 / Page 1 blocks"},
4691 {"trace", CmdT55xxReadTrace
, AlwaysAvailable
, "Show T55x7 traceability data (page 1/ blk 0-1)"},
4692 {"wakeup", CmdT55xxWakeUp
, IfPm3Lf
, "Send AOR wakeup command"},
4693 {"write", CmdT55xxWriteBlock
, IfPm3Lf
, "Write T55xx block data"},
4694 {"-----------", CmdHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("recovery") " ---------------------"},
4695 {"bruteforce", CmdT55xxBruteForce
, IfPm3Lf
, "Simple bruteforce attack to find password"},
4696 {"chk", CmdT55xxChkPwds
, IfPm3Lf
, "Check passwords"},
4697 {"protect", CmdT55xxProtect
, IfPm3Lf
, "Password protect tag"},
4698 {"recoverpw", CmdT55xxRecoverPW
, IfPm3Lf
, "Try to recover from bad password write from a cloner"},
4699 {"sniff", CmdT55xxSniff
, AlwaysAvailable
, "Attempt to recover T55xx commands from sample buffer"},
4700 {"special", CmdT55xxSpecial
, IfPm3Lf
, "Show block changes with 64 different offsets"},
4701 {"wipe", CmdT55xxWipe
, IfPm3Lf
, "Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
4702 {NULL
, NULL
, NULL
, NULL
}
4705 static int CmdHelp(const char *Cmd
) {
4706 (void)Cmd
; // Cmd is not used so far
4707 CmdsHelp(CommandTable
);
4711 int CmdLFT55XX(const char *Cmd
) {
4712 clearCommandBuffer();
4713 return CmdsParse(CommandTable
, Cmd
);
4721 lf t55 write -b 3 --pg1 -d 90000800
4724 lf t55 write -b 3 --pg1 -d 90000C00
4727 T55xx clone card lock: block 3 page 1 0x00000020 00000000 00000000 00000000 00100000
4729 (this bit in any combo seems to lock the card)
4731 You can have other data in the block write, but if that single bit is set "1" the entire card locks in its current state; no know way to unlock