1 //-----------------------------------------------------------------------------
3 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
4 // at your option, any later version. See the LICENSE.txt file for the text of
6 //-----------------------------------------------------------------------------
7 // Low frequency T55xx commands
8 //-----------------------------------------------------------------------------
10 // ensure localtime_r is available even with -std=c99; must be included before
12 #define _POSIX_C_SOURCE 200112L
15 #include "cmdlft55xx.h"
17 #include <time.h> // MingW
18 #include "cmdparser.h" // command_t
20 #include "commonutil.h"
21 #include "protocols.h"
26 #include "cmdhf14a.h" // for getTagInfo
27 #include "fileutils.h" // loadDictionary
28 #include "util_posix.h"
29 #include "cmdlf.h" // for lf sniff
30 #include "generator.h"
31 #include "cliparser.h" // cliparsing
33 // Some defines for readability
34 #define T55XX_DLMODE_FIXED 0 // Default Mode
35 #define T55XX_DLMODE_LLR 1 // Long Leading Reference
36 #define T55XX_DLMODE_LEADING_ZERO 2 // Leading Zero
37 #define T55XX_DLMODE_1OF4 3 // 1 of 4
38 // #define T55XX_LONGLEADINGREFERENCE 4 // Value to tell Write Bit to send long reference
39 #define T55XX_DLMODE_ALL 4 // Tell help to show 'r 4' for all dl modes
40 #define T55XX_DLMODE_SINGLE 5 // Tell help file NOT to show 'r 4' (not available)
42 #define T55XX_PrintConfig true
43 #define T55XX_DontPrintConfig false
45 //static uint8_t bit_rates[9] = {8, 16, 32, 40, 50, 64, 100, 128, 0};
47 // Default configuration
48 t55xx_conf_block_t config
= {
49 .modulation
= DEMOD_ASK
,
53 .block0Status
= NOTSET
,
56 .downlink_mode
= refFixedBit
59 static t55xx_memory_item_t cardmem
[T55x7_BLOCK_COUNT
] = {{0}};
61 t55xx_conf_block_t
Get_t55xx_Config(void) {
65 void Set_t55xx_Config(t55xx_conf_block_t conf
) {
69 static int CmdHelp(const char *Cmd
);
71 static void arg_add_t55xx_downloadlink(void *at
[], uint8_t *idx
, uint8_t show
, uint8_t dl_mode_def
) {
73 char *r0
= (char *)calloc(56, sizeof(uint8_t));
74 char *r1
= (char *)calloc(56, sizeof(uint8_t));
75 char *r2
= (char *)calloc(56, sizeof(uint8_t));
76 char *r3
= (char *)calloc(56, sizeof(uint8_t));
78 sprintf(r0
, "downlink - fixed bit length %s", (dl_mode_def
== 0) ? "(detected def)" : "");
79 sprintf(r1
, "downlink - long leading reference %s", (dl_mode_def
== 1) ? "(detected def)" : "");
80 sprintf(r2
, "downlink - leading zero %s", (dl_mode_def
== 2) ? "(detected def)" : "");
81 sprintf(r3
, "downlink - 1 of 4 coding reference %s", (dl_mode_def
== 3) ? "(detected def)" : "");
84 at
[n
++] = arg_lit0(NULL
, "r0", r0
);
85 at
[n
++] = arg_lit0(NULL
, "r1", r1
);
86 at
[n
++] = arg_lit0(NULL
, "r2", r2
);
87 at
[n
++] = arg_lit0(NULL
, "r3", r3
);
89 if (show
== T55XX_DLMODE_ALL
) {
90 char *r4
= (char *)calloc(56, sizeof(uint8_t));
91 sprintf(r4
, "try all downlink modes %s", (dl_mode_def
== 4) ? "(def)" : "");
92 at
[n
++] = arg_lit0(NULL
, "all", r4
);
94 at
[n
++] = arg_param_end
;
98 static int CmdT55xxCloneHelp(const char *Cmd
) {
99 CLIParserContext
*ctx
;
100 CLIParserInit(&ctx
, "lf t55xx clonehelp",
101 "Display a list of available commands for cloning specific techs on T5xx tags",
108 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
110 PrintAndLogEx(NORMAL
, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:");
111 PrintAndLogEx(NORMAL
, _GREEN_("lf awid clone"));
112 PrintAndLogEx(NORMAL
, _GREEN_("lf destron clone"));
113 PrintAndLogEx(NORMAL
, _GREEN_("lf em 410x clone"));
114 // todo: implement restore
115 // PrintAndLogEx(NORMAL, _GREEN_("lf em 4x05 write"));
116 // PrintAndLogEx(NORMAL, _GREEN_("lf em 4x50 write"));
117 PrintAndLogEx(NORMAL
, _GREEN_("lf fdxb clone"));
118 PrintAndLogEx(NORMAL
, _GREEN_("lf gallagher clone"));
119 PrintAndLogEx(NORMAL
, _GREEN_("lf gproxii clone"));
120 PrintAndLogEx(NORMAL
, _GREEN_("lf hid clone"));
121 PrintAndLogEx(NORMAL
, _GREEN_("lf indala clone"));
122 PrintAndLogEx(NORMAL
, _GREEN_("lf io clone"));
123 PrintAndLogEx(NORMAL
, _GREEN_("lf jablotron clone"));
124 PrintAndLogEx(NORMAL
, _GREEN_("lf keri clone"));
125 PrintAndLogEx(NORMAL
, _GREEN_("lf motorola clone"));
126 PrintAndLogEx(NORMAL
, _GREEN_("lf nedap clone"));
127 PrintAndLogEx(NORMAL
, _GREEN_("lf nexwatch clone"));
128 PrintAndLogEx(NORMAL
, _GREEN_("lf noralsy clone"));
129 PrintAndLogEx(NORMAL
, _GREEN_("lf pac clone"));
130 PrintAndLogEx(NORMAL
, _GREEN_("lf paradox clone"));
131 PrintAndLogEx(NORMAL
, _GREEN_("lf presco clone"));
132 PrintAndLogEx(NORMAL
, _GREEN_("lf pyramid clone"));
133 PrintAndLogEx(NORMAL
, _GREEN_("lf securakey clone"));
134 PrintAndLogEx(NORMAL
, _GREEN_("lf viking clone"));
135 PrintAndLogEx(NORMAL
, _GREEN_("lf visa2000 clone"));
139 static void T55x7_SaveBlockData(uint8_t idx
, uint32_t data
) {
140 if (idx
< T55x7_BLOCK_COUNT
) {
141 cardmem
[idx
].valid
= true;
142 cardmem
[idx
].blockdata
= data
;
145 static void T55x7_ClearAllBlockData(void) {
146 for (uint8_t idx
= 0; idx
< T55x7_BLOCK_COUNT
; idx
++) {
147 cardmem
[idx
].valid
= false;
148 cardmem
[idx
].blockdata
= 0x00;
152 int clone_t55xx_tag(uint32_t *blockdata
, uint8_t numblocks
) {
154 if (blockdata
== NULL
)
156 if (numblocks
< 1 || numblocks
> 8)
159 PacketResponseNG resp
;
162 conn
.block_after_ACK
= true;
164 for (int8_t i
= 0; i
< numblocks
; i
++) {
166 // Disable fast mode on last packet
167 if (i
== numblocks
- 1) {
168 conn
.block_after_ACK
= false;
171 clearCommandBuffer();
173 t55xx_write_block_t ng
;
174 ng
.data
= blockdata
[i
];
179 SendCommandNG(CMD_LF_T55XX_WRITEBL
, (uint8_t *)&ng
, sizeof(ng
));
180 if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL
, &resp
, T55XX_WRITE_TIMEOUT
)) {
181 PrintAndLogEx(ERR
, "Error occurred, device did not respond during write operation.");
187 for (int8_t i
= 0; i
< numblocks
; i
++) {
190 SetConfigWithBlock0(blockdata
[0]);
191 if (t55xxAquireAndCompareBlock0(false, 0, blockdata
[0], false))
195 if (t55xxVerifyWrite(i
, 0, false, false, 0, 0xFF, blockdata
[i
]) == false)
200 PrintAndLogEx(SUCCESS
, "Data written and verified");
205 static bool t55xxProtect(bool lock
, bool usepwd
, uint8_t override
, uint32_t password
, uint8_t downlink_mode
, uint32_t new_password
) {
207 PrintAndLogEx(INFO
, "Checking current configuration");
209 bool testmode
= false;
212 int res
= T55xxReadBlockEx(T55x7_CONFIGURATION_BLOCK
, T55x7_PAGE0
, usepwd
, override
, password
, downlink_mode
, false);
213 if (res
!= PM3_SUCCESS
) {
214 PrintAndLogEx(WARNING
, "Failed to read block0, use " _YELLOW_("`p`") " password parameter?");
218 if (GetT55xxBlockData(&block0
) == false) {
219 PrintAndLogEx(DEBUG
, "ERROR decoded block0 == %08x", block0
);
222 PrintAndLogEx(DEBUG
, "OK read block0 == %08x", block0
);
225 bool isPwdBitAlreadySet
= (block0
>> (32 - 28) & 1);
226 if (isPwdBitAlreadySet
) {
227 PrintAndLogEx(INFO
, "PWD bit is already set");
231 // set / clear pwd bit
238 // write new password
239 if (t55xxWrite(T55x7_PWD_BLOCK
, T55x7_PAGE0
, usepwd
, testmode
, password
, downlink_mode
, new_password
) != PM3_SUCCESS
) {
240 PrintAndLogEx(ERR
, "Failed to write new password");
243 PrintAndLogEx(SUCCESS
, "Wrote new password");
246 // validate new password
247 uint32_t curr_password
= (isPwdBitAlreadySet
) ? new_password
: password
;
249 if (t55xxVerifyWrite(T55x7_PWD_BLOCK
, T55x7_PAGE0
, usepwd
, override
, curr_password
, downlink_mode
, new_password
) == false) {
250 PrintAndLogEx(WARNING
, "Failed to validate the password write. aborting.");
253 PrintAndLogEx(SUCCESS
, "Validated new password");
257 if (t55xxWrite(T55x7_CONFIGURATION_BLOCK
, T55x7_PAGE0
, usepwd
, testmode
, curr_password
, downlink_mode
, block0
) != PM3_SUCCESS
) {
258 PrintAndLogEx(ERR
, "Failed to write modified configuration block %08X", block0
);
261 PrintAndLogEx(SUCCESS
, "Wrote modified configuration block");
264 // validate new config. If all went well, card should now demand pwd, hence override = 0.
266 if (t55xxVerifyWrite(T55x7_CONFIGURATION_BLOCK
, T55x7_PAGE0
, true, override
, new_password
, downlink_mode
, block0
) == false) {
267 PrintAndLogEx(WARNING
, "Failed to validate pwd bit set on configuration block. aborting.");
270 PrintAndLogEx(SUCCESS
, "New configuration block " _YELLOW_("%08X")" password " _YELLOW_("%08X"), block0
, new_password
);
271 PrintAndLogEx(SUCCESS
, "Success, tag is locked");
276 bool t55xxAquireAndCompareBlock0(bool usepwd
, uint32_t password
, uint32_t known_block0
, bool verbose
) {
279 PrintAndLogEx(INFO
, "Block0 write detected, running `detect` to see if validation is possible");
281 for (uint8_t m
= 0; m
< 4; m
++) {
282 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, usepwd
, password
, m
) == false) {
286 if (DecodeT55xxBlock() == false) {
290 for (uint16_t i
= 0; i
< DemodBufferLen
- 32; i
++) {
291 uint32_t tmp
= PackBits(i
, 32, DemodBuffer
);
292 if (tmp
== known_block0
) {
294 config
.downlink_mode
= m
;
302 bool t55xxAquireAndDetect(bool usepwd
, uint32_t password
, uint32_t known_block0
, bool verbose
) {
305 PrintAndLogEx(INFO
, "Block0 write detected, running `detect` to see if validation is possible");
307 for (uint8_t m
= 0; m
< 4; m
++) {
308 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, usepwd
, password
, m
) == false)
311 if (t55xxTryDetectModulationEx(m
, verbose
, known_block0
, (usepwd
) ? password
: -1) == false)
314 config
.downlink_mode
= m
;
317 config
.usepwd
= false; // unknown so assume no password
322 bool t55xxVerifyWrite(uint8_t block
, bool page1
, bool usepwd
, uint8_t override
, uint32_t password
, uint8_t downlink_mode
, uint32_t data
) {
324 uint32_t read_data
= 0;
326 if (downlink_mode
== 0xFF)
327 downlink_mode
= config
.downlink_mode
;
329 int res
= T55xxReadBlockEx(block
, page1
, usepwd
, override
, password
, downlink_mode
, false);
330 if (res
== PM3_SUCCESS
) {
332 if (GetT55xxBlockData(&read_data
) == false)
335 } else if (res
== PM3_EWRONGANSWER
) {
337 // could't decode. Lets see if this was a block 0 write and try read/detect it auto.
338 // this messes up with ppls config..
339 if (block
== 0 && page1
== false) {
341 if (t55xxAquireAndDetect(usepwd
, password
, data
, true) == false)
344 return t55xxVerifyWrite(block
, page1
, usepwd
, 2, password
, config
.downlink_mode
, data
);
348 return (read_data
== data
);
351 int t55xxWrite(uint8_t block
, bool page1
, bool usepwd
, bool testMode
, uint32_t password
, uint8_t downlink_mode
, uint32_t data
) {
354 flags
= (usepwd
) ? 0x1 : 0;
355 flags
|= (page1
) ? 0x2 : 0;
356 flags
|= (testMode
) ? 0x4 : 0;
357 flags
|= (downlink_mode
<< 3);
361 arg0 = data, (4 bytes)
362 arg1 = block (1 byte)
363 arg2 = password (4 bytes)
364 flags = data[0] (1 byte)
367 uses struct in pm3_cmd.h
369 t55xx_write_block_t ng
;
375 PacketResponseNG resp
;
376 clearCommandBuffer();
377 SendCommandNG(CMD_LF_T55XX_WRITEBL
, (uint8_t *)&ng
, sizeof(ng
));
378 if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL
, &resp
, 2000)) {
379 PrintAndLogEx(ERR
, "Error occurred, device did not ACK write operation.");
385 void printT5xxHeader(uint8_t page
) {
386 PrintAndLogEx(SUCCESS
, "Reading Page %d:", page
);
387 PrintAndLogEx(SUCCESS
, "blk | hex data | binary | ascii");
388 PrintAndLogEx(SUCCESS
, "----+----------+----------------------------------+-------");
391 void SetConfigWithBlock0(uint32_t block0
) {
392 SetConfigWithBlock0Ex(block0
, 0, false);
394 void SetConfigWithBlock0Ex(uint32_t block0
, uint8_t offset
, bool Q5
) {
396 uint32_t extend
= (block0
>> (32 - 15)) & 0x01;
399 dbr
= (block0
>> (32 - 14)) & 0x3F;
401 dbr
= (block0
>> (32 - 14)) & 0x07;
403 uint32_t datamod
= (block0
>> (32 - 20)) & 0x1F;
404 bool pwd
= (bool)((block0
>> (32 - 28)) & 0x01);
405 bool sst
= (bool)((block0
>> (32 - 29)) & 0x01);
406 bool inv
= (bool)((block0
>> (32 - 31)) & 0x01);
408 config
.modulation
= datamod
;
409 config
.bitrate
= dbr
;
412 if (datamod
== DEMOD_FSK1a
|| datamod
== DEMOD_FSK2a
|| datamod
== DEMOD_BIa
)
415 config
.inverted
= inv
;
420 config
.offset
= offset
;
421 config
.block0
= block0
;
424 static int CmdT55xxSetConfig(const char *Cmd
) {
426 if (strlen(Cmd
) == 0) {
427 PrintAndLogEx(INFO
, "--- " _CYAN_("current t55xx config") " --------------------------");
428 return printConfiguration(config
);
431 CLIParserContext
*ctx
;
432 CLIParserInit(&ctx
, "lf t55xx config",
433 "Set/Get T55XX configuration of the pm3 client. Like modulation, inverted, offset, rate etc.\n"
434 "Offset is start position to decode data.",
435 "lf t55xx config --FSK --> FSK demodulation\n"
436 "lf t55xx config --FSK -i --> FSK demodulation, inverse data\n"
437 "lf t55xx config --FSK -i -o 3 --> FSK demodulation, inverse data, offset 3\n"
440 // 1 (help) + 19 (user specified params) + (5 T55XX_DLMODE_SINGLE)
441 void *argtable
[1 + 12 + 6 + 5] = {
443 arg_lit0(NULL
, "FSK", "set demodulation FSK"),
444 arg_lit0(NULL
, "FSK1", "set demodulation FSK 1"),
445 arg_lit0(NULL
, "FSK1A", "set demodulation FSK 1a (inv)"),
446 arg_lit0(NULL
, "FSK2", "set demodulation FSK 2"),
447 arg_lit0(NULL
, "FSK2A", "set demodulation FSK 2a (inv)"),
448 arg_lit0(NULL
, "ASK", "set demodulation ASK"),
449 arg_lit0(NULL
, "PSK1", "set demodulation PSK 1"),
450 arg_lit0(NULL
, "PSK2", "set demodulation PSK 2"),
451 arg_lit0(NULL
, "PSK3", "set demodulation PSK 3"),
452 arg_lit0(NULL
, "NRZ", "set demodulation NRZ"),
453 arg_lit0(NULL
, "BI", "set demodulation Biphase"),
454 arg_lit0(NULL
, "BIA", "set demodulation Diphase (inverted biphase)"),
455 arg_lit0("i", "inv", "set/reset data signal inversion"),
456 arg_lit0(NULL
, "q5", "set/reset as Q5/T5555 chip instead of T55x7"),
457 arg_lit0(NULL
, "st", "set/reset Sequence Terminator on"),
458 arg_int0(NULL
, "rate", "<dec>", "set bitrate <8|16|32|40|50|64|100|128>"),
459 arg_str0("c", "blk0", "<hex>", "set configuration from a block0 (4 hex bytes)"),
460 arg_int0("o", "offset", "<0-255>", "set offset, where data should start decode in bitstream "),
464 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
465 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
470 while (idx
- 1 < sizeof(mods
)) {
471 mods
[idx
- 1] = arg_get_lit(ctx
, idx
);
472 verify_mods
+= mods
[idx
- 1];
476 // Not these flags are used to Toggle the values.
477 // If not flag then dont set or reset, leave as is since the call may just be be setting a different value.
478 bool invert
= arg_get_lit(ctx
, idx
++);
479 bool use_q5
= arg_get_lit(ctx
, idx
++);
480 bool use_st
= arg_get_lit(ctx
, idx
++);
482 int bitrate
= arg_get_int_def(ctx
, idx
, -1);
485 bool gotconf
= false;
487 int res
= arg_get_u32_hexstr_def_nlen(ctx
, idx
++, 0, &block0
, 4, true);
488 if (res
== 0 || res
== 2) {
489 PrintAndLogEx(ERR
, "block0 data must be 4 hex bytes");
497 int offset
= arg_get_int_def(ctx
, idx
, -1);
500 bool r0
= arg_get_lit(ctx
, idx
++);
501 bool r1
= arg_get_lit(ctx
, idx
++);
502 bool r2
= arg_get_lit(ctx
, idx
++);
503 bool r3
= arg_get_lit(ctx
, idx
++);
506 // validate user specified downlink mode
507 if ((r0
+ r1
+ r2
+ r3
) > 1) {
508 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
512 // validate user specified modulation FSK,FSK1,...BIA
513 if (verify_mods
> 1) {
514 PrintAndLogEx(FAILED
, "Error multiple demodulations, select one");
518 // validate user specified bitrate
521 uint8_t rates
[9] = {8, 16, 32, 40, 50, 64, 100, 128, 0};
523 for (; i
< ARRAYLEN(rates
); i
++) {
524 if (rates
[i
] == bitrate
) {
526 config
.block0
= ((config
.block0
& ~(0x1c0000)) | (i
<< 18));
531 PrintAndLogEx(FAILED
, "Error select a valid bitrate");
536 // validate user specified offset
537 if (offset
> -1 && offset
< 0x100) {
538 config
.offset
= offset
;
541 // validate user specific T5555 / Q5 - use the flag to toggle between T5577 and Q5
544 // validate user specific sequence terminator
545 // if use_st flag was supplied, then toggle and update the config block0; if not supplied skip the config block0 update.
548 config
.block0
= ((config
.block0
& ~(0x8)) | (config
.ST
<< 3));
551 // validate user specific invert
552 // In theory this should also be set in the config block 0; butit requries the extend mode config, which will change other things.
553 // as such, leave in user config for decoding the data until a full fix can be added.
554 // use the flag to toggle if invert is on or off.
555 config
.inverted
^= invert
;
557 // validate user specific downlink mode
558 uint8_t downlink_mode
= config
.downlink_mode
;
560 downlink_mode
= refFixedBit
;
562 downlink_mode
= refLongLeading
;
564 downlink_mode
= refLeading0
;
566 downlink_mode
= ref1of4
;
568 config
.downlink_mode
= downlink_mode
;
570 // validate user specific modulation
572 config
.modulation
= DEMOD_FSK
;
573 } else if (mods
[1]) {
574 config
.modulation
= DEMOD_FSK1
;
576 } else if (mods
[2]) {
577 config
.modulation
= DEMOD_FSK1a
;
579 } else if (mods
[3]) {
580 config
.modulation
= DEMOD_FSK2
;
582 } else if (mods
[4]) {
583 config
.modulation
= DEMOD_FSK2a
;
585 } else if (mods
[5]) {
586 config
.modulation
= DEMOD_ASK
;
587 } else if (mods
[6]) {
588 config
.modulation
= DEMOD_PSK1
;
589 } else if (mods
[7]) {
590 config
.modulation
= DEMOD_PSK2
;
591 } else if (mods
[8]) {
592 config
.modulation
= DEMOD_PSK3
;
593 } else if (mods
[9]) {
594 config
.modulation
= DEMOD_NRZ
;
595 } else if (mods
[10]) {
596 config
.modulation
= DEMOD_BI
;
598 } else if (mods
[11]) {
599 config
.modulation
= DEMOD_BIa
;
603 config
.block0
= ((config
.block0
& ~(0x1f000)) | (config
.modulation
<< 12));
605 config
.block0Status
= USERSET
;
607 SetConfigWithBlock0Ex(block0
, config
.offset
, config
.Q5
);
610 PrintAndLogEx(INFO
, "--- " _CYAN_("current t55xx config") " --------------------------");
611 return printConfiguration(config
);
613 int T55xxReadBlock(uint8_t block
, bool page1
, bool usepwd
, uint8_t override
, uint32_t password
, uint8_t downlink_mode
) {
614 return T55xxReadBlockEx(block
, page1
, usepwd
, override
, password
, downlink_mode
, true);
617 int T55xxReadBlockEx(uint8_t block
, bool page1
, bool usepwd
, uint8_t override
, uint32_t password
, uint8_t downlink_mode
, bool verbose
) {
620 // try reading the config block and verify that PWD bit is set before doing this!
621 // override = 1 (override and display)
622 // override = 2 (override and no display)
624 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, false, 0, downlink_mode
) == false)
627 if (t55xxTryDetectModulationEx(downlink_mode
, false, 0, password
) == false) {
628 PrintAndLogEx(WARNING
, "Safety check: Could not detect if PWD bit is set in config block. Exits.");
629 PrintAndLogEx(HINT
, "Consider using the override parameter to force read.");
630 return PM3_EWRONGANSWER
;
632 PrintAndLogEx(WARNING
, "Safety check: PWD bit is NOT set in config block. Reading without password...");
636 } else if (override
== 1) {
637 PrintAndLogEx(INFO
, "Safety check overridden - proceeding despite risk");
641 if (AcquireData(page1
, block
, usepwd
, password
, downlink_mode
) == false)
644 if (DecodeT55xxBlock() == false)
645 return PM3_EWRONGANSWER
;
648 printT55xxBlock(block
, page1
);
653 static int CmdT55xxReadBlock(const char *Cmd
) {
654 CLIParserContext
*ctx
;
655 CLIParserInit(&ctx
, "lf t55xx read",
656 "Read T55xx block data. This commands defaults to page 0.\n\n"
657 _RED_(" * * * WARNING * * *") "\n"
658 _CYAN_("Use of read with password on a tag not configured") "\n"
659 _CYAN_("for a password can damage the tag") "\n"
660 _RED_(" * * * * * * * * * *"),
661 "lf t55xx read -b 0 --> read data from block 0\n"
662 "lf t55xx read -b 0 --pwd 01020304 --> read data from block 0, pwd 01020304\n"
663 "lf t55xx read -b 0 --pwd 01020304 -o --> read data from block 0, pwd 01020304, override\n"
666 // 1 (help) + 4(four user specified params) + (5 T55XX_DLMODE_SINGLE)
667 void *argtable
[5 + 5] = {
669 arg_int1("b", "blk", "<0-7>", "block number to read"),
670 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
671 arg_lit0("o", "override", "override safety check"),
672 arg_lit0(NULL
, "pg1", "read page 1"),
675 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
676 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
678 int block
= arg_get_int_def(ctx
, 1, REGULAR_READ_MODE_BLOCK
);
681 uint32_t password
= 0;
682 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &password
, 4, true);
683 if (res
== 0 || res
== 2) {
684 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
692 uint8_t override
= arg_get_lit(ctx
, 3);
693 bool page1
= arg_get_lit(ctx
, 4);
695 bool r0
= arg_get_lit(ctx
, 5);
696 bool r1
= arg_get_lit(ctx
, 6);
697 bool r2
= arg_get_lit(ctx
, 7);
698 bool r3
= arg_get_lit(ctx
, 8);
701 if ((r0
+ r1
+ r2
+ r3
) > 1) {
702 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
706 uint8_t downlink_mode
= config
.downlink_mode
;
708 downlink_mode
= refFixedBit
;
710 downlink_mode
= refLongLeading
;
712 downlink_mode
= refLeading0
;
714 downlink_mode
= ref1of4
;
716 if (block
> 7 && block
!= REGULAR_READ_MODE_BLOCK
) {
717 PrintAndLogEx(NORMAL
, "Block must be between 0 and 7");
721 printT5xxHeader(page1
);
722 return T55xxReadBlock(block
, page1
, usepwd
, override
, password
, downlink_mode
);
725 bool DecodeT55xxBlock(void) {
729 uint8_t bitRate
[8] = {8, 16, 32, 40, 50, 64, 100, 128};
730 DemodBufferLen
= 0x00;
732 switch (config
.modulation
) {
734 ans
= FSKrawDemod(bitRate
[config
.bitrate
], config
.inverted
, 0, 0, false);
738 ans
= FSKrawDemod(bitRate
[config
.bitrate
], config
.inverted
, 8, 5, false);
742 ans
= FSKrawDemod(bitRate
[config
.bitrate
], config
.inverted
, 10, 8, false);
745 ans
= ASKDemod_ext(bitRate
[config
.bitrate
], config
.inverted
, 1, 0, false, false, false, 1, &ST
);
748 ans
= PSKDemod(bitRate
[config
.bitrate
], config
.inverted
, 6, false);
750 case DEMOD_PSK2
: //inverted won't affect this
751 case DEMOD_PSK3
: //not fully implemented
752 ans
= PSKDemod(bitRate
[config
.bitrate
], 0, 6, false);
753 psk1TOpsk2(DemodBuffer
, DemodBufferLen
);
756 ans
= NRZrawDemod(bitRate
[config
.bitrate
], config
.inverted
, 1, false);
760 ans
= ASKbiphaseDemod(0, bitRate
[config
.bitrate
], config
.inverted
, 1, false);
765 return (ans
== PM3_SUCCESS
);
768 static bool DecodeT5555TraceBlock(void) {
769 DemodBufferLen
= 0x00;
771 // According to datasheet. Always: RF/64, not inverted, Manchester
773 return (ASKDemod_ext(64, 0, 1, 0, false, false, false, 1, &st
) == PM3_SUCCESS
);
776 // sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf
777 static int SanityOfflineCheck(bool useGraphBuffer
) {
778 if (!useGraphBuffer
&& !session
.pm3_present
) {
779 PrintAndLogEx(WARNING
, "Your proxmark3 device is offline. Specify [1] to use graphbuffer data instead");
785 static void T55xx_Print_DownlinkMode(uint8_t downlink_mode
) {
787 snprintf(msg
, sizeof(msg
), "Downlink Mode used : ");
789 switch (downlink_mode
) {
791 strcat(msg
, _YELLOW_("long leading reference"));
794 strcat(msg
, _YELLOW_("leading zero reference"));
797 strcat(msg
, _YELLOW_("1 of 4 coding reference"));
800 strcat(msg
, _YELLOW_("default/fixed bit length"));
804 PrintAndLogEx(NORMAL
, msg
);
807 static int CmdT55xxWakeUp(const char *Cmd
) {
808 CLIParserContext
*ctx
;
809 CLIParserInit(&ctx
, "lf t55xx wakeup",
810 "This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards",
811 "lf t55xx wakeup -p 11223344 --> send wakeup with password\n"
814 // 1 (help) + 2 (two user specified params) + (5 T55XX_DLMODE_SINGLE)
815 void *argtable
[3 + 5] = {
817 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
818 arg_lit0("v", "verbose", "verbose output"),
821 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
822 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
824 uint32_t password
= 0;
825 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &password
, 4, true);
826 if (res
== 0 || res
== 2) {
827 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
832 bool verbose
= arg_get_lit(ctx
, 2);
833 bool r0
= arg_get_lit(ctx
, 3);
834 bool r1
= arg_get_lit(ctx
, 4);
835 bool r2
= arg_get_lit(ctx
, 5);
836 bool r3
= arg_get_lit(ctx
, 6);
839 if ((r0
+ r1
+ r2
+ r3
) > 1) {
840 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
844 uint8_t downlink_mode
= config
.downlink_mode
;
846 downlink_mode
= refFixedBit
;
848 downlink_mode
= refLongLeading
;
850 downlink_mode
= refLeading0
;
852 downlink_mode
= ref1of4
;
859 payload
.password
= password
;
860 payload
.flags
= (downlink_mode
<< 3);
862 clearCommandBuffer();
863 SendCommandNG(CMD_LF_T55XX_WAKEUP
, (uint8_t *)&payload
, sizeof(payload
));
864 if (WaitForResponseTimeout(CMD_LF_T55XX_WAKEUP
, NULL
, 1000) == false) {
865 PrintAndLogEx(WARNING
, "command execution time out");
870 PrintAndLogEx(SUCCESS
, "Wake up command sent. Try read now");
875 static int CmdT55xxDetect(const char *Cmd
) {
876 CLIParserContext
*ctx
;
877 CLIParserInit(&ctx
, "lf t55xx detect",
878 "Try detecting the tag modulation from reading the configuration block",
880 "lf t55xx detect -1\n"
881 "lf t55xx detect -p 11223344\n"
884 // 1 (help) + 2 (two user specified params) + (6 T55XX_DLMODE_ALL)
885 void *argtable
[3 + 6] = {
887 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
888 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
891 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_ALL
, config
.downlink_mode
);
892 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
894 bool use_gb
= arg_get_lit(ctx
, 1);
897 uint64_t password
= -1;
898 uint32_t tmp_pwd
= 0;
899 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &tmp_pwd
, 4, true);
900 if (res
== 0 || res
== 2) {
901 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
910 bool r0
= arg_get_lit(ctx
, 3);
911 bool r1
= arg_get_lit(ctx
, 4);
912 bool r2
= arg_get_lit(ctx
, 5);
913 bool r3
= arg_get_lit(ctx
, 6);
914 bool ra
= arg_get_lit(ctx
, 7);
917 if ((r0
+ r1
+ r2
+ r3
+ ra
) > 1) {
918 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
922 bool try_all_dl_modes
= false;
923 uint8_t downlink_mode
= config
.downlink_mode
;
925 downlink_mode
= refFixedBit
;
927 downlink_mode
= refLongLeading
;
929 downlink_mode
= refLeading0
;
931 downlink_mode
= ref1of4
;
932 else // This will set the default to user all d/l modes which will cover the ra flag as well.
933 try_all_dl_modes
= true;
937 // Setup the 90ms time value to sleep for after the wake, to allow delay init to complete (~70ms)
938 struct timespec sleepperiod
;
939 sleepperiod
.tv_sec
= 0;
940 sleepperiod
.tv_nsec
= 90000000;
942 // detect called so clear data blocks
943 T55x7_ClearAllBlockData();
946 if (SanityOfflineCheck(use_gb
) != PM3_SUCCESS
)
949 if (use_gb
== false) {
951 char wakecmd
[20] = { 0x00 };
952 sprintf(wakecmd
, "-p %08" PRIx64
, password
);
954 bool usewake
= false;
955 bool try_with_pwd
= false;
956 // do ... while not found and not yet tried with wake (for AOR or Init Delay)
958 // do ... while to check without password then loop back if password supplied
960 if (try_all_dl_modes
) {
961 // Loop from 1st d/l mode refFixedBit to the last d/l mode ref1of4
962 for (uint8_t m
= refFixedBit
; m
<= ref1of4
; m
++) {
966 CmdT55xxWakeUp(wakecmd
);
970 nanosleep(&sleepperiod
, &sleepperiod
);
973 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, (try_with_pwd
&& usepwd
), password
, m
) == false)
976 if (t55xxTryDetectModulationEx(m
, T55XX_PrintConfig
, 0, (try_with_pwd
&& usepwd
) ? password
: -1) == false)
986 CmdT55xxWakeUp(wakecmd
);
990 nanosleep(&sleepperiod
, &sleepperiod
);
993 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, usepwd
, password
, downlink_mode
)) {
994 found
= t55xxTryDetectModulationEx(downlink_mode
, T55XX_PrintConfig
, 0, (usepwd
) ? password
: -1);
998 // toggle so we loop back if not found and try with pwd
999 if (found
== false && usepwd
)
1000 try_with_pwd
= !try_with_pwd
;
1002 // force exit as detect block has been found
1004 try_with_pwd
= false;
1006 } while (try_with_pwd
);
1007 // Toggle so we loop back and try with wakeup.
1009 } while (found
== false && usewake
);
1011 found
= t55xxTryDetectModulation(downlink_mode
, T55XX_PrintConfig
);
1014 if (found
== false) {
1015 config
.usepwd
= false;
1017 PrintAndLogEx(WARNING
, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'"));
1022 // detect configuration?
1023 bool t55xxTryDetectModulation(uint8_t downlink_mode
, bool print_config
) {
1024 return t55xxTryDetectModulationEx(downlink_mode
, print_config
, 0, -1);
1027 bool t55xxTryDetectModulationEx(uint8_t downlink_mode
, bool print_config
, uint32_t wanted_conf
, uint64_t pwd
) {
1029 t55xx_conf_block_t tests
[15];
1030 int bitRate
= 0, clk
= 0, firstClockEdge
= 0;
1031 uint8_t hits
= 0, fc1
= 0, fc2
= 0, ans
= 0;
1033 ans
= fskClocks(&fc1
, &fc2
, (uint8_t *)&clk
, &firstClockEdge
);
1035 if (ans
&& ((fc1
== 10 && fc2
== 8) || (fc1
== 8 && fc2
== 5))) {
1036 if ((FSKrawDemod(0, 0, 0, 0, false) == PM3_SUCCESS
) && test(DEMOD_FSK
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1037 tests
[hits
].modulation
= DEMOD_FSK
;
1038 if (fc1
== 8 && fc2
== 5)
1039 tests
[hits
].modulation
= DEMOD_FSK1a
;
1040 else if (fc1
== 10 && fc2
== 8)
1041 tests
[hits
].modulation
= DEMOD_FSK2
;
1042 tests
[hits
].bitrate
= bitRate
;
1043 tests
[hits
].inverted
= false;
1044 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1045 tests
[hits
].ST
= false;
1046 tests
[hits
].downlink_mode
= downlink_mode
;
1049 if ((FSKrawDemod(0, 1, 0, 0, false) == PM3_SUCCESS
) && test(DEMOD_FSK
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1050 tests
[hits
].modulation
= DEMOD_FSK
;
1051 if (fc1
== 8 && fc2
== 5)
1052 tests
[hits
].modulation
= DEMOD_FSK1
;
1053 else if (fc1
== 10 && fc2
== 8)
1054 tests
[hits
].modulation
= DEMOD_FSK2a
;
1055 tests
[hits
].bitrate
= bitRate
;
1056 tests
[hits
].inverted
= true;
1057 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1058 tests
[hits
].ST
= false;
1059 tests
[hits
].downlink_mode
= downlink_mode
;
1063 clk
= GetAskClock("", false);
1065 tests
[hits
].ST
= true;
1066 // "0 0 1 " == clock auto, invert false, maxError 1.
1067 // false = no verbose
1068 // false = no emSearch
1071 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
)) {
1072 tests
[hits
].modulation
= DEMOD_ASK
;
1073 tests
[hits
].bitrate
= bitRate
;
1074 tests
[hits
].inverted
= false;
1075 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1076 tests
[hits
].downlink_mode
= downlink_mode
;
1079 tests
[hits
].ST
= true;
1080 // "0 0 1 " == clock auto, invert true, maxError 1.
1081 // false = no verbose
1082 // false = no emSearch
1085 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
)) {
1086 tests
[hits
].modulation
= DEMOD_ASK
;
1087 tests
[hits
].bitrate
= bitRate
;
1088 tests
[hits
].inverted
= true;
1089 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1090 tests
[hits
].downlink_mode
= downlink_mode
;
1093 if ((ASKbiphaseDemod(0, 0, 0, 2, false) == PM3_SUCCESS
) && test(DEMOD_BI
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1094 tests
[hits
].modulation
= DEMOD_BI
;
1095 tests
[hits
].bitrate
= bitRate
;
1096 tests
[hits
].inverted
= false;
1097 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1098 tests
[hits
].ST
= false;
1099 tests
[hits
].downlink_mode
= downlink_mode
;
1102 if ((ASKbiphaseDemod(0, 0, 1, 2, false) == PM3_SUCCESS
) && test(DEMOD_BIa
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1103 tests
[hits
].modulation
= DEMOD_BIa
;
1104 tests
[hits
].bitrate
= bitRate
;
1105 tests
[hits
].inverted
= true;
1106 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1107 tests
[hits
].ST
= false;
1108 tests
[hits
].downlink_mode
= downlink_mode
;
1112 clk
= GetNrzClock("", false);
1113 if (clk
> 8) { //clock of rf/8 is likely a false positive, so don't use it.
1114 if ((NRZrawDemod(0, 0, 1, false) == PM3_SUCCESS
) && test(DEMOD_NRZ
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1115 tests
[hits
].modulation
= DEMOD_NRZ
;
1116 tests
[hits
].bitrate
= bitRate
;
1117 tests
[hits
].inverted
= false;
1118 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1119 tests
[hits
].ST
= false;
1120 tests
[hits
].downlink_mode
= downlink_mode
;
1124 if ((NRZrawDemod(0, 1, 1, false) == PM3_SUCCESS
) && test(DEMOD_NRZ
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1125 tests
[hits
].modulation
= DEMOD_NRZ
;
1126 tests
[hits
].bitrate
= bitRate
;
1127 tests
[hits
].inverted
= true;
1128 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1129 tests
[hits
].ST
= false;
1130 tests
[hits
].downlink_mode
= downlink_mode
;
1135 clk
= GetPskClock("", false);
1138 save_restoreGB(GRAPH_SAVE
);
1139 // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
1141 if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) && test(DEMOD_PSK1
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1142 tests
[hits
].modulation
= DEMOD_PSK1
;
1143 tests
[hits
].bitrate
= bitRate
;
1144 tests
[hits
].inverted
= false;
1145 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1146 tests
[hits
].ST
= false;
1147 tests
[hits
].downlink_mode
= downlink_mode
;
1150 if ((PSKDemod(0, 1, 6, false) == PM3_SUCCESS
) && test(DEMOD_PSK1
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1151 tests
[hits
].modulation
= DEMOD_PSK1
;
1152 tests
[hits
].bitrate
= bitRate
;
1153 tests
[hits
].inverted
= true;
1154 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1155 tests
[hits
].ST
= false;
1156 tests
[hits
].downlink_mode
= downlink_mode
;
1159 //ICEMAN: are these PSKDemod calls needed?
1160 // PSK2 - needs a call to psk1TOpsk2.
1161 if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) {
1162 psk1TOpsk2(DemodBuffer
, DemodBufferLen
);
1163 if (test(DEMOD_PSK2
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1164 tests
[hits
].modulation
= DEMOD_PSK2
;
1165 tests
[hits
].bitrate
= bitRate
;
1166 tests
[hits
].inverted
= false;
1167 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1168 tests
[hits
].ST
= false;
1169 tests
[hits
].downlink_mode
= downlink_mode
;
1172 } // inverse waves does not affect this demod
1173 // PSK3 - needs a call to psk1TOpsk2.
1174 if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) {
1175 psk1TOpsk2(DemodBuffer
, DemodBufferLen
);
1176 if (test(DEMOD_PSK3
, &tests
[hits
].offset
, &bitRate
, clk
, &tests
[hits
].Q5
)) {
1177 tests
[hits
].modulation
= DEMOD_PSK3
;
1178 tests
[hits
].bitrate
= bitRate
;
1179 tests
[hits
].inverted
= false;
1180 tests
[hits
].block0
= PackBits(tests
[hits
].offset
, 32, DemodBuffer
);
1181 tests
[hits
].ST
= false;
1182 tests
[hits
].downlink_mode
= downlink_mode
;
1185 } // inverse waves does not affect this demod
1187 save_restoreGB(GRAPH_RESTORE
);
1191 config
.modulation
= tests
[0].modulation
;
1192 config
.bitrate
= tests
[0].bitrate
;
1193 config
.inverted
= tests
[0].inverted
;
1194 config
.offset
= tests
[0].offset
;
1195 config
.block0
= tests
[0].block0
;
1196 config
.Q5
= tests
[0].Q5
;
1197 config
.ST
= tests
[0].ST
;
1198 config
.downlink_mode
= downlink_mode
;
1200 config
.usepwd
= true;
1201 config
.pwd
= pwd
& 0xffffffff;
1204 config
.block0Status
= AUTODETECT
;
1206 printConfiguration(config
);
1211 bool retval
= false;
1213 PrintAndLogEx(SUCCESS
, "Found [%d] possible matches for modulation.", hits
);
1214 for (int i
= 0; i
< hits
; ++i
) {
1216 bool wanted
= false;
1217 if (wanted_conf
> 0)
1218 wanted
= (wanted_conf
== tests
[i
].block0
);
1220 retval
= testKnownConfigBlock(tests
[i
].block0
);
1221 if (retval
|| wanted
) {
1222 PrintAndLogEx(NORMAL
, "--[%d]--------------- << selected this", i
+ 1);
1223 config
.modulation
= tests
[i
].modulation
;
1224 config
.bitrate
= tests
[i
].bitrate
;
1225 config
.inverted
= tests
[i
].inverted
;
1226 config
.offset
= tests
[i
].offset
;
1227 config
.block0
= tests
[i
].block0
;
1228 config
.Q5
= tests
[i
].Q5
;
1229 config
.ST
= tests
[i
].ST
;
1230 config
.downlink_mode
= tests
[i
].downlink_mode
;
1233 config
.usepwd
= true;
1234 config
.pwd
= pwd
& 0xffffffff;
1237 PrintAndLogEx(NORMAL
, "--[%d]---------------", i
+ 1);
1240 config
.block0Status
= AUTODETECT
;
1242 printConfiguration(tests
[i
]);
1248 bool testKnownConfigBlock(uint32_t block0
) {
1250 case T55X7_DEFAULT_CONFIG_BLOCK
:
1251 case T55X7_RAW_CONFIG_BLOCK
:
1252 case T55X7_EM_UNIQUE_CONFIG_BLOCK
:
1253 case T55X7_FDXB_CONFIG_BLOCK
:
1254 case T55X7_FDXB_2_CONFIG_BLOCK
:
1255 case T55X7_HID_26_CONFIG_BLOCK
:
1256 case T55X7_PYRAMID_CONFIG_BLOCK
:
1257 case T55X7_INDALA_64_CONFIG_BLOCK
:
1258 case T55X7_INDALA_224_CONFIG_BLOCK
:
1259 case T55X7_GUARDPROXII_CONFIG_BLOCK
:
1260 case T55X7_VIKING_CONFIG_BLOCK
:
1261 case T55X7_NORALSY_CONFIG_BLOCK
:
1262 case T55X7_IOPROX_CONFIG_BLOCK
:
1263 case T55X7_PRESCO_CONFIG_BLOCK
:
1264 case T55X7_NEDAP_64_CONFIG_BLOCK
:
1265 case T55X7_NEDAP_128_CONFIG_BLOCK
:
1266 case T55X7_VISA2000_CONFIG_BLOCK
:
1267 case T55X7_SECURAKEY_CONFIG_BLOCK
:
1268 case T55X7_PAC_CONFIG_BLOCK
:
1269 case T55X7_VERICHIP_CONFIG_BLOCK
:
1270 case T55X7_KERI_CONFIG_BLOCK
:
1271 case T55X7_NEXWATCH_CONFIG_BLOCK
:
1272 case T55X7_JABLOTRON_CONFIG_BLOCK
:
1278 bool GetT55xxBlockData(uint32_t *blockdata
) {
1280 if (DemodBufferLen
== 0)
1283 uint8_t idx
= config
.offset
;
1285 if (idx
+ 32 > DemodBufferLen
) {
1286 PrintAndLogEx(WARNING
, "The configured offset %d is too big. Possible offset: %zu)", idx
, DemodBufferLen
- 32);
1290 *blockdata
= PackBits(0, 32, DemodBuffer
+ idx
);
1294 void printT55xxBlock(uint8_t blockNum
, bool page1
) {
1297 if (GetT55xxBlockData(&val
) == false)
1300 uint8_t bytes
[4] = {0};
1301 num_to_bytes(val
, 4, bytes
);
1303 T55x7_SaveBlockData((page1
) ? blockNum
+ 8 : blockNum
, val
);
1305 PrintAndLogEx(SUCCESS
, " %02d | %08X | %s | %s", blockNum
, val
, sprint_bin(DemodBuffer
+ config
.offset
, 32), sprint_ascii(bytes
, 4));
1308 static bool testModulation(uint8_t mode
, uint8_t modread
) {
1311 if (modread
>= DEMOD_FSK1
&& modread
<= DEMOD_FSK2a
) return true;
1314 if (modread
== DEMOD_ASK
) return true;
1317 if (modread
== DEMOD_PSK1
) return true;
1320 if (modread
== DEMOD_PSK2
) return true;
1323 if (modread
== DEMOD_PSK3
) return true;
1326 if (modread
== DEMOD_NRZ
) return true;
1329 if (modread
== DEMOD_BI
) return true;
1332 if (modread
== DEMOD_BIa
) return true;
1340 static bool testQ5Modulation(uint8_t mode
, uint8_t modread
) {
1343 if (modread
>= 4 && modread
<= 5) return true;
1346 if (modread
== 0) return true;
1349 if (modread
== 1) return true;
1352 if (modread
== 2) return true;
1355 if (modread
== 3) return true;
1358 if (modread
== 7) return true;
1361 if (modread
== 6) return true;
1369 static int convertQ5bitRate(uint8_t bitRateRead
) {
1370 uint8_t expected
[] = {8, 16, 32, 40, 50, 64, 100, 128};
1371 for (int i
= 0; i
< 8; i
++)
1372 if (expected
[i
] == bitRateRead
)
1378 static bool testQ5(uint8_t mode
, uint8_t *offset
, int *fndBitRate
, uint8_t clk
) {
1380 if (DemodBufferLen
< 64) return false;
1382 for (uint8_t idx
= 28; idx
< 64; idx
++) {
1384 if (PackBits(si
, 28, DemodBuffer
) == 0x00) continue;
1386 uint8_t safer
= PackBits(si
, 4, DemodBuffer
);
1387 si
+= 4; //master key
1388 uint8_t resv
= PackBits(si
, 8, DemodBuffer
);
1390 // 2nibble must be zeroed.
1391 if (safer
!= 0x6 && safer
!= 0x9) continue;
1392 if (resv
> 0x00) continue;
1393 //uint8_t pageSel = PackBits(si, 1, DemodBuffer); si += 1;
1394 //uint8_t fastWrite = PackBits(si, 1, DemodBuffer); si += 1;
1396 int bitRate
= PackBits(si
, 6, DemodBuffer
) * 2 + 2;
1398 if (bitRate
> 128 || bitRate
< 8) continue;
1400 //uint8_t AOR = PackBits(si, 1, DemodBuffer); si += 1;
1401 //uint8_t PWD = PackBits(si, 1, DemodBuffer); si += 1;
1402 //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2; //could check psk cr
1403 //uint8_t inverse = PackBits(si, 1, DemodBuffer); si += 1;
1404 si
+= 1 + 1 + 2 + 1;
1405 uint8_t modread
= PackBits(si
, 3, DemodBuffer
);
1407 uint8_t maxBlk
= PackBits(si
, 3, DemodBuffer
);
1409 //uint8_t ST = PackBits(si, 1, DemodBuffer); si += 1;
1410 if (maxBlk
== 0) continue;
1413 if (!testQ5Modulation(mode
, modread
)) continue;
1414 if (bitRate
!= clk
) continue;
1416 *fndBitRate
= convertQ5bitRate(bitRate
);
1417 if (*fndBitRate
< 0) continue;
1426 static bool testBitRate(uint8_t readRate
, uint8_t clk
) {
1427 uint8_t expected
[] = {8, 16, 32, 40, 50, 64, 100, 128};
1428 if (expected
[readRate
] == clk
)
1434 bool test(uint8_t mode
, uint8_t *offset
, int *fndBitRate
, uint8_t clk
, bool *Q5
) {
1436 if (DemodBufferLen
< 64) return false;
1437 for (uint8_t idx
= 28; idx
< 64; idx
++) {
1439 if (PackBits(si
, 28, DemodBuffer
) == 0x00) continue;
1441 uint8_t safer
= PackBits(si
, 4, DemodBuffer
);
1442 si
+= 4; //master key
1443 uint8_t resv
= PackBits(si
, 4, DemodBuffer
);
1444 si
+= 4; //was 7 & +=7+3 //should be only 4 bits if extended mode
1445 // 2nibble must be zeroed.
1446 // moved test to here, since this gets most faults first.
1447 if (resv
> 0x00) continue;
1449 int bitRate
= PackBits(si
, 6, DemodBuffer
);
1450 si
+= 6; //bit rate (includes extended mode part of rate)
1451 uint8_t extend
= PackBits(si
, 1, DemodBuffer
);
1452 si
+= 1; //bit 15 extended mode
1453 uint8_t modread
= PackBits(si
, 5, DemodBuffer
);
1455 //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr
1456 //uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode
1457 //uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2;
1460 bool extMode
= ((safer
== 0x6 || safer
== 0x9) && extend
) ? true : false;
1463 if (bitRate
> 7) continue;
1464 if (!testBitRate(bitRate
, clk
)) continue;
1465 } else { //extended mode bitrate = same function to calc bitrate as em4x05
1466 if (EM4x05_GET_BITRATE(bitRate
) != clk
) continue;
1470 if (!testModulation(mode
, modread
)) continue;
1471 *fndBitRate
= bitRate
;
1476 if (testQ5(mode
, offset
, fndBitRate
, clk
)) {
1483 int CmdT55xxSpecial(const char *Cmd
) {
1485 CLIParserContext
*ctx
;
1486 CLIParserInit(&ctx
, "lf t55xx special",
1487 "Show block changes with 64 different offsets, data taken from Demod buffer.",
1488 "lf t55xx special\n"
1491 void *argtable
[] = {
1495 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1498 uint8_t bits
[32] = {0x00};
1500 PrintAndLogEx(NORMAL
, "OFFSET | DATA | BINARY | ASCII");
1501 PrintAndLogEx(NORMAL
, "-------+-------+-------------------------------------+------");
1503 for (; j
< 64; ++j
) {
1505 for (i
= 0; i
< 32; ++i
)
1506 bits
[i
] = DemodBuffer
[j
+ i
];
1508 uint32_t blockData
= PackBits(0, 32, bits
);
1510 PrintAndLogEx(NORMAL
, "%02d | 0x%08X | %s", j
, blockData
, sprint_bin(bits
, 32));
1515 int printConfiguration(t55xx_conf_block_t b
) {
1516 PrintAndLogEx(INFO
, " Chip type......... " _GREEN_("%s"), (b
.Q5
) ? "Q5/T5555" : "T55x7");
1517 PrintAndLogEx(INFO
, " Modulation........ " _GREEN_("%s"), GetSelectedModulationStr(b
.modulation
));
1518 PrintAndLogEx(INFO
, " Bit rate.......... %s", GetBitRateStr(b
.bitrate
, (b
.block0
& T55x7_X_MODE
&& (b
.block0
>> 28 == 6 || b
.block0
>> 28 == 9))));
1519 PrintAndLogEx(INFO
, " Inverted.......... %s", (b
.inverted
) ? _GREEN_("Yes") : "No");
1520 PrintAndLogEx(INFO
, " Offset............ %d", b
.offset
);
1521 PrintAndLogEx(INFO
, " Seq. terminator... %s", (b
.ST
) ? _GREEN_("Yes") : "No");
1522 PrintAndLogEx(INFO
, " Block0............ %08X %s", b
.block0
, GetConfigBlock0Source(b
.block0Status
));
1523 PrintAndLogEx(INFO
, " Downlink mode..... %s", GetDownlinkModeStr(b
.downlink_mode
));
1524 PrintAndLogEx(INFO
, " Password set...... %s", (b
.usepwd
) ? _RED_("Yes") : _GREEN_("No"));
1526 PrintAndLogEx(INFO
, " Password.......... %08X", b
.pwd
);
1528 PrintAndLogEx(NORMAL
, "");
1532 static int CmdT55xxWriteBlock(const char *Cmd
) {
1533 CLIParserContext
*ctx
;
1534 CLIParserInit(&ctx
, "lf t55xx write",
1535 "Write T55xx block data",
1536 "lf t55xx write -b 3 -d 11223344 --> write 11223344 to block 3\n"
1537 "lf t55xx write -b 3 -d 11223344 --pwd 01020304 --> write 11223344 to block 3, pwd 01020304\n"
1538 "lf t55xx write -b 3 -d 11223344 --pwd 01020304 --verify --> write 11223344 to block 3 and try validating write"
1541 // 1 (help) + 6 (six user specified params) + (5 T55XX_DLMODE_SINGLE)
1542 void *argtable
[7 + 5] = {
1544 arg_int1("b", "blk", "<0-7>", "block number to write"),
1545 arg_str0("d", "data", "<hex>", "data to write (4 hex bytes)"),
1546 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
1547 arg_lit0("t", "tm", "test mode write ( " _RED_("danger") " )"),
1548 arg_lit0(NULL
, "pg1", "write page 1"),
1549 arg_lit0(NULL
, "verify", "try validate data afterward"),
1552 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
1553 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1555 int block
= arg_get_int_def(ctx
, 1, REGULAR_READ_MODE_BLOCK
);
1557 uint32_t data
= 0; // default to blank Block
1558 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &data
, 4, true);
1559 if (res
== 0 || res
== 2) {
1560 PrintAndLogEx(ERR
, "data must be 4 hex bytes");
1565 bool usepwd
= false;
1566 uint32_t password
= 0; // default to blank Block 7
1567 res
= arg_get_u32_hexstr_def_nlen(ctx
, 3, 0, &password
, 4, true);
1568 if (res
== 0 || res
== 2) {
1569 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
1577 bool testmode
= arg_get_lit(ctx
, 4);
1578 bool page1
= arg_get_lit(ctx
, 5);
1579 bool validate
= arg_get_lit(ctx
, 6);
1581 bool r0
= arg_get_lit(ctx
, 7);
1582 bool r1
= arg_get_lit(ctx
, 8);
1583 bool r2
= arg_get_lit(ctx
, 9);
1584 bool r3
= arg_get_lit(ctx
, 10);
1587 if ((r0
+ r1
+ r2
+ r3
) > 1) {
1588 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
1592 uint8_t downlink_mode
= config
.downlink_mode
;
1594 downlink_mode
= refFixedBit
;
1596 downlink_mode
= refLongLeading
;
1598 downlink_mode
= refLeading0
;
1600 downlink_mode
= ref1of4
;
1602 if (block
> 7 && block
!= REGULAR_READ_MODE_BLOCK
) {
1603 PrintAndLogEx(NORMAL
, "Block must be between 0 and 7");
1607 char pwdstr
[16] = {0};
1608 snprintf(pwdstr
, sizeof(pwdstr
), "pwd: 0x%08X", password
);
1610 PrintAndLogEx(INFO
, "Writing page %d block: %02d data: 0x%08X %s", page1
, block
, data
, (usepwd
) ? pwdstr
: "");
1612 if (t55xxWrite(block
, page1
, usepwd
, testmode
, password
, downlink_mode
, data
) != PM3_SUCCESS
) {
1613 PrintAndLogEx(ERR
, "Write failed");
1618 bool isOK
= t55xxVerifyWrite(block
, page1
, usepwd
, 1, password
, downlink_mode
, data
);
1620 PrintAndLogEx(SUCCESS
, "Write OK, validation successful");
1622 PrintAndLogEx(WARNING
, "Write could not validate the written data");
1628 static int CmdT55xxDangerousRaw(const char *Cmd
) {
1629 CLIParserContext
*ctx
;
1630 CLIParserInit(&ctx
, "lf t55xx dangerraw",
1631 "This command allows to emit arbitrary raw commands on T5577 and cut the field after arbitrary duration.\n"
1632 "Uncontrolled usage can easily write an invalid configuration, activate lock bits,\n"
1633 "OTP bit, password protection bit, deactivate test-mode, lock your card forever.\n"
1634 _RED_("WARNING:") _CYAN_(" this may lock definitively the tag in an unusable state!"),
1635 "lf t55xx dangerraw -d 01000000000000010000100000000100000000 -t 3200\n"
1638 void *argtable
[] = {
1640 arg_str1("d", "data", NULL
, "raw bit string"),
1641 arg_int1("t", "time", "<us>", "<0 - 200000> time in microseconds before dropping the field"),
1644 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1646 // supports only default downlink mode
1647 t55xx_test_block_t ng
;
1650 memset(ng
.data
, 0x00, sizeof(ng
.data
));
1653 uint8_t bin
[128] = {0};
1654 CLIGetStrWithReturn(ctx
, 1, bin
, &bin_len
);
1656 ng
.time
= arg_get_int_def(ctx
, 2, 0);
1659 if (ng
.time
== 0 || ng
.time
> 200000) {
1660 PrintAndLogEx(ERR
, "Timing off 1..200000 limits, got %i", ng
.time
);
1664 int bs_len
= binstring2binarray(ng
.data
, (char *)bin
, bin_len
);
1671 PacketResponseNG resp
;
1672 clearCommandBuffer();
1673 SendCommandNG(CMD_LF_T55XX_DANGERRAW
, (uint8_t *)&ng
, sizeof(ng
));
1674 if (!WaitForResponseTimeout(CMD_LF_T55XX_DANGERRAW
, &resp
, 2000)) {
1675 PrintAndLogEx(ERR
, "Error occurred, device did not ACK write operation.");
1676 return PM3_ETIMEOUT
;
1681 static int CmdT55xxReadTrace(const char *Cmd
) {
1683 CLIParserContext
*ctx
;
1684 CLIParserInit(&ctx
, "lf t55xx trace",
1685 "Show T55x7 configuration data (page 0/ blk 0) from reading the configuration block",
1690 // 1 (help) + 1 (one user specified params) + (5 T55XX_DLMODE_SINGLE)
1691 void *argtable
[2 + 5] = {
1693 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
1696 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
1697 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1699 bool use_gb
= arg_get_lit(ctx
, 1);
1701 bool r0
= arg_get_lit(ctx
, 2);
1702 bool r1
= arg_get_lit(ctx
, 3);
1703 bool r2
= arg_get_lit(ctx
, 4);
1704 bool r3
= arg_get_lit(ctx
, 5);
1707 if ((r0
+ r1
+ r2
+ r3
) > 1) {
1708 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
1712 uint8_t downlink_mode
= config
.downlink_mode
;
1714 downlink_mode
= refFixedBit
;
1716 downlink_mode
= refLongLeading
;
1718 downlink_mode
= refLeading0
;
1720 downlink_mode
= ref1of4
;
1722 if (use_gb
== false) {
1724 if (SanityOfflineCheck(false) != PM3_SUCCESS
) return PM3_ENODATA
;
1726 bool pwdmode
= false;
1727 uint32_t password
= 0;
1729 // REGULAR_READ_MODE_BLOCK - yeilds correct Page 1 Block 2 data i.e. + 32 bit offset.
1730 if (!AcquireData(T55x7_PAGE1
, REGULAR_READ_MODE_BLOCK
, pwdmode
, password
, downlink_mode
))
1735 if (DecodeT5555TraceBlock() == false) {
1739 if (DecodeT55xxBlock() == false) {
1744 if (DemodBufferLen
== 0) {
1748 RepaintGraphWindow();
1749 uint8_t repeat
= (config
.offset
> 5) ? 32 : 0;
1751 uint8_t si
= config
.offset
+ repeat
;
1752 uint32_t bl1
= PackBits(si
, 32, DemodBuffer
);
1753 uint32_t bl2
= PackBits(si
+ 32, 32, DemodBuffer
);
1756 uint32_t hdr
= PackBits(si
, 9, DemodBuffer
);
1760 PrintAndLogEx(FAILED
, "Invalid Q5/T5555 Trace data header (expected 0x1FF, found %X)", hdr
);
1764 t5555_tracedata_t data
= {.bl1
= bl1
, .bl2
= bl2
, .icr
= 0, .lotidc
= '?', .lotid
= 0, .wafer
= 0, .dw
= 0};
1766 data
.icr
= PackBits(si
, 2, DemodBuffer
);
1768 data
.lotidc
= 'Z' - PackBits(si
, 2, DemodBuffer
);
1771 data
.lotid
= PackBits(si
, 4, DemodBuffer
);
1774 data
.lotid
|= PackBits(si
, 4, DemodBuffer
);
1777 data
.lotid
|= PackBits(si
, 4, DemodBuffer
);
1780 data
.lotid
|= PackBits(si
, 4, DemodBuffer
);
1783 data
.lotid
|= PackBits(si
, 1, DemodBuffer
);
1786 data
.wafer
= PackBits(si
, 3, DemodBuffer
);
1789 data
.wafer
|= PackBits(si
, 2, DemodBuffer
);
1792 data
.dw
= PackBits(si
, 2, DemodBuffer
);
1795 data
.dw
|= PackBits(si
, 4, DemodBuffer
);
1798 data
.dw
|= PackBits(si
, 4, DemodBuffer
);
1801 data
.dw
|= PackBits(si
, 4, DemodBuffer
);
1803 printT5555Trace(data
, repeat
);
1807 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};
1809 data
.acl
= PackBits(si
, 8, DemodBuffer
);
1811 if (data
.acl
!= 0xE0) {
1812 PrintAndLogEx(FAILED
, "The modulation is most likely wrong since the ACL is not 0xE0. ");
1816 data
.mfc
= PackBits(si
, 8, DemodBuffer
);
1818 data
.cid
= PackBits(si
, 5, DemodBuffer
);
1820 data
.icr
= PackBits(si
, 3, DemodBuffer
);
1822 data
.year
= PackBits(si
, 4, DemodBuffer
);
1824 data
.quarter
= PackBits(si
, 2, DemodBuffer
);
1826 data
.lotid
= PackBits(si
, 14, DemodBuffer
);
1828 data
.wafer
= PackBits(si
, 5, DemodBuffer
);
1830 data
.dw
= PackBits(si
, 15, DemodBuffer
);
1832 struct tm
*ct
, tm_buf
;
1833 time_t now
= time(NULL
);
1835 ct
= localtime_s(&tm_buf
, &now
) == 0 ? &tm_buf
: NULL
;
1837 ct
= localtime_r(&now
, &tm_buf
);
1840 if (data
.year
> ct
->tm_year
- 110)
1845 printT55x7Trace(data
, repeat
);
1850 void printT55x7Trace(t55x7_tracedata_t data
, uint8_t repeat
) {
1851 PrintAndLogEx(INFO
, "--- " _CYAN_("T55x7 Trace Information") " ----------------------------------");
1852 PrintAndLogEx(INFO
, " ACL Allocation class (ISO/IEC 15963-1) : 0x%02X ( %d )", data
.acl
, data
.acl
);
1853 PrintAndLogEx(INFO
, " MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X ( %d ) - %s", data
.mfc
, data
.mfc
, getTagInfo(data
.mfc
));
1854 PrintAndLogEx(INFO
, " CID : 0x%02X ( %d ) - %s", data
.cid
, data
.cid
, GetModelStrFromCID(data
.cid
));
1855 PrintAndLogEx(INFO
, " ICR IC Revision : %d", data
.icr
);
1856 PrintAndLogEx(INFO
, " Manufactured");
1857 PrintAndLogEx(INFO
, " Year/Quarter... %d/%d", data
.year
, data
.quarter
);
1858 PrintAndLogEx(INFO
, " Lot ID......... %d", data
.lotid
);
1859 PrintAndLogEx(INFO
, " Wafer number... %d", data
.wafer
);
1860 PrintAndLogEx(INFO
, " Die Number..... %d", data
.dw
);
1861 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
1862 PrintAndLogEx(INFO
, " Raw Data - Page 1");
1863 PrintAndLogEx(INFO
, " Block 1... %08X - %s", data
.bl1
, sprint_bin(DemodBuffer
+ config
.offset
+ repeat
, 32));
1864 PrintAndLogEx(INFO
, " Block 2... %08X - %s", data
.bl2
, sprint_bin(DemodBuffer
+ config
.offset
+ repeat
+ 32, 32));
1865 PrintAndLogEx(NORMAL
, "");
1869 M1, M2 has the about ATMEL defintion of trace data.
1870 M3 has unique format following industry defacto standard with row/col parity
1874 1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0
1875 9-16 MFC Manufacturer ID (ISO/IEC 7816-6) 0x15 Atmel Corporation
1876 17-21 CID 0x1 = Atmel ATA5577M1
1877 0x2 = Atmel ATA5577M2
1878 0x3 = Atmel ATA5577M3
1879 22-24 ICR IC revision
1880 25-28 YEAR (BCD encoded) 9 (= 2009)
1881 29-30 QUARTER 1,2,3,4
1887 18-32 DW, die number sequential
1896 void printT5555Trace(t5555_tracedata_t data
, uint8_t repeat
) {
1897 PrintAndLogEx(INFO
, "--- " _CYAN_("Q5/T5555 Trace Information") " ---------------------------");
1898 PrintAndLogEx(INFO
, " ICR IC Revision.... %d", data
.icr
);
1899 PrintAndLogEx(INFO
, " Lot ID......... %c%d", data
.lotidc
, data
.lotid
);
1900 PrintAndLogEx(INFO
, " Wafer number... %d", data
.wafer
);
1901 PrintAndLogEx(INFO
, " Die Number..... %d", data
.dw
);
1902 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
1903 PrintAndLogEx(INFO
, " Raw Data - Page 1");
1904 PrintAndLogEx(INFO
, " Block 1... %08X - %s", data
.bl1
, sprint_bin(DemodBuffer
+ config
.offset
+ repeat
, 32));
1905 PrintAndLogEx(INFO
, " Block 2... %08X - %s", data
.bl2
, sprint_bin(DemodBuffer
+ config
.offset
+ repeat
+ 32, 32));
1909 TRACE - BLOCK O and BLOCK1
1914 15-35 Lot ID (NB parity)
1915 36-41 Wafer number (NB parity)
1916 42-58 DW, die number sequential (NB parity)
1922 static void printT5x7KnownBlock0(uint32_t b0
) {
1925 memset(s
, 0, sizeof(s
));
1928 case T55X7_DEFAULT_CONFIG_BLOCK
:
1929 snprintf(s
, sizeof(s
) - strlen(s
), "T55x7 Default ");
1931 case T55X7_RAW_CONFIG_BLOCK
:
1932 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "T55x7 Raw ");
1934 case T55X7_EM_UNIQUE_CONFIG_BLOCK
:
1935 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "EM unique, Paxton ");
1937 case T55X7_FDXB_2_CONFIG_BLOCK
:
1938 case T55X7_FDXB_CONFIG_BLOCK
:
1939 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "FDXB ");
1941 case T55X7_HID_26_CONFIG_BLOCK
:
1942 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "HID 26b (ProxCard), Paradox, AWID ");
1944 case T55X7_PYRAMID_CONFIG_BLOCK
:
1945 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Pyramid ");
1947 case T55X7_INDALA_64_CONFIG_BLOCK
:
1948 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Indala 64, Motorola, Idteck");
1950 case T55X7_INDALA_224_CONFIG_BLOCK
:
1951 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Indala 224 ");
1953 case T55X7_GUARDPROXII_CONFIG_BLOCK
:
1954 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Guard Prox II ");
1956 case T55X7_VIKING_CONFIG_BLOCK
:
1957 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Viking ");
1959 case T55X7_NORALSY_CONFIG_BLOCK
:
1960 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Noralys ");
1962 case T55X7_IOPROX_CONFIG_BLOCK
:
1963 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "IO Prox ");
1965 case T55X7_PRESCO_CONFIG_BLOCK
:
1966 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Presco ");
1968 case T55X7_NEDAP_64_CONFIG_BLOCK
:
1969 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Nedap 64 ");
1971 case T55X7_NEDAP_128_CONFIG_BLOCK
:
1972 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Nedap 128 ");
1974 case T55X7_PAC_CONFIG_BLOCK
:
1975 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "PAC/Stanley ");
1977 case T55X7_VERICHIP_CONFIG_BLOCK
:
1978 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Verichip ");
1980 case T55X7_VISA2000_CONFIG_BLOCK
:
1981 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "VISA2000 ");
1983 case T55X7_JABLOTRON_CONFIG_BLOCK
:
1984 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "Jablotron ");
1986 case T55X7_KERI_CONFIG_BLOCK
:
1987 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "KERI ");
1989 case T55X7_SECURAKEY_CONFIG_BLOCK
:
1990 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "SecuraKey ");
1992 case T55X7_NEXWATCH_CONFIG_BLOCK
:
1993 snprintf(s
+ strlen(s
), sizeof(s
) - strlen(s
), "NexWatch, Quadrakey ");
1999 if (strlen(s
) > 0) {
2000 PrintAndLogEx(SUCCESS
, "Config block match : " _YELLOW_("%s"), s
);
2004 static int CmdT55xxInfo(const char *Cmd
) {
2005 CLIParserContext
*ctx
;
2006 CLIParserInit(&ctx
, "lf t55xx info",
2007 "Show T55x7 configuration data (page 0/ blk 0) from reading the configuration block\n"
2008 "from tag. Use `-c` to specify a config block data to be used instead of reading tag.",
2010 "lf t55xx info -1\n"
2011 "lf t55xx info -p 11223344\n"
2012 "lf t55xx info -c 00083040\n"
2013 "lf t55xx info -c 6001805A --q5"
2016 // 1 (help) + 4 (four user specified params) + (5 T55XX_DLMODE_SINGLE)
2017 void *argtable
[5 + 5] = {
2019 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
2020 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
2021 arg_str0("c", "blk0", "<hex>", "use these data instead (4 hex bytes)"),
2022 arg_lit0(NULL
, "q5", "interprete provided data as T5555/Q5 config"),
2025 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
2026 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2028 bool use_gb
= arg_get_lit(ctx
, 1);
2030 bool usepwd
= false;
2031 uint32_t password
= 0;
2032 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &password
, 4, true);
2033 if (res
== 0 || res
== 2) {
2034 PrintAndLogEx(ERR
, "Password must be 4 hex bytes");
2042 bool gotdata
= false;
2043 uint32_t block0
= 0;
2044 res
= arg_get_u32_hexstr_def_nlen(ctx
, 3, 0, &block0
, 4, true);
2045 if (res
== 0 || res
== 2) {
2046 PrintAndLogEx(ERR
, "block0 data must be 4 hex bytes");
2054 bool dataasq5
= arg_get_lit(ctx
, 4);
2056 bool r0
= arg_get_lit(ctx
, 5);
2057 bool r1
= arg_get_lit(ctx
, 6);
2058 bool r2
= arg_get_lit(ctx
, 7);
2059 bool r3
= arg_get_lit(ctx
, 8);
2062 if (gotdata
&& use_gb
) {
2063 PrintAndLogEx(FAILED
, "Must select one of user supplied data and use graphbuffer");
2067 if (dataasq5
&& gotdata
== false) {
2068 PrintAndLogEx(FAILED
, "Must specify user supplied Q5 data");
2072 if ((r0
+ r1
+ r2
+ r3
) > 1) {
2073 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
2077 uint8_t downlink_mode
= config
.downlink_mode
;
2079 downlink_mode
= refFixedBit
;
2081 downlink_mode
= refLongLeading
;
2083 downlink_mode
= refLeading0
;
2085 downlink_mode
= ref1of4
;
2089 Page 0 Block 0 Configuration data.
2094 if (use_gb
== false && gotdata
== false) {
2096 if (SanityOfflineCheck(false) != PM3_SUCCESS
) {
2100 if (!AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, usepwd
, password
, downlink_mode
)) {
2105 if (gotdata
== false) {
2106 if (DecodeT55xxBlock() == false) {
2110 // too little space to start with
2111 if (DemodBufferLen
< 32 + config
.offset
) {
2115 //PrintAndLogEx(NORMAL, "Offset+32 ==%d\n DemodLen == %d", config.offset + 32, DemodBufferLen);
2116 block0
= PackBits(config
.offset
, 32, DemodBuffer
);
2119 PrintAndLogEx(NORMAL
, "");
2120 if (((!gotdata
) && config
.Q5
) || (gotdata
&& dataasq5
)) {
2121 uint32_t header
= (block0
>> (32 - 12)) & 0xFFF;
2122 uint32_t ps
= (block0
>> (32 - 13)) & 0x01;
2123 uint32_t fw
= (block0
>> (32 - 14)) & 0x01;
2124 uint32_t dbr
= (block0
>> (32 - 20)) & 0x3F;
2125 uint32_t aor
= (block0
>> (32 - 21)) & 0x01;
2126 uint32_t pwd
= (block0
>> (32 - 22)) & 0x01;
2127 uint32_t pskcf
= (block0
>> (32 - 24)) & 0x03;
2128 uint32_t inv
= (block0
>> (32 - 25)) & 0x01;
2129 uint32_t datamod
= (block0
>> (32 - 28)) & 0x07;
2130 uint32_t maxblk
= (block0
>> (32 - 31)) & 0x07;
2131 uint32_t st
= block0
& 0x01;
2132 PrintAndLogEx(INFO
, "--- " _CYAN_("Q5 Configuration & Information") " ------------");
2133 PrintAndLogEx(INFO
, " Header : 0x%03X%s", header
, (header
!= 0x600) ? _RED_(" - Warning") : "");
2134 PrintAndLogEx(INFO
, " Page select : %d", ps
);
2135 PrintAndLogEx(INFO
, " Fast Write : %s", (fw
) ? _GREEN_("Yes") : "No");
2136 PrintAndLogEx(INFO
, " Data bit rate : %s", GetBitRateStr(dbr
, 1));
2137 PrintAndLogEx(INFO
, " AOR - Answer on Request : %s", (aor
) ? _GREEN_("Yes") : "No");
2138 PrintAndLogEx(INFO
, " Password mode : %s", (pwd
) ? _GREEN_("Yes") : "No");
2139 PrintAndLogEx(INFO
, " PSK clock frequency : %s", GetPskCfStr(pskcf
, 1));
2140 PrintAndLogEx(INFO
, " Inverse data : %s", (inv
) ? _GREEN_("Yes") : "No");
2141 PrintAndLogEx(INFO
, " Modulation : %s", GetQ5ModulationStr(datamod
));
2142 PrintAndLogEx(INFO
, " Max block : %d", maxblk
);
2143 PrintAndLogEx(INFO
, " Sequence Terminator : %s", (st
) ? _GREEN_("Yes") : "No");
2145 uint32_t safer
= (block0
>> (32 - 4)) & 0x0F;
2146 uint32_t extend
= (block0
>> (32 - 15)) & 0x01;
2149 resv
= (block0
>> (32 - 8)) & 0x0F;
2150 dbr
= (block0
>> (32 - 14)) & 0x3F;
2152 resv
= (block0
>> (32 - 11)) & 0x7F;
2153 dbr
= (block0
>> (32 - 14)) & 0x07;
2155 uint32_t datamod
= (block0
>> (32 - 20)) & 0x1F;
2156 uint32_t pskcf
= (block0
>> (32 - 22)) & 0x03;
2157 uint32_t aor
= (block0
>> (32 - 23)) & 0x01;
2158 uint32_t otp
= (block0
>> (32 - 24)) & 0x01;
2159 uint32_t maxblk
= (block0
>> (32 - 27)) & 0x07;
2160 uint32_t pwd
= (block0
>> (32 - 28)) & 0x01;
2161 uint32_t sst
= (block0
>> (32 - 29)) & 0x01;
2162 uint32_t fw
= (block0
>> (32 - 30)) & 0x01;
2163 uint32_t inv
= (block0
>> (32 - 31)) & 0x01;
2164 uint32_t por
= (block0
>> (32 - 32)) & 0x01;
2166 PrintAndLogEx(INFO
, "--- " _CYAN_("T55x7 Configuration & Information") " ---------");
2167 PrintAndLogEx(INFO
, " Safer key : %s", GetSaferStr(safer
));
2168 PrintAndLogEx(INFO
, " reserved : %d", resv
);
2169 PrintAndLogEx(INFO
, " Data bit rate : %s", GetBitRateStr(dbr
, extend
));
2170 PrintAndLogEx(INFO
, " eXtended mode : %s", (extend
) ? _YELLOW_("Yes - Warning") : "No");
2171 PrintAndLogEx(INFO
, " Modulation : %s", GetModulationStr(datamod
, extend
));
2172 PrintAndLogEx(INFO
, " PSK clock frequency : %s", GetPskCfStr(pskcf
, 0));
2173 PrintAndLogEx(INFO
, " AOR - Answer on Request : %s", (aor
) ? _GREEN_("Yes") : "No");
2174 PrintAndLogEx(INFO
, " OTP - One Time Pad : %s", (otp
) ? ((extend
) ? _YELLOW_("Yes - Warning") : _RED_("Yes - Warning")) : "No");
2175 PrintAndLogEx(INFO
, " Max block : %d", maxblk
);
2176 PrintAndLogEx(INFO
, " Password mode : %s", (pwd
) ? _GREEN_("Yes") : "No");
2177 PrintAndLogEx(INFO
, " Sequence %-12s : %s", (extend
) ? "Start Marker" : "Terminator", (sst
) ? _GREEN_("Yes") : "No");
2178 PrintAndLogEx(INFO
, " Fast Write : %s", (fw
) ? ((extend
) ? _GREEN_("Yes") : _RED_("Yes - Warning")) : "No");
2179 PrintAndLogEx(INFO
, " Inverse data : %s", (inv
) ? ((extend
) ? _GREEN_("Yes") : _RED_("Yes - Warning")) : "No");
2180 PrintAndLogEx(INFO
, " POR-Delay : %s", (por
) ? _GREEN_("Yes") : "No");
2182 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
2183 PrintAndLogEx(INFO
, " Raw Data - Page 0, block 0");
2185 PrintAndLogEx(INFO
, " " _GREEN_("%08X"), block0
);
2187 PrintAndLogEx(INFO
, " " _GREEN_("%08X") " - %s", block0
, sprint_bin(DemodBuffer
+ config
.offset
, 32));
2189 if (((!gotdata
) && (!config
.Q5
)) || (gotdata
&& (!dataasq5
))) {
2190 PrintAndLogEx(INFO
, "--- " _CYAN_("Fingerprint") " ------------");
2191 printT5x7KnownBlock0(block0
);
2194 PrintAndLogEx(NORMAL
, "");
2195 //PrintAndLogEx(INFO, "-------------------------------------------------------------");
2199 static int CmdT55xxDump(const char *Cmd
) {
2201 CLIParserContext
*ctx
;
2202 CLIParserInit(&ctx
, "lf t55xx dump",
2203 "This command dumps a T55xx card Page 0 block 0-7.\n"
2204 "It will create three files (bin/eml/json)",
2206 "lf t55xx dump -p aabbccdd --override\n"
2207 "lf t55xx dump -f my_lf_dump"
2210 // 1 (help) + 3 (two user specified params) + (5 T55XX_DLMODE_SINGLE)
2211 void *argtable
[4 + 5] = {
2213 arg_str0("f", "filename", "<fn>", "filename (default is generated on blk 0)"),
2214 arg_lit0("o", "override", "override, force pwd read despite danger to card"),
2215 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
2218 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, T55XX_DLMODE_SINGLE
);
2219 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2222 char filename
[FILE_PATH_SIZE
] = {0};
2223 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, sizeof(filename
), &fnlen
);
2225 uint8_t override
= arg_get_lit(ctx
, 2) ? 1 : 0;
2227 bool usepwd
= false;
2228 uint32_t password
= 0;
2229 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 3, 0, &password
, 4, true);
2230 if (res
== 0 || res
== 2) {
2231 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
2239 bool r0
= arg_get_lit(ctx
, 4);
2240 bool r1
= arg_get_lit(ctx
, 5);
2241 bool r2
= arg_get_lit(ctx
, 6);
2242 bool r3
= arg_get_lit(ctx
, 7);
2245 if ((r0
+ r1
+ r2
+ r3
) > 1) {
2246 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
2250 uint8_t downlink_mode
= config
.downlink_mode
;
2252 downlink_mode
= refFixedBit
;
2254 downlink_mode
= refLongLeading
;
2256 downlink_mode
= refLeading0
;
2258 downlink_mode
= ref1of4
;
2260 bool success
= true;
2262 // Due to the few different T55xx cards and number of blocks supported
2263 // will save the dump file if ALL page 0 is OK
2265 for (uint8_t i
= 0; i
< 8; ++i
) {
2266 if (T55xxReadBlock(i
, 0, usepwd
, override
, password
, downlink_mode
) != PM3_SUCCESS
)
2269 // only show override warning on the first block read
2270 if (override
== 1) {
2275 for (uint8_t i
= 0; i
< 4; i
++)
2276 if (T55xxReadBlock(i
, 1, usepwd
, override
, password
, downlink_mode
) != PM3_SUCCESS
)
2277 T55x7_SaveBlockData(8 + i
, 0x00);
2279 // all ok, save dump to file
2282 // set default filename, if not set by user
2283 if (strlen(filename
) == 0) {
2284 strcpy(filename
, "lf-t55xx");
2285 for (uint8_t i
= 1; i
<= 7; i
++) {
2286 if ((cardmem
[i
].blockdata
!= 0x00) && (cardmem
[i
].blockdata
!= 0xFFFFFFFF)) {
2287 snprintf(filename
+ strlen(filename
), sizeof(filename
) - strlen(filename
), "-%08X", cardmem
[i
].blockdata
);
2292 strcat(filename
, "-dump");
2295 // Swap endian so the files match the txt display
2296 uint32_t data
[T55x7_BLOCK_COUNT
];
2298 for (int i
= 0; i
< T55x7_BLOCK_COUNT
; i
++) {
2299 data
[i
] = BSWAP_32(cardmem
[i
].blockdata
);
2302 // saveFileEML will add .eml extension to filename
2303 // saveFile (binary) passes in the .bin extension.
2304 saveFileJSON(filename
, jsfT55x7
, (uint8_t *)data
, T55x7_BLOCK_COUNT
* sizeof(uint32_t), NULL
);
2305 saveFileEML(filename
, (uint8_t *)data
, T55x7_BLOCK_COUNT
* sizeof(uint32_t), sizeof(uint32_t));
2306 saveFile(filename
, ".bin", data
, sizeof(data
));
2312 static int CmdT55xxRestore(const char *Cmd
) {
2313 CLIParserContext
*ctx
;
2314 CLIParserInit(&ctx
, "lf t55xx restore",
2315 "Restore T55xx card page 0/1 n blocks from (bin/eml/json) dump file",
2316 "lf t55xx restore -f lf-t55xx-00148040-dump.bin"
2319 void *argtable
[] = {
2321 arg_str0("f", "file", "<fn>", "filename of dump file"),
2322 arg_str0("p", "pwd", "<hex>", "password if target card has password set (4 hex bytes)"),
2325 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2328 char filename
[FILE_PATH_SIZE
] = {0};
2329 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, sizeof(filename
), &fnlen
);
2331 bool usepwd
= false;
2332 uint32_t password
= 0;
2333 int res
= arg_get_u32_hexstr_def_nlen(ctx
, 2, 0, &password
, 4, true);
2334 if (res
== 0 || res
== 2) {
2335 PrintAndLogEx(ERR
, "Password should be 4 hex bytes");
2345 PrintAndLogEx(ERR
, "Must specify a filename");
2351 DumpFileType_t dftype
= getfiletype(filename
);
2354 res
= loadFile_safe(filename
, ".bin", (void **)&dump
, &dlen
);
2358 res
= loadFileEML_safe(filename
, (void **)&dump
, &dlen
);
2362 dump
= calloc(T55x7_BLOCK_COUNT
* 4, sizeof(uint8_t));
2364 PrintAndLogEx(WARNING
, "Fail, cannot allocate memory");
2367 res
= loadFileJSON(filename
, dump
, T55x7_BLOCK_COUNT
* 4, &dlen
, NULL
);
2371 PrintAndLogEx(ERR
, "Error: Only BIN/EML/JSON formats allowed");
2377 //sanity checks of file processing
2378 if (res
!= PM3_SUCCESS
) {
2383 if (dlen
!= T55x7_BLOCK_COUNT
* 4) {
2385 PrintAndLogEx(FAILED
, "wrong length of dump file. Expected 48 bytes, got %zu", dlen
);
2389 // 12 blocks * 4 bytes per block
2390 // this part creates strings to call "lf t55 write" command.
2391 PrintAndLogEx(INFO
, "Starting to write...");
2393 uint8_t downlink_mode
;
2395 char pwdopt
[14] = {0}; // p XXXXXXXX
2398 snprintf(pwdopt
, sizeof(pwdopt
), "-p %08X", password
);
2400 uint32_t *data
= (uint32_t *) dump
;
2402 // Restore endien for writing to card
2403 for (idx
= 0; idx
< 12; idx
++) {
2404 data
[idx
] = BSWAP_32(data
[idx
]);
2407 // Have data ready, lets write
2409 // write blocks 1..7 page 0
2410 // write blocks 1..3 page 1
2411 // update downlink mode (if needed) and write b 0
2413 if ((((data
[11] >> 28) & 0xf) == 6) || (((data
[11] >> 28) & 0xf) == 9))
2414 downlink_mode
= (data
[11] >> 10) & 3;
2416 // write out blocks 1-7 page 0
2417 for (idx
= 1; idx
<= 7; idx
++) {
2418 snprintf(wcmd
, sizeof(wcmd
), "-b %d -d %08X %s", idx
, data
[idx
], pwdopt
);
2420 if (CmdT55xxWriteBlock(wcmd
) != PM3_SUCCESS
) {
2421 PrintAndLogEx(WARNING
, "Warning: error writing blk %d", idx
);
2425 // if password was set on the "blank" update as we may have just changed it
2427 snprintf(pwdopt
, sizeof(pwdopt
), "-p %08X", data
[7]);
2430 // write out blocks 1-3 page 1
2431 for (idx
= 9; idx
<= 11; idx
++) {
2432 snprintf(wcmd
, sizeof(wcmd
), "-b %d --pg1 -d %08X %s", idx
- 8, data
[idx
], pwdopt
);
2434 if (CmdT55xxWriteBlock(wcmd
) != PM3_SUCCESS
) {
2435 PrintAndLogEx(WARNING
, "Warning: error writing blk %d", idx
);
2439 // Update downlink mode for the page 0 config write.
2440 config
.downlink_mode
= downlink_mode
;
2442 // Write the page 0 config
2443 snprintf(wcmd
, sizeof(wcmd
), "-b 0 -d %08X %s", data
[0], pwdopt
);
2444 if (CmdT55xxWriteBlock(wcmd
) != PM3_SUCCESS
) {
2445 PrintAndLogEx(WARNING
, "Warning: error writing blk 0");
2448 PrintAndLogEx(INFO
, "Done!");
2452 static int CmdT55xxRestore(const char *Cmd) {
2454 uint32_t password = 0;
2455 uint8_t override = 0;
2456 uint8_t downlink_mode = config.downlink_mode;
2457 bool usepwd = false;
2458 bool errors = false;
2461 while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
2462 switch (tolower(param_getchar(Cmd, cmdp))) {
2464 return usage_t55xx_restore();
2466 downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
2467 if (downlink_mode > 3)
2473 password = param_get32ex(Cmd, cmdp + 1, 0, 16);
2482 PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
2487 if (errors) return usage_t55xx_restore();
2489 PrintAndLogEx(INFO, "Work in progress. To be implemented");
2490 if (usepwd || password || override ) {
2493 // load file name (json/eml/bin)
2497 uint32_t res = PM3_SUCCESS;
2500 // res = clone_t55xx_tag(blockdata, numblocks);
2505 bool AcquireData(uint8_t page
, uint8_t block
, bool pwdmode
, uint32_t password
, uint8_t downlink_mode
) {
2508 // b1 = page to read from
2509 // b2 = brute_mem (armside function)
2510 // arg1: which block to read
2517 uint8_t downlink_mode
;
2520 payload
.password
= password
;
2521 payload
.blockno
= block
;
2522 payload
.page
= page
& 0x1;
2523 payload
.pwdmode
= pwdmode
;
2524 payload
.downlink_mode
= downlink_mode
;
2526 clearCommandBuffer();
2527 SendCommandNG(CMD_LF_T55XX_READBL
, (uint8_t *)&payload
, sizeof(payload
));
2528 if (!WaitForResponseTimeout(CMD_LF_T55XX_READBL
, NULL
, 2500)) {
2529 PrintAndLogEx(WARNING
, "command execution time out");
2533 getSamples(12000, false);
2534 bool ok
= !getSignalProperties()->isnoise
;
2536 config
.usepwd
= pwdmode
;
2540 char *GetPskCfStr(uint32_t id
, bool q5
) {
2541 static char buf
[40];
2545 snprintf(retStr
, sizeof(buf
), "%u - RF/2", id
);
2548 snprintf(retStr
, sizeof(buf
), "%u - RF/4", id
);
2551 snprintf(retStr
, sizeof(buf
), "%u - RF/8", id
);
2555 snprintf(retStr
, sizeof(buf
), "%u - RF/8", id
);
2557 snprintf(retStr
, sizeof(buf
), "%u - " _RED_("(Unknown)"), id
);
2560 snprintf(retStr
, sizeof(buf
), "%u - " _RED_("(Unknown)"), id
);
2566 char *GetBitRateStr(uint32_t id
, bool xmode
) {
2567 static char buf
[25];
2570 if (xmode
) { //xmode bitrate calc is same as em4x05 calc
2571 snprintf(retStr
, sizeof(buf
), "%u - RF/%u", id
, EM4x05_GET_BITRATE(id
));
2575 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/8"), id
);
2578 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/16"), id
);
2581 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/32"), id
);
2584 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/40"), id
);
2587 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/50"), id
);
2590 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/64"), id
);
2593 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/100"), id
);
2596 snprintf(retStr
, sizeof(buf
), "%u - "_GREEN_("RF/128"), id
);
2599 snprintf(retStr
, sizeof(buf
), "%u - " _RED_("(Unknown)"), id
);
2606 char *GetSaferStr(uint32_t id
) {
2607 static char buf
[40];
2610 snprintf(retStr
, sizeof(buf
), "%u", id
);
2612 snprintf(retStr
, sizeof(buf
), "%u - " _YELLOW_("passwd"), id
);
2615 snprintf(retStr
, sizeof(buf
), "%u - " _YELLOW_("testmode"), id
);
2621 char *GetModulationStr(uint32_t id
, bool xmode
) {
2622 static char buf
[60];
2627 snprintf(retStr
, sizeof(buf
), "%u - DIRECT (ASK/NRZ)", id
);
2630 snprintf(retStr
, sizeof(buf
), "%u - PSK 1 phase change when input changes", id
);
2633 snprintf(retStr
, sizeof(buf
), "%u - PSK 2 phase change on bitclk if input high", id
);
2636 snprintf(retStr
, sizeof(buf
), "%u - PSK 3 phase change on rising edge of input", id
);
2639 snprintf(retStr
, sizeof(buf
), "%u - FSK 1 RF/8 RF/5", id
);
2642 snprintf(retStr
, sizeof(buf
), "%u - FSK 2 RF/8 RF/10", id
);
2645 snprintf(retStr
, sizeof(buf
), "%u - %s RF/5 RF/8", id
, (xmode
) ? "FSK 1a" : _YELLOW_("FSK 1a"));
2648 snprintf(retStr
, sizeof(buf
), "%u - %s RF/10 RF/8", id
, (xmode
) ? "FSK 2a" : _YELLOW_("FSK 2a"));
2651 snprintf(retStr
, sizeof(buf
), "%u - Manchester", id
);
2654 snprintf(retStr
, sizeof(buf
), "%u - Biphase", id
);
2657 snprintf(retStr
, sizeof(buf
), "%u - %s", id
, (xmode
) ? "Biphase a - AKA Conditional Dephase Encoding(CDP)" : _YELLOW_("Reserved"));
2660 snprintf(retStr
, sizeof(buf
), "0x%02X " _RED_("(Unknown)"), id
);
2666 char *GetDownlinkModeStr(uint8_t downlink_mode
) {
2667 static char buf
[30];
2670 switch (downlink_mode
) {
2671 case T55XX_DLMODE_FIXED
:
2672 snprintf(retStr
, sizeof(buf
), "default/fixed bit length");
2674 case T55XX_DLMODE_LLR
:
2675 snprintf(retStr
, sizeof(buf
), "long leading reference");
2677 case T55XX_DLMODE_LEADING_ZERO
:
2678 snprintf(retStr
, sizeof(buf
), "leading zero reference");
2680 case T55XX_DLMODE_1OF4
:
2681 snprintf(retStr
, sizeof(buf
), "1 of 4 coding reference");
2684 snprintf(retStr
, sizeof(buf
), _RED_("(Unknown)"));
2690 char *GetQ5ModulationStr(uint32_t id
) {
2691 static char buf
[60];
2696 snprintf(retStr
, sizeof(buf
), "%u - Manchester", id
);
2699 snprintf(retStr
, sizeof(buf
), "%u - PSK 1 phase change when input changes", id
);
2702 snprintf(retStr
, sizeof(buf
), "%u - PSK 2 phase change on bitclk if input high", id
);
2705 snprintf(retStr
, sizeof(buf
), "%u - PSK 3 phase change on rising edge of input", id
);
2708 snprintf(retStr
, sizeof(buf
), "%u - FSK 1a RF/5 RF/8", id
);
2711 snprintf(retStr
, sizeof(buf
), "%u - FSK 2a RF/10 RF/8", id
);
2714 snprintf(retStr
, sizeof(buf
), "%u - Biphase", id
);
2717 snprintf(retStr
, sizeof(buf
), "%u - NRZ / Direct", id
);
2723 char *GetModelStrFromCID(uint32_t cid
) {
2725 static char buf
[10];
2728 if (cid
== 1) snprintf(retStr
, sizeof(buf
), "ATA5577M1");
2729 if (cid
== 2) snprintf(retStr
, sizeof(buf
), "ATA5577M2");
2730 if (cid
== 3) snprintf(retStr
, sizeof(buf
), "ATA5577M3");
2734 char *GetConfigBlock0Source(uint8_t id
) {
2736 static char buf
[40];
2741 snprintf(retStr
, sizeof(buf
), _YELLOW_("(auto detect)"));
2744 snprintf(retStr
, sizeof(buf
), _YELLOW_("(user set)"));
2747 snprintf(retStr
, sizeof(buf
), _GREEN_("(tag read)"));
2750 snprintf(retStr
, sizeof(buf
), _RED_("(n/a)"));
2756 char *GetSelectedModulationStr(uint8_t id
) {
2758 static char buf
[20];
2763 snprintf(retStr
, sizeof(buf
), "FSK");
2766 snprintf(retStr
, sizeof(buf
), "FSK1");
2769 snprintf(retStr
, sizeof(buf
), "FSK1a");
2772 snprintf(retStr
, sizeof(buf
), "FSK2");
2775 snprintf(retStr
, sizeof(buf
), "FSK2a");
2778 snprintf(retStr
, sizeof(buf
), "ASK");
2781 snprintf(retStr
, sizeof(buf
), "DIRECT/NRZ");
2784 snprintf(retStr
, sizeof(buf
), "PSK1");
2787 snprintf(retStr
, sizeof(buf
), "PSK2");
2790 snprintf(retStr
, sizeof(buf
), "PSK3");
2793 snprintf(retStr
, sizeof(buf
), "BIPHASE");
2796 snprintf(retStr
, sizeof(buf
), "BIPHASEa - (CDP)");
2799 snprintf(retStr
, sizeof(buf
), _RED_("(Unknown)"));
2806 static void t55x7_create_config_block(int tagtype) {
2808 // T55X7_DEFAULT_CONFIG_BLOCK, T55X7_RAW_CONFIG_BLOCK
2809 // T55X7_EM_UNIQUE_CONFIG_BLOCK, T55X7_FDXB_CONFIG_BLOCK,
2810 // T55X7_FDXB_CONFIG_BLOCK, T55X7_HID_26_CONFIG_BLOCK, T55X7_INDALA_64_CONFIG_BLOCK, T55X7_INDALA_224_CONFIG_BLOCK
2811 // T55X7_GUARDPROXII_CONFIG_BLOCK, T55X7_VIKING_CONFIG_BLOCK, T55X7_NORALYS_CONFIG_BLOCK, T55X7_IOPROX_CONFIG_BLOCK
2812 static char buf[60];
2817 snprintf(retStr, sizeof(buf), "%08X - T55X7 Default", T55X7_DEFAULT_CONFIG_BLOCK);
2820 snprintf(retStr, sizeof(buf), "%08X - T55X7 Raw", T55X7_RAW_CONFIG_BLOCK);
2823 snprintf(retStr, sizeof(buf), "%08X - Q5/T5555 Default", T5555_DEFAULT_CONFIG_BLOCK);
2828 PrintAndLogEx(NORMAL, buf);
2832 static int CmdResetRead(const char *Cmd
) {
2834 CLIParserContext
*ctx
;
2835 CLIParserInit(&ctx
, "lf t55xx resetread",
2836 "Send Reset Cmd then `lf read` the stream to attempt\n"
2837 "to identify the start of it (needs a demod and/or plot after)",
2838 "lf t55xx resetread"
2841 // 1 (help) + 0(one user specified params) + (5 T55XX_DLMODE_SINGLE)
2842 void *argtable
[2 + 5] = {
2844 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
2847 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
2848 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2850 bool r0
= arg_get_lit(ctx
, 1);
2851 bool r1
= arg_get_lit(ctx
, 2);
2852 bool r2
= arg_get_lit(ctx
, 3);
2853 bool r3
= arg_get_lit(ctx
, 4);
2856 if ((r0
+ r1
+ r2
+ r3
) > 1) {
2857 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
2861 uint8_t downlink_mode
= config
.downlink_mode
;
2863 downlink_mode
= refFixedBit
;
2865 downlink_mode
= refLongLeading
;
2867 downlink_mode
= refLeading0
;
2869 downlink_mode
= ref1of4
;
2871 uint8_t flags
= downlink_mode
<< 3;
2873 PrintAndLogEx(INFO
, "Sending reset command...");
2875 PacketResponseNG resp
;
2876 clearCommandBuffer();
2877 SendCommandNG(CMD_LF_T55XX_RESET_READ
, &flags
, sizeof(flags
));
2878 if (WaitForResponseTimeout(CMD_LF_T55XX_RESET_READ
, &resp
, 2500) == false) {
2879 PrintAndLogEx(WARNING
, "command execution time out");
2880 return PM3_ETIMEOUT
;
2883 if (resp
.status
== PM3_SUCCESS
) {
2885 uint16_t gotsize
= pm3_capabilities
.bigbuf_size
- 1;
2886 uint8_t *got
= calloc(gotsize
, sizeof(uint8_t));
2888 PrintAndLogEx(WARNING
, "failed to allocate memory");
2892 PrintAndLogEx(INFO
, "Downloading samples...");
2893 if (!GetFromDevice(BIG_BUF
, got
, gotsize
, 0, NULL
, 0, NULL
, 2500, false)) {
2894 PrintAndLogEx(WARNING
, "command execution time out");
2896 return PM3_ETIMEOUT
;
2898 setGraphBuf(got
, gotsize
);
2902 PrintAndLogEx(INFO
, "Done");
2906 static int CmdT55xxWipe(const char *Cmd
) {
2907 CLIParserContext
*ctx
;
2908 CLIParserInit(&ctx
, "lf t55xx wipe",
2909 "This commands wipes a tag, fills blocks 1-7 with zeros and a default configuration block",
2910 "lf t55xx wipe -> wipes a T55x7 tag, config block 0x000880E0\n"
2911 "lf t55xx wipe --q5 -> wipes a Q5/T5555 tag, config block 0x6001F004\n"
2912 "lf t55xx wipe -p 11223344 -> wipes a T55x7 tag, config block 0x000880E0, using pwd"
2915 // 1 (help) + 3 (three user specified params) + (5 T55XX_DLMODE_SINGLE)
2916 void *argtable
[4 + 5] = {
2918 arg_str0("c", "cfg", "<hex>", "configuration block0 (4 hex bytes)"),
2919 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
2920 arg_lit0(NULL
, "q5", "specify writing to Q5/T5555 tag using dedicated config block"),
2923 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
2924 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2926 bool usepwd
= false, gotconf
= false;
2927 uint32_t block0
= 0;
2928 int res
= arg_get_u32_hexstr_def(ctx
, 1, 0, &block0
);
2934 PrintAndLogEx(WARNING
, "config block needs to be 4 hex bytes");
2938 uint32_t password
= 0;
2939 res
= arg_get_u32_hexstr_def(ctx
, 2, 0x51243648, &password
);
2945 PrintAndLogEx(WARNING
, "Password should be 4 bytes, using default pwd");
2948 bool Q5
= arg_get_lit(ctx
, 3);
2951 PrintAndLogEx(INFO
, "Target " _YELLOW_("%s")" tag", (Q5
) ? "Q5/T5555" : "T55x7");
2953 // default config blocks.
2954 if (gotconf
== false) {
2955 block0
= (Q5
) ? 0x6001F004 : 0x000880E0;
2959 PrintAndLogEx(INFO
, "Using password " _GREEN_("%08X"), password
);
2963 snprintf(msg
, sizeof(msg
), "User provided configuration block " _GREEN_("%08X"), block0
);
2965 snprintf(msg
, sizeof(msg
), "Default configuration block " _GREEN_("%08X"), block0
);
2967 PrintAndLogEx(INFO
, "%s\n", msg
);
2969 PrintAndLogEx(INFO
, "Begin wiping...");
2971 // Creating cmd string for write block :)
2972 char wcmd
[36] = {0};
2975 snprintf(pwcmd
, sizeof(wcmd
), "-b 0 ");
2978 snprintf(pwcmd
+ strlen(wcmd
), sizeof(wcmd
) - strlen(wcmd
), "-p %08x ", password
);
2980 snprintf(pwcmd
+ strlen(wcmd
), sizeof(wcmd
) - strlen(wcmd
), "-d %08X", block0
);
2982 if (CmdT55xxWriteBlock(pwcmd
) != PM3_SUCCESS
)
2983 PrintAndLogEx(WARNING
, "Warning: error writing blk 0");
2985 for (uint8_t blk
= 1; blk
< 8; blk
++) {
2987 snprintf(pwcmd
, sizeof(wcmd
), "-b %d -d 00000000", blk
);
2989 if (CmdT55xxWriteBlock(pwcmd
) != PM3_SUCCESS
)
2990 PrintAndLogEx(WARNING
, "Warning: error writing blk %d", blk
);
2992 memset(wcmd
, 0x00, sizeof(wcmd
));
2995 // Check and rest t55xx downlink mode.
2996 if (config
.downlink_mode
!= T55XX_DLMODE_FIXED
) { // Detect found a different mode so card must support
2997 snprintf(pwcmd
, sizeof(wcmd
), "-b 3 --pg1 -d 00000000");
2998 if (CmdT55xxWriteBlock(pwcmd
) != PM3_SUCCESS
) {
2999 PrintAndLogEx(WARNING
, "Warning: failed writing block 3 page 1 (config)");
3001 memset(wcmd
, 0x00, sizeof(wcmd
));
3006 static bool IsCancelled(void) {
3007 if (kbd_enter_pressed()) {
3008 PrintAndLogEx(WARNING
, "\naborted via keyboard!\n");
3014 // load a default pwd file.
3015 static int CmdT55xxChkPwds(const char *Cmd
) {
3016 CLIParserContext
*ctx
;
3017 CLIParserInit(&ctx
, "lf t55xx chk",
3018 "This command uses a dictionary attack.\n"
3019 "For some cloners, try '--em' for known pwdgen algo.\n"
3020 "Try to reading Page 0 block 7 before.\n"
3021 _RED_("WARNING:") _CYAN_(" this may brick non-password protected chips!"),
3022 "lf t55xx chk -m -> use dictionary from flash memory (RDV4)\n"
3023 "lf t55xx chk -f my_dictionary_pwds -> loads a default keys dictionary file\n"
3024 "lf t55xx chk --em aa11223344 -> try known pwdgen algo from some cloners based on EM4100 ID"
3028 Calculate size of argtable accordingly:
3029 1 (help) + 3 (three user specified params) + ( 5 or 6 T55XX_DLMODE)
3030 start index to call arg_add_t55xx_downloadlink() is 4 (1 + 3) given the above sample
3033 // 1 (help) + 3 (three user specified params) + (6 T55XX_DLMODE_ALL)
3034 void *argtable
[4 + 6] = {
3036 arg_lit0("m", "fm", "use dictionary from flash memory (RDV4)"),
3037 arg_str0("f", "file", "<fn>", "file name"),
3038 arg_str0(NULL
, "em", "<hex>", "EM4100 ID (5 hex bytes)"),
3041 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_ALL
, T55XX_DLMODE_ALL
);
3042 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3044 bool from_flash
= arg_get_lit(ctx
, 1);
3047 char filename
[FILE_PATH_SIZE
] = {0};
3048 CLIParamStrToBuf(arg_get_str(ctx
, 2), (uint8_t *)filename
, sizeof(filename
), &fnlen
);
3050 // White cloner password based on EM4100 ID
3051 bool use_calc_password
= false;
3052 uint32_t card_password
= 0x00;
3053 uint64_t cardid
= 0;
3054 int res
= arg_get_u64_hexstr_def_nlen(ctx
, 3, 0x00, &cardid
, 5, true);
3056 use_calc_password
= true;
3057 uint32_t calc
= cardid
& 0xFFFFFFFF;
3058 card_password
= lf_t55xx_white_pwdgen(calc
);
3062 PrintAndLogEx(WARNING
, "EM4100 ID must be 5 hex bytes");
3070 bool r0
= arg_get_lit(ctx
, 4);
3071 bool r1
= arg_get_lit(ctx
, 5);
3072 bool r2
= arg_get_lit(ctx
, 6);
3073 bool r3
= arg_get_lit(ctx
, 7);
3074 bool ra
= arg_get_lit(ctx
, 8);
3077 if ((r0
+ r1
+ r2
+ r3
+ ra
) > 1) {
3078 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3082 uint8_t downlink_mode
= refFixedBit
; // Password checks should always start with default/fixed bit unluess requested by user for specific mode
3083 // if (r0 || ra) // ra should start downlink mode ad fixed bit to loop through all modes correctly
3084 // downlink_mode = refFixedBit;
3087 downlink_mode
= refLongLeading
;
3089 downlink_mode
= refLeading0
;
3091 downlink_mode
= ref1of4
;
3093 bool use_pwd_file
= true; // Assume we are going to use a file, unless turned off later.
3095 if (strlen(filename
) == 0) {
3096 snprintf(filename
, sizeof(filename
), "t55xx_default_pwds");
3099 PrintAndLogEx(INFO
, "press " _GREEN_("<Enter>") " to exit");
3100 PrintAndLogEx(NORMAL
, "");
3102 // block 7, page1 = false, usepwd = false, override = false, pwd = 00000000
3103 if ( T55xxReadBlock(7, false, false, false, 0x00000000) == PM3_SUCCESS) {
3105 // now try to validate it..
3106 PrintAndLogEx(WARNING, "\n Block 7 was readable");
3113 uint64_t t1
= msclock();
3114 uint8_t flags
= downlink_mode
<< 3;
3117 use_pwd_file
= false; // turn of local password file since we are checking from flash.
3118 clearCommandBuffer();
3119 SendCommandNG(CMD_LF_T55XX_CHK_PWDS
, &flags
, sizeof(flags
));
3120 PacketResponseNG resp
;
3122 uint8_t timeout
= 0;
3123 while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS
, &resp
, 2000)) {
3125 PrintAndLogEx(NORMAL
, "." NOLF
);
3126 if (timeout
> 180) {
3127 PrintAndLogEx(WARNING
, "\nno response from Proxmark3. Aborting...");
3131 PrintAndLogEx(NORMAL
, "");
3136 struct p
*packet
= (struct p
*)resp
.data
.asBytes
;
3138 if (packet
->found
) {
3139 PrintAndLogEx(SUCCESS
, "\nfound a candidate [ " _YELLOW_("%08"PRIX32
) " ]", packet
->candidate
);
3141 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, true, packet
->candidate
, downlink_mode
)) {
3142 found
= t55xxTryDetectModulationEx(downlink_mode
, T55XX_PrintConfig
, 0, packet
->candidate
);
3144 PrintAndLogEx(SUCCESS
, "found valid password [ " _GREEN_("%08"PRIX32
) " ]", packet
->candidate
);
3147 PrintAndLogEx(WARNING
, "check pwd failed");
3150 PrintAndLogEx(WARNING
, "check pwd failed");
3153 PrintAndLogEx(WARNING
, "check pwd failed");
3158 // to try each downlink mode for each password
3161 // try calculated password
3162 if (use_calc_password
) {
3164 PrintAndLogEx(INFO
, "testing %08"PRIX32
" generated ", card_password
);
3165 for (dl_mode
= downlink_mode
; dl_mode
<= 3; dl_mode
++) {
3167 if (!AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, true, card_password
, dl_mode
)) {
3171 found
= t55xxTryDetectModulationEx(dl_mode
, T55XX_PrintConfig
, 0, card_password
);
3173 PrintAndLogEx(SUCCESS
, "found valid password : [ " _GREEN_("%08"PRIX32
) " ]", card_password
);
3182 if ((found
== false) && use_pwd_file
) {
3183 uint32_t keycount
= 0;
3184 uint8_t *keyblock
= NULL
;
3186 res
= loadFileDICTIONARY_safe(filename
, (void **) &keyblock
, 4, &keycount
);
3187 if (res
!= PM3_SUCCESS
|| keycount
== 0 || keyblock
== NULL
) {
3188 PrintAndLogEx(WARNING
, "no keys found in file");
3189 if (keyblock
!= NULL
)
3195 PrintAndLogEx(INFO
, "press " _GREEN_("<Enter>") " to exit");
3197 for (uint32_t c
= 0; c
< keycount
&& found
== false; ++c
) {
3199 if (!session
.pm3_present
) {
3200 PrintAndLogEx(WARNING
, "device offline\n");
3205 if (IsCancelled()) {
3207 return PM3_EOPABORTED
;
3210 uint32_t curr_password
= bytes_to_num(keyblock
+ 4 * c
, 4);
3212 PrintAndLogEx(INFO
, "testing %08"PRIX32
, curr_password
);
3213 for (dl_mode
= downlink_mode
; dl_mode
<= 3; dl_mode
++) {
3214 // If aquire fails, then we still need to check if we are only trying a single downlink mode.
3215 // If we continue on fail, it will skip that test and try the next downlink mode; thus slowing down the check
3216 // when on a single downlink mode is wanted.
3217 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, true, curr_password
, dl_mode
)) {
3218 found
= t55xxTryDetectModulationEx(dl_mode
, T55XX_PrintConfig
, 0, curr_password
);
3220 PrintAndLogEx(SUCCESS
, "found valid password: [ " _GREEN_("%08"PRIX32
) " ]", curr_password
);
3224 if (ra
== false) // Exit loop if not trying all downlink modes
3233 PrintAndLogEx(WARNING
, "failed to find password");
3236 t1
= msclock() - t1
;
3237 PrintAndLogEx(SUCCESS
, "\ntime in check pwd " _YELLOW_("%.0f") " seconds\n", (float)t1
/ 1000.0);
3241 // Bruteforce - incremental password range search
3242 static int CmdT55xxBruteForce(const char *Cmd
) {
3243 CLIParserContext
*ctx
;
3244 CLIParserInit(&ctx
, "lf t55xx bruteforce",
3245 "This command uses bruteforce to scan a number range.\n"
3246 "Try reading Page 0, block 7 before.\n\n"
3247 _RED_("WARNING") _CYAN_(" this may brick non-password protected chips!"),
3248 "lf t55xx bruteforce --r2 -s aaaaaa77 -e aaaaaa99\n"
3251 // 1 (help) + 2 (two user specified params) + (6 T55XX_DLMODE_ALL)
3252 void *argtable
[3 + 6] = {
3254 arg_str1("s", "start", "<hex>", "search start password (4 hex bytes)"),
3255 arg_str1("e", "end", "<hex>", "search end password (4 hex bytes)"),
3258 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_ALL
, T55XX_DLMODE_ALL
);
3259 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3261 uint32_t start_password
= 0;
3262 int res
= arg_get_u32_hexstr_def(ctx
, 1, 0, &start_password
);
3265 PrintAndLogEx(FAILED
, "start password should be 4 bytes");
3269 uint32_t end_password
= 0xFFFFFFFF;
3270 res
= arg_get_u32_hexstr_def(ctx
, 2, 0xFFFFFFFF, &end_password
);
3273 PrintAndLogEx(FAILED
, "end password should be 4 bytes");
3277 bool r0
= arg_get_lit(ctx
, 3);
3278 bool r1
= arg_get_lit(ctx
, 4);
3279 bool r2
= arg_get_lit(ctx
, 5);
3280 bool r3
= arg_get_lit(ctx
, 6);
3281 bool ra
= arg_get_lit(ctx
, 7);
3284 if ((r0
+ r1
+ r2
+ r3
+ ra
) > 1) {
3285 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3289 uint8_t downlink_mode
= refFixedBit
; // if no downlink mode suppliled use fixed bit/default as the is the most common
3290 // Since we dont know the password the config.downlink mode is of little value.
3291 // if (r0 || ra) // if try all (ra) then start at fixed bit for correct try all
3292 // downlink_mode = refFixedBit;
3295 downlink_mode
= refLongLeading
;
3297 downlink_mode
= refLeading0
;
3299 downlink_mode
= ref1of4
;
3302 uint8_t found
= 0; // > 0 if found xx1 xx downlink needed, 1 found
3304 if (start_password
>= end_password
) {
3305 PrintAndLogEx(FAILED
, "Error, start larger then end password");
3309 PrintAndLogEx(INFO
, "press " _GREEN_("<Enter>") " to exit");
3310 PrintAndLogEx(INFO
, "Search password range [%08X -> %08X]", start_password
, end_password
);
3312 uint64_t t1
= msclock();
3313 curr
= start_password
;
3315 while (found
== 0) {
3317 PrintAndLogEx(NORMAL
, "." NOLF
);
3319 if (IsCancelled()) {
3320 return PM3_EOPABORTED
;
3323 found
= t55xx_try_one_password(curr
, downlink_mode
, ra
);
3325 if (curr
== end_password
)
3331 PrintAndLogEx(NORMAL
, "");
3334 PrintAndLogEx(SUCCESS
, "Found valid password: [ " _GREEN_("%08X") " ]", curr
- 1);
3335 T55xx_Print_DownlinkMode((found
>> 1) & 3);
3337 PrintAndLogEx(WARNING
, "Bruteforce failed, last tried: [ " _YELLOW_("%08X") " ]", curr
);
3339 t1
= msclock() - t1
;
3340 PrintAndLogEx(SUCCESS
, "\ntime in bruteforce " _YELLOW_("%.0f") " seconds\n", (float)t1
/ 1000.0);
3344 uint8_t t55xx_try_one_password(uint32_t password
, uint8_t downlink_mode
, bool try_all_dl_modes
) {
3346 PrintAndLogEx(INFO
, "Trying password %08X", password
);
3349 downlink_mode
= (downlink_mode
& 3);
3351 // check if dl mode 4 and loop if needed
3352 for (uint8_t dl_mode
= downlink_mode
; dl_mode
< 4; dl_mode
++) {
3354 if (AcquireData(T55x7_PAGE0
, T55x7_CONFIGURATION_BLOCK
, true, password
, dl_mode
)) {
3355 // if (getSignalProperties()->isnoise == false) {
3357 if (t55xxTryDetectModulationEx(dl_mode
, T55XX_PrintConfig
, 0, password
)) {
3358 return 1 + (dl_mode
<< 1);
3362 if (try_all_dl_modes
== false) {
3369 static int CmdT55xxRecoverPW(const char *Cmd
) {
3370 CLIParserContext
*ctx
;
3371 CLIParserInit(&ctx
, "lf t55xx recoverpw",
3372 "This command uses a few tricks to try to recover mangled password.\n"
3373 "Try reading Page 0, block 7 before.\n\n"
3374 _RED_("WARNING") _CYAN_(" this may brick non-password protected chips!"),
3375 "lf t55xx recoverpw\n"
3376 "lf t55xx recoverpw -p 11223344\n"
3377 "lf t55xx recoverpw -p 11223344 --r3\n"
3380 // 1 (help) + 1 (one user specified params) + (6 T55XX_DLMODE_ALL)
3381 void *argtable
[2 + 6] = {
3383 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
3386 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_ALL
, T55XX_DLMODE_ALL
);
3387 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3389 uint32_t orig_password
= 0;
3390 int res
= arg_get_u32_hexstr_def(ctx
, 1, 0x51243648, &orig_password
);
3392 PrintAndLogEx(INFO
, "Password should be 4 bytes, using default pwd instead");
3395 bool r0
= arg_get_lit(ctx
, 2);
3396 bool r1
= arg_get_lit(ctx
, 3);
3397 bool r2
= arg_get_lit(ctx
, 4);
3398 bool r3
= arg_get_lit(ctx
, 5);
3399 bool ra
= arg_get_lit(ctx
, 6);
3402 if ((r0
+ r1
+ r2
+ r3
+ ra
) > 1) {
3403 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3407 uint8_t downlink_mode
= config
.downlink_mode
;
3409 downlink_mode
= refFixedBit
;
3411 downlink_mode
= refLongLeading
;
3413 downlink_mode
= refLeading0
;
3415 downlink_mode
= ref1of4
;
3417 PrintAndLogEx(INFO
, "press " _GREEN_("<Enter>") " to exit");
3420 uint32_t curr_password
= 0x0;
3421 uint32_t prev_password
= 0xffffffff;
3422 uint32_t mask
= 0x0;
3425 // first try fliping each bit in the expected password
3427 curr_password
= orig_password
^ (1u << bit
);
3428 found
= t55xx_try_one_password(curr_password
, downlink_mode
, ra
);
3429 if (found
> 0) // xx1 for found xx = dl mode used
3435 return PM3_EOPABORTED
;
3438 // now try to use partial original password, since block 7 should have been completely
3439 // erased during the write sequence and it is possible that only partial password has been
3441 // not sure from which end the bit bits are written, so try from both ends
3442 // from low bit to high bit
3445 mask
+= (1u << bit
);
3446 curr_password
= orig_password
& mask
;
3447 // if updated mask didn't change the password, don't try it again
3448 if (prev_password
== curr_password
) {
3453 found
= t55xx_try_one_password(curr_password
, downlink_mode
, ra
);
3458 prev_password
= curr_password
;
3461 return PM3_EOPABORTED
;
3464 // from high bit to low
3468 mask
-= (1u << bit
);
3469 curr_password
= orig_password
& mask
;
3470 // if updated mask didn't change the password, don't try it again
3471 if (prev_password
== curr_password
) {
3475 found
= t55xx_try_one_password(curr_password
, downlink_mode
, ra
);
3480 prev_password
= curr_password
;
3483 return PM3_EOPABORTED
;
3487 PrintAndLogEx(NORMAL
, "");
3490 PrintAndLogEx(SUCCESS
, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password
);
3491 T55xx_Print_DownlinkMode((found
>> 1) & 3);
3493 PrintAndLogEx(FAILED
, "Recover password failed");
3498 // note length of data returned is different for different chips.
3499 // some return all page 1 (64 bits) and others return just that block (32 bits)
3500 // unfortunately the 64 bits makes this more likely to get a false positive...
3501 bool tryDetectP1(bool getData
) {
3502 uint8_t preamble
[] = {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1};
3503 size_t startIdx
= 0;
3504 uint8_t fc1
= 0, fc2
= 0, ans
= 0;
3505 int clk
= 0, firstClockEdge
= 0;
3509 if (!AcquireData(T55x7_PAGE1
, T55x7_TRACE_BLOCK1
, false, 0, 0))
3513 // try fsk clock detect. if successful it cannot be any other type of modulation... (in theory...)
3514 ans
= fskClocks(&fc1
, &fc2
, (uint8_t *)&clk
, &firstClockEdge
);
3515 if (ans
&& ((fc1
== 10 && fc2
== 8) || (fc1
== 8 && fc2
== 5))) {
3516 if ((FSKrawDemod(0, 0, 0, 0, false) == PM3_SUCCESS
) &&
3517 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3518 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3521 if ((FSKrawDemod(0, 1, 0, 0, false) == PM3_SUCCESS
) &&
3522 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3523 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3529 // try ask clock detect. it could be another type even if successful.
3530 clk
= GetAskClock("", false);
3532 if ((ASKDemod_ext(0, 0, 1, 0, false, false, false, 1, &st
) == PM3_SUCCESS
) &&
3533 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3534 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3539 if ((ASKDemod_ext(0, 1, 1, 0, false, false, false, 1, &st
) == PM3_SUCCESS
) &&
3540 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3541 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3545 if ((ASKbiphaseDemod(0, 0, 0, 2, false) == PM3_SUCCESS
) &&
3546 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3547 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3551 if ((ASKbiphaseDemod(0, 0, 1, 2, false) == PM3_SUCCESS
) &&
3552 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3553 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3558 // try NRZ clock detect. it could be another type even if successful.
3559 clk
= GetNrzClock("", false); //has the most false positives :(
3561 if ((NRZrawDemod(0, 0, 1, false) == PM3_SUCCESS
) &&
3562 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3563 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3566 if ((NRZrawDemod(0, 1, 1, false) == PM3_SUCCESS
) &&
3567 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3568 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3573 // Fewer card uses PSK
3574 // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...)
3575 clk
= GetPskClock("", false);
3578 // save_restoreGB(GRAPH_SAVE);
3579 // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)
3580 //CmdLtrim("-i 160");
3581 if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) &&
3582 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3583 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3584 //save_restoreGB(GRAPH_RESTORE);
3587 if ((PSKDemod(0, 1, 6, false) == PM3_SUCCESS
) &&
3588 preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3589 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3590 //save_restoreGB(GRAPH_RESTORE);
3593 // PSK2 - needs a call to psk1TOpsk2.
3594 if (PSKDemod(0, 0, 6, false) == PM3_SUCCESS
) {
3595 psk1TOpsk2(DemodBuffer
, DemodBufferLen
);
3596 if (preambleSearchEx(DemodBuffer
, preamble
, sizeof(preamble
), &DemodBufferLen
, &startIdx
, false) &&
3597 (DemodBufferLen
== 32 || DemodBufferLen
== 64)) {
3598 //save_restoreGB(GRAPH_RESTORE);
3601 } // inverse waves does not affect PSK2 demod
3603 //save_restoreGB(GRAPH_RESTORE);
3604 // no other modulation clocks = 2 or 4 so quit searching
3605 if (fc1
!= 8) return false;
3610 // does this need to be a callable command?
3611 static int CmdT55xxDetectPage1(const char *Cmd
) {
3612 CLIParserContext
*ctx
;
3613 CLIParserInit(&ctx
, "lf t55xx p1detect",
3614 "Detect Page 1 of a T55xx chip",
3615 "lf t55xx p1detect\n"
3616 "lf t55xx p1detect -1\n"
3617 "lf t55xx p1detect -p 11223344 --r3\n"
3620 // 1 (help) + 2 (two user specified params) + (5 T55XX_DLMODE_SINGLE)
3621 void *argtable
[3 + 5] = {
3623 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
3624 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
3627 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
3628 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3630 bool use_graphbuf
= arg_get_lit(ctx
, 1);
3632 bool usepwd
= false;
3633 uint32_t password
= 0;
3634 int res
= arg_get_u32_hexstr_def(ctx
, 2, 0, &password
);
3636 PrintAndLogEx(INFO
, "Password should be 4 hex bytes");
3639 } else if (res
== 1) {
3643 bool r0
= arg_get_lit(ctx
, 3);
3644 bool r1
= arg_get_lit(ctx
, 4);
3645 bool r2
= arg_get_lit(ctx
, 5);
3646 bool r3
= arg_get_lit(ctx
, 6);
3649 if ((r0
+ r1
+ r2
+ r3
) > 1) {
3650 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3654 uint8_t downlink_mode
= config
.downlink_mode
;
3656 downlink_mode
= refFixedBit
;
3658 downlink_mode
= refLongLeading
;
3660 downlink_mode
= refLeading0
;
3662 downlink_mode
= ref1of4
;
3664 bool try_all_dl_modes
= true;
3667 if (downlink_mode
== 4)
3668 try_all_dl_modes
= true;
3669 if (downlink_mode
< 4)
3670 try_all_dl_modes
= false;
3672 if (downlink_mode
> 3)
3676 uint8_t found_mode
= 0;
3678 if (use_graphbuf
== false) {
3679 for (uint8_t dl_mode
= downlink_mode
; dl_mode
< 4; dl_mode
++) {
3681 if (AcquireData(T55x7_PAGE1
, T55x7_TRACE_BLOCK1
, usepwd
, password
, dl_mode
) == false)
3684 if (tryDetectP1(false)) {
3686 found_mode
= dl_mode
;
3692 if (try_all_dl_modes
== false) {
3697 found
= tryDetectP1(false);
3701 PrintAndLogEx(SUCCESS
, "T55xx chip found!");
3702 T55xx_Print_DownlinkMode(found_mode
);
3704 PrintAndLogEx(WARNING
, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'"));
3709 static int CmdT55xxSetDeviceConfig(const char *Cmd
) {
3710 CLIParserContext
*ctx
;
3711 CLIParserInit(&ctx
, "lf t55xx deviceconfig",
3712 "Sets t55x7 timings for direct commands.\n"
3713 "The timings are set here in Field Clocks (FC) which is converted to (US) on device.",
3714 "lf t55xx deviceconfig -a 29 -b 17 -c 15 -d 47 -e 15 -> default T55XX\n"
3715 "lf t55xx deviceconfig -a 55 -b 14 -c 21 -d 30 -> default EM4305"
3718 // 1 (help) + 9 (nine user specified params) + (5 T55XX_DLMODE_SINGLE)
3719 void *argtable
[10 + 5] = {
3721 arg_int0("a", NULL
, "<8..255>", "Set start gap"),
3722 arg_int0("b", NULL
, "<8..255>", "Set write gap"),
3723 arg_int0("c", NULL
, "<8..255>", "Set write ZERO gap"),
3724 arg_int0("d", NULL
, "<8..255>", "Set write ONE gap"),
3725 arg_int0("e", NULL
, "<8..255>", "Set read gap"),
3726 arg_int0("f", NULL
, "<8..255>", "Set write TWO gap (1 of 4 only)"),
3727 arg_int0("g", NULL
, "<8..255>", "Set write THREE gap (1 of 4 only)"),
3728 arg_lit0("p", "persist", "persist to flash memory (RDV4)"),
3729 arg_lit0("z", NULL
, "Set default t55x7 timings (use `-p` to save if required)"),
3732 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
3733 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
3735 uint8_t startgap
= arg_get_int(ctx
, 1);
3736 uint8_t writegap
= arg_get_int(ctx
, 2);
3737 uint8_t write0
= arg_get_int(ctx
, 3);
3738 uint8_t write1
= arg_get_int(ctx
, 4);
3739 uint8_t readgap
= arg_get_int(ctx
, 5);
3740 uint8_t write2
= arg_get_int(ctx
, 6);
3741 uint8_t write3
= arg_get_int(ctx
, 7);
3742 bool shall_persist
= arg_get_lit(ctx
, 8);
3743 bool set_defaults
= arg_get_lit(ctx
, 9);
3744 bool r0
= arg_get_lit(ctx
, 10);
3745 bool r1
= arg_get_lit(ctx
, 11);
3746 bool r2
= arg_get_lit(ctx
, 12);
3747 bool r3
= arg_get_lit(ctx
, 13);
3750 if ((r0
+ r1
+ r2
+ r3
) > 1) {
3751 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3755 uint8_t downlink_mode
= 0;
3757 downlink_mode
= refFixedBit
;
3759 downlink_mode
= refLongLeading
;
3761 downlink_mode
= refLeading0
;
3763 downlink_mode
= ref1of4
;
3765 t55xx_configurations_t configurations
= {{{0}, {0}, {0}, {0}}};
3769 configurations
.m
[T55XX_DLMODE_FIXED
].start_gap
= 29 * 8;
3770 configurations
.m
[T55XX_DLMODE_FIXED
].write_gap
= 17 * 8;
3771 configurations
.m
[T55XX_DLMODE_FIXED
].write_0
= 15 * 8;
3772 configurations
.m
[T55XX_DLMODE_FIXED
].write_1
= 47 * 8;
3773 configurations
.m
[T55XX_DLMODE_FIXED
].read_gap
= 15 * 8;
3774 configurations
.m
[T55XX_DLMODE_FIXED
].write_2
= 0;
3775 configurations
.m
[T55XX_DLMODE_FIXED
].write_3
= 0;
3777 // long leading reference
3778 configurations
.m
[T55XX_DLMODE_LLR
].start_gap
= 29 * 8;
3779 configurations
.m
[T55XX_DLMODE_LLR
].write_gap
= 17 * 8;
3780 configurations
.m
[T55XX_DLMODE_LLR
].write_0
= 15 * 8;
3781 configurations
.m
[T55XX_DLMODE_LLR
].write_1
= 47 * 8;
3782 configurations
.m
[T55XX_DLMODE_LLR
].read_gap
= 15 * 8;
3783 configurations
.m
[T55XX_DLMODE_LLR
].write_2
= 0;
3784 configurations
.m
[T55XX_DLMODE_LLR
].write_3
= 0;
3787 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].start_gap
= 29 * 8;
3788 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_gap
= 17 * 8;
3789 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_0
= 15 * 8;
3790 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_1
= 40 * 8;
3791 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].read_gap
= 15 * 8;
3792 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_2
= 0;
3793 configurations
.m
[T55XX_DLMODE_LEADING_ZERO
].write_3
= 0;
3795 // 1 of 4 coding reference
3796 configurations
.m
[T55XX_DLMODE_1OF4
].start_gap
= 29 * 8;
3797 configurations
.m
[T55XX_DLMODE_1OF4
].write_gap
= 17 * 8;
3798 configurations
.m
[T55XX_DLMODE_1OF4
].write_0
= 15 * 8;
3799 configurations
.m
[T55XX_DLMODE_1OF4
].write_1
= 31 * 8;
3800 configurations
.m
[T55XX_DLMODE_1OF4
].read_gap
= 15 * 8;
3801 configurations
.m
[T55XX_DLMODE_1OF4
].write_2
= 47 * 8;
3802 configurations
.m
[T55XX_DLMODE_1OF4
].write_3
= 63 * 8;
3805 configurations
.m
[downlink_mode
].start_gap
= startgap
* 8;
3806 configurations
.m
[downlink_mode
].write_gap
= writegap
* 8;
3807 configurations
.m
[downlink_mode
].write_0
= write0
* 8;
3808 configurations
.m
[downlink_mode
].write_1
= write1
* 8;
3809 configurations
.m
[downlink_mode
].read_gap
= readgap
* 8;
3810 configurations
.m
[downlink_mode
].write_2
= write2
* 8;
3811 configurations
.m
[downlink_mode
].write_3
= write3
* 8;
3814 clearCommandBuffer();
3815 SendCommandMIX(CMD_LF_T55XX_SET_CONFIG
, shall_persist
, 0, 0, &configurations
, sizeof(t55xx_configurations_t
));
3819 static int CmdT55xxProtect(const char *Cmd
) {
3821 CLIParserContext
*ctx
;
3822 CLIParserInit(&ctx
, "lf t55xx protect",
3823 "This command sets the pwd bit on T5577.\n"
3824 _RED_("WARNING") _CYAN_(" this locks the tag!"),
3825 "lf t55xx protect -n 01020304 -> sets new pwd 01020304\n"
3826 "lf t55xx protect -p 11223344 -n 00000000 -> use pwd 11223344, sets new pwd 00000000"
3829 // 1 (help) + 3 (three user specified params) + (5 T55XX_DLMODE_SINGLE)
3830 void *argtable
[4 + 5] = {
3832 arg_lit0("o", "override", "override safety check"),
3833 arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
3834 arg_str1("n", "new", "<hex>", "new password (4 hex bytes)"),
3837 arg_add_t55xx_downloadlink(argtable
, &idx
, T55XX_DLMODE_SINGLE
, config
.downlink_mode
);
3838 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3840 uint8_t override
= 0;
3841 if (arg_get_lit(ctx
, 1))
3844 uint32_t password
= 0;
3845 bool usepwd
= false;
3846 int res
= arg_get_u32_hexstr_def(ctx
, 2, 0, &password
);
3849 PrintAndLogEx(FAILED
, "Error parsing password bytes");
3851 } else if (res
== 1) {
3856 uint32_t new_password
= 0;
3857 res
= arg_get_u32_hexstr_def(ctx
, 3, 0, &new_password
);
3860 PrintAndLogEx(FAILED
, "Error parsing new password bytes");
3862 } else if (res
== 0) {
3863 PrintAndLogEx(FAILED
, "Must specify new password param");
3868 bool r0
= arg_get_lit(ctx
, 4);
3869 bool r1
= arg_get_lit(ctx
, 5);
3870 bool r2
= arg_get_lit(ctx
, 6);
3871 bool r3
= arg_get_lit(ctx
, 7);
3874 if ((r0
+ r1
+ r2
+ r3
) > 1) {
3875 PrintAndLogEx(FAILED
, "Error multiple downlink encoding");
3879 uint8_t downlink_mode
= config
.downlink_mode
;
3881 downlink_mode
= refFixedBit
;
3883 downlink_mode
= refLongLeading
;
3885 downlink_mode
= refLeading0
;
3887 downlink_mode
= ref1of4
;
3890 if (SanityOfflineCheck(false) != PM3_SUCCESS
)
3894 if (t55xxProtect(true, usepwd
, override
, password
, downlink_mode
, new_password
) == false) {
3895 PrintAndLogEx(WARNING
, "Command failed. Did you run " _YELLOW_("`lf t55xx detect`") " before?");
3901 // if the difference between a and b is less then or eq to d i.e. does a = b +/- d
3902 #define APPROX_EQ(a, b, d) ((abs(a - b) <= d) ? true : false)
3904 static uint8_t t55sniff_get_packet(int *pulseBuffer
, char *data
, uint8_t width0
, uint8_t width1
, uint8_t tolerance
) {
3909 while (ok
&& (i
< 73)) { // 70 bits max Fixed bit packet
3910 if (APPROX_EQ(width0
, pulseBuffer
[i
], tolerance
)) {
3915 if (APPROX_EQ(width1
, pulseBuffer
[i
], tolerance
)) {
3927 static uint8_t t55sniff_trim_samples(int *pulseBuffer
, int *pulseIdx
, uint8_t len
) {
3928 for (uint8_t i
= 0; i
< (80 - len
); i
++) {
3929 pulseBuffer
[i
] = pulseBuffer
[i
+ len
];
3936 static int CmdT55xxSniff(const char *Cmd
) {
3937 CLIParserContext
*ctx
;
3938 CLIParserInit(&ctx
, "lf t55xx sniff",
3939 "Sniff LF t55xx based trafic and decode possible cmd / blocks.\n"
3940 "Lower tolerance means tighter pulses. ",
3942 "lf t55xx sniff -1 -t 2 -> use buffer with tolerance of 2\n"
3943 "lf t55xx sniff -1 --zero 7 --one 14 -> use buffer, zero pulse width 7, one pulse width 15"
3946 void *argtable
[] = {
3948 arg_lit0("1", NULL
, "extract using data from graphbuffer"),
3949 arg_int0("t", "tol", "<dec>", "set tolerance level (default 5)"),
3950 // arg_int0(NULL, "signal", "<dec>", "set minimum signal level (default 20)"),
3951 arg_int0("o", "one", "<dec>", "set samples width for ONE pulse (default auto)"),
3952 arg_int0("z", "zero", "<dec>", "set samples width for ZERO pulse (default auto)"),
3955 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3956 bool use_graphbuf
= arg_get_lit(ctx
, 1);
3957 uint8_t tolerance
= arg_get_int_def(ctx
, 2, 5);
3958 int opt_width1
= arg_get_int_def(ctx
, 3, -1);
3959 int opt_width0
= arg_get_int_def(ctx
, 4, -1);
3962 if (opt_width0
== 0) {
3963 PrintAndLogEx(ERR
, "Must call with --zero larger than 0");
3966 if (opt_width1
== 0) {
3967 PrintAndLogEx(ERR
, "Must call with --one larger than 0");
3971 if (opt_width0
> 0 && opt_width1
== -1) {
3972 PrintAndLogEx(ERR
, _RED_("Missing sample width for ONE"));
3976 if (opt_width1
> 0 && opt_width0
== -1) {
3977 PrintAndLogEx(ERR
, _RED_("Missing sample width for ZERO"));
3984 if (opt_width0
> -1)
3985 width0
= (uint8_t)opt_width0
& 0xFF;
3987 if (opt_width1
> -1)
3988 width1
= (uint8_t)opt_width1
& 0xFF;
3994 T55xx packet lengths (1 of 4 needs to be checked)
3995 -----------------------------------------------
3996 | Default | LL 0 | Leading 0 | 1 of 4 |
3997 ----------------------------------------------------------------|
3998 | Standard Write | 38 | 39 | 39 | 40 |
3999 | Protect Write | 70 | 71 | 73 | 74 |
4000 | AOR | 34 | 35 | 37 | 38 |
4001 | Standard Read | 5 | 6 | 7 | 8 |
4002 | Protect Read | 38 | 39 | 41 | 42 |
4003 | Regular Read | 2 | 3 | 3 | 4 |
4004 | Reset | 2 | 3 | 3 | 4 |
4005 ----------------------------------------------------------------
4007 T55xx bit widths (decimation 1) - Expected, but may vary a little
4008 Reference 0 for LL0 and Leading 0 can be longer
4009 -----------------------------------------------
4010 | Default | LL 0 | Leading 0 | 1 of 4 |
4011 ----------------------------------------------------|
4012 | 0 | 16 - 32 | 9 - 33 | 5 - 80 | tbc |
4013 | 1 | 48 - 64 | 41 - 72 | 21 - 96 | tbc |
4014 ----------------------------------------------------
4018 uint8_t page
, blockAddr
;
4020 uint32_t usedPassword
, blockData
;
4021 int pulseSamples
= 0, pulseIdx
= 0;
4025 int pulseBuffer
[80] = { 0 }; // max should be 73 +/- - Holds Pulse widths
4026 char data
[80]; // linked to pulseBuffer. - Holds 0/1 from pulse widths
4028 // setup and sample data from Proxmark
4029 // if not directed to existing sample/graphbuffer
4030 if (use_graphbuf
== false) {
4035 PrintAndLogEx(NORMAL
, "");
4036 PrintAndLogEx(INFO
, _CYAN_("T55xx command detection"));
4037 PrintAndLogEx(SUCCESS
, "Downlink mode | password | Data | blk | page | 0 | 1 | raw");
4038 PrintAndLogEx(SUCCESS
, "----------------------+----------+----------+-----+------+-----+-----+-------------------------------------------------------------------------------");
4041 // loop though sample buffer
4042 while (idx
< GraphTraceLen
) {
4044 int minWidth
= 1000;
4046 uint16_t dataLen
= 0;
4048 bool have_data
= false;
4049 sprintf(modeText
, "Default");
4050 sprintf(pwdText
, " ");
4051 sprintf(dataText
, " ");
4053 if (pulseSamples
== 0) {
4058 while ((idx
< GraphTraceLen
) && (GraphBuffer
[idx
] < 0)) {
4062 // count high samples
4064 while ((idx
< GraphTraceLen
) && (GraphBuffer
[idx
] > 0)) { // last bit seems to be high to zero, but can vary in width..
4069 if (pulseSamples
> 0) {
4070 pulseBuffer
[pulseIdx
++] = pulseSamples
;
4071 if (pulseIdx
> 79) { // make room for next sample - if not used by now, it wont be.
4072 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 1);
4075 // Check Samples for valid packets;
4076 // We should find (outside of leading bits) we have a packet of "1" and "0" at same widths.
4077 if (pulseIdx
>= 6) {// min size for a read - ignoring 1of4 10 0 <adr>
4079 // We auto find widths
4080 if ((width0
== 0) && (width1
== 0)) {
4081 // We ignore bit 0 for the moment as it may be a ref. pulse, so check last
4083 minWidth
= pulseBuffer
[1];
4084 maxWidth
= pulseBuffer
[1];
4087 while ((!done
) && (ii
< pulseIdx
) && ((maxWidth
<= minWidth
) || (APPROX_EQ(minWidth
, maxWidth
, tolerance
)))) { // min should be 8, 16-32 more normal
4088 if (pulseBuffer
[ii
] + 3 < minWidth
) {
4089 minWidth
= pulseBuffer
[ii
];
4092 if (pulseBuffer
[ii
] - 1 > maxWidth
) {
4093 maxWidth
= pulseBuffer
[ii
];
4104 // out of bounds... min max far enough appart and minWidth is large enough
4105 if (((maxWidth
- minWidth
) < 6) || (minWidth
< 6)) // min 8 +/-
4108 // At this point we should have
4109 // - a min of 6 samples
4110 // - the 0 and 1 sample widths
4111 // - min 0 and min seperations (worst case)
4112 // No max checks done (yet) as have seen samples > then specs in use.
4117 if (have_data
== false && (APPROX_EQ(pulseBuffer
[0], 136 + minWidth
, tolerance
) && APPROX_EQ(pulseBuffer
[1], maxWidth
, tolerance
))) {
4118 // printf ("Long Leading 0 - not yet hanled | have 1 Fisrt bit | Min : %-3d - Max : %-3d : diff : %d\n",minWidth,maxWidth, maxWidth-minWidth);
4122 // Fixed bit - Default
4123 if (have_data
== false && (APPROX_EQ(pulseBuffer
[0], maxWidth
, tolerance
))) {
4124 dataLen
= t55sniff_get_packet(pulseBuffer
, data
, minWidth
, maxWidth
, tolerance
);
4126 // if ((dataLen == 39) )
4127 // printf ("Fixed | Data end of 80 samples | offset : %llu - datalen %-2d - data : %s --- - Bit 0 width : %d\n",idx,dataLen,data,pulseBuffer[0]);
4129 if (data
[0] == '0') { // should never get here..
4135 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 4); // left 1 or 2 samples seemed to help
4137 page
= data
[1] - '0';
4139 for (uint8_t i
= 3; i
< 6; i
++) {
4146 sprintf(modeText
, "Default Read");
4150 if (dataLen
== 70) {
4151 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 70);
4153 page
= data
[1] - '0';
4155 for (uint8_t i
= 2; i
<= 33; i
++) {
4162 for (uint8_t i
= 35; i
<= 66; i
++) {
4168 for (uint8_t i
= 67; i
<= 69; i
++) {
4174 sprintf(modeText
, "Default pwd write");
4175 sprintf(pwdText
, "%08X", usedPassword
);
4176 sprintf(dataText
, "%08X", blockData
);
4179 // Default Write (or password read ??)
4180 if (dataLen
== 38) {
4181 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 38);
4183 page
= data
[1] - '0';
4186 for (uint8_t i
= 3; i
<= 34; i
++) {
4192 for (uint8_t i
= 35; i
<= 37; i
++) {
4198 sprintf(modeText
, "Default write");
4199 sprintf(dataText
, "%08X", blockData
);
4205 if (have_data
== false && (APPROX_EQ(pulseBuffer
[0], minWidth
, tolerance
))) {
4206 // leading 0 (should = 0 width)
4207 // 1 of 4 (leads with 00)
4208 dataLen
= t55sniff_get_packet(pulseBuffer
, data
, minWidth
, maxWidth
, tolerance
);
4209 // **** Should check to 0 to be actual 0 as well i.e. 01 .... data ....
4210 if ((data
[0] == '0') && (data
[1] == '1')) {
4211 if (dataLen
== 73) {
4212 t55sniff_trim_samples(pulseBuffer
, &pulseIdx
, 73);
4214 page
= data
[2] - '0';
4216 for (uint8_t i
= 5; i
<= 36; i
++) {
4222 for (uint8_t i
= 38; i
<= 69; i
++) {
4228 for (uint8_t i
= 70; i
<= 72; i
++) {
4234 sprintf(modeText
, "Leading 0 pwd write");
4235 sprintf(pwdText
, "%08X", usedPassword
);
4236 sprintf(dataText
, "%08X", blockData
);
4245 PrintAndLogEx(SUCCESS
, "%-20s | "_GREEN_("%8s")" | "_YELLOW_("%8s")" | "_YELLOW_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s", modeText
, pwdText
, dataText
, blockAddr
, page
, minWidth
, maxWidth
, data
);
4247 PrintAndLogEx(SUCCESS
, "%-20s | "_GREEN_("%8s")" | "_GREEN_("%8s")" | "_GREEN_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s", modeText
, pwdText
, dataText
, blockAddr
, page
, minWidth
, maxWidth
, data
);
4252 PrintAndLogEx(SUCCESS
, "-----------------------------------------------------------------------------------------------------------------------------------------------------");
4253 PrintAndLogEx(NORMAL
, "");
4257 static command_t CommandTable
[] = {
4258 {"-----------", CmdHelp
, AlwaysAvailable
, "---------------------------- " _CYAN_("notice") " -----------------------------"},
4259 {"", CmdHelp
, AlwaysAvailable
, "Remember to run `" _YELLOW_("lf t55xx detect") "` first whenever a new card"},
4260 {"", CmdHelp
, AlwaysAvailable
, "is placed on the Proxmark3 or the config block changed."},
4261 {"", CmdHelp
, AlwaysAvailable
, ""},
4262 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
4263 {"-----------", CmdHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("operations") " ---------------------"},
4264 {"clonehelp", CmdT55xxCloneHelp
, IfPm3Lf
, "Shows the available clone commands"},
4265 {"config", CmdT55xxSetConfig
, AlwaysAvailable
, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
4266 {"dangerraw", CmdT55xxDangerousRaw
, IfPm3Lf
, "Sends raw bitstream. Dangerous, do not use!!"},
4267 {"detect", CmdT55xxDetect
, AlwaysAvailable
, "Try detecting the tag modulation from reading the configuration block"},
4268 {"deviceconfig", CmdT55xxSetDeviceConfig
, IfPm3Lf
, "Set/Get T55XX device configuration"},
4269 {"dump", CmdT55xxDump
, IfPm3Lf
, "Dump T55xx card Page 0 block 0-7"},
4270 {"info", CmdT55xxInfo
, AlwaysAvailable
, "Show T55x7 configuration data (page 0/ blk 0)"},
4271 {"p1detect", CmdT55xxDetectPage1
, IfPm3Lf
, "Try detecting if this is a t55xx tag by reading page 1"},
4272 {"read", CmdT55xxReadBlock
, IfPm3Lf
, "Read T55xx block data"},
4273 {"resetread", CmdResetRead
, IfPm3Lf
, "Send Reset Cmd then lf read the stream to attempt to identify the start of it"},
4274 {"restore", CmdT55xxRestore
, IfPm3Lf
, "Restore T55xx card Page 0 / Page 1 blocks"},
4275 {"trace", CmdT55xxReadTrace
, AlwaysAvailable
, "Show T55x7 traceability data (page 1/ blk 0-1)"},
4276 {"wakeup", CmdT55xxWakeUp
, IfPm3Lf
, "Send AOR wakeup command"},
4277 {"write", CmdT55xxWriteBlock
, IfPm3Lf
, "Write T55xx block data"},
4278 {"-----------", CmdHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("recovery") " ---------------------"},
4279 {"bruteforce", CmdT55xxBruteForce
, IfPm3Lf
, "Simple bruteforce attack to find password"},
4280 {"chk", CmdT55xxChkPwds
, IfPm3Lf
, "Check passwords from dictionary/flash"},
4281 {"protect", CmdT55xxProtect
, IfPm3Lf
, "Password protect tag"},
4282 {"recoverpw", CmdT55xxRecoverPW
, IfPm3Lf
, "Try to recover from bad password write from a cloner"},
4283 {"sniff", CmdT55xxSniff
, AlwaysAvailable
, "Attempt to recover T55xx commands from sample buffer"},
4284 {"special", CmdT55xxSpecial
, IfPm3Lf
, "Show block changes with 64 different offsets"},
4285 {"wipe", CmdT55xxWipe
, IfPm3Lf
, "Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
4286 {NULL
, NULL
, NULL
, NULL
}
4289 static int CmdHelp(const char *Cmd
) {
4290 (void)Cmd
; // Cmd is not used so far
4291 CmdsHelp(CommandTable
);
4295 int CmdLFT55XX(const char *Cmd
) {
4296 clearCommandBuffer();
4297 return CmdsParse(CommandTable
, Cmd
);