mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
Added T55 downlink mode support
This commit is contained in:
parent
9a1c0ff8a8
commit
4e0e69ed63
8 changed files with 1017 additions and 415 deletions
|
@ -293,6 +293,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (@merlokk)
|
||||
- Added trailer block decoding to `hf mf rdbl` and `hf mf cgetbl` (@merlokk)
|
||||
- Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk)
|
||||
- Added T55x7 downlink mode support r <mode> 0 Default, 1 Long Leading 0, 2 Leading 0, 3 1 of 4 and 4 (in some commands) try all.
|
||||
|
||||
### Fixed
|
||||
- Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi)
|
||||
|
|
|
@ -876,9 +876,10 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
uint8_t blockno;
|
||||
uint8_t page;
|
||||
bool pwdmode;
|
||||
uint8_t downlink_mode;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
T55xxReadBlock(payload->page, payload->pwdmode, false, payload->blockno, payload->password);
|
||||
T55xxReadBlock(payload->page, payload->pwdmode, false, payload->blockno, payload->password,payload->downlink_mode);
|
||||
break;
|
||||
}
|
||||
case CMD_T55XX_WRITE_BLOCK: {
|
||||
|
@ -887,15 +888,15 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_T55XX_WAKEUP: {
|
||||
T55xxWakeUp(packet->oldarg[0]);
|
||||
T55xxWakeUp(packet->oldarg[0],packet->oldarg[1]);
|
||||
break;
|
||||
}
|
||||
case CMD_T55XX_RESET_READ: {
|
||||
T55xxResetRead();
|
||||
T55xxResetRead(packet->data.asBytes[0]&0xff);
|
||||
break;
|
||||
}
|
||||
case CMD_T55XX_CHKPWDS: {
|
||||
T55xx_ChkPwds();
|
||||
T55xx_ChkPwds(packet->data.asBytes[0]&0xff);
|
||||
break;
|
||||
}
|
||||
case CMD_PCF7931_READ: {
|
||||
|
|
|
@ -102,12 +102,13 @@ void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5);
|
|||
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
|
||||
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
|
||||
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
|
||||
void T55xxResetRead(void);
|
||||
void T55xxResetRead(uint8_t flags);
|
||||
//id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
|
||||
void T55xxWriteBlock(uint8_t *data);
|
||||
void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
|
||||
void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd);
|
||||
void T55xxWakeUp(uint32_t Pwd);
|
||||
void T55xx_ChkPwds(void);
|
||||
// void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
|
||||
void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd,uint8_t downlink_mode);
|
||||
void T55xxWakeUp(uint32_t Pwd, uint8_t flags);
|
||||
void T55xx_ChkPwds(uint8_t flags);
|
||||
|
||||
void TurnReadLFOn(uint32_t delay);
|
||||
|
||||
|
|
576
armsrc/lfops.c
576
armsrc/lfops.c
|
@ -46,31 +46,133 @@
|
|||
// = 1us = 1.5ticks
|
||||
// 1fc = 8us = 12ticks
|
||||
/*
|
||||
Default LF T55xx config is set to:
|
||||
startgap = 31*8
|
||||
writegap = 17*8
|
||||
write_0 = 15*8
|
||||
write_1 = 47*8
|
||||
read_gap = 15*8
|
||||
==========================================================================================================
|
||||
T55x7 Timing
|
||||
==========================================================================================================
|
||||
|
||||
// t55xx_config t_config = { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8 } ;
|
||||
|
||||
ATA5577 Downlink Protocol Timings.
|
||||
Note: All absolute times assume TC = 1 / fC = 8 μs (fC = 125 kHz)
|
||||
-----------------------------------------------------------------------
|
||||
Fixed-bit-length Protocol | Normal Downlink | Fast Downlink |
|
||||
------------------------------+-----------------------------------+-----------------------------------+------
|
||||
| Parameter | Remark | Symbol | Min. | Typ. | Max. | Min. | Typ. | Max. | Unit |
|
||||
|------------+--------+--------+-----------+-----------+-----------+-----------+-----------+-----------+------|
|
||||
| Start gap | | Sgap | 8 | 15 | 50 | 8 | 15 | 50 | Tc |
|
||||
| Write gap | | Wgap | 8 | 10 | 20 | 8 | 10 | 20 | Tc |
|
||||
|------------+--------+--------+-----------+-----------+-----------+-----------+-----------+-----------+------|
|
||||
| coding | 0 data | d0 | 16 | 24 | 32 | 8 | 12 | 16 | Tc |
|
||||
| | 1 data | d1 | 48 | 56 | 64 | 24 | 28 | 32 | Tc |
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Long Leading Reference | Normal Downlink | Fast Downlink |
|
||||
------------------------------+-----------------------------------+-----------------------------------+------
|
||||
| Parameter | Remark | Symbol | Min. | Typ. | Max. | Min. | Typ. | Max. | Unit |
|
||||
|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
|
||||
| Start gap | | Sgap | 8 | 10 | 50 | 8 | 10 | 50 | Tc |
|
||||
| Write gap | | Wgap | 8 | 10 | 20 | 8 | 10 | 20 | Tc |
|
||||
|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
|
||||
| Write | Ref | | 152 | 160 | 168 | 140 | 144 | 148 | Tc |
|
||||
| data | Pulse | dref | 136 clocks + 0 data bit | 132 clocks + 0 data bit | Tc |
|
||||
| coding |--------+---------+-----------------------------------+-----------------------------------+------|
|
||||
| | 0 data | d0 |dref – 143 |dref – 136 |dref – 128 |dref – 135 |dref – 132 |dref – 124 | Tc |
|
||||
| | 1 data | d1 |dref – 111 |dref – 104 |dref – 96 |dref – 119 |dref – 116 |dref – 112 | Tc |
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Leading-zero Reference | Normal Downlink | Fast Downlink |
|
||||
------------------------------+-----------------------------------+-----------------------------------+------
|
||||
| Parameter | Remark | Symbol | Min. | Typ. | Max. | Min. | Typ. | Max. | Unit |
|
||||
|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
|
||||
| Start gap | | Sgap | 8 | 10 | 50 | 8 | 10 | 50 | Tc |
|
||||
| Write gap | | Wgap | 8 | 10 | 20 | 8 | 10 | 20 | Tc |
|
||||
|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
|
||||
| Write | Ref | dref | 12 | – | 72 | 8 | – | 68 | Tc |
|
||||
| data | 0 data | d0 | dref – 7 | dref | dref + 8 | dref – 3 | dref | dref + 4 | Tc |
|
||||
| coding | 1 data | d1 | dref + 9 | dref + 16 | dref + 24 | dref + 5 | dref + 8 | dref + 12 | Tc |
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
1-of-4 Coding | Normal Downlink | Fast Downlink |
|
||||
------------------------------+-----------------------------------+-----------------------------------+------
|
||||
| Parameter | Remark | Symbol | Min. | Typ. | Max. | Min. | Typ. | Max. | Unit |
|
||||
|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
|
||||
| Start gap | | Sgap | 8 | 10 | 50 | 8 | 10 | 50 | Tc |
|
||||
| Write gap | | Wgap | 8 | 10 | 20 | 8 | 10 | 20 | Tc |
|
||||
|-----------+--------+---------+-----------+-----------+-----------+-----------+-----------+-----------+------|
|
||||
| Write | Ref 00 | dref | 8 | – | 68 | 12 | – | 72 | Tc |
|
||||
| data |00 data | d00 | dref – 7 | dref | dref + 8 | dref – 3 | dref | dref+ 4 | Tc |
|
||||
| coding |01 data | d01 | dref + 9 | dref + 16 | dref + 24 | dref + 5 | dref + 8 | dref + 12 | Tc |
|
||||
| |10 data | d10 | dref + 25 | dref + 32 | dref + 40 | dref + 13 | dref + 16 | dref + 20 | Tc |
|
||||
| |11 data | d11 | dref + 41 | dref + 48 | dref + 56 | dref + 21 | dref + 24 | dref + 28 | Tc |
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
t55xx_config t_config = { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8 } ;
|
||||
// Initial values if not in flash
|
||||
// Note: Moved * 8 to apply when used. Saving 28 bytes here (- the *8) and 28 bytes flash.
|
||||
// StartGap WriteGap Bit 0/00 Bit 1/01 Bit 10 Bit 11 ReadGap
|
||||
t55xx_config T55xx_Timing = {{{ 29 , 17 , 15 , 50 , 0 , 0 , 15 }, // Default Fixed
|
||||
{ 31 , 20 , 18 , 50 , 0 , 0 , 15 }, // Long Leading Ref.
|
||||
{ 31 , 20 , 18 , 40 , 0 , 0 , 15 }, // Leading 0
|
||||
{ 29 , 17 , 15 , 31 , 47 , 63 , 15 } }}; // 1 of 4
|
||||
/*
|
||||
// StartGap WriteGap Bit 0/00 Bit 1/01 Bit 10 Bit 11 ReadGap
|
||||
t55xx_config T55xx_Timing = {{{ 29 * 8 , 17 * 8 , 15 * 8 , 50 * 8 , 0 , 0 , 15 * 8 }, // Default Fixed
|
||||
{ 31 * 8 , 20 * 8 , 18 * 8 , 50 * 8 , 0 , 0 , 15 * 8 }, // Long Leading Ref.
|
||||
{ 31 * 8 , 20 * 8 , 18 * 8 , 40 * 8 , 0 , 0 , 15 * 8 }, // Leading 0
|
||||
{ 29 * 8 , 17 * 8 , 15 * 8 , 31 * 8 , 47 * 8, 63 * 8, 15 * 8 } }}; // 1 of 4
|
||||
*/
|
||||
|
||||
// Some defines for readability
|
||||
#define T55xx_DLMode_Fixed 0 // Default Mode
|
||||
#define T55xx_DLMode_LLR 1 // Long Leading Reference
|
||||
#define T55xx_DLMode_Leading0 2 // Leading Zero
|
||||
#define T55xx_DLMode_1of4 3 // 1 of 4
|
||||
#define T55xx_LongLeadingReference 4 // Value to tell Write Bit to send long reference
|
||||
|
||||
void printT55xxConfig(void) {
|
||||
int DLMode;
|
||||
|
||||
DbpString(_BLUE_("LF T55XX config"));
|
||||
Dbprintf(" [a] startgap............%d*8 (%d)", t_config.start_gap / 8, t_config.start_gap);
|
||||
Dbprintf(" [b] writegap............%d*8 (%d)", t_config.write_gap / 8, t_config.write_gap);
|
||||
Dbprintf(" [c] write_0.............%d*8 (%d)", t_config.write_0 / 8, t_config.write_0);
|
||||
Dbprintf(" [d] write_1.............%d*8 (%d)", t_config.write_1 / 8, t_config.write_1);
|
||||
Dbprintf(" [e] readgap.............%d*8 (%d)", t_config.read_gap / 8, t_config.read_gap);
|
||||
for (DLMode = 0; DLMode < 4; DLMode++) {
|
||||
switch (DLMode){
|
||||
case T55xx_DLMode_Fixed : Dbprintf("r 0 fixed bit length (default)"); break;
|
||||
case T55xx_DLMode_LLR : Dbprintf("r 1 long leading reference"); break;
|
||||
case T55xx_DLMode_Leading0 : Dbprintf("r 2 leading zero"); break;
|
||||
case T55xx_DLMode_1of4 : Dbprintf("r 3 1 of 4 coding reference"); break;
|
||||
}
|
||||
// Save 36 bytes by not showing dec. all data sheets and entry is the x * 8 value, so not sure what we get for the 36 bytes dec?
|
||||
Dbprintf(" [a] startgap............%d*8", T55xx_Timing.m[DLMode].start_gap );//, T55xx_Timing.start_gap[DLMode]);
|
||||
Dbprintf(" [b] writegap............%d*8", T55xx_Timing.m[DLMode].write_gap );//, T55xx_Timing.write_gap[DLMode]);
|
||||
Dbprintf(" [c] write_0.............%d*8", T55xx_Timing.m[DLMode].write_0 );//, T55xx_Timing.write_0 [DLMode]);
|
||||
Dbprintf(" [d] write_1.............%d*8", T55xx_Timing.m[DLMode].write_1 );//, T55xx_Timing.write_1 [DLMode]);
|
||||
if (DLMode == T55xx_DLMode_1of4) {
|
||||
Dbprintf(" [e] write_2.............%d*8", T55xx_Timing.m[DLMode].write_2 );//, T55xx_Timing.write_2 [DLMode]);
|
||||
Dbprintf(" [f] write_3.............%d*8", T55xx_Timing.m[DLMode].write_3 );//, T55xx_Timing.write_3 [DLMode]);
|
||||
}
|
||||
Dbprintf(" [g] readgap.............%d*8", T55xx_Timing.m[DLMode].read_gap );//, T55xx_Timing.read_gap [DLMode]);
|
||||
}
|
||||
}
|
||||
|
||||
void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
|
||||
uint8_t DLMode;
|
||||
|
||||
if (c->start_gap != 0) t_config.start_gap = c->start_gap;
|
||||
if (c->write_gap != 0) t_config.write_gap = c->write_gap;
|
||||
if (c->write_0 != 0) t_config.write_0 = c->write_0;
|
||||
if (c->write_1 != 0) t_config.write_1 = c->write_1;
|
||||
if (c->read_gap != 0) t_config.read_gap = c->read_gap;
|
||||
for (DLMode = 0; DLMode < 4; DLMode++) {
|
||||
if (c->m[DLMode].start_gap != 0) T55xx_Timing.m[DLMode].start_gap = c->m[DLMode].start_gap;
|
||||
if (c->m[DLMode].write_gap != 0) T55xx_Timing.m[DLMode].write_gap = c->m[DLMode].write_gap;
|
||||
if (c->m[DLMode].write_0 != 0) T55xx_Timing.m[DLMode].write_0 = c->m[DLMode].write_0 ;
|
||||
if (c->m[DLMode].write_1 != 0) T55xx_Timing.m[DLMode].write_1 = c->m[DLMode].write_1 ;
|
||||
if (DLMode == T55xx_DLMode_1of4) {
|
||||
if (c->m[DLMode].write_2 != 0) T55xx_Timing.m[DLMode].write_2 = c->m[DLMode].write_2 ;
|
||||
if (c->m[DLMode].write_3 != 0) T55xx_Timing.m[DLMode].write_3 = c->m[DLMode].write_3 ;
|
||||
}
|
||||
else{
|
||||
T55xx_Timing.m[DLMode].write_2 = 0x00;
|
||||
T55xx_Timing.m[DLMode].write_3 = 0x00;
|
||||
}
|
||||
if (c->m[DLMode].read_gap != 0) T55xx_Timing.m[DLMode].read_gap = c->m[DLMode].read_gap ;
|
||||
}
|
||||
|
||||
printT55xxConfig();
|
||||
|
||||
|
@ -93,27 +195,32 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
|
|||
return;
|
||||
}
|
||||
|
||||
memcpy(buf, &t_config, T55XX_CONFIG_LEN);
|
||||
memcpy(buf, &T55xx_Timing, T55XX_CONFIG_LEN);
|
||||
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable();
|
||||
Flash_Erase4k(3, 0xD);
|
||||
|
||||
// if not a settings erase, write data
|
||||
if (buf[0] != 0xff) {
|
||||
res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
|
||||
|
||||
if (res == T55XX_CONFIG_LEN && DBGLEVEL > 1) {
|
||||
DbpString("T55XX Config save success");
|
||||
}
|
||||
}
|
||||
|
||||
BigBuf_free();
|
||||
#endif
|
||||
}
|
||||
|
||||
t55xx_config *getT55xxConfig(void) {
|
||||
return &t_config;
|
||||
return &T55xx_Timing;//_FixedBit;
|
||||
}
|
||||
|
||||
void loadT55xxConfig(void) {
|
||||
#ifdef WITH_FLASH
|
||||
|
||||
if (!FlashInit()) {
|
||||
return;
|
||||
}
|
||||
|
@ -135,7 +242,7 @@ void loadT55xxConfig(void) {
|
|||
return;
|
||||
}
|
||||
|
||||
memcpy((uint8_t *)&t_config, buf, T55XX_CONFIG_LEN);
|
||||
memcpy((uint8_t *)&T55xx_Timing, buf, T55XX_CONFIG_LEN);
|
||||
|
||||
if (isok == T55XX_CONFIG_LEN) {
|
||||
if (DBGLEVEL > 1) DbpString("T55XX Config load success");
|
||||
|
@ -1354,36 +1461,178 @@ void TurnReadLF_off(uint32_t delay) {
|
|||
WaitUS(delay);
|
||||
}
|
||||
|
||||
// Write one bit to card
|
||||
void T55xxWriteBit(int bit) {
|
||||
if (!bit)
|
||||
TurnReadLFOn(t_config.write_0);
|
||||
else
|
||||
TurnReadLFOn(t_config.write_1);
|
||||
// Macro for code readability
|
||||
#define BitStream_Byte(X) ((X) >> 3)
|
||||
#define BitStream_Bit(X) ((X) & 7)
|
||||
#define t55_send_PwdMode (arg & 0x01)
|
||||
#define t55_send_Page ((arg & 0x02) >> 1)
|
||||
#define t55_send_TestMode ((arg & 0x04) >> 2)
|
||||
#define t55_send_RegReadMode ((arg & 0x20) >> 5)
|
||||
#define t55_send_ReadCmd ((arg & 0x40) >> 6)
|
||||
#define t55_send_Reset ((arg & 0x80) >> 7)
|
||||
|
||||
// Write one bit to chip
|
||||
void T55xxWriteBit(uint8_t bit, uint8_t downlink_idx) {
|
||||
|
||||
// Dbprintf ("%d",bit);
|
||||
// If bit = 4 Send Long Leading Reference which is (138*8) + WRITE_0
|
||||
switch (bit){
|
||||
case 0 : TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_0 * 8); break; // Send bit 0/00
|
||||
case 1 : TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_1 * 8); break; // Send bit 1/01
|
||||
case 2 : TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_2 * 8); break; // Send bits 10 (1 of 4)
|
||||
case 3 : TurnReadLFOn(T55xx_Timing.m[downlink_idx].write_3 * 8); break; // Send bits 11 (1 of 4)
|
||||
case 4 : TurnReadLFOn((T55xx_Timing.m[downlink_idx].write_0 + 136) * 8); break; // Send Long Leading Reference
|
||||
}
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitUS(t_config.write_gap);
|
||||
WaitUS(T55xx_Timing.m[downlink_idx].write_gap * 8);
|
||||
}
|
||||
|
||||
// Send T5577 reset command then read stream (see if we can identify the start of the stream)
|
||||
void T55xxResetRead(void) {
|
||||
LED_A_ON();
|
||||
//clear buffer now so it does not interfere with timing later
|
||||
BigBuf_Clear_keep_EM();
|
||||
// Function to abstract an Arbitrary length byte array to store bit pattern.
|
||||
// bit_array - Array to hold data/bit pattern
|
||||
// start_offset - bit location to start storing new bits.
|
||||
// data - upto 32 bits of data to store
|
||||
// num_bits - how many bits (low x bits of data) Max 32 bits at a time
|
||||
// max_len - how many bytes can the bit_array hold (ensure no buffer overflow)
|
||||
// returns "Next" bit offset / bits stored (for next store)
|
||||
uint8_t T55xx_SetBits (uint8_t *BitStream, uint8_t start_offset, uint32_t data , uint8_t num_bits, uint8_t max_len)
|
||||
{
|
||||
int8_t offset;
|
||||
int8_t NextOffset = start_offset;
|
||||
|
||||
// Check if data will fit.
|
||||
if ((start_offset + num_bits) <= (max_len*8)) {
|
||||
// Loop through the data and store
|
||||
for (offset = (num_bits-1); offset >= 0; offset--) {
|
||||
|
||||
if ((data >> offset) & 1) BitStream[BitStream_Byte(NextOffset)] |= (1 << BitStream_Bit(NextOffset)); // Set the bit to 1
|
||||
else BitStream[BitStream_Byte(NextOffset)] &= (0xff ^ (1 << BitStream_Bit(NextOffset))); // Set the bit to 0
|
||||
|
||||
NextOffset++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Note: This should never happen unless some code changes cause it.
|
||||
// So short message for coders when testing.
|
||||
Dbprintf ("T55 too many bits");
|
||||
}
|
||||
return NextOffset;
|
||||
}
|
||||
|
||||
// Send one downlink command to the card
|
||||
// void T55xx_SendCMD (uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) {
|
||||
void T55xx_SendCMD (uint32_t Data, uint32_t Pwd, uint16_t arg) {
|
||||
|
||||
/*
|
||||
arg bits
|
||||
xxxx xxxxxxx1 0x001 PwdMode
|
||||
xxxx xxxxxx1x 0x002 Page
|
||||
xxxx xxxxx1xx 0x004 testMode
|
||||
xxxx xxx11xxx 0x018 downlink mode
|
||||
xxxx xx1xxxxx 0x020 !reg_readmode
|
||||
xxxx x1xxxxxx 0x040 called for a read, so no data packet
|
||||
xxxx 1xxxxxxx 0x080 reset
|
||||
xxx1 xxxxxxxx 0x100 brute force
|
||||
111x xxxxxxxx 0xE00 Block
|
||||
|
||||
*/
|
||||
|
||||
uint8_t downlink_mode = (arg >> 3) & 0x03;
|
||||
uint8_t i = 0;
|
||||
uint8_t BitStream[10]; // Max Downlink Command size ~74 bits, so 10 bytes (80 bits)
|
||||
uint8_t BitStreamLen = 0;
|
||||
uint8_t SendBits;
|
||||
uint8_t start_wait = 4;
|
||||
bool brute_mem = (arg & 0x100);
|
||||
uint8_t Block = (arg >> 9) & 0x07;
|
||||
|
||||
if (brute_mem) start_wait = 0;
|
||||
|
||||
// Build Bit Stream to send.
|
||||
memset (BitStream,0x00,sizeof(BitStream));
|
||||
|
||||
BitStreamLen = 0; // Ensure 0 bit index to start.
|
||||
|
||||
// Add Leading 0 and 1 of 4 reference bit
|
||||
if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4))
|
||||
BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream));
|
||||
|
||||
// Add extra reference 0 for 1 of 4
|
||||
if (downlink_mode == T55xx_DLMode_1of4)
|
||||
BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream));
|
||||
|
||||
// Add Opcode
|
||||
if (t55_send_Reset) {
|
||||
// Reset : r*) 00
|
||||
BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 2,sizeof(BitStream));
|
||||
}
|
||||
else {
|
||||
if (t55_send_TestMode) Dbprintf("TestMODE");
|
||||
BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,t55_send_TestMode ? 0 : 1 , 1,sizeof(BitStream));
|
||||
BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,t55_send_TestMode ? 1 : t55_send_Page , 1,sizeof(BitStream));
|
||||
//if (PwdMode) {
|
||||
if (t55_send_PwdMode) {
|
||||
// Leading 0 and 1 of 4 00 fixed bits if passsword used
|
||||
if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) {
|
||||
BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 2,sizeof(BitStream));
|
||||
}
|
||||
BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream));
|
||||
}
|
||||
|
||||
// Add Lock bit 0
|
||||
if (!t55_send_RegReadMode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream));
|
||||
|
||||
// Add Data if a write command
|
||||
if (!t55_send_ReadCmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream));
|
||||
|
||||
// Add Address
|
||||
if (!t55_send_RegReadMode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream));
|
||||
}
|
||||
|
||||
// Send Bits to T55xx
|
||||
// Set up FPGA, 125kHz
|
||||
LFSetupFPGAForADC(95, true);
|
||||
|
||||
// make sure tag is fully powered up...
|
||||
WaitMS(4);
|
||||
WaitMS(start_wait);
|
||||
|
||||
// Trigger T55x7 in mode.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitUS(t_config.start_gap);
|
||||
WaitUS(T55xx_Timing.m[downlink_mode].start_gap * 8);
|
||||
|
||||
// reset tag - op code 00
|
||||
T55xxWriteBit(0);
|
||||
T55xxWriteBit(0);
|
||||
// If long leading 0 send long reference pulse
|
||||
if (downlink_mode == T55xx_DLMode_LLR)
|
||||
T55xxWriteBit (T55xx_LongLeadingReference,downlink_mode);//Timing); // Send Long Leading Start Reference
|
||||
|
||||
TurnReadLFOn(t_config.read_gap);
|
||||
if ((downlink_mode == T55xx_DLMode_1of4) && (BitStreamLen > 0)) { // 1 of 4 need to send 2 bits at a time
|
||||
for ( i = 0; i < BitStreamLen-1; i+=2 ) {
|
||||
SendBits = (BitStream[BitStream_Byte(i )] >> (BitStream_Bit(i )) & 1) << 1; // Bit i
|
||||
SendBits += (BitStream[BitStream_Byte(i+1)] >> (BitStream_Bit(i+1)) & 1); // Bit i+1;
|
||||
T55xxWriteBit (SendBits & 3,downlink_mode);//Timing);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < BitStreamLen; i++) {
|
||||
SendBits = (BitStream[BitStream_Byte(i)] >> BitStream_Bit(i));
|
||||
T55xxWriteBit (SendBits & 1,downlink_mode);//Timing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send T5577 reset command then read stream (see if we can identify the start of the stream)
|
||||
void T55xxResetRead(uint8_t flags) {
|
||||
|
||||
uint8_t downlink_mode = ((flags >> 3) & 3);
|
||||
uint8_t arg = 0x80 | downlink_mode;
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
//clear buffer now so it does not interfere with timing later
|
||||
BigBuf_Clear_keep_EM();
|
||||
|
||||
T55xx_SendCMD (0, 0, arg);
|
||||
|
||||
TurnReadLFOn(T55xx_Timing.m[downlink_mode].read_gap * 8);
|
||||
|
||||
// Acquisition
|
||||
DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0);
|
||||
|
@ -1391,54 +1640,34 @@ void T55xxResetRead(void) {
|
|||
// Turn the field off
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
|
||||
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
|
||||
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
// Write one card block in page 0, no lock
|
||||
void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags) {
|
||||
LED_A_ON();
|
||||
bool pwd_mode = (flags & 0x1);
|
||||
uint8_t page = (flags & 0x2) >> 1;
|
||||
bool test_mode = (flags & 0x4) >> 2;
|
||||
uint32_t i = 0;
|
||||
//void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags) {
|
||||
void T55xxWriteBlock(uint8_t *data) {
|
||||
|
||||
// Set up FPGA, 125kHz
|
||||
LFSetupFPGAForADC(95, true);
|
||||
/*
|
||||
flag bits
|
||||
xxxxxxx1 0x01 PwdMode
|
||||
xxxxxx1x 0x02 Page
|
||||
xxxxx1xx 0x04 testMode
|
||||
xxx11xxx 0x18 downlink mode
|
||||
xx1xxxxx 0x20 !reg_readmode
|
||||
x1xxxxxx 0x40 called for a read, so no data packet
|
||||
1xxxxxxx 0x80 reset
|
||||
*/
|
||||
|
||||
// make sure tag is fully powered up...
|
||||
WaitMS(4);
|
||||
t55xx_write_block_t *c = (t55xx_write_block_t *)data;
|
||||
// c->data, c->blockno, c->pwd, c->flags
|
||||
|
||||
// Trigger T55x7 in mode.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitUS(t_config.start_gap);
|
||||
bool testMode = ((c->flags & 0x04) == 0x04);
|
||||
|
||||
if (test_mode) {
|
||||
Dbprintf("T55xx writing with %s", _YELLOW_("test mode enabled"));
|
||||
// undocmented testmode opcode 01
|
||||
T55xxWriteBit(0);
|
||||
T55xxWriteBit(1);
|
||||
} else {
|
||||
// std opcode 10 == page 0
|
||||
// std opcode 11 == page 1
|
||||
T55xxWriteBit(1);
|
||||
T55xxWriteBit(page);
|
||||
}
|
||||
c->flags &= (0xff ^ 0x40); // Called for a write, so ensure it is clear/0
|
||||
|
||||
if (pwd_mode) {
|
||||
// Send pwd
|
||||
for (i = 0x80000000; i != 0; i >>= 1)
|
||||
T55xxWriteBit(pwd & i);
|
||||
}
|
||||
// Send lock bit
|
||||
T55xxWriteBit(0);
|
||||
|
||||
// Send data
|
||||
for (i = 0x80000000; i != 0; i >>= 1)
|
||||
T55xxWriteBit(data & i);
|
||||
|
||||
// Send block number
|
||||
for (i = 0x04; i != 0; i >>= 1)
|
||||
T55xxWriteBit(blockno & i);
|
||||
LED_A_ON ();
|
||||
T55xx_SendCMD (c->data, c->pwd, c->flags | (c->blockno << 9)) ;//, false);
|
||||
|
||||
// Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550,
|
||||
// so wait a little more)
|
||||
|
@ -1447,7 +1676,7 @@ void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t fl
|
|||
// - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567
|
||||
// so we should wait 1 clock + 5.6ms then read response?
|
||||
// but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow...
|
||||
if (test_mode) {
|
||||
if (testMode) {
|
||||
//TESTMODE TIMING TESTS:
|
||||
// <566us does nothing
|
||||
// 566-568 switches between wiping to 0s and doing nothing
|
||||
|
@ -1457,7 +1686,6 @@ void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t fl
|
|||
|
||||
} else {
|
||||
TurnReadLFOn(20 * 1000);
|
||||
|
||||
//could attempt to do a read to confirm write took
|
||||
// as the tag should repeat back the new block
|
||||
// until it is reset, but to confirm it we would
|
||||
|
@ -1468,69 +1696,63 @@ void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t fl
|
|||
|
||||
//DoPartialAcquisition(20, true, 12000);
|
||||
}
|
||||
|
||||
// turn field off
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_A_OFF();
|
||||
|
||||
// cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
reply_ng(CMD_T55XX_WRITE_BLOCK, PM3_SUCCESS, NULL, 0);
|
||||
LED_A_OFF ();
|
||||
}
|
||||
|
||||
// Write one card block in page 0, no lock
|
||||
/*
|
||||
// uses NG format
|
||||
void T55xxWriteBlock(uint8_t *data) {
|
||||
t55xx_write_block_t *c = (t55xx_write_block_t *)data;
|
||||
T55xxWriteBlockExt(c->data, c->blockno, c->pwd, c->flags);
|
||||
reply_ng(CMD_T55XX_WRITE_BLOCK, PM3_SUCCESS, NULL, 0);
|
||||
// reply_ng(CMD_T55XX_WRITE_BLOCK, PM3_SUCCESS, NULL, 0);
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
// Read one card block in page [page]
|
||||
void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd) {
|
||||
LED_A_ON();
|
||||
bool regular_readmode = (block == 0xFF);
|
||||
uint8_t start_wait = 4;
|
||||
void T55xxReadBlockExt (uint16_t flags, uint8_t block, uint32_t pwd) {
|
||||
/ *
|
||||
flag bits
|
||||
xxxx xxxxxxx1 0x0001 PwdMode
|
||||
xxxx xxxxxx1x 0x0002 Page
|
||||
xxxx xxxxx1xx 0x0004 testMode
|
||||
xxxx xxx11xxx 0x0018 downlink mode
|
||||
xxxx xx1xxxxx 0x0020 !reg_readmode
|
||||
xxxx x1xxxxxx 0x0040 called for a read, so no data packet
|
||||
xxxx 1xxxxxxx 0x0080 reset
|
||||
xxx1 xxxxxxxx 0x0100 brute/leave field on
|
||||
* /
|
||||
size_t samples = 12000;
|
||||
uint32_t i;
|
||||
bool brute_mem = (flags & 0x0100) >> 8;
|
||||
|
||||
if (brute_mem) {
|
||||
start_wait = 0;
|
||||
samples = 1024;
|
||||
}
|
||||
LED_A_ON();
|
||||
|
||||
//clear buffer now so it does not interfere with timing later
|
||||
BigBuf_Clear_keep_EM();
|
||||
if (brute_mem) samples = 1024;
|
||||
|
||||
// Set Read Flag to ensure SendCMD does not add "data" to the packet
|
||||
flags |= 0x40;
|
||||
|
||||
// RegRead Mode true block = 0xff, so read without an address
|
||||
if (block == 0xff) flags |= 0x20;
|
||||
|
||||
//make sure block is at max 7
|
||||
block &= 0x7;
|
||||
|
||||
// Set up FPGA, 125kHz to power up the tag
|
||||
LFSetupFPGAForADC(95, true);
|
||||
// make sure tag is fully powered up...
|
||||
WaitMS(start_wait);
|
||||
//clear buffer now so it does not interfere with timing later
|
||||
BigBuf_Clear_keep_EM();
|
||||
|
||||
// Trigger T55x7 Direct Access Mode with start gap
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitUS(t_config.start_gap);
|
||||
|
||||
// Opcode 1[page]
|
||||
T55xxWriteBit(1);
|
||||
T55xxWriteBit(page); //Page 0
|
||||
|
||||
if (pwd_mode) {
|
||||
// Send Pwd
|
||||
for (i = 0x80000000; i != 0; i >>= 1)
|
||||
T55xxWriteBit(pwd & i);
|
||||
}
|
||||
// Send a zero bit separation
|
||||
T55xxWriteBit(0);
|
||||
|
||||
// Send Block number (if direct access mode)
|
||||
if (!regular_readmode)
|
||||
for (i = 0x04; i != 0; i >>= 1)
|
||||
T55xxWriteBit(block & i);
|
||||
T55xx_SendCMD (0, pwd, flags | (block << 9)); //, true);
|
||||
|
||||
// Turn field on to read the response
|
||||
// 137*8 seems to get to the start of data pretty well...
|
||||
// but we want to go past the start and let the repeating data settle in...
|
||||
TurnReadLFOn(150 * 8);
|
||||
|
||||
// TurnReadLFOn(210*8); // issues with block 1 reads so dropping down seemed to help
|
||||
TurnReadLFOn(137*8);
|
||||
|
||||
// Acquisition
|
||||
// Now do the acquisition
|
||||
|
@ -1543,8 +1765,69 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block,
|
|||
LED_A_OFF();
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Read one card block in page [page]
|
||||
void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd, uint8_t downlink_mode) {
|
||||
/*
|
||||
flag bits
|
||||
xxxxxxx1 0x0001 PwdMode
|
||||
xxxxxx1x 0x0002 Page
|
||||
xxxxx1xx 0x0004 testMode
|
||||
xxx11xxx 0x0018 downlink mode
|
||||
xx1xxxxx 0x0020 !reg_readmode
|
||||
x1xxxxxx 0x0040 called for a read, so no data packet
|
||||
1xxxxxxx 0x0080 reset
|
||||
1xxxxxxxx 0x0100 brute/leave field on
|
||||
*/
|
||||
uint16_t flags = 0x0040; // read packet
|
||||
if (pwd_mode) flags |= 0x0001;
|
||||
if (page) flags |= 0x0002;
|
||||
flags |= (downlink_mode & 3) << 3;
|
||||
if (brute_mem) flags |= 0x0100;
|
||||
|
||||
void T55xx_ChkPwds() {
|
||||
// T55xxReadBlockExt (flags,block,pwd);
|
||||
size_t samples = 12000;
|
||||
// bool brute_mem = (flags & 0x0100) >> 8;
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
if (brute_mem) samples = 1024;
|
||||
|
||||
//-- Set Read Flag to ensure SendCMD does not add "data" to the packet
|
||||
//-- flags |= 0x40;
|
||||
|
||||
// RegRead Mode true block = 0xff, so read without an address
|
||||
if (block == 0xff) flags |= 0x20;
|
||||
|
||||
//make sure block is at max 7
|
||||
block &= 0x7;
|
||||
|
||||
//clear buffer now so it does not interfere with timing later
|
||||
BigBuf_Clear_keep_EM();
|
||||
|
||||
T55xx_SendCMD (0, pwd, flags | (block << 9)); //, true);
|
||||
|
||||
// Turn field on to read the response
|
||||
// 137*8 seems to get to the start of data pretty well...
|
||||
// but we want to go past the start and let the repeating data settle in...
|
||||
|
||||
// TurnReadLFOn(210*8); // issues with block 1 reads so dropping down seemed to help
|
||||
TurnReadLFOn(137*8);
|
||||
|
||||
// Acquisition
|
||||
// Now do the acquisition
|
||||
DoPartialAcquisition(0, true, samples, 0);
|
||||
|
||||
// Turn the field off
|
||||
if (!brute_mem) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
reply_ng(CMD_T55XX_READ_BLOCK, PM3_SUCCESS, NULL, 0);
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void T55xx_ChkPwds(uint8_t flags) {
|
||||
|
||||
DbpString("[+] T55XX Check pwds using flashmemory starting");
|
||||
|
||||
|
@ -1552,16 +1835,14 @@ void T55xx_ChkPwds() {
|
|||
// First get baseline and setup LF mode.
|
||||
// tends to mess up BigBuf
|
||||
uint8_t *buf = BigBuf_get_addr();
|
||||
|
||||
uint32_t b1, baseline = 0;
|
||||
uint8_t downlink_mode = (flags >> 3) & 0x03;
|
||||
|
||||
// collect baseline for failed attempt
|
||||
uint8_t x = 32;
|
||||
while (x--) {
|
||||
b1 = 0;
|
||||
|
||||
// T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd)
|
||||
T55xxReadBlock(0, 0, true, 1, 0);
|
||||
T55xxReadBlock(0, 0, true, 1, 0,downlink_mode);
|
||||
for (uint16_t j = 0; j < 1024; ++j)
|
||||
b1 += buf[j];
|
||||
|
||||
|
@ -1576,8 +1857,8 @@ void T55xx_ChkPwds() {
|
|||
uint8_t *pwds = BigBuf_get_EM_addr();
|
||||
uint16_t pwdCount = 0;
|
||||
uint32_t candidate = 0;
|
||||
|
||||
#ifdef WITH_FLASH
|
||||
|
||||
BigBuf_Clear_EM();
|
||||
uint16_t isok = 0;
|
||||
uint8_t counter[2] = {0x00, 0x00};
|
||||
|
@ -1606,7 +1887,7 @@ void T55xx_ChkPwds() {
|
|||
|
||||
pwd = bytes_to_num(pwds + i * 4, 4);
|
||||
|
||||
T55xxReadBlock(0, true, true, 0, pwd);
|
||||
T55xxReadBlock(0, true, true, 0, pwd,downlink_mode);
|
||||
|
||||
// calc mean of BigBuf 1024 samples.
|
||||
uint32_t sum = 0;
|
||||
|
@ -1623,8 +1904,6 @@ void T55xx_ChkPwds() {
|
|||
Dbprintf("[=] Pwd %08X | ABS %u", pwd, curr);
|
||||
|
||||
if (curr > prev) {
|
||||
|
||||
|
||||
Dbprintf("[=] --> ABS %u Candidate %08X <--", curr, pwd);
|
||||
candidate = pwd;
|
||||
prev = curr;
|
||||
|
@ -1640,36 +1919,31 @@ OUT:
|
|||
LEDsoff();
|
||||
}
|
||||
|
||||
void T55xxWakeUp(uint32_t Pwd) {
|
||||
void T55xxWakeUp(uint32_t Pwd, uint8_t flags) {
|
||||
|
||||
flags |= 0x01 | 0x40 | 0x20; //Password | Read Call (no data) | reg_read no block
|
||||
LED_B_ON();
|
||||
uint32_t i = 0;
|
||||
|
||||
// Set up FPGA, 125kHz
|
||||
LFSetupFPGAForADC(95, true);
|
||||
// make sure tag is fully powered up...
|
||||
WaitMS(4);
|
||||
T55xx_SendCMD (0, Pwd, flags);
|
||||
|
||||
// Trigger T55x7 Direct Access Mode
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitUS(t_config.start_gap);
|
||||
|
||||
// Opcode 10
|
||||
T55xxWriteBit(1);
|
||||
T55xxWriteBit(0); //Page 0
|
||||
|
||||
// Send Pwd
|
||||
for (i = 0x80000000; i != 0; i >>= 1)
|
||||
T55xxWriteBit(Pwd & i);
|
||||
|
||||
// Turn and leave field on to let the begin repeating transmission
|
||||
//-- Turn and leave field on to let the begin repeating transmission
|
||||
TurnReadLFOn(20 * 1000);
|
||||
}
|
||||
|
||||
|
||||
/*-------------- Cloning routines -----------*/
|
||||
void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) {
|
||||
// write last block first and config block last (if included)
|
||||
for (uint8_t i = numblocks + startblock; i > startblock; i--)
|
||||
T55xxWriteBlockExt(blockdata[i - 1], i - 1, 0, 0);
|
||||
|
||||
t55xx_write_block_t cmd;
|
||||
cmd.pwd = 0;
|
||||
cmd.flags = 0;
|
||||
|
||||
for (uint8_t i = numblocks + startblock; i > startblock; i--) {
|
||||
cmd.data = blockdata[i - 1];
|
||||
cmd.blockno = i - 1;
|
||||
T55xxWriteBlock ((uint8_t *)&cmd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Copy HID id to card and setup block 0 config
|
||||
|
|
|
@ -43,12 +43,14 @@ static int usage_t55xx_config() {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_t55xx_read() {
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx read [b <block>] [p <password>] <override_safety> <page1>");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx read [r <mode>] b <block> [p <password>] <override_safety> <page1>");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " b <block> - block number to read. Between 0-7");
|
||||
PrintAndLogEx(NORMAL, " p <password> - OPTIONAL password (8 hex characters)");
|
||||
PrintAndLogEx(NORMAL, " o - OPTIONAL override safety check");
|
||||
PrintAndLogEx(NORMAL, " 1 - OPTIONAL read Page 1 instead of Page 0");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default), '1' long leading ref.");
|
||||
PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref.");
|
||||
PrintAndLogEx(NORMAL, " ****WARNING****");
|
||||
PrintAndLogEx(NORMAL, " Use of read with password on a tag not configured for a pwd");
|
||||
PrintAndLogEx(NORMAL, " can damage the tag");
|
||||
|
@ -61,13 +63,15 @@ static int usage_t55xx_read() {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_t55xx_write() {
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx write [b <block>] [d <data>] [p <password>] [1] [t]");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx write [r <mode>] b <block> d <data> [p <password>] [1] [t]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " b <block> - block number to write. Between 0-7");
|
||||
PrintAndLogEx(NORMAL, " d <data> - 4 bytes of data to write (8 hex characters)");
|
||||
PrintAndLogEx(NORMAL, " p <password> - OPTIONAL password 4bytes (8 hex characters)");
|
||||
PrintAndLogEx(NORMAL, " 1 - OPTIONAL write Page 1 instead of Page 0");
|
||||
PrintAndLogEx(NORMAL, " t - OPTIONAL test mode write - ****DANGER****");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default), '1' long leading ref.");
|
||||
PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref.");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx write b 3 d 11223344 - write 11223344 to block 3");
|
||||
|
@ -76,24 +80,29 @@ static int usage_t55xx_write() {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_t55xx_trace() {
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx trace [1]");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx trace [r mode]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default), '1' long leading ref.");
|
||||
PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref.");
|
||||
// Command did not seem to support the 1 option (yet) so have removed the help lines
|
||||
// PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx trace");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx trace 1");
|
||||
// PrintAndLogEx(NORMAL, " lf t55xx trace 1");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_t55xx_info() {
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx info [1] [d <data> [q]]");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx info [1] [r <mode>] [d <data> [q]]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " (default) - read data from tag.");
|
||||
PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer instead of reading tag.");
|
||||
PrintAndLogEx(NORMAL, " d <data> - 4 bytes of data (8 hex characters)");
|
||||
PrintAndLogEx(NORMAL, " if set, use these data instead of reading tag.");
|
||||
PrintAndLogEx(NORMAL, " q - if set, provided data are interpreted as Q5 config.");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default), '1' long leading ref.");
|
||||
PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref.");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx info");
|
||||
|
@ -104,10 +113,12 @@ static int usage_t55xx_info() {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_t55xx_dump() {
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx dump <password> [o]");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx dump [r <mode>] [<password> [o]]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " <password> - OPTIONAL password 4bytes (8 hex symbols)");
|
||||
PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default), '1' long leading ref.");
|
||||
PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref.");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx dump");
|
||||
|
@ -116,10 +127,13 @@ static int usage_t55xx_dump() {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_t55xx_detect() {
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [p <password>]");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [r <mode>] [p <password>]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLogEx(NORMAL, " p <password> - OPTIONAL password (8 hex characters)");
|
||||
PrintAndLogEx(NORMAL, " p <password - OPTIONAL password (8 hex characters)");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default)");
|
||||
PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero ");
|
||||
PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx detect");
|
||||
|
@ -130,10 +144,13 @@ static int usage_t55xx_detect() {
|
|||
}
|
||||
static int usage_t55xx_detectP1() {
|
||||
PrintAndLogEx(NORMAL, "Command: Detect Page 1 of a t55xx chip");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx p1detect [1] [p <password>]");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx p1detect [1] [r <mode>] [p <password>]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag.");
|
||||
PrintAndLogEx(NORMAL, " p <password> - OPTIONAL password (8 hex characters)");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default)");
|
||||
PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero ");
|
||||
PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx p1detect");
|
||||
|
@ -143,11 +160,13 @@ static int usage_t55xx_detectP1() {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_t55xx_wakup() {
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx wakeup [h] p <password>");
|
||||
PrintAndLogEx(NORMAL, "This commands send the Answer-On-Request command and leaves the readerfield ON afterwards.");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx wakeup [h] [r <mode>] p <password>");
|
||||
PrintAndLogEx(NORMAL, "This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards.");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " p <password> - password 4bytes (8 hex symbols)");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default), '1' long leading ref.");
|
||||
PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref.");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx wakeup p 11223344 - send wakeup password");
|
||||
|
@ -158,10 +177,13 @@ static int usage_t55xx_chk() {
|
|||
PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
|
||||
PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!");
|
||||
PrintAndLogEx(NORMAL, "Try to reading block 7 before\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx chk [h] <m> [i <*.dic>]");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx chk [h] [m] [r <mode>] [i <*.dic>]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default)");
|
||||
PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero ");
|
||||
PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes");
|
||||
PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
|
@ -174,16 +196,19 @@ static int usage_t55xx_bruteforce() {
|
|||
PrintAndLogEx(NORMAL, "This command uses bruteforce to scan a number range");
|
||||
PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
|
||||
PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!");
|
||||
PrintAndLogEx(NORMAL, "Try to reading block 7 before\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] <start password> <end password>");
|
||||
PrintAndLogEx(NORMAL, "Try reading block 7 before\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] [r <mode>] <start password> <end password>");
|
||||
PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default)");
|
||||
PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero ");
|
||||
PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes");
|
||||
PrintAndLogEx(NORMAL, " <start_pwd> - 4 byte hex value to start pwd search at");
|
||||
PrintAndLogEx(NORMAL, " <end_pwd> - 4 byte hex value to end pwd search at");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx bruteforce aaaaaa77 aaaaaa99");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx bruteforce r 2 aaaaaa77 aaaaaa99");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -191,17 +216,20 @@ static int usage_t55xx_recoverpw() {
|
|||
PrintAndLogEx(NORMAL, "This command uses a few tricks to try to recover mangled password");
|
||||
PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
|
||||
PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!");
|
||||
PrintAndLogEx(NORMAL, "Try to reading block 7 before\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx recoverpw [password]");
|
||||
PrintAndLogEx(NORMAL, "Try reading block 7 before\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx recoverpw [r <mode>] [password]");
|
||||
PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)");
|
||||
PrintAndLogEx(NORMAL, " default password is 51243648, used by many cloners");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - this help");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default)");
|
||||
PrintAndLogEx(NORMAL, " '1' long leading ref., '2' leading zero ");
|
||||
PrintAndLogEx(NORMAL, " '3' 1 of 4 coding ref., '4' try all modes");
|
||||
PrintAndLogEx(NORMAL, " [password] - 4 byte hex value of password written by cloner");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx recoverpw");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx recoverpw 51243648");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx r 3 recoverpw 51243648");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -218,16 +246,21 @@ static int usage_t55xx_wipe() {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
static int usage_lf_deviceconfig() {
|
||||
PrintAndLogEx(NORMAL, "Sets t55x7 timings for direkt commands. The timings are set here in Field Clocks (FC), \nwhich is converted to (US) on device");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a <gap> b <gap> c <gap> d <gap> e <gap> p");
|
||||
PrintAndLogEx(NORMAL, "Sets t55x7 timings for direct commands. The timings are set here in Field Clocks (FC), \nwhich is converted to (US) on device");
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig [r <mode>] a <gap> b <gap> c <gap> d <gap> e <gap> f <gap> g <gap> [p]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h - This help");
|
||||
PrintAndLogEx(NORMAL, " a <8..255> - Set start gap");
|
||||
PrintAndLogEx(NORMAL, " b <8..255> - Set write gap");
|
||||
PrintAndLogEx(NORMAL, " c <8..255> - Set write ZERO gap");
|
||||
PrintAndLogEx(NORMAL, " d <8..255> - Set write ONE gap");
|
||||
PrintAndLogEx(NORMAL, " e <8..255> - Set read gap");
|
||||
PrintAndLogEx(NORMAL, " e <8..255> - Set write TWO gap (1 of 4 only)");
|
||||
PrintAndLogEx(NORMAL, " f <8..255> - Set write THREE gap (1 of 4 only)");
|
||||
PrintAndLogEx(NORMAL, " g <8..255> - Set read gap");
|
||||
PrintAndLogEx(NORMAL, " p - persist to flashmemory");
|
||||
PrintAndLogEx(NORMAL, " r <mode> - downlink encoding '0' fixed bit length (default), '1' long leading ref.");
|
||||
PrintAndLogEx(NORMAL, " '2' leading zero, '3' 1 of 4 coding ref.");
|
||||
PrintAndLogEx(NORMAL, " z - erase t55x7 timings (needs p and reboot to load defaults)");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 - default T55XX");
|
||||
|
@ -359,13 +392,12 @@ static int CmdT55xxSetConfig(const char *Cmd) {
|
|||
return printConfiguration(config);
|
||||
}
|
||||
|
||||
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password) {
|
||||
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode) {
|
||||
//Password mode
|
||||
if (usepwd) {
|
||||
// try reading the config block and verify that PWD bit is set before doing this!
|
||||
if (!override) {
|
||||
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0)) return PM3_ESOFT;
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0,downlink_mode)) return PM3_ESOFT;
|
||||
|
||||
if (!tryDetectModulation()) {
|
||||
PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits.");
|
||||
|
@ -376,11 +408,14 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32
|
|||
page1 = false;
|
||||
}
|
||||
} else {
|
||||
// Show only if first for command i.e. override = 1 (override and display) override = 2 (override and dont display)
|
||||
if ((override & 2) != 2)
|
||||
PrintAndLogEx(NORMAL, "Safety Check Overriden - proceeding despite risk");
|
||||
}
|
||||
}
|
||||
|
||||
if (!AquireData(page1, block, usepwd, password)) return PM3_ESOFT;
|
||||
|
||||
if (!AquireData(page1, block, usepwd, password, downlink_mode)) return PM3_ESOFT;
|
||||
if (!DecodeT55xxBlock()) return PM3_ESOFT;
|
||||
|
||||
printT55xxBlock(block);
|
||||
|
@ -395,6 +430,8 @@ static int CmdT55xxReadBlock(const char *Cmd) {
|
|||
bool page1 = false;
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t downlink_mode = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
|
@ -416,6 +453,13 @@ static int CmdT55xxReadBlock(const char *Cmd) {
|
|||
page1 = true;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
downlink_mode = param_getchar(Cmd, cmdp+1) - '0';
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
cmdp +=2;
|
||||
break;
|
||||
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
|
@ -430,7 +474,7 @@ static int CmdT55xxReadBlock(const char *Cmd) {
|
|||
}
|
||||
|
||||
printT5xxHeader(page1);
|
||||
return T55xxReadBlock(block, page1, usepwd, override, password);
|
||||
return T55xxReadBlock(block, page1, usepwd, override, password, downlink_mode);
|
||||
}
|
||||
|
||||
bool DecodeT55xxBlock(void) {
|
||||
|
@ -512,11 +556,34 @@ static int SanityOfflineCheck(bool useGraphBuffer) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
void T55xx_Print_DownlinkMode (uint8_t downlink_mode)
|
||||
{
|
||||
char Msg[80];
|
||||
sprintf (Msg,"Downlink Mode used : ");
|
||||
|
||||
switch (downlink_mode) {
|
||||
case 0 : strcat (Msg,"default/fixed bit length"); break;
|
||||
case 1 : strcat (Msg,"long leading reference (r 1)"); break;
|
||||
case 2 : strcat (Msg,"leading zero reference (r 2)"); break;
|
||||
case 3 : strcat (Msg,"1 of 4 coding reference (r 3)"); break;
|
||||
default :
|
||||
strcat (Msg,"default/fixed bit length"); break;
|
||||
}
|
||||
|
||||
PrintAndLogEx (NORMAL,Msg);
|
||||
}
|
||||
//
|
||||
static int CmdT55xxDetect(const char *Cmd) {
|
||||
|
||||
bool errors = false;
|
||||
bool useGB = false, usepwd = false;
|
||||
bool useGB = false;
|
||||
bool usepwd = false;
|
||||
bool try_all_dl_modes = false;
|
||||
bool found = false;
|
||||
uint32_t password = 0;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t downlink_mode = 0;
|
||||
uint8_t dl_mode = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
@ -532,6 +599,12 @@ static int CmdT55xxDetect(const char *Cmd) {
|
|||
useGB = true;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'r':
|
||||
downlink_mode = param_getchar(Cmd, cmdp+1) - '0';
|
||||
if (downlink_mode == 4) try_all_dl_modes = true;
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
cmdp +=2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
|
@ -544,16 +617,47 @@ static int CmdT55xxDetect(const char *Cmd) {
|
|||
if (SanityOfflineCheck(useGB) != PM3_SUCCESS) return PM3_ENODATA;
|
||||
|
||||
if (!useGB) {
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password))
|
||||
for (dl_mode = downlink_mode; dl_mode < 4; dl_mode++) {
|
||||
found = AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password,dl_mode);
|
||||
|
||||
// found = false if password is supplied but wrong d/l mode
|
||||
// so keep trying other modes (if requested)
|
||||
/* if (!found) {
|
||||
printf ("Aquire not found");
|
||||
return PM3_ENODATA;
|
||||
}
|
||||
*/
|
||||
if (tryDetectModulation())
|
||||
{
|
||||
T55xx_Print_DownlinkMode (dl_mode);
|
||||
dl_mode = 4;
|
||||
found = true;
|
||||
}
|
||||
else found = false;
|
||||
|
||||
if (!try_all_dl_modes) dl_mode = 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (useGB) found = tryDetectModulation();
|
||||
|
||||
if (!found)
|
||||
PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'"));
|
||||
|
||||
|
||||
/* if (!useGB) {
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password,downlink_mode))
|
||||
return PM3_ENODATA;
|
||||
}
|
||||
if (!tryDetectModulation())
|
||||
PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'"));
|
||||
else
|
||||
T55xx_Print_DownlinkMode (downlink_mode);
|
||||
*/
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// detect configuration?
|
||||
bool tryDetectModulation(void) {
|
||||
|
||||
|
@ -997,9 +1101,13 @@ int printConfiguration(t55xx_conf_block_t b) {
|
|||
}
|
||||
|
||||
static int CmdT55xxWakeUp(const char *Cmd) {
|
||||
|
||||
uint32_t password = 0;
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
uint8_t downlink_mode = 0;
|
||||
uint8_t flags = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
|
@ -1009,17 +1117,25 @@ static int CmdT55xxWakeUp(const char *Cmd) {
|
|||
cmdp += 2;
|
||||
errors = false;
|
||||
break;
|
||||
case 'r':
|
||||
downlink_mode = param_getchar(Cmd, cmdp+1) - '0';
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
cmdp +=2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors) return usage_t55xx_wakup();
|
||||
|
||||
flags = (downlink_mode & 3) << 3;
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_T55XX_WAKEUP, password, 0, 0, NULL, 0);
|
||||
SendCommandMIX(CMD_T55XX_WAKEUP, password, flags, 0, NULL, 0);
|
||||
PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1033,6 +1149,8 @@ static int CmdT55xxWriteBlock(const char *Cmd) {
|
|||
bool testMode = false;
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
uint32_t downlink_mode = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
|
@ -1064,6 +1182,11 @@ static int CmdT55xxWriteBlock(const char *Cmd) {
|
|||
page1 = true;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'r':
|
||||
downlink_mode = param_getchar(Cmd, cmdp+1) - '0';
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
cmdp +=2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
|
@ -1077,6 +1200,7 @@ static int CmdT55xxWriteBlock(const char *Cmd) {
|
|||
flags = (usepwd) ? 0x1 : 0;
|
||||
flags |= (page1) ? 0x2 : 0;
|
||||
flags |= (testMode) ? 0x4 : 0;
|
||||
flags |= (downlink_mode << 3);
|
||||
|
||||
char pwdStr[16] = {0};
|
||||
snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password);
|
||||
|
@ -1110,16 +1234,26 @@ static int CmdT55xxWriteBlock(const char *Cmd) {
|
|||
}
|
||||
|
||||
static int CmdT55xxReadTrace(const char *Cmd) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) > 1 || cmdp == 'h') return usage_t55xx_trace();
|
||||
uint8_t cmd_len = 0;
|
||||
uint8_t downlink_mode = 0;
|
||||
|
||||
if (strlen(Cmd) == 0) {
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'r') {
|
||||
downlink_mode = param_getchar(Cmd, 1) - '0';
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
cmd_len = 3;
|
||||
}
|
||||
if ((strlen(Cmd) != cmd_len) || (cmdp == 'h')) return usage_t55xx_trace();
|
||||
|
||||
if (strlen(Cmd) == cmd_len) {
|
||||
// sanity check.
|
||||
if (SanityOfflineCheck(false) != PM3_SUCCESS) return PM3_ENODATA;
|
||||
|
||||
bool pwdmode = false;
|
||||
uint32_t password = 0;
|
||||
if (!AquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, pwdmode, password))
|
||||
// REGULAR_READ_MODE_BLOCK - yeilds correct Page 1 Block 2 data i.e. + 32 bit offset.
|
||||
// if (!AquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, pwdmode, password,downlink_mode))
|
||||
if (!AquireData(T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password,downlink_mode))
|
||||
return PM3_ENODATA;
|
||||
}
|
||||
|
||||
|
@ -1363,6 +1497,7 @@ static int CmdT55xxInfo(const char *Cmd) {
|
|||
*/
|
||||
bool frombuff = false, gotdata = false, dataasq5 = false;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t downlink_mode = 0;
|
||||
uint32_t block0 = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00) {
|
||||
|
@ -1382,6 +1517,11 @@ static int CmdT55xxInfo(const char *Cmd) {
|
|||
dataasq5 = true;
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'r':
|
||||
downlink_mode = param_getchar(Cmd, cmdp+1)- '0';
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
return usage_t55xx_info();
|
||||
|
@ -1400,7 +1540,7 @@ static int CmdT55xxInfo(const char *Cmd) {
|
|||
|
||||
bool pwdmode = false;
|
||||
uint32_t password = 0;
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password))
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password,downlink_mode))
|
||||
return PM3_ENODATA;
|
||||
}
|
||||
if (!gotdata) {
|
||||
|
@ -1496,29 +1636,42 @@ static int CmdT55xxInfo(const char *Cmd) {
|
|||
static int CmdT55xxDump(const char *Cmd) {
|
||||
|
||||
uint32_t password = 0;
|
||||
bool override = false;
|
||||
uint8_t override = false;
|
||||
uint8_t cmd_opt_idx = 0;
|
||||
uint8_t downlink_mode = 0;
|
||||
uint8_t pwd_offset = 0;
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_t55xx_dump();
|
||||
|
||||
bool usepwd = (strlen(Cmd) > 0);
|
||||
|
||||
if (cmdp == 'h') return usage_t55xx_dump();
|
||||
if (cmdp == 'r') {
|
||||
cmd_opt_idx++;
|
||||
downlink_mode = param_getchar(Cmd, cmd_opt_idx++) - '0';
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
pwd_offset = 3;
|
||||
}
|
||||
bool usepwd = (strlen(Cmd) > pwd_offset);
|
||||
if (usepwd) {
|
||||
password = param_get32ex(Cmd, 0, 0, 16);
|
||||
if (param_getchar(Cmd, 1) == 'o')
|
||||
password = param_get32ex(Cmd, cmd_opt_idx++, 0, 16);
|
||||
if (param_getchar(Cmd, cmd_opt_idx++) == 'o')
|
||||
override = true;
|
||||
}
|
||||
|
||||
printT5xxHeader(0);
|
||||
for (uint8_t i = 0; i < 8; ++i)
|
||||
T55xxReadBlock(i, 0, usepwd, override, password);
|
||||
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
T55xxReadBlock(i, 0, usepwd, override, password,downlink_mode);
|
||||
// idea for better user experience and display.
|
||||
// only show override warning on the first block read
|
||||
if (override) override |= 2; // flag not to show safty for 2nd and on.
|
||||
}
|
||||
printT5xxHeader(1);
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
T55xxReadBlock(i, 1, usepwd, override, password);
|
||||
T55xxReadBlock(i, 1, usepwd, override, password,downlink_mode);
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password) {
|
||||
bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint8_t downlink_mode) {
|
||||
// arg0 bitmodes:
|
||||
// b0 = pwdmode
|
||||
// b1 = page to read from
|
||||
|
@ -1530,12 +1683,14 @@ bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password) {
|
|||
uint8_t blockno;
|
||||
uint8_t page;
|
||||
bool pwdmode;
|
||||
uint8_t downlink_mode;
|
||||
} PACKED;
|
||||
struct p payload;
|
||||
payload.password = password;
|
||||
payload.blockno = block;
|
||||
payload.page = page & 0x1;
|
||||
payload.pwdmode = pwdmode;
|
||||
payload.downlink_mode = downlink_mode;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_T55XX_READ_BLOCK, (uint8_t *)&payload, sizeof(payload));
|
||||
|
@ -1795,9 +1950,20 @@ static void t55x7_create_config_block(int tagtype) {
|
|||
*/
|
||||
|
||||
static int CmdResetRead(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
|
||||
uint8_t downlink_mode = 0;
|
||||
uint8_t flags = 0;
|
||||
|
||||
|
||||
if (strlen (Cmd) == 3)
|
||||
downlink_mode = param_getchar(Cmd, 1) - '0';
|
||||
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
|
||||
printf ("DL : %d\n",downlink_mode);
|
||||
flags = downlink_mode << 3;
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_T55XX_RESET_READ, NULL, 0);
|
||||
SendCommandNG(CMD_T55XX_RESET_READ, &flags, sizeof(flags));
|
||||
if (!WaitForResponseTimeout(CMD_ACK, NULL, 2500)) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
|
@ -1857,9 +2023,40 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
|||
bool found = false;
|
||||
uint8_t timeout = 0;
|
||||
uint8_t *keyBlock = NULL;
|
||||
bool from_flash = false;
|
||||
bool try_all_dl_modes = false;
|
||||
uint8_t downlink_mode = 0;
|
||||
int len;
|
||||
char cmdp;
|
||||
bool use_pwd_file = false;
|
||||
int dl_mode; // to try each downlink mode for each password
|
||||
|
||||
|
||||
cmdp = tolower(param_getchar(Cmd,0));
|
||||
|
||||
if (cmdp == 'h') return usage_t55xx_chk();
|
||||
if (cmdp == 'm') {
|
||||
from_flash = true;
|
||||
Cmd +=2;
|
||||
cmdp = tolower(param_getchar(Cmd,0));
|
||||
}
|
||||
if (cmdp == 'r') {
|
||||
Cmd += 2;
|
||||
downlink_mode = param_getchar(Cmd,0 ) - '0'; // get 2nd option, as this is fixed order.
|
||||
if (downlink_mode == 4) try_all_dl_modes = true;
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
Cmd += 2;
|
||||
cmdp = param_getchar(Cmd,0);
|
||||
}
|
||||
if (cmdp == 'i') {
|
||||
Cmd+=2;
|
||||
len = strlen(Cmd);
|
||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||
memcpy(filename, Cmd, len);
|
||||
use_pwd_file = true;
|
||||
}
|
||||
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_t55xx_chk();
|
||||
|
||||
/*
|
||||
// block 7, page1 = false, usepwd = false, override = false, pwd = 00000000
|
||||
|
@ -1872,10 +2069,11 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
|||
*/
|
||||
|
||||
uint64_t t1 = msclock();
|
||||
uint8_t flags = downlink_mode << 3;
|
||||
|
||||
if (cmdp == 'm') {
|
||||
if (from_flash) {
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_T55XX_CHKPWDS, NULL, 0);
|
||||
SendCommandNG(CMD_T55XX_CHKPWDS, &flags, sizeof(flags));
|
||||
PacketResponseNG resp;
|
||||
|
||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
|
@ -1891,10 +2089,12 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
|||
if (resp.oldarg[0]) {
|
||||
PrintAndLogEx(SUCCESS, "\nFound a candidate [ " _YELLOW_("%08X") " ]. Trying to validate", resp.oldarg[1]);
|
||||
|
||||
if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.oldarg[1])) {
|
||||
if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.oldarg[1],downlink_mode)) {
|
||||
found = tryDetectModulation();
|
||||
if (found) {
|
||||
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08") " ]", resp.oldarg[1]);
|
||||
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", resp.oldarg[1]);
|
||||
T55xx_Print_DownlinkMode (downlink_mode);
|
||||
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "Check pwd failed");
|
||||
}
|
||||
|
@ -1907,12 +2107,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (cmdp == 'i') {
|
||||
|
||||
int len = strlen(Cmd + 2);
|
||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||
memcpy(filename, Cmd + 2, len);
|
||||
|
||||
if (use_pwd_file) {
|
||||
uint16_t keycount = 0;
|
||||
size_t datalen = 0;
|
||||
|
||||
|
@ -1948,19 +2143,25 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
|||
curr_password = bytes_to_num(keyBlock + 4 * c, 4);
|
||||
|
||||
PrintAndLogEx(INFO, "Testing %08X", curr_password);
|
||||
for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++){
|
||||
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr_password)) {
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr_password,dl_mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
found = tryDetectModulation();
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
if (found)
|
||||
if (found) {
|
||||
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password);
|
||||
else
|
||||
PrintAndLogEx(WARNING, "Check pwd failed");
|
||||
T55xx_Print_DownlinkMode (dl_mode);
|
||||
dl_mode = 4; // Exit other downlink mode checks
|
||||
c = keycount; // Exit loop
|
||||
}
|
||||
|
||||
if (!try_all_dl_modes) // Exit loop if not trying all downlink modes
|
||||
dl_mode = 4;
|
||||
}
|
||||
}
|
||||
if (!found) PrintAndLogEx(WARNING, "Check pwd failed");
|
||||
}
|
||||
|
||||
free(keyBlock);
|
||||
|
@ -1977,15 +2178,24 @@ static int CmdT55xxBruteForce(const char *Cmd) {
|
|||
uint32_t start_password = 0x00000000; //start password
|
||||
uint32_t end_password = 0xFFFFFFFF; //end password
|
||||
uint32_t curr = 0;
|
||||
bool found = false;
|
||||
uint8_t downlink_mode = 0;
|
||||
uint8_t cmd_opt_idx = 0;
|
||||
uint8_t found = 0; // > 0 if found xx1 xx downlink needed, 1 found
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, cmd_opt_idx));
|
||||
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_t55xx_bruteforce();
|
||||
if (cmdp == 'r') { // downlink mode supplied
|
||||
cmd_opt_idx++; // skip over 'r'
|
||||
downlink_mode = param_getchar (Cmd,cmd_opt_idx++) - '0';
|
||||
if (downlink_mode > 4) downlink_mode = 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t t1 = msclock();
|
||||
|
||||
start_password = param_get32ex(Cmd, 0, 0, 16);
|
||||
end_password = param_get32ex(Cmd, 1, 0, 16);
|
||||
start_password = param_get32ex(Cmd, cmd_opt_idx++, 0, 16);
|
||||
end_password = param_get32ex(Cmd, cmd_opt_idx++, 0, 16);
|
||||
|
||||
curr = start_password;
|
||||
|
||||
|
@ -1995,7 +2205,7 @@ static int CmdT55xxBruteForce(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password);
|
||||
|
||||
while (!found) {
|
||||
while (found == 0) {
|
||||
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
@ -2004,7 +2214,7 @@ static int CmdT55xxBruteForce(const char *Cmd) {
|
|||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
||||
found = tryOnePassword(curr);
|
||||
found = tryOnePassword(curr,downlink_mode);
|
||||
|
||||
if (curr == end_password)
|
||||
break;
|
||||
|
@ -2014,27 +2224,43 @@ static int CmdT55xxBruteForce(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (found)
|
||||
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr);
|
||||
if (found) {
|
||||
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") "]", curr-1);
|
||||
T55xx_Print_DownlinkMode ((found >> 1) & 3);
|
||||
}
|
||||
else
|
||||
PrintAndLogEx(WARNING, "Bruteforce failed, last tried: [ " _YELLOW_("%08X") " ]", --curr);
|
||||
PrintAndLogEx(WARNING, "Bruteforce failed, last tried: [ " _YELLOW_("%08X") " ]", curr);
|
||||
|
||||
t1 = msclock() - t1;
|
||||
PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1 / 1000.0);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int tryOnePassword(uint32_t password) {
|
||||
uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode) {
|
||||
|
||||
bool try_all_dl_modes = false;
|
||||
uint8_t dl_mode = 0;
|
||||
|
||||
PrintAndLogEx(INFO, "Trying password %08X", password);
|
||||
|
||||
AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password);
|
||||
if (downlink_mode == 4) try_all_dl_modes = true;
|
||||
|
||||
if (getSignalProperties()->isnoise == false)
|
||||
return 0;
|
||||
downlink_mode = (downlink_mode & 3); // ensure 0-3
|
||||
|
||||
// check if dl mode 4 and loop if needed
|
||||
for (dl_mode = downlink_mode; dl_mode < 4; dl_mode++){
|
||||
|
||||
AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password,dl_mode);
|
||||
|
||||
// if (getSignalProperties()->isnoise == false) {
|
||||
// } else {
|
||||
if (tryDetectModulation())
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
return 1 + (dl_mode << 1);
|
||||
}
|
||||
// }
|
||||
if (!try_all_dl_modes) dl_mode = 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2044,17 +2270,26 @@ static int CmdT55xxRecoverPW(const char *Cmd) {
|
|||
uint32_t curr_password = 0x0;
|
||||
uint32_t prev_password = 0xffffffff;
|
||||
uint32_t mask = 0x0;
|
||||
int found = 0;
|
||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||
if (cmdp == 'h') return usage_t55xx_recoverpw();
|
||||
uint8_t downlink_mode = 0;
|
||||
uint8_t found = 0;
|
||||
uint8_t cmd_opt_idx = 0;
|
||||
|
||||
orig_password = param_get32ex(Cmd, 0, 0x51243648, 16); //password used by handheld cloners
|
||||
char cmdp = tolower(param_getchar(Cmd, cmd_opt_idx));
|
||||
|
||||
if (cmdp == 'h') return usage_t55xx_recoverpw();
|
||||
if (cmdp == 'r') { // downlink mode supplied
|
||||
cmd_opt_idx++; // skip over 'r'
|
||||
downlink_mode = param_getchar (Cmd,cmd_opt_idx++) - '0';
|
||||
if (downlink_mode > 4) downlink_mode = 0;
|
||||
}
|
||||
|
||||
orig_password = param_get32ex(Cmd, cmd_opt_idx++, 0x51243648, 16); //password used by handheld cloners
|
||||
|
||||
// first try fliping each bit in the expected password
|
||||
while (bit < 32) {
|
||||
curr_password = orig_password ^ (1u << bit);
|
||||
found = tryOnePassword(curr_password);
|
||||
if (found == 1)
|
||||
found = tryOnePassword(curr_password,downlink_mode);
|
||||
if (found > 0) // xx1 for found xx = dl mode used
|
||||
goto out;
|
||||
|
||||
bit++;
|
||||
|
@ -2078,8 +2313,8 @@ static int CmdT55xxRecoverPW(const char *Cmd) {
|
|||
continue;
|
||||
}
|
||||
|
||||
found = tryOnePassword(curr_password);
|
||||
if (found == 1)
|
||||
found = tryOnePassword(curr_password,downlink_mode);
|
||||
if (found > 0)
|
||||
goto out;
|
||||
|
||||
bit++;
|
||||
|
@ -2100,8 +2335,8 @@ static int CmdT55xxRecoverPW(const char *Cmd) {
|
|||
bit++;
|
||||
continue;
|
||||
}
|
||||
found = tryOnePassword(curr_password);
|
||||
if (found == 1)
|
||||
found = tryOnePassword(curr_password,downlink_mode);
|
||||
if (found > 0)
|
||||
goto out;
|
||||
|
||||
bit++;
|
||||
|
@ -2115,8 +2350,10 @@ out:
|
|||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (found == 1)
|
||||
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password);
|
||||
if (found > 0) {
|
||||
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") "]", curr_password);
|
||||
T55xx_Print_DownlinkMode ((found >> 1) & 3);
|
||||
}
|
||||
else
|
||||
PrintAndLogEx(WARNING, "Recover pwd failed");
|
||||
|
||||
|
@ -2134,7 +2371,7 @@ bool tryDetectP1(bool getData) {
|
|||
bool st = true;
|
||||
|
||||
if (getData) {
|
||||
if (!AquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, false, 0))
|
||||
if (!AquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, false, 0,0))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2240,8 +2477,12 @@ static int CmdT55xxDetectPage1(const char *Cmd) {
|
|||
bool errors = false;
|
||||
bool useGB = false;
|
||||
bool usepwd = false;
|
||||
bool try_all_dl_modes = false;
|
||||
uint8_t found = 0;
|
||||
uint32_t password = 0;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t downlink_mode = 0;
|
||||
uint8_t dl_mode = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
@ -2257,6 +2498,12 @@ static int CmdT55xxDetectPage1(const char *Cmd) {
|
|||
useGB = true;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'r':
|
||||
downlink_mode = param_getchar(Cmd, cmdp+1) - '0';
|
||||
if (downlink_mode == 4) try_all_dl_modes = true;
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
cmdp +=2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
|
@ -2266,21 +2513,42 @@ static int CmdT55xxDetectPage1(const char *Cmd) {
|
|||
if (errors) return usage_t55xx_detectP1();
|
||||
|
||||
if (!useGB) {
|
||||
if (!AquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, usepwd, password))
|
||||
return PM3_ENODATA;
|
||||
for (dl_mode = downlink_mode; dl_mode < 4; dl_mode++) {
|
||||
found = AquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, usepwd, password,dl_mode);
|
||||
//return PM3_ENODATA;
|
||||
if (tryDetectP1(false)) //tryDetectModulation())
|
||||
{
|
||||
found = dl_mode;
|
||||
dl_mode = 4;
|
||||
}
|
||||
else found = false;
|
||||
|
||||
if (!try_all_dl_modes) dl_mode = 4;
|
||||
}
|
||||
|
||||
if (tryDetectP1(false))
|
||||
}
|
||||
|
||||
if (useGB) found = tryDetectP1(false);
|
||||
|
||||
if (found) {
|
||||
PrintAndLogEx(SUCCESS, "T55xx chip found!");
|
||||
T55xx_Print_DownlinkMode (found);
|
||||
}
|
||||
else
|
||||
PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'"));
|
||||
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdT55xxSetDeviceConfig(const char *Cmd) {
|
||||
uint8_t startgap = 0, writegap = 0;
|
||||
uint8_t write0 = 0, write1 = 0, readgap = 0;
|
||||
uint8_t startgap = 0, writegap = 0, readgap = 0;
|
||||
uint8_t write0 = 0, write1 = 0, write2 = 0, write3 = 0;
|
||||
bool errors = false, shall_persist = false;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t downlink_mode = 0;
|
||||
bool erase = false;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
|
@ -2302,13 +2570,30 @@ static int CmdT55xxSetDeviceConfig(const char *Cmd) {
|
|||
cmdp += 2;
|
||||
break;
|
||||
case 'e':
|
||||
errors |= param_getdec(Cmd, cmdp + 1, &write2);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'f':
|
||||
errors |= param_getdec(Cmd, cmdp + 1, &write3);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'g':
|
||||
errors |= param_getdec(Cmd, cmdp + 1, &readgap);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'r':
|
||||
downlink_mode = param_getchar(Cmd, cmdp + 1) - '0';
|
||||
if (downlink_mode > 3) downlink_mode = 0;
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'p':
|
||||
shall_persist = true;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'z':
|
||||
erase = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = 1;
|
||||
|
@ -2319,8 +2604,21 @@ static int CmdT55xxSetDeviceConfig(const char *Cmd) {
|
|||
//Validations
|
||||
if (errors || cmdp == 0) return usage_lf_deviceconfig();
|
||||
|
||||
t55xx_config conf = { startgap * 8, writegap * 8, write0 * 8, write1 * 8, readgap * 8 };
|
||||
// printf ("DLmode %d\n",downlink_mode);
|
||||
t55xx_config conf = {0};
|
||||
if (erase) {
|
||||
memset (&conf,0xff, sizeof(conf));
|
||||
}
|
||||
else {
|
||||
|
||||
conf.m[downlink_mode].start_gap = startgap;// * 8;
|
||||
conf.m[downlink_mode].write_gap = writegap;// * 8;
|
||||
conf.m[downlink_mode].write_0 = write0 ;// * 8;
|
||||
conf.m[downlink_mode].write_1 = write1 ;// * 8;
|
||||
conf.m[downlink_mode].write_2 = write2 ;// * 8;
|
||||
conf.m[downlink_mode].write_3 = write3 ;// * 8;
|
||||
conf.m[downlink_mode].read_gap = readgap ;// * 8;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_SET_LF_T55XX_CONFIG, shall_persist, 0, 0, &conf, sizeof(t55xx_config));
|
||||
return PM3_SUCCESS;
|
||||
|
@ -2328,9 +2626,9 @@ static int CmdT55xxSetDeviceConfig(const char *Cmd) {
|
|||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "<start password> <end password> [i <*.dic>] Simple bruteforce attack to find password"},
|
||||
{"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "<start password> <end password> Simple bruteforce attack to find password"},
|
||||
{"config", CmdT55xxSetConfig, AlwaysAvailable, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
||||
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords"},
|
||||
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"},
|
||||
{"detect", CmdT55xxDetect, AlwaysAvailable, "[1] Try detecting the tag modulation from reading the configuration block."},
|
||||
{"deviceconfig", CmdT55xxSetDeviceConfig, IfPm3Lf, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"},
|
||||
{"p1detect", CmdT55xxDetectPage1, IfPm3Lf, "[1] Try detecting if this is a t55xx tag by reading page 1"},
|
||||
|
|
|
@ -150,7 +150,7 @@ void printT5xxHeader(uint8_t page);
|
|||
void printT55xxBlock(uint8_t blockNum);
|
||||
int printConfiguration(t55xx_conf_block_t b);
|
||||
|
||||
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password);
|
||||
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode);
|
||||
bool GetT55xxBlockData(uint32_t *blockdata);
|
||||
bool DecodeT55xxBlock(void);
|
||||
bool tryDetectModulation(void);
|
||||
|
@ -159,8 +159,8 @@ bool testKnownConfigBlock(uint32_t block0);
|
|||
bool tryDetectP1(bool getData);
|
||||
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5);
|
||||
int special(const char *Cmd);
|
||||
bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password);
|
||||
int tryOnePassword(uint32_t password);
|
||||
bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint8_t downlink_mode);
|
||||
uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode);
|
||||
|
||||
void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat);
|
||||
void printT5555Trace(t5555_tracedata_t data, uint8_t repeat);
|
||||
|
|
|
@ -903,7 +903,7 @@ static int l_T55xx_readblock(lua_State *L) {
|
|||
// try reading the config block and verify that PWD bit is set before doing this!
|
||||
if (!override) {
|
||||
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0)) {
|
||||
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0,0)) {
|
||||
return returnToLuaWithError(L, "Failed to read config block");
|
||||
}
|
||||
|
||||
|
@ -920,7 +920,7 @@ static int l_T55xx_readblock(lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!AquireData(usepage1, block, usepwd, password)) {
|
||||
if (!AquireData(usepage1, block, usepwd, password,0)) {
|
||||
return returnToLuaWithError(L, "Failed to aquire data from card");
|
||||
}
|
||||
|
||||
|
@ -977,7 +977,7 @@ static int l_T55xx_detect(lua_State *L) {
|
|||
|
||||
if (!useGB) {
|
||||
|
||||
isok = AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password);
|
||||
isok = AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password,0);
|
||||
if (isok == false) {
|
||||
return returnToLuaWithError(L, "Failed to aquire LF signal data");
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ typedef struct {
|
|||
int divisor;
|
||||
int trigger_threshold;
|
||||
} sample_config;
|
||||
|
||||
/*
|
||||
typedef struct {
|
||||
uint16_t start_gap;
|
||||
uint16_t write_gap;
|
||||
|
@ -127,7 +127,34 @@ typedef struct {
|
|||
uint16_t write_1;
|
||||
uint16_t read_gap;
|
||||
} t55xx_config;
|
||||
*/
|
||||
|
||||
// Extended to support 1 of 4 timing
|
||||
typedef struct {
|
||||
uint8_t start_gap ;
|
||||
uint8_t write_gap ;
|
||||
uint8_t write_0 ;
|
||||
uint8_t write_1 ;
|
||||
uint8_t write_2 ;
|
||||
uint8_t write_3 ;
|
||||
uint8_t read_gap ;
|
||||
} t55xx_config_t;
|
||||
// This setup will allow for the 4 downlink modes "m" as well as other items if needed.
|
||||
// Given the one struct we can then read/write to flash/client in one go.
|
||||
typedef struct {
|
||||
t55xx_config_t m[4]; // mode
|
||||
} t55xx_config;
|
||||
|
||||
/*typedef struct {
|
||||
uint16_t start_gap [4];
|
||||
uint16_t write_gap [4];
|
||||
uint16_t write_0 [4];
|
||||
uint16_t write_1 [4];
|
||||
uint16_t write_2 [4];
|
||||
uint16_t write_3 [4];
|
||||
uint16_t read_gap [4];
|
||||
} t55xx_config;
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t version;
|
||||
uint32_t baudrate;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue